2020年になって今更ながら、raspberry pi+java+twitter API(twitter4j)で自身にメンションしてきた投稿に自動でメッセージを返すtwitter botを作った(というよりは自分のアカウントをbot化した)ので、そのレシピを書き残します。

 

これから作るもの

 

自身にメンション(@picker_wtb)して投稿されたツイートを取得して、特定の文字列(きょうごはん)を検出したら、ランダムにコメント(料理名)をリプライするbotになります。

料理名をリプライするtwitter botをtwitter4jで作ってみる

両方とも自分のアカウントなので自作自演ツイートです。

ちなみに、公開して1か月たちましたが利用してくれた人は0人です笑。

@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("J9BxQEzgnFusrdaAk15dAVcqA")
                .setOAuthConsumerSecret("s7GLXMuEpyYhgwGFmaPns3XSQJrbsIlkhHDtLtXSA3OG0LIYmM")
                .setOAuthAccessToken("803776376310362112-9Ejq8p6FWO3GbstsrPMvEU0QXTD5z8R")
                .setOAuthAccessTokenSecret("nQcAxoWozfSgTFzHEdoSgUzFBfHtuUFVJnKEnqzIFlend");
        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;
    }
}

 

[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(); }
    }
}