twitter botのフォローの同期の仕組み

なんかこういうキーワードで流れてくる人が多い感じがしたので、
一応書いておこうかな、と。




といっても、特別なことは何もしてません。
twitter APIからフォローと、フォロワーの情報をとってきて、
ぐるぐるまわして同期を取るだけです。


▼参考
http://watcher.moe-nifty.com/memo/docs/twitterAPI.txt
twitter API仕様書 日本語訳



以下、実際に使ってる自作twitter botクラスのメソッド

public function followSync(){
	$result = array("follow" => 0, "remove" => 0);
	$friends_data = array();
	$followers_data = array();
	
	// GETコンテクスト
	$context = array();
	$context["http"] = array(
		"method" => "GET",
		"header" => "Authorization: Basic ".base64_encode($this->ac.":".$this->pw)."\r\n"
	);
	$context = stream_context_create($context);
	
	// フォロー一覧取得
	$res_friends = file_get_contents($this->friends_uri, FALSE, $context);
	if($res_friends != FALSE){
		$friends_data = simplexml_load_string($res_friends);
	}

	// フォロワー一覧取得
	$res_followers = file_get_contents($this->followers_uri, FALSE, $context);
	if($res_followers != FALSE){
		$followers_data = simplexml_load_string($res_followers);
	}
	
	// どっちか取れてなければやめちゃいます
	if($res_friends == FALSE || $res_followers == FALSE){
		return $result;
	}
	
	unset($res_friends, $res_followers);
	
	//--- 差分を取る
	// フォロー
	$create_friend = array();
	foreach($followers_data->user AS $follower){
		$exist_flag = FALSE;
		foreach($friends_data->user AS $friend){
			if((int)$follower->id == (int)$friend->id){
				$exist_flag = TRUE;
				break;
			}
		}
		if($exist_flag == FALSE){
			$create_friend[] = $follower->id;
		}
	}
	unset($follower, $friends, $exist_flag);
	
	// リムーブ
	$remove_friend = array();
	foreach($friends_data->user AS $friend){
		$exist_flag = FALSE;
		foreach($followers_data->user AS $follower){
			if((int)$follower->id == (int)$friend->id){
				$exist_flag = TRUE;
				break;
			}
		}
		if($exist_flag == FALSE){
			$remove_friend[] = $friend->id;
		}
	}
	unset($context, $friends_data, $followers_data, $follower, $friends, $exist_flag);

	//--- 実行
	// POSTコンテクスト
	$context = array();
	$context["http"] = array(
		"method" => "POST",
		"header" => "Authorization: Basic ".base64_encode($this->ac.":".$this->pw)."\r\n"
	);
	$context = stream_context_create($context);
	
	// フォロー
	if($create_friend != array()){
		foreach($create_friend AS $id){
			$res = file_get_contents($this->follow_uri.$id.".xml", FALSE, $context);
			if($res != FALSE){
				$result["follow"]++;
			}
		}
	}
	unset($id);
	
	// リムーブ
	if($remove_friend != array()){
		foreach($remove_friend AS $id){
			$res = file_get_contents($this->remove_uri.$id.".xml", FALSE, $context);
			if($res != FALSE){
				$result["remove"]++;
			}
		}
	}
	unset($id);
	
	return $result;
}

twitter API用のuriBASIC認証用のidやらpassやらを、クラスのメンバ変数にしているので、
($this->remove_uriとかね)
適当にそこを置き換えれば、単純に関数として使えるかもね。


うーん。
晒してみたはいいものの、
恥ずかしいことをしてそうな気はする。

実際エラーケースの対処が相当甘くて、
一部情報がtwitter本体からとれなかったとき、
botが全フォローをリムーブしちゃうという恐ろしい障害を、
ちょこちょこ出してました(汗
(今は改善されている、ハズです><)


あと、今はフォロワー少ないからいいけど、
もしこれが数百人になったとき(まあならないけど)、
結構リソース喰うんじゃないかっていう懸念も。


エロい人いたら添削おねがいします><