bxdxmx3

きじれてじろあ なきがせすで あぷせとねでぶ

BOT作ったよ。

rubyの勉強がてらにお天気BOT作ったよ。
既存のとほとんど同じの。
だから公開しないけど。


こんな感じ
(最高気温が最大気温とかなってるけど・・・)
f:id:eo-oe-aaaa:20100913215136p:image

sourceだけ書いておこう。

version

1.9.2

main.rb

# coding : utf-8

require "twitter"
require_relative 'otenki'

Thread.abort_on_exception = true

ckey = "コンシューマーキー"
csec = "コンシューマーシックレット"

atoken="アクセストークン"
asecret="アクセスシークレット"

oauth = Twitter::OAuth.new(ckey,csec)
oauth.authorize_from_access(atoken, asecret)

tw = Twitter::Base.new(oauth)

tenki = Otenki.new(tw)
tenki.otenki

puts "終了したい場合は何かキーを押してね"
gets

tenki.finish

otenki.rb

# coding : utf-8

require "thread"
require "open-uri"
require "rexml/document"

class Otenki

  def initialize( tw )
    @tw = tw
    @finished = false
    @area_id_pair = {:北海道=>"4", :稚内=>"1", :旭川=>"2", :留萌=>"3", :札幌=>"4", :岩見沢=>"5", :倶知安=>"6", :網走=>"7", :北見=>"8", :紋別=>"9", :根室=>"10", :釧路=>"11", :帯広=>"12", :室蘭=>"13", :浦河=>"14", :函館=>"15", :江差=>"16", :青森=>"17", :むつ=>"18", :八戸=>"19", :秋田=>"20", :横手=>"21", :岩手=>"22", :盛岡=>"22", :宮古=>"23", :大船渡=>"24", :宮城=>"25", :仙台=>"25", :白石=>"26", :山形=>"27", :米沢=>"28", :酒田=>"29", :新庄=>"30", :福島=>"31", :小名浜=>"32", :若松=>"33", :茨城=>"54", :水戸=>"54", :土浦=>"55", :栃木=>"56", :宇都宮=>"56", :大田原=>"57", :群馬=>"58", :前橋=>"58", :みなかみ=>"59", :埼玉=>"60", :さいたま=>"60", :熊谷=>"61", :秩父=>"62", :東京=>"63", :大島=>"64", :八丈島=>"65", :父島=>"66", :千葉=>"67", :銚子=>"68", :館山=>"69", :神奈川=>"70", :横浜=>"70", :小田原=>"71", :山梨=>"75", :甲府=>"75", :河口湖=>"76", :富山=>"44", :伏木=>"45", :石川=>"46", :金沢=>"46", :輪島=>"47", :福井=>"48", :敦賀=>"49", :新潟=>"50", :長岡=>"51", :高田=>"52", :相川=>"53", :長野=>"72", :松本=>"73", :飯田=>"74", :静岡=>"34", :網代=>"35", :三島=>"36", :浜松=>"37", :愛知=>"38", :名古屋=>"38", :豊橋=>"39", :岐阜=>"40", :高山=>"41", :三重=>"42", :津=>"42", :尾鷲=>"43", :滋賀=>"77", :大津=>"77", :彦根=>"78", :京都=>"79", :舞鶴=>"80", :大阪=>"81", :兵庫=>"82", :神戸=>"82", :豊岡=>"83", :奈良=>"84", :風屋=>"85", :和歌山=>"86", :潮岬=>"87", :岡山=>"88", :津山=>"89", :広島=>"90", :庄原=>"91", :島根=>"92", :松江=>"92", :浜田=>"93", :西郷=>"94", :鳥取=>"95", :米子=>"96", :下関=>"97", :山口=>"98", :柳井=>"99", :萩=>"100", :徳島=>"101", :日和佐=>"102", :香川=>"103", :高松=>"103", :愛媛=>"104", :松山=>"104", :新居浜=>"105", :宇和島=>"106", :高知=>"107", :室戸=>"108", :清水=>"109", :福岡=>"110", :八幡=>"111", :飯塚=>"112", :久留米=>"113", :大分=>"114", :中津=>"115", :日田=>"116", :佐伯=>"117", :長崎=>"118", :佐世保=>"119", :厳原=>"120", :福江=>"121", :佐賀=>"122", :伊万里=>"123", :熊本=>"124", :阿蘇乙姫=>"125", :牛深=>"126", :人吉=>"127", :宮崎=>"128", :延岡=>"129", :都城=>"130", :高千穂=>"131", :鹿児島=>"132", :鹿屋=>"133", :種子島=>"134", :名瀬=>"135", :沖縄=>"136", :那覇=>"136", :名護=>"137", :久米島=>"138", :南大東島=>"139", :宮古島=>"140", :石垣島=>"141", :与那国島=>"142"}
    @day_id_pair = {
      :今日 => "today",
      :きょう => "today",
      :本日 => "today",
      :明日 => "tomorrow",
      :あした => "tomorrow",
      :あす => "tomorrow",
      :みょうにち => "tomorrow",
      :明後日 => "dayaftertomorrow",
      :あさって => "dayaftertomorrow",
      :みょうごにち => "dayaftertomorrow"
    }
  end

  def otenki
    target_id_from = get_most_new_mention_id || 0

    @t = Thread.start do
      loop do
        break if @finished

        mentions = get_target_mentions(target_id_from)

        if mentions.length != 0 then
          reply_otenki mentions
          target_id_from = mentions[0].id
        end

        sleep 60

      end
    end
  end

  def reply_otenki( mentions)
    mentions.reverse.each do |m|
      user_mension_text = m.text

      area = get_area_from_text(user_mension_text)

      unless area then
        reply_message(m,"対応していない地名です。")
        next
      end

      day = get_day_from_text(user_mension_text) || @day_id_pair[:today]

      otenki_message = create_otenki_message(area, day)
      reply_message(m,otenki_message)
    end
  end

  def get_area_from_text( text )
    get_key_from_text(@area_id_pair, text)
  end

  def get_day_from_text(text)
    get_key_from_text(@day_id_pair, text)
  end

  def get_key_from_text(pair,text)
    pair.keys.each do |key|
      if text[/#{key}/] then
        return key
      end
    end
    nil
  end

  def create_otenki_message(area, day)
    area_id = @area_id_pair[area]
    day_id = @day_id_pair[day]

    return if area_id == nil || day_id == nil
    
    doc = open("http://weather.livedoor.com/forecast/webservice/rest/v1?city=#{area_id}&day=#{day_id}") do |f|
      REXML::Document.new f.read
    end

#    city = doc.elements["//location"].attributes["city"]
    max = doc.elements["//temperature/max/celsius"].text
    min = doc.elements["//temperature/min/celsius"].text

    "#{day}#{area}の最高気温は#{max}度、最低気温は#{mix}度です。"

  def get_target_mentions(since_id, count = 200)
    @tw.mentions( :since_id => since_id, :count => count)
  end

  def get_most_new_mention_id
    mentions = @tw.mentions( :count => 1)
    return nil if mentions.length != 0
    mentions[0].id
  end

  def reply_message(m, s)
    @tw.update("@#{m.user.name} #{s}", :in_reply_to_status_id => m.id )
  end

  def finish
    @finished = true
    @t.join if @t

    puts "finish"
  end

end

追記

作り終わってから気付いたけど、
weatherhacksのgemがあるのか・・・