From 56d5cd3637e9fa4102408f6e0286ae4253e4bac3 Mon Sep 17 00:00:00 2001 From: jcipriano Date: Wed, 6 Jul 2016 16:14:53 -0700 Subject: [PATCH] Initial source. --- .gitignore | 3 + README.md | 0 async-upload.py | 169 +++++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 3 + 4 files changed, 175 insertions(+) create mode 100644 README.md create mode 100644 async-upload.py create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore index 72364f9..0ad7621 100644 --- a/.gitignore +++ b/.gitignore @@ -87,3 +87,6 @@ ENV/ # Rope project settings .ropeproject + + +.DS_Store diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/async-upload.py b/async-upload.py new file mode 100644 index 0000000..aa3e21b --- /dev/null +++ b/async-upload.py @@ -0,0 +1,169 @@ +import os +import sys +import time + +import json +import requests +from requests_oauthlib import OAuth1 + + +MEDIA_ENDPOINT_URL = 'https://upload.twitter.com/1.1/media/upload.json' +POST_TWEET_URL = 'https://api.twitter.com/1.1/statuses/update.json' + +CONSUMER_KEY = 'your-consumer-key' +CONSUMER_SECRET = 'your-consumer-secret' +ACCESS_TOKEN = 'your-access-token' +ACCESS_TOKEN_SECRET = 'your-access-secret' + +VIDEO_FILENAME = 'path/to/video/file' + + +oauth = OAuth1(CONSUMER_KEY, + client_secret=CONSUMER_SECRET, + resource_owner_key=ACCESS_TOKEN, + resource_owner_secret=ACCESS_TOKEN_SECRET) + + +class VideoTweet(object): + + def __init__(self, file_name): + ''' + Defines video tweet properties + ''' + self.video_filename = file_name + self.total_bytes = os.path.getsize(self.video_filename) + self.media_id = None + self.processing_info = None + + + def upload_init(self): + ''' + Initializes Upload + ''' + print('INIT') + + request_data = { + 'command': 'INIT', + 'media_type': 'video/mp4', + 'total_bytes': self.total_bytes, + 'media_category': 'tweetvideo' + } + + req = requests.post(url=MEDIA_ENDPOINT_URL, data=request_data, auth=oauth) + media_id = req.json()['media_id'] + + self.media_id = media_id + + print('Media ID: %s' % str(media_id)) + + + def upload_append(self): + ''' + Uploads media in chunks and appends to chunks uploaded + ''' + segment_id = 0 + bytes_sent = 0 + file = open(self.video_filename, 'rb') + + while bytes_sent < self.total_bytes: + chunk = file.read(4*1024*1024) + + print('APPEND') + + request_data = { + 'command': 'APPEND', + 'media_id': self.media_id, + 'segment_index': segment_id + } + + files = { + 'media':chunk + } + + req = requests.post(url=MEDIA_ENDPOINT_URL, data=request_data, files=files, auth=oauth) + + if req.status_code < 200 or req.status_code > 299: + print(req.status_code) + print(req.text) + sys.exit(0) + + segment_id = segment_id + 1 + bytes_sent = file.tell() + + print('%s of %s bytes uploaded' % (str(bytes_sent), str(self.total_bytes))) + + print('Upload chunks complete.') + + + def upload_finalize(self): + ''' + Finalizes uploads and starts video processing + ''' + print('FINALIZE') + + request_data = { + 'command': 'FINALIZE', + 'media_id': self.media_id + } + + req = requests.post(url=MEDIA_ENDPOINT_URL, data=request_data, auth=oauth) + print(req.json()) + + self.processing_info = req.json().get('processing_info', None) + self.check_status() + + + def check_status(self): + ''' + Checks video processing status + ''' + if self.processing_info is None: + return + + state = self.processing_info['state'] + + print('Media processing status is %s ' % state) + + if state == u'succeeded': + return + + if state == u'failed': + sys.exit(0) + + check_after_secs = self.processing_info['check_after_secs'] + + print('Checking after %s seconds' % str(check_after_secs)) + time.sleep(check_after_secs) + + print('STATUS') + + request_params = { + 'command': 'STATUS', + 'media_id': self.media_id + } + + req = requests.get(url=MEDIA_ENDPOINT_URL, params=request_params, auth=oauth) + + self.processing_info = req.json().get('processing_info', None) + self.check_status() + + + def tweet(self): + ''' + Publishes Tweet with attached video + ''' + request_data = { + 'status': 'I just uploaded a video with the @TwitterAPI.', + 'media_ids': self.media_id + } + + req = requests.post(url=POST_TWEET_URL, data=request_data, auth=oauth) + print(req.json()) + + +if __name__ == '__main__': + videoTweet = VideoTweet(VIDEO_FILENAME) + videoTweet.upload_init() + videoTweet.upload_append() + videoTweet.upload_finalize() + videoTweet.tweet() \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..a8e58d7 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +oauthlib==1.1.2 +requests==2.10.0 +requests-oauthlib==0.6.1 -- 2.25.1