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/messagemapper.rb
CHANGED
@@ -1,6 +1,41 @@
|
|
1
|
+
# First of all we add a method to the Regexp class
|
2
|
+
class Regexp
|
3
|
+
|
4
|
+
# a Regexp has captures when its source has open parenthesis which are
|
5
|
+
# preceded by an even number of slashes and not followed by a question mark
|
6
|
+
#
|
7
|
+
def has_captures?
|
8
|
+
self.source.match(/(?:^|[^\\])(?:\\\\)*\([^?]/)
|
9
|
+
end
|
10
|
+
|
11
|
+
# We may want to remove captures
|
12
|
+
def remove_captures
|
13
|
+
new = self.source.gsub(/(^|[^\\])((?:\\\\)*)\(([^?])/) {
|
14
|
+
"%s%s(?:%s" % [$1, $2, $3]
|
15
|
+
}
|
16
|
+
Regexp.new(new, self.options)
|
17
|
+
end
|
18
|
+
|
19
|
+
# We may want to remove head and tail anchors
|
20
|
+
def remove_head_tail
|
21
|
+
new = self.source.sub(/^\^/,'').sub(/\$$/,'')
|
22
|
+
Regexp.new(new, self.options)
|
23
|
+
end
|
24
|
+
|
25
|
+
# The MessageMapper cleanup method: does both remove_capture
|
26
|
+
# and remove_head_tail
|
27
|
+
def mm_cleanup
|
28
|
+
new = self.source.gsub(/(^|[^\\])((?:\\\\)*)\(([^?])/) {
|
29
|
+
"%s%s(?:%s" % [$1, $2, $3]
|
30
|
+
}.sub(/^\^/,'').sub(/\$$/,'')
|
31
|
+
Regexp.new(new, self.options)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
1
35
|
module Irc
|
36
|
+
class Bot
|
2
37
|
|
3
|
-
#
|
38
|
+
# MessageMapper is a class designed to reduce the amount of regexps and
|
4
39
|
# string parsing plugins and bot modules need to do, in order to process
|
5
40
|
# and respond to messages.
|
6
41
|
#
|
@@ -13,7 +48,7 @@ module Irc
|
|
13
48
|
# A template such as "foo :option :otheroption" will match the string "foo
|
14
49
|
# bar baz" and, by default, result in method +foo+ being called, if
|
15
50
|
# present, in the parent class. It will receive two parameters, the
|
16
|
-
#
|
51
|
+
# message (derived from BasicUserMessage) and a Hash containing
|
17
52
|
# {:option => "bar", :otheroption => "baz"}
|
18
53
|
# See the #map method for more details.
|
19
54
|
class MessageMapper
|
@@ -21,96 +56,139 @@ module Irc
|
|
21
56
|
# The default fallback is a method called "usage".
|
22
57
|
attr_writer :fallback
|
23
58
|
|
24
|
-
#
|
59
|
+
# _parent_:: parent class which will receive mapped messages
|
25
60
|
#
|
26
|
-
#
|
61
|
+
# Create a new MessageMapper with parent class _parent_. This class will
|
27
62
|
# receive messages from the mapper via the handle() method.
|
28
63
|
def initialize(parent)
|
29
64
|
@parent = parent
|
30
65
|
@templates = Array.new
|
31
|
-
@fallback =
|
66
|
+
@fallback = :usage
|
32
67
|
end
|
33
68
|
|
34
|
-
#
|
69
|
+
# call-seq: map(botmodule, template, options)
|
35
70
|
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
39
|
-
# action with the name of the first word in the template. The action is
|
40
|
-
# a method which takes a message and a parameter hash for arguments.
|
71
|
+
# _botmodule_:: the BotModule which will handle this map
|
72
|
+
# _template_:: a String describing the messages to be matched
|
73
|
+
# _options_:: a Hash holding variouns options
|
41
74
|
#
|
42
|
-
#
|
43
|
-
#
|
44
|
-
#
|
75
|
+
# This method is used to register a new MessageTemplate that will map any
|
76
|
+
# BasicUserMessage matching the given _template_ to a corresponding action.
|
77
|
+
# A simple example:
|
78
|
+
# plugin.map 'myplugin :parameter'
|
79
|
+
# (other examples follow).
|
45
80
|
#
|
46
|
-
# By default
|
47
|
-
#
|
48
|
-
#
|
81
|
+
# By default, the action to which the messages are mapped is a method named
|
82
|
+
# like the first word of the template. The
|
83
|
+
# :action => 'method_name'
|
84
|
+
# option can be used to override this default behaviour. Example:
|
85
|
+
# plugin.map 'myplugin :parameter', :action => 'mymethod'
|
86
|
+
#
|
87
|
+
# By default whether a handler is fired depends on an auth check. In rbot
|
88
|
+
# versions up to 0.9.10, the first component of the string was used for the
|
89
|
+
# auth check, unless overridden via the :auth => 'auth_name' option. Since
|
90
|
+
# version 0.9.11, a new auth method has been implemented. TODO document.
|
49
91
|
#
|
50
92
|
# Static parameters (not prefixed with ':' or '*') must match the
|
51
93
|
# respective component of the message exactly. Example:
|
52
|
-
# map 'myplugin :foo is :bar'
|
94
|
+
# plugin.map 'myplugin :foo is :bar'
|
53
95
|
# will only match messages of the form "myplugin something is
|
54
96
|
# somethingelse"
|
55
97
|
#
|
56
98
|
# Dynamic parameters can be specified by a colon ':' to match a single
|
57
|
-
# component (whitespace
|
99
|
+
# component (whitespace separated), or a * to suck up all following
|
58
100
|
# parameters into an array. Example:
|
59
|
-
# map 'myplugin :parameter1 *rest'
|
101
|
+
# plugin.map 'myplugin :parameter1 *rest'
|
60
102
|
#
|
61
103
|
# You can provide defaults for dynamic components using the :defaults
|
62
104
|
# parameter. If a component has a default, then it is optional. e.g:
|
63
|
-
# map 'myplugin :foo :bar', :defaults => {:bar => 'qux'}
|
105
|
+
# plugin.map 'myplugin :foo :bar', :defaults => {:bar => 'qux'}
|
64
106
|
# would match 'myplugin param param2' and also 'myplugin param'. In the
|
65
107
|
# latter case, :bar would be provided from the default.
|
66
108
|
#
|
109
|
+
# Static and dynamic parameters can also be made optional by wrapping them
|
110
|
+
# in square brackets []. For example
|
111
|
+
# plugin.map 'myplugin :foo [is] :bar'
|
112
|
+
# will match both 'myplugin something is somethingelse' and 'myplugin
|
113
|
+
# something somethingelse'.
|
114
|
+
#
|
67
115
|
# Components can be validated before being allowed to match, for
|
68
116
|
# example if you need a component to be a number:
|
69
|
-
# map 'myplugin :param', :requirements => {:param => /^\d+$/}
|
117
|
+
# plugin.map 'myplugin :param', :requirements => {:param => /^\d+$/}
|
70
118
|
# will only match strings of the form 'myplugin 1234' or some other
|
71
119
|
# number.
|
72
120
|
#
|
73
121
|
# Templates can be set not to match public or private messages using the
|
74
122
|
# :public or :private boolean options.
|
75
123
|
#
|
124
|
+
# Summary of recognized options:
|
125
|
+
#
|
126
|
+
# action::
|
127
|
+
# method to call when the template is matched
|
128
|
+
# auth_path::
|
129
|
+
# TODO document
|
130
|
+
# requirements::
|
131
|
+
# a Hash whose keys are names of dynamic parameters and whose values are
|
132
|
+
# regular expressions that the parameters must match
|
133
|
+
# defaults::
|
134
|
+
# a Hash whose keys are names of dynamic parameters and whose values are
|
135
|
+
# the values to be assigned to those parameters when they are missing from
|
136
|
+
# the message. Any dynamic parameter appearing in the :defaults Hash is
|
137
|
+
# therefore optional
|
138
|
+
# public::
|
139
|
+
# a boolean (defaults to true) that determines whether the template should
|
140
|
+
# match public (in channel) messages.
|
141
|
+
# private::
|
142
|
+
# a boolean (defaults to true) that determines whether the template should
|
143
|
+
# match private (not in channel) messages.
|
144
|
+
# threaded::
|
145
|
+
# a boolean (defaults to false) that determines whether the action should be
|
146
|
+
# called in a separate thread.
|
147
|
+
#
|
148
|
+
#
|
76
149
|
# Further examples:
|
77
150
|
#
|
78
151
|
# # match 'karmastats' and call my stats() method
|
79
|
-
# map 'karmastats', :action => 'stats'
|
152
|
+
# plugin.map 'karmastats', :action => 'stats'
|
80
153
|
# # match 'karma' with an optional 'key' and call my karma() method
|
81
|
-
# map 'karma :key', :defaults => {:key => false}
|
154
|
+
# plugin.map 'karma :key', :defaults => {:key => false}
|
82
155
|
# # match 'karma for something' and call my karma() method
|
83
|
-
# map 'karma for :key'
|
156
|
+
# plugin.map 'karma for :key'
|
84
157
|
#
|
85
158
|
# # two matches, one for public messages in a channel, one for
|
86
159
|
# # private messages which therefore require a channel argument
|
87
|
-
# map 'urls search :channel :limit :string',
|
160
|
+
# plugin.map 'urls search :channel :limit :string',
|
161
|
+
# :action => 'search',
|
88
162
|
# :defaults => {:limit => 4},
|
89
163
|
# :requirements => {:limit => /^\d+$/},
|
90
164
|
# :public => false
|
91
|
-
# plugin.map 'urls search :limit :string',
|
165
|
+
# plugin.map 'urls search :limit :string',
|
166
|
+
# :action => 'search',
|
92
167
|
# :defaults => {:limit => 4},
|
93
168
|
# :requirements => {:limit => /^\d+$/},
|
94
169
|
# :private => false
|
95
170
|
#
|
96
|
-
def map(*args)
|
97
|
-
@templates <<
|
171
|
+
def map(botmodule, *args)
|
172
|
+
@templates << MessageTemplate.new(botmodule, *args)
|
98
173
|
end
|
99
174
|
|
175
|
+
# Iterate over each MessageTemplate handled.
|
100
176
|
def each
|
101
177
|
@templates.each {|tmpl| yield tmpl}
|
102
178
|
end
|
179
|
+
|
180
|
+
# Return the last added MessageTemplate
|
103
181
|
def last
|
104
182
|
@templates.last
|
105
183
|
end
|
106
184
|
|
107
|
-
#
|
185
|
+
# _m_:: derived from BasicUserMessage
|
108
186
|
#
|
109
|
-
#
|
187
|
+
# Examine the message _m_, comparing it with each map()'d template to
|
110
188
|
# find and process a match. Templates are examined in the order they
|
111
189
|
# were map()'d - first match wins.
|
112
190
|
#
|
113
|
-
#
|
191
|
+
# Returns +true+ if a match is found including fallbacks, +false+
|
114
192
|
# otherwise.
|
115
193
|
def handle(m)
|
116
194
|
return false if @templates.empty?
|
@@ -120,16 +198,28 @@ module Irc
|
|
120
198
|
if options.nil?
|
121
199
|
failures << [tmpl, failure]
|
122
200
|
else
|
123
|
-
action = tmpl.options[:action]
|
201
|
+
action = tmpl.options[:action]
|
124
202
|
unless @parent.respond_to?(action)
|
125
203
|
failures << [tmpl, "class does not respond to action #{action}"]
|
126
204
|
next
|
127
205
|
end
|
128
|
-
auth = tmpl.options[:
|
206
|
+
auth = tmpl.options[:full_auth_path]
|
129
207
|
debug "checking auth for #{auth}"
|
130
208
|
if m.bot.auth.allow?(auth, m.source, m.replyto)
|
131
209
|
debug "template match found and auth'd: #{action.inspect} #{options.inspect}"
|
132
|
-
|
210
|
+
if !m.in_thread && (tmpl.options[:thread] || tmpl.options[:threaded])
|
211
|
+
Thread.new do
|
212
|
+
begin
|
213
|
+
@parent.send(action, m, options)
|
214
|
+
rescue Exception => e
|
215
|
+
error "In threaded action: #{e.message}"
|
216
|
+
debug e.backtrace.join("\n")
|
217
|
+
end
|
218
|
+
end
|
219
|
+
else
|
220
|
+
@parent.send(action, m, options)
|
221
|
+
end
|
222
|
+
|
133
223
|
return true
|
134
224
|
end
|
135
225
|
debug "auth failed for #{auth}"
|
@@ -142,7 +232,7 @@ module Irc
|
|
142
232
|
debug "#{f.inspect} => #{r}"
|
143
233
|
}
|
144
234
|
debug "no handler found, trying fallback"
|
145
|
-
if @fallback
|
235
|
+
if @fallback && @parent.respond_to?(@fallback)
|
146
236
|
if m.bot.auth.allow?(@fallback, m.source, m.replyto)
|
147
237
|
@parent.send(@fallback, m, {})
|
148
238
|
return true
|
@@ -153,26 +243,230 @@ module Irc
|
|
153
243
|
|
154
244
|
end
|
155
245
|
|
156
|
-
class
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
246
|
+
# MessageParameter is a class that collects all the necessary information
|
247
|
+
# about a message (dynamic) parameter (the :param or *param that can be found
|
248
|
+
# in a #map).
|
249
|
+
#
|
250
|
+
# It has a +name+ attribute, +multi+ and +optional+ booleans that tell if the
|
251
|
+
# parameter collects more than one word, and if it's optional (respectively).
|
252
|
+
# In the latter case, it can also have a default value.
|
253
|
+
#
|
254
|
+
# It is possible to assign a collector to a MessageParameter. This can be either
|
255
|
+
# a Regexp with captures or an Array or a Hash. The collector defines what the
|
256
|
+
# collect() method is supposed to return.
|
257
|
+
class MessageParameter
|
258
|
+
attr_reader :name
|
259
|
+
attr_writer :multi
|
260
|
+
attr_writer :optional
|
261
|
+
attr_accessor :default
|
262
|
+
|
263
|
+
def initialize(name)
|
264
|
+
self.name = name
|
265
|
+
@multi = false
|
266
|
+
@optional = false
|
267
|
+
@default = nil
|
268
|
+
@regexp = nil
|
269
|
+
@index = nil
|
270
|
+
end
|
271
|
+
|
272
|
+
def name=(val)
|
273
|
+
@name = val.to_sym
|
274
|
+
end
|
275
|
+
|
276
|
+
def multi?
|
277
|
+
@multi
|
278
|
+
end
|
279
|
+
|
280
|
+
def optional?
|
281
|
+
@optional
|
282
|
+
end
|
283
|
+
|
284
|
+
# This method is used to turn a matched item into the actual parameter value.
|
285
|
+
# It only does something when collector= set the @regexp to something. In
|
286
|
+
# this case, _val_ is matched against @regexp and then the match result
|
287
|
+
# specified in @index is selected. As a special case, when @index is nil
|
288
|
+
# the first non-nil captured group is returned.
|
289
|
+
def collect(val)
|
290
|
+
return val unless @regexp
|
291
|
+
mdata = @regexp.match(val)
|
292
|
+
if @index
|
293
|
+
return mdata[@index]
|
294
|
+
else
|
295
|
+
return mdata[1..-1].compact.first
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
# This method allow the plugin programmer to choose to only pick a subset of the
|
300
|
+
# string matched by a parameter. This is done by passing the collector=()
|
301
|
+
# method either a Regexp with captures or an Array or a Hash.
|
302
|
+
#
|
303
|
+
# When the method is passed a Regexp with captures, the collect() method will
|
304
|
+
# return the first non-nil captured group.
|
305
|
+
#
|
306
|
+
# When the method is passed an Array, it will grab a regexp from the first
|
307
|
+
# element, and possibly an index from the second element. The index can
|
308
|
+
# also be nil.
|
309
|
+
#
|
310
|
+
# When the method is passed a Hash, it will grab a regexp from the :regexp
|
311
|
+
# element, and possibly an index from the :index element. The index can
|
312
|
+
# also be nil.
|
313
|
+
def collector=(val)
|
314
|
+
return unless val
|
315
|
+
case val
|
316
|
+
when Regexp
|
317
|
+
return unless val.has_captures?
|
318
|
+
@regexp = val
|
319
|
+
when Array
|
320
|
+
warning "Collector #{val.inspect} is too long, ignoring extra entries" unless val.length <= 2
|
321
|
+
@regexp = val[0]
|
322
|
+
@index = val[1] rescue nil
|
323
|
+
when Hash
|
324
|
+
raise "Collector #{val.inspect} doesn't have a :regexp key" unless val.has_key?(:regexp)
|
325
|
+
@regexp = val[:regexp]
|
326
|
+
@index = val.fetch(:regexp, nil)
|
327
|
+
end
|
328
|
+
raise "The regexp of collector #{val.inspect} isn't a Regexp" unless @regexp.kind_of?(Regexp)
|
329
|
+
raise "The index of collector #{val.inspect} is present but not an integer " if @index and not @index.kind_of?(Fixnum)
|
330
|
+
end
|
331
|
+
|
332
|
+
def inspect
|
333
|
+
mul = multi? ? " multi" : " single"
|
334
|
+
opt = optional? ? " optional" : " needed"
|
335
|
+
if @regexp
|
336
|
+
reg = " regexp=%s index=%d" % [@regexp, @index]
|
337
|
+
else
|
338
|
+
reg = nil
|
339
|
+
end
|
340
|
+
"<%s %s%s%s%s>" % [self.class, name, mul, opt, reg]
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
# MessageTemplate is the class that holds the actual message template map()'d
|
345
|
+
# by a BotModule and handled by a MessageMapper
|
346
|
+
#
|
347
|
+
class MessageTemplate
|
348
|
+
attr_reader :defaults # the defaults hash
|
349
|
+
attr_reader :options # the options hash
|
350
|
+
attr_reader :template # the actual template string
|
351
|
+
attr_reader :items # the collection of dynamic and static items in the template
|
352
|
+
attr_reader :regexp # the Regexp corresponding to the template
|
353
|
+
attr_reader :botmodule # the BotModule that map()'d this MessageTemplate
|
354
|
+
|
355
|
+
# call-seq: initialize(botmodule, template, opts={})
|
356
|
+
#
|
357
|
+
# Create a new MessageTemplate associated to BotModule _botmodule_, with
|
358
|
+
# template _template_ and options _opts_
|
359
|
+
#
|
360
|
+
def initialize(botmodule, template, hash={})
|
361
|
+
raise ArgumentError, "Third argument must be a hash!" unless hash.kind_of?(Hash)
|
162
362
|
@defaults = hash[:defaults].kind_of?(Hash) ? hash.delete(:defaults) : {}
|
163
363
|
@requirements = hash[:requirements].kind_of?(Hash) ? hash.delete(:requirements) : {}
|
364
|
+
@template = template
|
365
|
+
case botmodule
|
366
|
+
when String
|
367
|
+
@botmodule = botmodule
|
368
|
+
when Plugins::BotModule
|
369
|
+
@botmodule = botmodule.name
|
370
|
+
else
|
371
|
+
raise ArgumentError, "#{botmodule.inspect} is not a botmodule nor a botmodule name"
|
372
|
+
end
|
373
|
+
|
164
374
|
self.items = template
|
375
|
+
# @dyn_items is an array of MessageParameters, except for the first entry
|
376
|
+
# which is the template
|
377
|
+
@dyn_items = @items.collect { |it|
|
378
|
+
if it.kind_of?(Symbol)
|
379
|
+
i = it.to_s
|
380
|
+
opt = MessageParameter.new(i)
|
381
|
+
if i.sub!(/^\*/,"")
|
382
|
+
opt.name = i
|
383
|
+
opt.multi = true
|
384
|
+
end
|
385
|
+
opt.default = @defaults[opt.name]
|
386
|
+
opt.collector = @requirements[opt.name]
|
387
|
+
opt
|
388
|
+
else
|
389
|
+
nil
|
390
|
+
end
|
391
|
+
}
|
392
|
+
@dyn_items.unshift(template).compact!
|
393
|
+
debug "Items: #{@items.inspect}; dyn items: #{@dyn_items.inspect}"
|
394
|
+
|
395
|
+
self.regexp = template
|
396
|
+
debug "Command #{template.inspect} in #{@botmodule} will match using #{@regexp}"
|
397
|
+
|
398
|
+
set_auth_path(hash)
|
399
|
+
|
400
|
+
unless hash.has_key?(:action)
|
401
|
+
hash[:action] = items[0]
|
402
|
+
end
|
403
|
+
|
165
404
|
@options = hash
|
405
|
+
|
406
|
+
# debug "Create template #{self.inspect}"
|
407
|
+
end
|
408
|
+
|
409
|
+
def set_auth_path(hash)
|
410
|
+
if hash.has_key?(:auth)
|
411
|
+
warning "Command #{@template.inspect} in #{@botmodule} uses old :auth syntax, please upgrade"
|
412
|
+
end
|
413
|
+
if hash.has_key?(:full_auth_path)
|
414
|
+
warning "Command #{@template.inspect} in #{@botmodule} sets :full_auth_path, please don't do this"
|
415
|
+
else
|
416
|
+
pre = @botmodule
|
417
|
+
words = items.reject{ |x|
|
418
|
+
x == pre || x.kind_of?(Symbol) || x =~ /\[|\]/
|
419
|
+
}
|
420
|
+
if words.empty?
|
421
|
+
post = nil
|
422
|
+
else
|
423
|
+
post = words.first
|
424
|
+
end
|
425
|
+
if hash.has_key?(:auth_path)
|
426
|
+
extra = hash[:auth_path]
|
427
|
+
if extra.sub!(/^:/, "")
|
428
|
+
pre += "::" + post
|
429
|
+
post = nil
|
430
|
+
end
|
431
|
+
if extra.sub!(/:$/, "")
|
432
|
+
if words.length > 1
|
433
|
+
post = [post,words[1]].compact.join("::")
|
434
|
+
end
|
435
|
+
end
|
436
|
+
pre = nil if extra.sub!(/^!/, "")
|
437
|
+
post = nil if extra.sub!(/!$/, "")
|
438
|
+
extra = nil if extra.empty?
|
439
|
+
else
|
440
|
+
extra = nil
|
441
|
+
end
|
442
|
+
hash[:full_auth_path] = [pre,extra,post].compact.join("::")
|
443
|
+
debug "Command #{@template} in #{botmodule} will use authPath #{hash[:full_auth_path]}"
|
444
|
+
# TODO check if the full_auth_path is sane
|
445
|
+
end
|
166
446
|
end
|
447
|
+
|
167
448
|
def items=(str)
|
168
|
-
|
169
|
-
|
170
|
-
|
449
|
+
raise ArgumentError, "template #{str.inspect} should be a String" unless str.kind_of?(String)
|
450
|
+
|
451
|
+
# split and convert ':xyz' to symbols
|
452
|
+
items = str.strip.split(/\]?\s+\[?|\]?$/).collect { |c|
|
453
|
+
# there might be extra (non-alphanumeric) stuff (e.g. punctuation) after the symbol name
|
454
|
+
if /^(:|\*)(\w+)(.*)/ =~ c
|
455
|
+
sym = ($1 == ':' ) ? $2.intern : "*#{$2}".intern
|
456
|
+
if $3.empty?
|
457
|
+
sym
|
458
|
+
else
|
459
|
+
[sym, $3]
|
460
|
+
end
|
461
|
+
else
|
462
|
+
c
|
463
|
+
end
|
464
|
+
}.flatten
|
171
465
|
@items = items
|
172
466
|
|
173
|
-
if @items.first.kind_of? Symbol
|
174
|
-
|
175
|
-
|
467
|
+
raise ArgumentError, "Illegal template -- first component cannot be dynamic: #{str.inspect}" if @items.first.kind_of? Symbol
|
468
|
+
|
469
|
+
raise ArgumentError, "Illegal template -- first component cannot be optional: #{str.inspect}" if @items.first =~ /\[|\]/
|
176
470
|
|
177
471
|
# Verify uniqueness of each component.
|
178
472
|
@items.inject({}) do |seen, item|
|
@@ -187,46 +481,110 @@ module Irc
|
|
187
481
|
end
|
188
482
|
end
|
189
483
|
|
484
|
+
def regexp=(str)
|
485
|
+
# debug "Original string: #{str.inspect}"
|
486
|
+
rx = Regexp.escape(str)
|
487
|
+
# debug "Escaped: #{rx.inspect}"
|
488
|
+
rx.gsub!(/((?:\\ )*)(:|\\\*)(\w+)/) { |m|
|
489
|
+
whites = $1
|
490
|
+
is_single = $2 == ":"
|
491
|
+
name = $3.intern
|
492
|
+
|
493
|
+
not_needed = @defaults.has_key?(name)
|
494
|
+
|
495
|
+
has_req = @requirements[name]
|
496
|
+
debug "Requirements for #{name}: #{has_req.inspect}"
|
497
|
+
case has_req
|
498
|
+
when nil
|
499
|
+
sub = is_single ? "\\S+" : ".*?"
|
500
|
+
when Regexp
|
501
|
+
# Remove captures and the ^ and $ that are sometimes placed in requirement regexps
|
502
|
+
sub = has_req.mm_cleanup
|
503
|
+
when String
|
504
|
+
sub = Regexp.escape(has_req)
|
505
|
+
when Array
|
506
|
+
sub = has_req[0].mm_cleanup
|
507
|
+
when Hash
|
508
|
+
sub = has_req[:regexp].mm_cleanup
|
509
|
+
else
|
510
|
+
warning "Odd requirement #{has_req.inspect} of class #{has_req.class} for parameter '#{name}'"
|
511
|
+
sub = Regexp.escape(has_req.to_s) rescue "\\S+"
|
512
|
+
end
|
513
|
+
debug "Regexp for #{name}: #{sub.inspect}"
|
514
|
+
s = "#{not_needed ? "(?:" : ""}#{whites}(#{sub})#{ not_needed ? ")?" : ""}"
|
515
|
+
}
|
516
|
+
# debug "Replaced dyns: #{rx.inspect}"
|
517
|
+
rx.gsub!(/((?:\\ )*)\\\[/, "(?:\\1")
|
518
|
+
rx.gsub!(/\\\]/, ")?")
|
519
|
+
# debug "Delimited optionals: #{rx.inspect}"
|
520
|
+
rx.gsub!(/(?:\\ )+/, "\\s+")
|
521
|
+
# debug "Corrected spaces: #{rx.inspect}"
|
522
|
+
# Created message (such as by fake_message) can contain multiple lines
|
523
|
+
@regexp = /\A#{rx}\z/m
|
524
|
+
end
|
525
|
+
|
190
526
|
# Recognize the provided string components, returning a hash of
|
191
527
|
# recognized values, or [nil, reason] if the string isn't recognized.
|
192
528
|
def recognize(m)
|
193
|
-
|
529
|
+
|
530
|
+
debug "Testing #{m.message.inspect} against #{self.inspect}"
|
531
|
+
|
532
|
+
# Early out
|
533
|
+
return nil, "template #{@template} is not configured for private messages" if @options.has_key?(:private) && !@options[:private] && m.private?
|
534
|
+
return nil, "template #{@template} is not configured for public messages" if @options.has_key?(:public) && !@options[:public] && !m.private?
|
535
|
+
|
194
536
|
options = {}
|
195
537
|
|
196
|
-
@
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
538
|
+
matching = @regexp.match(m.message)
|
539
|
+
return nil, "#{m.message.inspect} doesn't match #{@template} (#{@regexp})" unless matching
|
540
|
+
return nil, "#{m.message.inspect} only matches #{@template} (#{@regexp}) partially: #{matching[0].inspect}" unless matching[0] == m.message
|
541
|
+
|
542
|
+
debug_match = matching[1..-1].collect{ |d| d.inspect}.join(', ')
|
543
|
+
debug "#{m.message.inspect} matched #{@regexp} with #{debug_match}"
|
544
|
+
debug "Associating #{debug_match} with dyn items #{@dyn_items.join(', ')}"
|
545
|
+
|
546
|
+
@dyn_items.each_with_index { |it, i|
|
547
|
+
next if i == 0
|
548
|
+
item = it.name
|
549
|
+
debug "dyn item #{item} (multi-word: #{it.multi?.inspect})"
|
550
|
+
if it.multi?
|
551
|
+
if matching[i].nil?
|
552
|
+
default = it.default
|
553
|
+
case default
|
554
|
+
when Array
|
555
|
+
value = default.clone
|
556
|
+
when String
|
557
|
+
value = default.strip.split
|
558
|
+
when nil, false, []
|
559
|
+
value = []
|
215
560
|
else
|
216
|
-
|
561
|
+
warning "Unmanageable default #{default} detected for :*#{item.to_s}, using []"
|
562
|
+
value = []
|
217
563
|
end
|
564
|
+
case default
|
565
|
+
when String
|
566
|
+
value.instance_variable_set(:@string_value, default)
|
567
|
+
else
|
568
|
+
value.instance_variable_set(:@string_value, value.join(' '))
|
569
|
+
end
|
570
|
+
else
|
571
|
+
value = matching[i].split
|
572
|
+
value.instance_variable_set(:@string_value, matching[i])
|
573
|
+
end
|
574
|
+
def value.to_s
|
575
|
+
@string_value
|
218
576
|
end
|
219
577
|
else
|
220
|
-
|
221
|
-
|
222
|
-
|
578
|
+
if matching[i].nil?
|
579
|
+
warning "No default value for option #{item.inspect} specified" unless @defaults.has_key?(item)
|
580
|
+
value = it.default
|
581
|
+
else
|
582
|
+
value = it.collect(matching[i])
|
583
|
+
end
|
223
584
|
end
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
return nil, "template is not configured for private messages" if @options.has_key?(:private) && !@options[:private] && m.private?
|
229
|
-
return nil, "template is not configured for public messages" if @options.has_key?(:public) && !@options[:public] && !m.private?
|
585
|
+
options[item] = value
|
586
|
+
debug "set #{item} to #{options[item].inspect}"
|
587
|
+
}
|
230
588
|
|
231
589
|
options.delete_if {|k, v| v.nil?} # Remove nil values.
|
232
590
|
return options, nil
|
@@ -235,22 +593,7 @@ module Irc
|
|
235
593
|
def inspect
|
236
594
|
when_str = @requirements.empty? ? "" : " when #{@requirements.inspect}"
|
237
595
|
default_str = @defaults.empty? ? "" : " || #{@defaults.inspect}"
|
238
|
-
"<#{self.class.to_s} #{@items.
|
239
|
-
end
|
240
|
-
|
241
|
-
# Verify that the given value passes this template's requirements
|
242
|
-
def passes_requirements?(name, value)
|
243
|
-
return @defaults.key?(name) && @defaults[name].nil? if value.nil? # Make sure it's there if it should be
|
244
|
-
|
245
|
-
case @requirements[name]
|
246
|
-
when nil then true
|
247
|
-
when Regexp then
|
248
|
-
value = value.to_s
|
249
|
-
match = @requirements[name].match(value)
|
250
|
-
match && match[0].length == value.length
|
251
|
-
else
|
252
|
-
@requirements[name] == value.to_s
|
253
|
-
end
|
596
|
+
"<#{self.class.to_s} #{@items.map { |c| c.inspect }.join(' ').inspect}#{default_str}#{when_str}>"
|
254
597
|
end
|
255
598
|
|
256
599
|
def requirements_for(name)
|
@@ -268,3 +611,4 @@ module Irc
|
|
268
611
|
end
|
269
612
|
end
|
270
613
|
end
|
614
|
+
end
|