mikutterの最新の情報は、mikutter blogに引っ越しました。

2011年1月15日土曜日

自動投稿(Postクラス)

Twitterクライアントの基本はつぶやくこととつぶやきを見ること。mikutterでは、Post#update を使ってつぶやけます。Post#postというエイリアスもあります。

Postクラス http://mikutter.hachune.net/rdoc/classes/Post.html

でも、updateは内部ではdefine_methodを使って定義しています。だからRDocには載っていません。載せ方書いてあったけどうまくいかなかった
このPostオブジェクトはもともとつぶやきの投稿のためのものだったんだけど気づいたらAPIのインターフェイスになってました。だからfriend_timelineとかも実はこのクラスを使って取得するんだけど、普通はイベントを使ってください。そのうちServiceに名前変えたいと思ってたけどそろそろ引っ込みがつかなくなってきました

肝心のupdateの使い方ですが、引数はハッシュ1つで、symbolで最大3つの引数を与えられます。

  • :message つぶやきの本文をStringで。必須
  • :replyto リプライ先のメッセージ(in_reply_to_status)。Messageのインスタンスを渡す
  • :receiver リプライ先のユーザ(in_reply_to_user)。このユーザに宛てられる。本文に@そのユーザ名が含まれているかreplytoがセットされていれば自動的に補完される。Userのインスタンスで。

あと、実際の投稿は勝手に別スレッドでやります。気をつけてください。
ブロックを渡すと、(状態, 補足説明)を引数に取って以下のタイミングで呼び出されます。

  • (:try, str) コネクション開始。strは引数の:messageの値。
  • (:success, message) 投稿成功。messageは投稿したメッセージのMessageオブジェクト。
  • (:fail, exception) 失敗。これが渡ってきたらもうリトライしないということ。exceptionには発生した例外オブジェクトか、不正なHTTPコードが送られてきた場合はnilが渡される。
  • (:retry, exception) 失敗。ただし、後でもう一回接続を試みる(現在は1秒後に決め打ち)。

以下の例は、よるほーするプラグインです。

Module.new do
  plugin = Plugin.create(:yoruho)
  plugin.add_event(:boot){ |service|
    Thread.new{
      yoruho = nextyrhtime
      loop{
        nex = yoruho - Time.new # 次回のよるほーまでの秒数
        if(nex <= 0.5)
          say_yoruho(service)
          sleep(43200) # 半日待つ
          yoruho = nextyrhtime
        else
          sleep(nex / 2)
        end
      }
    }
  }

  # 次回のよるほー時間を取得
  def self.nextyrhtime
    now = Time.new
    result = Time.local(now.year, now.month, now.day, 0, 0)
    while result < now
      result += 86400 end
    result
  end

  # よるほーとつぶやく
  def self.say_yoruho(service)
    service.update(:message => 'よるほー'){ |stat, value|
      if stat == :success
        reflection(service, value)
      end
    }
  end

  # messageがよるほーに成功していたらドヤ顔をする
  def self.reflection(service, message)
    if is_pitari?(message[:created])
      service.update(:message => '決まったァ…(ドヤ')
    else
      service.update(:message => 'なん・・・だと・・・')
    end
  end

  # timeが0時0分0秒ならtrueを返す
  def self.is_pitari?(time)
    time.hour == 0 and time.min == 0 and time.sec == 0
  end

end

適当な実装だけど、だいたいこんなかんじ。時間の判定がやたら汚いけど、まあこんなふうにとっても簡単に実装できます。
ちなみにbootっていうイベントは起動時に一回だけ他のイベントより先に呼ばれるイベントで、今のところはPostオブジェクトを得る一番ベターな手段です。

リプライの送り方ですが、あるメッセージへの返信だったら、Message#postを使えばリプライが打てます。今回は省略。

つぶやきの受信と送信の機能があれば、よくあるお遊びbotは実装できます。例えばフォローしてる人限定ぼむったーなんかは簡単な正規表現だけで実装できます。がんばればおはなしbotなんかも実装できるでしょう。