naoya_t@hatenablog

いわゆるチラシノウラであります

erlang-oauthでTwitter Streaming APIとかUserStreamsとか

先月「R15Bを入れたらerlang-oauthが動かなくなった」というエントリで erlang-oauth についてちらっと触れた続編というか応用編というか

Twitter Streaming APIもUserStreamsもストリーミングなのですが

ですよね

id:takkkun さんの記事「Twitter Streaming APIをErlangから使ってみる」を参考にしながら、これにTim Fletcher氏のerlang-oauth を使えば何とかなるだろう、と思ってあれこれあれこれあれこれ試行錯誤してたら出来た感じです(その過程でデバッグ回りのサポートが改善されたR15Bに期待してアップデートしたらerlang-oauthが動かなくなって云々、というのが前回までのあらすじ)

OAuth(あるいはBasic認証)でstreamingする為のライブラリを https://github.com/naoyat/erlang-oauth-stream に置いてます

  • erlang-oauth (OAuth認証つきHTTP GET/POST)
  • mochijson (Twitter APIからのJSON出力を読み解くのに使ってます)

は同梱していないのでそれぞれ別途取得してください

sample.erl:

-module(sample).
-export([start/0, stream_process_loop/1, react_to_status/2]).
-include("twitter.hrl").

start() ->
  % erl -pa ebin -s crypto -s inets
  crypto:start(),
  inets:start(),
  ssl:start(),

  TwitterPid = twitter:start(#twitter_params{
    username = "USERNAME HERE",
    password = "PASSWORD HERE",
    consumer_key = "CONSUMER KEY HERE",
    consumer_secret = "CONSUMER SECRET HERE",
    access_token = "ACCESS TOKEN HERE",
    access_token_secret = "ACCESS TOKEN SECRET HERE"}),

  twitter_api:user_stream(TwitterPid, spawn(fun() -> stream_process_loop(TwitterPid) end)),
  ok.

stream_process_loop(TwitterPid) ->
  receive
      {_Streamer, {start, _Headers}} ->
          stream_process_loop(TwitterPid);

      {_Streamer, {stream, Part}} ->
          case mochijson2:decode(Part) of
              {struct, [{<<"friends">>, Friends}]} -> io:format("friends: ~p~n", [Friends]);
              {struct, Status} -> react_to_status(Status, TwitterPid);
              Other -> io:format("ignored: ~p~n", [Other])
          end,
          stream_process_loop(TwitterPid);

      {_Streamer, {error, Reason}} ->
          io:format("process_loop()... <error> reason:~p~n", [Reason])
  end.

react_to_status(Status, TwitterPid) ->
  % Text = proplists:get_value(<<"text">>, Status),
  StatusIdStr = binary_to_list( proplists:get_value(<<"id_str">>, Status) ),
  {struct, User} = proplists:get_value(<<"user">>, Status),

  % ScreenName = proplists:get_value(<<"screen_name">>, User),
  UserIdStr = binary_to_list( proplists:get_value(<<"id_str">>, User) ),

  Params = [{"status", "blah blah blah"},
            {"in_reply_to_status_id", StatusIdStr},
            {"in_reply_to_user_id", UserIdStr}],

  twitter_api:update(TwitterPid, Params).

みたいな感じで遊べます