Hatena::ブログ(Diary)

math, programming, and little something to laugh Twitter

2009-10-01

Twitterのbotを作ってみた

number_bot(http://twitter.com/number_bot)は投稿数が何かの数に達すると通知するbotです。基本的には素数ですが、たまに変なものも通知します。

稼動:2009.09.27〜

素数以外に実装されている数列と、最初にそのreplyを受けた人を発見者として記録しておきます。

「〜数とか全然わかんねぇよ!」という方は解説記事へどうぞ。→ number_bot解説 - math, programming, and little something to laugh

数列名発見者実装出現日
2^ndhileilu2009.09.272009.09.28
5^ncachetteholic2009.09.272009.09.30
7^nazmny2009.09.272009.09.27
11^nossty2009.09.272009.09.29
13^nossty2009.09.272009.10.04
17^nxlis2009.09.272009.10.02
19^nEagh2009.09.272009.09.29
完全数yniimi2009.09.272009.09.30
レピュニットayakashi_oyadi2009.09.272009.10.02
メルセンヌ数bardothodol2009.09.272009.10.01
フィボナッチ数cachetteholic2009.09.272009.09.28
トリボナッチ数aomoriringo2009.09.272009.09.28
テトラナッチ数yananan_2009.09.272009.09.28
回文平方数Grabacr072009.09.272009.09.29
カタラン数Grabacr072009.09.272009.09.28
完全トーティエント数akaari2009.09.272009.09.28
リュカtasogarenastan2009.09.272009.09.27
カーマイケル数p_lost2009.09.272009.09.28
カプレカ数violante3062009.09.272009.09.28
タンジェントAzr_pp2009.09.272009.10.07
回文素数akaari2009.09.272009.09.28
??? 2009.10.02
アキレス数(10)Eagh2009.10.022009.10.02
エマープ(100)falsie2009.10.022009.10.02
スミス数(100)akazora2009.10.022009.10.02
ハーシャッド数(1000)magtam2009.10.032009.10.04
ナルシストexecr2009.10.032009.10.04
ズッカーマン数(10)yananan_2009.10.032009.10.04
???(10000) 2009.10.03
???(10) 2009.10.20
???(10000) 2009.10.20
超過剰数varenatires2009.10.202009.10.20

ver 1.03 / 2009.10.20

数列を3つ追加しました(???・???・超過剰数)。

ver 1.02 / 2009.10.03

数列を4つ追加しました(ハーシャッド数・ナルシスト数・ズッカーマン数・???)。

ver 1.01 / 2009.10.02

数列を4つ追加しました(???・アキレス数・エマープ・スミス数)。


--------------------------------------------------------------


以下ソースコード

今回はPHPで書きました。

大きく分けて、IDnumberを読み取ってTwitterに投稿する部分と、followerとfriendsを同期させる部分の2つにわかれています。

正直前半は誰得ですが、follower - friends同期は流用が効く、かもね

<?php
/* 
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
        //数列
        //完全数
        $perfect = array(6, 28, 496, 8128, 33550336);
        //フィボナッチ数
        $fibonacci = array(1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040);

        //以降適当に数列などを追加


        require_once 'Services/Twitter.php';
        require_once 'HTTP/Client.php';
        $username = 'ゆーざーねーむ';
        $password = 'ぱすわーど';


        $url = "http://twitter.com/statuses/update.xml?";

        $basic = array('Authorization'=>'Basic '.base64_encode($username.':'.$password));
        $client = new HTTP_Client(null, $basic);

        $filename = "c:/xampp/htdocs/newid.txt";
        $fp = @fopen($filename , "r");
        $loadid = fgets($fp);
        fclose($fp);

        $apiurl = "http://twitter.com/statuses/friends_timeline.xml?since_id=".$loadid."";


        //$apiurl = "http://twitter.com/statuses/friends_timeline.xml";
        $client->get($apiurl);
        $response = $client->currentResponse();
        $body = mb_convert_encoding($response['body'], "UTF-8","JIS,UTF-8,SJIS,EUC-JP");

        $sxe = new SimpleXMLElement($body);

        //print_r($sxe);

        // 一番新しい発言者のidを取得
        // if分は、新規更新がなかったときにnullを書き込まれると、次回の読み込みでまずいことになるので。
        $newid = $sxe->status[0]->id;
        if($newid > 10000){
            $fp = fopen($filename,"w");
            fwrite($fp, $newid);
            fclose($fp);
        }


        //新規発言userの名前を配列arr_screen_nameに入れる。
        //取得した中で一番古い発言が0番目に入る。
        $arr_screen_name = array();
        for($i = 0 ; $i < count($sxe->status) ; $i++){
            $tmp = $sxe->status[$i]->user->screen_name;
            array_unshift($arr_screen_name, $tmp);
        }

        //新規発言userのpost数を配列arr_statuses_countに入れる。
        //取得した中で一番古い発言が0番目に入る。
        $arr_statuses_count = array();
        for($i = 0 ; $i < count($sxe->status) ; $i++){
            $tmp = $sxe->status[$i]->user->statuses_count;
            array_unshift($arr_statuses_count, $tmp);
        }



        $arrmes = array();

        for($i = 0 ; $i < count($sxe->status) ; $i++){
            $num = $arr_statuses_count[$i];

            $th = 0;
            $word = null;
            $type = 0;

          if($num >= 100){
            if(in_array($num, $perfect)){
                $th = sequenceSearch($num,$perfect);
                $word = "完全数";
                $type = 1;
            }
            else if(in_array($num, $fibonacci)){
                $th = sequenceSearch($num,$fibonacci);
                $word = "フィボナッチ数";
                $type = 1;
            }


            if($word!=null && $type==1 && $arr_screen_name[$i]!="number_bot"){
                array_push($arrmes, "@".$arr_screen_name[$i]." さんの投稿数が".$th."番目の".$word.$num."に達しました" );
            }


          }

        }

        print_r($arrmes);

        // $arrmesの中身を順に投稿
        for($i = 0 ; $i < count($arrmes) ; $i++){
        $params = "status=". rawurlencode($arrmes[$i]);
        $result = file_get_contents($url.$params , false, stream_context_create(array(
                "http" => array(
                        "method" => "POST",
                        "header" => "Authorization: Basic ". base64_encode($username. ":". $password)
                )
        )));
        }

/******************************************************************/

        // friendsとfollowerを同期させる
        // followerにあってfriendにない人をフォロー
        // friendにあってfollowerにない人をremove
        //$basic = array('Authorization'=>'Basic '.base64_encode($username.':'.$password));


        // friendsのidを取得
        $client = new HTTP_Client(null, $basic);
        $apiurl = "http://twitter.com/friends/ids.xml";
        $client->get($apiurl);
        $response = $client->currentResponse();
        $body = mb_convert_encoding($response['body'], "UTF-8","JIS,UTF-8,SJIS,EUC-JP");

        $sxe2 = new SimpleXMLElement($body);

        //friendsのid全てを arr_friendsにいれる
        $arr_friends = array();
        for($i = 0 ; $i < count($sxe2->id) ; $i++){
            $tmp = $sxe2->id[$i];
            array_push($arr_friends, (int)$tmp);
        }

        //followersのidを取得
        $client = new HTTP_Client(null, $basic);
        $apiurl = "http://twitter.com/followers/ids.xml";

        $client->get($apiurl);
        $response = $client->currentResponse();
        $body = mb_convert_encoding($response['body'], "UTF-8","JIS,UTF-8,SJIS,EUC-JP");

        $sxe3 = new SimpleXMLElement($body);

        //followersのid全てを arr_followersにいれる
        $arr_followers = array();
        for($i = 0 ; $i < count($sxe3->id) ; $i++){
            $tmp = $sxe3->id[$i];
            array_push($arr_followers, (int)$tmp);
        }


        // followersがfriendsになかった場合、followをする
        for($i=0 ; $i < count($arr_followers) ; $i++){
            $id_num = $arr_followers[$i];
            if(  in_array( (int)$id_num, $arr_friends, false )==FALSE  ){
                echo "follower". $arr_followers[$i] ." not found in friends\n";
                $client = new HTTP_Client(null, $basic);
                $follow_url = "http://twitter.com/friendships/create/".$arr_followers[$i].".xml";
                $client->post($follow_url, $post_param);
            }
        }
         

        // friendsがfollowersになかった場合、removeをする
        $post_param = array();
        for($i=0 ; $i < count($arr_friends) ; $i++){
            $id_num = $arr_friends[$i];
            if(  in_array( (int)$id_num, $arr_followers, false )==FALSE  ){
                echo "friend". $arr_friends[$i] ." not found in followers\n";
                
                $client = new HTTP_Client(null, $basic);
                $follow_url = "http://twitter.com/friendships/destroy/".$arr_friends[$i].".xml";
                $client->post($follow_url, $post_param);
                 
                 
            }
        }



function sequenceSearch($num, $array){
    for($j=0 ; $j<count($array) ; $j++){
        if($num==$array[$j]) break;
    }
    return $j+1;
}


?>