読者です 読者をやめる 読者になる 読者になる

Road To Nowhere

主にWebまわりのエンジニア的なお仕事に関するようなことのあれこれ。

twitterのbotを作ってみた

みんながすなるbotといふものをぼくもしてみようと思って作ってみた。
http://twitter.com/4travetter


機能は、@4travetterをつけてどこか行きたいエリアや国名をtwitterにpostすると、
4travelからマッチした旅行記を返すというもの。


今さらだけど、もしかしたら誰かの何かの役に立つかもしれないのでプログラムを公開しておく。
こいつをcron等で5分おきとかに定期的に動かせばOK。
エラー判定とかしていないけど、とりあえず思った通り動くのは確認済み。


twitterアカウントは変えてあります。
mysqlアカウントは環境に合わせてください。

<?php
//twitterアカウント
$username = "user";
$password = "pass";

//mysqlアカウント
$mysql_user = "user";
$mysql_pass = "pass";

require_once("DB.php");
$dsn = 'mysqli://'. $mysql_user .':'. $mysql_pass .'@localhost/4travetter';
$db = DB::connect($dsn);

$sql = "SELECT post_id FROM post ORDER BY post_id DESC LIMIT 1";
$res =& $db->query($sql);
$row =& $res->fetchRow(DB_FETCHMODE_ASSOC);

$since = "";
if($row){
    $since = "?since_id=".$row['post_id'];
}

//mentions取得
$contents = file_get_contents( "http://". $username .":". $password ."@twitter.com/statuses/mentions.xml".$since );
$xml = simplexml_load_string( $contents );


$sql = "INSERT INTO post 
(post_id, post_text, user_id, user_name, user_screen_name, user_location, user_description, user_profile_image_url, post_datetime) 
VALUES 
(?, ?, ?, ?, ?, ?, ?, ?, now())";
$stmt = $db->prepare($sql);

//取得したmentionの数だけloop
$count = count($xml->status);
for($i=0;$i<$count;$i++){
    
    $data = array(
    strval($xml->status[$i]->id[0]), 
    $xml->status[$i]->text,
    $xml->status[$i]->user->id,
    $xml->status[$i]->user->name,
    $xml->status[$i]->user->screen_name,
    $xml->status[$i]->user->location,
    $xml->status[$i]->user->description,
    $xml->status[$i]->user->profile_image_url,
    );
    
    $ret = $db->execute($stmt, $data);
    if (PEAR::isError($ret)) {
        echo "error ".$ret->getMessage();
    }
    
    //旅行記取得
    $keyword = trim(str_replace("@4travetter","",$xml->status[$i]->text));
    $res = getTravelogue($keyword);
    
    $message = "@".$xml->status[$i]->user->screen_name ." ";
    if($res){
    	$message .= $res['title']." ".$res['url'];
    }
    else{
    	$message .= "". $keyword ."」の旅行記が見つかりませんでした。";
    }
    
    //リプライをpost
    postTwitter($message, $username, $password);
    
}

function getTravelogue( $keyword ){
    $contents = file_get_contents( "http://api.4travel.jp/Ver1/SearchAlbum.php?ic=utf8&max=1&keyword=".urlencode($keyword) );
    $xml = simplexml_load_string( $contents );
    
    if($xml->numofresult=="0"){
    	return null;
    }
    
    $ret = array(
    	"title" => $xml->travelogue->item[0]->albumtitle,
    	"url" => $xml->travelogue->item[0]->albumurl,
    );
    return $ret;
}

function postTwitter( $message, $username, $password ){
	$url = "http://twitter.com/statuses/update.xml?";
	$params = "status=". rawurlencode($message);
	
	$result = file_get_contents($url.$params , false, stream_context_create(array(
		"http" => array(
		"method" => "POST",
		"header" => "Authorization: Basic ". base64_encode($username. ":". $password)
		)
	)));
}

?>


リプライを保存しておくテーブルの構造もコピペ。
本当はpost_idだけあればいいんだけど、ついでなのでそれ以外の情報も取得してみる。

CREATE TABLE post (
  post_id varchar(10) NOT NULL,
  post_text text NOT NULL,
  user_id int(10) NOT NULL,
  user_name varchar(100) NOT NULL default '',
  user_screen_name varchar(100) NOT NULL default '',
  user_location varchar(50) default NULL,
  user_description varchar(200) default NULL,
  user_profile_image_url varchar(200) default NULL,
  post_datetime datetime NOT NULL,
  PRIMARY KEY  (post_id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;