M.C.P.C.

―むり・くり―プラスコミュニケーション(更新終了)


| トップページ |

2011年9月24日 18:27

Google ChromeウェブブラウザにMojolicious::LiteサーバからWebSocketで接続しリアルタイムでTwitterのストリームを表示する

このエントリーをはてなブックマークに追加 mixiチェック

Twitter Streaming APIからの出力をリアルタイムにWebブラウザに表示する実装を作るにあたり、Mojolicious::LiteサーバとGoogle ChromeブラウザをWebSocketで接続すればいいと考え、実際にできるかどうか試してみました。

動画でイメージを見たほうが早いので、下記をどうぞ。

Mojoliciousの発音がこれでいいかは知らない。

Filename: test4-anony.pl

#!/usr/bin/perl
 
use AnyEvent::Twitter::Stream;
use Config::Pit;
use DateTime;
use Encode;
use EV;
use File::Spec;
use FindBin::Real;
use HTML::Entities;
use Mojolicious::Lite;
use Mojo::JSON;
use URI::Escape;
use utf8;
use YAML;
 
# consumer_keyが書かれたYAMLファイルを用意しておく
my $keys = YAML::LoadFile(
  File::Spec->catdir( FindBin::Real::Bin(), '..', 'consumer_keys.yaml' )
);
# Config::Pit あらかじめ自分のディレクトリにtokenが書かれたYAML用意しておく
my $pit = pit_get( 'twitter.com@CLCLCL' );
 
my $clients = {};
my $done = AnyEvent->condvar;
 
my $listener = AnyEvent::Twitter::Stream->new(
  consumer_key    => $keys->{consumer_key},
  consumer_secret => $keys->{consumer_key_secret},
  token           => $pit->{access_token},
  token_secret    => $pit->{access_token_secret},
  method => 'sample',
  #method => 'filter',
  #track  => 'dtpstudy',
  on_tweet => sub {
    my $tweet = shift;
    my $user = $tweet->{user}{screen_name};
    my $text = decode_entities($tweet->{text} || '');
    my $lang = $tweet->{user}{lang} || '';
    return if $lang ne 'ja'; # 日本語メッセージのみ選ぶ
    return unless $user && $text;
    $user =~ s/./*/g;
    $text =~ s/\@[^\s:]+/@****/g;
    $text =~ s/[^\s]+さん/****ちゃん/g;
    $text =~ s/[^\s]+ちゃん/****さん/g;
    $text =~ s/[^\s]+くん/****クン/g;
    $text =~ s{http://t.co/[\w\-]+}{http://t.co/******}g;
    print $user." : ".encode_utf8($text)."\n";
    my $json = Mojo::JSON->new;
    my $dt   = DateTime->now( time_zone => 'Asia/Tokyo');
    my $str = $json->encode({
      hms  => $dt->hms,
      user => $user,
      text => $text,
    }); # utf8フラグが落ちる
    utf8::decode( $str ); # utf8フラグ付きに戻す
    for (keys %$clients) {
      $clients->{$_}->send_message( $str );
    }
  },
  on_error => sub {
    my $error = shift;
    warn "ERROR: $error";
    $done->send;
  },
  on_eof   => sub {
    $done->send;
  },
);
 
get '/' => 'index';
 
 
websocket '/echo' => sub {
  my $self = shift;
 
  app->log->debug(sprintf 'Client connected: %s', $self->tx);
  my $id = sprintf "%s", $self->tx;
  $clients->{$id} = $self->tx;
 
  $self->on_message();
 
  $self->on_finish(
    sub {
      app->log->debug('Client disconnected');
      delete $clients->{$id};
    }
  );
};
 
app->start;
 
__DATA__
@@ index.html.ep
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Mojolicious + WebSocket + Twitter Streaming API</title>
    %= javascript '/js/jquery.js';
    <script type="text/javascript">
    $(function() {
      $('textarea').height(
        $('body').innerHeight() - $('article').position().top
      );
    });
    $(function () {
      var show = function (text) {
        var sel = 'textarea';
        $(sel).val( text + "\n" + $(sel).val() );
      };
      var ws = new WebSocket('ws://' + location.host + '/echo');
      ws.onopen = function () {
        console.log('Connection opened');
      };
      ws.onmessage = function (msg) {
        var res = JSON.parse(msg.data);
        show(res.user + ': ' + res.text); 
      };
    });
    </script>
    <style type="text/css">
      html, body { height: 98%; }
      h1 { font-size: 14px; }
      textarea { width: 100%; }
    </style>
  </head>
  
  <body>
    <header>
      <h1>Mojolicious + WebSocket + Twitter Streaming API</h1>
    </header>
    <article>
      <textarea></textarea>
    </article>
  </body>
</html>

サーバを立ち上げるあたりが大変なのかもしれませんが、これでいろんなものが作れそうな気がしてきますよね。

参考にした:
Mojolicious::Lite で WebSocket を使ったチャットを作る - naoyaのはてなダイアリー [d.hatena.ne.jp]
M.C.P.C.: AnyEvent::Twitterなるものを知ったがSearch APIは使えないのかな←Search APIはないけれども、methodをFilterにして、trackにひっかけたい文字列を設定するんですね。


(2011-10-10 15:50追記)

このままだと、素の状態から構築したときEVモジュールが入っていないと動かないことが判明したので、use EV;を追加しました。

投稿 大野 義貴 [Web] | |

トラックバック(0)

トラックバックURL: http://blog.dtpwiki.jp/MTOS/mt-tb.cgi/3719

コメントする