GAE/Pyを使ってTwitter本アカのふぁぼを自動ではてブ+サブアカに公式RTする。
Google App Engine を使ってTwitter本アカのふぁぼったツイートに含まれるリンクを自動ではてブ+サブアカに公式RTする。
※はてブからTwitterに流す設定をしている場合、AtomAPIからの投稿をTwitterに流さないようにしておく。ブコメに@を使っているので、ふぁぼったツイートの発言者さんに@飛ばすことを防ぐため。
ついでにGoogle Readerのスター付きアイテムを自動ではてブ+Twitterサブ垢に流す。
oauth.py
GAEのpython用oauthライブラリ
https://github.com/mikeknapp/AppEngine-OAuth-Library
WSSE.py
WSSE認証を利用したAtom APIとか - YAMAGUCHI::weblog
http://d.hatena.ne.jp/ymotongpoo/20081201/1228115936
[詰まったところ]
・Google Readerスター付きアイテムのAtomフィードをElementTreeだけでパースするところ。
・Task queueの使い方。
app.yaml
application: XXXXXXXXXXX #アプリケーション名 version: XX runtime: python api_version: 1 handlers: - url: /.* script: main.py login: admin
cron.yaml
cron: - description: twitter favs url: /regist_favs schedule: every 10 minutes timezone: Asia/Tokyo - description: Google Reader Stars url: /regist_GStars schedule: every 10 minutes timezone: Asia/Tokyo
queue.yaml
queue: - name: default rate: 1/s - name: bookmarkGStar rate: 1/m retry_parameters: task_retry_limit: 7 task_age_limit: 2d - name: bookmarkTwFav rate: 1/m retry_parameters: task_retry_limit: 7 task_age_limit: 2d - name: retweet rate: 1/m retry_parameters: task_retry_limit: 7 task_age_limit: 2d - name: tweetGStar rate: 1/m retry_parameters: task_retry_limit: 7 task_age_limit: 2d
main.py
#!/usr/bin/env python # -*- coding: utf-8 -*- __author__ = "yadokari23" import oauth import os import urllib, urllib2 from google.appengine.ext import webapp from google.appengine.ext.webapp import util from google.appengine.ext import db from google.appengine.api import urlfetch from django.utils import simplejson from xml.etree.ElementTree import * import datetime from WSSE import * from google.appengine.api.labs import taskqueue #Twitter アプリの情報 CONSUMER_KEY = "XXXXXXXXXX" #Consumer key CONSUMER_SECRET = "XXXXXXXXX" #Consumer secret #投稿先(サブ垢)のもの ACCESS_TOKEN = "XXXXXXXXXX" #access token ACCESS_TOKEN_SECRET = "XXXXXXXXXX" #access token secret #ふぁぼを監視するアカウントのscreen_name(今回は本アカ) T_ACCOUNT = 'XXXXXXXXXXX' #はてなアカウント情報 HATENA_USERNAME='XXXXXXX' HATENA_PWD='XXXXXXX' #Google Readerのスター付きアイテム公開ページのURL GSTARURL='XXXXXXXXXXXXXXXXXXXXX' MaxPage = 1 #MaxPage*20件 class favorites(db.Model): status_id = db.StringProperty(required=True) text = db.TextProperty() created = db.DateTimeProperty() url = db.TextProperty() user_id = db.StringProperty() user_screen_name = db.StringProperty() task = db.BooleanProperty(default=False) class GStars(db.Model): id = db.StringProperty(required=True) link = db.TextProperty() title = db.TextProperty() source_title = db.TextProperty() author = db.TextProperty() task = db.BooleanProperty(default=False) def get_longURL(shortURL): #短縮URLの展開 try: longURL = urllib2.urlopen(shortURL).geturl() except: longURL = '' return longURL class MainHandler(webapp.RequestHandler): def get(self, mode=""): if mode=='regist_favs': page = 1 while page <= MaxPage: query = {'screen_name':T_ACCOUNT, 'include_entities':'True', 'page':page } t_url = 'http://api.twitter.com/1/favorites.xml?%s' % urllib.urlencode(query) results = urlfetch.fetch(url=t_url, method=urlfetch.GET, deadline=10) dom = fromstring(results.content) if results.status_code == 200: if dom.findall('.//status'): for e in dom.findall('.//status'): q = favorites.gql("WHERE status_id = :1", e.findtext('./id')) fav = q.get() if fav is None: tweet_created = e.findtext('./created_at') tweet_created = datetime.datetime.strptime(tweet_created, '%a %b %d %H:%M:%S +0000 %Y') \ + datetime.timedelta(hours=9) p = favorites( status_id=e.findtext('./id'), text=e.findtext('./text'), created=tweet_created, url=e.findtext('./entities/urls/url/expanded_url'), user_id=e.findtext('./user/id'), user_screen_name=e.findtext('./user/screen_name'), ) if p.url == None: p.task = True p.put() page +=1 #task queue未登録のレコードを取り出す。 fav = favorites.all().filter('task =', False).get() if fav: fav_values={'status_id':fav.status_id, 'user_screen_name':fav.user_screen_name, 'url':fav.url } #タスクbookmarkTwFavのインスタンスを作成し、タスクを追加 bookmark_task = taskqueue.Queue('bookmarkTwFav') next_task = taskqueue.Task(url='/_bookmarkTwFav', params=fav_values) bookmark_task.add(next_task) #タスクretweetのインスタンスを作成し、タスクを追加 retweet_task = taskqueue.Queue('retweet') next_task = taskqueue.Task(countdown='60',url='/_retweet', params=fav_values) retweet_task.add(next_task) fav.task = True db.put(fav) if mode=='regist_GStars': #Googleスター付きアイテムをはてブする。 results = urlfetch.fetch(url=GSTARURL, method=urlfetch.GET, deadline=10) dom = fromstring(results.content) atom_ns = "http://www.w3.org/2005/Atom" if results.status_code == 200: if dom.findall('.//{%s}entry' % atom_ns): for e in dom.findall('.//{%s}entry' % atom_ns): q = GStars.gql("WHERE id = :1", e.find('./{%s}id' % atom_ns).text) GStar = q.get() if GStar is None: for e2 in e.findall('.//{%s}source' % atom_ns): source_title = e2.find('./{%s}title' % atom_ns).text for e3 in e.findall('.//{%s}author' % atom_ns): author = e3.find('./{%s}name' % atom_ns).text p = GStars(id=e.find('./{%s}id' % atom_ns).text, title=e.find('./{%s}title' % atom_ns).text, link=e.find('./{%s}link' % atom_ns).attrib['href'], source_title=source_title, author=author ) if p.link == None: p.task = True p.put() #task queue未登録のレコードを取り出す。 GStar = GStars.all().filter('task =', False).get() if GStar: param={'title':GStar.title, 'source_title':GStar.source_title, 'author':GStar.author, 'link':GStar.link } #タスクbookmarkGStarのインスタンスを作成し、タスクを追加 bookmark_task = taskqueue.Queue('bookmarkGStar') next_task = taskqueue.Task(url='/_bookmarkGStar', params=param) bookmark_task.add(next_task) #タスクtweetGStarのインスタンスを作成し、タスクを追加 tweet_task = taskqueue.Queue('tweetGStar') next_task = taskqueue.Task(url='/_tweet', params=param) tweet_task.add(next_task) GStar.task = True db.put(GStar) def post(self, mode=""): if mode=='_bookmarkTwFav': status_id = self.request.get("status_id") user_screen_name = self.request.get("user_screen_name") url = self.request.get("url") #WSSE認証 hbc = HatenaBookmarkClient(HATENA_USERNAME,HATENA_PWD) hbc.getServiceURI() # サービスエンドポイントの取得(PostURIとFeedURI) bookmarkURL = get_longURL(url) if bookmarkURL <> '': status_url = 'http://twitter.com/%s/status/%s' % (user_screen_name,status_id) hbcomment = u'[☆]@%s %s' % (user_screen_name,status_url) hbc.postBookmark(bookmarkURL, hbcomment) # ブックマークの登録 if mode=='_bookmarkGStar': url = self.request.get("link") #WSSE認証 hbc = HatenaBookmarkClient(HATENA_USERNAME,HATENA_PWD) hbc.getServiceURI() # サービスエンドポイントの取得(PostURIとFeedURI) if url <> '': hbcomment = u'[☆]' hbc.postBookmark(url, hbcomment) # ブックマークの登録 if mode=='_retweet': status_id = self.request.get("status_id") #TwitterClientクラスの作成 twc = oauth.TwitterClient(CONSUMER_KEY, CONSUMER_SECRET, None) url='http://api.twitter.com/1/statuses/retweet/%s.json' % status_id twc.make_request(url=url, token=ACCESS_TOKEN, secret=ACCESS_TOKEN_SECRET, protected=True, method='POST') if mode=='_tweet': title = self.request.get("title") source_title = self.request.get("source_title") author = self.request.get("author") link = self.request.get("link") text = u'[☆] %s / %s (%s) %s' % (title,source_title,author,link) query={'status':text} #TwitterClientクラスの作成 twc = oauth.TwitterClient(CONSUMER_KEY, CONSUMER_SECRET, None) url='http://api.twitter.com/1/statuses/update.json' twc.make_request(url=url, token=ACCESS_TOKEN, secret=ACCESS_TOKEN_SECRET, protected=True, additional_params=query, method='POST') def main(): application = webapp.WSGIApplication([('/(.*)', MainHandler)], debug=True) util.run_wsgi_app(application) if __name__ == '__main__': main()