2010年3月7日日曜日

TwitterボットをOAuthに対応させてみた - Google App Engine(Python)

Twitter APIのBASIC認証は2010年6月に「廃止予定」ということなので、対応していないアプリは今のうちにOAuthに対応させておいたほうが無難です。

自分の手持ちのTwitter botはBASIC認証を利用していたので、それをOAuth対応させてみました。
こいつ => @jquerybuzz

実際やってみた感想は、わりと簡単、でもハマりどころはある、という感じです。



以下、実際にやったことをメモ的にまとめておきます。
環境はGoogle App Engine (Python)です。




0. 準備

Twitterアプリの認証にOAuthを使う場合は、アプリケーションをTwitterに登録する必要があります。

自分の登録済のアプリ一覧

このページの下のほうにRegister a new application »というリンクがあるのでそこから新しいアプリを登録できます。

アプリ名やURLは適当に。
Twitterボットの場合は下のようにチェックを入れます。



登録が完了すると Consumer keyConsumer Secret が発行されます。
このキーを後で利用します。





1. アクセストークンを取得する

アプリケーションの登録が完了した後は、そのアプリを利用するユーザーの認証用のアクセス・トークンを取得します。
(厳密にはアクセス・トークンとアクセス・トークン・シークレット)

Twitterボットの場合、ユーザーはボットのアカウントをさします (自分の場合は@jquerybuzz)。

このあたり個人的にはややこしくて分かりにくかったのですが、ようするに下のように利用します。

・アクセストークンを最初に1度だけ取得
・取得したアクセストークンをボットのスクリプトに仕込んで認証に使う


さて、アクセストークンの取得の仕方ですが、自分でスクリプトを用意してTwitterに問い合せる必要があるようです。


以下Rubyになってしまいますが、便利なコードを提供してくれている方がいるのでそれを利用します。


a. ブラウザ無しでアクセストークンを取得する(いわゆるxAuth)

http://gist.github.com/304123

上のコードをxauth-twitter.rbという名前で保存して

ruby xauth-twitter.rb [1] [2] [3] [4] ([5])
# [1]: Your Twitter Name
# [2]: Your Twitter Password
# [3]: The Consumer Key of Your OAuth Apprication
# [4]: The Consumer Secret of Your OAuth Apprication
# [5]: The Server of the Service (optional: default is 'https://api.twitter.com')

アクセス・トークンが返ってくる...はずなのですが、自分の環境では certificate verify failed (OpenSSL::SSL::SSLError) というエラーが発生してうまくいきませんでした。

[2010/3/18 追記]
xAuthの利用はメールで承認を得る必要があるようです。
http://apiwiki.twitter.com/Twitter-REST-API-Method:-oauth-access_token-for-xAuth



b. ブラウザをはさんでアクセス・トークンを取得する


TwitterのbotをOAuthに対応させる

こちらの記事のtwitter-oauth.rbというスクリプトを使わせてもらいました。

(非常に丁寧な記事で、アクセス・トークンの取得だけでなくTwitterボットをOAuthに対応させるやり方がとっても参考になります。Rubyでボットを作っている方はそのままマネッコできそうです!)


途中ブラウザをはさむので誰のアカウントでログインしているのかややこしくなりますが、無事アクセス・トークン(とアクセス・トークン・シークレット)を取得。



2. Twitterにつぶやく

PythonのTwitterライブラリはいろいろあるのですが、今回はGAE向けということで下のライブラリを使うことに。

AppEngine-OAuth-Library

oauth.pyを下のapp.yaml、main.pyと同じディレクトリに置きます。

app.yaml
application: app
version: 1
runtime: python
api_version: 1

handlers:
- url: /.*
  script: main.py

main.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os

from google.appengine.ext import webapp
from google.appengine.ext.webapp import template, util

ROOT_PATH = os.path.dirname(__file__)
DEBUG = ROOT_PATH.find('/base') != 0

# さきほど取得した各情報をここで指定する
TWITTER_CONSUMER_KEY = 'アプリのconsumer key'
TWITTER_CONSUMER_SECRET = 'アプリのconsumer secret'
TWITTER_ACCESS_TOKEN = 'ボットのアカウントのアクセス・トークン'
TWITTER_ACCESS_TOKEN_SECRET =  'ボットのアカウントのアクセス・トークン・シークレット'


class TweetHandler(webapp.RequestHandler):
  def get(self):
    import oauth
    client = oauth.TwitterClient(TWITTER_CONSUMER_KEY,
                                 TWITTER_CONSUMER_SECRET, None)
    param = {'status': u"ボットにつぶやかせたい内容"}
    client.make_request('http://twitter.com/statuses/update.json',
                        token=TWITTER_ACCESS_TOKEN,
                        secret=TWITTER_ACCESS_TOKEN_SECRET,
                        additional_params=param,
                        protected=True,
                        method='POST')
    self.response.out.write('')


def main():
  application = webapp.WSGIApplication([('/tweet', TweetHandler)], debug=DEBUG)
  util.run_wsgi_app(application)

if __name__ == '__main__':
  main()

記述を簡略化するためにエラー処理などは省いてあります。
また、ボットにつぶやかせる内容を取得する処理などは各自で書く必要があるでしょう。

cron.yaml
cron:
- description: Post to Twitter
  url: /tweet
  schedule: every 1 hour
  #schedule: every 1 day     1日おき
  #schedule: every 15 minutes 15分おき

どれくらいの間隔でつぶやかせるかを設定。



あとは、上記のファイルを置いたディレクトリに移動して
appcfg.py update .

とコマンドを叩けばボットが動きはじめます。

0 件のコメント: