0

I'm creating a feedback bot that will send out direct messages to individuals as soon as an event on their calendar ends. For this, i've developed most of the code using appscript. I got the calendar api trigger working and i can get the same functionality working using /slash commands, but what i want is to automate this process, in that, the bot will automatically send out the message on the calendar trigger.

I'm not sure how to get this to work as i didn't find any examples or documentation to do the same. I read somewhere that google chat api doesn't allow proactively sending messages directly to users, but i have seen examples of it working.

When i try to send the message using the appscript chat api sdk, it doesn't send any message, although the flow runs successfully as i can see from the logs.

When i try using google chat rest api i'm facing errors when trying to send out a message.

The error for rest api, the error i'm seeing is :

12:10:32 PM Error   
Exception: Request failed for https://chat.googleapis.com returned code 400. Truncated server response: {
  "error": {
    "code": 400,
    "message": "Message cannot have cards for requests carrying human credentials.",
    "status": "INVALID_ARGUMEN... (use muteHttpExceptions option to examine full response)
showFeedbackMessageRest @ feedback.gs:105
pubsub_subscribe    @ feedback.gs:42

the code for the pub/sub subscriber is :

function pubsub_subscribe(e){
  var service = getService();
  
  if (!service.hasAccess()) {
    var authorizationUrl = service.getAuthorizationUrl();
    console.log('Authorize PubSub Service First : !!!!!!!!!!!!!!!!');
    console.log(authorizationUrl);
    showFeedbackMessageRest(e, {'auth_url' : authorizationUrl});
  }else{
    console.log('PubSub has Access!')
    var project_id = get_property('PROJECT_ID');
    // var topic = get_property('TOPIC');
    var subscriber = get_property('SUBSCRIBER');

    var url = `https://pubsub.googleapis.com/v1/projects/${project_id}/subscriptions/${subscriber}:pull`

    var body = {
      returnImmediately: true, 
      maxMessages: 1
    }

    var response = UrlFetchApp.fetch(url, {
      method: "POST",
      contentType: 'application/json',
      muteHttpExceptions: true,
      payload: JSON.stringify(body),
      headers: {
        Authorization: 'Bearer ' + getService().getAccessToken()
      }
    });

    var result = JSON.parse(response.getContentText());
    console.log(JSON.stringify(result));
    console.log(Object.keys(result).length);
    if (Object.keys(result).length > 0){
      var decoded = Utilities.base64Decode(result.receivedMessages[0].message.data);
      var event_details = JSON.parse(Utilities.newBlob(decoded).getDataAsString());
      var popup_obj = {
        'summary' : event_details.EventTitle
      };
      console.log(popup_obj);
      return showFeedbackMessageRest(e, popup_obj);
    }else{
      console.log('No Recent Messages!');
    }
  }
}

and the code to send the message using chat rest api is :


function showFeedbackMessageRest(e, event) {
  var chat_service = getChatService()

  var message = {};

  if (!chat_service.hasAccess()) {
    var authorizationUrl = chat_service.getAuthorizationUrl();
    console.log('Authorize Chat Service First : !!!!!!!!!!!!!!!!');
    console.log(authorizationUrl);
  }else{
    console.log('Chat App Has Access!');
    if (event.hasOwnProperty('summary')){
      message = {
        "text" : `Provide Feedback For : ${event.summary}`
};
    }else{
      message = {
        "cards_v2": [{
          "card_id": "feedbackMessage",
          "card": {
            "header": {
              "title": `Provide Feedback For : ${event.summary}`,
              "subtitle": `This meeting just ended, provide feedback for the organizers to organize meetings more effectively.`,
              "imageUrl": "https://raw.githubusercontent.com/google/material-design-icons/master/png/social/poll/materialicons/24dp/2x/baseline_poll_black_24dp.png",
              "imageType": "CIRCLE"
            },
            "sections": [
              {
                "widgets": [
                  {
                    "buttonList": {
                      "buttons": [
                        {
                          "text": "Give Feedback",
                          "onClick": {
                            "action": {
                              "function": "promptQuestion",
                              "interaction": "OPEN_DIALOG"
                            }
                          }
                        }
                      ]
                    }
                  }
                ]
              }
            ]
          }
        }]
      };
    }
  }

  var url = 'https://chat.googleapis.com/v1/' + `${user_dm_space_name}` + '/messages';
  UrlFetchApp.fetch(url, {
    method: 'POST',
    headers: { 'Authorization': 'Bearer ' + chat_service.getAccessToken() },
    contentType: 'application/json',
    payload: JSON.stringify(message),
  });
}

I even tried to send a simple text message as according to the error, the cards are not allowed to be sent, but i'm getting this error :

12:30:36 PM Error   
Exception: Request failed for https://chat.googleapis.com returned code 403. Truncated server response: {
  "error": {
    "code": 403,
    "message": "This API is not accessible for external HTTP caller.",
    "status": "PERMISSION_DENIED"
  }
}
 (use muteHttpExceptions option to examine full response)
showFeedbackMessageRest @ feedback.gs:105
pubsub_subscribe    @ feedback.gs:42

abtExp
  • 9
  • 1
  • 14

2 Answers2

0

It's possible, but you'll have to jump through quite a few hoops to make it work.

First is the authentication. You authenticate as user (at least I see that you log authorization url in console in your code, I assume you paste it in browser afterwards). So you need Application type of authentication here (service account email and p12/json key): https://developers.google.com/chat/api/guides/auth/service-accounts

Next two steps you probably already have done but I'll mention them just in case:

Enable Chat API: https://console.cloud.google.com/marketplace/product/google/chat.googleapis.com

Configure a Chat app (your message bot): https://console.cloud.google.com/apis/api/chat.googleapis.com/hangouts-chat

As you already figured out only bots so far can send cards: https://developers.google.com/chat/concepts/cards

TLDR:

  1. Configure Application type of authentication
  2. Configure Chat Bot
  3. Add bot into google space where you expect to see message
  4. Send message card through properly authenticated service

And the reason why you can't even send plain text message with user authentication is because it's hidden behind Developers Preview at the moment: https://developers.google.com/workspace/preview#active_developer_previews

Denis M.
  • 1
  • 2
0

I faced the same issue sometime back. If you carefully go through this Google chat link : Sending cards using Google Chat API

It tells you that sending cards is only possible using app authentication while it seems that you are using a user account and not a service account.

When I sent card based messages using service account, it was successful. Hope this helps.

Pranav
  • 1
  • 1
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jun 16 '23 at 22:21