rbot 0.9.14 → 0.9.15
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +6 -2
- data/REQUIREMENTS +7 -1
- data/Rakefile +10 -32
- data/bin/rbot +6 -1
- data/bin/svnwatch-postcommit-hook +68 -0
- data/data/rbot/contrib/plugins/stats.rb +3 -3
- data/data/rbot/contrib/plugins/vandale.rb +1 -1
- data/data/rbot/filters/rss.rb +72 -0
- data/data/rbot/languages/finnish.lang +50 -0
- data/data/rbot/plugins/alias.rb +6 -6
- data/data/rbot/plugins/autorejoin.rb +41 -2
- data/data/rbot/plugins/bans.rb +100 -6
- data/data/rbot/plugins/bash.rb +9 -4
- data/data/rbot/plugins/cal.rb +1 -1
- data/data/rbot/plugins/chucknorris.rb +6 -6
- data/data/rbot/plugins/debugger.rb +7 -3
- data/data/rbot/plugins/deepthoughts.rb +1 -1
- data/data/rbot/plugins/delicious.rb +6 -2
- data/data/rbot/plugins/dice.rb +7 -7
- data/data/rbot/plugins/dict.rb +4 -3
- data/data/rbot/plugins/dictclient.rb +17 -13
- data/data/rbot/plugins/digg.rb +3 -3
- data/data/rbot/plugins/eightball.rb +1 -1
- data/data/rbot/plugins/factoids.rb +13 -4
- data/data/rbot/plugins/figlet.rb +4 -4
- data/data/rbot/plugins/forecast.rb +3 -3
- data/data/rbot/plugins/fortune.rb +14 -8
- data/data/rbot/plugins/freshmeat.rb +2 -2
- data/data/rbot/plugins/games/azgame.rb +72 -19
- data/data/rbot/plugins/games/hangman.rb +499 -0
- data/data/rbot/plugins/games/quiz.rb +15 -13
- data/data/rbot/plugins/games/roshambo.rb +1 -1
- data/data/rbot/plugins/games/roulette.rb +4 -4
- data/data/rbot/plugins/games/shiritori.rb +31 -31
- data/data/rbot/plugins/games/uno.rb +28 -6
- data/data/rbot/plugins/games/wheelfortune.rb +1 -3
- data/data/rbot/plugins/geoip.rb +83 -28
- data/data/rbot/plugins/googlefight.rb +64 -0
- data/data/rbot/plugins/greet.rb +45 -0
- data/data/rbot/plugins/grouphug.rb +40 -12
- data/data/rbot/plugins/imdb.rb +4 -4
- data/data/rbot/plugins/insult.rb +2 -2
- data/data/rbot/plugins/karma.rb +6 -5
- data/data/rbot/plugins/keywords.rb +26 -22
- data/data/rbot/plugins/lart.rb +5 -6
- data/data/rbot/plugins/lastfm.rb +488 -125
- data/data/rbot/plugins/lib_spotify.rb +84 -0
- data/data/rbot/plugins/linkbot.rb +1 -1
- data/data/rbot/plugins/markov.rb +567 -78
- data/data/rbot/plugins/math.rb +3 -3
- data/data/rbot/plugins/modes.rb +1 -1
- data/data/rbot/plugins/nickrecover.rb +1 -1
- data/data/rbot/plugins/nickserv.rb +7 -7
- data/data/rbot/plugins/note.rb +55 -0
- data/data/rbot/plugins/nslookup.rb +2 -2
- data/data/rbot/plugins/quakeauth.rb +4 -4
- data/data/rbot/plugins/quotes.rb +53 -19
- data/data/rbot/plugins/reaction.rb +76 -19
- data/data/rbot/plugins/remind.rb +3 -96
- data/data/rbot/plugins/ri.rb +1 -1
- data/data/rbot/plugins/rot13.rb +1 -1
- data/data/rbot/plugins/rss.rb +296 -190
- data/data/rbot/plugins/salut.rb +8 -8
- data/data/rbot/plugins/script.rb +48 -11
- data/data/rbot/plugins/search.rb +124 -28
- data/data/rbot/plugins/seen.rb +162 -31
- data/data/rbot/plugins/shortenurls.rb +1 -1
- data/data/rbot/plugins/slashdot.rb +19 -6
- data/data/rbot/plugins/spotify.rb +78 -0
- data/data/rbot/plugins/theyfightcrime.rb +10 -10
- data/data/rbot/plugins/time.rb +2 -2
- data/data/rbot/plugins/translator.rb +161 -85
- data/data/rbot/plugins/tube.rb +2 -2
- data/data/rbot/plugins/tumblr.rb +143 -0
- data/data/rbot/plugins/twitter.rb +25 -6
- data/data/rbot/plugins/urban.rb +6 -4
- data/data/rbot/plugins/url.rb +49 -10
- data/data/rbot/plugins/weather.rb +6 -6
- data/data/rbot/plugins/wserver.rb +5 -5
- data/data/rbot/plugins/youtube.rb +12 -12
- data/data/rbot/templates/lart/larts-italian +1 -1
- data/launch_here.rb +68 -0
- data/lib/rbot/botuser.rb +1 -1
- data/lib/rbot/compat19.rb +70 -0
- data/lib/rbot/config.rb +8 -6
- data/lib/rbot/core/auth.rb +37 -21
- data/lib/rbot/core/basics.rb +33 -2
- data/lib/rbot/core/config.rb +24 -17
- data/lib/rbot/core/filters_ui.rb +2 -2
- data/lib/rbot/core/irclog.rb +20 -11
- data/lib/rbot/core/remote.rb +9 -9
- data/lib/rbot/core/unicode.rb +4 -0
- data/lib/rbot/core/userdata.rb +16 -1
- data/lib/rbot/core/utils/extends.rb +76 -0
- data/lib/rbot/core/utils/filters.rb +47 -0
- data/lib/rbot/core/utils/httputil.rb +36 -26
- data/lib/rbot/core/utils/parse_time.rb +193 -0
- data/lib/rbot/core/utils/utils.rb +81 -56
- data/lib/rbot/core/utils/wordlist.rb +66 -0
- data/lib/rbot/core/wordlist_ui.rb +27 -0
- data/lib/rbot/irc.rb +59 -19
- data/lib/rbot/ircbot.rb +190 -58
- data/lib/rbot/ircsocket.rb +14 -8
- data/lib/rbot/language.rb +4 -3
- data/lib/rbot/load-gettext.rb +22 -9
- data/lib/rbot/message.rb +89 -18
- data/lib/rbot/messagemapper.rb +71 -19
- data/lib/rbot/plugins.rb +112 -44
- data/lib/rbot/{registry.rb → registry/bdb.rb} +226 -22
- data/lib/rbot/registry/tc.rb +531 -0
- data/lib/rbot/rfc2812.rb +33 -8
- data/lib/rbot/timer.rb +12 -20
- data/po/en_US/rbot-autorejoin.po +3 -0
- data/po/en_US/rbot-azgame.po +51 -43
- data/po/en_US/rbot-bash.po +15 -0
- data/po/en_US/rbot-dictclient.po +20 -20
- data/po/en_US/rbot-factoids.po +9 -9
- data/po/en_US/rbot-geoip.po +0 -0
- data/po/en_US/rbot-googlefight.po +24 -0
- data/po/en_US/rbot-grouphug.po +4 -4
- data/po/en_US/rbot-hangman.po +114 -0
- data/po/en_US/rbot-keywords.po +3 -3
- data/po/en_US/rbot-lastfm.po +268 -70
- data/po/en_US/rbot-markov.po +73 -2
- data/po/en_US/rbot-quotes.po +21 -21
- data/po/en_US/rbot-rss.po +6 -2
- data/po/en_US/rbot-script.po +3 -0
- data/po/en_US/rbot-seen.po +72 -0
- data/po/en_US/rbot-spell.po +2 -2
- data/po/en_US/rbot-translator.po +13 -13
- data/po/en_US/rbot-twitter.po +3 -3
- data/po/en_US/rbot-uno.po +131 -114
- data/po/en_US/rbot-wall.po +12 -13
- data/po/en_US/rbot-wheelfortune.po +41 -41
- data/po/en_US/rbot.po +254 -194
- data/po/fi/rbot-alias.po +82 -0
- data/po/fi/rbot-autoop.po +0 -0
- data/po/fi/rbot-autorejoin.po +20 -0
- data/po/fi/rbot-azgame.po +194 -0
- data/po/fi/rbot-bans.po +0 -0
- data/po/fi/rbot-bash.po +32 -0
- data/po/fi/rbot-botsnack.po +0 -0
- data/po/fi/rbot-cal.po +20 -0
- data/po/fi/rbot-chanserv.po +0 -0
- data/po/fi/rbot-chucknorris.po +0 -0
- data/po/fi/rbot-debugger.po +0 -0
- data/po/fi/rbot-deepthoughts.po +0 -0
- data/po/fi/rbot-delicious.po +0 -0
- data/po/fi/rbot-dice.po +0 -0
- data/po/fi/rbot-dict.po +0 -0
- data/po/fi/rbot-dictclient.po +111 -0
- data/po/fi/rbot-digg.po +0 -0
- data/po/fi/rbot-eightball.po +0 -0
- data/po/fi/rbot-excuse.po +0 -0
- data/po/fi/rbot-factoids.po +107 -0
- data/po/fi/rbot-figlet.po +36 -0
- data/po/fi/rbot-fish.po +0 -0
- data/po/fi/rbot-forecast.po +0 -0
- data/po/fi/rbot-fortune.po +0 -0
- data/po/fi/rbot-freshmeat.po +0 -0
- data/po/fi/rbot-geoip.po +0 -0
- data/po/fi/rbot-googlefight.po +24 -0
- data/po/fi/rbot-grouphug.po +35 -0
- data/po/fi/rbot-hangman.po +121 -0
- data/po/fi/rbot-hl2.po +0 -0
- data/po/fi/rbot-host.po +20 -0
- data/po/fi/rbot-imdb.po +0 -0
- data/po/fi/rbot-insult.po +0 -0
- data/po/fi/rbot-iplookup.po +0 -0
- data/po/fi/rbot-karma.po +0 -0
- data/po/fi/rbot-keywords.po +24 -0
- data/po/fi/rbot-lart.po +0 -0
- data/po/fi/rbot-lastfm.po +377 -0
- data/po/fi/rbot-linkbot.po +0 -0
- data/po/fi/rbot-markov.po +91 -0
- data/po/fi/rbot-math.po +0 -0
- data/po/fi/rbot-modes.po +0 -0
- data/po/fi/rbot-nickrecover.po +36 -0
- data/po/fi/rbot-nickserv.po +104 -0
- data/po/fi/rbot-nslookup.po +0 -0
- data/po/fi/rbot-quakeauth.po +0 -0
- data/po/fi/rbot-quiz.po +0 -0
- data/po/fi/rbot-quotes.po +108 -0
- data/po/fi/rbot-reaction.po +0 -0
- data/po/fi/rbot-remind.po +0 -0
- data/po/fi/rbot-remotectl.po +0 -0
- data/po/fi/rbot-ri.po +0 -0
- data/po/fi/rbot-roshambo.po +0 -0
- data/po/fi/rbot-rot13.po +0 -0
- data/po/fi/rbot-roulette.po +0 -0
- data/po/fi/rbot-rss.po +24 -0
- data/po/fi/rbot-salut.po +0 -0
- data/po/fi/rbot-script.po +20 -0
- data/po/fi/rbot-search.po +0 -0
- data/po/fi/rbot-seen.po +92 -0
- data/po/fi/rbot-shiritori.po +102 -0
- data/po/fi/rbot-shortenurls.po +0 -0
- data/po/fi/rbot-slashdot.po +0 -0
- data/po/fi/rbot-spell.po +54 -0
- data/po/fi/rbot-theyfightcrime.po +0 -0
- data/po/fi/rbot-threat.po +0 -0
- data/po/fi/rbot-time.po +0 -0
- data/po/fi/rbot-topic.po +0 -0
- data/po/fi/rbot-translator.po +77 -0
- data/po/fi/rbot-tube.po +0 -0
- data/po/fi/rbot-twitter.po +24 -0
- data/po/fi/rbot-uno.po +529 -0
- data/po/fi/rbot-urban.po +0 -0
- data/po/fi/rbot-url.po +0 -0
- data/po/fi/rbot-usermodes.po +0 -0
- data/po/fi/rbot-wall.po +32 -0
- data/po/fi/rbot-weather.po +0 -0
- data/po/fi/rbot-wheelfortune.po +205 -0
- data/po/fi/rbot-wow.po +0 -0
- data/po/fi/rbot-wserver.po +0 -0
- data/po/fi/rbot-youtube.po +58 -0
- data/po/fi/rbot.po +1152 -0
- data/po/fr/rbot-autorejoin.po +3 -0
- data/po/fr/rbot-azgame.po +51 -43
- data/po/fr/rbot-bash.po +15 -0
- data/po/fr/rbot-dictclient.po +20 -20
- data/po/fr/rbot-factoids.po +9 -9
- data/po/fr/rbot-geoip.po +0 -0
- data/po/fr/rbot-googlefight.po +24 -0
- data/po/fr/rbot-grouphug.po +4 -4
- data/po/fr/rbot-hangman.po +114 -0
- data/po/fr/rbot-keywords.po +3 -3
- data/po/fr/rbot-lastfm.po +268 -70
- data/po/fr/rbot-markov.po +74 -2
- data/po/fr/rbot-quotes.po +21 -21
- data/po/fr/rbot-rss.po +6 -2
- data/po/fr/rbot-script.po +3 -0
- data/po/fr/rbot-seen.po +72 -0
- data/po/fr/rbot-spell.po +2 -2
- data/po/fr/rbot-translator.po +13 -13
- data/po/fr/rbot-twitter.po +3 -3
- data/po/fr/rbot-uno.po +132 -114
- data/po/fr/rbot-wall.po +8 -9
- data/po/fr/rbot-wheelfortune.po +41 -41
- data/po/fr/rbot.po +268 -197
- data/po/it/rbot-autorejoin.po +3 -0
- data/po/it/rbot-azgame.po +50 -42
- data/po/it/rbot-bash.po +15 -0
- data/po/it/rbot-dictclient.po +20 -20
- data/po/it/rbot-factoids.po +9 -9
- data/po/it/rbot-geoip.po +0 -0
- data/po/it/rbot-googlefight.po +24 -0
- data/po/it/rbot-grouphug.po +4 -4
- data/po/it/rbot-hangman.po +114 -0
- data/po/it/rbot-keywords.po +3 -3
- data/po/it/rbot-lastfm.po +268 -70
- data/po/it/rbot-markov.po +75 -3
- data/po/it/rbot-quotes.po +21 -21
- data/po/it/rbot-rss.po +7 -3
- data/po/it/rbot-script.po +19 -0
- data/po/it/rbot-seen.po +72 -0
- data/po/it/rbot-spell.po +2 -2
- data/po/it/rbot-translator.po +13 -13
- data/po/it/rbot-twitter.po +3 -3
- data/po/it/rbot-uno.po +137 -116
- data/po/it/rbot-wall.po +8 -9
- data/po/it/rbot-wheelfortune.po +41 -41
- data/po/it/rbot.po +265 -208
- data/po/ja/rbot-autorejoin.po +3 -0
- data/po/ja/rbot-azgame.po +51 -43
- data/po/ja/rbot-bash.po +15 -0
- data/po/ja/rbot-dictclient.po +20 -20
- data/po/ja/rbot-factoids.po +9 -9
- data/po/ja/rbot-geoip.po +0 -0
- data/po/ja/rbot-googlefight.po +24 -0
- data/po/ja/rbot-grouphug.po +4 -4
- data/po/ja/rbot-hangman.po +114 -0
- data/po/ja/rbot-keywords.po +3 -3
- data/po/ja/rbot-lastfm.po +268 -70
- data/po/ja/rbot-markov.po +73 -2
- data/po/ja/rbot-quotes.po +21 -21
- data/po/ja/rbot-rss.po +6 -2
- data/po/ja/rbot-script.po +3 -0
- data/po/ja/rbot-seen.po +72 -0
- data/po/ja/rbot-spell.po +2 -2
- data/po/ja/rbot-translator.po +13 -13
- data/po/ja/rbot-twitter.po +3 -3
- data/po/ja/rbot-uno.po +131 -114
- data/po/ja/rbot-wall.po +8 -9
- data/po/ja/rbot-wheelfortune.po +41 -41
- data/po/ja/rbot.po +248 -192
- data/po/rbot-alias.pot +2 -2
- data/po/rbot-autorejoin.pot +21 -0
- data/po/rbot-azgame.pot +51 -43
- data/po/rbot-bash.pot +33 -0
- data/po/rbot-cal.pot +2 -2
- data/po/rbot-dictclient.pot +21 -21
- data/po/rbot-factoids.pot +10 -10
- data/po/rbot-figlet.pot +2 -2
- data/po/rbot-geoip.pot +0 -0
- data/po/rbot-googlefight.pot +25 -0
- data/po/rbot-grouphug.pot +6 -6
- data/po/rbot-hangman.pot +115 -0
- data/po/rbot-host.pot +2 -2
- data/po/rbot-keywords.pot +4 -4
- data/po/rbot-lastfm.pot +270 -72
- data/po/rbot-markov.pot +74 -3
- data/po/rbot-nickrecover.pot +2 -2
- data/po/rbot-nickserv.pot +2 -2
- data/po/rbot-quotes.pot +22 -22
- data/po/rbot-rss.pot +7 -3
- data/po/rbot-script.pot +21 -0
- data/po/rbot-seen.pot +90 -0
- data/po/rbot-shiritori.pot +2 -2
- data/po/rbot-spell.pot +3 -3
- data/po/rbot-translator.pot +14 -14
- data/po/rbot-twitter.pot +4 -4
- data/po/rbot-uno.pot +132 -115
- data/po/rbot-wall.pot +2 -2
- data/po/rbot-wheelfortune.pot +42 -42
- data/po/rbot-youtube.pot +2 -2
- data/po/rbot.pot +249 -193
- data/po/zh_CN/rbot-autorejoin.po +3 -0
- data/po/zh_CN/rbot-azgame.po +50 -42
- data/po/zh_CN/rbot-bash.po +15 -0
- data/po/zh_CN/rbot-dictclient.po +20 -20
- data/po/zh_CN/rbot-factoids.po +9 -9
- data/po/zh_CN/rbot-geoip.po +0 -0
- data/po/zh_CN/rbot-googlefight.po +24 -0
- data/po/zh_CN/rbot-grouphug.po +4 -4
- data/po/zh_CN/rbot-hangman.po +114 -0
- data/po/zh_CN/rbot-keywords.po +3 -3
- data/po/zh_CN/rbot-lastfm.po +268 -70
- data/po/zh_CN/rbot-markov.po +73 -2
- data/po/zh_CN/rbot-quotes.po +21 -21
- data/po/zh_CN/rbot-rss.po +6 -2
- data/po/zh_CN/rbot-script.po +3 -0
- data/po/zh_CN/rbot-seen.po +72 -0
- data/po/zh_CN/rbot-spell.po +2 -2
- data/po/zh_CN/rbot-translator.po +13 -13
- data/po/zh_CN/rbot-twitter.po +3 -3
- data/po/zh_CN/rbot-uno.po +131 -114
- data/po/zh_CN/rbot-wall.po +7 -8
- data/po/zh_CN/rbot-wheelfortune.po +41 -41
- data/po/zh_CN/rbot.po +248 -192
- data/po/zh_TW/rbot-autorejoin.po +3 -0
- data/po/zh_TW/rbot-azgame.po +50 -42
- data/po/zh_TW/rbot-bash.po +15 -0
- data/po/zh_TW/rbot-dictclient.po +20 -20
- data/po/zh_TW/rbot-factoids.po +9 -9
- data/po/zh_TW/rbot-geoip.po +0 -0
- data/po/zh_TW/rbot-googlefight.po +24 -0
- data/po/zh_TW/rbot-grouphug.po +4 -4
- data/po/zh_TW/rbot-hangman.po +114 -0
- data/po/zh_TW/rbot-keywords.po +3 -3
- data/po/zh_TW/rbot-lastfm.po +268 -70
- data/po/zh_TW/rbot-markov.po +73 -2
- data/po/zh_TW/rbot-quotes.po +21 -21
- data/po/zh_TW/rbot-rss.po +6 -2
- data/po/zh_TW/rbot-script.po +3 -0
- data/po/zh_TW/rbot-seen.po +72 -0
- data/po/zh_TW/rbot-spell.po +2 -2
- data/po/zh_TW/rbot-translator.po +13 -13
- data/po/zh_TW/rbot-twitter.po +3 -3
- data/po/zh_TW/rbot-uno.po +131 -114
- data/po/zh_TW/rbot-wall.po +7 -8
- data/po/zh_TW/rbot-wheelfortune.po +41 -41
- data/po/zh_TW/rbot.po +253 -194
- data/setup.rb +4 -4
- metadata +127 -18
- data/README +0 -43
- data/data/rbot/plugins/fish.rb +0 -121
- data/lib/rbot/dbhash.rb +0 -199
data/data/rbot/plugins/time.rb
CHANGED
@@ -45,13 +45,13 @@ class TimePlugin < Plugin
|
|
45
45
|
end
|
46
46
|
['/', '_'].each { |sp|
|
47
47
|
arr = Array.new
|
48
|
-
zone.split(sp).each{ |s|
|
48
|
+
zone.split(sp).each{ |s|
|
49
49
|
s[0] = s[0,1].upcase
|
50
50
|
s[1, s.length] = s[1, s.length].downcase if sp == '/'
|
51
51
|
arr.push(s) }
|
52
52
|
zone = arr.join( sp )
|
53
53
|
}
|
54
|
-
|
54
|
+
|
55
55
|
tz = TZInfo::Timezone.get( zone )
|
56
56
|
"#{tz.friendly_identifier} - #{tz.now.strftime( '%a %b %d %H:%M' )} #{tz.current_period.abbreviation}"
|
57
57
|
end
|
@@ -39,7 +39,7 @@ class Translator
|
|
39
39
|
@cache = cache
|
40
40
|
end
|
41
41
|
|
42
|
-
|
42
|
+
|
43
43
|
# whether the translator supports this direction
|
44
44
|
def support?(from, to)
|
45
45
|
from != to && @directions[from].include?(to)
|
@@ -110,17 +110,19 @@ class NiftyTranslator < Translator
|
|
110
110
|
def initialize(cache={})
|
111
111
|
require 'mechanize'
|
112
112
|
super(Translator::Direction.all_from_to(%w[ja en zh_CN ko], %w[ja]), cache)
|
113
|
-
@form = WWW::Mechanize.new.
|
114
|
-
get('http://nifty.amikai.com/amitext/indexUTF8.jsp').
|
115
|
-
forms.name('translateForm').first
|
116
113
|
end
|
117
114
|
|
118
115
|
def do_translate(text, from, to)
|
119
|
-
@form
|
120
|
-
|
121
|
-
|
122
|
-
@form.
|
123
|
-
|
116
|
+
@form ||= WWW::Mechanize.new.
|
117
|
+
get('http://nifty.amikai.com/amitext/indexUTF8.jsp').
|
118
|
+
forms_with(:name => 'translateForm').last
|
119
|
+
@radio = @form.radiobuttons_with(:name => 'langpair').first
|
120
|
+
@radio.value = "#{from},#{to}".upcase
|
121
|
+
@radio.check
|
122
|
+
@form.fields_with(:name => 'sourceText').last.value = text
|
123
|
+
|
124
|
+
@form.submit(@form.buttons_with(:name => 'translate').last).
|
125
|
+
forms_with(:name => 'translateForm').last.fields_with(:name => 'translatedText').last.value
|
124
126
|
end
|
125
127
|
end
|
126
128
|
|
@@ -149,7 +151,7 @@ class ExciteTranslator < Translator
|
|
149
151
|
|
150
152
|
def open_form(name)
|
151
153
|
WWW::Mechanize.new.get("http://www.excite.co.jp/world/#{name}").
|
152
|
-
|
154
|
+
forms_with(:name => 'world').first
|
153
155
|
end
|
154
156
|
|
155
157
|
def do_translate(text, from, to)
|
@@ -157,15 +159,15 @@ class ExciteTranslator < Translator
|
|
157
159
|
form = @forms[non_ja_language]
|
158
160
|
|
159
161
|
if non_ja_language =~ /zh_(CN|TW)/
|
160
|
-
|
161
|
-
|
162
|
+
form_with_fields(:name => 'wb_lp').first.value = "#{from}#{to}".sub(/_(?:CN|TW)/, '').upcase
|
163
|
+
form_with_fields(:name => 'big5').first.value = ($1 == 'TW' ? 'yes' : 'no')
|
162
164
|
else
|
163
165
|
# the en<->ja page is in Shift_JIS while other pages are UTF-8
|
164
166
|
text = Iconv.iconv('Shift_JIS', 'UTF-8', text) if non_ja_language == 'en'
|
165
|
-
form.
|
167
|
+
form.fields_with(:name => 'wb_lp').first.value = "#{from}#{to}".upcase
|
166
168
|
end
|
167
|
-
form.
|
168
|
-
result = form.submit.
|
169
|
+
form.fields_with(:name => 'before').first.value = text
|
170
|
+
result = form.submit.forms_with(:name => 'world').first.fields_with(:name => 'after').first.value
|
169
171
|
# the en<->ja page is in Shift_JIS while other pages are UTF-8
|
170
172
|
if non_ja_language == 'en'
|
171
173
|
Iconv.iconv('UTF-8', 'Shift_JIS', result)
|
@@ -180,31 +182,30 @@ end
|
|
180
182
|
class GoogleTranslator < Translator
|
181
183
|
INFO = 'Google Translate <http://www.google.com/translate_t>'
|
182
184
|
|
185
|
+
LANGUAGES =
|
186
|
+
%w[af sq am ar hy az eu be bn bh bg my ca chr zh zh_CN zh_TW hr
|
187
|
+
cs da dv en eo et tl fi fr gl ka de el gn gu iw hi hu is id iu
|
188
|
+
ga it ja kn kk km ko lv lt mk ms ml mt mr mn ne no or ps fa pl
|
189
|
+
pt_PT pa ro ru sa sr sd si sk sl es sw sv tg ta tl te th bo tr
|
190
|
+
uk ur uz ug vi cy yi auto]
|
183
191
|
def initialize(cache={})
|
184
|
-
require
|
185
|
-
|
186
|
-
|
187
|
-
# these options have values like "en|zh-CN"; map to things like ['en', 'zh_CN'].
|
188
|
-
o.value.split('|').map {|l| l.sub('-', '_')}
|
189
|
-
end
|
190
|
-
super(Translator::Direction.pairs(language_pairs), cache)
|
191
|
-
end
|
192
|
-
|
193
|
-
def load_form!
|
194
|
-
agent = WWW::Mechanize.new
|
195
|
-
# without faking the user agent, Google Translate will serve non-UTF-8 text
|
196
|
-
agent.user_agent_alias = 'Linux Konqueror'
|
197
|
-
@form = agent.get('http://www.google.com/translate_t').
|
198
|
-
forms.action('/translate_t').first
|
199
|
-
@lang_list = @form.fields.name('langpair')
|
192
|
+
require "uri"
|
193
|
+
require "json"
|
194
|
+
super(Translator::Direction.all_to_all(LANGUAGES), cache)
|
200
195
|
end
|
201
196
|
|
202
197
|
def do_translate(text, from, to)
|
203
|
-
|
198
|
+
langpair = [from == 'auto' ? '' : from, to].map { |e| e.tr('_', '-') }.join("|")
|
199
|
+
raw_json = Irc::Utils.bot.httputil.get_response(URI.escape(
|
200
|
+
"http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=#{text}&langpair=#{langpair}")).body
|
201
|
+
response = JSON.parse(raw_json)
|
204
202
|
|
205
|
-
|
206
|
-
|
207
|
-
|
203
|
+
if response["responseStatus"] != 200
|
204
|
+
raise Translator::NoTranslationError, response["responseDetails"]
|
205
|
+
else
|
206
|
+
translation = response["responseData"]["translatedText"]
|
207
|
+
return Utils.decode_html_entities(translation)
|
208
|
+
end
|
208
209
|
end
|
209
210
|
end
|
210
211
|
|
@@ -214,23 +215,31 @@ class BabelfishTranslator < Translator
|
|
214
215
|
|
215
216
|
def initialize(cache)
|
216
217
|
require 'mechanize'
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
@lang_list = @form.fields.name('lp')
|
221
|
-
language_pairs = @lang_list.options.map {|o| o.value.split('_')}.
|
222
|
-
reject {|p| p.empty?}
|
218
|
+
(_, lang_list) = parse_page
|
219
|
+
language_pairs = lang_list.options.map {|o| o.value.split('_')}.
|
220
|
+
reject {|p| p.empty?}
|
223
221
|
super(Translator::Direction.pairs(language_pairs), cache)
|
224
222
|
end
|
225
223
|
|
224
|
+
def parse_page
|
225
|
+
form = WWW::Mechanize.new.get('http://babelfish.altavista.com/babelfish/').
|
226
|
+
forms_with(:name => 'frmTrText').first
|
227
|
+
lang_list = form.fields_with(:name => 'lp').first
|
228
|
+
[form, lang_list]
|
229
|
+
end
|
230
|
+
|
226
231
|
def do_translate(text, from, to)
|
227
|
-
|
232
|
+
unless @form && @lang_list
|
233
|
+
@form, @lang_list = parse_page
|
234
|
+
end
|
235
|
+
|
236
|
+
if @form.fields_with(:name => 'trtext').empty?
|
228
237
|
@form.add_field!('trtext', text)
|
229
238
|
else
|
230
|
-
@form.
|
239
|
+
@form.fields_with(:name => 'trtext').first.value = text
|
231
240
|
end
|
232
241
|
@lang_list.value = "#{from}_#{to}"
|
233
|
-
@form.submit.parser.search("
|
242
|
+
@form.submit.parser.search("div[@id='result']/div[@style]").inner_html
|
234
243
|
end
|
235
244
|
end
|
236
245
|
|
@@ -260,6 +269,9 @@ class TranslatorPlugin < Plugin
|
|
260
269
|
Config.register Config::IntegerValue.new('translator.timeout',
|
261
270
|
:default => 30, :validate => Proc.new{|v| v > 0},
|
262
271
|
:desc => _("Number of seconds to wait for the translation service before timeout"))
|
272
|
+
Config.register Config::StringValue.new('translator.destination',
|
273
|
+
:default => "en",
|
274
|
+
:desc => _("Default destination language to be used with translate command"))
|
263
275
|
|
264
276
|
TRANSLATORS = {
|
265
277
|
'nifty' => NiftyTranslator,
|
@@ -271,16 +283,13 @@ class TranslatorPlugin < Plugin
|
|
271
283
|
|
272
284
|
def initialize
|
273
285
|
super
|
274
|
-
|
286
|
+
@failed_translators = []
|
275
287
|
@translators = {}
|
276
288
|
TRANSLATORS.each_pair do |name, c|
|
277
|
-
|
289
|
+
watch_for_fail(name) do
|
278
290
|
@translators[name] = c.new(@registry.sub_registry(name))
|
279
291
|
map "#{name} :from :to *phrase",
|
280
292
|
:action => :cmd_translate, :thread => true
|
281
|
-
rescue Exception
|
282
|
-
warning _("Translator %{name} cannot be used: %{reason}") %
|
283
|
-
{:name => name, :reason => $!}
|
284
293
|
end
|
285
294
|
end
|
286
295
|
|
@@ -292,34 +301,95 @@ class TranslatorPlugin < Plugin
|
|
292
301
|
update_default
|
293
302
|
end
|
294
303
|
|
304
|
+
def watch_for_fail(name, &block)
|
305
|
+
begin
|
306
|
+
yield
|
307
|
+
rescue Exception
|
308
|
+
@failed_translators << { :name => name, :reason => $!.to_s }
|
309
|
+
|
310
|
+
warning _("Translator %{name} cannot be used: %{reason}") %
|
311
|
+
{:name => name, :reason => $!}
|
312
|
+
map "#{name} [*args]", :action => :failed_translator,
|
313
|
+
:defaults => {:name => name, :reason => $!}
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
def failed_translator(m, params)
|
318
|
+
m.reply _("Translator %{name} cannot be used: %{reason}") %
|
319
|
+
{:name => params[:name], :reason => params[:reason]}
|
320
|
+
end
|
321
|
+
|
295
322
|
def help(plugin, topic=nil)
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
:
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
323
|
+
case (topic.intern rescue nil)
|
324
|
+
when :failed
|
325
|
+
unless @failed_translators.empty?
|
326
|
+
failed_list = @failed_translators.map { |t| _("%{bold}%{translator}%{bold}: %{reason}") % {
|
327
|
+
:translator => t[:name],
|
328
|
+
:reason => t[:reason],
|
329
|
+
:bold => Bold
|
330
|
+
}}
|
331
|
+
|
332
|
+
_("Failed translators: %{list}") % { :list => failed_list.join(", ") }
|
333
|
+
else
|
334
|
+
_("None of the translators failed")
|
335
|
+
end
|
306
336
|
else
|
307
|
-
|
308
|
-
|
337
|
+
if @translators.has_key?(plugin)
|
338
|
+
translator = @translators[plugin]
|
339
|
+
_('%{translator} <from> <to> <phrase> => Look up phrase using %{info}, supported from -> to languages: %{directions}') % {
|
340
|
+
:translator => plugin,
|
341
|
+
:info => translator.class::INFO,
|
342
|
+
:directions => translator.directions.map do |source, targets|
|
343
|
+
_('%{source} -> %{targets}') %
|
344
|
+
{:source => source, :targets => targets.to_a.join(', ')}
|
345
|
+
end.join(' | ')
|
346
|
+
}
|
347
|
+
else
|
348
|
+
help_str = _('Command: <translator> <from> <to> <phrase>, where <translator> is one of: %{translators}. If "translator" is used in place of the translator name, the first translator in translator.default_list which supports the specified direction will be picked automatically. Use "help <translator>" to look up supported from and to languages') %
|
349
|
+
{:translators => @translators.keys.join(', ')}
|
350
|
+
|
351
|
+
help_str << "\n" + _("%{bold}Note%{bold}: %{failed_amt} translators failed, see %{reverse}%{prefix}help translate failed%{reverse} for details") % {
|
352
|
+
:failed_amt => @failed_translators.size,
|
353
|
+
:bold => Bold,
|
354
|
+
:reverse => Reverse,
|
355
|
+
:prefix => @bot.config['core.address_prefix'].first
|
356
|
+
}
|
357
|
+
|
358
|
+
help_str
|
359
|
+
end
|
309
360
|
end
|
310
361
|
end
|
311
362
|
|
363
|
+
def languages
|
364
|
+
@languages ||= @translators.map { |t| t.last.directions.keys }.flatten.uniq
|
365
|
+
end
|
366
|
+
|
312
367
|
def update_default
|
313
|
-
@default_translators = bot.config['translator.default_list'] & @translators.keys
|
368
|
+
@default_translators = bot.config['translator.default_list'] & @translators.keys
|
314
369
|
end
|
315
370
|
|
316
371
|
def cmd_translator(m, params)
|
317
|
-
|
318
|
-
|
372
|
+
params[:to] = @bot.config['translator.destination'] if params[:to].nil?
|
373
|
+
params[:from] ||= 'auto'
|
374
|
+
translator = @default_translators.find {|t| @translators[t].support?(params[:from], params[:to])}
|
375
|
+
|
319
376
|
if translator
|
320
377
|
cmd_translate m, params.merge({:translator => translator, :show_provider => true})
|
321
378
|
else
|
322
|
-
|
379
|
+
# When translate command is used without source language, "auto" as source
|
380
|
+
# language is assumed. It means that google translator is used and we let google
|
381
|
+
# figure out what the source language is.
|
382
|
+
#
|
383
|
+
# Problem is that the google translator will fail if the system that the bot is
|
384
|
+
# running on does not have the json gem installed.
|
385
|
+
if params[:from] == 'auto'
|
386
|
+
m.reply _("Unable to auto-detect source language due to broken google translator, see %{reverse}%{prefix}help translate failed%{reverse} for details") % {
|
387
|
+
:reverse => Reverse,
|
388
|
+
:prefix => @bot.config['core.address_prefix'].first
|
389
|
+
}
|
390
|
+
else
|
391
|
+
m.reply _('None of the default translators (translator.default_list) supports translating from %{source} to %{target}') % {:source => params[:from], :target => params[:to]}
|
392
|
+
end
|
323
393
|
end
|
324
394
|
end
|
325
395
|
|
@@ -329,25 +399,27 @@ class TranslatorPlugin < Plugin
|
|
329
399
|
translator = @translators[tname]
|
330
400
|
from, to, phrase = params[:from], params[:to], params[:phrase].to_s
|
331
401
|
if translator
|
332
|
-
|
333
|
-
|
334
|
-
translator.
|
402
|
+
watch_for_fail(tname) do
|
403
|
+
begin
|
404
|
+
translation = Timeout.timeout(@bot.config['translator.timeout']) do
|
405
|
+
translator.translate(phrase, from, to)
|
406
|
+
end
|
407
|
+
m.reply(if params[:show_provider]
|
408
|
+
_('%{translation} (provided by %{translator})') %
|
409
|
+
{:translation => translation, :translator => tname.gsub("_", " ")}
|
410
|
+
else
|
411
|
+
translation
|
412
|
+
end)
|
413
|
+
|
414
|
+
rescue Translator::UnsupportedDirectionError
|
415
|
+
m.reply _("%{translator} doesn't support translating from %{source} to %{target}") %
|
416
|
+
{:translator => tname, :source => from, :target => to}
|
417
|
+
rescue Translator::NoTranslationError
|
418
|
+
m.reply _('%{translator} failed to provide a translation') %
|
419
|
+
{:translator => tname}
|
420
|
+
rescue Timeout::Error
|
421
|
+
m.reply _('The translator timed out')
|
335
422
|
end
|
336
|
-
m.reply(if params[:show_provider]
|
337
|
-
_('%{translation} (provided by %{translator})') %
|
338
|
-
{:translation => translation, :translator => tname}
|
339
|
-
else
|
340
|
-
translation
|
341
|
-
end)
|
342
|
-
|
343
|
-
rescue Translator::UnsupportedDirectionError
|
344
|
-
m.reply _("%{translator} doesn't support translating from %{source} to %{target}") %
|
345
|
-
{:translator => tname, :source => from, :target => to}
|
346
|
-
rescue Translator::NoTranslationError
|
347
|
-
m.reply _('%{translator} failed to provide a translation') %
|
348
|
-
{:translator => tname}
|
349
|
-
rescue Timeout::Error
|
350
|
-
m.reply _('The translator timed out')
|
351
423
|
end
|
352
424
|
else
|
353
425
|
m.reply _('No translator called %{name}') % {:name => tname}
|
@@ -356,5 +428,9 @@ class TranslatorPlugin < Plugin
|
|
356
428
|
end
|
357
429
|
|
358
430
|
plugin = TranslatorPlugin.new
|
359
|
-
|
360
|
-
|
431
|
+
req = Hash[*%w(from to).map { |e| [e.to_sym, /#{plugin.languages.join("|")}/] }.flatten]
|
432
|
+
|
433
|
+
plugin.map 'translate [:from] [:to] *phrase',
|
434
|
+
:action => :cmd_translator, :thread => true, :requirements => req
|
435
|
+
plugin.map 'translator [:from] [:to] *phrase',
|
436
|
+
:action => :cmd_translator, :thread => true, :requirements => req
|
data/data/rbot/plugins/tube.rb
CHANGED
@@ -5,7 +5,7 @@ class TubePlugin < Plugin
|
|
5
5
|
def help(plugin, topic="")
|
6
6
|
"tube [district|circle|metropolitan|central|jubilee|bakerloo|waterlooandcity|hammersmithandcity|victoria|eastlondon|northern|piccadilly] => display tube service status for the specified line(Docklands Light Railway is not currently supported)" # , tube stations => list tube stations (not lines) with problems"
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
def tube(m, params)
|
10
10
|
line = params[:line]
|
11
11
|
tube_page = @bot.httputil.get('http://www.tfl.gov.uk/tfl/livetravelnews/realtime/tube/default.html')
|
@@ -45,7 +45,7 @@ class TubePlugin < Plugin
|
|
45
45
|
stations_array.push $1
|
46
46
|
end
|
47
47
|
}
|
48
|
-
if stations_array.empty?
|
48
|
+
if stations_array.empty?
|
49
49
|
m.reply "There are no station-specific announcements"
|
50
50
|
return
|
51
51
|
else
|
@@ -0,0 +1,143 @@
|
|
1
|
+
#-- vim:sw=2:et
|
2
|
+
#++
|
3
|
+
#
|
4
|
+
# :title: tumblr interface
|
5
|
+
#
|
6
|
+
# Author:: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
|
7
|
+
# Copyright:: (C) 2009 Giuseppe Bilotta
|
8
|
+
# License:: GPLv2
|
9
|
+
#
|
10
|
+
# Submit URLs to channel-specific tumblr accounts
|
11
|
+
#
|
12
|
+
# TODO reblog tumblr URLs
|
13
|
+
# TODO support video better (e.g. Vimeo or anything else with embed)
|
14
|
+
# TODO support image better (e.g. pages with a single big image)
|
15
|
+
# TODO customize caption/description format
|
16
|
+
|
17
|
+
require 'rexml/document'
|
18
|
+
require 'cgi'
|
19
|
+
|
20
|
+
class TumblrPlugin < Plugin
|
21
|
+
RBOT = CGI.escape("rbot #{$version.split.first}")
|
22
|
+
WRITE_URL = "http://www.tumblr.com/api/write"
|
23
|
+
LOGIN = "email=%{email}&password=%{pwd}&group=%{group}&format=markdown&generator=" + RBOT
|
24
|
+
PHOTO = "&type=photo&source=%{src}&click-through-url=%{src}"
|
25
|
+
VIDEO = "&type=video&embed=%{src}"
|
26
|
+
CAPTION = "&caption=%{desc}"
|
27
|
+
LINK = "&type=link&url=%{src}"
|
28
|
+
DESC = "&name=%{desc}"
|
29
|
+
|
30
|
+
def help(plugin, topic="")
|
31
|
+
case topic
|
32
|
+
when "configure"
|
33
|
+
"tumblr configure [<channel>]: show credentials used for channel <channel> (default: current). tumblr configure [<channel>] <email> <password> [<group>] => post links from channel <channel> (default: current) to group <group> (default: name of channel) using the given tumblr credentials"
|
34
|
+
when "deconfigure"
|
35
|
+
"tumblr deconfigure [<channel>]: forget credentials for channel <channel> (default: current)."
|
36
|
+
else
|
37
|
+
"post links, photos and videos to a channel-specific tumblr. topics: configure, deconfigure"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def event_url_added(url, options={})
|
42
|
+
return unless options.key? :channel
|
43
|
+
chan = options[:channel]
|
44
|
+
return unless @registry.key? chan
|
45
|
+
|
46
|
+
account = @registry[chan]
|
47
|
+
|
48
|
+
line = options[:ircline]
|
49
|
+
line = nil if line and line.empty?
|
50
|
+
if line and nick = options[:nick]
|
51
|
+
line = "<#{nick}> #{line}"
|
52
|
+
end
|
53
|
+
|
54
|
+
req = LOGIN % account
|
55
|
+
type = options[:htmlinfo][:headers]['content-type'].first rescue nil
|
56
|
+
case type
|
57
|
+
when /^image\/.*/
|
58
|
+
data = PHOTO
|
59
|
+
data << CAPTION if line
|
60
|
+
else
|
61
|
+
if url.match(%r{^http://(\w+\.)?youtube\.com/watch.*})
|
62
|
+
data = VIDEO
|
63
|
+
data << CAPTION if line
|
64
|
+
else
|
65
|
+
data = LINK
|
66
|
+
data << DESC if line
|
67
|
+
end
|
68
|
+
end
|
69
|
+
req << (data % { :src => CGI.escape(url), :desc => CGI.escape(line) })
|
70
|
+
debug "posting #{req.inspect}"
|
71
|
+
resp = @bot.httputil.post(WRITE_URL, req)
|
72
|
+
debug "tumblr response: #{resp.inspect}"
|
73
|
+
end
|
74
|
+
|
75
|
+
def configuration(m, params={})
|
76
|
+
channel = params[:channel] || m.channel
|
77
|
+
if not channel
|
78
|
+
m.reply _("Please specify a channel")
|
79
|
+
return
|
80
|
+
end
|
81
|
+
if not @registry.key? channel
|
82
|
+
m.reply _("No tumblr credentials set for %{chan}" % { :chan => channel })
|
83
|
+
return false
|
84
|
+
end
|
85
|
+
|
86
|
+
account = @registry[channel]
|
87
|
+
|
88
|
+
account[:pwd] = _("<hidden>") if m.public?
|
89
|
+
account[:chan] = channel
|
90
|
+
|
91
|
+
m.reply _("Links on %{chan} will go to %{group} using account %{email} and password %{pwd}" % account)
|
92
|
+
end
|
93
|
+
|
94
|
+
def deconfigure(m, params={})
|
95
|
+
channel = params[:channel] || m.channel
|
96
|
+
if not channel
|
97
|
+
m.reply _("Please specify a channel")
|
98
|
+
return
|
99
|
+
end
|
100
|
+
if not @registry.key? channel
|
101
|
+
m.reply _("No tumblr credentials set for %{chan}" % { :chan => channel })
|
102
|
+
return false
|
103
|
+
end
|
104
|
+
|
105
|
+
@registry.delete channel
|
106
|
+
|
107
|
+
m.reply _("Links on %{chan} will not be posted to tumblr anymore" % {:chan => channel})
|
108
|
+
end
|
109
|
+
|
110
|
+
def configure(m, params={})
|
111
|
+
channel = params[:channel] || m.channel
|
112
|
+
if not channel
|
113
|
+
m.reply _("Please specify a channel")
|
114
|
+
return
|
115
|
+
end
|
116
|
+
if @registry.key? channel
|
117
|
+
m.reply _("%{chan} already has credentials configured" % { :chan => channel })
|
118
|
+
else
|
119
|
+
group = params[:group] || Channel.npname(channel)
|
120
|
+
group << ".tumblr.com" unless group.match(/\.tumblr\.com/)
|
121
|
+
@registry[channel] = {
|
122
|
+
:email => CGI.escape(params[:email]),
|
123
|
+
:pwd => CGI.escape(params[:pwd]),
|
124
|
+
:group => CGI.escape(group)
|
125
|
+
}
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
return configuration(m, params)
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
plugin = TumblrPlugin.new
|
135
|
+
|
136
|
+
plugin.default_auth('*', false)
|
137
|
+
|
138
|
+
plugin.map 'tumblr configure [:channel]', :action => :configuration
|
139
|
+
plugin.map 'tumblr deconfigure [:channel]', :action => :deconfigure
|
140
|
+
plugin.map 'tumblr configure [:channel] :email :pwd [:group]',
|
141
|
+
:action => :configure,
|
142
|
+
:requirements => {:channel => Regexp::Irc::GEN_CHAN, :email => /.+@.+/, :group => /[A-Za-z-]+/}
|
143
|
+
|