rbot 0.9.10 → 0.9.12
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +22 -4
- data/COPYING +5 -18
- data/ChangeLog +396 -0
- data/README +23 -25
- data/REQUIREMENTS +58 -12
- data/Rakefile +215 -0
- data/bin/rbot +47 -25
- data/bin/rbot-remote +76 -0
- data/data/rbot/languages/french.lang +5 -5
- data/data/rbot/languages/german.lang +4 -4
- data/data/rbot/languages/italian.lang +53 -0
- data/data/rbot/languages/japanese.lang +43 -0
- data/data/rbot/languages/russian.lang +60 -60
- data/data/rbot/languages/traditional_chinese.lang +75 -0
- data/data/rbot/plugins/alias.rb +192 -0
- data/data/rbot/plugins/autoop.rb +74 -37
- data/data/rbot/plugins/autorejoin.rb +15 -5
- data/data/rbot/plugins/bans.rb +454 -150
- data/data/rbot/plugins/bash.rb +173 -31
- data/data/rbot/plugins/botsnack.rb +37 -0
- data/data/rbot/plugins/cal.rb +11 -2
- data/data/rbot/plugins/chanserv.rb +132 -0
- data/data/rbot/plugins/chucknorris.rb +2 -2
- data/data/rbot/plugins/chucknorris.yml.gz +0 -0
- data/data/rbot/plugins/debugger.rb +136 -0
- data/data/rbot/plugins/deepthoughts.rb +89 -95
- data/data/rbot/plugins/delicious.rb +109 -0
- data/data/rbot/plugins/dice.rb +77 -25
- data/data/rbot/plugins/dict.rb +243 -0
- data/data/rbot/plugins/dictclient.rb +211 -0
- data/data/rbot/plugins/digg.rb +2 -2
- data/data/rbot/plugins/excuse.rb +4 -4
- data/data/rbot/plugins/factoids.rb +506 -0
- data/data/rbot/plugins/figlet.rb +127 -18
- data/data/rbot/plugins/fish.rb +93 -33
- data/data/rbot/plugins/forecast.rb +40 -27
- data/data/rbot/plugins/fortune.rb +86 -11
- data/data/rbot/plugins/freshmeat.rb +46 -12
- data/data/rbot/plugins/games/azgame.rb +565 -0
- data/data/rbot/plugins/games/quiz.rb +961 -0
- data/data/rbot/plugins/games/roshambo.rb +62 -0
- data/data/rbot/plugins/{roulette.rb → games/roulette.rb} +58 -8
- data/data/rbot/plugins/games/shiritori.rb +485 -0
- data/data/rbot/plugins/games/uno.rb +1205 -0
- data/data/rbot/plugins/games/wheelfortune.rb +615 -0
- data/data/rbot/plugins/grouphug.rb +76 -22
- data/data/rbot/plugins/hl2.rb +97 -0
- data/data/rbot/plugins/host.rb +10 -1
- data/data/rbot/plugins/httpd.rb.disabled +1 -0
- data/data/rbot/plugins/imdb.rb +511 -47
- data/data/rbot/plugins/insult.rb +32 -37
- data/data/rbot/plugins/iplookup.rb +224 -224
- data/data/rbot/plugins/karma.rb +45 -21
- data/data/rbot/plugins/keywords.rb +258 -160
- data/data/rbot/plugins/lart.rb +126 -95
- data/data/rbot/plugins/lastfm.rb +421 -12
- data/data/rbot/plugins/linkbot.rb +75 -0
- data/data/rbot/plugins/markov.rb +103 -46
- data/data/rbot/plugins/math.rb +6 -5
- data/data/rbot/plugins/modes.rb +114 -0
- data/data/rbot/plugins/nickrecover.rb +97 -0
- data/data/rbot/plugins/nickserv.rb +111 -48
- data/data/rbot/plugins/nslookup.rb +15 -19
- data/data/rbot/plugins/plugin.header +11 -0
- data/data/rbot/plugins/quakeauth.rb +74 -11
- data/data/rbot/plugins/quotes.rb +189 -233
- data/data/rbot/plugins/reaction.rb +415 -0
- data/data/rbot/plugins/remind.rb +11 -15
- data/data/rbot/plugins/remotectl.rb +29 -0
- data/data/rbot/plugins/ri.rb +74 -0
- data/data/rbot/plugins/rot13.rb +16 -1
- data/data/rbot/plugins/rss.rb +1219 -585
- data/data/rbot/plugins/salut.rb +226 -0
- data/data/rbot/plugins/script.rb +184 -0
- data/data/rbot/plugins/search.rb +233 -0
- data/data/rbot/plugins/seen.rb +44 -40
- data/data/rbot/plugins/shortenurls.rb +93 -0
- data/data/rbot/plugins/slashdot.rb +49 -11
- data/data/rbot/plugins/spell.rb +37 -27
- data/data/rbot/plugins/theyfightcrime.rb +36 -39
- data/data/rbot/plugins/threat.rb +25 -22
- data/data/rbot/plugins/time.rb +135 -0
- data/data/rbot/plugins/topic.rb +107 -50
- data/data/rbot/plugins/translator.rb +360 -0
- data/data/rbot/plugins/tube.rb +28 -40
- data/data/rbot/plugins/twitter.rb +187 -0
- data/data/rbot/plugins/urban.rb +62 -53
- data/data/rbot/plugins/url.rb +193 -409
- data/data/rbot/plugins/usermodes.rb +26 -0
- data/data/rbot/plugins/wall.rb +60 -0
- data/data/rbot/plugins/weather.rb +254 -598
- data/data/rbot/plugins/wow.rb +41 -37
- data/data/rbot/plugins/wserver.rb +17 -25
- data/data/rbot/plugins/youtube.rb +237 -0
- data/data/rbot/templates/lart/{larts → larts-english} +0 -0
- data/data/rbot/templates/lart/larts-italian +25 -0
- data/data/rbot/templates/lart/larts-japanese +10 -0
- data/data/rbot/templates/lart/{praises → praises-english} +0 -0
- data/data/rbot/templates/lart/praises-italian +4 -0
- data/data/rbot/templates/lart/praises-japanese +3 -0
- data/data/rbot/templates/quiz/win_messages +11 -0
- data/data/rbot/templates/salut/salut-english +40 -0
- data/data/rbot/templates/salut/salut-french +29 -0
- data/data/rbot/templates/salut/salut-italian +51 -0
- data/data/rbot/templates/salut/salut-japanese +31 -0
- data/lib/rbot/botuser.rb +940 -0
- data/lib/rbot/config-compat.rb +23 -0
- data/lib/rbot/config.rb +211 -276
- data/lib/rbot/core/auth.rb +1063 -0
- data/lib/rbot/core/basics.rb +214 -0
- data/lib/rbot/core/config.rb +330 -0
- data/lib/rbot/core/filters_ui.rb +64 -0
- data/lib/rbot/core/irclog.rb +292 -0
- data/lib/rbot/core/remote.rb +401 -0
- data/lib/rbot/core/unicode.rb +91 -0
- data/lib/rbot/core/userdata.rb +200 -0
- data/lib/rbot/core/utils/extends.rb +444 -0
- data/lib/rbot/core/utils/filters.rb +154 -0
- data/lib/rbot/core/utils/httputil.rb +689 -0
- data/lib/rbot/core/utils/utils.rb +717 -0
- data/lib/rbot/dbhash.rb +30 -9
- data/lib/rbot/irc.rb +1966 -0
- data/lib/rbot/ircbot.rb +816 -675
- data/lib/rbot/ircsocket.rb +246 -232
- data/lib/rbot/language.rb +86 -8
- data/lib/rbot/load-gettext.rb +154 -0
- data/lib/rbot/maskdb.rb +162 -0
- data/lib/rbot/message.rb +392 -65
- data/lib/rbot/messagemapper.rb +438 -94
- data/lib/rbot/pkgconfig.rb +6 -0
- data/lib/rbot/plugins.rb +713 -172
- data/lib/rbot/post-config.rb +1 -0
- data/lib/rbot/rbotconfig.rb +31 -12
- data/lib/rbot/registry.rb +79 -48
- data/lib/rbot/rfc2812.rb +927 -519
- data/lib/rbot/timer.rb +232 -167
- data/po/en_US/rbot-alias.po +82 -0
- data/po/en_US/rbot-autoop.po +0 -0
- data/po/en_US/rbot-autorejoin.po +0 -0
- data/po/en_US/rbot-azgame.po +200 -0
- data/po/en_US/rbot-bans.po +0 -0
- data/po/en_US/rbot-bash.po +0 -0
- data/po/en_US/rbot-botsnack.po +0 -0
- data/po/en_US/rbot-cal.po +3 -0
- data/po/en_US/rbot-chanserv.po +0 -0
- data/po/en_US/rbot-chucknorris.po +0 -0
- data/po/en_US/rbot-debugger.po +0 -0
- data/po/en_US/rbot-deepthoughts.po +0 -0
- data/po/en_US/rbot-delicious.po +0 -0
- data/po/en_US/rbot-dice.po +0 -0
- data/po/en_US/rbot-dict.po +0 -0
- data/po/en_US/rbot-dictclient.po +124 -0
- data/po/en_US/rbot-digg.po +0 -0
- data/po/en_US/rbot-eightball.po +0 -0
- data/po/en_US/rbot-excuse.po +0 -0
- data/po/en_US/rbot-factoids.po +107 -0
- data/po/en_US/rbot-figlet.po +36 -0
- data/po/en_US/rbot-fish.po +0 -0
- data/po/en_US/rbot-forecast.po +0 -0
- data/po/en_US/rbot-fortune.po +0 -0
- data/po/en_US/rbot-freshmeat.po +0 -0
- data/po/en_US/rbot-grouphug.po +18 -0
- data/po/en_US/rbot-hl2.po +0 -0
- data/po/en_US/rbot-host.po +3 -0
- data/po/en_US/rbot-imdb.po +0 -0
- data/po/en_US/rbot-insult.po +0 -0
- data/po/en_US/rbot-iplookup.po +0 -0
- data/po/en_US/rbot-karma.po +0 -0
- data/po/en_US/rbot-keywords.po +24 -0
- data/po/en_US/rbot-lart.po +0 -0
- data/po/en_US/rbot-lastfm.po +172 -0
- data/po/en_US/rbot-linkbot.po +0 -0
- data/po/en_US/rbot-markov.po +20 -0
- data/po/en_US/rbot-math.po +0 -0
- data/po/en_US/rbot-modes.po +0 -0
- data/po/en_US/rbot-nickrecover.po +40 -0
- data/po/en_US/rbot-nickserv.po +104 -0
- data/po/en_US/rbot-nslookup.po +0 -0
- data/po/en_US/rbot-quakeauth.po +0 -0
- data/po/en_US/rbot-quiz.po +0 -0
- data/po/en_US/rbot-quotes.po +108 -0
- data/po/en_US/rbot-reaction.po +0 -0
- data/po/en_US/rbot-remind.po +0 -0
- data/po/en_US/rbot-remotectl.po +0 -0
- data/po/en_US/rbot-ri.po +0 -0
- data/po/en_US/rbot-roshambo.po +0 -0
- data/po/en_US/rbot-rot13.po +0 -0
- data/po/en_US/rbot-roulette.po +0 -0
- data/po/en_US/rbot-rss.po +20 -0
- data/po/en_US/rbot-salut.po +0 -0
- data/po/en_US/rbot-script.po +0 -0
- data/po/en_US/rbot-search.po +0 -0
- data/po/en_US/rbot-seen.po +0 -0
- data/po/en_US/rbot-shiritori.po +113 -0
- data/po/en_US/rbot-shortenurls.po +0 -0
- data/po/en_US/rbot-slashdot.po +0 -0
- data/po/en_US/rbot-spell.po +54 -0
- data/po/en_US/rbot-theyfightcrime.po +0 -0
- data/po/en_US/rbot-threat.po +0 -0
- data/po/en_US/rbot-time.po +0 -0
- data/po/en_US/rbot-topic.po +0 -0
- data/po/en_US/rbot-translator.po +77 -0
- data/po/en_US/rbot-tube.po +0 -0
- data/po/en_US/rbot-twitter.po +24 -0
- data/po/en_US/rbot-uno.po +512 -0
- data/po/en_US/rbot-urban.po +0 -0
- data/po/en_US/rbot-url.po +0 -0
- data/po/en_US/rbot-usermodes.po +0 -0
- data/po/en_US/rbot-wall.po +33 -0
- data/po/en_US/rbot-weather.po +0 -0
- data/po/en_US/rbot-wheelfortune.po +205 -0
- data/po/en_US/rbot-wow.po +0 -0
- data/po/en_US/rbot-wserver.po +0 -0
- data/po/en_US/rbot-youtube.po +58 -0
- data/po/en_US/rbot.po +1097 -0
- data/po/fr/rbot-alias.po +97 -0
- data/po/fr/rbot-autoop.po +0 -0
- data/po/fr/rbot-autorejoin.po +0 -0
- data/po/fr/rbot-azgame.po +204 -0
- data/po/fr/rbot-bans.po +0 -0
- data/po/fr/rbot-bash.po +0 -0
- data/po/fr/rbot-botsnack.po +0 -0
- data/po/fr/rbot-cal.po +3 -0
- data/po/fr/rbot-chanserv.po +0 -0
- data/po/fr/rbot-chucknorris.po +0 -0
- data/po/fr/rbot-debugger.po +0 -0
- data/po/fr/rbot-deepthoughts.po +0 -0
- data/po/fr/rbot-delicious.po +0 -0
- data/po/fr/rbot-dice.po +0 -0
- data/po/fr/rbot-dict.po +0 -0
- data/po/fr/rbot-dictclient.po +134 -0
- data/po/fr/rbot-digg.po +0 -0
- data/po/fr/rbot-eightball.po +0 -0
- data/po/fr/rbot-excuse.po +0 -0
- data/po/fr/rbot-factoids.po +111 -0
- data/po/fr/rbot-figlet.po +37 -0
- data/po/fr/rbot-fish.po +0 -0
- data/po/fr/rbot-forecast.po +0 -0
- data/po/fr/rbot-fortune.po +0 -0
- data/po/fr/rbot-freshmeat.po +0 -0
- data/po/fr/rbot-grouphug.po +18 -0
- data/po/fr/rbot-hl2.po +0 -0
- data/po/fr/rbot-host.po +3 -0
- data/po/fr/rbot-imdb.po +0 -0
- data/po/fr/rbot-insult.po +0 -0
- data/po/fr/rbot-iplookup.po +0 -0
- data/po/fr/rbot-karma.po +0 -0
- data/po/fr/rbot-keywords.po +24 -0
- data/po/fr/rbot-lart.po +0 -0
- data/po/fr/rbot-lastfm.po +172 -0
- data/po/fr/rbot-linkbot.po +0 -0
- data/po/fr/rbot-markov.po +20 -0
- data/po/fr/rbot-math.po +0 -0
- data/po/fr/rbot-modes.po +0 -0
- data/po/fr/rbot-nickrecover.po +36 -0
- data/po/fr/rbot-nickserv.po +116 -0
- data/po/fr/rbot-nslookup.po +0 -0
- data/po/fr/rbot-quakeauth.po +0 -0
- data/po/fr/rbot-quiz.po +0 -0
- data/po/fr/rbot-quotes.po +138 -0
- data/po/fr/rbot-reaction.po +0 -0
- data/po/fr/rbot-remind.po +0 -0
- data/po/fr/rbot-remotectl.po +0 -0
- data/po/fr/rbot-ri.po +0 -0
- data/po/fr/rbot-roshambo.po +0 -0
- data/po/fr/rbot-rot13.po +0 -0
- data/po/fr/rbot-roulette.po +0 -0
- data/po/fr/rbot-rss.po +20 -0
- data/po/fr/rbot-salut.po +0 -0
- data/po/fr/rbot-script.po +0 -0
- data/po/fr/rbot-search.po +0 -0
- data/po/fr/rbot-seen.po +0 -0
- data/po/fr/rbot-shiritori.po +119 -0
- data/po/fr/rbot-shortenurls.po +0 -0
- data/po/fr/rbot-slashdot.po +0 -0
- data/po/fr/rbot-spell.po +56 -0
- data/po/fr/rbot-theyfightcrime.po +0 -0
- data/po/fr/rbot-threat.po +0 -0
- data/po/fr/rbot-time.po +0 -0
- data/po/fr/rbot-topic.po +0 -0
- data/po/fr/rbot-translator.po +90 -0
- data/po/fr/rbot-tube.po +0 -0
- data/po/fr/rbot-twitter.po +24 -0
- data/po/fr/rbot-uno.po +521 -0
- data/po/fr/rbot-urban.po +0 -0
- data/po/fr/rbot-url.po +0 -0
- data/po/fr/rbot-usermodes.po +0 -0
- data/po/fr/rbot-wall.po +33 -0
- data/po/fr/rbot-weather.po +0 -0
- data/po/fr/rbot-wheelfortune.po +255 -0
- data/po/fr/rbot-wow.po +0 -0
- data/po/fr/rbot-wserver.po +0 -0
- data/po/fr/rbot-youtube.po +64 -0
- data/po/fr/rbot.po +1133 -0
- data/po/it/rbot-alias.po +82 -0
- data/po/it/rbot-autoop.po +0 -0
- data/po/it/rbot-autorejoin.po +0 -0
- data/po/it/rbot-azgame.po +186 -0
- data/po/it/rbot-bans.po +0 -0
- data/po/it/rbot-bash.po +0 -0
- data/po/it/rbot-botsnack.po +0 -0
- data/po/it/rbot-cal.po +3 -0
- data/po/it/rbot-chanserv.po +0 -0
- data/po/it/rbot-chucknorris.po +0 -0
- data/po/it/rbot-debugger.po +0 -0
- data/po/it/rbot-deepthoughts.po +0 -0
- data/po/it/rbot-delicious.po +0 -0
- data/po/it/rbot-dice.po +0 -0
- data/po/it/rbot-dict.po +0 -0
- data/po/it/rbot-dictclient.po +111 -0
- data/po/it/rbot-digg.po +0 -0
- data/po/it/rbot-eightball.po +0 -0
- data/po/it/rbot-excuse.po +0 -0
- data/po/it/rbot-factoids.po +110 -0
- data/po/it/rbot-figlet.po +36 -0
- data/po/it/rbot-fish.po +0 -0
- data/po/it/rbot-forecast.po +0 -0
- data/po/it/rbot-fortune.po +0 -0
- data/po/it/rbot-freshmeat.po +0 -0
- data/po/it/rbot-grouphug.po +18 -0
- data/po/it/rbot-hl2.po +0 -0
- data/po/it/rbot-host.po +3 -0
- data/po/it/rbot-imdb.po +0 -0
- data/po/it/rbot-insult.po +0 -0
- data/po/it/rbot-iplookup.po +0 -0
- data/po/it/rbot-karma.po +0 -0
- data/po/it/rbot-keywords.po +24 -0
- data/po/it/rbot-lart.po +0 -0
- data/po/it/rbot-lastfm.po +172 -0
- data/po/it/rbot-linkbot.po +0 -0
- data/po/it/rbot-markov.po +20 -0
- data/po/it/rbot-math.po +0 -0
- data/po/it/rbot-modes.po +0 -0
- data/po/it/rbot-nickrecover.po +36 -0
- data/po/it/rbot-nickserv.po +104 -0
- data/po/it/rbot-nslookup.po +0 -0
- data/po/it/rbot-quakeauth.po +0 -0
- data/po/it/rbot-quiz.po +0 -0
- data/po/it/rbot-quotes.po +108 -0
- data/po/it/rbot-reaction.po +0 -0
- data/po/it/rbot-remind.po +0 -0
- data/po/it/rbot-remotectl.po +0 -0
- data/po/it/rbot-ri.po +0 -0
- data/po/it/rbot-roshambo.po +0 -0
- data/po/it/rbot-rot13.po +0 -0
- data/po/it/rbot-roulette.po +0 -0
- data/po/it/rbot-rss.po +20 -0
- data/po/it/rbot-salut.po +0 -0
- data/po/it/rbot-script.po +0 -0
- data/po/it/rbot-search.po +0 -0
- data/po/it/rbot-seen.po +0 -0
- data/po/it/rbot-shiritori.po +102 -0
- data/po/it/rbot-shortenurls.po +0 -0
- data/po/it/rbot-slashdot.po +0 -0
- data/po/it/rbot-spell.po +54 -0
- data/po/it/rbot-theyfightcrime.po +0 -0
- data/po/it/rbot-threat.po +0 -0
- data/po/it/rbot-time.po +0 -0
- data/po/it/rbot-topic.po +0 -0
- data/po/it/rbot-translator.po +77 -0
- data/po/it/rbot-tube.po +0 -0
- data/po/it/rbot-twitter.po +24 -0
- data/po/it/rbot-uno.po +564 -0
- data/po/it/rbot-urban.po +0 -0
- data/po/it/rbot-url.po +0 -0
- data/po/it/rbot-usermodes.po +0 -0
- data/po/it/rbot-wall.po +33 -0
- data/po/it/rbot-weather.po +0 -0
- data/po/it/rbot-wheelfortune.po +251 -0
- data/po/it/rbot-wow.po +0 -0
- data/po/it/rbot-wserver.po +0 -0
- data/po/it/rbot-youtube.po +64 -0
- data/po/it/rbot.po +1127 -0
- data/po/ja/rbot-alias.po +82 -0
- data/po/ja/rbot-autoop.po +0 -0
- data/po/ja/rbot-autorejoin.po +0 -0
- data/po/ja/rbot-azgame.po +194 -0
- data/po/ja/rbot-bans.po +0 -0
- data/po/ja/rbot-bash.po +0 -0
- data/po/ja/rbot-botsnack.po +0 -0
- data/po/ja/rbot-cal.po +3 -0
- data/po/ja/rbot-chanserv.po +0 -0
- data/po/ja/rbot-chucknorris.po +0 -0
- data/po/ja/rbot-debugger.po +0 -0
- data/po/ja/rbot-deepthoughts.po +0 -0
- data/po/ja/rbot-delicious.po +0 -0
- data/po/ja/rbot-dice.po +0 -0
- data/po/ja/rbot-dict.po +0 -0
- data/po/ja/rbot-dictclient.po +111 -0
- data/po/ja/rbot-digg.po +0 -0
- data/po/ja/rbot-eightball.po +0 -0
- data/po/ja/rbot-excuse.po +0 -0
- data/po/ja/rbot-factoids.po +107 -0
- data/po/ja/rbot-figlet.po +36 -0
- data/po/ja/rbot-fish.po +0 -0
- data/po/ja/rbot-forecast.po +0 -0
- data/po/ja/rbot-fortune.po +0 -0
- data/po/ja/rbot-freshmeat.po +0 -0
- data/po/ja/rbot-grouphug.po +18 -0
- data/po/ja/rbot-hl2.po +0 -0
- data/po/ja/rbot-host.po +3 -0
- data/po/ja/rbot-imdb.po +0 -0
- data/po/ja/rbot-insult.po +0 -0
- data/po/ja/rbot-iplookup.po +0 -0
- data/po/ja/rbot-karma.po +0 -0
- data/po/ja/rbot-keywords.po +24 -0
- data/po/ja/rbot-lart.po +0 -0
- data/po/ja/rbot-lastfm.po +172 -0
- data/po/ja/rbot-linkbot.po +0 -0
- data/po/ja/rbot-markov.po +20 -0
- data/po/ja/rbot-math.po +0 -0
- data/po/ja/rbot-modes.po +0 -0
- data/po/ja/rbot-nickrecover.po +36 -0
- data/po/ja/rbot-nickserv.po +104 -0
- data/po/ja/rbot-nslookup.po +0 -0
- data/po/ja/rbot-quakeauth.po +0 -0
- data/po/ja/rbot-quiz.po +0 -0
- data/po/ja/rbot-quotes.po +108 -0
- data/po/ja/rbot-reaction.po +0 -0
- data/po/ja/rbot-remind.po +0 -0
- data/po/ja/rbot-remotectl.po +0 -0
- data/po/ja/rbot-ri.po +0 -0
- data/po/ja/rbot-roshambo.po +0 -0
- data/po/ja/rbot-rot13.po +0 -0
- data/po/ja/rbot-roulette.po +0 -0
- data/po/ja/rbot-rss.po +20 -0
- data/po/ja/rbot-salut.po +0 -0
- data/po/ja/rbot-script.po +0 -0
- data/po/ja/rbot-search.po +0 -0
- data/po/ja/rbot-seen.po +0 -0
- data/po/ja/rbot-shiritori.po +115 -0
- data/po/ja/rbot-shortenurls.po +0 -0
- data/po/ja/rbot-slashdot.po +0 -0
- data/po/ja/rbot-spell.po +54 -0
- data/po/ja/rbot-theyfightcrime.po +0 -0
- data/po/ja/rbot-threat.po +0 -0
- data/po/ja/rbot-time.po +0 -0
- data/po/ja/rbot-topic.po +0 -0
- data/po/ja/rbot-translator.po +77 -0
- data/po/ja/rbot-tube.po +0 -0
- data/po/ja/rbot-twitter.po +24 -0
- data/po/ja/rbot-uno.po +512 -0
- data/po/ja/rbot-urban.po +0 -0
- data/po/ja/rbot-url.po +0 -0
- data/po/ja/rbot-usermodes.po +0 -0
- data/po/ja/rbot-wall.po +33 -0
- data/po/ja/rbot-weather.po +0 -0
- data/po/ja/rbot-wheelfortune.po +205 -0
- data/po/ja/rbot-wow.po +0 -0
- data/po/ja/rbot-wserver.po +0 -0
- data/po/ja/rbot-youtube.po +58 -0
- data/po/ja/rbot.po +999 -0
- data/po/rbot-alias.pot +83 -0
- data/po/rbot-autoop.pot +0 -0
- data/po/rbot-autorejoin.pot +0 -0
- data/po/rbot-azgame.pot +187 -0
- data/po/rbot-bans.pot +0 -0
- data/po/rbot-bash.pot +0 -0
- data/po/rbot-botsnack.pot +0 -0
- data/po/rbot-cal.pot +21 -0
- data/po/rbot-chanserv.pot +0 -0
- data/po/rbot-chucknorris.pot +0 -0
- data/po/rbot-debugger.pot +0 -0
- data/po/rbot-deepthoughts.pot +0 -0
- data/po/rbot-delicious.pot +0 -0
- data/po/rbot-dice.pot +0 -0
- data/po/rbot-dict.pot +0 -0
- data/po/rbot-dictclient.pot +112 -0
- data/po/rbot-digg.pot +0 -0
- data/po/rbot-eightball.pot +0 -0
- data/po/rbot-excuse.pot +0 -0
- data/po/rbot-factoids.pot +108 -0
- data/po/rbot-figlet.pot +37 -0
- data/po/rbot-fish.pot +0 -0
- data/po/rbot-forecast.pot +0 -0
- data/po/rbot-fortune.pot +0 -0
- data/po/rbot-freshmeat.pot +0 -0
- data/po/rbot-grouphug.pot +36 -0
- data/po/rbot-hl2.pot +0 -0
- data/po/rbot-host.pot +21 -0
- data/po/rbot-imdb.pot +0 -0
- data/po/rbot-insult.pot +0 -0
- data/po/rbot-iplookup.pot +0 -0
- data/po/rbot-karma.pot +0 -0
- data/po/rbot-keywords.pot +25 -0
- data/po/rbot-lart.pot +0 -0
- data/po/rbot-lastfm.pot +190 -0
- data/po/rbot-linkbot.pot +0 -0
- data/po/rbot-markov.pot +21 -0
- data/po/rbot-math.pot +0 -0
- data/po/rbot-modes.pot +0 -0
- data/po/rbot-nickrecover.pot +37 -0
- data/po/rbot-nickserv.pot +105 -0
- data/po/rbot-nslookup.pot +0 -0
- data/po/rbot-quakeauth.pot +0 -0
- data/po/rbot-quiz.pot +0 -0
- data/po/rbot-quotes.pot +109 -0
- data/po/rbot-reaction.pot +0 -0
- data/po/rbot-remind.pot +0 -0
- data/po/rbot-remotectl.pot +0 -0
- data/po/rbot-ri.pot +0 -0
- data/po/rbot-roshambo.pot +0 -0
- data/po/rbot-rot13.pot +0 -0
- data/po/rbot-roulette.pot +0 -0
- data/po/rbot-rss.pot +21 -0
- data/po/rbot-salut.pot +0 -0
- data/po/rbot-script.pot +0 -0
- data/po/rbot-search.pot +0 -0
- data/po/rbot-seen.pot +0 -0
- data/po/rbot-shiritori.pot +103 -0
- data/po/rbot-shortenurls.pot +0 -0
- data/po/rbot-slashdot.pot +0 -0
- data/po/rbot-spell.pot +55 -0
- data/po/rbot-theyfightcrime.pot +0 -0
- data/po/rbot-threat.pot +0 -0
- data/po/rbot-time.pot +0 -0
- data/po/rbot-topic.pot +0 -0
- data/po/rbot-translator.pot +78 -0
- data/po/rbot-tube.pot +0 -0
- data/po/rbot-twitter.pot +25 -0
- data/po/rbot-uno.pot +513 -0
- data/po/rbot-urban.pot +0 -0
- data/po/rbot-url.pot +0 -0
- data/po/rbot-usermodes.pot +0 -0
- data/po/rbot-wall.pot +33 -0
- data/po/rbot-weather.pot +0 -0
- data/po/rbot-wheelfortune.pot +206 -0
- data/po/rbot-wow.pot +0 -0
- data/po/rbot-wserver.pot +0 -0
- data/po/rbot-youtube.pot +59 -0
- data/po/rbot.pot +1004 -0
- data/po/zh_CN/rbot-alias.po +82 -0
- data/po/zh_CN/rbot-autoop.po +0 -0
- data/po/zh_CN/rbot-autorejoin.po +0 -0
- data/po/zh_CN/rbot-azgame.po +186 -0
- data/po/zh_CN/rbot-bans.po +0 -0
- data/po/zh_CN/rbot-bash.po +0 -0
- data/po/zh_CN/rbot-botsnack.po +0 -0
- data/po/zh_CN/rbot-cal.po +3 -0
- data/po/zh_CN/rbot-chanserv.po +0 -0
- data/po/zh_CN/rbot-chucknorris.po +0 -0
- data/po/zh_CN/rbot-debugger.po +0 -0
- data/po/zh_CN/rbot-deepthoughts.po +0 -0
- data/po/zh_CN/rbot-delicious.po +0 -0
- data/po/zh_CN/rbot-dice.po +0 -0
- data/po/zh_CN/rbot-dict.po +0 -0
- data/po/zh_CN/rbot-dictclient.po +111 -0
- data/po/zh_CN/rbot-digg.po +0 -0
- data/po/zh_CN/rbot-eightball.po +0 -0
- data/po/zh_CN/rbot-excuse.po +0 -0
- data/po/zh_CN/rbot-factoids.po +107 -0
- data/po/zh_CN/rbot-figlet.po +36 -0
- data/po/zh_CN/rbot-fish.po +0 -0
- data/po/zh_CN/rbot-forecast.po +0 -0
- data/po/zh_CN/rbot-fortune.po +0 -0
- data/po/zh_CN/rbot-freshmeat.po +0 -0
- data/po/zh_CN/rbot-grouphug.po +18 -0
- data/po/zh_CN/rbot-hl2.po +0 -0
- data/po/zh_CN/rbot-host.po +3 -0
- data/po/zh_CN/rbot-imdb.po +0 -0
- data/po/zh_CN/rbot-insult.po +0 -0
- data/po/zh_CN/rbot-iplookup.po +0 -0
- data/po/zh_CN/rbot-karma.po +0 -0
- data/po/zh_CN/rbot-keywords.po +24 -0
- data/po/zh_CN/rbot-lart.po +0 -0
- data/po/zh_CN/rbot-lastfm.po +172 -0
- data/po/zh_CN/rbot-linkbot.po +0 -0
- data/po/zh_CN/rbot-markov.po +20 -0
- data/po/zh_CN/rbot-math.po +0 -0
- data/po/zh_CN/rbot-modes.po +0 -0
- data/po/zh_CN/rbot-nickrecover.po +36 -0
- data/po/zh_CN/rbot-nickserv.po +104 -0
- data/po/zh_CN/rbot-nslookup.po +0 -0
- data/po/zh_CN/rbot-quakeauth.po +0 -0
- data/po/zh_CN/rbot-quiz.po +0 -0
- data/po/zh_CN/rbot-quotes.po +108 -0
- data/po/zh_CN/rbot-reaction.po +0 -0
- data/po/zh_CN/rbot-remind.po +0 -0
- data/po/zh_CN/rbot-remotectl.po +0 -0
- data/po/zh_CN/rbot-ri.po +0 -0
- data/po/zh_CN/rbot-roshambo.po +0 -0
- data/po/zh_CN/rbot-rot13.po +0 -0
- data/po/zh_CN/rbot-roulette.po +0 -0
- data/po/zh_CN/rbot-rss.po +20 -0
- data/po/zh_CN/rbot-salut.po +0 -0
- data/po/zh_CN/rbot-script.po +0 -0
- data/po/zh_CN/rbot-search.po +0 -0
- data/po/zh_CN/rbot-seen.po +0 -0
- data/po/zh_CN/rbot-shiritori.po +102 -0
- data/po/zh_CN/rbot-shortenurls.po +0 -0
- data/po/zh_CN/rbot-slashdot.po +0 -0
- data/po/zh_CN/rbot-spell.po +54 -0
- data/po/zh_CN/rbot-theyfightcrime.po +0 -0
- data/po/zh_CN/rbot-threat.po +0 -0
- data/po/zh_CN/rbot-time.po +0 -0
- data/po/zh_CN/rbot-topic.po +0 -0
- data/po/zh_CN/rbot-translator.po +77 -0
- data/po/zh_CN/rbot-tube.po +0 -0
- data/po/zh_CN/rbot-twitter.po +24 -0
- data/po/zh_CN/rbot-uno.po +512 -0
- data/po/zh_CN/rbot-urban.po +0 -0
- data/po/zh_CN/rbot-url.po +0 -0
- data/po/zh_CN/rbot-usermodes.po +0 -0
- data/po/zh_CN/rbot-wall.po +33 -0
- data/po/zh_CN/rbot-weather.po +0 -0
- data/po/zh_CN/rbot-wheelfortune.po +205 -0
- data/po/zh_CN/rbot-wow.po +0 -0
- data/po/zh_CN/rbot-wserver.po +0 -0
- data/po/zh_CN/rbot-youtube.po +58 -0
- data/po/zh_CN/rbot.po +1006 -0
- data/po/zh_TW/rbot-alias.po +82 -0
- data/po/zh_TW/rbot-autoop.po +0 -0
- data/po/zh_TW/rbot-autorejoin.po +0 -0
- data/po/zh_TW/rbot-azgame.po +186 -0
- data/po/zh_TW/rbot-bans.po +0 -0
- data/po/zh_TW/rbot-bash.po +0 -0
- data/po/zh_TW/rbot-botsnack.po +0 -0
- data/po/zh_TW/rbot-cal.po +3 -0
- data/po/zh_TW/rbot-chanserv.po +0 -0
- data/po/zh_TW/rbot-chucknorris.po +0 -0
- data/po/zh_TW/rbot-debugger.po +0 -0
- data/po/zh_TW/rbot-deepthoughts.po +0 -0
- data/po/zh_TW/rbot-delicious.po +0 -0
- data/po/zh_TW/rbot-dice.po +0 -0
- data/po/zh_TW/rbot-dict.po +0 -0
- data/po/zh_TW/rbot-dictclient.po +111 -0
- data/po/zh_TW/rbot-digg.po +0 -0
- data/po/zh_TW/rbot-eightball.po +0 -0
- data/po/zh_TW/rbot-excuse.po +0 -0
- data/po/zh_TW/rbot-factoids.po +107 -0
- data/po/zh_TW/rbot-figlet.po +36 -0
- data/po/zh_TW/rbot-fish.po +0 -0
- data/po/zh_TW/rbot-forecast.po +0 -0
- data/po/zh_TW/rbot-fortune.po +0 -0
- data/po/zh_TW/rbot-freshmeat.po +0 -0
- data/po/zh_TW/rbot-grouphug.po +18 -0
- data/po/zh_TW/rbot-hl2.po +0 -0
- data/po/zh_TW/rbot-host.po +3 -0
- data/po/zh_TW/rbot-imdb.po +0 -0
- data/po/zh_TW/rbot-insult.po +0 -0
- data/po/zh_TW/rbot-iplookup.po +0 -0
- data/po/zh_TW/rbot-karma.po +0 -0
- data/po/zh_TW/rbot-keywords.po +24 -0
- data/po/zh_TW/rbot-lart.po +0 -0
- data/po/zh_TW/rbot-lastfm.po +172 -0
- data/po/zh_TW/rbot-linkbot.po +0 -0
- data/po/zh_TW/rbot-markov.po +20 -0
- data/po/zh_TW/rbot-math.po +0 -0
- data/po/zh_TW/rbot-modes.po +0 -0
- data/po/zh_TW/rbot-nickrecover.po +36 -0
- data/po/zh_TW/rbot-nickserv.po +104 -0
- data/po/zh_TW/rbot-nslookup.po +0 -0
- data/po/zh_TW/rbot-quakeauth.po +0 -0
- data/po/zh_TW/rbot-quiz.po +0 -0
- data/po/zh_TW/rbot-quotes.po +108 -0
- data/po/zh_TW/rbot-reaction.po +0 -0
- data/po/zh_TW/rbot-remind.po +0 -0
- data/po/zh_TW/rbot-remotectl.po +0 -0
- data/po/zh_TW/rbot-ri.po +0 -0
- data/po/zh_TW/rbot-roshambo.po +0 -0
- data/po/zh_TW/rbot-rot13.po +0 -0
- data/po/zh_TW/rbot-roulette.po +0 -0
- data/po/zh_TW/rbot-rss.po +20 -0
- data/po/zh_TW/rbot-salut.po +0 -0
- data/po/zh_TW/rbot-script.po +0 -0
- data/po/zh_TW/rbot-search.po +0 -0
- data/po/zh_TW/rbot-seen.po +0 -0
- data/po/zh_TW/rbot-shiritori.po +102 -0
- data/po/zh_TW/rbot-shortenurls.po +0 -0
- data/po/zh_TW/rbot-slashdot.po +0 -0
- data/po/zh_TW/rbot-spell.po +54 -0
- data/po/zh_TW/rbot-theyfightcrime.po +0 -0
- data/po/zh_TW/rbot-threat.po +0 -0
- data/po/zh_TW/rbot-time.po +0 -0
- data/po/zh_TW/rbot-topic.po +0 -0
- data/po/zh_TW/rbot-translator.po +77 -0
- data/po/zh_TW/rbot-tube.po +0 -0
- data/po/zh_TW/rbot-twitter.po +24 -0
- data/po/zh_TW/rbot-uno.po +512 -0
- data/po/zh_TW/rbot-urban.po +0 -0
- data/po/zh_TW/rbot-url.po +0 -0
- data/po/zh_TW/rbot-usermodes.po +0 -0
- data/po/zh_TW/rbot-wall.po +33 -0
- data/po/zh_TW/rbot-weather.po +0 -0
- data/po/zh_TW/rbot-wheelfortune.po +205 -0
- data/po/zh_TW/rbot-wow.po +0 -0
- data/po/zh_TW/rbot-wserver.po +0 -0
- data/po/zh_TW/rbot-youtube.po +58 -0
- data/po/zh_TW/rbot.po +1034 -0
- data/setup.rb +800 -574
- metadata +723 -108
- data/data/rbot/contrib/plugins/figlet.rb +0 -20
- data/data/rbot/contrib/plugins/ri.rb +0 -83
- data/data/rbot/plugins/demauro.rb +0 -95
- data/data/rbot/plugins/google.rb +0 -53
- data/data/rbot/plugins/opme.rb +0 -19
- data/data/rbot/plugins/roshambo.rb +0 -54
- data/data/rbot/plugins/rubyurl.rb +0 -39
- data/data/rbot/plugins/tinyurl.rb +0 -39
- data/data/rbot/plugins/xmlrpc.rb.disabled +0 -52
- data/data/rbot/templates/levels.rbot +0 -32
- data/data/rbot/templates/users.rbot +0 -1
- data/lib/rbot/auth.rb +0 -314
- data/lib/rbot/channel.rb +0 -54
- data/lib/rbot/httputil.rb +0 -309
- data/lib/rbot/utils.rb +0 -83
@@ -0,0 +1,26 @@
|
|
1
|
+
#-- vim:sw=2:et
|
2
|
+
#++
|
3
|
+
#
|
4
|
+
# :title: Usermodes plugin
|
5
|
+
#
|
6
|
+
# Author:: Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com>
|
7
|
+
# Copyright:: (C) 2007 Giuseppe Bilotta
|
8
|
+
# License:: rbot's licence
|
9
|
+
#
|
10
|
+
|
11
|
+
class UserModesPlugin < Plugin
|
12
|
+
Config.register Config::StringValue.new('irc.usermodes',
|
13
|
+
:default => '',
|
14
|
+
:desc => "User modes to set when connecting to the server")
|
15
|
+
|
16
|
+
def help(plugin, topic="")
|
17
|
+
"handles automatic usermode settings on connect. See the config variable irc.usermodes"
|
18
|
+
end
|
19
|
+
|
20
|
+
def connect
|
21
|
+
modes = @bot.config['irc.usermodes']
|
22
|
+
@bot.mode(@bot.nick, modes, '') unless modes.empty?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
plugin = UserModesPlugin.new
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#-- vim:sw=2:et
|
2
|
+
#++
|
3
|
+
#
|
4
|
+
# :title: Wall plugin
|
5
|
+
#
|
6
|
+
# Author:: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
|
7
|
+
# Copyright:: (C) 2008 Giuseppe Bilotta
|
8
|
+
# License:: GPLv2
|
9
|
+
#
|
10
|
+
# Wall plugin: !wall to show the writing on the wall, !wall whatever to write
|
11
|
+
# whatever on the wall
|
12
|
+
#
|
13
|
+
# The wall is global for all rbots and is available at http://ruby-rbot.org/wall/
|
14
|
+
|
15
|
+
class WallPlugin < Plugin
|
16
|
+
|
17
|
+
Config.register Config::ArrayValue.new('wall.readers',
|
18
|
+
:default => ['toilet', 'figlet'],
|
19
|
+
:desc => _('figlet method to use to display the writing on the wall (nil for none)'),
|
20
|
+
:validate => Proc.new { |v| v !~ /\s|`/ },
|
21
|
+
:on_change => Proc.new { |bot, v| bot.plugins['figlet'].test_toilet })
|
22
|
+
|
23
|
+
def help(plugin, topic="")
|
24
|
+
"wall => read latest writing on the wall: http://ruby-rbot.org/wall"
|
25
|
+
end
|
26
|
+
|
27
|
+
def write_wall(m, p)
|
28
|
+
m.reply _("writing on the wall not implemented yet")
|
29
|
+
end
|
30
|
+
|
31
|
+
def read_wall(m, p)
|
32
|
+
wall = @bot.httputil.get('http://ruby-rbot.org/wall/', :cache => false)
|
33
|
+
if wall.nil_or_empty?
|
34
|
+
m.reply _("No writing on the wall")
|
35
|
+
return
|
36
|
+
end
|
37
|
+
if @bot.plugins['figlet']
|
38
|
+
reader = nil
|
39
|
+
@bot.config['wall.readers'].each { |p|
|
40
|
+
plug = p.intern rescue nil
|
41
|
+
if @bot.plugins['figlet'].has[plug]
|
42
|
+
reader = plug
|
43
|
+
break
|
44
|
+
end
|
45
|
+
}
|
46
|
+
if reader
|
47
|
+
@bot.plugins['figlet'].figlet m, :plugin => reader,
|
48
|
+
:message => wall
|
49
|
+
return
|
50
|
+
end
|
51
|
+
end
|
52
|
+
m.reply(_("The writing on the wall reads: %{wall}") % {
|
53
|
+
:wall => wall
|
54
|
+
})
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
wall = WallPlugin.new
|
59
|
+
wall.map 'wall', :action => :read_wall
|
60
|
+
wall.map 'wall *text', :action => :write_wall
|
@@ -1,649 +1,305 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
@date = l.chomp.strip
|
14
|
-
str = ""
|
15
|
-
else
|
16
|
-
if(str == "")
|
17
|
-
str = l.chomp.strip
|
18
|
-
else
|
19
|
-
str += " " + l.chomp.strip
|
20
|
-
end
|
21
|
-
end
|
22
|
-
}
|
23
|
-
if @date && @date =~ /^(\d+)\/(\d+)\/(\d+) (\d+):(\d+)$/
|
24
|
-
# 2002/02/26 05:00
|
25
|
-
@date = Time.gm($1, $2, $3, $4, $5, 0)
|
26
|
-
else
|
27
|
-
@date = Time.now
|
28
|
-
end
|
29
|
-
@input = str.chomp
|
30
|
-
@cloud_layers = 0
|
31
|
-
@cloud_coverage = {
|
32
|
-
'SKC' => '0',
|
33
|
-
'CLR' => '0',
|
34
|
-
'VV' => '8/8',
|
35
|
-
'FEW' => '1/8 - 2/8',
|
36
|
-
'SCT' => '3/8 - 4/8',
|
37
|
-
'BKN' => '5/8 - 7/8',
|
38
|
-
'OVC' => '8/8'
|
39
|
-
}
|
40
|
-
@wind_dir_texts = [
|
41
|
-
'North',
|
42
|
-
'North/Northeast',
|
43
|
-
'Northeast',
|
44
|
-
'East/Northeast',
|
45
|
-
'East',
|
46
|
-
'East/Southeast',
|
47
|
-
'Southeast',
|
48
|
-
'South/Southeast',
|
49
|
-
'South',
|
50
|
-
'South/Southwest',
|
51
|
-
'Southwest',
|
52
|
-
'West/Southwest',
|
53
|
-
'West',
|
54
|
-
'West/Northwest',
|
55
|
-
'Northwest',
|
56
|
-
'North/Northwest',
|
57
|
-
'North'
|
58
|
-
]
|
59
|
-
@wind_dir_texts_short = [
|
60
|
-
'N',
|
61
|
-
'N/NE',
|
62
|
-
'NE',
|
63
|
-
'E/NE',
|
64
|
-
'E',
|
65
|
-
'E/SE',
|
66
|
-
'SE',
|
67
|
-
'S/SE',
|
68
|
-
'S',
|
69
|
-
'S/SW',
|
70
|
-
'SW',
|
71
|
-
'W/SW',
|
72
|
-
'W',
|
73
|
-
'W/NW',
|
74
|
-
'NW',
|
75
|
-
'N/NW',
|
76
|
-
'N'
|
77
|
-
]
|
78
|
-
@weather_array = {
|
79
|
-
'MI' => 'Mild ',
|
80
|
-
'PR' => 'Partial ',
|
81
|
-
'BC' => 'Patches ',
|
82
|
-
'DR' => 'Low Drifting ',
|
83
|
-
'BL' => 'Blowing ',
|
84
|
-
'SH' => 'Shower(s) ',
|
85
|
-
'TS' => 'Thunderstorm ',
|
86
|
-
'FZ' => 'Freezing',
|
87
|
-
'DZ' => 'Drizzle ',
|
88
|
-
'RA' => 'Rain ',
|
89
|
-
'SN' => 'Snow ',
|
90
|
-
'SG' => 'Snow Grains ',
|
91
|
-
'IC' => 'Ice Crystals ',
|
92
|
-
'PE' => 'Ice Pellets ',
|
93
|
-
'GR' => 'Hail ',
|
94
|
-
'GS' => 'Small Hail and/or Snow Pellets ',
|
95
|
-
'UP' => 'Unknown ',
|
96
|
-
'BR' => 'Mist ',
|
97
|
-
'FG' => 'Fog ',
|
98
|
-
'FU' => 'Smoke ',
|
99
|
-
'VA' => 'Volcanic Ash ',
|
100
|
-
'DU' => 'Widespread Dust ',
|
101
|
-
'SA' => 'Sand ',
|
102
|
-
'HZ' => 'Haze ',
|
103
|
-
'PY' => 'Spray',
|
104
|
-
'PO' => 'Well-Developed Dust/Sand Whirls ',
|
105
|
-
'SQ' => 'Squalls ',
|
106
|
-
'FC' => 'Funnel Cloud Tornado Waterspout ',
|
107
|
-
'SS' => 'Sandstorm/Duststorm '
|
108
|
-
}
|
109
|
-
@cloud_condition_array = {
|
110
|
-
'SKC' => 'clear',
|
111
|
-
'CLR' => 'clear',
|
112
|
-
'VV' => 'vertical visibility',
|
113
|
-
'FEW' => 'a few',
|
114
|
-
'SCT' => 'scattered',
|
115
|
-
'BKN' => 'broken',
|
116
|
-
'OVC' => 'overcast'
|
117
|
-
}
|
118
|
-
@strings = {
|
119
|
-
'mm_inches' => '%s mm (%s inches)',
|
120
|
-
'precip_a_trace' => 'a trace',
|
121
|
-
'precip_there_was' => 'There was %s of precipitation ',
|
122
|
-
'sky_str_format1' => 'There were %s at a height of %s meters (%s feet)',
|
123
|
-
'sky_str_clear' => 'The sky was clear',
|
124
|
-
'sky_str_format2' => ', %s at a height of %s meter (%s feet) and %s at a height of %s meters (%s feet)',
|
125
|
-
'sky_str_format3' => ' and %s at a height of %s meters (%s feet)',
|
126
|
-
'clouds' => ' clouds',
|
127
|
-
'clouds_cb' => ' cumulonimbus clouds',
|
128
|
-
'clouds_tcu' => ' towering cumulus clouds',
|
129
|
-
'visibility_format' => 'The visibility was %s kilometers (%s miles).',
|
130
|
-
'wind_str_format1' => 'blowing at a speed of %s meters per second (%s miles per hour)',
|
131
|
-
'wind_str_format2' => ', with gusts to %s meters per second (%s miles per hour),',
|
132
|
-
'wind_str_format3' => ' from the %s',
|
133
|
-
'wind_str_calm' => 'calm',
|
134
|
-
'precip_last_hour' => 'in the last hour. ',
|
135
|
-
'precip_last_6_hours' => 'in the last 3 to 6 hours. ',
|
136
|
-
'precip_last_24_hours' => 'in the last 24 hours. ',
|
137
|
-
'precip_snow' => 'There is %s mm (%s inches) of snow on the ground. ',
|
138
|
-
'temp_min_max_6_hours' => 'The maximum and minimum temperatures over the last 6 hours were %s and %s degrees Celsius (%s and %s degrees Fahrenheit).',
|
139
|
-
'temp_max_6_hours' => 'The maximum temperature over the last 6 hours was %s degrees Celsius (%s degrees Fahrenheit). ',
|
140
|
-
'temp_min_6_hours' => 'The minimum temperature over the last 6 hours was %s degrees Celsius (%s degrees Fahrenheit). ',
|
141
|
-
'temp_min_max_24_hours' => 'The maximum and minimum temperatures over the last 24 hours were %s and %s degrees Celsius (%s and %s degrees Fahrenheit). ',
|
142
|
-
'light' => 'Light ',
|
143
|
-
'moderate' => 'Moderate ',
|
144
|
-
'heavy' => 'Heavy ',
|
145
|
-
'mild' => 'Mild ',
|
146
|
-
'nearby' => 'Nearby ',
|
147
|
-
'current_weather' => 'Current weather is %s. ',
|
148
|
-
'pretty_print_metar' => '%s on %s, the wind was %s at %s. The temperature was %s degrees Celsius (%s degrees Fahrenheit), and the pressure was %s hPa (%s inHg). The relative humidity was %s%%. %s %s %s %s %s'
|
149
|
-
}
|
1
|
+
#-- vim:sw=2:et
|
2
|
+
#++
|
3
|
+
#
|
4
|
+
# :title: Weather plugin for rbot
|
5
|
+
#
|
6
|
+
# Author:: MrChucho (mrchucho@mrchucho.net): NOAA National Weather Service support
|
7
|
+
# Author:: Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com>
|
8
|
+
#
|
9
|
+
# Copyright:: (C) 2006 Ralph M. Churchill
|
10
|
+
# Copyright:: (C) 2006-2007 Giuseppe Bilotta
|
11
|
+
#
|
12
|
+
# License:: GPL v2
|
150
13
|
|
151
|
-
|
152
|
-
end
|
14
|
+
require 'rexml/document'
|
153
15
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
# The windspeed measured in miles per hour, rounded to one decimal place: */
|
164
|
-
@decoded[milesperhour] = sprintf("%.2f", value.to_f * 1.1507695060844667)
|
165
|
-
elsif (windunit == 'MPS')
|
166
|
-
# The windspeed measured in meters per second:
|
167
|
-
@decoded[meterspersec] = sprintf("%.2f", value)
|
168
|
-
# The windspeed measured in knots, rounded to one decimal place:
|
169
|
-
@decoded[knots] = sprintf("%.2f", value.to_f / 0.51444)
|
170
|
-
#The windspeed measured in miles per hour, rounded to one decimal place:
|
171
|
-
@decoded[milesperhour] = sprintf("%.1f", value.to_f / 0.51444 * 1.1507695060844667)
|
172
|
-
elsif (windunit == 'KMH')
|
173
|
-
# The windspeed measured in kilometers per hour:
|
174
|
-
@decoded[meterspersec] = sprintf("%.1f", value.to_f * 1000 / 3600)
|
175
|
-
@decoded[knots] = sprintf("%.1f", value.to_f * 1000 / 3600 / 0.51444)
|
176
|
-
# The windspeed measured in miles per hour, rounded to one decimal place:
|
177
|
-
@decoded[milesperhour] = sprintf("%.1f", knots.to_f * 1.1507695060844667)
|
16
|
+
# Wraps NOAA National Weather Service information
|
17
|
+
class CurrentConditions
|
18
|
+
def initialize(station)
|
19
|
+
@station = station
|
20
|
+
@url = "http://www.nws.noaa.gov/data/current_obs/#{@station.upcase}.xml"
|
21
|
+
@etag = String.new
|
22
|
+
@mtime = Time.mktime(0)
|
23
|
+
@current_conditions = String.new
|
24
|
+
@iscached = false
|
178
25
|
end
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
@decoded['station'] = part
|
199
|
-
elsif (part =~ /([0-9]{2})([0-9]{2})([0-9]{2})Z/)
|
200
|
-
# ignore this bit, it's useless without month/year. some of these
|
201
|
-
# things are hideously out of date.
|
202
|
-
# now = Time.new
|
203
|
-
# time = Time.gm(now.year, now.month, $1, $2, $3, 0)
|
204
|
-
# Date and Time of Report
|
205
|
-
# @decoded['time'] = time
|
206
|
-
elsif (part == 'COR')
|
207
|
-
# Report Modifier: COR
|
208
|
-
@decoded['report_mod'] = 'COR'
|
209
|
-
elsif (part =~ /([0-9]{3}|VRB)([0-9]{2,3}).*(KT|MPS|KMH)/)
|
210
|
-
# Wind Group
|
211
|
-
windunit = $3
|
212
|
-
# now do ereg to get the actual values
|
213
|
-
part =~ /([0-9]{3}|VRB)([0-9]{2,3})((G[0-9]{2,3})?#{windunit})/
|
214
|
-
if ($1 == 'VRB')
|
215
|
-
@decoded['wind_deg'] = 'variable directions'
|
216
|
-
@decoded['wind_dir_text'] = 'variable directions'
|
217
|
-
@decoded['wind_dir_text_short'] = 'VAR'
|
218
|
-
else
|
219
|
-
@decoded['wind_deg'] = $1
|
220
|
-
@decoded['wind_dir_text'] = @wind_dir_texts[($1.to_i/22.5).round]
|
221
|
-
@decoded['wind_dir_text_short'] = @wind_dir_texts_short[($1.to_i/22.5).round]
|
26
|
+
def update
|
27
|
+
begin
|
28
|
+
open(@url,"If-Modified-Since" => @mtime.rfc2822) do |feed|
|
29
|
+
# open(@url,"If-None-Match"=>@etag) do |feed|
|
30
|
+
@etag = feed.meta['etag']
|
31
|
+
@mtime = feed.last_modified
|
32
|
+
cc_doc = (REXML::Document.new feed).root
|
33
|
+
@iscached = false
|
34
|
+
@current_conditions = parse(cc_doc)
|
35
|
+
end
|
36
|
+
rescue OpenURI::HTTPError => e
|
37
|
+
case e
|
38
|
+
when /304/:
|
39
|
+
@iscached = true
|
40
|
+
when /404/:
|
41
|
+
raise "Data for #{@station} not found"
|
42
|
+
else
|
43
|
+
raise "Error retrieving data: #{e}"
|
44
|
+
end
|
222
45
|
end
|
223
|
-
|
224
|
-
'wind_meters_per_second',
|
225
|
-
'wind_knots',
|
226
|
-
'wind_miles_per_hour')
|
227
|
-
|
228
|
-
if ($4 != nil)
|
229
|
-
# We have a report with information about the gust.
|
230
|
-
# First we have the gust measured in knots
|
231
|
-
if ($4 =~ /G([0-9]{2,3})/)
|
232
|
-
store_speed($1,windunit,
|
233
|
-
'wind_gust_meters_per_second',
|
234
|
-
'wind_gust_knots',
|
235
|
-
'wind_gust_miles_per_hour')
|
46
|
+
@current_conditions # +" Cached? "+ ((@iscached) ? "Y" : "N")
|
236
47
|
end
|
48
|
+
def parse(cc_doc)
|
49
|
+
cc = Hash.new
|
50
|
+
cc_doc.elements.each do |c|
|
51
|
+
cc[c.name.to_sym] = c.text
|
237
52
|
end
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
elsif (part =~ /^([0-9]{4})$/)
|
249
|
-
# Visibility in meters (4 digits only)
|
250
|
-
# The visibility measured in kilometers, rounded to one decimal place.
|
251
|
-
@decoded['visibility_km'] = sprintf("%.1f", $1.to_i / 1000)
|
252
|
-
# The visibility measured in miles, rounded to one decimal place.
|
253
|
-
@decoded['visibility_miles'] = sprintf("%.1f", $1.to_i / 1000 / 1.609344)
|
254
|
-
elsif (part =~ /^[0-9]$/)
|
255
|
-
# Temp Visibility Group, single digit followed by space
|
256
|
-
@decoded['temp_visibility_miles'] = part
|
257
|
-
elsif (@decoded['temp_visibility_miles'] && (@decoded['temp_visibility_miles']+' '+part) =~ /^M?(([0-9]?)[ ]?([0-9])(\/?)([0-9]*))SM$/)
|
258
|
-
# Visibility Group
|
259
|
-
if ($4 == '/')
|
260
|
-
vis_miles = $2.to_i + $3.to_i/$5.to_i
|
261
|
-
else
|
262
|
-
vis_miles = $1.to_i;
|
263
|
-
end
|
264
|
-
if (@decoded['temp_visibility_miles'][0] == 'M')
|
265
|
-
# The visibility measured in miles, prefixed with < to indicate 'Less than'
|
266
|
-
@decoded['visibility_miles'] = '<' + sprintf("%.1f", vis_miles)
|
267
|
-
# The visibility measured in kilometers. The value is rounded
|
268
|
-
# to one decimal place, prefixed with < to indicate 'Less than' */
|
269
|
-
@decoded['visibility_km'] = '<' . sprintf("%.1f", vis_miles * 1.609344)
|
270
|
-
else
|
271
|
-
# The visibility measured in mile.s */
|
272
|
-
@decoded['visibility_miles'] = sprintf("%.1f", vis_miles)
|
273
|
-
# The visibility measured in kilometers, rounded to one decimal place.
|
274
|
-
@decoded['visibility_km'] = sprintf("%.1f", vis_miles * 1.609344)
|
275
|
-
end
|
276
|
-
elsif (part =~ /^(-|\+|VC|MI)?(TS|SH|FZ|BL|DR|BC|PR|RA|DZ|SN|SG|GR|GS|PE|IC|UP|BR|FG|FU|VA|DU|SA|HZ|PY|PO|SQ|FC|SS|DS)+$/)
|
277
|
-
# Current weather-group
|
278
|
-
@decoded['weather'] = '' unless @decoded.has_key?('weather')
|
279
|
-
if (part[0].chr == '-')
|
280
|
-
# A light phenomenon
|
281
|
-
@decoded['weather'] += @strings['light']
|
282
|
-
part = part[1,part.length]
|
283
|
-
elsif (part[0].chr == '+')
|
284
|
-
# A heavy phenomenon
|
285
|
-
@decoded['weather'] += @strings['heavy']
|
286
|
-
part = part[1,part.length]
|
287
|
-
elsif (part[0,2] == 'VC')
|
288
|
-
# Proximity Qualifier
|
289
|
-
@decoded['weather'] += @strings['nearby']
|
290
|
-
part = part[2,part.length]
|
291
|
-
elsif (part[0,2] == 'MI')
|
292
|
-
@decoded['weather'] += @strings['mild']
|
293
|
-
part = part[2,part.length]
|
294
|
-
else
|
295
|
-
# no intensity code => moderate phenomenon
|
296
|
-
@decoded['weather'] += @strings['moderate']
|
297
|
-
end
|
298
|
-
|
299
|
-
while (part && bite = part[0,2]) do
|
300
|
-
# Now we take the first two letters and determine what they
|
301
|
-
# mean. We append this to the variable so that we gradually
|
302
|
-
# build up a phrase.
|
303
|
-
|
304
|
-
@decoded['weather'] += @weather_array[bite]
|
305
|
-
# Here we chop off the two first letters, so that we can take
|
306
|
-
# a new bite at top of the while-loop.
|
307
|
-
part = part[2,-1]
|
308
|
-
end
|
309
|
-
elsif (part =~ /(SKC|CLR)/)
|
310
|
-
# Cloud-layer-group.
|
311
|
-
# There can be up to three of these groups, so we store them as
|
312
|
-
# cloud_layer1, cloud_layer2 and cloud_layer3.
|
313
|
-
|
314
|
-
@cloud_layers += 1;
|
315
|
-
# Again we have to translate the code-characters to a
|
316
|
-
# meaningful string.
|
317
|
-
@decoded['cloud_layer'+ (@cloud_layers.to_s) +'_condition'] = @cloud_condition_array[$1]
|
318
|
-
@decoded['cloud_layer'+ (@cloud_layers.to_s) +'_coverage'] = @cloud_coverage[$1]
|
319
|
-
elsif (part =~ /^(VV|FEW|SCT|BKN|OVC)([0-9]{3})(CB|TCU)?$/)
|
320
|
-
# We have found (another) a cloud-layer-group. There can be up
|
321
|
-
# to three of these groups, so we store them as cloud_layer1,
|
322
|
-
# cloud_layer2 and cloud_layer3.
|
323
|
-
@cloud_layers += 1;
|
324
|
-
# Again we have to translate the code-characters to a meaningful string.
|
325
|
-
if ($3 == 'CB')
|
326
|
-
# cumulonimbus (CB) clouds were observed. */
|
327
|
-
@decoded['cloud_layer'+ (@cloud_layers.to_s) +'_condition'] =
|
328
|
-
@cloud_condition_array[$1] + @strings['clouds_cb']
|
329
|
-
elsif ($3 == 'TCU')
|
330
|
-
# towering cumulus (TCU) clouds were observed.
|
331
|
-
@decoded['cloud_layer'+ (@cloud_layers.to_s) +'_condition'] =
|
332
|
-
@cloud_condition_array[$1] + @strings['clouds_tcu']
|
333
|
-
else
|
334
|
-
@decoded['cloud_layer'+ (@cloud_layers.to_s) +'_condition'] =
|
335
|
-
@cloud_condition_array[$1] + @strings['clouds']
|
336
|
-
end
|
337
|
-
@decoded['cloud_layer'+ (@cloud_layers.to_s) +'_coverage'] = @cloud_coverage[$1]
|
338
|
-
@decoded['cloud_layer'+ (@cloud_layers.to_s) +'_altitude_ft'] = $2.to_i * 100
|
339
|
-
@decoded['cloud_layer'+ (@cloud_layers.to_s) +'_altitude_m'] = ($2.to_f * 30.48).round
|
340
|
-
elsif (part =~ /^T([0-9]{4})$/)
|
341
|
-
store_temp($1,'temp_c','temp_f')
|
342
|
-
elsif (part =~ /^T?(M?[0-9]{2})\/(M?[0-9\/]{1,2})?$/)
|
343
|
-
# Temperature/Dew Point Group
|
344
|
-
# The temperature and dew-point measured in Celsius.
|
345
|
-
@decoded['temp_c'] = sprintf("%d", $1.tr('M', '-'))
|
346
|
-
if $2 == "//" || !$2
|
347
|
-
@decoded['dew_c'] = 0
|
53
|
+
"At #{cc[:observation_time_rfc822]}, the wind was #{cc[:wind_string]} at #{cc[:location]} (#{cc[:station_id]}). The temperature was #{cc[:temperature_string]}#{heat_index_or_wind_chill(cc)}, and the pressure was #{cc[:pressure_string]}. The relative humidity was #{cc[:relative_humidity]}%. Current conditions are #{cc[:weather]} with #{cc[:visibility_mi]}mi visibility."
|
54
|
+
end
|
55
|
+
private
|
56
|
+
def heat_index_or_wind_chill(cc)
|
57
|
+
hi = cc[:heat_index_string]
|
58
|
+
wc = cc[:windchill_string]
|
59
|
+
if hi != 'NA' then
|
60
|
+
" with a heat index of #{hi}"
|
61
|
+
elsif wc != 'NA' then
|
62
|
+
" with a windchill of #{wc}"
|
348
63
|
else
|
349
|
-
|
64
|
+
""
|
350
65
|
end
|
351
|
-
|
352
|
-
|
353
|
-
@decoded['temp_f'] = ((@decoded['temp_c'].to_f * 9 / 5) + 32).round
|
354
|
-
@decoded['dew_f'] = ((@decoded['dew_c'].to_f * 9 / 5) + 32).round
|
355
|
-
elsif(part =~ /A([0-9]{4})/)
|
356
|
-
# Altimeter
|
357
|
-
# The pressure measured in inHg
|
358
|
-
@decoded['altimeter_inhg'] = sprintf("%.2f", $1.to_i/100)
|
359
|
-
# The pressure measured in mmHg, hPa and atm
|
360
|
-
@decoded['altimeter_mmhg'] = sprintf("%.1f", $1.to_f * 0.254)
|
361
|
-
@decoded['altimeter_hpa'] = sprintf("%d", ($1.to_f * 0.33863881578947).to_i)
|
362
|
-
@decoded['altimeter_atm'] = sprintf("%.3f", $1.to_f * 3.3421052631579e-4)
|
363
|
-
elsif(part =~ /Q([0-9]{4})/)
|
364
|
-
# Altimeter
|
365
|
-
# This is strange, the specification doesnt say anything about
|
366
|
-
# the Qxxxx-form, but it's in the METARs.
|
367
|
-
# The pressure measured in hPa
|
368
|
-
@decoded['altimeter_hpa'] = sprintf("%d", $1.to_i)
|
369
|
-
# The pressure measured in mmHg, inHg and atm
|
370
|
-
@decoded['altimeter_mmhg'] = sprintf("%.1f", $1.to_f * 0.7500616827)
|
371
|
-
@decoded['altimeter_inhg'] = sprintf("%.2f", $1.to_f * 0.0295299875)
|
372
|
-
@decoded['altimeter_atm'] = sprintf("%.3f", $1.to_f * 9.869232667e-4)
|
373
|
-
elsif (part =~ /^T([0-9]{4})([0-9]{4})/)
|
374
|
-
# Temperature/Dew Point Group, coded to tenth of degree.
|
375
|
-
# The temperature and dew-point measured in Celsius.
|
376
|
-
store_temp($1,'temp_c','temp_f')
|
377
|
-
store_temp($2,'dew_c','dew_f')
|
378
|
-
elsif (part =~ /^1([0-9]{4}$)/)
|
379
|
-
# 6 hour maximum temperature Celsius, coded to tenth of degree
|
380
|
-
store_temp($1,'temp_max6h_c','temp_max6h_f')
|
381
|
-
elsif (part =~ /^2([0-9]{4}$)/)
|
382
|
-
# 6 hour minimum temperature Celsius, coded to tenth of degree
|
383
|
-
store_temp($1,'temp_min6h_c','temp_min6h_f')
|
384
|
-
elsif (part =~ /^4([0-9]{4})([0-9]{4})$/)
|
385
|
-
# 24 hour maximum and minimum temperature Celsius, coded to
|
386
|
-
# tenth of degree
|
387
|
-
store_temp($1,'temp_max24h_c','temp_max24h_f')
|
388
|
-
store_temp($2,'temp_min24h_c','temp_min24h_f')
|
389
|
-
elsif (part =~ /^P([0-9]{4})/)
|
390
|
-
# Precipitation during last hour in hundredths of an inch
|
391
|
-
# (store as inches)
|
392
|
-
@decoded['precip_in'] = sprintf("%.2f", $1.to_f/100)
|
393
|
-
@decoded['precip_mm'] = sprintf("%.2f", $1.to_f * 0.254)
|
394
|
-
elsif (part =~ /^6([0-9]{4})/)
|
395
|
-
# Precipitation during last 3 or 6 hours in hundredths of an
|
396
|
-
# inch (store as inches)
|
397
|
-
@decoded['precip_6h_in'] = sprintf("%.2f", $1.to_f/100)
|
398
|
-
@decoded['precip_6h_mm'] = sprintf("%.2f", $1.to_f * 0.254)
|
399
|
-
elsif (part =~ /^7([0-9]{4})/)
|
400
|
-
# Precipitation during last 24 hours in hundredths of an inch
|
401
|
-
# (store as inches)
|
402
|
-
@decoded['precip_24h_in'] = sprintf("%.2f", $1.to_f/100)
|
403
|
-
@decoded['precip_24h_mm'] = sprintf("%.2f", $1.to_f * 0.254)
|
404
|
-
elsif(part =~ /^4\/([0-9]{3})/)
|
405
|
-
# Snow depth in inches
|
406
|
-
@decoded['snow_in'] = sprintf("%.2f", $1);
|
407
|
-
@decoded['snow_mm'] = sprintf("%.2f", $1.to_f * 25.4)
|
408
|
-
else
|
409
|
-
# If we couldn't match the group, we assume that it was a
|
410
|
-
# remark.
|
411
|
-
@decoded['remarks'] = '' unless @decoded.has_key?("remarks")
|
412
|
-
@decoded['remarks'] += ' ' + part;
|
413
|
-
end
|
414
|
-
}
|
415
|
-
|
416
|
-
# Relative humidity
|
417
|
-
# p @decoded['dew_c'] # 11.0
|
418
|
-
# p @decoded['temp_c'] # 21.0
|
419
|
-
# => 56.1
|
420
|
-
@decoded['rel_humidity'] = sprintf("%.1f",100 *
|
421
|
-
(6.11 * (10.0**(7.5 * @decoded['dew_c'].to_f / (237.7 + @decoded['dew_c'].to_f)))) / (6.11 * (10.0 ** (7.5 * @decoded['temp_c'].to_f / (237.7 + @decoded['temp_c'].to_f))))) if @decoded.has_key?('dew_c')
|
422
|
-
end
|
66
|
+
end
|
67
|
+
end
|
423
68
|
|
424
|
-
|
425
|
-
# Given a numerical temperature temp in Celsius, coded to tenth of
|
426
|
-
# degree, store in @decoded[temp_cname], convert to Fahrenheit
|
427
|
-
# and store in @decoded[temp_fname]
|
428
|
-
# Note: temp is converted to negative if temp > 100.0 (See
|
429
|
-
# Federal Meteorological Handbook for groups T, 1, 2 and 4)
|
69
|
+
class WeatherPlugin < Plugin
|
430
70
|
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
71
|
+
Config.register Config::BooleanValue.new('weather.advisory',
|
72
|
+
:default => true,
|
73
|
+
:desc => "Should the bot report special weather advisories when any is present?")
|
74
|
+
|
75
|
+
def help(plugin, topic="")
|
76
|
+
case topic
|
77
|
+
when "nws"
|
78
|
+
"weather nws <station> => display the current conditions at the location specified by the NOAA National Weather Service station code <station> ( lookup your station code at http://www.nws.noaa.gov/data/current_obs/ )"
|
79
|
+
when "station", "wu"
|
80
|
+
"weather [<units>] <location> => display the current conditions at the location specified, looking it up on the Weather Underground site; you can use 'station <code>' to look up data by station code ( lookup your station code at http://www.weatherunderground.com/ ); you can optionally set <units> to 'metric' or 'english' if you only want data with the units; use 'both' for units to go back to having both."
|
81
|
+
else
|
82
|
+
"weather information lookup. Looks up weather information for the last location you specified. See topics 'nws' and 'wu' for more information"
|
436
83
|
end
|
437
|
-
@decoded[temp_cname] = sprintf("%.1f", temp)
|
438
|
-
# The temperature in Fahrenheit.
|
439
|
-
@decoded[temp_fname] = sprintf("%.1f", (temp * 9 / 5) + 32)
|
440
84
|
end
|
85
|
+
|
86
|
+
def initialize
|
87
|
+
super
|
441
88
|
|
442
|
-
|
443
|
-
# Returns amount if $precip_mm > 0, otherwise "trace" (see Federal
|
444
|
-
# Meteorological Handbook No. 1 for code groups P, 6 and 7) used in
|
445
|
-
# several places, so standardized in one function.
|
446
|
-
if (precip_mm.to_i > 0)
|
447
|
-
amount = sprintf(@strings['mm_inches'], precip_mm, precip_in)
|
448
|
-
else
|
449
|
-
amount = @strings['a_trace']
|
450
|
-
end
|
451
|
-
return sprintf(@strings['precip_there_was'], amount)
|
452
|
-
end
|
89
|
+
@nws_cache = Hash.new
|
453
90
|
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
91
|
+
@wu_url = "http://mobile.wunderground.com/cgi-bin/findweather/getForecast?brand=mobile%s&query=%s"
|
92
|
+
@wu_station_url = "http://mobile.wunderground.com/auto/mobile%s/global/stations/%s.html"
|
93
|
+
end
|
94
|
+
|
95
|
+
def weather(m, params)
|
96
|
+
if params[:where].empty?
|
97
|
+
if @registry.has_key?(m.sourcenick)
|
98
|
+
where = @registry[m.sourcenick]
|
99
|
+
debug "Loaded weather info #{where.inspect} for #{m.sourcenick}"
|
458
100
|
|
459
|
-
|
460
|
-
|
461
|
-
|
101
|
+
service = where.first.to_sym
|
102
|
+
loc = where[1].to_s
|
103
|
+
units = params[:units] || where[2] rescue nil
|
104
|
+
else
|
105
|
+
debug "No weather info for #{m.sourcenick}"
|
106
|
+
m.reply "I don't know where you are yet, #{m.sourcenick}. See 'help weather nws' or 'help weather wu' for additional help"
|
107
|
+
return
|
462
108
|
end
|
463
|
-
}
|
464
|
-
|
465
|
-
mins_old = ((Time.now - @date.to_i).to_f/60).round
|
466
|
-
if (mins_old <= 60)
|
467
|
-
weather_age = mins_old.to_s + " minutes ago,"
|
468
|
-
elsif (mins_old <= 60 * 25)
|
469
|
-
weather_age = (mins_old / 60).to_s + " hours, "
|
470
|
-
weather_age += (mins_old % 60).to_s + " minutes ago,"
|
471
|
-
else
|
472
|
-
# return "The weather stored for #{@decoded['station']} is hideously out of date :( (Last update #{@date})"
|
473
|
-
weather_age = "The weather stored for #{@decoded['station']} is hideously out of date :( here it is anyway:"
|
474
|
-
end
|
475
|
-
|
476
|
-
if(@decoded.has_key?("cloud_layer1_altitude_ft"))
|
477
|
-
sky_str = sprintf(@strings['sky_str_format1'],
|
478
|
-
@decoded["cloud_layer1_condition"],
|
479
|
-
@decoded["cloud_layer1_altitude_m"],
|
480
|
-
@decoded["cloud_layer1_altitude_ft"])
|
481
109
|
else
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
if(@decoded.has_key?("cloud_layer3_altitude_ft"))
|
487
|
-
sky_str += sprintf(@strings['sky_str_format2'],
|
488
|
-
@decoded["cloud_layer2_condition"],
|
489
|
-
@decoded["cloud_layer2_altitude_m"],
|
490
|
-
@decoded["cloud_layer2_altitude_ft"],
|
491
|
-
@decoded["cloud_layer3_condition"],
|
492
|
-
@decoded["cloud_layer3_altitude_m"],
|
493
|
-
@decoded["cloud_layer3_altitude_ft"])
|
110
|
+
where = params[:where]
|
111
|
+
if ['nws','station'].include?(where.first)
|
112
|
+
service = where.first.to_sym
|
113
|
+
loc = where[1].to_s
|
494
114
|
else
|
495
|
-
|
496
|
-
|
497
|
-
@decoded["cloud_layer2_altitude_m"],
|
498
|
-
@decoded["cloud_layer2_altitude_ft"])
|
115
|
+
service = :wu
|
116
|
+
loc = where.to_s
|
499
117
|
end
|
118
|
+
units = params[:units]
|
500
119
|
end
|
501
|
-
sky_str += "."
|
502
120
|
|
503
|
-
if
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
else
|
508
|
-
visibility = ""
|
121
|
+
if loc.empty?
|
122
|
+
debug "No weather location found for #{m.sourcenick}"
|
123
|
+
m.reply "I don't know where you are yet, #{m.sourcenick}. See 'help weather nws' or 'help weather wu' for additional help"
|
124
|
+
return
|
509
125
|
end
|
510
126
|
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
127
|
+
wu_units = String.new
|
128
|
+
if units
|
129
|
+
case units.to_sym
|
130
|
+
when :english, :metric
|
131
|
+
wu_units = "_#{units}"
|
132
|
+
when :both
|
133
|
+
else
|
134
|
+
m.reply "Ignoring unknown units #{units}"
|
135
|
+
wu_units = String.new
|
519
136
|
end
|
520
|
-
wind_str += sprintf(@strings['wind_str_format3'],
|
521
|
-
@decoded["wind_dir_text"])
|
522
|
-
else
|
523
|
-
wind_str = @strings['wind_str_calm']
|
524
137
|
end
|
525
138
|
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
if (@decoded.has_key?("precip_24h_in"))
|
534
|
-
prec_str += pretty_print_precip(@decoded["precip_24h_mm"], @decoded["precip_24h_in"]) + @strings['precip_last_24_hours']
|
535
|
-
end
|
536
|
-
if (@decoded.has_key?("snow_in"))
|
537
|
-
prec_str += sprintf(@strings['precip_snow'], @decoded["snow_mm"], @decoded["snow_in"])
|
139
|
+
case service
|
140
|
+
when :nws
|
141
|
+
nws_describe(m, loc)
|
142
|
+
when :station
|
143
|
+
wu_station(m, loc, wu_units)
|
144
|
+
when :wu
|
145
|
+
wu_weather(m, loc, wu_units)
|
538
146
|
end
|
539
147
|
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
@decoded["temp_min6h_f"])
|
148
|
+
@registry[m.sourcenick] = [service, loc, units]
|
149
|
+
end
|
150
|
+
|
151
|
+
def nws_describe(m, where)
|
152
|
+
if @nws_cache.has_key?(where) then
|
153
|
+
met = @nws_cache[where]
|
547
154
|
else
|
548
|
-
|
549
|
-
temp_str += sprintf(@strings['temp_max_6_hours'],
|
550
|
-
@decoded["temp_max6h_c"],
|
551
|
-
@decoded["temp_max6h_f"])
|
552
|
-
end
|
553
|
-
if (@decoded.has_key?("temp_min6h_c"))
|
554
|
-
temp_str += sprintf(@strings['temp_max_6_hours'],
|
555
|
-
@decoded["temp_min6h_c"],
|
556
|
-
@decoded["temp_min6h_f"])
|
557
|
-
end
|
558
|
-
end
|
559
|
-
if (@decoded.has_key?("temp_max24h_c"))
|
560
|
-
temp_str += sprintf(@strings['temp_min_max_24_hours'],
|
561
|
-
@decoded["temp_max24h_c"],
|
562
|
-
@decoded["temp_min24h_c"],
|
563
|
-
@decoded["temp_max24h_f"],
|
564
|
-
@decoded["temp_min24h_f"])
|
155
|
+
met = CurrentConditions.new(where)
|
565
156
|
end
|
566
|
-
|
567
|
-
|
568
|
-
|
157
|
+
if met
|
158
|
+
begin
|
159
|
+
m.reply met.update
|
160
|
+
@nws_cache[where] = met
|
161
|
+
rescue => e
|
162
|
+
m.reply e.message
|
163
|
+
end
|
569
164
|
else
|
570
|
-
|
165
|
+
m.reply "couldn't find weather data for #{where}"
|
571
166
|
end
|
572
|
-
|
573
|
-
return sprintf(@strings['pretty_print_metar'],
|
574
|
-
weather_age,
|
575
|
-
@date,
|
576
|
-
wind_str, @decoded["station"], @decoded["temp_c"],
|
577
|
-
@decoded["temp_f"], @decoded["altimeter_hpa"],
|
578
|
-
@decoded["altimeter_inhg"],
|
579
|
-
@decoded["rel_humidity"], sky_str,
|
580
|
-
visibility, weather_str, prec_str, temp_str).strip
|
581
167
|
end
|
582
168
|
|
583
|
-
def
|
584
|
-
|
169
|
+
def wu_station(m, where, units)
|
170
|
+
begin
|
171
|
+
xml = @bot.httputil.get(@wu_station_url % [units, CGI.escape(where)])
|
172
|
+
case xml
|
173
|
+
when nil
|
174
|
+
m.reply "couldn't retrieve weather information, sorry"
|
175
|
+
return
|
176
|
+
when /Search not found:/
|
177
|
+
m.reply "no such station found (#{where})"
|
178
|
+
return
|
179
|
+
when /<table border.*?>(.*?)<\/table>/m
|
180
|
+
data = $1.dup
|
181
|
+
m.reply wu_weather_filter(data)
|
182
|
+
wu_out_special(m, xml)
|
183
|
+
else
|
184
|
+
debug xml
|
185
|
+
m.reply "something went wrong with the data for #{where}..."
|
186
|
+
end
|
187
|
+
rescue => e
|
188
|
+
m.reply "retrieving info about '#{where}' failed (#{e})"
|
189
|
+
end
|
585
190
|
end
|
586
|
-
end
|
587
|
-
|
588
191
|
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
192
|
+
def wu_weather(m, where, units)
|
193
|
+
begin
|
194
|
+
xml = @bot.httputil.get(@wu_url % [units, CGI.escape(where)])
|
195
|
+
case xml
|
196
|
+
when nil
|
197
|
+
m.reply "couldn't retrieve weather information, sorry"
|
198
|
+
when /City Not Found/
|
199
|
+
m.reply "no such location found (#{where})"
|
200
|
+
when /Current<\/a>/
|
201
|
+
data = ""
|
202
|
+
xml.scan(/<table border.*?>(.*?)<\/table>/m).each do |match|
|
203
|
+
data += wu_weather_filter(match.first)
|
204
|
+
end
|
205
|
+
if data.length > 0
|
206
|
+
m.reply data
|
207
|
+
else
|
208
|
+
m.reply "couldn't parse weather data from #{where}"
|
209
|
+
end
|
210
|
+
wu_out_special(m, xml)
|
211
|
+
when /<a href="\/(?:global\/stations|US\/\w\w)\//
|
212
|
+
wu_weather_multi(m, xml)
|
213
|
+
else
|
214
|
+
debug xml
|
215
|
+
m.reply "something went wrong with the data from #{where}..."
|
216
|
+
end
|
217
|
+
rescue => e
|
218
|
+
m.reply "retrieving info about '#{where}' failed (#{e})"
|
219
|
+
end
|
593
220
|
end
|
594
221
|
|
595
|
-
def
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
222
|
+
def wu_clean(stuff)
|
223
|
+
txt = stuff
|
224
|
+
txt.gsub!(/[\n\s]+/,' ')
|
225
|
+
txt.gsub!(/ /, ' ')
|
226
|
+
txt.gsub!(/°/, ' ') # degree sign
|
227
|
+
txt.gsub!(/<\/?b>/,'')
|
228
|
+
txt.gsub!(/<\/?span[^<>]*?>/,'')
|
229
|
+
txt.gsub!(/<img\s*[^<>]*?>/,'')
|
230
|
+
txt.gsub!(/<br\s?\/?>/,'')
|
231
|
+
txt
|
601
232
|
end
|
602
233
|
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
#
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
234
|
+
def wu_weather_multi(m, xml)
|
235
|
+
# debug xml
|
236
|
+
stations = xml.scan(/<td>\s*(?:<a href="([^?"]+\?feature=[^"]+)"\s*[^>]*><img [^>]+><\/a>\s*)?<a href="\/(?:global\/stations|US\/(\w\w))\/([^"]*?)\.html">(.*?)<\/a>\s*:\s*(.*?)<\/td>/m)
|
237
|
+
# debug stations
|
238
|
+
m.reply "multiple stations available, use 'weather station <code>' or 'weather <city, state>' as appropriate, for one of the following (current temp shown):"
|
239
|
+
stations.map! { |ar|
|
240
|
+
warning = ar[0]
|
241
|
+
loc = ar[2]
|
242
|
+
state = ar[1]
|
243
|
+
par = ar[3]
|
244
|
+
w = ar[4]
|
245
|
+
if state # US station
|
246
|
+
(warning ? "*" : "") + ("%s, %s (%s): %s" % [loc, state, par, wu_clean(w)])
|
247
|
+
else # non-US station
|
248
|
+
(warning ? "*" : "") + ("station %s (%s): %s" % [loc, par, wu_clean(w)])
|
613
249
|
end
|
614
|
-
|
615
|
-
|
250
|
+
}
|
251
|
+
m.reply stations.join("; ")
|
616
252
|
end
|
617
|
-
|
618
|
-
def
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
@
|
629
|
-
|
630
|
-
|
253
|
+
|
254
|
+
def wu_check_special(xml)
|
255
|
+
specials = []
|
256
|
+
# We only scan the first half to prevent getting the advisories twice
|
257
|
+
xml[0,xml.length/2].scan(%r{<a href="([^"]+\?[^"]*feature=warning#([^"]+))"[^>]*>([^<]+)</a>}) do
|
258
|
+
special = {
|
259
|
+
:url => "http://mobile.wunderground.com"+$1,
|
260
|
+
:type => $2.dup,
|
261
|
+
:special => $3.dup
|
262
|
+
}
|
263
|
+
spec_rx = Regexp.new("<a name=\"#{special[:type]}\">(?:.+?)<td align=\"left\">\\s+(.+?)\\s+</td>\\s+</tr>\\s+</table>", Regexp::MULTILINE)
|
264
|
+
spec_xml = @bot.httputil.get(special[:url])
|
265
|
+
if spec_xml and spec_td = spec_xml.match(spec_rx)
|
266
|
+
special.merge!(:text => spec_td.captures.first.ircify_html)
|
267
|
+
end
|
268
|
+
specials << special
|
631
269
|
end
|
270
|
+
return specials
|
632
271
|
end
|
633
272
|
|
634
|
-
def
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
273
|
+
def wu_out_special(m, xml)
|
274
|
+
return unless @bot.config['weather.advisory']
|
275
|
+
specials = wu_check_special(xml)
|
276
|
+
debug specials
|
277
|
+
specials.each do |special|
|
278
|
+
special.merge!(:underline => Underline)
|
279
|
+
if special[:text]
|
280
|
+
m.reply("%{underline}%{special}%{underline}: %{text}" % special)
|
642
281
|
else
|
643
|
-
m.reply
|
282
|
+
m.reply("%{underline}%{special}%{underline} @ %{url}" % special)
|
644
283
|
end
|
645
284
|
end
|
646
285
|
end
|
286
|
+
|
287
|
+
def wu_weather_filter(stuff)
|
288
|
+
txt = wu_clean(stuff)
|
289
|
+
|
290
|
+
result = Array.new
|
291
|
+
if txt.match(/<\/a>\s*Updated:\s*(.*?)\s*Observed at\s*(.*?)\s*<\/td>/)
|
292
|
+
result << ("Weather info for %s (updated on %s)" % [$2, $1])
|
293
|
+
end
|
294
|
+
txt.scan(/<tr>\s*<td>\s*(.*?)\s*<\/td>\s*<td>\s*(.*?)\s*<\/td>\s*<\/tr>/) { |k, v|
|
295
|
+
next if v.empty?
|
296
|
+
next if ["-", "- approx.", "N/A", "N/A approx."].include?(v)
|
297
|
+
next if k == "Raw METAR"
|
298
|
+
result << ("%s: %s" % [k, v])
|
299
|
+
}
|
300
|
+
return result.join('; ')
|
301
|
+
end
|
647
302
|
end
|
303
|
+
|
648
304
|
plugin = WeatherPlugin.new
|
649
|
-
plugin.map 'weather :where', :defaults => {:where => false}
|
305
|
+
plugin.map 'weather :units *where', :defaults => {:where => false, :units => false}, :requirements => {:units => /metric|english|both/}
|