2020年になって今更ながら、raspberry pi+java+twitter API(twitter4j)で自身にメンションしてきた投稿に自動でメッセージを返すtwitter botを作った(というよりは自分のアカウントをbot化した)ので、そのレシピを書き残します。
これから作るもの
自身にメンション(@picker_wtb)して投稿されたツイートを取得して、特定の文字列(きょうごはん)を検出したら、ランダムにコメント(料理名)をリプライするbotになります。
両方とも自分のアカウントなので自作自演ツイートです。
ちなみに、公開して1か月たちましたが利用してくれた人は0人です笑。
ピラフ!!!
— picker. (@picker_wtb) August 29, 2020
@picker_wtbときょうごはんというワードを入れてつぶやけばいいのでよかったらやってみてください。
材料
raspberry pi ←常にネットにつながって電源が入ってるpcなら可です。raspberry piがないと人はawsの無料枠でもいいかもしれません。
twitter developer に登録されたtwitterアカウント ←開発者申請しないとtwitter APIは使えないです(申請には2週間くらいかかる)。
twitter4j ←twitter APIをjavaで使用するために利用
作り方
先に流れを説明していきます。
①OAuth認証してTwitter APIと接続(twitterインスタンスできる)
②getMentionsTimelineで自身がメンションされているツイートを数件取得
③previousIdに取得したツイートの中で最新のもののIDを格納
④getMentionsTimelineで自信がメンションされているツイートを数件取得
⑤最新のツイートからpreviousIdとIDが一致するかチェック。一致していなければ⑥を実行。一致していれば以後は無視する。
⑥previousIdとIDが一致しなかった投稿に対して、ランダムに選ばれたメッセージをリプライ。
③から⑥を10秒おきにひたすら繰り返す。
Twitter APIは15分間に叩いていい関数が決められているので(2020年時点で180回)一回APIを叩くごとに20秒間インターバルを開けるようにしています。
リプライの際も制限回数を消費してしまうのでもし15分間に何回もリプライすることになるのならこの感覚をさらに空ける必要があるかもしれません。
ただ、間隔を空ければ空けるほど返信するまでに時間がかかってしまうのでそこは調整する必要がありますね。
ソースコード
TwitterClient.javaで各種必要なメソッドを定義して、それをApp.javaで読み出して実行します。gitからダウンロード可です
[TwitterClient.java]
package TwitterBot; import twitter4j.*; import twitter4j.conf.ConfigurationBuilder; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Random; public class TwitterClient { public TwitterClient() { } //①OAuth認証してTwitter APIと接続(twitterインスタンスができる) public Twitter connect() { ConfigurationBuilder cb = new ConfigurationBuilder(); cb.setDebugEnabled(true) .setOAuthConsumerKey("Twitter developerサイトからConsumerKeyを取得") .setOAuthConsumerSecret("Twitter developerサイトからConsumerSecretを取得") .setOAuthAccessToken("Twitter developerサイトからAccessTokenを取得") .setOAuthAccessTokenSecret("Twitter developerサイトからAccessTokenSecretを取得"); TwitterFactory tf = new TwitterFactory(cb.build()); Twitter twitter = tf.getInstance(); return twitter; } //②getMentionsTimelineで自信がメンションされているツイートを数件取得 public List<Status> getMentionPost(Paging page, Twitter twitter){ //取得した投稿を格納するリスト List<Status> statuses = null; try { //自分にメンションされているタイムラインを表示するはず statuses = twitter.getMentionsTimeline(page);//pageは取得数を表す //取得した投稿を一件ずつ表示 for(Status status:statuses){ System.out.println(status.getUser().getName()+"(@"+status.getUser().getScreenName()+")\n"+ status.getText()+"\n"); } } catch (TwitterException e) { e.printStackTrace(); } return statuses; } //⑥previousIdとIDが一致しなかった投稿に対して、ランダムに選ばれたメッセージをリプライ。 public String relpy(long replyId, String text, Twitter twitter){ StatusUpdate stat= new StatusUpdate(text); stat.inReplyToStatusId(replyId); try { //返信を投稿 twitter.updateStatus(stat); return "Replied"; }catch (Exception e){ e.printStackTrace(); } return "Not replied"; } //ランダムに料理名を返す public String getMessage(){ ArrayList<String> messages = new ArrayList<>(Arrays.asList("カレー", "麻婆豆腐", "肉じゃが", "サバの味噌煮", "スンドゥブ")); int listLength = messages.size(); Random random = new Random(); String message = messages.get(random.nextInt(listLength) + 1); return message; } }
Oauth認証系のトークンの取得方法は調べてください。
具体的手順は書かれていませんが、概要は下のサイトでわかります。
[App.java]
/* * 実行プログラム */ package TwitterBot; import twitter4j.*; import java.util.List; public class App { public static void main(String[] args) { //これまで作ったメソッドを読み出すためのインスタンス TwitterClient twitterClient = new TwitterClient(); //一度に取得するメンションされた投稿数 int tweet_num = 10; Paging page = new Paging(); page.setCount(tweet_num); //過去に取得したツイートの中で最新のツイートのID long previousId = 0; try{ for(; true ;) { //①OAuth認証してTwitter APIと接続(twitterインスタンスできる) Twitter twitter = twitterClient.connect(); //②getMentionsTimelineで自身がメンションされているツイートを数件取得 List<Status> statuses= twitterClient.getMentionPost(page, twitter); //③previousIdに取得したツイートの中で最新のもののIDを格納 previousId = statuses.get(0).getId(); for(int l = 0; l < 10 ; l++){ //20秒間停止 Thread.sleep(20000); //④getMentionsTimelineで自身がメンションされているツイートを数件取得 statuses = twitterClient.getMentionPost(page, twitter); //⑤最新のツイートからpreviousIdとIDが一致するかチェック。一致していなければ⑥を実行。一致していれば以後は無視する。 for (int i = 0; i < tweet_num; i++) { if (statuses.get(i).getId() == previousId) { break; } else { long replyId = statuses.get(i).getId(); String text = "@" + statuses.get(i).getUser().getScreenName() + "\n"; String contents = statuses.get(i).getText(); //ツイート野の中に文字列(きょうごはん)が存在するかチェック if (contents.contains("きょうごはん")) { String message = twitterClient.getMessage(); String replyMessage = text + message + "!!!"; //リプライ System.out.println(twitterClient.relpy(replyId, replyMessage, twitter)); } } } } } }catch (Exception e) { e.printStackTrace(); } } }
かなり適当な感じになってしまってますが、参考にしていただければ幸いです。
それでは。