The jonki

呼ばれて飛び出てじょじょじょじょーんき

Google App Engine for Java でTwitterボットを動かす。

GAEには定期的にコマンドを実行するcronの機能があるので、cronを使ってTwitterボットを作ってみる。

最終的にこういうボットが出来上がりました。千家は横浜のおいしいラーメン屋です。

参考

以前の日記にも利用したこれ。この本で紹介してるボットはWebからのカスタマイズ可能だったりと結構凝ってるのだけど、今回はただ動かすだけということでもっと簡略化したやつを。
「すっきりわかるGoogle App Engine for Javaクラウドプログラミング」

下準備

適当なボットアカウントを作成し、アプリケーション登録申請を行います。次に発行されたコンシューマー・キーとコンシューマー・シークレットを元にアクセス・トークンとアクセス・トークン・シークレットを発行します。以前Pythonで発行した際の手順をここに書いてます。
今回はJavaで発行しました。冒頭紹介した本の付録Hからの引用です。ちなみにTwitterのライブラリはTwitter4Jを利用。

import java.io.BufferedReader;
import java.io.InputStreamReader;

import twitter4j.Twitter;
import twitter4j.TwitterFactory;
import twitter4j.auth.AccessToken;
import twitter4j.auth.RequestToken;

public class TwitterAuth {
	static String consumerKey = "xxxxx";
	static String consumerSecret = "xxxxx";
	public static void main(String args[]){
		try{
			Twitter twitter = new TwitterFactory().getInstance();
			twitter.setOAuthConsumer(consumerKey, consumerSecret);
			RequestToken requestToken = twitter.getOAuthRequestToken();
			AccessToken accessToken = null;
			BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
			while(null==accessToken){
				System.out.println("open following URL");
				System.out.println(requestToken.getAuthenticationURL());
				System.out.println("hit enter:");
				String line = br.readLine();
				try{
					accessToken = twitter.getOAuthAccessToken();
				}catch(Exception e){
					
				}
			}
			System.out.println("token= " + accessToken.getToken());
			System.out.println("tokenSecret= " + accessToken.getTokenSecret());
		}catch(Exception e){
			System.err.print(e);
		}
	}
}

Twitterボットプログラム

ボットに必要なトークン等が無事発行できたら、メインの投稿プログラムをTwitter4Jを利用して書きます。今回はツイートしたい文字配列を用意しておき、ランダムに選択したものを投稿するボットにしました。プログラムは普通のサーブレットです。

import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.conf.ConfigurationBuilder;

public class SenyaBot extends HttpServlet{
	static Logger logger = Logger.getLogger("SenyaBot");
	
	static String consumerKey = "xxxxxx";
	static String consumerSecret = "xxxxxx";
	
	static String accessToken = "xxxxx";
	static String accessTokenSecret = "xxxxx";
	
	private String getTweet(){
		String tweets[] = {
				"家系といったら千屋っしょ",
				"通は固めの濃いめ",
				"やっぱり根岸の千家がいいよね。",
				"信頼の深夜営業",
				"水曜は定休日なんだよな",
				"とりあえず千家行こうぜ",
				"ユー、ライス付けちゃう?",
				"ミニカレーも意外と美味しいぜ",
				"ネギうますぎ",
				"あのネギ盛見るとテンションあがっちゃうよねー",
				"大将まじかっけぇ",
				"ここは食券制です"
		};
		int randint = (int)(Math.random()*tweets.length);
		return tweets[randint];
	}
	
	public void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws IOException {
		//http://twitter4j.org/ja/configuration.html
		ConfigurationBuilder cb = new ConfigurationBuilder();
		cb.setDebugEnabled(true)
			.setOAuthAccessToken(accessToken)
			.setOAuthAccessTokenSecret(accessTokenSecret)
			.setOAuthConsumerKey(consumerKey)
			.setOAuthConsumerSecret(consumerSecret);
		String message = getTweet();
		Twitter twitter = new TwitterFactory(cb.build()).getInstance();
		try {
			//Twitterに書き出し
			twitter.updateStatus(message);
		} catch (TwitterException e) {
			logger.log(Level.SEVERE, "Twitter error", e);
		}
	}
}

GAE設定

cron.xml

war/WEB-INF/cron.xmlという感じに配置します。
設定方法は公式にバッチリ乗ってます。

<?xml version="1.0" encoding="utf-8"?>
<cronentries>
	<cron>
		<url>/cron/senya</url>
		<description>Love Senya</description>
		<schedule>every 30 mins</schedule>
		<timezone>Asia/Tokyo</timezone>

	</cron>
</cronentries>
web.xml

上記Twitterボットプログラムをweb.xmlサーブレットととして登録すればOK。ただこのままだとhttp://<あなたのページ>/cron/senyaを誰かがブラウザで叩くたびに実行されてしまうので、security-constraintタグで管理者権限でしか実行できないようにしておく。

<servlet>
	<servlet-name>senyaBot</servlet-name>
	<servlet-class>hoge.fuga.SenyaBot</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>senyaBot</servlet-name>
	<url-pattern>/cron/senya</url-pattern>
</servlet-mapping>
<security-constraint>
	<web-resource-collection>/cron/*</web-resource-collection>
	<auth-constraint>
			<role-name>admin</role-name>
	</auth-constraint>
</security-constraint>

設定確認

アップロードしたらWebの管理画面で[Main]->[Cron Jobs]を確認し、こんな感じの表示になっていたらOK。ちゃんと動いていれば定期的に投稿されてるはず。

Cron Job	Schedule/Last Run/Last Status (All times are UTC)
/cron/senya
Love Senya	 every 30 mins (Asia/Tokyo) 
2011/04/03 16:15:21 on time Success

おしまい。