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
data/lib/rbot/language.rb
CHANGED
@@ -1,9 +1,64 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
#-- vim:sw=2:et
|
2
|
+
#++
|
3
|
+
#
|
4
|
+
# :title: Language module for rbot
|
5
|
+
#
|
6
|
+
# This module takes care of language handling for rbot:
|
7
|
+
# setting the core.language value, loading the appropriate
|
8
|
+
# .lang file etc.
|
3
9
|
|
10
|
+
module Irc
|
11
|
+
class Bot
|
4
12
|
class Language
|
5
|
-
|
6
|
-
|
13
|
+
|
14
|
+
# This constant hash holds the mapping
|
15
|
+
# from long language names to the usual POSIX
|
16
|
+
# locale specifications
|
17
|
+
Lang2Locale = {
|
18
|
+
:english => 'en',
|
19
|
+
:british_english => 'en_GB',
|
20
|
+
:american_english => 'en_US',
|
21
|
+
:italian => 'it',
|
22
|
+
:french => 'fr',
|
23
|
+
:german => 'de',
|
24
|
+
:dutch => 'nl',
|
25
|
+
:japanese => 'ja',
|
26
|
+
:russian => 'ru',
|
27
|
+
:traditional_chinese => 'zh_TW',
|
28
|
+
:simplified_chinese => 'zh_CN'
|
29
|
+
}
|
30
|
+
# On WIN32 it appears necessary to have ".UTF-8" explicitly for gettext to use UTF-8
|
31
|
+
Lang2Locale.each_value {|v| v.replace(v + '.UTF-8')}
|
32
|
+
|
33
|
+
# Return the shortest language for the current
|
34
|
+
# GetText locale
|
35
|
+
def Language.from_locale
|
36
|
+
return 'english' unless defined?(GetText)
|
37
|
+
lang = locale.language
|
38
|
+
if locale.country
|
39
|
+
str = lang + "_#{locale.country}"
|
40
|
+
if Lang2Locale.value?(str)
|
41
|
+
# Get the shortest key in Lang2Locale which maps to the given lang_country
|
42
|
+
lang_str = Lang2Locale.select { |k, v| v == str }.transpose.first.map { |v| v.to_s }.sort { |a, b| a.length <=> b.length }.first
|
43
|
+
if File.exist?(File.join(Config::datadir, "languages/#{lang_str}.lang"))
|
44
|
+
return lang_str
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
# lang_country didn't work, let's try lan
|
49
|
+
if Lang2Locale.value?(lang)
|
50
|
+
# Get the shortest key in Lang2Locale which maps to the given lang
|
51
|
+
lang_str = Lang2Locale.select { |k, v| v == lang }.transpose.first.map { |v| v.to_s }.sort { |a, b| a.length <=> b.length }.first
|
52
|
+
if File.exist?(File.join(Config::datadir, "/languages/#{lang_str}.lang"))
|
53
|
+
return lang_str
|
54
|
+
end
|
55
|
+
end
|
56
|
+
# all else fail, return 'english'
|
57
|
+
return 'english'
|
58
|
+
end
|
59
|
+
|
60
|
+
Config.register Config::EnumValue.new('core.language',
|
61
|
+
:default => Irc::Bot::Language.from_locale, :wizard => true,
|
7
62
|
:values => Proc.new{|bot|
|
8
63
|
Dir.new(Config::datadir + "/languages").collect {|f|
|
9
64
|
f =~ /\.lang$/ ? f.gsub(/\.lang$/, "") : nil
|
@@ -12,18 +67,41 @@ module Language
|
|
12
67
|
:on_change => Proc.new {|bot, v| bot.lang.set_language v},
|
13
68
|
:desc => "Which language file the bot should use")
|
14
69
|
|
15
|
-
def initialize(language)
|
70
|
+
def initialize(bot, language)
|
71
|
+
@bot = bot
|
16
72
|
set_language language
|
17
73
|
end
|
74
|
+
attr_reader :language
|
18
75
|
|
19
76
|
def set_language(language)
|
20
|
-
|
77
|
+
lang_str = language.to_s.downcase.gsub(/\s+/,'_')
|
78
|
+
lang_sym = lang_str.intern
|
79
|
+
if defined?(GetText) and Lang2Locale.key?(lang_sym)
|
80
|
+
setlocale(Lang2Locale[lang_sym])
|
81
|
+
debug "locale set to #{locale}"
|
82
|
+
rbot_gettext_debug
|
83
|
+
else
|
84
|
+
warning "Unable to set locale, unknown language #{language} (#{lang_str})"
|
85
|
+
end
|
86
|
+
|
87
|
+
file = Config::datadir + "/languages/#{lang_str}.lang"
|
21
88
|
unless(FileTest.exist?(file))
|
22
|
-
raise "no such language: #{
|
89
|
+
raise "no such language: #{lang_str} (no such file #{file})"
|
23
90
|
end
|
24
|
-
@language =
|
91
|
+
@language = lang_str
|
25
92
|
@file = file
|
26
93
|
scan
|
94
|
+
return if @bot.plugins.nil?
|
95
|
+
@bot.plugins.core_modules.each { |p|
|
96
|
+
if p.respond_to?('set_language')
|
97
|
+
p.set_language(@language)
|
98
|
+
end
|
99
|
+
}
|
100
|
+
@bot.plugins.plugins.each { |p|
|
101
|
+
if p.respond_to?('set_language')
|
102
|
+
p.set_language(@language)
|
103
|
+
end
|
104
|
+
}
|
27
105
|
end
|
28
106
|
|
29
107
|
def scan
|
@@ -0,0 +1,154 @@
|
|
1
|
+
#-- vim:sw=2:et
|
2
|
+
#++
|
3
|
+
#
|
4
|
+
# :title: GetText interface for rbot
|
5
|
+
#
|
6
|
+
# Load gettext module and provide fallback in case of failure
|
7
|
+
|
8
|
+
class GetTextVersionError < Exception
|
9
|
+
end
|
10
|
+
|
11
|
+
# try to load gettext, or provide fake getttext functions
|
12
|
+
begin
|
13
|
+
require 'gettext/version'
|
14
|
+
|
15
|
+
gettext_version = GetText::VERSION.split('.').map {|n| n.to_i}
|
16
|
+
include Comparable # for Array#>=
|
17
|
+
unless gettext_version >= [1, 8, 0]
|
18
|
+
raise GetTextVersionError, "Unsupported ruby-gettext version installed: #{gettext_version.join '.'}; supported versions are 1.8.0 and above"
|
19
|
+
end
|
20
|
+
|
21
|
+
require 'gettext'
|
22
|
+
|
23
|
+
include GetText
|
24
|
+
|
25
|
+
add_default_locale_path(File.join(Irc::Bot::Config.datadir, "../locale/%{locale}/LC_MESSAGES/%{name}.mo"))
|
26
|
+
|
27
|
+
if GetText.respond_to? :cached=
|
28
|
+
GetText.cached = false
|
29
|
+
else
|
30
|
+
warning 'This version of ruby-gettext does not support non-cached mode; mo files are not reloaded when setting language'
|
31
|
+
end
|
32
|
+
bindtextdomain 'rbot'
|
33
|
+
|
34
|
+
module GetText
|
35
|
+
# patch for ruby-gettext 1.8.0 up to 1.10.0 (and more?) to cope with anonymous
|
36
|
+
# modules used by rbot
|
37
|
+
# FIXME remove the patch when ruby-gettext is fixed, or rbot switches to named modules
|
38
|
+
if !instance_methods.include?('orig_bound_targets')
|
39
|
+
alias :orig_bound_targets :bound_targets
|
40
|
+
end
|
41
|
+
def bound_targets(*a) # :nodoc:
|
42
|
+
bt = orig_bound_targets(*a) rescue []
|
43
|
+
bt.empty? ? orig_bound_targets(Object) : bt
|
44
|
+
end
|
45
|
+
|
46
|
+
require 'stringio'
|
47
|
+
|
48
|
+
# This method is used to output debug information on the GetText
|
49
|
+
# textdomain, and it's called by the language setting routines
|
50
|
+
# in rbot
|
51
|
+
def rbot_gettext_debug
|
52
|
+
begin
|
53
|
+
gettext_info = StringIO.new
|
54
|
+
current_textdomain_info(:out => gettext_info) # fails sometimes
|
55
|
+
rescue Exception
|
56
|
+
warning "gettext failed to set call textdomain info. maybe an mo file doesn't exist for your locale."
|
57
|
+
ensure
|
58
|
+
gettext_info.string.each_line { |l| debug l}
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
log "gettext loaded"
|
64
|
+
|
65
|
+
rescue LoadError, GetTextVersionError
|
66
|
+
warning "failed to load ruby-gettext package: #{$!}; translations are disabled"
|
67
|
+
|
68
|
+
# undefine GetText, in case it got defined because the error was caused by a
|
69
|
+
# wrong version
|
70
|
+
if defined?(GetText)
|
71
|
+
Object.module_eval { remove_const("GetText") }
|
72
|
+
end
|
73
|
+
|
74
|
+
# dummy functions that return msg_id without translation
|
75
|
+
def _(s)
|
76
|
+
s
|
77
|
+
end
|
78
|
+
|
79
|
+
def N_(s)
|
80
|
+
s
|
81
|
+
end
|
82
|
+
|
83
|
+
def n_(s_single, s_plural, n)
|
84
|
+
n > 1 ? s_plural : s_single
|
85
|
+
end
|
86
|
+
|
87
|
+
def Nn_(s_single, s_plural)
|
88
|
+
n_(s_single, s_plural)
|
89
|
+
end
|
90
|
+
|
91
|
+
def s_(*args)
|
92
|
+
args[0]
|
93
|
+
end
|
94
|
+
|
95
|
+
def bindtextdomain_to(*args)
|
96
|
+
end
|
97
|
+
|
98
|
+
# the following extension to String#% is from ruby-gettext's string.rb file.
|
99
|
+
# it needs to be included in the fallback since the source already use this form
|
100
|
+
|
101
|
+
=begin
|
102
|
+
string.rb - Extension for String.
|
103
|
+
|
104
|
+
Copyright (C) 2005,2006 Masao Mutoh
|
105
|
+
|
106
|
+
You may redistribute it and/or modify it under the same
|
107
|
+
license terms as Ruby.
|
108
|
+
=end
|
109
|
+
|
110
|
+
# Extension for String class.
|
111
|
+
#
|
112
|
+
# String#% method which accept "named argument". The translator can know
|
113
|
+
# the meaning of the msgids using "named argument" instead of %s/%d style.
|
114
|
+
class String
|
115
|
+
alias :_old_format_m :% # :nodoc:
|
116
|
+
|
117
|
+
# call-seq:
|
118
|
+
# %(arg)
|
119
|
+
# %(hash)
|
120
|
+
#
|
121
|
+
# Format - Uses str as a format specification, and returns the result of applying it to arg.
|
122
|
+
# If the format specification contains more than one substitution, then arg must be
|
123
|
+
# an Array containing the values to be substituted. See Kernel::sprintf for details of the
|
124
|
+
# format string. This is the default behavior of the String class.
|
125
|
+
# * arg: an Array or other class except Hash.
|
126
|
+
# * Returns: formatted String
|
127
|
+
#
|
128
|
+
# (e.g.) "%s, %s" % ["Masao", "Mutoh"]
|
129
|
+
#
|
130
|
+
# Also you can use a Hash as the "named argument". This is recommanded way for Ruby-GetText
|
131
|
+
# because the translators can understand the meanings of the msgids easily.
|
132
|
+
# * hash: {:key1 => value1, :key2 => value2, ... }
|
133
|
+
# * Returns: formatted String
|
134
|
+
#
|
135
|
+
# (e.g.) "%{firstname}, %{familyname}" % {:firstname => "Masao", :familyname => "Mutoh"}
|
136
|
+
def %(args)
|
137
|
+
if args.kind_of?(Hash)
|
138
|
+
ret = dup
|
139
|
+
args.each {|key, value|
|
140
|
+
ret.gsub!(/\%\{#{key}\}/, value.to_s)
|
141
|
+
}
|
142
|
+
ret
|
143
|
+
else
|
144
|
+
ret = gsub(/%\{/, '%%{')
|
145
|
+
begin
|
146
|
+
ret._old_format_m(args)
|
147
|
+
rescue ArgumentError
|
148
|
+
$stderr.puts " The string:#{ret}"
|
149
|
+
$stderr.puts " args:#{args.inspect}"
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
data/lib/rbot/maskdb.rb
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
module Irc
|
2
|
+
class NetmaskDb
|
3
|
+
# helper backend class: generic nested radix tree
|
4
|
+
class Tree
|
5
|
+
attr_reader :pre, :chi
|
6
|
+
|
7
|
+
def initialize(pre = '', chi = Hash.new)
|
8
|
+
@pre = pre
|
9
|
+
@chi = chi
|
10
|
+
end
|
11
|
+
|
12
|
+
def add(val, *prefs)
|
13
|
+
str = prefs.shift or raise 'empty prefs'
|
14
|
+
@pre = str.dup if @chi.empty?
|
15
|
+
|
16
|
+
n = 0
|
17
|
+
@pre.size.times do
|
18
|
+
break if @pre[n] != str[n]
|
19
|
+
n += 1
|
20
|
+
end
|
21
|
+
|
22
|
+
rest = str.slice(n .. -1)
|
23
|
+
|
24
|
+
if n != @pre.size
|
25
|
+
prest = @pre.slice!(n .. -1)
|
26
|
+
pc = prest.slice! 0
|
27
|
+
@chi = {pc => Tree.new(prest, @chi)}
|
28
|
+
end
|
29
|
+
|
30
|
+
c = rest.slice!(0)
|
31
|
+
|
32
|
+
if c
|
33
|
+
(@chi[c] ||= Tree.new).add(val, rest, *prefs)
|
34
|
+
else
|
35
|
+
if prefs.empty?
|
36
|
+
(@chi[''] ||= Array.new).push val
|
37
|
+
else
|
38
|
+
(@chi[''] ||= Tree.new).add(val, *prefs)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def empty?
|
44
|
+
@chi.empty?
|
45
|
+
end
|
46
|
+
|
47
|
+
def remove(*prefs, &block)
|
48
|
+
str = prefs.shift or raise 'empty prefs?'
|
49
|
+
return nil unless @pre.empty? or str.index(@pre) == 0
|
50
|
+
c = str.slice(@pre.size) || ''
|
51
|
+
return nil unless @chi.include? c
|
52
|
+
if c == ''
|
53
|
+
if prefs.empty?
|
54
|
+
@chi[c].reject!(&block)
|
55
|
+
else
|
56
|
+
@chi[c].remove(*prefs, &block)
|
57
|
+
end
|
58
|
+
else
|
59
|
+
@chi[c].remove(str.slice((@pre.size + 1) .. -1), *prefs, &block)
|
60
|
+
end
|
61
|
+
@chi.delete(c) if @chi[c].empty?
|
62
|
+
|
63
|
+
if @chi.size == 1
|
64
|
+
k = @chi.keys.shift
|
65
|
+
return nil if k == ''
|
66
|
+
@pre << k << @chi[k].pre
|
67
|
+
@chi = @chi[k].chi
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def find(*prefs)
|
72
|
+
str = prefs.shift or raise 'empty prefs?'
|
73
|
+
self.find_helper(str, *prefs) + self.find_helper(str.reverse, *prefs)
|
74
|
+
end
|
75
|
+
|
76
|
+
protected
|
77
|
+
def find_helper(*prefs)
|
78
|
+
str = prefs.shift or raise 'empty prefs?'
|
79
|
+
return [] unless @pre.empty? or str.index(@pre) == 0
|
80
|
+
# puts "#{self.inspect}: #{str} == #{@pre} pfx matched"
|
81
|
+
if !@chi.include? ''
|
82
|
+
matches = []
|
83
|
+
elsif Array === @chi['']
|
84
|
+
matches = @chi['']
|
85
|
+
else
|
86
|
+
matches = @chi[''].find(*prefs)
|
87
|
+
end
|
88
|
+
|
89
|
+
c = str.slice(@pre.size)
|
90
|
+
|
91
|
+
more = []
|
92
|
+
if c and @chi.include?(c)
|
93
|
+
more = @chi[c].find_helper(str.slice((@pre.size + 1) .. -1), *prefs)
|
94
|
+
end
|
95
|
+
return more + matches
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# api wrapper for netmasks
|
100
|
+
|
101
|
+
def initialize
|
102
|
+
@tree = Tree.new
|
103
|
+
end
|
104
|
+
|
105
|
+
def cook_component(str)
|
106
|
+
s = (str && !str.empty?) ? str : '*'
|
107
|
+
l = s.index(/[\?\*]/)
|
108
|
+
if l
|
109
|
+
l2 = s.size - s.rindex(/[\?\*]/) - 1
|
110
|
+
if l2 > l
|
111
|
+
s = s.reverse
|
112
|
+
l = l2
|
113
|
+
end
|
114
|
+
|
115
|
+
return (l > 0) ? s.slice(0 .. (l - 1)) : ''
|
116
|
+
else
|
117
|
+
return s
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def mask2keys(m)
|
122
|
+
md = m.downcased
|
123
|
+
[md.host, md.user, md.nick].map { |c| cook_component(c) }
|
124
|
+
end
|
125
|
+
|
126
|
+
def add(user, *masks)
|
127
|
+
masks.each do |m|
|
128
|
+
debug "adding user #{user} with mask #{m.fullform}"
|
129
|
+
@tree.add([user, m], *mask2keys(m))
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def remove(user, mask)
|
134
|
+
debug "trying to remove user #{user} with mask #{mask}"
|
135
|
+
@tree.remove(*mask2keys(mask)) do |val|
|
136
|
+
val[0] == user and val[1].fullform == mask.fullform
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def metric(iu, bu, mask)
|
141
|
+
ret = nil
|
142
|
+
if iu.matches? mask
|
143
|
+
ret = iu.fullform.length - mask.fullform.length
|
144
|
+
ret += 10 if bu.transient?
|
145
|
+
end
|
146
|
+
return ret
|
147
|
+
end
|
148
|
+
|
149
|
+
def find(iu)
|
150
|
+
debug "find(#{iu.fullform})"
|
151
|
+
iud = iu.downcased
|
152
|
+
matches = @tree.find(iud.host, iud.user, iud.nick).uniq.map do |val|
|
153
|
+
m = metric(iu, *val)
|
154
|
+
m ? [val[0], m] : nil
|
155
|
+
end.compact.sort { |a, b| a[1] <=> a[1] }
|
156
|
+
debug "matches: " + (matches.map do |m|
|
157
|
+
"#{m[0].username}: [#{m[1]}]"
|
158
|
+
end.join(', '))
|
159
|
+
return matches.empty? ? nil : matches[0][0]
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
data/lib/rbot/message.rb
CHANGED
@@ -1,13 +1,106 @@
|
|
1
|
+
#-- vim:sw=2:et
|
2
|
+
#++
|
3
|
+
#
|
4
|
+
# :title: IRC message datastructures
|
5
|
+
|
1
6
|
module Irc
|
2
|
-
BotConfig.register BotConfigArrayValue.new('core.address_prefix',
|
3
|
-
:default => [], :wizard => true,
|
4
|
-
:desc => "what non nick-matching prefixes should the bot respond to as if addressed (e.g !, so that '!foo' is treated like 'rbot: foo')"
|
5
|
-
)
|
6
7
|
|
7
|
-
|
8
|
+
|
9
|
+
class Bot
|
10
|
+
module Config
|
11
|
+
Config.register ArrayValue.new('core.address_prefix',
|
12
|
+
:default => [], :wizard => true,
|
13
|
+
:desc => "what non nick-matching prefixes should the bot respond to as if addressed (e.g !, so that '!foo' is treated like 'rbot: foo')"
|
14
|
+
)
|
15
|
+
|
16
|
+
Config.register BooleanValue.new('core.reply_with_nick',
|
17
|
+
:default => false, :wizard => true,
|
18
|
+
:desc => "if true, the bot will prepend the nick to what he has to say when replying (e.g. 'markey: you can't do that!')"
|
19
|
+
)
|
20
|
+
|
21
|
+
Config.register StringValue.new('core.nick_postfix',
|
22
|
+
:default => ':', :wizard => true,
|
23
|
+
:desc => "when replying with nick put this character after the nick of the user the bot is replying to"
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
# Define standard IRC attriubtes (not so standard actually,
|
30
|
+
# but the closest thing we have ...)
|
8
31
|
Bold = "\002"
|
9
32
|
Underline = "\037"
|
10
33
|
Reverse = "\026"
|
34
|
+
Italic = "\011"
|
35
|
+
NormalText = "\017"
|
36
|
+
AttributeRx = /#{Bold}|#{Underline}|#{Reverse}|#{Italic}|#{NormalText}/
|
37
|
+
|
38
|
+
# Color is prefixed by \003 and followed by optional
|
39
|
+
# foreground and background specifications, two-digits-max
|
40
|
+
# numbers separated by a comma. One of the two parts
|
41
|
+
# must be present.
|
42
|
+
Color = "\003"
|
43
|
+
ColorRx = /#{Color}\d?\d?(?:,\d\d?)?/
|
44
|
+
|
45
|
+
FormattingRx = /#{AttributeRx}|#{ColorRx}/
|
46
|
+
|
47
|
+
# Standard color codes
|
48
|
+
ColorCode = {
|
49
|
+
:black => 1,
|
50
|
+
:blue => 2,
|
51
|
+
:navyblue => 2,
|
52
|
+
:navy_blue => 2,
|
53
|
+
:green => 3,
|
54
|
+
:red => 4,
|
55
|
+
:brown => 5,
|
56
|
+
:purple => 6,
|
57
|
+
:olive => 7,
|
58
|
+
:yellow => 8,
|
59
|
+
:limegreen => 9,
|
60
|
+
:lime_green => 9,
|
61
|
+
:teal => 10,
|
62
|
+
:aqualight => 11,
|
63
|
+
:aqua_light => 11,
|
64
|
+
:royal_blue => 12,
|
65
|
+
:hotpink => 13,
|
66
|
+
:hot_pink => 13,
|
67
|
+
:darkgray => 14,
|
68
|
+
:dark_gray => 14,
|
69
|
+
:lightgray => 15,
|
70
|
+
:light_gray => 15,
|
71
|
+
:white => 16
|
72
|
+
}
|
73
|
+
|
74
|
+
# Convert a String or Symbol into a color number
|
75
|
+
def Irc.find_color(data)
|
76
|
+
"%02d" % if Integer === data
|
77
|
+
data
|
78
|
+
else
|
79
|
+
f = if String === data
|
80
|
+
data.intern
|
81
|
+
else
|
82
|
+
data
|
83
|
+
end
|
84
|
+
if ColorCode.key?(f)
|
85
|
+
ColorCode[f]
|
86
|
+
else
|
87
|
+
0
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Insert the full color code for a given
|
93
|
+
# foreground/background combination.
|
94
|
+
def Irc.color(fg=nil,bg=nil)
|
95
|
+
str = Color.dup
|
96
|
+
if fg
|
97
|
+
str << Irc.find_color(fg)
|
98
|
+
end
|
99
|
+
if bg
|
100
|
+
str << "," << Irc.find_color(bg)
|
101
|
+
end
|
102
|
+
return str
|
103
|
+
end
|
11
104
|
|
12
105
|
# base user message class, all user messages derive from this
|
13
106
|
# (a user message is defined as having a source hostmask, a target
|
@@ -17,33 +110,65 @@ module Irc
|
|
17
110
|
# associated bot
|
18
111
|
attr_reader :bot
|
19
112
|
|
113
|
+
# associated server
|
114
|
+
attr_reader :server
|
115
|
+
|
20
116
|
# when the message was received
|
21
117
|
attr_reader :time
|
22
118
|
|
23
|
-
#
|
119
|
+
# User that originated the message
|
24
120
|
attr_reader :source
|
25
121
|
|
26
|
-
#
|
27
|
-
attr_reader :sourcenick
|
28
|
-
|
29
|
-
# url part of message source
|
30
|
-
attr_reader :sourceaddress
|
31
|
-
|
32
|
-
# nick/channel message was sent to
|
122
|
+
# User/Channel message was sent to
|
33
123
|
attr_reader :target
|
34
124
|
|
35
|
-
# contents of the message
|
125
|
+
# contents of the message (stripped of initial/final format codes)
|
36
126
|
attr_accessor :message
|
37
127
|
|
128
|
+
# contents of the message (for logging purposes)
|
129
|
+
attr_accessor :logmessage
|
130
|
+
|
131
|
+
# contents of the message (stripped of all formatting)
|
132
|
+
attr_accessor :plainmessage
|
133
|
+
|
38
134
|
# has the message been replied to/handled by a plugin?
|
39
135
|
attr_accessor :replied
|
136
|
+
alias :replied? :replied
|
137
|
+
|
138
|
+
# should the message be ignored?
|
139
|
+
attr_accessor :ignored
|
140
|
+
alias :ignored? :ignored
|
141
|
+
|
142
|
+
# set this to true if the method that delegates the message is run in a thread
|
143
|
+
attr_accessor :in_thread
|
144
|
+
alias :in_thread? :in_thread
|
145
|
+
|
146
|
+
def inspect(fields=nil)
|
147
|
+
ret = self.__to_s__[0..-2]
|
148
|
+
ret << ' bot=' << @bot.__to_s__
|
149
|
+
ret << ' server=' << server.to_s
|
150
|
+
ret << ' time=' << time.to_s
|
151
|
+
ret << ' source=' << source.to_s
|
152
|
+
ret << ' target=' << target.to_s
|
153
|
+
ret << ' message=' << message.inspect
|
154
|
+
ret << ' logmessage=' << logmessage.inspect
|
155
|
+
ret << ' plainmessage=' << plainmessage.inspect
|
156
|
+
ret << fields if fields
|
157
|
+
ret << ' (identified)' if identified?
|
158
|
+
ret << ' (addressed to me)' if address?
|
159
|
+
ret << ' (replied)' if replied?
|
160
|
+
ret << ' (ignored)' if ignored?
|
161
|
+
ret << ' (in thread)' if in_thread?
|
162
|
+
ret << '>'
|
163
|
+
end
|
40
164
|
|
41
165
|
# instantiate a new Message
|
42
166
|
# bot:: associated bot class
|
43
|
-
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
|
167
|
+
# server:: Server where the message took place
|
168
|
+
# source:: User that sent the message
|
169
|
+
# target:: User/Channel is destined for
|
170
|
+
# message:: actual message
|
171
|
+
def initialize(bot, server, source, target, message)
|
47
172
|
@msg_wants_id = false unless defined? @msg_wants_id
|
48
173
|
|
49
174
|
@time = Time.now
|
@@ -51,31 +176,51 @@ module Irc
|
|
51
176
|
@source = source
|
52
177
|
@address = false
|
53
178
|
@target = target
|
54
|
-
@message =
|
179
|
+
@message = message || ""
|
55
180
|
@replied = false
|
181
|
+
@server = server
|
182
|
+
@ignored = false
|
183
|
+
@in_thread = false
|
56
184
|
|
57
185
|
@identified = false
|
58
|
-
if @msg_wants_id && @
|
59
|
-
if @message =~
|
186
|
+
if @msg_wants_id && @server.capabilities[:"identify-msg"]
|
187
|
+
if @message =~ /^([-+])(.*)/
|
60
188
|
@identified = ($1=="+")
|
61
189
|
@message = $2
|
62
190
|
else
|
63
191
|
warning "Message does not have identification"
|
64
192
|
end
|
65
193
|
end
|
194
|
+
@logmessage = @message.dup
|
195
|
+
@plainmessage = BasicUserMessage.strip_formatting(@message)
|
196
|
+
@message = BasicUserMessage.strip_initial_formatting(@message)
|
66
197
|
|
67
|
-
|
68
|
-
if source =~ /^((\S+)!(\S+))$/
|
69
|
-
@sourcenick = $2
|
70
|
-
@sourceaddress = $3
|
71
|
-
end
|
72
|
-
|
73
|
-
if target && target.downcase == @bot.nick.downcase
|
198
|
+
if target && target == @bot.myself
|
74
199
|
@address = true
|
75
200
|
end
|
76
201
|
|
77
202
|
end
|
78
203
|
|
204
|
+
# Access the nick of the source
|
205
|
+
#
|
206
|
+
def sourcenick
|
207
|
+
@source.nick rescue @source.to_s
|
208
|
+
end
|
209
|
+
|
210
|
+
# Access the user@host of the source
|
211
|
+
#
|
212
|
+
def sourceaddress
|
213
|
+
"#{@source.user}@#{@source.host}" rescue @source.to_s
|
214
|
+
end
|
215
|
+
|
216
|
+
# Access the botuser corresponding to the source, if any
|
217
|
+
#
|
218
|
+
def botuser
|
219
|
+
source.botuser rescue @bot.auth.everyone
|
220
|
+
end
|
221
|
+
|
222
|
+
|
223
|
+
# Was the message from an identified user?
|
79
224
|
def identified?
|
80
225
|
return @identified
|
81
226
|
end
|
@@ -88,19 +233,32 @@ module Irc
|
|
88
233
|
return @address
|
89
234
|
end
|
90
235
|
|
91
|
-
# has this message been replied to by a plugin?
|
92
|
-
def replied?
|
93
|
-
return @replied
|
94
|
-
end
|
95
|
-
|
96
236
|
# strip mIRC colour escapes from a string
|
97
237
|
def BasicUserMessage.stripcolour(string)
|
98
238
|
return "" unless string
|
99
|
-
ret = string.gsub(
|
239
|
+
ret = string.gsub(ColorRx, "")
|
100
240
|
#ret.tr!("\x00-\x1f", "")
|
101
241
|
ret
|
102
242
|
end
|
103
243
|
|
244
|
+
def BasicUserMessage.strip_initial_formatting(string)
|
245
|
+
return "" unless string
|
246
|
+
ret = string.gsub(/^#{FormattingRx}|#{FormattingRx}$/,"")
|
247
|
+
end
|
248
|
+
|
249
|
+
def BasicUserMessage.strip_formatting(string)
|
250
|
+
string.gsub(FormattingRx,"")
|
251
|
+
end
|
252
|
+
|
253
|
+
end
|
254
|
+
|
255
|
+
# class for handling welcome messages from the server
|
256
|
+
class WelcomeMessage < BasicUserMessage
|
257
|
+
end
|
258
|
+
|
259
|
+
# class for handling MOTD from the server. Yes, MotdMessage
|
260
|
+
# is somewhat redundant, but it fits with the naming scheme
|
261
|
+
class MotdMessage < BasicUserMessage
|
104
262
|
end
|
105
263
|
|
106
264
|
# class for handling IRC user messages. Includes some utilities for handling
|
@@ -109,6 +267,24 @@ module Irc
|
|
109
267
|
# (address? will return true in this case)
|
110
268
|
class UserMessage < BasicUserMessage
|
111
269
|
|
270
|
+
def inspect
|
271
|
+
fields = ' plugin=' << plugin.inspect
|
272
|
+
fields << ' params=' << params.inspect
|
273
|
+
fields << ' channel=' << channel.to_s if channel
|
274
|
+
fields << ' (reply to ' << replyto.to_s << ')'
|
275
|
+
if self.private?
|
276
|
+
fields << ' (private)'
|
277
|
+
else
|
278
|
+
fields << ' (public)'
|
279
|
+
end
|
280
|
+
if self.action?
|
281
|
+
fields << ' (action)'
|
282
|
+
elsif ctcp
|
283
|
+
fields << ' (CTCP ' << ctcp << ')'
|
284
|
+
end
|
285
|
+
super(fields)
|
286
|
+
end
|
287
|
+
|
112
288
|
# for plugin messages, the name of the plugin invoked by the message
|
113
289
|
attr_reader :plugin
|
114
290
|
|
@@ -124,6 +300,12 @@ module Irc
|
|
124
300
|
# channel the message was in, nil for privately addressed messages
|
125
301
|
attr_reader :channel
|
126
302
|
|
303
|
+
# for PRIVMSGs, false unless the message was a CTCP command,
|
304
|
+
# in which case it evaluates to the CTCP command itself
|
305
|
+
# (TIME, PING, VERSION, etc). The CTCP command parameters
|
306
|
+
# are then stored in the message.
|
307
|
+
attr_reader :ctcp
|
308
|
+
|
127
309
|
# for PRIVMSGs, true if the message was a CTCP ACTION (CTCP stuff
|
128
310
|
# will be stripped from the message)
|
129
311
|
attr_reader :action
|
@@ -133,18 +315,19 @@ module Irc
|
|
133
315
|
# source:: hostmask of the message source
|
134
316
|
# target:: nick/channel message is destined for
|
135
317
|
# message:: message part
|
136
|
-
def initialize(bot, source, target, message)
|
137
|
-
super(bot, source, target, message)
|
318
|
+
def initialize(bot, server, source, target, message)
|
319
|
+
super(bot, server, source, target, message)
|
138
320
|
@target = target
|
139
321
|
@private = false
|
140
322
|
@plugin = nil
|
323
|
+
@ctcp = false
|
141
324
|
@action = false
|
142
325
|
|
143
|
-
if target
|
326
|
+
if target == @bot.myself
|
144
327
|
@private = true
|
145
328
|
@address = true
|
146
329
|
@channel = nil
|
147
|
-
@replyto =
|
330
|
+
@replyto = source
|
148
331
|
else
|
149
332
|
@replyto = @target
|
150
333
|
@channel = @target
|
@@ -166,14 +349,20 @@ module Irc
|
|
166
349
|
@address = true
|
167
350
|
end
|
168
351
|
|
169
|
-
if(@message =~ /^\
|
170
|
-
@
|
171
|
-
|
352
|
+
if(@message =~ /^\001(\S+)(\s(.+))?\001/)
|
353
|
+
@ctcp = $1
|
354
|
+
# FIXME need to support quoting of NULL and CR/LF, see
|
355
|
+
# http://www.irchelp.org/irchelp/rfc/ctcpspec.html
|
356
|
+
@message = $3 || String.new
|
357
|
+
@action = @ctcp == 'ACTION'
|
358
|
+
debug "Received CTCP command #{@ctcp} with options #{@message} (action? #{@action})"
|
359
|
+
@logmessage = @message.dup
|
172
360
|
end
|
173
361
|
|
174
362
|
# free splitting for plugins
|
175
363
|
@params = @message.dup
|
176
|
-
|
364
|
+
# Created messges (such as by fake_message) can contain multiple lines
|
365
|
+
if @params.gsub!(/\A\s*(\S+)[\s$]*/m, "")
|
177
366
|
@plugin = $1.downcase
|
178
367
|
@params = nil unless @params.length > 0
|
179
368
|
end
|
@@ -198,42 +387,92 @@ module Irc
|
|
198
387
|
# <tt>@bot.say m.replyto, string</tt>
|
199
388
|
# So if the message is private, it will reply to the user. If it was
|
200
389
|
# in a channel, it will reply in the channel.
|
201
|
-
def
|
202
|
-
@bot.say @replyto, string
|
390
|
+
def plainreply(string, options={})
|
391
|
+
@bot.say @replyto, string, options
|
203
392
|
@replied = true
|
204
393
|
end
|
205
394
|
|
395
|
+
# Same as reply, but when replying in public it adds the nick of the user
|
396
|
+
# the bot is replying to
|
397
|
+
def nickreply(string, options={})
|
398
|
+
extra = self.public? ? "#{@source}#{@bot.config['core.nick_postfix']} " : ""
|
399
|
+
@bot.say @replyto, extra + string, options
|
400
|
+
@replied = true
|
401
|
+
end
|
402
|
+
|
403
|
+
# the default reply style is to nickreply unless the reply already contains
|
404
|
+
# the nick or core.reply_with_nick is set to false
|
405
|
+
#
|
406
|
+
def reply(string, options={})
|
407
|
+
if @bot.config['core.reply_with_nick'] and not string =~ /(?:^|\W)#{Regexp.escape(@source.to_s)}(?:$|\W)/
|
408
|
+
return nickreply(string, options)
|
409
|
+
end
|
410
|
+
plainreply(string, options)
|
411
|
+
end
|
412
|
+
|
206
413
|
# convenience method to reply to a message with an action. It's the
|
207
414
|
# same as doing:
|
208
415
|
# <tt>@bot.action m.replyto, string</tt>
|
209
416
|
# So if the message is private, it will reply to the user. If it was
|
210
417
|
# in a channel, it will reply in the channel.
|
211
|
-
def act(string)
|
212
|
-
@bot.action @replyto, string
|
418
|
+
def act(string, options={})
|
419
|
+
@bot.action @replyto, string, options
|
213
420
|
@replied = true
|
214
421
|
end
|
215
422
|
|
423
|
+
# send a CTCP response, i.e. a private NOTICE to the sender
|
424
|
+
# with the same CTCP command and the reply as a parameter
|
425
|
+
def ctcp_reply(string, options={})
|
426
|
+
@bot.ctcp_notice @source, @ctcp, string, options
|
427
|
+
end
|
428
|
+
|
216
429
|
# convenience method to reply "okay" in the current language to the
|
217
430
|
# message
|
431
|
+
def plainokay
|
432
|
+
self.plainreply @bot.lang.get("okay")
|
433
|
+
end
|
434
|
+
|
435
|
+
# Like the above, but append the username
|
436
|
+
def nickokay
|
437
|
+
str = @bot.lang.get("okay").dup
|
438
|
+
if self.public?
|
439
|
+
# remove final punctuation
|
440
|
+
str.gsub!(/[!,.]$/,"")
|
441
|
+
str += ", #{@source}"
|
442
|
+
end
|
443
|
+
self.plainreply str
|
444
|
+
end
|
445
|
+
|
446
|
+
# the default okay style is the same as the default reply style
|
447
|
+
#
|
218
448
|
def okay
|
219
|
-
|
449
|
+
if @bot.config['core.reply_with_nick']
|
450
|
+
return nickokay
|
451
|
+
end
|
452
|
+
plainokay
|
453
|
+
end
|
454
|
+
|
455
|
+
# send a NOTICE to the message source
|
456
|
+
#
|
457
|
+
def notify(msg,opts={})
|
458
|
+
@bot.notice(sourcenick, msg, opts)
|
220
459
|
end
|
221
460
|
|
222
461
|
end
|
223
462
|
|
224
463
|
# class to manage IRC PRIVMSGs
|
225
464
|
class PrivMessage < UserMessage
|
226
|
-
def initialize(bot, source, target, message)
|
227
|
-
@msg_wants_id =
|
228
|
-
super
|
465
|
+
def initialize(bot, server, source, target, message, opts={})
|
466
|
+
@msg_wants_id = opts[:handle_id]
|
467
|
+
super(bot, server, source, target, message)
|
229
468
|
end
|
230
469
|
end
|
231
470
|
|
232
471
|
# class to manage IRC NOTICEs
|
233
472
|
class NoticeMessage < UserMessage
|
234
|
-
def initialize(bot, source, target, message)
|
235
|
-
@msg_wants_id =
|
236
|
-
super
|
473
|
+
def initialize(bot, server, source, target, message, opts={})
|
474
|
+
@msg_wants_id = opts[:handle_id]
|
475
|
+
super(bot, server, source, target, message)
|
237
476
|
end
|
238
477
|
end
|
239
478
|
|
@@ -244,8 +483,31 @@ module Irc
|
|
244
483
|
# channel user was kicked from
|
245
484
|
attr_reader :channel
|
246
485
|
|
247
|
-
def
|
248
|
-
|
486
|
+
def inspect
|
487
|
+
fields = ' channel=' << channel.to_s
|
488
|
+
super(fields)
|
489
|
+
end
|
490
|
+
|
491
|
+
def initialize(bot, server, source, target, channel, message="")
|
492
|
+
super(bot, server, source, target, message)
|
493
|
+
@channel = channel
|
494
|
+
end
|
495
|
+
end
|
496
|
+
|
497
|
+
# class to manage IRC INVITEs
|
498
|
+
# +address?+ can be used as a shortcut to see if the bot was invited,
|
499
|
+
# which should be true except for server bugs
|
500
|
+
class InviteMessage < BasicUserMessage
|
501
|
+
# channel user was invited to
|
502
|
+
attr_reader :channel
|
503
|
+
|
504
|
+
def inspect
|
505
|
+
fields = ' channel=' << channel.to_s
|
506
|
+
super(fields)
|
507
|
+
end
|
508
|
+
|
509
|
+
def initialize(bot, server, source, target, channel, message="")
|
510
|
+
super(bot, server, source, target, message)
|
249
511
|
@channel = channel
|
250
512
|
end
|
251
513
|
end
|
@@ -253,14 +515,61 @@ module Irc
|
|
253
515
|
# class to pass IRC Nick changes in. @message contains the old nickame,
|
254
516
|
# @sourcenick contains the new one.
|
255
517
|
class NickMessage < BasicUserMessage
|
256
|
-
|
257
|
-
|
518
|
+
attr_accessor :is_on
|
519
|
+
def initialize(bot, server, source, oldnick, newnick)
|
520
|
+
super(bot, server, source, oldnick, newnick)
|
521
|
+
@is_on = []
|
522
|
+
end
|
523
|
+
|
524
|
+
def oldnick
|
525
|
+
return @target
|
526
|
+
end
|
527
|
+
|
528
|
+
def newnick
|
529
|
+
return @message
|
530
|
+
end
|
531
|
+
|
532
|
+
def inspect
|
533
|
+
fields = ' old=' << oldnick
|
534
|
+
fields << ' new=' << newnick
|
535
|
+
super(fields)
|
536
|
+
end
|
537
|
+
end
|
538
|
+
|
539
|
+
# class to manage mode changes
|
540
|
+
class ModeChangeMessage < BasicUserMessage
|
541
|
+
attr_accessor :modes
|
542
|
+
def initialize(bot, server, source, target, message="")
|
543
|
+
super(bot, server, source, target, message)
|
544
|
+
@address = (source == @bot.myself)
|
545
|
+
@modes = []
|
546
|
+
end
|
547
|
+
|
548
|
+
def inspect
|
549
|
+
fields = ' modes=' << modes.inspect
|
550
|
+
super(fields)
|
551
|
+
end
|
552
|
+
end
|
553
|
+
|
554
|
+
# class to manage NAME replies
|
555
|
+
class NamesMessage < BasicUserMessage
|
556
|
+
attr_accessor :users
|
557
|
+
def initialize(bot, server, source, target, message="")
|
558
|
+
super(bot, server, source, target, message)
|
559
|
+
@users = []
|
560
|
+
end
|
561
|
+
|
562
|
+
def inspect
|
563
|
+
fields = ' users=' << users.inspect
|
564
|
+
super(fields)
|
258
565
|
end
|
259
566
|
end
|
260
567
|
|
261
568
|
class QuitMessage < BasicUserMessage
|
262
|
-
|
263
|
-
|
569
|
+
attr_accessor :was_on
|
570
|
+
def initialize(bot, server, source, target, message="")
|
571
|
+
super(bot, server, source, target, message)
|
572
|
+
@was_on = []
|
264
573
|
end
|
265
574
|
end
|
266
575
|
|
@@ -272,11 +581,20 @@ module Irc
|
|
272
581
|
# topic set on channel
|
273
582
|
attr_reader :channel
|
274
583
|
|
275
|
-
|
276
|
-
|
584
|
+
# :info if topic info, :set if topic set
|
585
|
+
attr_accessor :info_or_set
|
586
|
+
def initialize(bot, server, source, channel, topic=ChannelTopic.new)
|
587
|
+
super(bot, server, source, channel, topic.text)
|
277
588
|
@topic = topic
|
278
|
-
@timestamp =
|
589
|
+
@timestamp = topic.set_on
|
279
590
|
@channel = channel
|
591
|
+
@info_or_set = nil
|
592
|
+
end
|
593
|
+
|
594
|
+
def inspect
|
595
|
+
fields = ' topic=' << topic
|
596
|
+
fields << ' (set on ' << timestamp << ')'
|
597
|
+
super(fields)
|
280
598
|
end
|
281
599
|
end
|
282
600
|
|
@@ -284,11 +602,17 @@ module Irc
|
|
284
602
|
class JoinMessage < BasicUserMessage
|
285
603
|
# channel joined
|
286
604
|
attr_reader :channel
|
287
|
-
|
288
|
-
|
605
|
+
|
606
|
+
def inspect
|
607
|
+
fields = ' channel=' << channel.to_s
|
608
|
+
super(fields)
|
609
|
+
end
|
610
|
+
|
611
|
+
def initialize(bot, server, source, channel, message="")
|
612
|
+
super(bot, server, source, channel, message)
|
289
613
|
@channel = channel
|
290
614
|
# in this case sourcenick is the nick that could be the bot
|
291
|
-
@address = (
|
615
|
+
@address = (source == @bot.myself)
|
292
616
|
end
|
293
617
|
end
|
294
618
|
|
@@ -296,4 +620,7 @@ module Irc
|
|
296
620
|
# same as a join, but can have a message too
|
297
621
|
class PartMessage < JoinMessage
|
298
622
|
end
|
623
|
+
|
624
|
+
class UnknownMessage < BasicUserMessage
|
625
|
+
end
|
299
626
|
end
|