こいつです。今回は自動フォロー返し(follow back)機能を実装します。

まず、用語を整理しておきましょう。一番難しいのはここです。

followerとは、あるユーザーのことをフォローしている人のことです。逆に、friendとは、あるユーザフォローしている人のことです。

twitter4jには、あるユーザー同士の関係を調べる showFriendship() という便利なメソッドがあるのでそれを活用します。例によってJSON形式でデータが帰ってくるので、適当に処理してやります。ここでは、towelie_botアカウントのIDと、”towelie_botのfollowers” のIDを比較して、相互フォローになっていない場合にフォロー返しをするようになっています。132737336がtowelie_botのuserIDです。

import twitter4j.Twitter;
import twitter4j.TwitterException;

public class TowelFollow {
	static int[] followersIDs = null;

	public static void followBack(Twitter towel) {
		try {
			followersIDs = towel.getFollowersIDs().getIDs();

			for (int followers : followersIDs) {
				if (towel.showFriendship(132737336, followers)
						.isTargetFollowingSource()
						&& !towel.showFriendship(132737336, followers)
								.isSourceFollowingTarget()
						&& towel.showFriendship(132737336, followers)
								.isSourceNotificationsEnabled()) {
					towel.createFriendship(followers);
				}
			}
		} catch (TwitterException e) {
			e.printStackTrace();
		}
	}
}

非公開ユーザに対する動作がよくわからなかったので、そこは手付かずのままです。

フォローバックの機能はツイート機能のように頻繁に動かす必要もないので、別ファイルとして動作させます。

とりあえず必要最低限botとして十分な機能は実装できたので満足です。もしよければフォローしてね。
英語の勉強にも…ならないかw

, , , ,

こいつです。今回は簡単な自動返信機能を実装します。

TwitterではポストごとにIDが付いているので、取得したポストのIDと前回返信したポストのIDを見比べて返信すべきかどうかを判断すれば良さそうです。ただし、仕様によりタスクスケジューラで定期的に実行しているだけなので、一度返信したポストのIDは外部のファイルに保存しておかなくてはいけません。

自動返信機能はTowelReplyクラスで実装します。以下がソースコードです。

Towelie_bot クラス(メインクラス)

import java.io.IOException;

import twitter4j.Twitter;
import twitter4j.TwitterFactory;
import twitter4j.http.AccessToken;

public class Towelie_bot {
  // Consumer と AccessToken をここで指定
  public static final String ConsumerKey = "";
  public static final String ConsumerSecret = ;
  public static final String Token = ;
  public static final String TokenSecret = ;
  
  @SuppressWarnings("deprecation")
    public static void main(String[] args) throws IOException {
     // connect Twitter using oauth
     System.setProperty("twitter4j.http.useSSL", "false");
     Twitter towel = new TwitterFactory().getInstance();
     towel.setOAuthConsumer(ConsumerKey, ConsumerSecret);
     AccessToken accessToken = new AccessToken(Token, TokenSecret);
     towel.setOAuthAccessToken(accessToken);

     TowelPostDialog.post(towel);
     TowelReply.reply(towel);
   }
}

TowelReply クラス (新しいクラス)

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

import twitter4j.ResponseList;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;

public class TowelReply {
	public static final String FileName = "reply_log.txt";
	private static long lastPostId;

	public static void reply(Twitter towel) {
		// get last post id from the file
		FileReader in;
		try {
			in = new FileReader(FileName);
			BufferedReader br = new BufferedReader(in);
			try {
				lastPostId = Long.parseLong(br.readLine());
			} catch (IOException e) {
				e.printStackTrace();
			}
			br.close();
			in.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		// get mention list from twitter
		ResponseList<status> mentions = null;
		try {
			mentions = towel.getMentions();
		} catch (TwitterException e) {
			e.printStackTrace();
		}

		// reply
		for (Status mention : mentions) {
			if (lastPostId < mention.getId()) {
				String reply = "@" + mention.getUser().getScreenName() + " "
						+ TowelReply.decideWhatToSay(mention.getText());
				try {
					towel.updateStatus(reply);
				} catch (TwitterException e) {
					e.printStackTrace();
				}
			}
		}

		// write last post id to the file
		File file = new File(FileName);
		try {
			FileWriter fr = new FileWriter(file);
			fr.write(Long.toString(mentions.get(0).getId()));
			fr.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static String decideWhatToSay(String mention) {
		String[] replies = new String[3];
		replies[0] = "Don't forget to bring a towel.";
		replies[1] = "Hi.";
		replies[2] = "What are you saying... i'm really high now...";

		if (mention.matches(".*water.*|.*水.*")) {
			return replies[0];
		} else if (mention.matches(".*[Hh]i.*")) {
			return replies[1];
		} else {
			return replies[2];
		}
	}
}

いつにもましてtry-catchがすごいことになってるw
decideWhatToSayメソッドでどんな内容をreplyするかを決定します。レパートリーを増やしたかったらここをいじればOK.

List(ResponseList)に入っているデータの型に気をつけていれば、特に問題ないでしょう。

, , ,