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).
How can I access uploaded files via bot?
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
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})
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
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()
Related
I write a code to send a proxy link to my telegram bot but when i send the request
my proxy link don't send complete
this is my code
#/bin/bash
TOKEN="***********************"
ID="************"
URL="https://api.telegram.org/bot$TOKEN/sendMessage"
PRLINK="tg://proxy?server=xxx.xxx.xxx.xxx&port=443&secret=eeb000000000000000000000000000"
curl -s -X POST $URL -d chat_id=$ID -d text=${PRLINK} > /root/sendResult
and this response
{ [..] ,"text":"tg://proxy?server=18.202.178.109", [..]}
in response
"text":"tg://proxy?server=18.202.178.109" no equal to PRLINK that me send with curl
The problem is related to URL encoding: https://www.w3schools.com/tags/ref_urlencode.ASP
In a nutshell, you should encode the ampersand character in order to let the entire URL be considered properly.
So that, the ampersand character is encoded as %26, therefore:
Your code should be:
#/bin/bash
TOKEN="***********************"
ID="************"
URL="https://api.telegram.org/bot$TOKEN/sendMessage"
PRLINK="tg://proxy?server=xxx.xxx.xxx.xxx%26port=443%26secret=eeb000000000000000000000000000"
curl -s -X POST $URL -d chat_id=$ID -d text=${PRLINK} > /root/sendResult
I have a script that uses the Azure DevOps API to retrieve every work item in a query. Then it retrieves the metadata for each work item. It requires a PAT. Until today the PAT has worked. I believe it is expired. I created a new PAT, but every attempt to retrieve the same information is unauthorized (401).
The cURL command in my script that worked until now:
ado_token={username#company.com:PAT, all Base-64 encoded as one string}
curl -X GET -H "Authorization: Basic $ado_token" -H 'Cache-Control: no-cache' "https://dev.azure.com/{company}/{project}/_apis/wit/wiql/{query ID}?api-version=5.1"
Here are the facts:
Going to the URL directly in the browser succeeds.
The new token is in the same project as the URL.
The new token has full access.
Microsoft documentation on ADO PATs provides this example:
curl -u username[:{personalaccesstoken}] https://dev.azure.com/{organization}/_apis/build-release/builds
However, when my username and PAT are entered with a URL I know to be correct, it is unauthorized.
Both in the format of the Microsoft example and the URL I would like to use in my script, these are all unauthorized in all iterations of Bearer and Basic. The URL used works in the browser:
{username}:{PAT}
{username}#{company}.com:{PAT}
Base-64 encoded {PAT}
Base-64 encoded {username}#{company}.com:{PAT}
Base-64 encoded pat:{PAT}
Base-64 encoded {username}:{PAT}
Base-64 encoded {username}#{company}.com:{PAT}
I have tried both in the command line and Postman but no added information was provided.
Am I missing something obvious? The most confusing aspect of this is that the previous PAT worked in this same code. Thank you for any help.
Try the command below:
curl -u :{PAT} 'https://dev.azure.com/{company}/{project}/_apis/wit/wiql/{query ID}?api-version=5.1'
In the -u parameter the Username field must be blank and the PAT is the original string.
Thus the command would be in the following format:
curl -u :lplnqn4l4glwqkslsfel7t2wjevfi5tayuiwm772qeawbwo3ztua 'https://dev.azure.com/acme/projetx/_apis/wit/wiql/6cbbddb4-f752-453b-9f98-f523470826fe?api-version=5.1'
Postman
using Authorization without username: Choose Basic Auth. and enter the PAT as password.
using Headers: Use key as Authorization and value as Basic {Base-64 encoded pat{:PAT}}. Note that {:PAT} needs to be base64 encoded
Curl
using basic authentication without username: curl -u :{PAT} https://dev.azure.com/{org}/_apis/projects
using headers: curl -H 'Authorization: Basic {Base-64 encoded pat{:PAT}}'
https://dev.azure.com/{org}/_apis/projects
I wanna make a very simple bash script for downloading files from google drive via Drive API, so in this case there is a big file on google drive and I installed OAuth 2.0 Playground on my google drive account, then in the Select the Scope box, I choose Drive API v3, and https://www.googleapis.com/auth/drive.readonly to make a token and link.
After clicking Authorize APIs and then Exchange authorization code for tokens. I copied the Access tokenlike below.
#! /bin/bash
read -p 'Enter your id : ' id
read -p 'Enter your new token : ' token
read -p 'Enter your file name : ' file
curl -H "Authorization: Bearer $token" "https://www.googleapis.com/drive/v3/files/$id?alt=media" -o "$file"
but it won't work, any idea ?
for example the size of my file is 12G, when I run the code I will get this as output and after a second it back to prompt again ! I checked it in two computers with two different ip addresses.(I also add alt=media to URL)
-bash-3.2# bash mycode.sh
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 166 100 166 0 0 80 0 0:00:02 0:00:02 --:--:-- 80
-bash-3.2#
the content of file that it created is like this
{
"error": {
"errors": [
{
"domain": "global",
"reason": "downloadQuotaExceeded",
"message": "The download quota for this file has been exceeded."
}
],
"code": 403,
"message": "The download quota for this file has been exceeded."
}
}
You want to download a file from Google Drive using the curl command with the access token.
If my understanding is correct, how about this modification?
Modified curl command:
Please add the query parameter of alt=media.
curl -H "Authorization: Bearer $token" "https://www.googleapis.com/drive/v3/files/$id?alt=media" -o "$file"
Note:
This modified curl command supposes that your access token can be used for downloading the file.
In this modification, the files except for Google Docs can be downloaded. If you want to download the Google Docs, please use the Files: export method of Drive API. Ref
Reference:
Download files
If I misunderstood your question and this was not the direction you want, I apologize.
UPDATE AS FOR MARCH 2021
Simply follow this guide here. It worked for me.
In summary:
For small files to download run
wget --no-check-certificate 'https://docs.google.com/uc?export=download&id=FILEID' -O FILENAME
While if you are trying to download a quite large file you should try to run
wget --load-cookies /tmp/cookies.txt "https://docs.google.com/uc?export=download&confirm=$(wget --quiet --save-cookies /tmp/cookies.txt --keep-session-cookies --no-check-certificate 'https://docs.google.com/uc?export=download&id=FILEID' -O- | sed -rn 's/.*confirm=([0-9A-Za-z_]+).*/\1\n/p')&id=FILEID" -O FILENAME && rm -rf /tmp/cookies.txt
Simply substitute FILEID and FILENAME with your custom values.
FILEID can be found in your file share link (after the /d/ as illustrated in the article mantioned above).
FILENAME is simply the name you want to save the download as. Remember to include the right extension. For Example FILENAME = my_file.pdf if the file is a pdf.
This is a known bug
It has been reported in this Issue Tracker post. This is caused because as you can read in the documentation:
(about download url)
Short lived download URL for the file. This field is only populated
for files with content stored in Google Drive; it is not populated for
Google Docs or shortcut files.
So you should use another field.
You can follow the report by clicking on the star next to the issue
number to give more priority to the bug and to receive updates.
As you can read in the comments of the report, the current workaround is:
Use webContentlink instead
or
Change www.googleapis.com to content.googleapis.com
I'm trying to follow the tutorial found here https://api.slack.com/methods/files.upload .
curl -F file=#example.txt -F "initial_comment=I play the drums." -F channels=C024BE91L -F thread_ts=1532293503.000001 -H "Authorization: Bearer xoxp-xxxxxxxxx-xxxx" https://slack.com/api/files.upload
I'm able to upload files to a specific channel. However, how do I upload files to a user through direct message?
Similar to how sending direct messages work you can simply use the user ID for the channel and the file will be uploaded in a direct message channel between that user and the owner of the token.
Alternatively you can first open a direct message channel from your app with im.open and then use the channel ID of that IM in files.upload.
I am trying to upload a zip file to Google drive account using curl.
The file is uploaded successfully but the filename is not getting updated. It gets uploaded with default filename i.e. "Untitled".
I am using below command.
curl -k -H "Authorization: Bearer cat /tmp/token.txt" -F "metadata={name : 'backup.zip'} --data-binary "#backup.zip" https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart
You can use Drive API v3 to upload the zip file. The modified curl code is as follows.
curl -X POST -L \
-H "Authorization: Bearer `cat /tmp/token.txt`" \
-F "metadata={name : 'backup.zip'};type=application/json;charset=UTF-8" \
-F "file=#backup.zip;type=application/zip" \
"https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart"
In order to use this, please include https://www.googleapis.com/auth/drive in the scope.
The answer above works fine and was the command I used in uploading my file to Google Drive using Curl. However, I didn't understand what scope was and all of the initial setup required to make this command work. Hence, for documentation purposes. I'll give a second answer.
Valid as at the time of writing...
Visit the Credentials page and create a new credential (this is assuming you have created a project). I created credentials for TVs and Limited devices, so the work flow was similar to:
Create credentials > OAuth client ID > Application Type > TVs and Limited Input devices > Named the client > Clicked Create.
After doing this, I was able to copy the Client ID and Client Secret when viewing the newly created credential.
NB: Only the variables with double asterisk from the Curl commands should be replaced.
Next step was to run the Curl command:
curl -d "client_id=**client_id**&scope=**scope**" https://oauth2.googleapis.com/device/code
Scope in this situation can be considered to be the kind of access you intend to have with the credential having the inputted client_id. More about scope from the docs For the use case in focus, which is to upload files, the scope chosen was https://www.googleapis.com/auth/drive.file.
On running the curl command above, you'll get a response similar to:
{ "device_code": "XXXXXXXXXXXXX", "user_code": "ABCD-EFGH",
"expires_in": 1800, "interval": 5, "verification_url":
"https://www.google.com/device" }
Next step is to visit the verification_url in the response in your browser, provide the user_code and accept requests for permissions. You will be presented with a code when all prompts have been followed, this code wasn't required for the remaining steps (but there may be some reasons to use it for other use cases).
Next step is to use the Curl command:
curl -d client_id=**client_id** -d client_secret=**client_secret** -d device_code=**device_code** -d grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code https://accounts.google.com/o/oauth2/token
You will get a response similar to:
{ "access_token": "XXXXXXXXX", "expires_in": 3599,
"refresh_token": "XXXXXXXXX", "scope":
"https://www.googleapis.com/auth/drive.file", "token_type": "Bearer"
}
Now you can use the access token and follow the accepted answer with a Curl command similar to:
curl -X POST -L \
-H "Authorization: Bearer **access_token**" \
-F "metadata={name : 'backup.zip'};type=application/json;charset=UTF-8" \
-F "file=#backup.zip;type=application/zip" \
"https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart"