Twitter Streaming APIを使って関連TLをテレビにオーバーレイ表示するAIRアプリを作ってみた
一昨年の記事、テレビにTwitterの関連TLをオーバーレイ表示するAIRアプリを作ってみた - Tosshi Note で紹介したアプリを Twitter Streaming API に対応してみました。
AIRアプリ自体の公開は反応をみることにして、Twitter Streaming API を ActionScript で実装する例があまり見つからなかったので、とりあえず載せときます。
ちなみに URLStream を使って実装していますが、URLStream の Progress イベントは HTTP chunk レスポンスの受信とは別に起こります。そのため、流れの速いTLでないと TweetReceived イベントにタイムラグが発生するかもしれません。
URLStreamから取得できるデータ本体は、[ツイートJSON][CRLF][ツイートJSON][CRLF][ツイートJSON][CRLF] となります。
ツイートがないときに、Keep-Aliveのためのパケットも[CRLF]となるため、バッファに文字列をためつつ、[CRLF]を探しては切り出して、文字列長0でなければJSONをパースしてツイート受信イベント発生という流れです。
以下、ソースをべた貼りしておきます。
TwitterStreamLoader.as
コンストラクタ引数にBASIC認証のTwitterスクリーン名とパスワードを指定します。
package com.tilfin.tvtwlayer.twitter { import com.adobe.serialization.json.JSON; import flash.events.EventDispatcher; import flash.events.HTTPStatusEvent; import flash.events.IOErrorEvent; import flash.events.ProgressEvent; import flash.net.URLRequest; import flash.net.URLRequestHeader; import flash.net.URLRequestMethod; import flash.net.URLStream; import flash.net.URLVariables; import mx.utils.Base64Encoder; /** * Tweet Received イベント */ [Event(name="tweetReceived", type="com.tilfin.tvtwlayer.twitter.TwitterStreamEvent")] /** * Twitter Stream API Loader */ public class TwitterStreamLoader extends EventDispatcher { private static const ROOT_URL:String = "http://stream.twitter.com/1/statuses/"; private var _authHeader:URLRequestHeader; private var _stream:URLStream; private var _streamBuffer:String = ""; /** * コンストラクタ * * @param screenName スクリーン名 * @param password パスワード */ public function TwitterStreamLoader(screenName:String , password:String) { super(); var encoder:Base64Encoder = new Base64Encoder(); encoder.encode(screenName + ":" + password); _authHeader = new URLRequestHeader("Authorization", "Basic " + encoder.flush()); } /** * 各種フィルタをかけたストリームの受信を開始します。 * * @param params クエリパラメータ */ public function loadFilterStream(params:Object):void { var variables:URLVariables = new URLVariables(); for (var key:String in params) { variables[key] = params[key]; } var request:URLRequest = new URLRequest(ROOT_URL + "filter.json"); request.method = URLRequestMethod.POST; request.requestHeaders = [ _authHeader ]; request.data = variables; _stream = new URLStream(); _stream.addEventListener(IOErrorEvent.IO_ERROR, onIoError); _stream.addEventListener(HTTPStatusEvent.HTTP_RESPONSE_STATUS, onHttpResponseStatus); _stream.addEventListener(ProgressEvent.PROGRESS, onProgress); _stream.load(request); } /** * ストリームを閉じます。 */ public function close():void { _stream.removeEventListener(IOErrorEvent.IO_ERROR, onIoError); _stream.removeEventListener(ProgressEvent.PROGRESS, onProgress); _stream.close(); _stream = null; } private function onProgress(event:ProgressEvent):void { var buffer:String = _stream.readUTFBytes(_stream.bytesAvailable); _streamBuffer += buffer; var twstr:String; var splitpos:int = _streamBuffer.indexOf("\r\n"); while (splitpos > -1) { twstr = _streamBuffer.substr(0, splitpos); if (twstr.length > 0) { receivedTweet(twstr); } _streamBuffer = _streamBuffer.substr(splitpos + 2); splitpos = _streamBuffer.indexOf("\r\n"); } } private function receivedTweet(str:String):void { var tweet:Object = JSON.decode(str); dispatchEvent(new TwitterStreamEvent(TwitterStreamEvent.TWEET_RECEIVED, tweet)); } private function onIoError(event:IOErrorEvent):void { trace("IO Error."); } } }
TwitterStreamEvent.as
package com.tilfin.tvtwlayer.twitter { import flash.events.Event; /** * Twitter Stream イベント */ public class TwitterStreamEvent extends Event { /** * イベントタイプ : ツイート受信 */ public static const TWEET_RECEIVED:String = "tweetReceived"; private var _tweet:Object; /** * @return ツイート */ public function get tweet():Object { return _tweet; } /** * コンストラクタ * * @param type イベントタイプ * @param tweet ツイート */ public function TwitterStreamEvent(type:String, tweet:Object = null) { super(type, false, false); _tweet = tweet; } } }
実行例
Public streams | Twitter Developers の statuses/filter の Parameters をマップかして loadFilterStream メソッドの引数に渡すと、ツイートを受信するたびに JSON を ActionScript Object化したものを受け取れます。
var streamLoader:TwitterStreamLoader = new TwitterStreamLoader(screenname, password); streamLoader.addEventListener(TwitterStreamEvent.TWEET_RECEIVED, function(event:TwitterStreamEvent):void { event.tweet; // ツイートの JSON を ActionScript Object化したもの }); streamLoader.loadFilterStream({ "track": "#f1jp,#f1" });
trackは「,」区切りで検索語を複数指定できる引数です。