2016年8月18日木曜日

natsuki_botの関数解説①

皆様に好評(?)を頂いているnatsuki_bot(@natsukitus)。

元々は知り合いのnatsukiの迷言集を呟くだけのbotだったのですが、返信機能がつき、スケジュール機能がつき、終いには天気予報がついた意味不明なbotとなってしまいました。笑

そろそろ開発を終了するつもりなので、このシリーズでは私が独自に追加した関数について、自分なりの解釈を含めつつ解説していきます。


今回は、natsuki_botの主要機能となったメモ機能です。

ソースコードを下に示します。簡単のため、一部を省略してあります。


 //タイムラインへの反応を作る
 function makeReplyTimelineTweets($timeline, $replyPatternFile){
 if(empty($this->_replyPatternData[$replyPatternFile])){ $this->_replyPatternData[$replyPatternFile] = $this->readPatternFile($replyPatternFile); }
        $replyTweets = array();
        foreach($timeline as $tweet){
            $status = "";

   if(preg_match ('/(.*)#(.*(メモ|めも))(.*)/s',$tweet["text"], $matches) === 1){
    $status = $this->MEMORANDUM ($tweet, $matches);
   }

            //リプライパターンと照合
            foreach($this->_replyPatternData[$replyPatternFile] as $pattern => $res){
                if(preg_match("@".$pattern."@u",$tweet["text"], $matches) === 1 && !preg_match("/\@/i",$tweet["text"])){                                        
                    $status = $res[array_rand($res)];
                    for($i=1;$i convertText($status, $tweet);
            //フッターを追加
            $status .= $this->_footer;

            //リプライ相手、リプライ元を付与
            $rep = array();
            
  switch(true){
  //リプライ反応をTLに発言
  case stristr($status, "[[TLH]]"):
  $status = str_replace("[[TLH]]","",$status);
  $rep["status"] = $status;
  $rpid = (string)$reply->id;
  file_put_contents($this->_logDataFile,$rpid);
  break; 
  //その他
  default:
  $rep["status"] = "@".$tweet["user"]["screen_name"]." ".$status;
  } 


            $rep["in_reply_to_status_id"] = $tweet["id_str"];      
            //応急処置
            if(!stristr($status,"[[END]]")){
                $replyTweets[] = $rep;
            }
        }                        
        return $replyTweets;    
    }          




 function MEMORANDUM ($tweet, $matches){
   //var_dump($matches);
   $filename = "memo/{$matches[2]}.txt"; 
   if (!file_exists($filename)){
     touch($filename);
     chmod($filename,0666);
   }
   $date = date ("Y-m-d H:i");
   $filename = "memorandum.txt";
   $matches[0] = str_replace("#.*","",$status);
   $matches[0] = htmlspecialchars_decode($matches[0]);
   $nakami = preg_replace("/#(.*(メモ|めも))/", "", $matches[0]);
   $matches[0] = preg_replace('/\n/', '{kaigyou}', $matches[0]);

   $txt = $date."\t".$matches[0]."\r\n";
   if(file_put_contents ($filename, $txt, FILE_APPEND | LOCK_EX)){
    echo "メモ登録成功。
"; }else{ echo "メモ登録失敗。
"; } $status = NULL; return $status; }


僕が作成したMEMORANDUM関数は引数が$matches、返り値が$statusです。
$matchesはpreg_match関数を用いてツイートを分解し、要素を配列に入れたものです。
$statusは最終的にツイートされる文章です。すなわち、メモ完了ツイートです。


さて、誰かが「テストです #ミズヒトメモ」と呟きます。すると、この関数にはまず次のような配列$matchesが渡されます。

[0] => "テストです #ミズヒトメモ"
[1] => "テストです"
[2] => "ミズヒトメモ"
[3] => ""

これはpreg_match関数の動作の特徴になります。preg_match関数では、()で囲われた正規表現による文字列を検索パターンとし、検索対象の文字列の中でそのパターンに合致したものを順番に配列に入れていきます。ただし、0番目の要素は検索対象の文字列そのものが入っています。

配列が渡されると、最初にメモを記録する用のtxtファイルを参照します。
ここで、txtファイルが存在しない場合は新たにtxtファイルを作成します。touch関数でファイルを作成し、chmod関数で「自分もグループメンバも他人も、読み込みと書き込みができる」パーミッション(666)設定を行います。

次に、txtファイルに書き込むデータを作成します。date関数でツイートの日時を作成し、htmlspecialchars_decode関数を用いて特殊記号をデコードした$matches[0]と組み合わせて$txtに整えて入れます。

そして、最後にfile_put_contents関数で用意したtxtファイルに書き込みをします。FILE_APPENDはファイルの後ろに追記するオプション、LOCK_EXは排他アクセス(他のプログラムに書き込みをさせない)オプションです。

ところで、途中で出てきた$nakamiはpreg_replace関数を用いて$matches[0]からタグを取り去ったものです。最後の$statusで用いられているのが分かると思います。そして、return $status;によってメモ完了ツイートが戻り値として呼び出したところへ戻っていきます。

このようにしてnatsuki_botは皆様のツイートを収集してファイルに保存しています。



いかがでしたか?それほど難しいプログラムではありませんが、やはり正規表現によるマッチングでつまずく可能性が高いでしょう。何かわからないことがあったらコメントくださいね。


0 件のコメント:

コメントを投稿