Skip to content

Instantly share code, notes, and snippets.

@wlerin
Last active May 30, 2018 13:45
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wlerin/70f55d0f62cdfedb0a74 to your computer and use it in GitHub Desktop.
Save wlerin/70f55d0f62cdfedb0a74 to your computer and use it in GitHub Desktop.
Upload a Photoset to Tumblr using the Python Requests library (http://docs.python-requests.org/en/latest/).
# Adapted from:
# https://gist.github.com/charlesbrandt/11eadaec114288d621fa
# https://gist.github.com/velocityzen/1242662
# https://gist.github.com/derekg/1198576
# https://groups.google.com/forum/#!msg/tumblr-api/0QxFn79B2n4/6MHC4GNHqp8J
# https://github.com/tumblr/jumblr/blob/master/src/main/java/com/tumblr/jumblr/request/MultipartConverter.java
import requests_oauthlib
import requests
import os.path
from mimetypes import guess_type
class SimpleTumblrClient(object):
def __init__(self, consumer_key, consumer_secret, token, token_secret):
self._oauth = requests_oauthlib.OAuth1(consumer_key, consumer_secret, token, token_secret)
def new_multipart_post(self, hostname, parameters={}, data_files=None):
"""
hostname: the full domain name for the blog you wish to post on, e.g.
'example.tumblr.com', rather than 'example' or 'http://example.tumblr.com'
parameters: a dictionary containing all desired post parameters, EXCEPT
data/source/data64
data_files: the result of handing a list of image URIs (local or web) to
encode_media().
"""
full_url = "https://api.tumblr.com/v2/blog/{}/post".format(hostname)
# http://docs.python-requests.org/en/latest/api/#requests.Response
# prepare the initial request without the binary data
req = requests.Request(method="POST", url=full_url, data=parameters, auth=self._oauth)
prep = req.prepare()
# grab the computed auth data
headers = {'Authorization': prep.headers['Authorization']}
# combine the parameters, the computed auth data, and the binary files into a new request
req = requests.Request(method="POST", url=full_url, data=parameters, headers=headers, files=data_files)
prep = req.prepare()
# send the combined request
s = requests.Session()
r = s.send(prep)
# check whether it succeeded
if r.status_code != 201:
print("Post request failed with status code {}".format(r.status_code))
print(r.text)
else:
print("Posted successfully.")
print(r.text)
def encode_media(media_list):
"""
encode_photos takes a list of photo URIs, either local or on the web,
and returns a dictionary of image data suitable for Requests
can also take a list containing one video or audio URI (adding more will
probably break the request)
"""
media = {}
if media_list == None:
return None
if len(media_list) > 1:
pattern = 'data[{}]'
else:
pattern = 'data'
for i in range(len(media_list)):
media_uri = media_list[i]
if os.path.isfile(media_uri):
_, filename = media_uri.rsplit(os.path.sep, 1)
media.update({pattern.format(i): (filename, open(media_uri, mode='rb'), detect_mimetype(filename))})
else: # assume this is a web url
_, filename = media_uri.rsplit('/', 1)
r = requests.get(media_uri)
media.update({pattern.format(i): (filename, r.content, detect_mimetype(filename))})
return media
def detect_mimetype(uri):
"""
Tries to guess the mimetype based on filename extension. If the extension
is unknown, or does not exist, returns None
"""
return guess_type(uri)[0]
if __name__ == '__main__':
# enter the host name of the blog you wish to post to here
base_hostname = "example.tumblr.com"
params = {"type": "photo", "tags": "your, tags", \
"more params": "see https://www.tumblr.com/docs/en/api/v2#posting"}
# to upload a non-media posts, just set this to None, or delete it from the call below
# to upload a video or audio file, set its URI as the only list item
# local video uploads work, have yet to test audio or remote video
# obviously you need to set the correct params too
media_file_list = ["list photo uris here",\
"C:\\example\\windows\\photo.jpg",\
"/example/linux/photo.jpg",\
"http://example.com/photo.jpg"]
files = encode_media(media_file_list)
# FILL IN KEYS/SECRETS FROM TUMBLR API CONSOLE
client = SimpleTumblrClient(consumer_key="", consumer_secret="", token="", token_secret="")
client.new_multipart_post(base_hostname, params, files)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment