Search code examples
slackslack-api

Uploading and attaching images to private messages from bots in Slack


I have a node service that's using WebClient from @slack/client.

I am using the access token of a bot to upload an image using the web.files.upload API method. I then want to send the uploaded image to a user as an attachment to a private message (i.e. a channel that starts with D). I want access to this image to be limited to the Slack users in this team (much like when you share a document or other file).

I tried doing this with the response from the files.upload function, but there doesn't seem to be any property of res.file that gives me a URL that's accessible to all members of this Slack team:

conversationId = 'Dxxxxxxxx'; // ID of private channel between bot and user

web.chat
  .postMessage({
    channel: conversationId,
    text: 'Hello there',
    attachments: [
      {
        fallback: 'Required plain-text summary of the attachment.',
        color: '#36a64f',
        title: 'Slack API Documentation',
        title_link: 'https://api.slack.com/',
        text: 'Optional text that appears within the attachment',
        image_url: res.file.permalink_public,
        ts: 123456789
      }
    ]
  });

From the docs, it sounds like this file is private to the bot until it is sent to a public channel.

An alternative I considered was uploading the file to the private message channel between the user and the bot, however that gives me the following error:

{ Error: An API error occurred: invalid_channel
  code: 'slackclient_platform_error',
  data:
  { ok: false,
    error: 'invalid_channel',
    channel: '["Dxxxxxxxx"]',
    scopes: [ 'identify', 'bot:basic' ],
    acceptedScopes: [ 'files:write:user', 'post' ] } }

Is there no way to achieve what I'm after?


Solution

  • My mistake came from misreading the docs - the files.upload API expects a comma-separated string for the channels property and I was passing an array.

    Once I had corrected this I could successfully upload files and share them with a user privately (channel IDs starting with 'D') and in public channels (channel IDs starting with 'C').

    Copying the image URL and pasting it in a browser brought me to a login page, so by default they are private to the Slack team as I had hoped.