Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

What sort of Stream is fileUploadV2 looking for? #2131

Open
cssinate opened this issue Dec 20, 2024 · 3 comments
Open

What sort of Stream is fileUploadV2 looking for? #2131

cssinate opened this issue Dec 20, 2024 · 3 comments
Labels
pkg:web-api applies to `@slack/web-api` question M-T: User needs support to use the project

Comments

@cssinate
Copy link

(Filling out the following with as much detail as you can provide will help us answer your question sooner.)

@slack/bolt version

4.1.1

Your App and Receiver Configuration

export const app = new App({
    token: SLACK_TOKEN, 
    signingSecret: SLACK_SIGNING_SECRET,
    socketMode: true,
    appToken: SLACK_SOCKET_TOKEN,
    logLevel: LogLevel.DEBUG
});

Node.js runtime version

20.13.1

Steps to reproduce:

I'm trying to create a bot to help run a hackathon; all of the pitching, team management, swag forms, and demo submissions, etc. I want teams to be able to upload a video into their private team channel, and when voting opens, the bot posts all of the videos in a public channel simultaneously. I'm having trouble doing that. Here's a minimal test with an MP4 file I uploaded.

  const fileInfo = await app.client.files.info({
    file: 'FXXXXXXXXXX',
    token: process.env.SLACK_BOT_TOKEN
  })
  const filePath = fileInfo.file!.url_private as string;
  const readableStream = await fetch(filePath).then(r => {
    if (!r.body) {
      throw new Error('Response body is null');
    }
    return Readable.from(r.body as any);
  });

  await app.client.filesUploadV2({
    channel_id: 'DXXXXXXXXXX',
    initial_comment: 'This is a test',
    file: readableStream,
    filename: fileInfo.file!.name as string,
  })

The file says it can accept a Stream, but when it posts this in the DM, it's a 56KB Binary file presented to the user. Visiting the filePath in a browser shows the MP4 as expected.

I fully recognize this could be a lack of understanding on my part with Readable Streams. I apologize if that's the sole issue at play.

Expected result:

I expect the readableStream passed into file to be given back in the same file format and size as the input file.

Actual result:

image
The file came back as a binary file.

Requirements

For general questions/issues about Slack API platform or its server-side, could you submit questions at https://my.slack.com/help/requests/new instead. 🙇

Please read the Contributing guidelines and Code of Conduct before creating this issue or pull request. By submitting, you are agreeing to those rules.

@zimeg zimeg added question M-T: User needs support to use the project and removed untriaged labels Dec 21, 2024
@zimeg zimeg transferred this issue from slackapi/bolt-js Jan 3, 2025
@zimeg zimeg added the pkg:web-api applies to `@slack/web-api` label Jan 3, 2025
@zimeg
Copy link
Member

zimeg commented Jan 3, 2025

Hey @cssinate 👋 Thanks for sharing this setup and question! 🎁

I'm moving this issue to the slackapi/node-slack-sdk since this is related to file uploads using @slack/web-api

The file says it can accept a Stream, but when it posts this in the DM, it's a 56KB Binary file presented to the user. Visiting the filePath in a browser shows the MP4 as expected.

A blob of binary data can sometimes be caused by unexpected data mixing with an unknown filetype and misleading file extension - meaning this confusion is super fair!

I believe the upload and readable stream are working as expected, but the data downloaded from url_private might be a page requesting authorization. To unlock this file download, a token will have to be included in the fetch call:

const readableStream = await fetch(fileInfo.file.url_private, {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.SLACK_TOKEN}`,
  },
}).then((r) => {
  if (!r.body) {
    throw new Error('Response body is null');
  }
  return Readable.from(r.body);
});

This seems to download (then upload) a file uploaded by a user as long as the bot has been added to that channel and includes the files:read and files:write scopes!

I apologize for the delay in this response, but I hope this change downloads the files as expected. Please let me know if something else seems strange though 🙏

@cssinate
Copy link
Author

cssinate commented Jan 3, 2025

Thanks so much! This worked.

I have a quick follow-up request for confirmation... It seems that, even if a file is public across the workspace, a bot can't just re-share/forward that file to a DM. Is that accurate? The only way to send files in DMs is to always use the upload method and create new copies of the same file?

@seratch
Copy link
Member

seratch commented Jan 6, 2025

If you include the file's URL in a DM message, you can share the file again without uploading it again. If the file is visible to the recipient, Slack's UI should display the file preview.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
pkg:web-api applies to `@slack/web-api` question M-T: User needs support to use the project
Projects
None yet
Development

No branches or pull requests

3 participants