今回もTwitter API v1.1に関連するお話です。perlでTwitter APIを利用する際に使われているNet::TwitterとNet::Twitter::Liteに関することについて書いてみます。
背景
Net::TwitterはTwitter APIのperlクライアントの一つです。これを利用することでTwitter APIを簡単に利用できることが出来ます。
しかしながらNet::TwitterはMooseに依存していました。そのためMoose依存を無くし、同じ機能を有したモジュールが同じ作者によって作られました。それがNet::Twitter::Liteです。
現状であればとりあえずperlでTwitter APIを使いたければNet::Twitter::Liteを使うのがよいでしょう。いろいろ面倒であればOAuth系だけ他のモジュールに頼り、独自実装でも良いかもしれません。
Net::Twitter::Liteの中身
それで最近Twitter APIのv1.1対応をしていて、Net::Twitter::Liteの中身はどうなってるんだろうなーと思ったので調べて見ることにしました。
このへんから適当にダウンロードしてみると、lib/Net/Twitter/Lite.pmに以下の様な定義がずらっと並んでいて、動的にメソッドを作っていることがわかりました。
my $api_def = [ [ Lists => [ [ 'legacy_add_list_member', { aliases => [ qw// ], path => ':user/:list_id/members', method => 'POST', params => [ qw/user list_id id/ ], required => [ qw/user list_id id/ ], add_source => 0, deprecated => 0, authenticate => 1, booleans => [ qw// ], base_url_method => 'lists_api_url', } ], [ 'legacy_create_list', { aliases => [ qw// ], path => ':user/lists', method => 'POST', params => [ qw/user name mode description/ ], required => [ qw/user name/ ], add_source => 0, deprecated => 0, authenticate => 1, booleans => [ qw// ], base_url_method => 'lists_api_url', } ], ....
なるほどなるほどと思い、そこでもう少し調べようと思ってgithubからcloneしてくることにしました。https://github.com/semifor/net-twitter-lite からcloneします。
するとcloneした中にlib/Net/Twitter/Lite.pmが存在しません。これは驚きですね。どうしているんでしょう。
Net::Twitter::Liteのコード動的生成
でいろいろ調べてみると、なんとNet::Twitter::Liteは手元に入っているNet::Twitterを利用してコードを動的生成しています。
cloneしたrepositoryをみてみると、おもむろにsrcというdirectoryがあり、この中にbuild.plとnet-twitter-lite.tt2というファイルがあります。これを使うことで手元にNet::TwitterとTemplate::Toolkitが入っていれば、以下のようにしてコードを生成することが可能になります。
perl src/build.pl 0.11002 src/net-twitter-lite.tt2 lib/Net/Twitter/Lite.pm
なかなか大変ですね。
Net::TwitterのAPI v1.1対応
さてここでNet::TwitterのAPI v1.1対応について見てみましょう。https://github.com/semifor/Net-Twitter からbranch一覧を見てみると実はapi-v1.1というbranchが存在しています。またTwitter API version 1.1 · Issue #13 · semifor/Net-Twitter · GitHubをみると、テストやドキュメントは整備されていないけど機能は大体出来ているみたいなことが書かれています。
このbranchの中もみてみるとlib/Net/Twitter/Role/APIの中にRESTv1_1.pmが存在していることを確認出来ます。
Net::Twitter::Liteを強引にv1.1に対応させる
ここまで書いてきた内容でNet::Twitterのv1.1ブランチを使えば強引にNet::Twitter::Liteを対応できるのではないかという考えが出てきます。というわけでやってみました。
まずNet-Twitterをcloneして、api-v1.1をcheckoutし、インストールしてみます。
git clone git://github.com/semifor/Net-Twitter.git cd Net-Twitter git checkout api-v1.1 cpanm .
その後Net::Twitter::Liteをcloneしてきます。
git clone git://github.com/semifor/net-twitter-lite.git
さらに以下の様な変更をしたりします。
diff --git a/src/net-twitter-lite.tt2 b/src/net-twitter-lite.tt2 index 38cf430..0ee9288 100644 --- a/src/net-twitter-lite.tt2 +++ b/src/net-twitter-lite.tt2 @@ -20,10 +20,10 @@ sub new { my $netrc = delete $args{netrc}; my $new = bless { - apiurl => 'http://api.twitter.com/1', - searchapiurl => 'http://search.twitter.com', - search_trends_api_url => 'http://api.twitter.com/1', - lists_api_url => 'http://api.twitter.com/1', + apiurl => 'http://api.twitter.com/1.1', + searchapiurl => 'http://api.twitter.com/1.1/search', + search_trends_api_url => 'http://api.twitter.com/1.1', + lists_api_url => 'http://api.twitter.com/1.1', apirealm => 'Twitter API', $args{identica} ? ( apiurl => 'http://identi.ca/api' ) : (), useragent => __PACKAGE__ . "/$VERSION (Perl)", @@ -404,7 +404,7 @@ sub _mk_post_msg { { ### scope $api_def my $api_def = [ -[% FOREACH api IN [ [ 'Lists', '^legacy_' ], [ 'REST' ], [ 'Search' ] ] -%] +[% FOREACH api IN [ [ 'Lists', '^legacy_' ], [ 'RESTv1_1' ] ] -%] [ [% api.0 %] => [ [% FOREACH method IN get_methods_for(api.0, api.1) -%] [ '[% method.name %]', {
そしてbuildします。
perl src/build.pl 0.11002 src/net-twitter-lite.tt2 lib/Net/Twitter/Lite.pm
さらにNet::Twitterのapi-v1.1はdeprecatedというパラメータにcoderefが入ることがあり、これがbuild.plは対応していないので、適当にCODE(0x...)となっているところを1とかに置換します。
すると一応v1.1対応しているNet::Twitter::Liteが出来上がります。とりあえずの一時対応ならまあ使えるかなといった感じです。注意点はたまにメソッドの引数が変わっていることです。普通に使うだけでは動かなくなるメソッドが存在します。