読者です 読者をやめる 読者になる 読者になる

$shibayu36->blog;

株式会社はてなでエンジニアをしています。プログラミングや読書のことなどについて書いています。

Net::TwitterとNet::Twitter::Liteの関係

今回もTwitter API v1.1に関連するお話です。perlTwitter APIを利用する際に使われているNet::TwitterとNet::Twitter::Liteに関することについて書いてみます。

背景

Net::TwitterTwitter APIperlクライアントの一つです。これを利用することでTwitter APIを簡単に利用できることが出来ます。
しかしながらNet::TwitterMooseに依存していました。そのためMoose依存を無くし、同じ機能を有したモジュールが同じ作者によって作られました。それがNet::Twitter::Liteです。
現状であればとりあえずperlTwitter 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.plnet-twitter-lite.tt2というファイルがあります。これを使うことで手元にNet::TwitterとTemplate::Toolkitが入っていれば、以下のようにしてコードを生成することが可能になります。

perl src/build.pl 0.11002 src/net-twitter-lite.tt2 lib/Net/Twitter/Lite.pm

なかなか大変ですね。

Net::TwitterAPI v1.1対応

さてここでNet::TwitterAPI 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::Twitterapi-v1.1はdeprecatedというパラメータにcoderefが入ることがあり、これがbuild.plは対応していないので、適当にCODE(0x...)となっているところを1とかに置換します。

すると一応v1.1対応しているNet::Twitter::Liteが出来上がります。とりあえずの一時対応ならまあ使えるかなといった感じです。注意点はたまにメソッドの引数が変わっていることです。普通に使うだけでは動かなくなるメソッドが存在します。

まとめ

今回はNet::TwitterとNet::Twitter::Liteの関係について書き、強引にNet::Twitter::Liteをv1.1対応する方法について書きました。本当はpull requestを送るほうが良いのでしょうが、Net::Twitterのv1.1のステータスがよくわからないというのと、動的生成のためそちらが確定しないと手を出せないということで、まだ出来ていません。

かなり強引な方法なのでご利用は自己責任で。