Search code examples
google-apps-scriptgoogle-drive-apigoogle-chat

Get Chat Spaces Attachment File and Save in Google Drive using Google Apps Script


I have a simple chat bot written in Google Apps Script that responds to various /slash commands from users within our organisation.

I want to create a feature which can accept an attachment from the user, then upload that attachment into a specified Google Drive location.

I am running into issues with authentication, I think.

I have tried many things.

To begin with I thought it would be simple, as when a user sends a message to the bot, the chat event includes an object with data about the attachment, including a "downloadUri=https://chat.google.com/api/get_attachment_url?url_type=DOWNLOAD_URL&content_type=application/pdf&attachment_token={etc, etc}"

I thought, great! I can simply:

  //get the downloadUri
  let attachmentUrl = data.message.attachment[0].attachmentData.downloadUri

  // Download the attachment
  let attachment = UrlFetchApp.fetch(attachmentUrl).getBlob();

  // Save the attachment to Google Drive
  let file = DriveApp.createFile(attachment);

I thought, since this script already has oauthScopes such as:

"oauthScopes": [
    "https://www.googleapis.com/auth/chat.spaces",
    "https://www.googleapis.com/auth/chat.messages",
    "https://www.googleapis.com/auth/drive",
    "https://www.googleapis.com/auth/script.external_request"
]

That it would simply be permitted to download that file.

But this just creates a file with all the HTML contents of the Google authentication page.

I tested by inputting that "attachmentUrl" into a browser and successfully download the file.

Then I got all caught up adding various auth scopes and methods to try to authenticate the script correctly.

I tried making a get request to the endpoint documented here: https://developers.google.com/chat/api/reference/rest/v1/spaces.messages.attachments/get

But it just returns another downloadUri, which if I try to retrieve that, ends up with the same problem (downloading an auth screen).

So I think after many hours I will turn to you for any help or suggestions you can offer.

I am wondering if I am perhaps just going about this the wrong way.

Thank you.


Solution

  • I was going about this the wrong way.

    I was attempting to download message.attachment[0].attachmentData.downloadUri

    But as per the documentation downloadUri is only for human users:

    "Output only. The download URL which should be used to allow a human user to download the attachment. Chat apps shouldn't use this URL to download attachment content."

    Instead:

    I needed to use the attachmentDataRef object which is subsequently used to make a request to the media API endpoint to then download the attachment data. This is documented here.

    I hope this helps anyone else stuck on this who, like me, didn't read the documentation.