Twitterのタイムラインを監視してキーワードにマッチしたらGrowlするRubyスクリプト(2)

先日のスクリプトを改良した。

前回からの変更点

  • Growl時にアイコンを表示するようにした
  • Growlのスティッキーに対応
  • 標準出力に出力するかどうかを設定可能にした
  • IDの読み上げを行う機能を追加
  • 複数の設定を持てるようにした。

かなり変わった。

twitterwatcher.rb

ファイル名をtwittertail.rbからtwitterwatcher.rbに変更したよ。tailだけじゃなくいろいろやるので。

require 'rubygems'
require 'twitter'
require 'meow'
require 'yaml'
require 'cgi'
require 'open-uri'
$KCODE = 'UTF8'

config = YAML.load(STDIN)
growl = Meow.new('twitterwatcher.rb')
twitter = Twitter::Base.new(config['username'], config['password'])

cache = []
while true
  begin
    timeline = twitter.timeline(:friends).reverse
    timeline.each do |status|
      next if cache.include?(status.id)
      
      # status
      screen_name = status.user.screen_name
      name = CGI.unescapeHTML(status.user.name)
      text = CGI.unescapeHTML(status.text)
      created_at = Time.parse(status.created_at).strftime('%Y-%m-%d %H:%M')
      image_uri = CGI.unescapeHTML(status.user.profile_image_url)
      
      # filter
      growltype = 'none'
      stdout = 'none'
      say = 'none'
      config['filters'].each do |f|
        if f['keywords'].any?{|k|[screen_name, name, text].any?{|t|t.match(k)}}
          growltype = f['growl']
          stdout = f['stdout']
          say = f['say']
          break
        end
      end
      
      # output
      if growltype != 'none'
        image_uri.gsub!(%r|[^/]+$|){|m|CGI.escape(m)}
        open(image_uri) do |image|
          open("icon_#{screen_name}", 'w') do |f|
            f.print image.read
          end
        end
        icon = Meow.import_image("icon_#{screen_name}")
        growl.notify("#{screen_name}(#{name})", text, {:icon => icon, :sticky => (growltype == 'sticky')})
      end
      if stdout == 'highlight'
        puts
        puts "  #{screen_name}(#{name}) #{created_at}"
        puts "    #{text}"
        puts
      elsif stdout == 'normal'
        puts "#{screen_name} : #{text}"
      end
      if say == 'name'
        `say #{screen_name.gsub(/_/, ' ').gsub(/([a-zA-Z]+|[0-9]+)/){$1 + ' '}}`
      end
      cache << status.id
    end
  rescue
    puts $!
  end
  sleep config['interval']
end

config.yaml

前のconfig.yamlとは互換してない。

username: hogehoge
password: passpass
interval: 60
filters:
  - growl: sticky
    stdout: highlight
    say: name
    keywords:
      - nacookan
      - mac
      - ruby
  - growl: normal
    stdout: highlight
    say: none
    keywords:
      - おは
      - 起きた
      - おやすみ
      - 寝る
  - growl: none
    stdout: none
    say: none
    keywords:
      - @
  - growl: none
    stdout: normal
    say: none
    keywords:
      - .*

こんな感じ。上記の設定だと、

  • nacookan, mac, ruby のどれかを含む発言があったとき
    • Growlをスティッキー(自動で閉じない通知)で表示。
    • 標準出力には目立つように出力。
    • 投稿者のIDを音声読み上げ(sayコマンド)。
  • おは, 起きた, おやすみ, 寝る のどれかを含む発言があったとき
    • Growlを普通に表示。
    • 標準出力には目立つように出力。
    • 読み上げはしない。
  • @ を含む発言があったとき
    • Growlはしない。
    • 標準出力には出力しない。
    • 読み上げはしない。
  • 上記以外の全ての発言で
    • Growlはしない。
    • 標準出力には普通に出力。
    • 読み上げはしない。

ということになる。

詳しくは以下。

  • growl : sticky, normal, none のいずれか
  • stdout : highlight, normal, none のいずれか
  • say : name, none のいずれか
  • keywords : 正規表現のリスト

まあわかるよね。

準備

Growlをインストールして、さらにgemでtwitterとmeowを入れておく。

Meowが動くにはRubyCocoaも必要なんだそうだ。入れてない人は入れる必要がある。

使い方

$ ruby twitterwatcher.rb < config.yaml

ruby-growlからMeowへ

前作はGrowlの制御にruby-growlを使っていた。ただ、これはスティッキーがうまくいかない、アイコンが設定できないなどの問題があったので、Meowに変えた。そしたらうまくいった。

Growlのアイコン表示

Meowはアイコン表示に対応してるけど、ローカルに置いてある画像じゃないとダメっぽい。画像のURLを指定してもダメだった。

そこで、画像をいったんローカルに保存して、それをMeowに渡すようにした。

なので、ディレクトリに icon_(TwitterのID) のファイルが生成される。めんどくさいからファイルは消してないので、Growlで通知させまくってるとユーザー数の分だけファイルが溜まると思う。

sayコマンド

Macはターミナルで

$ say hello

って打つと、「ハロー」としゃべってくれる。もちろんhelloじゃなくても良い。読み上げ機能。今回これも使ってみた。Rubyの内部でsayコマンドを呼んでるだけ。

sayコマンドは日本語に対応してないので、今回は名前(TwitterのID)の読み上げだけにしておいた。日本語→ローマ字変換エンジンを使ってローマ字をsayに渡せば本文読み上げも一応可能だとは思う。やったことはない。

まあでも本文を読み上げる必要ないよねたぶん。名前を読み上げるだけでも結構便利だよ。

まとめ

絶対に見逃したくないキーワードはスティッキーでGrowlするようにしたり、IDをキーワードにしてそのユーザーの発言を追いかけてるときはsayさせると良さそう。

あと、いまだに投稿はできないので注意。