sifue's blog

プログラマな二児の父の日常 ポートフォリオは www.soichiro.org

Twitterの検索結果をIRCにnoticeで転送し、閾値を超えるとmessageするボット

Scala2.9→2.10に移行するにあたって、公開することで誰かが使えるかもしれないScalaのツールがあったので、GitHubに公開しました。Twitter APIも1.0の廃止が近いので1.1への対応をしてあります。


https://github.com/sifue/twisearch_ircbot


使う用途は主にIRC上でのtwitter監視ですねw 内部的にStreaming APIではなくRESTのSearch APIを使っているので、ANDやOR、その他の検索指定演算子を利用することができます。http://blog.fkoji.com/2009/10191119.html の解説が丁寧です。


なおScala2.10といいつつ、akkaへの移行が大変だったりとか、長期間の検証をしなくていはいけないとかがあり、こいつはactorをそのまま使っています。build.sbtに

libraryDependencies <+= scalaVersion("org.scala-lang" % "scala-actors" % _)

を書くことでactorをそのまま使い続けられます。id:xuweiさん、情報ありがとうございました。
なお内部的には、twitter4jとsircを梱包しており、assemblyコマンドでビルドすることでjava -jarコマンドで実行できるjarになります。

$ git clone git@github.com:sifue/twisearch_ircbot.git

を利用して、思い思いにコードを変更してご利用ください。


ビルド方法は、以下のとおり

ビルド方法

javaとsbtをインストールの上、

$ sbt
> assembly

これでtargetディレクトリの中に、twisearch_ircbot-assembly-2.0.jarがビルドされます。

使い方

twisearch_ircbot-assembly-2.0.jarと同じディレクトリに、 twisearch_ircbot_template.propertiesを正しく編集して、 twisearch_ircbot.propertiesというファイル名で保存ください。

irc.address = hostname
irc.channel = #channelname
irc.nickname = twisearch_ircbot
irc.charset = UTF-8
limitCount = 3
intervalSec = 60
keyword = #MT2
messageFormat = interval:%1$s keyword:%2$s count:%3$s
noticeFormat = @%1$s %2$s %3$s
consumerKey = consumerKey
consumerSecret = consumerSecret
accessToken = acessToken
accessTokenSecret = accessTokenSecret

twisearch_ircbot.propertiesの内容のうち、consumerKey、consumerSecret、accessToken、accessTokenSecretはTwitter Developpers https://dev.twitter.com/ より、ログインの後、アプリケーションを作成してaccessTokenを発行してご利用ください。

なお日本語などを入れたい場合には、javaのnative2asciiコマンドを利用してascii化する必要があります。 http://symfo.web.fc2.com/js-sample/jq/sample2.html 以上のようなサイトでも変換できます。


設定の後、

$java -jar twisearch_ircbot-assembly-2.0.jar

で実行することができます。 またIRCのボットが入っているチャンネルにて

ping nickname

とするとWorking now.とnoticeを返します。

コードの中身

メインルーチンは、
TwitterSeacher.scala

  def act() = loop {
    val query = new Query
    query.setQuery(keyword)
    query.setSinceId(maxId)
    query.setResultType(Query.RECENT);
    val tweets = twitter.search(query).getTweets().reverse
    if(maxId != 0L) tweets.filter(t => t.getId() > maxId).foreach(sendNoticeToIRC)
    val count = tweets.filter(t => t.getId() > maxId).size
    if(count > limitCount && maxId != 0L) sendMessageToIRC(count)
    tweets.foreach(t => {if(t.getId() > maxId) maxId = t.getId()})
    TimeUnit.SECONDS.sleep(intervalSec)
  }

これだけで表現できています。あとは設定の読込と例外ハンドルだけ。やっぱりScalaは短く書けて良いです。