しりとリツイート

しりとリツイートって何?

数多のツイートから無作為にピックアップしてはじめの文字と終わりの文字でしりとりをするツイッターbotです。

現在の機能

  • 毎日午後10時に鍵なしツイートの中からピックアップ
  • ある程度探してしりとりが繋がらなかったらその回は何もしない
  • 「ば」→「は」のような感じで、割とゆるめなルール
  • 様々な文字種に対応(ひらがな、カタカナ、漢字)
  • 末尾のURL、「!」や「?」は無視
  • 名前やプロフィールに「bot」「Bot」「BOT」が入ってる場合は除外

コード紹介

twitterの認証とかはpythonがめちゃ便利なので、pythonで全部書いてしまいました。色々と関数化したら長くなってしまいましたが最後のmain関数が本体です。continueすると以降の処理は飛ばしてfor文の最初まで戻るらしいです。使いようによっては便利ですね。

#coding:utf-8

from requests_oauthlib import OAuth1Session
import json, urllib2
from datetime import datetime
import os
import sys
import time
import re
import TwitterKEYS #twitterのキーを保存しておくファイル
from subprocess import Popen, PIPE

#カタカナ→ひらがなに変換する関数
def henkan(text):
	hiragana=[unichr(i) for i in range(12353,12436)]
	katakana=[unichr(i) for i in range(12449,12532)]
	kana=""
	
	if u'ア' <= text <= u'ワ':
		for text in list(text):
			for i in range(83):
				if text == katakana[i]:
					kana+=hiragana[i]
		return kana
	else:
		return text

#小文字、濁音を変換する関数
def change(text):
	if len(text) == 1:
		n = ord(text)
		#ぁ〜ぉ→あ〜お
		if 0x3041 <= n <= 0x304A and n % 2 == 1:
			text = unichr( n + 1 )
		#が〜ぢ→か〜ち
		elif 0x304C <= n <= 0x3062 and n % 2 == 0:
			text = unichr( n - 1 )
		#っ、づ→つ
		elif 0x3063<= n <= 0x3065:
			text = unichr( 0x3064)
		#で〜ど→て〜と
		elif 0x3066 <= n <= 0x3069 and n % 2 == 1:
			text = unichr( n - 1 )
		#ば、ぱ〜ぼ、ぽ→は〜ほ
		elif 0x306F <= n <= 0x307D and n % 3 != 0:
			text = unichr( n - (n%3) )
		#ゃ、ゅ、ょ→や、ゆ、よ
		elif 0x3083 <= n <= 0x3088 and n % 2 == 1:
			text = unichr( n + 1 )
	else:
		print "change error."
	return text

#漢字の読み仮名をとってくる関数→「mecab」で実現
def get_yomigana(text):
	p1 = Popen(['echo', text], stdout = PIPE)
	p2 = Popen(['mecab', '-Oyomi'], stdin = p1.stdout, stdout = PIPE)
	p1.stdout.close()
	output = p2.communicate()[0]
	return re.sub(r'\n', '', output)

#末尾に英数字があったら削除する関数
def skip(text):
	skip_list = u"/: .abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789#」…。、??!!〜))ー"
	while skip_list.find(text[-1:])>=0:
		text = text[:-1]
	return text

#テキストをツイートする関数
def tweet(text):
	#ツイート投稿URL
	URL_tweet = 'https://api.twitter.com/1.1/statuses/update.json'
	
	twitter = OAuth1Session(TwitterKEYS.CK,TwitterKEYS.CS,TwitterKEYS.AT,TwitterKEYS.AS)
	
	params = {"status": text}
	req = twitter.post(URL_tweet,params = params)

#テキストの最初の文字をひらがなで返す
def check_first_letter(text):
	#最初の文字をひらがな、カタカナ、先頭4文字の読み仮名の順にチェック
	#最初の文字をひらがなで出す
	first_letter = text[0:1]
	if u'あ' <= first_letter <= u'わ':
		print first_letter.encode('utf-8')
	else:
		first_letter = henkan(first_letter)
		if u'あ' <= first_letter <= u'わ':
			print first_letter.encode('utf-8')
		else:
			yomi = get_yomigana(text[0:4]).decode('utf-8')
			first_letter = henkan(yomi[0:1])
			if u'あ' <= first_letter<= u'わ':
				print first_letter.encode('utf-8')
			else:
				print "cannot define first letter."
				first_letter = u'ん'
	return first_letter

#テキストの最後の文字をひらがなで返す
def check_last_letter(text):
	last_letter = text[-1:]
	last_letter = henkan(last_letter)
	last_letter = change(last_letter)
	return last_letter

#ここからメイン関数
def main():
	
	#はじめの文字をファイルから読み出す
	logfile_path = "/home/ppdr/chain.txt"
	f = open(logfile_path,"r")
	start = f.read().decode('utf-8')[0:1]
	f.close()
	
	print start.encode('utf-8')
	
	#はじめの文字で検索
	req_count = 100	#取得するツイート数
	params = {"q" : start + ' -rt','lang':'ja','count':req_count}	#検索時のパラメータ?
	twitter = OAuth1Session(TwitterKEYS.CK,TwitterKEYS.CS,TwitterKEYS.AT,TwitterKEYS.AS)	#twitteキーを使って認証
	req = twitter.get("https://api.twitter.com/1.1/search/tweets.json",params = params)	#検索結果をjsonで取得
	
	if req.status_code == 200:
		js = json.loads(req.text)
		for i in range(0, req_count):
			txt = js['statuses'][i]['text']
			
			#最初の文字が一致しない場合、除外
			if not(check_first_letter(txt) == start):
				continue
			
			#末尾の英数字を削除
			txt = skip(txt)
			print "skipped:    "+txt.encode('utf-8')
			
			#最後の文字がつぎにつながらない場合、除外
			last_letter = check_last_letter(txt)
			if not(u'あ' <= last_letter <= u'わ'):
				continue
			
			#最後の文字が前回と同じ場合、除外
			if (last_letter == start):
				continue
			
			#ユーザーネーム、プロフィール、スクリーンネームのいずれかに「bot」が入っていたら除外
			bot_check_text = js['statuses'][i]['user']['name']+js['statuses'][i]['user']['description']+js['statuses'][i]['user']['screen_name']
			if ('bot' in bot_check_text) or ('Bot' in bot_check_text) or ('BOT' in bot_check_text):
				continue
			
			#条件確定
			#リツイート
			txt_id = js['statuses'][i]['id']
			req = twitter.post('https://api.twitter.com/1.1/statuses/retweet/'+str(txt_id)+'.json')
			
			if req.status_code == 200:
				print "post success!"
				
				#リツイートが成功したらつぎの文字をファイルに書き出す
				f = open(logfile_path,"w")
				f.write(last_letter.encode('utf-8'))
				f.close()
				
				#つぎの文字をツイート
				txt = u"リツイートしりとり!\n\nつぎの文字は・・・\n『" + txt[-1:] + u"』!!"
				time.sleep(1)
				tweet(txt)
				break
			else:
				print "post filure"
				break
	
	else:
		print "error!"
		print req.status_code
	
if __name__ == "__main__":
	main()