<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>blog.alumican.net &#187; ボット</title>
	<atom:link href="http://blog.alumican.net/tag/%e3%83%9c%e3%83%83%e3%83%88/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.alumican.net</link>
	<description>日々の記憶と記録とActionScript とその周辺</description>
	<lastBuildDate>Tue, 20 Jul 2010 16:21:59 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>引用βのTwitterボットを作りました</title>
		<link>http://blog.alumican.net/2009/03/02_012527</link>
		<comments>http://blog.alumican.net/2009/03/02_012527#comments</comments>
		<pubDate>Sun, 01 Mar 2009 16:25:27 +0000</pubDate>
		<dc:creator>alumican</dc:creator>
				<category><![CDATA[DEVELOPMENT]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[ボット]]></category>

		<guid isPermaLink="false">http://blog.alumican.net/?p=255</guid>
		<description><![CDATA[
橋本商会さんのスーパーボット対戦の記事が素敵な感じだったので、僕もボットを作ってみたくなりました。
といっても、マルコフ連鎖とか高度な事はできないので(大学でやってたはずなんだけどなあ・・・)
引用βへの最新投稿を表示 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://twitter.com/inyo_beta"><img class="alignnone size-full wp-image-254" title="inyo_beta" src="http://blog.alumican.net/wp-content/uploads/2009/03/inyo_beta.jpg" alt="inyo_beta" width="478" height="200" /></a></p>
<p>橋本商会さんの<a href="http://shokai.org/blog/archives/4036">スーパーボット対戦</a>の記事が素敵な感じだったので、僕もボットを作ってみたくなりました。</p>
<p>といっても、マルコフ連鎖とか高度な事はできないので(大学でやってたはずなんだけどなあ・・・)<br />
引用βへの最新投稿を表示するTwitterボットを作ってみたのです。<br />
その名も</p>
<p><a href="http://twitter.com/inyo_beta">「引用β」</a></p>
<p>ってまんまやーん。<br />
怒られないかな、ドキドキ。</p>
<p>引用βって大好きなんですけど、つい見逃しちゃうことが多いのです。<br />
そこで、TwitterFox （ FireFox の拡張機能で、Twitter の新着ポストをペコッと知らせてくれる優れもの）で知らせてくれると便利じゃんと思って作りました。<br />
普通の RSS リーダーでも十分なんですが、ちょっと思うところがありまして Twitter ボットにしてみました。</p>
<p>実装は php で、heteml の cron で1時間に1回引用βの RSS をチェックしに行きます。<br />
で、前回チェックしたときよりも最新の記事があれば Twitter に投稿します。<br />
そんな動きなのですが、なぜか数回に1回、php の XML パーサがうまく動かなくて<br />
RSSの一番上のアイテムをスルーしてしまう様子。<br />
そのせいでたまに過去の引用を投稿しちゃうんだけれども、<br />
そこは愛嬌って事で御願いします(o&#8217;c_,`人)・:*:・ </p>
<p>以下ソースコード。<br />
いらないって？まあそういわずに。<br />
上記バグの原因を誰か教えてくれるといいなあ、なんつって。</p>
<p><span id="more-255"></span></p>
<p>Twitter に投稿するクラス(Twitter.php)</p>
<pre><code>&lt;?php
//テストコード
//$twitter = new Twitter("USER_NAME", "PASSWORD");
//$twitter-&gt;post("Hello Twitter !");

/* Twitterに投稿するクラス */
class Twitter {

    //-----------------------------------------
    // CONSTANT
    //-----------------------------------------
    const API = "http://twitter.com/statuses/update.xml?";

    //-----------------------------------------
    // VARIABLES
    //-----------------------------------------
    private $username;
    private $password;

    //-----------------------------------------
    // Constructor
    // @param    $username    Twitterのユーザーネーム
    // @param    $password    Twitterのパスワード
    //-----------------------------------------
    public function Twitter($username, $password) {
        $this-&gt;username = $username;
        $this-&gt;password = $password;
    }

    //-----------------------------------------
    // 投稿する
    // @param    $message    投稿するメッセージ
    //-----------------------------------------
    public function post($message) {
        $params = "status=".rawurlencode($message);
        $result = file_get_contents(Twitter::API.$params, false,
            stream_context_create(array(
                "http" =&gt; array(
                    "method" =&gt; "POST",
                    "header" =&gt; "Authorization: Basic ". base64_encode($this-&gt;username.":".$this-&gt;password)
                )
            ))
        );
    }
}
?&gt;</code></pre>
<p>引用βのRSSを取ってくるクラス(RssReader.php)</p>
<pre><code>&lt;?php
//テストコード
//$reader = new RssReader();
//$reader-&gt;load("http://feeds.feedburner.com/inyo/everyone", 5);

/* 引用βのRSSを取ってくるクラス */
class RssReader {

    //-----------------------------------------
    // CONSTANT
    //-----------------------------------------

    //-----------------------------------------
    // VARIABLES
    //-----------------------------------------
    private $url;
    private $xml;
    private $max_post;
    public $entries;

    //-----------------------------------------
    // Constructor
    //-----------------------------------------
    public function RssReader() {
    }

    //-----------------------------------------
    // load feed
    // @param    $url        RSSの場所
    // @param    $max_post    1回のチェックで拾ってくる最新のポスト数
    //-----------------------------------------
    public function load($url, $max_post=5) {

        $this-&gt;url = $url;
        $this-&gt;max_post = $max_post;

        if ($this-&gt;xml = simplexml_load_file($this-&gt;url)) {
            //取ってきたRSSを解析する
            $this-&gt;parseAsRSS();
        } else {
            return array();
        }
    }

    //-----------------------------------------
    // RSSを解析する
    //-----------------------------------------
    private function parseAsRSS() {

        //前回取ってきたRSSの最新記事が保存されているので読み込む
        if ($fp = fopen("log.dat", "r")) {
            $last = fgets($fp, 32000);
            fclose($fp);
        }

        //エントリをザーッと取ってくる
        $items = $this-&gt;xml-&gt;channel-&gt;item;

        //パーマリンクのURLを2重投稿防止用のチェックに使う
        $recent = (string) $items[0]-&gt;link;

        $c = 0;
        $this-&gt;entries = array();

        foreach ($items as $item) {

            //------------------------------------
            // 今回解析する最大記事数を超えていないかチェック
            //------------------------------------
            if (++$c &gt; $this-&gt;max_post) break;

            //パーマリンクを取得する
            $permalink = (string) $item-&gt;link;

            //------------------------------------
            // 2重投稿ではないかチェック
            //------------------------------------
            if (strcmp($last, $permalink) == 0) break;

            //&lt;p&gt;タグおよびURL部分を除いて、120文字にトリムしたエントリ内容を取得する
            preg_match("/(&lt;/p&gt;&lt;p&gt;)([^\/]+)(&lt; \/p&gt;)/", (string) $item-&gt;description, $tmp);
            $text = mb_strimwidth(chop($tmp[2]), 0, 120, "...", "UTF-8");

            //------------------------------------
            // 配列に入れておく(この中のを後で投稿する)
            //------------------------------------
            array_push($this-&gt;entries,
                array(
                    "text" =&gt; $text,
                    "permalink" =&gt; $permalink
                )
            );
        }

        //今回取得したRSSの中で、最新記事のパーマリンクを次回読み込み時用に保存しておく
        if ($fp = fopen("log.dat", "w")) {
            flock($fp, LOCK_EX);
            fputs($fp, $recent);
            flock($fp, LOCK_UN);
            fclose($fp);
        }
    }
}
?&gt;</code></pre>
<p>上2つのクラスを使って、取得→投稿の一連の動作をしてくれるスクリプト</p>
<pre><code>&lt;?php
//-----------------------------------------
// クラスの読み込み
//-----------------------------------------
require_once("Twitter.php");
require_once("RssReader.php");

//-----------------------------------------
// それぞれのクラスのインスタンスを生成する
//-----------------------------------------
$twitter = new Twitter("inyo_beta", "********");
$reader = new RssReader();

//-----------------------------------------
// まず更新分のRSSを取得する
//-----------------------------------------
$reader-&gt;load("http://feeds.feedburner.com/inyo/everyone", 5);

//-----------------------------------------
// 更新分のRSSをTwitterに投稿する
//-----------------------------------------
if (count($reader-&gt;entries) &gt; 0) {
    //逆順にしないと、最近記事が下になる
    $entries = array_reverse($reader-&gt;entries);
    foreach ($entries as $entry) {
        echo $entry["text"]." ".$entry["permalink"]."&lt;br /&gt;\n";
        $twitter-&gt;post($entry["text"]." ".$entry["permalink"]);
        sleep(2);
    }
}
//ログを吐く
echo count($entries)." entries were posted.";
?&gt;</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.alumican.net/2009/03/02_012527/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
