@tomitaさんが書いた「CPANモジュールガイド」の刊行記念ということで池袋のジュンク堂本店で話して・・・もとい、コードを書いてきました。普段は滅多にこういう場に現れない「初めてのPerl」や「プログラミングPerl」の翻訳者である近藤嘉雪氏がもう一人のゲスト。司会がもはや技術界のタモリと化しつつある@yusukebe。あと@941さんがスタッフとして手伝いに来てくれました
近藤さんを見られるというだけでも実はすごいイベントだった気がする。ちなみに近藤さんは出番直前まで頑張ってスライドを書いていて、そのおかげで話にクロージャが含まれたそうです!
こちらは@tomitaさんが書いた店頭POP。「Placクマ」の二重のパクリがひどいですねwww !
イベントの内容自体は・・・なんだかリハーサルというか、ちゃんとした打ち合わせもしてなかったのに、すごく内容が良い感じになった気がしますね。Perlの基本を@tomitaさんと近藤さんが丁寧に説明してくれて、最後に僕がわーーーっとCPANモジュールを使ってコードを書く過程をなぞる、という感じ。
自分の発表はCPAN 30分クッキングということでCPANから色々ダウンロードしてきてFacebook::Graphとか使ったらこうなるよー的なコードをざくざく書きました。
最終的に書いたコードは、@sugyanさんのブログのパクリと、自分の友達のタイムラインからロケタッチのリンクを抜き出してきてHTMLを作る、というようなもの。本番では実はトラブルがあって最後のロケタッチページを作成するためのHTTPリクエストがうまく動かなかったので一瞬焦ったが、「CPAN 30分クッキング」ということで「すでにこちらに出来たものがございます」というものを用意しておいたので助かった。一応その程度のネタは仕込んでおいてよかった・・・
というわけでなかなか楽しかった!みんな、もっと僕らの本を買ってくれると次が出せるようになるからよろしくお願いします!w
さて、僕の発表ですが、全然中身はないですが、スライドは以下のような感じ:
CPAN 30分クッキング
View more presentations from lestrrat.
あと一応こちらがコード。最初にconfig.plというファイルの中に自分のFacebookアプリ用のapp_idとsecretを入れておく
return {
app_id => "XXX your app ID",
secret => "XXX your app secret"
};
まずはsugyanさんのパクリのヤツ。アクセストークンをコピペするのが面倒くさいのでコンフィグファイルにダンプするようにしてある:
use strict;
use Data::Dumper;
use Facebook::Graph;
use Plack::Request;
my $config = require "config.pl";
my $fb = Facebook::Graph->new(
app_id => $config->{app_id},
secret => $config->{secret},
postback => "http://localhost:5000/"
);
return sub {
my $env = shift;
my $req = Plack::Request->new($env);
if ( my $code = $req->param('code') ) {
warn "requesting access_token";
$fb->request_access_token( $code );
my $dump = Dumper({
%$config,
access_token => $fb->access_token
});
$dump =~ s/\$VAR = //;
open my $fh, '>', "config.pl" or
die;
print $fh $dump;
close $fh;
return [ 200, [], [ $fb->access_token ] ];
}
warn "redirect";
return [
302,
[
Location => $fb->authorize
->extend_permissions( "publish_stream" )
->uri_as_string
],
[]
];
}
で、こっちがFacebookにアクセスしてロケタッチのデータだけ抜き出してくるヤツ。普通にFacebook::GraphのAPI使ってたらおせーな、と思ったのでFurl+Coroしてみた。よくよく考えてみると CoroとCoro::LWPしとけばFurl使わなくても多重化できるから速くなる気がするが、まぁ後悔はしてない
use strict;
use Text::Xslate;
use JSON;
use Coro;
use Coro::Select;
use Furl::HTTP;
use Facebook::Graph;
use Data::Dumper::Concise;
my $config = require "config.pl";
my $fb = Facebook::Graph->new(
app_id => $config->{app_id},
secret => $config->{secret},
access_token => $config->{access_token},
);
my $data = $fb->query->find("me/friends")->request->as_hashref;
my $furl = Furl::HTTP->new;
my @coros;
foreach my $friend ( @{ $data->{data} } ) {
my $q = $fb->query->find( "$friend->{id}/feed" );
push @coros, async {
my (undef, $code, undef, undef, $body ) = $furl->get( $q->uri_as_string
);
return unless $code eq 200;
return decode_json $body;
} $q->uri_as_string;
}
my @spots;
foreach my $coro (@coros) {
my $feed = $coro->join;
next unless $feed;
foreach my $entry ( @{ $feed->{data} } ) {
if ( $entry->{caption} eq 'tou.ch' ) {
push @spots, $entry->{link};
}
}
}
my $xslate = Text::Xslate->new(
path => [ "." ],
syntax => 'TTerse',
);
print $xslate->render_string( <<'EOM', { spots => \@spots } );
<script type="text/javascript" src="jquery-1.5.2.min.js">
<script type="text/javascript">
var urls = [ [% FOREACH spot IN spots %]"[% spot %]"[% IF ! loop.last %],[% END %][% END %] ];
$(document).ready( function() {
var delay = 200;
var f = function() {
url = urls.pop();
url = url.replace( /\/$/, "" );
url = url.replace(/\/spot/, "/widget/spot");
var iframe = $('<iframe frameborder="0" scrolling="no" allowtransparency="ture" height="321" width="350" src="' + url + '?i=0&m=1&t=blue&width=350"></iframe>');
$("#container").append( iframe );
setInterval(f, delay);
};
f();
} );
</script>
<div id="container"></div>
EOM