Fork me on GitHub

2010/04/15

はてな
今日、tsupoさんから「Twitter API プログラミング」という本が届いた。
tsupoさん、ありがとうございました。
twitter-api-book
Twitter API プログラミング Twitter API プログラミング
辻村 浩
ワークスコーポレーション / ¥ 2,730 (2010-04-21)
 
発送可能時間:在庫あり。

まだ少ししか読んでないけど、Twitterが好きで、プログラミング言語が好きで、そして何よりAPIが好きだという人にはもってこいな一冊だと思います。
1冊のほとんどをTwitterの認証やAPIの説明に費やしています。PHP、Python、Ruby、Perl、C/C++など多くの実装例も含まれています。
私は基本的なpythonのモジュールのみでxAuthを実装したサンプルコードを載せて頂きました。
ところで、今日ふとこの本を手にとった時、「なんでみんなこんなにAPIが好きなんだろう」、「たかだかネットワーク上に流れるテキストストリームになぜ皆が魅了されるんだろう」と思った。
APIがあって何が嬉しい?フィボナッチ数列をtwittre.comにポストしたい?誰が嬉しい?他人のポストをデスクトップでGrowlしたい?どこが嬉しい?

プログラミングって一体何が楽しいのか、なぜ職業にしてまでも続けるのか...

プログラミングって簡単に言うと、「束縛プレイと制圧感のアンサンブル」なんじゃないかと時折思ったりもする。わざわざインストールの面倒くさいスクリプト言語のインタプリタをインストールして、使おうと思ってたモジュールが実は他のモジュールに依存していて、そのインストールで苦しんで、いったい何が嬉しいのか。
そう、その「動かない」が楽しいんじゃなかろうか。みんな「動かない」を楽しんでいるんだ。それと同時に動くようになったときの達成感と自分がコンピュータに「こう動け!」と書いたシナリオ通りに動かす制圧感がプログラミングの醍醐味なんだと思う。さらにはそれをブログで書くと、びっくりしてくれる人もいるし、喜んでくれる人もいる。スクレイピングした結果をハッシュリファレンスの配列にしただけの状態のソースコードに「++」と書いてくれる人もいる。アクロバチックな技を使ってtwitterのAPIを介して「Hello World」を書くプログラムにアクセスが集中するのがプログラミングだ。「API制限とかあるんでしょ?素直にブラウザ使えばいいじゃない」と言われても「だってコードが書きたいんだもん」とただただAPIを追いかけるんですよ。ユーザIDとパスワードだけじゃなく、コンシューマーキー、コンシューマーシークレットキーなんて不可解な暗号を4つも使ってようやくHello Worldをポストするんですよ。

そしていつもAPI認証を通過した先には、いつものAPI好きな彼らがいる。APIというエントリポイントで繋がっているんだ。
そう、それがプログラミングだ。


プログラマってバカなんじゃなかろうか。

Posted at 02:28 in web::twitter
Tagged as: API, twitter
Bookmarks: add to hatena add to hatena | add to delicious.com | add to livedoor.clip add to livedoor.clip

2010/02/17

はてな
TwitterのBasic認証APIは6月で廃止される予定なのですが、OAuthという認証方法はブラウザを起動してユーザに認証して貰わなければなりません。一見flickrアプリケーションの様な認証方法を想定しますが、OAuthはflickr認証の様にサーバから貰ったトークンをブラウザから渡して認証させる様な物ではありません。
今回OAuthの問題を解決すべくOAuthを拡張した認証方式であるxAuthが取り入れられました。
詳しくはAPIドキュメントか以下のサイトが分かりやすいかと思います。
s-take Blog.: Twitterによる簡易版OAuth: "xAuth"

従来のOAuth認証ではまずアプリケーション(OAuthコンシューマ)がTwitterに接続してRequest Tokenを取得し、認証画面を開いてRequest Tokenを承認させ、承認されたRequest Tokenを使ってAccess TokenとToken Secretを取得することによって各APIにアクセスできるようになります。しかしこれはアプリケーション側の実装が複雑になる上、デスクトップアプリケーションの場合はわざわざWebブラウザへ切り替えなければならず(ブラウザを内包するものもありますが)、ユーザにとっても面倒なものです。

http://s-take.blogspot.com/2010/02/twitteroauth-xauth.html
the.hackerConundrum: Sneak peek at Twitter's browserless OAuth credentials exchange method

Over the past couple of months the Twitter API Google Group has been overflowing with more and more disgruntled developers complaining about lack of bug fixes, slow rollout of promised features, no mobile interface for OAuth, etc. (The list goes on and on) Well I'm happy to say Twitter appears to be almost done with one much requested feature: browserless OAuth credentials exchange. It was hinted that Seesmic Look was using said exchange so today I took a peek at how Look worked behind the scenes.

http://the.hackerconundrum.com/2010/02/sneak-peek-at-twitters-browserless.html
実装だと
Maraigue風。:[Ruby][Twitter] OAuthのアクセストークンを、ブラウザなしで、Twitterのユーザ名およびパスワードのみを用いて取得する(通称:xAuth)ためのRubyのコード
http://blog.livedoor.jp/maraigue/archives/1109122.html
とか
pastebin - 誰か - post number 1796209
http://ja.pastebin.ca/1796209
あとOAuthな話ですが
あまやどり: OAuthで認証してTwitterでつぶやいてみた
http://petitbanca.blogspot.com/2009/11/oauthtwitter.html
あたりが参考になります。今日はpythonを使ってxAuthするサンプルを書いてみました。pythonにも元々oauthライブラリはあるのですが、今回は分かりやすく使わず書いてみました。
以下ソース。
from pit import Pit
from random import getrandbits
from time import time
import hmac, hashlib
import sys
import urllib
import urllib2
import urlparse

consumer_key = 'YOUR-CONSUMER-KEY'
consumer_secret = 'YOUR-CONSUMER-SECRET'
user = Pit.get('twitter.com', {'require' : {
  'username' : 'your username in twitter.com',
  'password' : 'your password in twitter.com',
}})
message = sys.argv[1]
access_url = 'https://api.twitter.com/oauth/access_token'
post_url = 'http://twitter.com/statuses/update.json'

# build parameter to get access token
params = {
  'oauth_consumer_key' : consumer_key,
  'oauth_signature_method' : 'HMAC-SHA1',
  'oauth_timestamp' : str(int(time())),
  'oauth_nonce' : str(getrandbits(64)),
  'oauth_version' : '1.0',
  'x_auth_mode' : 'client_auth',
  'x_auth_username' : user['username'],
  'x_auth_password' : user['password'],
}
params['oauth_signature'] = hmac.new(
  '%s&%s' % (consumer_secret, ''),
  '&'.join([
      'POST',
      urllib.quote(access_url, ''),
      urllib.quote('&'.join(['%s=%s' % (x, params[x])
          for x in sorted(params)]), '')
  ]),
  hashlib.sha1).digest().encode('base64').strip()

# get access token
req = urllib2.Request(access_url, data = urllib.urlencode(params))
res = urllib2.urlopen(req)
token = urlparse.parse_qs(res.read())
token_key = token['oauth_token'][0]
token_secret = token['oauth_token_secret'][0]

# build parameters to post
params = {
  'oauth_consumer_key' : consumer_key,
  'oauth_signature_method' : 'HMAC-SHA1',
  'oauth_timestamp' : str(int(time())),
  'oauth_nonce' : str(getrandbits(64)),
  'oauth_version' : '1.0',
  'oauth_token' : token_key,
}
params['status'] = urllib.quote(message, '')
params['oauth_signature'] = hmac.new(
  '%s&%s' % (consumer_secret, token_secret),
  '&'.join([
      'POST',
      urllib.quote(post_url, ''),
      urllib.quote('&'.join(['%s=%s' % (x, params[x])
          for x in sorted(params)]), '')
  ]),
  hashlib.sha1).digest().encode('base64').strip()
del params['status']

# post with oauth token
req = urllib2.Request(post_url, data = urllib.urlencode(params))
req.add_data(urllib.urlencode({'status' : message}))
req.add_header('Authorization', 'OAuth %s' % ', '.join(
  ['%s="%s"' % (x, urllib.quote(params[x], '')) for x in params]))

# done!
print urllib2.urlopen(req).read()
生の処理で書いてあるので、oauthライブラリに依存させたくない様な移植には参考になるかもしれません。
ところで今回GtkTwitterというC言語で書いたTwitterクライアントのBasic認証を止めようと思っていてこの件を調べ始めたのですが, どうやらTwitterに登録するOAuthアプリケーションには「Twitter」という文言を使ってはいけない事が今日分かりました。まぁGtkTwitterはクライアントアプリが名前登録出来た頃に書いた物なので、あの頃はOKだったのかも知れません。
しかしまぁ...どうせぃっちゅうねん!

どうしましょ。Gtkほにゃらら...何がいいやろ。困った。
Posted at 01:15 in ソフトウェア::lang::python
Tagged as: oauth, python, twitter, xauth
Bookmarks: add to hatena add to hatena | add to delicious.com | add to livedoor.clip add to livedoor.clip

2010/01/21

はてな
いままでブログからtwitterへの投稿はtwitterfeedを使ってたんだけど、なんか変にキューイングされたり投稿されなかったりとイヤンな感じだったので、和製のFeedTweetに乗り換えた。
ダッシュボードも見やすい。
feedtweet1
アクセス解析も付いてくる。
feedtweet2
現在の状態がよく分かるし、キューを先行させる事も出来る。
投稿時間の制限も出来るみたい。私は夜中でも今すぐ投稿して欲しかったので以下の様に設定した。
feedtweet3
しばらく使ってみようと思う。
Posted at 00:21 in web
Tagged as: feed, rss, twitter
Bookmarks: add to hatena add to hatena | add to delicious.com | add to livedoor.clip add to livedoor.clip

2009/12/22

はてな
Go binding for GTK GoのGTKバインディングを現在作業中なのですが、ようやく簡単なTwitterクライアントくらいならば作れる程度に出来上がってきたのでご報告。
mattn's go-gtk at master - GitHub

Go binding for GTK

http://github.com/mattn/go-gtk
イベントハンドラがJavaScriptっぽく書けるので、結構見通し良いコードになります。
package main

import "gtk"
import "gdk-pixbuf"
import "unsafe"
import "http"
import "json"
import "io"
import "os"
import "strconv"
import "strings"
import "reflect"

func url2pixbuf(url string) *gdkpixbuf.GdkPixbuf {
    if r, _, err := http.Get(url); err == nil {
        n, _ := strconv.Atoi64(r.GetHeader("Content-Length"));
        t := r.GetHeader("Content-Type");
        b := make([]byte, n);
        io.ReadFull(r.Body, b);
        var loader *gdkpixbuf.GdkPixbufLoader;
        if strings.Index(t, "jpeg") >= 0 {
            loader, _ = gdkpixbuf.PixbufLoaderWithMimeType("image/jpeg");
        } else {
            loader, _ = gdkpixbuf.PixbufLoaderWithMimeType("image/png");
        }
        loader.SetSize(24, 24);
        loader.Write(b);
        loader.Close();
        return loader.GetPixbuf();
    }
    return nil;
}

func main() {
    gtk.Init(&os.Args);
    window := gtk.Window(gtk.GTK_WINDOW_TOPLEVEL);
    window.SetTitle("Twitter!");
    window.Connect("destroy", func(w *gtk.GtkWidget, args []unsafe.Pointer) {
        gtk.MainQuit();
    }, nil);

    vbox := gtk.VBox(false, 1);

    scrolledwin := gtk.ScrolledWindow(nil, nil);
    textview := gtk.TextView();
    textview.SetEditable(false);
    textview.SetCursorVisible(false);
    scrolledwin.Add(textview);
    vbox.Add(scrolledwin);

    buffer := textview.GetBuffer();

    tag := buffer.CreateTag("blue", map[string] string {
        "foreground": "#0000FF", "weight": "700" });
    button := gtk.ButtonWithLabel("Update Timeline");
    button.Clicked(func(w *gtk.GtkWidget, args []unsafe.Pointer) {
        if r, _, err := http.Get("http://twitter.com/statuses/public_timeline.json"); err == nil {
            n, _ := strconv.Atoi64(r.GetHeader("Content-Length"));
            b := make([]byte, n);
            io.ReadFull(r.Body, b);
            j, _ := json.Decode(string(b));
            arr := reflect.NewValue(j).(*reflect.SliceValue);
            for i := 0; i < arr.Len(); i++ {
                data := arr.Elem(i).(*reflect.InterfaceValue).Elem().(*reflect.MapValue);
                icon := data.Elem(reflect.NewValue("user")).(*reflect.InterfaceValue).Elem().(*reflect.MapValue).Elem(reflect.NewValue("profile_image_url")).(*reflect.InterfaceValue).Elem().(*reflect.StringValue).Get();
                var iter gtk.GtkTextIter;
                buffer.GetStartIter(&iter);
                buffer.InsertPixbuf(&iter, url2pixbuf(icon));
                name := data.Elem(reflect.NewValue("user")).(*reflect.InterfaceValue).Elem().(*reflect.MapValue).Elem(reflect.NewValue("screen_name")).(*reflect.InterfaceValue).Elem().(*reflect.StringValue).Get();
                text := data.Elem(reflect.NewValue("text")).(*reflect.InterfaceValue).Elem().(*reflect.StringValue).Get();
                buffer.Insert(&iter, " ");
                buffer.InsertWithTag(&iter, name, tag);
                buffer.Insert(&iter, ":" + text + "\n");
            }  
        }
    }, nil);
    vbox.PackEnd(button, false, false, 0);

    window.Add(vbox);
    window.SetSizeRequest(300, 400);
    window.ShowAll();
    gtk.Main();
}
実行すると以下の様な画面になります。
go-gtk-twitter-client
まだ、完成じゃないです。がんばります!
Posted at 00:26 in ソフトウェア::lang::go
Tagged as: golang, twitter
Bookmarks: add to hatena add to hatena | add to delicious.com | add to livedoor.clip add to livedoor.clip