GMailの新着をGTalkアカウントに通知するスクリプト[ruby][gmail]

#!/usr/bin/env ruby

require 'rubygems'
require 'mechanize'
require 'webrick'
require 'xmpp4r'

module Google
  module Mail
    class Error < StandardError ; end

    class Notifier
      #
      #=設定
      #
      #プロセス番号保存ファイル
      PID_FILE = "/tmp/gmail_notifier.pid"
      #エラーログ保存ファイル
      ERROR_LOG_FILE = "/tmp/gmail_notifier.log"
      #チェック間隔
      CHECK_INTERVAL = 60
      #メールアカウント
      MAIL_ACCOUNT  = "hoge"
      #メールパスワード
      MAIL_PASSWORD = "hoge"
      #botアカウント
      BOT_ACCOUNT   = "fuga"
      #botパスワード
      BOT_PASSWORD  = "fuga"

      #
      #=コンストラクタ
      #
      def initialize

        @gmail = WWW::Mechanize.new
        login_page = @gmail.get('https://gmail.com')
        login_form = login_page.forms.first
        login_form['Email']   = MAIL_ACCOUNT
        login_form['Passwd']  = MAIL_PASSWORD
        login_page = @gmail.submit(login_form)

        #タイトルにRedirectingがなければログインエラーと判断
        raise Error.new("Login failed")  unless "Redirecting" == (login_page/"title").inner_html
        login_page = @gmail.get('https://gmail.com')
        @url = (login_page/"//meta").shift["content"].gsub("0;URL=","")

        #botを初期化
        @bot = Jabber::Client.new(Jabber::JID.new("#{BOT_ACCOUNT}@gmail.com/bot"))
        @bot.connect('talk.google.com', 5222)
        #ログインに失敗したらJabber::AuthenticationFailureを放出するので注意
        @bot.auth(BOT_PASSWORD)
        @bot.send(Jabber::Presence.new.set_show(:chat))
        #チェックしたメールのUIDを記録するハッシュ
        @seen = Hash.new
      end

      def start
        begin
          #デーモン化
          WEBrick::Daemon.start {
            pid_file = File.open(PID_FILE,"w")
            pid_file.write(Process.pid)
            pid_file.close
            error_log_file = File.open(ERROR_LOG_FILE,"w")
            loop {
          
              #50件以上チェックしたら一端初期化する
              @seen = Hash.new if @seen.size > 50
              new_seen = Hash.new
              gmail_page =  @gmail.get("#{@url}&ui=html&zy=n")
              #背景が白いものを未読と判断
              (gmail_page/"tr[@bgcolor='#ffffff']").each do |elem|
                uid     = (elem/"//input[@type='checkbox']").shift["value"]
                mail    =  elem/"//b"
                from    = mail.shift.inner_html
                subject = mail.shift.inner_html
                new_seen[uid] = true
                #チャットは無視する
                next if @seen.key?(uid) or subject =~ /チャット/
                m2 = Jabber::Message.new("#{MAIL_ACCOUNT}@gmail.com", "#{subject} from:#{from} http://gmail.com")
                m2.type = :chat
                @bot.send(m2)
              end
              @seen = new_seen
              #CHECK_INTERVAL間スリーぷするデフォルト60秒
              sleep CHECK_INTERVAL

            }
          }
        rescue StandardError => e
            error_log_file.write(e)
            error_log_file.close
        end
      end
    end
  end
end

if $0 == __FILE__
  include Google
  case ARGV.shift
  when 'start'
    Google::Mail::Notifier.new.start
  when 'stop'
    `kill -9 \`cat #{Google::Mail::Notifier::PID_FILE} \``
  when 'restart'
    `kill -9 \`cat #{Google::Mail::Notifier::PID_FILE} \``
    Google::Mail::Notifier.new.start
  else
    puts "Usage: #{$0} {start|stop|restart}"
  end
end