Skip to content

Instantly share code, notes, and snippets.

@benmj
Last active April 7, 2018 19:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benmj/4557965 to your computer and use it in GitHub Desktop.
Save benmj/4557965 to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
# -*- coding: utf8 -*-
import oauth2 as oauth
import urlparse
import os
import urllib
import sys
import json
from pprint import pprint
import xml.etree.ElementTree as ET
directory_name = os.path.dirname(os.path.realpath(__file__))
token_fn = os.path.join(directory_name, 'goodreads_tokens')
# look for tokens file. dev token is required
# if oauth token is not already in file, we'll fetch it
try:
json_data = open(token_fn)
goodreads_tokens = json.load(json_data)
json_data.close()
except IOError:
print "WOOPS: Can't open required file '%s'" % token_fn
sys.exit()
url = 'http://www.goodreads.com'
request_token_url = '%s/oauth/request_token' % url
authorize_url = '%s/oauth/authorize/' % url
access_token_url = '%s/oauth/access_token' % url
consumer = oauth.Consumer(key=goodreads_tokens['dev_key'],
secret=goodreads_tokens['dev_secret'])
client = oauth.Client(consumer)
if not 'oauth_token' in goodreads_tokens and not 'oauth_token_secret' in goodreads_tokens:
response, content = client.request(request_token_url, 'GET')
if response['status'] != '200':
raise Exception('Invalid response: %s' % response['status'])
request_token = dict(urlparse.parse_qsl(content))
authorize_link = '%s?oauth_token=%s' % (authorize_url,
request_token['oauth_token'])
print authorize_link
accepted = 'n'
while accepted.lower() == 'n':
# you need to access the authorize_link via a browser,
# and proceed to manually authorize the consumer
accepted = raw_input('Have you authorized me? (y/n) ')
token = oauth.Token(request_token['oauth_token'],
request_token['oauth_token_secret'])
client = oauth.Client(consumer, token)
response, content = client.request(access_token_url, 'POST')
if response['status'] != '200':
raise Exception('Invalid response: %s' % response['status'])
access_token = dict(urlparse.parse_qsl(content))
goodreads_tokens['oauth_token'] = access_token['oauth_token']
goodreads_tokens['oauth_token_secret'] = access_token['oauth_token_secret']
# write the access token to file
try:
f = open(token_fn, 'w')
f.write(json.JSONEncoder().encode(goodreads_tokens))
f.close()
except IOError:
print "WOOPS: Can't write tokens to file: '%s'" % token_fn
sys.exit()
token = oauth.Token(goodreads_tokens['oauth_token'],
goodreads_tokens['oauth_token_secret'])
client = oauth.Client(consumer, token)
headers = {'content-type': 'application/x-www-form-urlencoded'}
lookup_successes = []
lookup_failures = []
print "Querying IDs from Goodreads.com ..."
book_file = open('/home/ben/Dropbox/Read.txt')
# loop through and find the id numbers
for line in book_file:
date, title_author = line.strip().split('\t')
book = {}
try:
title, author = title_author.split(' -- ')
except ValueError:
book = {'date': date, 'title': title}
body = urllib.urlencode({'title': title})
else:
book = {'date': date, 'title': title, 'author': author}
body = urllib.urlencode({'author': author, 'title': title})
response, content = client.request('%s/book/title.xml' % url, 'GET', body, headers)
if response['status'] != '200':
lookup_failures.append(book)
print 'Error locating "%s" response code %s' % (title, response['status'])
else:
# print "Found! '%s'" % book['title']
root = ET.fromstring(content)
book['id'] = root.findall('book')[0].findall('id')[0].text
lookup_successes.append(book)
book_file.close()
print """\n\nSEARCH QUERIES:
Successes found: %d
Failures %d
Total Queries: %d\n\n""" % (len(lookup_successes), len(lookup_failures), len(lookup_successes) + len(lookup_failures))
add_successes = 0
add_failures = []
print "Adding books to Goodreads.com ..."
# # try adding the books to the 'read' shelf
for book in lookup_successes:
body = urllib.urlencode({'book_id': book['id'], 'shelf': 'read', 'review[read_at]': book['date']})
response, content = client.request('%s/review.xml' % url, 'POST', body, headers)
if response['status'] != '201':
add_failures.append(book)
print 'Error adding "%s" response code %s' % (book['title'], response['status'])
else:
add_successes += 1
print "Added: '%s'" % book['title']
print """\n\nADD QUERIES:
Successfully Added %d
Failures %d""" % (add_successes, len(add_failures))
pprint(add_failures)
@benmj
Copy link
Author

benmj commented Jan 17, 2013

TODO:

  1. more command line options, like scan latest entries of Read.txt and add, instead of whole list
  2. Other shelves: to-read, etc
  3. Sync down from goodreads for Read.txt and To-read.txt

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment