はてなブックマークをTwitterに投稿するPHPスクリプト hatebu2tweet.php(OAuth, Bit.ly対応)
TwitterのBASIC認証が6月末で廃止されるので、はてなブックマークをWebHook経由でTwitterに投稿するPHPスクリプトをOAuth対応に書き直してみました。Bit.lyの短縮URLにも対応していますので、bit.lyのアクセス解析も利用できます。書き直すにあたって以下のサイトを参考にしました。
PHP+OAuthでTwitter - SDN Project
PHPからbit.lyやtr.im等のURL短縮サービスをまとめて扱える「PEAR::Services_ShortURL」:phpspot開発日誌
OAuthにtwitteroauth, Bit.lyの短縮URLにPEAR::Services_ShortURLを利用したのでコーディングしたのははてブWebHookからのPOSTメッセージを受け取って140文字以内に収めてtwitteroauthに渡すまで。BASIC認証版のコードと比べても大きな変更も無く移行できました。
スクリプトの動作
はてなブックマークで新規に追加されるブックマークに対して「タグなしコメント /// タイトル bit.ly短縮URL」の形式でTwitterに投稿します。140文字を超える場合は「タグなしコメント /// タイトル」の部分を後ろから削って、短縮URL込みで140文字に収まるように調整します。並び順や区切り文字はcreateMessage関数で変更できます。
$msg = "$comment_notag /// $title";
$urllength = mb_strlen($shorturl) + 1;
$msglength = 140 - $urllength;
if (mb_strlen($msg) > $msglength) {
$msg = mb_substr($msg, 0, $msglength, "UTF-8");
}
$msg = $msg . " " . $shorturl;
ログ
はてブを付けてWebHookからスクリプトが呼び出されると以下のようなログを出力します。
2010/05/05 00:44:10 bookmark test 3 /// Google http://bit.ly/3BxKtp
はてブをつけてもログに日付が出力されない場合はWebHookからの呼び出しが無かったことを示しています。たまにWebHookから呼び出されないことがあるような気がします。
ブックマークの更新や削除の場合は以下のようなログを出力します。add以外のステータスはすべてログを出力して終了していますが、スクリプトを書き換えればはてなスターなどを処理することも可能です。
2010/05/05 00:40:33 unknown status : update 2010/05/05 00:43:09 unknown status : delete
利用方法
ちょっと手続きが多めですが、大まかな流れはこんな感じです。
- hatebu2tweet.phpの設置
- Twitter OAuthクライアント登録 > OAuthキー取得
- PEAR::Services_ShortURLのインストール > Bit.lyキー取得
- はてブ WebHookの設定 > WebHookキー取得
- keys.phpにキーを設定
以下手続きの詳細。
- hatebu2tweet.phpの設置
- http://dev.twitter.com/apps/>新しいアプリケーションを登録する からOAuthクライアントを設定
- (例)
- アプリケーション名: hatebu2tweet (Twitterクライアント名。任意の名前にできます)
- アプリケーションの説明: hatebu2tweet
- アプリケーションのウェブサイトURL: http://twitter.com/mikage_sbm(Twitterクライアントのリンク先。任意のURLにできます)
- 所属会社/団体: mikage014
- アプリケーションの種類: クライアントアプリケーション
- Default Access type: Read & Write (投稿するのでWriteが必要です)
- OAuthキーの取得
- GitHub - abraham/twitteroauth: The most popular PHP library for use with the Twitter OAuth REST API.>download sourceからtwitteroauthをダウンロードして「twitteroauth」フォルダ内の「OAuth.php」と「twitteroauth.php」を「hatebu2tweet.php」と同じディレクトリに配置
- Services_ShortURLをインストール
- Services_ShortURL, HTTP_Request2, Net_URL2をhatebu2tweet.phpと同じディレクトリに展開
- http://bit.ly/pages/tools/developer-tools/でBit.ly APIキーを取得
- はてなブックマーク>設定>外部サイト連携>WebHook
ソースコード
hatebu2tweet.php
<?php // before using // touch hatebu2tweet.log // chmod 666 hatebu2tweet.log // twitteroauth require_once("twitteroauth.php"); // OAuth Keys, Bit.ly Keys, Hatena WebHook Keys require_once("keys.php"); // Service_ShortURL require('Services/ShortURL.php'); class hatebu2tweet { var $oauth; var $bitly; var $hatena_webhook_key; // ------------------------------------------------------------ // constructor // ------------------------------------------------------------ function __construct ($keys) { // OAuth Object $this->oauth = new TwitterOAuth( $keys['consumer_key'], $keys['consumer_secret'], $keys['access_token'], $keys['access_token_secret'] ); // Bitly Object Services_ShortURL::setServiceOptions('Bitly', array( 'login' => $keys['bitly_login'], 'apiKey' => $keys['bitly_apikey'] )); $this->bitly = Services_ShortURL::factory('Bitly'); // Hatebu WebHook Key $this->hatena_webhook_key = $keys['hatena_webhook_key']; } // ------------------------------------------------------------ // Check WebHook Key from Hatena Bookmark // ------------------------------------------------------------ function checkWebHookKeyAndStatus($key, $status) { if ($key != $this->hatena_webhook_key) { $this->writelogln("unknown key : $key"); return false; } if ($status != "add") { $this->writelogln("unknown status : $status"); return false; } return true; } // ------------------------------------------------------------ // Create POST Message ( msg < 140 and shorten URL ) // ------------------------------------------------------------ function createMessage($comment, $title, $url) { $comment_notag = preg_replace("/^(\[.*?\])*/", "", $comment); $shorturl = $this->bitly->shorten(urlencode($url)); $msg = "$comment_notag /// $title"; $urllength = mb_strlen($shorturl) + 1; $msglength = 140 - $urllength; if (mb_strlen($msg) > $msglength) { $msg = mb_substr($msg, 0, $msglength, "UTF-8"); } $msg = $msg . " " . $shorturl; $this->writelogln($msg); return $msg; } // ------------------------------------------------------------ // send msg to twitter with OAuth // ------------------------------------------------------------ function tweet($msg) { $req = $this->oauth->OAuthRequest("https://twitter.com/statuses/update.xml","POST",array("status"=>$msg)); header("Content-Type: application/xml"); echo $req; } // ------------------------------------------------------------ // LOG // ------------------------------------------------------------ function writelog($log) { $fp = fopen("./hatebu2tweet.log","a"); if (flock($fp, LOCK_EX)) { fputs($fp, $log); flock($fp, LOCK_UN); } fclose($fp); } function writelogln($log) { $this->writelog($log . "\n"); } } // ------------------------------------------------------------ // Main section // ------------------------------------------------------------ // Hatena WebHook Parameters $is_private = $_POST["is_private"]; $count = $_POST["count"]; $status = $_POST["status"]; $key = $_POST["key"]; $username = $_POST["username"]; $permalink = $_POST["permalink"]; $timestamp = $_POST["timestamp"]; $comment = $_POST["comment"]; $url = $_POST["url"]; $title = $_POST["title"]; # only hatena star $color = $_POST["color"]; $quote = $_POST["quote"]; $hatebu2tweet = new hatebu2tweet($keys); $hatebu2tweet->writelog(date("Y/m/d H:i:s ")); if ($hatebu2tweet->checkWebHookKeyAndStatus($key, $status) == false) { exit; } $msg = $hatebu2tweet->createMessage($comment, $title, $url); $hatebu2tweet->tweet($msg); ?>
keys.php
<?php // ------------------------------------------------------------------ // Twitter OAuth Keys // ------------------------------------------------------------------ // Consumer key $keys['consumer_key'] = ""; // Consumer secret $keys['consumer_secret'] = ""; // Access Token $keys['access_token'] = ""; // Access Token Secret $keys['access_token_secret'] = ""; // ------------------------------------------------------------------ // Bit.ly Keys // ------------------------------------------------------------------ // Login Name $keys['bitly_login'] = ""; // API Key $keys['bitly_apikey'] = ""; // ------------------------------------------------------------------ // Hatena WebHook Keys // ------------------------------------------------------------------ $keys['hatena_webhook_key'] = ""; ?>