I've been exporting info from my iRacing Stats application to html to do weekly and end of season updates on my iRacing blog. This process had been fairly manual; I'd manually upload the graph images to blogger, create a new blog post and paste in the exported html and edit the img tags to point to the uploaded images. Its not that it was too painful, but since it was a repetitive task I wanted to see if I could automate it.
So I dived into the Google API doco and pretty quickly worked out how to get my python application to post a new blog update. Getting the images uploaded was more painful, since blogger actually uses picasa to store images and the picasa API is terrible. I ended up using Google Drive to store the images, which means I needed to handle a few more steps than just uploading; namely changing the permissions to public viewing, uploading to a folder and retrieving the public url.
I've got it all working now, including prompting the user for only their blog's URL from which it app pulls the BlogID (rather than having to have the user go off and find it). All in all I'm quite proud of getting it all working. I just hope Google don't go changing their APIs in the near future.
I'm sure the knowledge I've gained here will be useful in many other projects.
Here's a bunch of links which I found helpful:
Authorized Google API access from Python
google-api-python-client
oauth2client
Here's a bit of code:
from oauth2client import file, client, tools
from apiclient.discovery import build
from apiclient.http import MediaFileUpload
from httplib2 import Http
def blogger_post(outfile):
try:
html_file = open(outfile)
html_lines = html_file.read()
chop_start = html_lines.find('')
chop_end = html_lines.find('')
html_lines = html_lines[chop_start+6:chop_end]
CLIENT_SECRET = 'client_secrets.json'
SCOPE = 'https://www.googleapis.com/auth/blogger'
store = file.Storage('storage_blogger.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets(CLIENT_SECRET, SCOPE)
creds = tools.run(flow, store)
service = build('blogger', 'v3', creds.authorize(Http()))
body = {
"kind": "blogger#post",
"id": cfg.config['Blogger']['blogid'],
"title": os.path.basename(os.path.splitext(outfile)[0]),
"content":html_lines
}
request = service.posts().insert(blogId=cfg.config['Blogger']['blogid'], isDraft=True, body=body)
response = request.execute()
return response['url']
except:
return "Failed"
def blogger_img_upload(filename):
try:
CLIENT_SECRET = 'client_secrets.json'
SCOPE = ('https://www.googleapis.com/auth/drive', 'https://www.googleapis.com/auth/drive.file')
store = file.Storage('storage_drive.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets(CLIENT_SECRET, SCOPE)
creds = tools.run(flow, store)
service = build('drive', 'v2', creds.authorize(Http()))
q = "title = 'iRacing Stats Graphs' and mimeType = 'application/vnd.google-apps.folder'"
request = service.files().list(q=q)
response = request.execute()
if len(response['items']) == 0:
body = {
"title": "iRacing Stats Graphs",
"mimeType": "application/vnd.google-apps.folder"
}
request = service.files().insert(body=body)
response = request.execute()
folderId = response['id']
else:
folderId = response['items'][0]['id']
pub.sendMessage('Uploading', graph=os.path.basename(os.path.splitext(filename)[0]))
body = {
"title": os.path.basename(os.path.splitext(filename)[0]),
}
body['parents'] = [{'id': folderId}]
media_body = MediaFileUpload(filename)
request = service.files().insert(body=body, media_body=media_body)
response = request.execute()
fileId = response['id']
body = {
"type": "anyone",
"role": "reader"
}
response = service.permissions().insert(fileId=fileId, body=body).execute()
response = service.files().get(fileId=fileId).execute()
return response['webContentLink'].split('&')[0]
except:
print("Upload of %s to blogger failed" % os.path.basename(os.path.splitext(filename)[0]))
return "Failed"
def blogger_config(url):
try:
CLIENT_SECRET = 'client_secrets.json'
SCOPE = 'https://www.googleapis.com/auth/blogger'
store = file.Storage('storage_blogger.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets(CLIENT_SECRET, SCOPE)
creds = tools.run(flow, store)
service = build('blogger', 'v3', creds.authorize(Http()))
response = service.blogs().getByUrl(url=url).execute()
cfg.write_blogid(response['id'])
return True
except:
pub.sendMessage('Alert', msg="Unable to find BlogID of: %s" % url, title="Blogger Config Failed")
return False