Twicco Cloneをつくってみたよ
id:tottotiにTwiccoみたいなのを作りたいんだけどなんとかならん?という相談を受けたのでPythonを使ったOAuthの勉強がてらにいろいろいじってみましたよ
OAuth関係の語句とかはかなり適当に覚えてるっぽいので間違ってたら教えてください。ソレ以上にPython的におかしい箇所が多そうなので見つけたら教えていただければ(´;ω;`)Pythonリハビリチュウデスノ
想定する動作と環境
想定する動作は「自分(BOT用Twitterアカウント等)に対してPOSTされたmentionを自分の発言としてPOSTする」って感じです。
想定する環境はPythonをスクリプトとして実行できる感じデス…ごめんなさいLinuxしか想定してないです(´・ω・`)
ざっくりとした流れ
Twicco Clone的なものを動かすための手順は次のような感じですねー
情報保存用のディレクトリの用意
以下のディレクトリを実行ロケーションに用意します
- conf: CONSUMER情報の保存ディレクトリ
- users: ユーザ情報を格納(複数ユーザOK)
- tmp: 取得情報(どのmentionまで処理したか)を格納
設定ファイルの記述
CONSUMER情報をconf/twitter.confに以下の形式で記述しますよ
# Twitter OAuth Parameter CONSUMER_KEY:<CONSUMER KEY> CONSUMER_SECRET:<CONSUMER SECRET>
ユーザアクセストークンの取得
取得用スクリプトの作成
#!/usr/bin/python # -*- coding: utf-8 -*- # Code from reppets.log # http://d.hatena.ne.jp/reppets/20100522/1274553529 from oauth2 import Client, Token, Consumer import os # Read OAuth Parameter work_dir = os.path.dirname(os.path.abspath(__file__)) + '/' params = open(work_dir + 'conf/twitter.conf', 'r') conf = {} for line in params: param_list = line[:-1].split(':') if 1 < len(param_list): conf[param_list[0]] = param_list[1] params.close() consumer_key = conf['CONSUMER_KEY'] consumer_secret = conf['CONSUMER_SECRET'] # define param splitter def split_parameter(params): result_list = [tuple(param.split('=')) for param in params.split('&')] return dict(result_list) # getting twitter user name user_name = raw_input('Please input twitter user name:') # Authentication OAuth consumer = Consumer(consumer_key, consumer_secret) client = Client(consumer, None) result = client.request('http://api.twitter.com/oauth/request_token','GET') request_token_map = split_parameter(result[1]) request_token = Token(request_token_map['oauth_token'], request_token_map['oauth_token_secret']) ### URL display print 'Please access "http://api.twitter.com/oauth/authorize?oauth_token='+request_token.key+'".' pin = raw_input('Please input PIN:') request_token.set_verifier(pin) # POST clinent Token client.token = request_token result = client.request('http://api.twitter.com/oauth/access_token','POST') access_token_map = split_parameter(result[1]) print result[1] print 'User key: '+access_token_map['oauth_token'] print 'User secret: '+access_token_map['oauth_token_secret'] user_key = """USER_KEY:""" + access_token_map['oauth_token'] +""" USER_SECRET:""" + access_token_map['oauth_token_secret'] + """ """ # create user.key file f = open(work_dir + 'users/' + user_name, 'w') f.write(user_key) f.close() raw_input('Push any key to quit.')
twicco風スクリプトの作成
アクセストークン情報が取得できたので実際のTwitter関連の処理を作成しますかねー
スクリプトの作成
下記のようなスクリプトを作成してPythonスクリプトとして実行します。スクリプトの内容はmentionを取得して内容を発言するだけ、という単純動作です。
#!/usr/bin/python # -*- coding: utf-8 -*- from urllib import urlencode from oauth2 import Client, Consumer, Token import simplejson as json import re import os # Define Twicco Clone class TwiccoClone: #################################### # Constructor of TwiccoClone def __init__(self): # Get Dir Info self.work_dir = os.path.dirname(os.path.abspath(__file__)) + '/' # Get Twitter Param self.conf = self._param() # Define API URL self.api_url = 'http://api.twitter.com/1/' #################################### # Get Parameter def _param(self): conf = {} # Read Twitter config params = open(self.work_dir + 'conf/twitter.conf', 'r') for line in params: param_list = line[:-1].split(':') if 1 < len(param_list): conf[param_list[0]] = param_list[1] params.close() # Read user key config users = os.listdir(self.work_dir + 'users/') conf['users'] = [] for user in users: params = open(self.work_dir + 'users/' + user, 'r') user_keys = {} user_keys['name'] = user for line in params: param_list = line[:-1].split(':') if 1 < len(param_list): user_keys[param_list[0]] = param_list[1] params.close() conf['users'].append(user_keys) return conf #################################### # Get Mensions def _mentions(self): last_mention_file = 'tmp/last_mention_' + self.conf['USER_NAME'] # create empty file if os.path.isfile(self.work_dir + last_mention_file) == False: last_file = open(self.work_dir + last_mention_file,'w') last_file.write('') last_file.close() # Get last mentions last_file = open(self.work_dir + last_mention_file,'r') since_id = last_file.read() last_file.close() # last mentions exists if since_id != '': result = self.client.request(self.api_url + 'statuses/mentions.json?count=200&since_id=' + str(since_id)) # first time else: result = self.client.request(self.api_url + 'statuses/mentions.json?count=200') # Get Mentions mentions = json.loads(result[1]) # Execute Format Mentions r = re.compile('@' + self.conf['USER_NAME'] + ' ') count = 0 for mention in mentions: user = mention['user'] # keep back self loop if user['screen_name'] != self.conf['USER_NAME']: # init time not post if since_id != '': self._post({'user_name':user['screen_name'], # cut out target signature 'text':r.sub('', mention['text'])}) # save last mention if 0 == count: last_file = open(self.work_dir + last_mention_file,'w') last_file.write(str(mention['id'])) last_file.close() count += 1 #################################### # Post Message def _post(self, tweet=None): if tweet != None: # format message message = tweet['text'] + ' [ from @'+ tweet['user_name'] +' ]' # post message self.client.request(self.api_url + 'statuses/update.xml','POST', urlencode({'status':message.encode('utf_8')})) #################################### # Execute Process def echo(self): users = self.conf['users'] for user in users: self.conf['USER_NAME'] = user['name'] # Get Twitter API Session self.client = Client(Consumer(self.conf['CONSUMER_KEY'], self.conf['CONSUMER_SECRET']), Token(user['USER_KEY'], user['USER_SECRET'])) self._mentions() #################################################### # define main function def main(): import sys import codecs sys.stdout = codecs.getwriter('utf_8')(sys.stdout) ### Execute Code twicco = TwiccoClone() twicco.echo() # when exexute this script if __name__ == "__main__": main()
スクリプトの実行
実行時はこんな感じでOKです
$python twiccoClone.py
一応モジュールとしてインポート出来るように書いたので、適当にインポートして使っても大丈夫なはずです...たぶん(´・ω・`)それと、定期的に実行する場合はCRONを使ってくださいなー
以上ですよー
こんな感じにやればTwiccoっぽい処理が作れますよーというサンプルでした。
動くかどうかのお試し実装のためエラー処理とかは省いています(´;ω;`)ジカンガナカッタ ので実際に使う場合はそのあたりを補完したほうがいいです。
上記スクリプトファイルは以下においておきますね
http://plasticscafe.sakura.ne.jp/twicco_clone.tgz