19

I need a slack bot that's able to receive and save files send from slack chatrooms.

The problem is: slack doesn't send file contents, but an array of links pointing to the file. Most of them, including download link are private and cannot be accessed via bot. It does send one public link, but that link points at the file preview, which does not have the file itself (here's an example).

So the question is: how can I access uploaded files via bot?

Erik Kalkoken
  • 23,798
  • 6
  • 53
  • 81
ddgd
  • 1,497
  • 11
  • 25
  • If you give the bot an account, can you have the bot log in and grab the files that way? – tadman Mar 22 '16 at 02:00
  • @tadman I could, but I'd rather not deal with an extra set of credentials and all the additional logic that method entails. I hope there's a better way that I'm missing. – ddgd Mar 22 '16 at 02:08
  • Take a look at the files scopes on here: https://api.slack.com/docs/oauth-scopes. It seems that if you want to write files, you need user permissions. – Wilhelm Klopp Mar 22 '16 at 11:15
  • @WilhelmKlopp Bots use access token, not oauth and I need to download files, not upload. Plus I sort of have access to files, I just can't download them conveniently which seems strange to me as it should be a common usecase. – ddgd Mar 22 '16 at 19:35

4 Answers4

23

You can access private URLs from your bot by providing an access token in the HTTP header when you are doing you CURL request.

Your token needs to have the scope files.read in order to get access.

The format is:

Authorization: Bearer A_VALID_TOKEN

Replace A_VALID_TOKEN with your slack access token.

I just tested it with a simple PHP script to retrieve a file by its "url_private" and it works nicely.

Source: Slack API documententation / file object / Authentication

Erik Kalkoken
  • 23,798
  • 6
  • 53
  • 81
10

Example for using the Python requests library to fetch an example file:

import requests
url = 'https://slack-files.com/T0JU09BGC-F0UD6SJ21-a762ad74d3'
token = 'xoxp-8853424449-8820034832-8891394196-faf6f0'
requests.get(url, headers={'Authorization': 'Bearer %s' % token})
Maik Röder
  • 886
  • 7
  • 5
2

for those wanting to accomplish this with Bash & cURL, here's a helpful function! It will download the file to the current directory with a filename that uniquely identifies the file, even if the file has the same name as others in your file listing.

function slack_download {
  URL="$1";
  TOKEN="$2"
  FILENAME=`echo "$URL" | sed -r 's/.*\/(T.+)\/([^\/]+)$/\1-\2/'`; 
  curl -o "$FILENAME" -H "Authorization: Bearer $TOKEN" "$URL"; 
}
# Usage: 
# Downloads as ./TJOLLYDAY-FANGBEARD-NSFW_PIC.jpg
slack_download "https://files.slack.com/files-pri/TJOLLYDAY-FANGBEARD/NSFW_PIC.jpg" xoxp-12345678901-01234567890-123456789012-abcdef0123456789abcdef0123456789
turiyag
  • 2,345
  • 2
  • 17
  • 17
0

Tested with Python3 - just replace SLACK_TOKEN with your token. Downloads and creates an output file.

#!/usr/bin/env python3
# Usage: python3 download_files_from_slack.py <URL>

import sys
import re
import requests

url = " ".join(sys.argv[1:])

token = 'SLACK_TOKEN'
resp = requests.get(url, headers={'Authorization': 'Bearer %s' % token})

headers = resp.headers['content-disposition']
fname = re.findall("filename=(.*?);", headers)[0].strip("'").strip('"')

assert not os.path.exists(fname), print("File already exists. Please remove/rename and re-run")
out_file = open(fname, mode="wb+")
out_file.write(resp.content)
out_file.close()
csghone
  • 51
  • 4