Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
This script take pictures from directory and post it to tumblr blog and then delete it. Tumblr API v2! This example for oath file upload.
import urlparse
import oauth2 as oauth
consumer_key = ''
consumer_secret = ''
request_token_url = 'http://www.tumblr.com/oauth/request_token'
access_token_url = 'http://www.tumblr.com/oauth/access_token'
authorize_url = 'http://www.tumblr.com/oauth/authorize'
consumer = oauth.Consumer(consumer_key, consumer_secret)
client = oauth.Client(consumer)
# Step 1: Get a request token. This is a temporary token that is used for
# having the user authorize an access token and to sign the request to obtain
# said access token.
resp, content = client.request(request_token_url, "GET")
if resp['status'] != '200':
raise Exception("Invalid response %s." % resp['status'])
request_token = dict(urlparse.parse_qsl(content))
print "Request Token:"
print " - oauth_token = %s" % request_token['oauth_token']
print " - oauth_token_secret = %s" % request_token['oauth_token_secret']
print
# Step 2: Redirect to the provider. Since this is a CLI script we do not
# redirect. In a web application you would redirect the user to the URL
# below.
print "Go to the following link in your browser:"
print "%s?oauth_token=%s" % (authorize_url, request_token['oauth_token'])
print
# After the user has granted access to you, the consumer, the provider will
# redirect you to whatever URL you have told them to redirect to. You can
# usually define this in the oauth_callback argument as well.
accepted = 'n'
while accepted.lower() == 'n':
accepted = raw_input('Have you authorized me? (y/n) ')
oauth_verifier = raw_input('What is the PIN? ')
# Step 3: Once the consumer has redirected the user back to the oauth_callback
# URL you can request the access token the user has approved. You use the
# request token to sign this request. After this is done you throw away the
# request token and use the access token returned. You should store this
# access token somewhere safe, like a database, for future use.
token = oauth.Token(request_token['oauth_token'],
request_token['oauth_token_secret'])
token.set_verifier(oauth_verifier)
client = oauth.Client(consumer, token)
resp, content = client.request(access_token_url, "POST")
access_token = dict(urlparse.parse_qsl(content))
print "Access Token:"
print " - oauth_token = %s" % access_token['oauth_token']
print " - oauth_token_secret = %s" % access_token['oauth_token_secret']
print
print "You may now access protected resources using the access tokens above."
print
import glob
import json
import os
import time
import urllib2
import urlparse
import oauth2
from poster.encode import multipart_encode
from poster.streaminghttp import register_openers
class APIError(StandardError):
def __init__(self, msg, response=None):
StandardError.__init__(self, msg)
class TumblrAPIv2:
def __init__(self, consumer_key, consumer_secret, oauth_token, oauth_token_secret):
self.consumer = oauth2.Consumer(consumer_key, consumer_secret)
self.token = oauth2.Token(oauth_token, oauth_token_secret)
self.url = "http://api.tumblr.com"
def parse_response(self, result):
content = json.loads(result)
if 400 <= int(content["meta"]["status"]) <= 600:
raise APIError(content["meta"]["msg"], result)
return content["response"]
def createPhotoPost(self, id, post):
url = self.url + "/v2/blog/%s/post" %id
img_file = post['data']
del(post['data'])
req = oauth2.Request.from_consumer_and_token(self.consumer,
token=self.token,
http_method="POST",
http_url=url,
parameters=post)
req.sign_request(oauth2.SignatureMethod_HMAC_SHA1(), self.consumer, self.token)
compiled_postdata = req.to_postdata()
all_upload_params = urlparse.parse_qs(compiled_postdata, keep_blank_values=True)
for key, val in all_upload_params.iteritems():
all_upload_params[key] = val[0]
all_upload_params['data'] = open(img_file, 'rb')
datagen, headers = multipart_encode(all_upload_params)
request = urllib2.Request(url, datagen, headers)
try:
respdata = urllib2.urlopen(request).read()
except urllib2.HTTPError, ex:
return 'Received error code: ', ex.code
return self.parse_response(respdata)
register_openers()
CONSUMER_KEY = ''
CONSUMER_SECRET = ''
OAUTH_TOKEN = ''
OAUTH_TOKEN_SECRET = ''
DIR = 'dir/with/pictures'
FILE_MASK = '*.jpg'
BLOG = 'blog here'
api = TumblrAPIv2(CONSUMER_KEY, CONSUMER_SECRET, OAUTH_TOKEN, OAUTH_TOKEN_SECRET)
for img in glob.glob( os.path.join(DIR, FILE_MASK) ):
date = time.gmtime(os.path.getmtime(img))
post = {
'type' : 'photo',
'date' : time.strftime ("%Y-%m-%d %H:%M:%S", date),
'data' : img,
'tags' : time.strftime ("%Y", date) + ", photo",
'caption' : time.strftime ("%B %d / %Y", date)
}
try:
response = api.createPhotoPost(BLOG,post)
if 'id' in response:
print response['id']
os.remove(img)
else:
print response
break
except APIError:
print "Error"
break
print "Done!"
@danpalmer

This comment has been minimized.

Copy link

commented Sep 27, 2011

This doesn't work for me either. I just get the "Done!" message immediately and it doesn't actually upload. Any ideas what I might be getting wrong?

@velocityzen

This comment has been minimized.

Copy link
Owner Author

commented Sep 27, 2011

Do you setup all your settings? CONSUMER_KEY, CONSUMER_SECRET, OAUTH_TOKEN, OAUTH_TOKEN_SECRET, DIR, BLOG? And try absolute path to pictures.

@velocityzen

This comment has been minimized.

Copy link
Owner Author

commented Sep 27, 2011

Oh, I think you didn't provide right file mask for files. Just added option for this.

@danpalmer

This comment has been minimized.

Copy link

commented Sep 27, 2011

Ok, this seems to be working better now. I am now getting 404s when attempting to upload. It takes a while to do that though so I guess it is actually uploading.

@GeeGle

This comment has been minimized.

Copy link

commented Oct 5, 2011

Hi there
This script wont work for me, I keep getting 401 errors
Please check!
By the way, what should the "Default callback URL:" be? A random URL?

@velocityzen

This comment has been minimized.

Copy link
Owner Author

commented Oct 5, 2011

401 means that you are not authenticated. You must fill in all this CONSUMER_KEY, CONSUMER_SECRET, OAUTH_TOKEN, OAUTH_TOKEN_SECRET
If you don't know how to get oauth tokens, check example here: https://github.com/simplegeo/python-oauth2 (if you use script only to get token secret you can put any callback url)

@GeeGle

This comment has been minimized.

Copy link

commented Oct 5, 2011

Hi Thanks so much for your reply.
I guess I get the wrong OAUTH_TOKEN and OAUTH_TOKEN_SECRET.
I follow the example, but tumblr wont support PIN authorization method while Twitter does.
Check the first answer of this quetion:
http://stackoverflow.com/questions/7569018/oauth-client-initialization-in-python-for-tumblr-api-using-python-oauth2
Does that mean we will never get the OAUTH_TOKEN and OAUTH_TOKEN_SECRET?

@velocityzen

This comment has been minimized.

Copy link
Owner Author

commented Oct 5, 2011

Pin must be in callback url! I added script for authentication!

@GeeGle

This comment has been minimized.

Copy link

commented Oct 5, 2011

Hi But the problem is that there is no PIN.
I go to http://www.tumblr.com/oauth/authorize?oauth_token=xxxxx
and see "Grant this application read and write access to your Tumblr account? "
I click "Allow", then I am sent to the callback url
I cant find the PIN.
Tumblr dosent support PIN verification I am afraid.

@velocityzen

This comment has been minimized.

Copy link
Owner Author

commented Oct 5, 2011

after you press Allow you must be redirected to callback url. PIN is oauth_verifier in url

@velocityzen

This comment has been minimized.

Copy link
Owner Author

commented Oct 5, 2011

Don't be afraid. This completely working script!

@GeeGle

This comment has been minimized.

Copy link

commented Oct 5, 2011

velocityzen, Thanks for you help! You have made my day. It works perfectly now.

@velocityzen

This comment has been minimized.

Copy link
Owner Author

commented Oct 5, 2011

Cool!

@mohacs

This comment has been minimized.

Copy link

commented Nov 16, 2011

@velocityzen hi, here "data : img," what is the string equivalent of "img" here? i am sorry asking because i have no idea about this language. i mean what is data=????????????
many thanks.
m.

@velocityzen

This comment has been minimized.

Copy link
Owner Author

commented Nov 16, 2011

@mohacs it's python. img from line 69

@mohacs

This comment has been minimized.

Copy link

commented Nov 16, 2011

@velocityzen hi,
yes but i have no idea what do you send it as image or data or string. with my best knowledge it should be url encoded binary string. i want to figure out how should i encode the file that's why i say string output.. i hope i can tell what my problem is.

@velocityzen

This comment has been minimized.

Copy link
Owner Author

commented Nov 16, 2011

@mohacs Yeah it's string! All magic happens cause of poster (check line 55).

@mohacs

This comment has been minimized.

Copy link

commented Nov 16, 2011

i am sorry i do not understand the python. you can call me dumb but please paste the string here is possible. is it hex based or straight binary i am just stuck here. i have converted image to straight binary 11001010101 and base64 and hex, wrapped with url encoding but didn't work. yes it is stupid but i want to see the sting once if possible. thank you.

@velocityzen

This comment has been minimized.

Copy link
Owner Author

commented Nov 16, 2011

img — just string with full path to image file "/some/path/file.jpg"

@mohacs

This comment has been minimized.

Copy link

commented Nov 16, 2011

ok sorry it is my bad... let me ask from this way.when you send the request how body looks like
type=photo&caption=test&data=[????????]
many thanks.

@velocityzen

This comment has been minimized.

Copy link
Owner Author

commented Nov 22, 2011

It's a poster's kitchen. Check that module if you want to know how it works. But it must send multipart form data in post request.

@gerbz

This comment has been minimized.

Copy link

commented Jul 19, 2012

@mohacs did you ever get this working? Having same trouble with the format of the image data.

@mohacs

This comment has been minimized.

Copy link

commented Jul 19, 2012

@ggwarpig they posted new/working copy to the tumblr google group. i quit from the project because their API is defected.

@vvic2081

This comment has been minimized.

Copy link

commented Sep 19, 2012

thanks, this works for me, although "blog here" should really be "nameofblog.tumblr.com". However this one gives me 401 unauthorized: https://gist.github.com/1649885

@AJ

This comment has been minimized.

Copy link

commented Sep 22, 2012

Hi,

I'm getting the following output:

('Received error code: ', 404)
Done!

What does it mean and how do I fix it?

@jonathanbell

This comment has been minimized.

Copy link

commented Nov 30, 2012

Thank you so much for this! :) It's saved me a huge amount of work!

@dannysi

This comment has been minimized.

Copy link

commented Dec 17, 2012

great script. just what i was looking for

@mcanet

This comment has been minimized.

Copy link

commented Jan 7, 2013

Great script. Took me some hours to get that PIN is the variable "oauth_verifier" in the url encoding callback after accept permission in the tumblr account.

As a suggestion to safe time in future to people, maybe a print explaining what is PIN will be useful.

@bottah

This comment has been minimized.

Copy link

commented Feb 9, 2013

Is this still working...? I am getitng 404. I've gone through the auth process, received my access tokens, and configured the following:

CONSUMER_KEY = ''
CONSUMER_SECRET = ''
OAUTH_TOKEN = ''
OAUTH_TOKEN_SECRET = ''
DIR = ''
BLOG = ''

On execution, I receive the following:
('Received error code: ', 404)
Done!

Any help?

Thanks

@bottah

This comment has been minimized.

Copy link

commented Feb 10, 2013

Doh! I figured it out... I had everything configured correctly, except the BLOG variable. Tumblr expects the full base-hostname, and I was just using the blog's name. Simple oversight. Script works beautifully. Thank you!!

@H1ccup

This comment has been minimized.

Copy link

commented Feb 12, 2013

Script doesn't work. I get a 404 error code while posting to tumblr. Have checked all the necessary credentials multiple times.

@andrewkolesnikov

This comment has been minimized.

Copy link

commented Feb 20, 2013

Thank you for posting this!

@iMartian

This comment has been minimized.

Copy link

commented Mar 6, 2013

I too am getting that 404 error code.

Are these the correct format:

DIR = 'C:/Users/MyUserName/scripts/Python-Tumblr-Tests'
FILE_MASK = '*.jpg'
BLOG = 'http://myblog.tumblr.com'

@westondeboer

This comment has been minimized.

Copy link

commented Jun 11, 2013

awesome! Thanks for this. Took my newb mind a couple of hours to figure it out.

  1. python auth.py
  2. go to url
  3. allow in tumblr
  4. y (yes authenticated)
  5. copy url you are returned to: ex google.com/?oauth_token=927839871293871928hikjb copy this long key
  6. PIN = number copied from step 5
  7. you get your oath token and secret

now fill it all up in photo2tumblr.py and your goodie good to go

@josenaves

This comment has been minimized.

Copy link

commented Jun 29, 2013

I've had the same problems as you (404). It's fully functional now !

The problems is with BLOG variable.

It's just the blog host name not the URL !

WRONG: http://josenaves.tumblr.com/
RIGHT: josenaves.tumblr.com

@gosharplite

This comment has been minimized.

Copy link

commented Aug 26, 2013

Here's my 2 cents. (Ubuntu)

  1. Register application with tumblr. Get Consumer Key and Secret Key. http://www.tumblr.com/oauth/apps
  2. Edit consumer_key and consumer_secret in auth.py
  3. Install python, python-oauth2, python-poster
  4. python auth.py
  5. go to url
  6. 'allow' in tumblr web page
  7. y (yes authenticated)
  8. copy url you are returned to: ex google.com/?oauth_token=927839871293871928hikjb copy this long key (as PIN)
  9. PIN = number copied from step 8
  10. Edit photo2tumblr.py
    CONSUMER_KEY = ''
    CONSUMER_SECRET = ''
    OAUTH_TOKEN = ''
    OAUTH_TOKEN_SECRET = ''
    DIR = 'dir/with/pictures'
    FILE_MASK = '*.jpg'
    BLOG = 'blog here'
  11. Careful about BLOG
    WRONG: http://josenaves.tumblr.com/
    RIGHT: josenaves.tumblr.com
  12. python photo2tumblr.py
@cosmicpudding

This comment has been minimized.

Copy link

commented Oct 6, 2013

Thanks for this great script! Following gosharplite's steps, I got it working for single images. But how do you extend it so it posts multiple images in a single post? I've tried a few things which haven't worked :p

@windmillium

This comment has been minimized.

Copy link

commented Dec 17, 2013

Step number 8 above should use the oauth_verifier param not the oauth_token, other than that it works.

@soenkesmiletzki

This comment has been minimized.

Copy link

commented Dec 28, 2014

I have some problem with this script.
i copied two pictures to a folder and starting script:

python photo2tumblr.py
106408893386
106408894521
Done!

So, both pictures are deleted at the picturefolder, but there is no posting at my tumblr blog.
Any idea?

@charlesbrandt

This comment has been minimized.

Copy link

commented Jul 19, 2015

Here's what I did to make this work for photosets (multiple photos for one post):
https://gist.github.com/charlesbrandt/11eadaec114288d621fa

@Phrohdoh

This comment has been minimized.

Copy link

commented Aug 23, 2015

What is 'PIN' supposed to be?

$ python auth.py
Request Token:
    - oauth_token        = HNeepB644EtQcUTWGsSlhYZgQ0Z8Hg8kkI0XNqDR4x8Qyjl0Qa
    - oauth_token_secret = <secret key>

Go to the following link in your browser:
http://www.tumblr.com/oauth/authorize?oauth_token=HNeepB644EtQcUTWGsSlhYZgQ0Z8Hg8kkI0XNqDR4x8Qyjl0Qa

Have you authorized me? (y/n) y
What is the PIN?

My callback URL is just tumblr.com as I don't have a site for a test like this.

@j-gao

This comment has been minimized.

Copy link

commented Sep 27, 2016

Worked like a charm!! Thanks velocityzen!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.