phpでtwitterのbotを作る(TLに反応修正版)

昨日の記事の続きです。
TLの特定語句に反応するが、@付きのpostとRTには反応しない、という修正点。あと、eregからpreg_matchw使うように。
とりあえずソース

<?php
$username = "";
$password = "";
//最新のTLのステータスIDを保存しておくファイルです。パーミッションは書き込み可に。
$filename = "./tmp/last.dat";


//過去の開いて取得
$fp = @fopen($filename,'rb') or die("ファイルが開けません");
flock($fp, LOCK_EX);
$line = fgets($fp, 64);
fclose($fp); 

//自分がフォローしているfriendsのリストです。
$host = "http://twitter.com/statuses/friends_timeline.xml";      //ユーザーの発言一覧

//一番最初の時やファイルが壊れた時、最新1件のみ発言を取得する
if(!empty($line)){
$last_id=$line;
$host .="?since_id=".$last_id;
}
else{
    $host .="?count=1";
    }


$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $host);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
$result = curl_exec($ch);
curl_close($ch);
$XML = simplexml_load_string($result);


$i = count($XML)-1;
$j = 0;
 while($i >= $j) {
$var =  $XML->status[$i]->text;    
$reply_name = $XML->status[$i]->user->screen_name;
$name = $XML->status[$i]->user->name;

if($reply_name != $username){
if( !preg_match ( "/@[a-zA-Z0-9-_]{3,}/", $var ) ){
if( preg_match ( "/おやす|寝る/u", $var )){    
    $message = "@".$reply_name." おやすみ!";
    tweet($message ,$username,$password);
}
if(preg_match ( "/おはよ|むくり/u", $var )){    
    $message = "@".$reply_name." おはよう!";
    tweet($message ,$username,$password);
}
if(preg_match ( "/ただいま/u", $var )){    
    $message = "@".$reply_name." おかえり";
    tweet($message ,$username,$password);
}
}
}
$i--;
}

//ファイルに最新id書き込み
$last_id = $XML->status[0]->id;
$dat = (string)$last_id;
file_put_contents($filename,$dat,LOCK_EX);


//ポスト部分の関数
function tweet($message ,$username,$password)
{
$message =urlencode($message);
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'http://twitter.com/statuses/update.xml');
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 2);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, "status=$message ");
curl_setopt($ch, CURLOPT_USERPWD, "$username:$password");
$buffer = curl_exec($ch);
curl_close($ch);
}

?>

解説です。

if( !preg_match ( "/@[a-zA-Z0-9-_]{3,}/", $var ) ){

ここで、@[スクリーンネーム]の入った発言か否か、判断しています。
正規表現でまず先頭に@があって、そのあと中カッコ[]で囲ったa-zA-Z0-9と続きます。
中カッコは範囲なんですね。後、ハイフンとアンダーバーも使われる(ん?ハイフン使えたっけ?
つまり半角英数プラス-_。
その後に来てるのが大カッコ{}、数字の3、カンマ(,)と来てる。これは前の半角英数とかが3回続くって意味ですね。
ユーザーネームでとれる最小の字数が3っぽいので。
これで、文中に@[スクリーンネーム]のがあるか否か判定できますね。
ちなみにRTも考えていたのですが、RTにはたいがいこの@[スクリーンネーム]がついてきますから、RTのはわざわざ記述しなくても大丈夫でしょう。

次に、preg_matchです。

if( preg_match ( "/おやす|寝る/u", $var )){ 

ここで前のeregと違うのはエスケープ/の存在と、末尾のアルファベットu、区切りの|。
エスケープは前も書いたので、今回はその後にあるu。
こちらの記述が詳しいです。

http://ifs.seesaa.net/article/26300967.html
preg系の正規表現にパターン修飾子「u」を指定すると、パターン文字列がUTF-8エンコードされた文字列として扱われるようになります

twitter文字コードutf-8、このスクリプトも当然utf-8で書かれているのですが、あってるはずなのにマッチしない状態が長く続いて。
なんでかな?って疑問がずっとあったんです。(それで苦手だったってのもあるかも)
このやり方で氷解しました。
最後の区切り|ですが、勘のいい方ならわかると思いますがorみたいなものですね。
おやす、寝る、どちらが来てもマッチするということです。ちなみにカッコはつけてもつけなくても動作一緒でした。
違いがいまいちわからないんですが、併用する時とかだけですかね。スミマセン。詳しい方指摘してくださると嬉しい…(人任せ)
今までの言葉に反応する系のスクリプトも、書き換えたり自分なりに書いてみるのも一興だと思います、是非そうしてください。
正規表現は本当に奥が深いです。使いこなせばbotは精巧になるでしょうし、それ以外にも効率がよくなるでしょうね。
私も勉強していきます!