Skip to content

Instantly share code, notes, and snippets.

@proprietary
Last active February 26, 2020 09:02
Show Gist options
  • Save proprietary/b0a76ea56396d884d6e0f40457ea4067 to your computer and use it in GitHub Desktop.
Save proprietary/b0a76ea56396d884d6e0f40457ea4067 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import urllib.request
import json
import sys
import re
import shutil
# No, this isn't my own OAuth2 token. It isn't anyone's. It's the default token Twitter gives out to non-signedin users
AUTH_TOKEN = "AAAAAAAAAAAAAAAAAAAAANRILgAAAAAAnNwIzUejRCOuH5E6I8xnZz4puTs%3D1Zv7ttfk8LF81IUq16cHjhLTvJu4FA33AGWWjCpTnA"
def guest_token():
req = urllib.request.Request(
"https://api.twitter.com/1.1/guest/activate.json", method="POST"
)
req.add_header("Authorization", f"Bearer {AUTH_TOKEN}")
with urllib.request.urlopen(req) as f:
resp = f.read().decode("utf-8")
resp = json.loads(resp)
return resp["guest_token"]
def conversation(tweet_id):
req = urllib.request.Request(
f"https://api.twitter.com/2/timeline/conversation/{tweet_id}.json?tweet_mode=extended"
)
req.add_header("x-guest-token", guest_token())
req.add_header("Authorization", f"Bearer {AUTH_TOKEN}")
with urllib.request.urlopen(req) as f:
resp = f.read().decode("utf-8")
return json.dumps(json.loads(resp))
def find_video_urls(text):
video_regexp = r"https:\/\/video.twimg.com\/[^\"]*?\.mp4"
video_urls = re.findall(video_regexp, text)
# rank by resolution, descending
def resolution_string(src):
resolution_regexp = r"(\d{3,5})x(\d{3,5})"
m = re.search(resolution_regexp, src)
if not m:
return -1
# e.g. 1280x720
w, h = m.groups()
w = int(w)
h = int(h)
return w + h
# first video URL is highest resolution
return sorted(video_urls, key=resolution_string, reverse=True)
def download_file(url, dest_filename):
with open(dest_filename, "wb") as df:
with urllib.request.urlopen(url) as sf:
shutil.copyfileobj(sf, df)
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python3 twitter_video.py <tweet URL>", file=sys.stderr)
sys.exit(1)
tweet_id_regexp = r"\/(\d+)\/?"
m = re.search(tweet_id_regexp, sys.argv[1])
if not m:
print("That's not a recognized URL to a tweet", file=sys.stderr)
sys.exit(1)
tweet_id = m[1]
payload = conversation(tweet_id)
video_urls = find_video_urls(payload)
if len(video_urls) == 0:
print(
"No videos found in this tweet. Make sure the URL is the tweet with the video. If there are, then this program could not find them and is probably outdated.",
file=sys.stderr,
)
sys.exit(2)
download_file(video_urls[0], f"{tweet_id}.mp4")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment