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/post-config.rb
CHANGED
data/lib/rbot/rbotconfig.rb
CHANGED
@@ -1,31 +1,44 @@
|
|
1
1
|
module Irc
|
2
|
+
class Bot
|
2
3
|
module Config
|
3
|
-
@@datadir
|
4
|
+
unless defined?(@@datadir)
|
5
|
+
@@datadir = nil
|
4
6
|
|
5
|
-
|
6
|
-
defaultdir = File.expand_path(File.dirname($0) + '/../data')
|
7
|
+
defaultdatadir = File.expand_path(File.dirname($0) + '/../data/rbot')
|
7
8
|
|
8
|
-
|
9
|
-
|
9
|
+
if File.directory? defaultdatadir
|
10
|
+
@@datadir = defaultdatadir
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
unless defined?(@@coredir)
|
15
|
+
@@coredir = nil
|
16
|
+
|
17
|
+
defaultcoredir = File.expand_path(File.dirname($0) + '/../lib/rbot/core')
|
18
|
+
|
19
|
+
if File.directory? defaultcoredir
|
20
|
+
@@coredir = defaultcoredir
|
21
|
+
end
|
10
22
|
end
|
11
|
-
|
23
|
+
|
12
24
|
# setup pkg-based configuration - i.e. where were we installed to, where
|
13
25
|
# are our data files, etc.
|
14
|
-
if @@datadir.nil?
|
26
|
+
if @@datadir.nil? or @@coredir.nil?
|
15
27
|
begin
|
16
28
|
debug "trying to load rubygems"
|
17
29
|
require 'rubygems'
|
18
|
-
|
19
|
-
if $version =~ /(.*)-svn\Z/
|
30
|
+
if $version =~ /^(.*)-(?:git|rc\d)(?: .*)?$/
|
20
31
|
version = $1
|
21
32
|
else
|
22
33
|
version = $version
|
23
34
|
end
|
35
|
+
debug "loaded rubygems, looking for rbot version #{$version} (rbot-#{version})"
|
24
36
|
gemname, gem = Gem.source_index.find{|name, spec| spec.name == 'rbot' && spec.version.version == version}
|
25
37
|
debug "got gem #{gem}"
|
26
38
|
if gem && path = gem.full_gem_path
|
27
39
|
debug "installed via rubygems to #{path}"
|
28
40
|
@@datadir = "#{path}/data/rbot"
|
41
|
+
@@coredir = "#{path}/lib/rbot/core"
|
29
42
|
else
|
30
43
|
debug "not installed via rubygems"
|
31
44
|
end
|
@@ -34,18 +47,24 @@ module Irc
|
|
34
47
|
end
|
35
48
|
end
|
36
49
|
|
37
|
-
if @@datadir.nil?
|
50
|
+
if @@datadir.nil? or @@coredir.nil?
|
38
51
|
begin
|
39
52
|
require 'rbot/pkgconfig'
|
40
53
|
@@datadir = PKGConfig::DATADIR
|
54
|
+
@@coredir = PKGConfig::COREDIR
|
41
55
|
rescue LoadError
|
42
|
-
error "fatal - no way to determine data dir"
|
56
|
+
error "fatal - no way to determine data or core dir"
|
43
57
|
exit 2
|
44
58
|
end
|
45
59
|
end
|
46
|
-
|
60
|
+
|
47
61
|
def Config.datadir
|
48
62
|
@@datadir
|
49
63
|
end
|
64
|
+
|
65
|
+
def Config.coredir
|
66
|
+
@@coredir
|
67
|
+
end
|
50
68
|
end
|
51
69
|
end
|
70
|
+
end
|
data/lib/rbot/registry.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
require 'rbot/dbhash'
|
2
2
|
|
3
3
|
module Irc
|
4
|
+
class Bot
|
4
5
|
|
5
|
-
#
|
6
|
+
# This class is now used purely for upgrading from prior versions of rbot
|
6
7
|
# the new registry is split into multiple DBHash objects, one per plugin
|
7
|
-
class
|
8
|
+
class Registry
|
8
9
|
def initialize(bot)
|
9
10
|
@bot = bot
|
10
11
|
upgrade_data
|
@@ -16,7 +17,7 @@ module Irc
|
|
16
17
|
# work with is @bot.botclass.
|
17
18
|
def upgrade_data
|
18
19
|
if File.exist?("#{@bot.botclass}/registry.db")
|
19
|
-
log "upgrading old-style (rbot 0.9.5 or earlier) plugin registry to new format"
|
20
|
+
log _("upgrading old-style (rbot 0.9.5 or earlier) plugin registry to new format")
|
20
21
|
old = BDB::Hash.open("#{@bot.botclass}/registry.db", nil,
|
21
22
|
"r+", 0600)
|
22
23
|
new = BDB::CIBtree.open("#{@bot.botclass}/plugin_registry.db", nil,
|
@@ -34,9 +35,9 @@ module Irc
|
|
34
35
|
def upgrade_data2
|
35
36
|
if File.exist?("#{@bot.botclass}/plugin_registry.db")
|
36
37
|
Dir.mkdir("#{@bot.botclass}/registry") unless File.exist?("#{@bot.botclass}/registry")
|
37
|
-
env = BDB::Env.open("#{@bot.botclass}", BDB::INIT_TRANSACTION | BDB::CREATE | BDB::RECOVER )
|
38
|
+
env = BDB::Env.open("#{@bot.botclass}", BDB::INIT_TRANSACTION | BDB::CREATE | BDB::RECOVER)# | BDB::TXN_NOSYNC)
|
38
39
|
dbs = Hash.new
|
39
|
-
log "upgrading previous (rbot 0.9.9 or earlier) plugin registry to new split format"
|
40
|
+
log _("upgrading previous (rbot 0.9.9 or earlier) plugin registry to new split format")
|
40
41
|
old = BDB::CIBtree.open("#{@bot.botclass}/plugin_registry.db", nil,
|
41
42
|
"r+", 0600, "env" => env)
|
42
43
|
old.each {|k,v|
|
@@ -49,13 +50,13 @@ module Irc
|
|
49
50
|
dirs.length.times { |i|
|
50
51
|
dir = dirs[0,i+1].join("/")+"/"
|
51
52
|
unless File.exist?(dir)
|
52
|
-
log "creating subregistry directory #{dir}"
|
53
|
-
Dir.mkdir(dir)
|
53
|
+
log _("creating subregistry directory #{dir}")
|
54
|
+
Dir.mkdir(dir)
|
54
55
|
end
|
55
56
|
}
|
56
57
|
end
|
57
58
|
unless dbs.has_key?(prefix)
|
58
|
-
log "creating db #{@bot.botclass}/registry/#{prefix}.db"
|
59
|
+
log _("creating db #{@bot.botclass}/registry/#{prefix}.db")
|
59
60
|
dbs[prefix] = BDB::CIBtree.open("#{@bot.botclass}/registry/#{prefix}.db",
|
60
61
|
nil, BDB::CREATE | BDB::EXCL,
|
61
62
|
0600, "env" => env)
|
@@ -65,13 +66,12 @@ module Irc
|
|
65
66
|
old.close
|
66
67
|
File.rename("#{@bot.botclass}/plugin_registry.db", "#{@bot.botclass}/plugin_registry.db.old")
|
67
68
|
dbs.each {|k,v|
|
68
|
-
log "closing db #{k}"
|
69
|
+
log _("closing db #{k}")
|
69
70
|
v.close
|
70
71
|
}
|
71
72
|
env.close
|
72
73
|
end
|
73
74
|
end
|
74
|
-
end
|
75
75
|
|
76
76
|
|
77
77
|
# This class provides persistent storage for plugins via a hash interface.
|
@@ -94,7 +94,7 @@ module Irc
|
|
94
94
|
# in object store mode, don't make the mistake of treating it like a live
|
95
95
|
# object, e.g. (using the example above)
|
96
96
|
# @registry[:blah][:foo] = "flump"
|
97
|
-
# will NOT modify the object in the registry - remember that
|
97
|
+
# will NOT modify the object in the registry - remember that Registry#[]
|
98
98
|
# returns a Marshal.restore'd object, the object you just modified in place
|
99
99
|
# will disappear. You would need to:
|
100
100
|
# blah = @registry[:blah]
|
@@ -117,32 +117,46 @@ module Irc
|
|
117
117
|
# Your plugins section of the registry is private, it has its own namespace
|
118
118
|
# (derived from the plugin's class name, so change it and lose your data).
|
119
119
|
# Calls to registry.each etc, will only iterate over your namespace.
|
120
|
-
class
|
121
|
-
|
120
|
+
class Accessor
|
121
|
+
|
122
|
+
attr_accessor :recovery
|
123
|
+
|
124
|
+
# plugins don't call this - a Registry::Accessor is created for them and
|
122
125
|
# is accessible via @registry.
|
123
126
|
def initialize(bot, name)
|
124
127
|
@bot = bot
|
125
128
|
@name = name.downcase
|
126
|
-
|
129
|
+
@filename = "#{@bot.botclass}/registry/#{@name}"
|
130
|
+
dirs = File.dirname(@filename).split("/")
|
127
131
|
dirs.length.times { |i|
|
128
132
|
dir = dirs[0,i+1].join("/")+"/"
|
129
133
|
unless File.exist?(dir)
|
130
134
|
debug "creating subregistry directory #{dir}"
|
131
|
-
Dir.mkdir(dir)
|
135
|
+
Dir.mkdir(dir)
|
132
136
|
end
|
133
137
|
}
|
134
|
-
@
|
138
|
+
@filename << ".db"
|
139
|
+
@registry = nil
|
135
140
|
@default = nil
|
141
|
+
@recovery = nil
|
136
142
|
# debug "initializing registry accessor with name #{@name}"
|
137
143
|
end
|
138
144
|
|
145
|
+
def registry
|
146
|
+
@registry ||= DBTree.new @bot, "registry/#{@name}"
|
147
|
+
end
|
148
|
+
|
139
149
|
def flush
|
140
|
-
|
141
|
-
|
150
|
+
# debug "fushing registry #{registry}"
|
151
|
+
return if !@registry
|
152
|
+
registry.flush
|
153
|
+
registry.sync
|
142
154
|
end
|
143
155
|
|
144
156
|
def close
|
145
|
-
|
157
|
+
# debug "closing registry #{registry}"
|
158
|
+
return if !@registry
|
159
|
+
registry.close
|
146
160
|
end
|
147
161
|
|
148
162
|
# convert value to string form for storing in the registry
|
@@ -167,84 +181,93 @@ module Irc
|
|
167
181
|
begin
|
168
182
|
Marshal.restore(val)
|
169
183
|
rescue Exception => e
|
170
|
-
|
171
|
-
debug e
|
172
|
-
|
173
|
-
if @default != nil
|
184
|
+
error _("failed to restore marshal data for #{val.inspect}, attempting recovery or fallback to default")
|
185
|
+
debug e
|
186
|
+
if defined? @recovery and @recovery
|
174
187
|
begin
|
175
|
-
return
|
176
|
-
rescue
|
177
|
-
|
188
|
+
return @recovery.call(val)
|
189
|
+
rescue Exception => ee
|
190
|
+
error _("marshal recovery failed, trying default")
|
191
|
+
debug ee
|
178
192
|
end
|
179
|
-
else
|
180
|
-
return nil
|
181
193
|
end
|
194
|
+
return default
|
182
195
|
end
|
183
196
|
end
|
184
197
|
|
185
198
|
# lookup a key in the registry
|
186
199
|
def [](key)
|
187
|
-
if @registry.has_key?(key)
|
188
|
-
return restore(
|
189
|
-
elsif @default != nil
|
190
|
-
return restore(@default)
|
200
|
+
if File.exist?(@filename) && registry.has_key?(key)
|
201
|
+
return restore(registry[key])
|
191
202
|
else
|
192
|
-
return
|
203
|
+
return default
|
193
204
|
end
|
194
205
|
end
|
195
206
|
|
196
207
|
# set a key in the registry
|
197
208
|
def []=(key,value)
|
198
|
-
|
209
|
+
registry[key] = store(value)
|
199
210
|
end
|
200
211
|
|
201
212
|
# set the default value for registry lookups, if the key sought is not
|
202
213
|
# found, the default will be returned. The default default (har) is nil.
|
203
214
|
def set_default (default)
|
204
|
-
@default =
|
215
|
+
@default = default
|
216
|
+
end
|
217
|
+
|
218
|
+
def default
|
219
|
+
@default && (@default.dup rescue @default)
|
205
220
|
end
|
206
221
|
|
207
222
|
# just like Hash#each
|
208
223
|
def each(&block)
|
209
|
-
@
|
224
|
+
return nil unless File.exist?(@filename)
|
225
|
+
registry.each {|key,value|
|
210
226
|
block.call(key, restore(value))
|
211
227
|
}
|
212
228
|
end
|
213
229
|
|
214
230
|
# just like Hash#each_key
|
215
231
|
def each_key(&block)
|
216
|
-
|
232
|
+
return nil unless File.exist?(@filename)
|
233
|
+
registry.each {|key, value|
|
217
234
|
block.call(key)
|
218
235
|
}
|
219
236
|
end
|
220
237
|
|
221
238
|
# just like Hash#each_value
|
222
239
|
def each_value(&block)
|
223
|
-
|
240
|
+
return nil unless File.exist?(@filename)
|
241
|
+
registry.each {|key, value|
|
224
242
|
block.call(restore(value))
|
225
243
|
}
|
226
244
|
end
|
227
245
|
|
228
246
|
# just like Hash#has_key?
|
229
247
|
def has_key?(key)
|
230
|
-
return
|
248
|
+
return false unless File.exist?(@filename)
|
249
|
+
return registry.has_key?(key)
|
231
250
|
end
|
232
251
|
alias include? has_key?
|
233
252
|
alias member? has_key?
|
253
|
+
alias key? has_key?
|
234
254
|
|
235
255
|
# just like Hash#has_both?
|
236
256
|
def has_both?(key, value)
|
237
|
-
return
|
257
|
+
return false unless File.exist?(@filename)
|
258
|
+
return registry.has_both?(key, store(value))
|
238
259
|
end
|
239
260
|
|
240
261
|
# just like Hash#has_value?
|
241
262
|
def has_value?(value)
|
242
|
-
return
|
263
|
+
return false unless File.exist?(@filename)
|
264
|
+
return registry.has_value?(store(value))
|
243
265
|
end
|
244
266
|
|
245
267
|
# just like Hash#index?
|
246
268
|
def index(value)
|
247
|
-
|
269
|
+
return nil unless File.exist?(@filename)
|
270
|
+
ind = registry.index(store(value))
|
248
271
|
if ind
|
249
272
|
return ind
|
250
273
|
else
|
@@ -254,18 +277,21 @@ module Irc
|
|
254
277
|
|
255
278
|
# delete a key from the registry
|
256
279
|
def delete(key)
|
257
|
-
return
|
280
|
+
return default unless File.exist?(@filename)
|
281
|
+
return registry.delete(key)
|
258
282
|
end
|
259
283
|
|
260
284
|
# returns a list of your keys
|
261
285
|
def keys
|
262
|
-
return @
|
286
|
+
return [] unless File.exist?(@filename)
|
287
|
+
return registry.keys
|
263
288
|
end
|
264
289
|
|
265
290
|
# Return an array of all associations [key, value] in your namespace
|
266
291
|
def to_a
|
292
|
+
return [] unless File.exist?(@filename)
|
267
293
|
ret = Array.new
|
268
|
-
|
294
|
+
registry.each {|key, value|
|
269
295
|
ret << [key, restore(value)]
|
270
296
|
}
|
271
297
|
return ret
|
@@ -273,8 +299,9 @@ module Irc
|
|
273
299
|
|
274
300
|
# Return an hash of all associations {key => value} in your namespace
|
275
301
|
def to_hash
|
302
|
+
return {} unless File.exist?(@filename)
|
276
303
|
ret = Hash.new
|
277
|
-
|
304
|
+
registry.each {|key, value|
|
278
305
|
ret[key] = restore(value)
|
279
306
|
}
|
280
307
|
return ret
|
@@ -282,12 +309,14 @@ module Irc
|
|
282
309
|
|
283
310
|
# empties the registry (restricted to your namespace)
|
284
311
|
def clear
|
285
|
-
@
|
312
|
+
return true unless File.exist?(@filename)
|
313
|
+
registry.clear
|
286
314
|
end
|
287
315
|
alias truncate clear
|
288
316
|
|
289
317
|
# returns an array of the values in your namespace of the registry
|
290
318
|
def values
|
319
|
+
return [] unless File.exist?(@filename)
|
291
320
|
ret = Array.new
|
292
321
|
self.each {|k,v|
|
293
322
|
ret << restore(v)
|
@@ -296,7 +325,7 @@ module Irc
|
|
296
325
|
end
|
297
326
|
|
298
327
|
def sub_registry(prefix)
|
299
|
-
return
|
328
|
+
return Accessor.new(@bot, @name + "/" + prefix.to_s)
|
300
329
|
end
|
301
330
|
|
302
331
|
# returns the number of keys in your registry namespace
|
@@ -307,4 +336,6 @@ module Irc
|
|
307
336
|
|
308
337
|
end
|
309
338
|
|
339
|
+
end
|
340
|
+
end
|
310
341
|
end
|
data/lib/rbot/rfc2812.rb
CHANGED
@@ -1,35 +1,50 @@
|
|
1
|
+
#-- vim:sw=2:et
|
2
|
+
#++
|
3
|
+
#
|
4
|
+
# :title: RFC 2821 Client Protocol module
|
5
|
+
#
|
6
|
+
# This module defines the Irc::Client class, a class that can handle and
|
7
|
+
# dispatch messages based on RFC 2821 (Internet Relay Chat: Client Protocol)
|
8
|
+
|
1
9
|
module Irc
|
2
|
-
#
|
3
|
-
#
|
4
|
-
|
10
|
+
# - The server sends Replies 001 to 004 to a user upon
|
11
|
+
# successful registration.
|
12
|
+
|
5
13
|
# "Welcome to the Internet Relay Network
|
6
14
|
# <nick>!<user>@<host>"
|
7
|
-
|
15
|
+
#
|
16
|
+
RPL_WELCOME=001
|
17
|
+
|
8
18
|
# "Your host is <servername>, running version <ver>"
|
9
|
-
|
19
|
+
RPL_YOURHOST=002
|
20
|
+
|
10
21
|
# "This server was created <date>"
|
22
|
+
RPL_CREATED=003
|
23
|
+
|
24
|
+
# "<servername> <version> <available user modes> <available channel modes>"
|
11
25
|
RPL_MYINFO=004
|
12
|
-
|
13
|
-
#
|
26
|
+
|
27
|
+
# "005 nick PREFIX=(ov)@+ CHANTYPES=#& :are supported by this server"
|
14
28
|
#
|
15
|
-
#
|
16
|
-
# successful registration.
|
29
|
+
# defines the capabilities supported by the server.
|
17
30
|
#
|
18
|
-
#
|
19
|
-
# # "Try server <server name>, port <port number>"
|
20
|
-
RPL_ISUPPORT=005
|
21
|
-
# "005 nick PREFIX=(ov)@+ CHANTYPES=#& :are supported by this server"
|
31
|
+
# Previous RFCs defined message 005 as follows:
|
22
32
|
#
|
23
33
|
# - Sent by the server to a user to suggest an alternative
|
24
|
-
#
|
25
|
-
#
|
34
|
+
# server. This is often used when the connection is
|
35
|
+
# refused because the server is already full.
|
26
36
|
#
|
27
|
-
|
37
|
+
# # "Try server <server name>, port <port number>"
|
38
|
+
#
|
39
|
+
# RPL_BOUNCE=005
|
40
|
+
#
|
41
|
+
RPL_ISUPPORT=005
|
42
|
+
|
28
43
|
# ":*1<reply> *( " " <reply> )"
|
29
44
|
#
|
30
45
|
# - Reply format used by USERHOST to list replies to
|
31
|
-
#
|
32
|
-
#
|
46
|
+
# the query list. The reply string is composed as
|
47
|
+
# follows:
|
33
48
|
#
|
34
49
|
# reply = nickname [ "*" ] "=" ( "+" / "-" ) hostname
|
35
50
|
#
|
@@ -38,138 +53,158 @@ module Irc
|
|
38
53
|
# whether the client has set an AWAY message or not
|
39
54
|
# respectively.
|
40
55
|
#
|
41
|
-
|
56
|
+
RPL_USERHOST=302
|
57
|
+
|
42
58
|
# ":*1<nick> *( " " <nick> )"
|
43
59
|
#
|
44
60
|
# - Reply format used by ISON to list replies to the
|
45
|
-
#
|
61
|
+
# query list.
|
46
62
|
#
|
47
|
-
|
63
|
+
RPL_ISON=303
|
64
|
+
|
65
|
+
# - These replies are used with the AWAY command (if
|
66
|
+
# allowed). RPL_AWAY is sent to any client sending a
|
67
|
+
# PRIVMSG to a client which is away. RPL_AWAY is only
|
68
|
+
# sent by the server to which the client is connected.
|
69
|
+
# Replies RPL_UNAWAY and RPL_NOWAWAY are sent when the
|
70
|
+
# client removes and sets an AWAY message.
|
71
|
+
|
48
72
|
# "<nick> :<away message>"
|
49
|
-
|
73
|
+
RPL_AWAY=301
|
74
|
+
|
50
75
|
# ":You are no longer marked as being away"
|
51
|
-
|
76
|
+
RPL_UNAWAY=305
|
77
|
+
|
52
78
|
# ":You have been marked as being away"
|
53
|
-
|
54
|
-
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
|
79
|
+
RPL_NOWAWAY=306
|
80
|
+
|
81
|
+
# - Replies 311 - 313, 317 - 319 are all replies
|
82
|
+
# generated in response to a WHOIS message. Given that
|
83
|
+
# there are enough parameters present, the answering
|
84
|
+
# server MUST either formulate a reply out of the above
|
85
|
+
# numerics (if the query nick is found) or return an
|
86
|
+
# error reply. The '*' in RPL_WHOISUSER is there as
|
87
|
+
# the literal character and not as a wild card. For
|
88
|
+
# each reply set, only RPL_WHOISCHANNELS may appear
|
89
|
+
# more than once (for long lists of channel names).
|
90
|
+
# The '@' and '+' characters next to the channel name
|
91
|
+
# indicate whether a client is a channel operator or
|
92
|
+
# has been granted permission to speak on a moderated
|
93
|
+
# channel. The RPL_ENDOFWHOIS reply is used to mark
|
94
|
+
# the end of processing a WHOIS message.
|
95
|
+
|
62
96
|
# "<nick> <user> <host> * :<real name>"
|
63
|
-
|
97
|
+
RPL_WHOISUSER=311
|
98
|
+
|
64
99
|
# "<nick> <server> :<server info>"
|
65
|
-
|
100
|
+
RPL_WHOISSERVER=312
|
101
|
+
|
66
102
|
# "<nick> :is an IRC operator"
|
67
|
-
|
103
|
+
RPL_WHOISOPERATOR=313
|
104
|
+
|
68
105
|
# "<nick> <integer> :seconds idle"
|
69
|
-
|
106
|
+
RPL_WHOISIDLE=317
|
107
|
+
|
70
108
|
# "<nick> :End of WHOIS list"
|
71
|
-
|
109
|
+
RPL_ENDOFWHOIS=318
|
110
|
+
|
72
111
|
# "<nick> :*( ( "@" / "+" ) <channel> " " )"
|
73
|
-
|
74
|
-
|
75
|
-
#
|
76
|
-
#
|
77
|
-
#
|
78
|
-
#
|
79
|
-
#
|
80
|
-
#
|
81
|
-
|
82
|
-
# more than once (for long lists of channel names).
|
83
|
-
# The '@' and '+' characters next to the channel name
|
84
|
-
# indicate whether a client is a channel operator or
|
85
|
-
# has been granted permission to speak on a moderated
|
86
|
-
# channel. The RPL_ENDOFWHOIS reply is used to mark
|
87
|
-
# the end of processing a WHOIS message.
|
88
|
-
#
|
89
|
-
RPL_WHOWASUSER=314
|
112
|
+
RPL_WHOISCHANNELS=319
|
113
|
+
|
114
|
+
# - When replying to a WHOWAS message, a server MUST use
|
115
|
+
# the replies RPL_WHOWASUSER, RPL_WHOISSERVER or
|
116
|
+
# ERR_WASNOSUCHNICK for each nickname in the presented
|
117
|
+
# list. At the end of all reply batches, there MUST
|
118
|
+
# be RPL_ENDOFWHOWAS (even if there was only one reply
|
119
|
+
# and it was an error).
|
120
|
+
|
90
121
|
# "<nick> <user> <host> * :<real name>"
|
91
|
-
|
122
|
+
RPL_WHOWASUSER=314
|
123
|
+
|
92
124
|
# "<nick> :End of WHOWAS"
|
93
|
-
|
94
|
-
|
95
|
-
#
|
96
|
-
#
|
97
|
-
#
|
98
|
-
#
|
99
|
-
|
100
|
-
#
|
101
|
-
RPL_LISTSTART=321
|
125
|
+
RPL_ENDOFWHOWAS=369
|
126
|
+
|
127
|
+
# - Replies RPL_LIST, RPL_LISTEND mark the actual replies
|
128
|
+
# with data and end of the server's response to a LIST
|
129
|
+
# command. If there are no channels available to return,
|
130
|
+
# only the end reply MUST be sent.
|
131
|
+
|
102
132
|
# Obsolete. Not used.
|
103
|
-
|
104
|
-
|
133
|
+
RPL_LISTSTART=321
|
134
|
+
|
105
135
|
# "<channel> <# visible> :<topic>"
|
106
|
-
|
136
|
+
RPL_LIST=322
|
137
|
+
|
107
138
|
# ":End of LIST"
|
108
|
-
|
109
|
-
|
110
|
-
# with data and end of the server's response to a LIST
|
111
|
-
# command. If there are no channels available to return,
|
112
|
-
# only the end reply MUST be sent.
|
113
|
-
#
|
114
|
-
RPL_UNIQOPIS=325
|
139
|
+
RPL_LISTEND=323
|
140
|
+
|
115
141
|
# "<channel> <nickname>"
|
116
|
-
|
117
|
-
|
142
|
+
RPL_UNIQOPIS=325
|
143
|
+
|
118
144
|
# "<channel> <mode> <mode params>"
|
119
|
-
|
120
|
-
|
145
|
+
RPL_CHANNELMODEIS=324
|
146
|
+
|
121
147
|
# "<channel> :No topic is set"
|
122
|
-
|
123
|
-
|
124
|
-
#
|
148
|
+
RPL_NOTOPIC=331
|
149
|
+
|
125
150
|
# - When sending a TOPIC message to determine the
|
126
|
-
#
|
127
|
-
#
|
128
|
-
#
|
129
|
-
|
130
|
-
|
151
|
+
# channel topic, one of two replies is sent. If
|
152
|
+
# the topic is set, RPL_TOPIC is sent back else
|
153
|
+
# RPL_NOTOPIC.
|
154
|
+
|
155
|
+
# "<channel> :<topic>"
|
156
|
+
RPL_TOPIC=332
|
157
|
+
|
131
158
|
# <channel> <set by> <unixtime>
|
132
|
-
|
159
|
+
RPL_TOPIC_INFO=333
|
160
|
+
|
133
161
|
# "<channel> <nick>"
|
134
162
|
#
|
135
163
|
# - Returned by the server to indicate that the
|
136
|
-
#
|
137
|
-
#
|
164
|
+
# attempted INVITE message was successful and is
|
165
|
+
# being passed onto the end client.
|
138
166
|
#
|
139
|
-
|
167
|
+
RPL_INVITING=341
|
168
|
+
|
140
169
|
# "<user> :Summoning user to IRC"
|
141
170
|
#
|
142
171
|
# - Returned by a server answering a SUMMON message to
|
143
|
-
#
|
172
|
+
# indicate that it is summoning that user.
|
144
173
|
#
|
145
|
-
|
174
|
+
RPL_SUMMONING=342
|
175
|
+
|
146
176
|
# "<channel> <invitemask>"
|
147
|
-
|
177
|
+
RPL_INVITELIST=346
|
178
|
+
|
148
179
|
# "<channel> :End of channel invite list"
|
149
180
|
#
|
150
181
|
# - When listing the 'invitations masks' for a given channel,
|
151
|
-
#
|
152
|
-
#
|
153
|
-
#
|
154
|
-
#
|
155
|
-
#
|
182
|
+
# a server is required to send the list back using the
|
183
|
+
# RPL_INVITELIST and RPL_ENDOFINVITELIST messages. A
|
184
|
+
# separate RPL_INVITELIST is sent for each active mask.
|
185
|
+
# After the masks have been listed (or if none present) a
|
186
|
+
# RPL_ENDOFINVITELIST MUST be sent.
|
156
187
|
#
|
157
|
-
|
188
|
+
RPL_ENDOFINVITELIST=347
|
189
|
+
|
158
190
|
# "<channel> <exceptionmask>"
|
159
|
-
|
191
|
+
RPL_EXCEPTLIST=348
|
192
|
+
|
160
193
|
# "<channel> :End of channel exception list"
|
161
194
|
#
|
162
195
|
# - When listing the 'exception masks' for a given channel,
|
163
|
-
#
|
164
|
-
#
|
165
|
-
#
|
166
|
-
#
|
167
|
-
#
|
196
|
+
# a server is required to send the list back using the
|
197
|
+
# RPL_EXCEPTLIST and RPL_ENDOFEXCEPTLIST messages. A
|
198
|
+
# separate RPL_EXCEPTLIST is sent for each active mask.
|
199
|
+
# After the masks have been listed (or if none present)
|
200
|
+
# a RPL_ENDOFEXCEPTLIST MUST be sent.
|
168
201
|
#
|
169
|
-
|
202
|
+
RPL_ENDOFEXCEPTLIST=349
|
203
|
+
|
170
204
|
# "<version>.<debuglevel> <server> :<comments>"
|
171
205
|
#
|
172
206
|
# - Reply by the server showing its version details.
|
207
|
+
#
|
173
208
|
# The <version> is the version of the software being
|
174
209
|
# used (including any patchlevel revisions) and the
|
175
210
|
# <debuglevel> is used to indicate if the server is
|
@@ -178,276 +213,307 @@ module Irc
|
|
178
213
|
# The "comments" field may contain any comments about
|
179
214
|
# the version or further version details.
|
180
215
|
#
|
181
|
-
|
216
|
+
RPL_VERSION=351
|
217
|
+
|
218
|
+
# - The RPL_WHOREPLY and RPL_ENDOFWHO pair are used
|
219
|
+
# to answer a WHO message. The RPL_WHOREPLY is only
|
220
|
+
# sent if there is an appropriate match to the WHO
|
221
|
+
# query. If there is a list of parameters supplied
|
222
|
+
# with a WHO message, a RPL_ENDOFWHO MUST be sent
|
223
|
+
# after processing each list item with <name> being
|
224
|
+
# the item.
|
225
|
+
|
182
226
|
# "<channel> <user> <host> <server> <nick>
|
183
227
|
# ( "H" / "G" > ["*"] [ ( "@" / "+" ) ]
|
184
228
|
# :<hopcount> <real name>"
|
185
229
|
#
|
186
|
-
|
230
|
+
RPL_WHOREPLY=352
|
231
|
+
|
187
232
|
# "<name> :End of WHO list"
|
188
|
-
|
189
|
-
|
190
|
-
# to
|
191
|
-
#
|
192
|
-
#
|
193
|
-
#
|
194
|
-
#
|
195
|
-
#
|
196
|
-
#
|
197
|
-
|
233
|
+
RPL_ENDOFWHO=315
|
234
|
+
|
235
|
+
# - To reply to a NAMES message, a reply pair consisting
|
236
|
+
# of RPL_NAMREPLY and RPL_ENDOFNAMES is sent by the
|
237
|
+
# server back to the client. If there is no channel
|
238
|
+
# found as in the query, then only RPL_ENDOFNAMES is
|
239
|
+
# returned. The exception to this is when a NAMES
|
240
|
+
# message is sent with no parameters and all visible
|
241
|
+
# channels and contents are sent back in a series of
|
242
|
+
# RPL_NAMEREPLY messages with a RPL_ENDOFNAMES to mark
|
243
|
+
# the end.
|
244
|
+
|
198
245
|
# "( "=" / "*" / "@" ) <channel>
|
199
246
|
# :[ "@" / "+" ] <nick> *( " " [ "@" / "+" ] <nick> )
|
200
247
|
# - "@" is used for secret channels, "*" for private
|
201
248
|
# channels, and "=" for others (public channels).
|
202
249
|
#
|
203
|
-
|
250
|
+
RPL_NAMREPLY=353
|
251
|
+
|
204
252
|
# "<channel> :End of NAMES list"
|
205
|
-
|
206
|
-
|
207
|
-
#
|
208
|
-
#
|
209
|
-
#
|
210
|
-
|
211
|
-
# message is sent with no parameters and all visible
|
212
|
-
# channels and contents are sent back in a series of
|
213
|
-
# RPL_NAMEREPLY messages with a RPL_ENDOFNAMES to mark
|
214
|
-
# the end.
|
215
|
-
#
|
216
|
-
RPL_LINKS=364
|
253
|
+
RPL_ENDOFNAMES=366
|
254
|
+
|
255
|
+
# - In replying to the LINKS message, a server MUST send
|
256
|
+
# replies back using the RPL_LINKS numeric and mark the
|
257
|
+
# end of the list using an RPL_ENDOFLINKS reply.
|
258
|
+
|
217
259
|
# "<mask> <server> :<hopcount> <server info>"
|
218
|
-
|
260
|
+
RPL_LINKS=364
|
261
|
+
|
219
262
|
# "<mask> :End of LINKS list"
|
220
|
-
|
221
|
-
|
222
|
-
#
|
223
|
-
#
|
224
|
-
#
|
225
|
-
RPL_BANLIST
|
263
|
+
RPL_ENDOFLINKS=365
|
264
|
+
|
265
|
+
# - When listing the active 'bans' for a given channel,
|
266
|
+
# a server is required to send the list back using the
|
267
|
+
# RPL_BANLIST and RPL_ENDOFBANLIST messages. A separate
|
268
|
+
# RPL_BANLIST is sent for each active banmask. After the
|
269
|
+
# banmasks have been listed (or if none present) a
|
270
|
+
# RPL_ENDOFBANLIST MUST be sent.
|
271
|
+
|
226
272
|
# "<channel> <banmask>"
|
227
|
-
|
273
|
+
RPL_BANLIST=367
|
274
|
+
|
228
275
|
# "<channel> :End of channel ban list"
|
229
|
-
|
230
|
-
|
231
|
-
#
|
232
|
-
#
|
233
|
-
#
|
234
|
-
#
|
235
|
-
|
236
|
-
#
|
237
|
-
RPL_INFO=371
|
276
|
+
RPL_ENDOFBANLIST=368
|
277
|
+
|
278
|
+
# - A server responding to an INFO message is required to
|
279
|
+
# send all its 'info' in a series of RPL_INFO messages
|
280
|
+
# with a RPL_ENDOFINFO reply to indicate the end of the
|
281
|
+
# replies.
|
282
|
+
|
238
283
|
# ":<string>"
|
239
|
-
|
284
|
+
RPL_INFO=371
|
285
|
+
|
240
286
|
# ":End of INFO list"
|
241
|
-
|
242
|
-
|
243
|
-
# send all its 'info' in a series of RPL_INFO messages
|
244
|
-
# with a RPL_ENDOFINFO reply to indicate the end of the
|
245
|
-
# replies.
|
246
|
-
#
|
247
|
-
RPL_MOTDSTART=375
|
248
|
-
# ":- <server> Message of the day - "
|
249
|
-
RPL_MOTD=372
|
250
|
-
# ":- <text>"
|
251
|
-
RPL_ENDOFMOTD=376
|
252
|
-
# ":End of MOTD command"
|
253
|
-
#
|
287
|
+
RPL_ENDOFINFO=374
|
288
|
+
|
254
289
|
# - When responding to the MOTD message and the MOTD file
|
255
290
|
# is found, the file is displayed line by line, with
|
256
291
|
# each line no longer than 80 characters, using
|
257
292
|
# RPL_MOTD format replies. These MUST be surrounded
|
258
293
|
# by a RPL_MOTDSTART (before the RPL_MOTDs) and an
|
259
294
|
# RPL_ENDOFMOTD (after).
|
260
|
-
|
261
|
-
|
295
|
+
|
296
|
+
# ":- <server> Message of the day - "
|
297
|
+
RPL_MOTDSTART=375
|
298
|
+
|
299
|
+
# ":- <text>"
|
300
|
+
RPL_MOTD=372
|
301
|
+
|
302
|
+
# ":End of MOTD command"
|
303
|
+
RPL_ENDOFMOTD=376
|
304
|
+
|
262
305
|
# ":You are now an IRC operator"
|
263
306
|
#
|
264
307
|
# - RPL_YOUREOPER is sent back to a client which has
|
265
|
-
#
|
266
|
-
#
|
308
|
+
# just successfully issued an OPER message and gained
|
309
|
+
# operator status.
|
267
310
|
#
|
268
|
-
|
311
|
+
RPL_YOUREOPER=381
|
312
|
+
|
269
313
|
# "<config file> :Rehashing"
|
270
314
|
#
|
271
315
|
# - If the REHASH option is used and an operator sends
|
272
|
-
#
|
273
|
-
#
|
316
|
+
# a REHASH message, an RPL_REHASHING is sent back to
|
317
|
+
# the operator.
|
274
318
|
#
|
275
|
-
|
319
|
+
RPL_REHASHING=382
|
320
|
+
|
276
321
|
# "You are service <servicename>"
|
277
322
|
#
|
278
323
|
# - Sent by the server to a service upon successful
|
279
|
-
#
|
324
|
+
# registration.
|
280
325
|
#
|
281
|
-
|
326
|
+
RPL_YOURESERVICE=383
|
327
|
+
|
282
328
|
# "<server> :<string showing server's local time>"
|
283
329
|
#
|
284
330
|
# - When replying to the TIME message, a server MUST send
|
285
|
-
#
|
286
|
-
#
|
287
|
-
#
|
288
|
-
#
|
331
|
+
# the reply using the RPL_TIME format above. The string
|
332
|
+
# showing the time need only contain the correct day and
|
333
|
+
# time there. There is no further requirement for the
|
334
|
+
# time string.
|
289
335
|
#
|
290
|
-
|
336
|
+
RPL_TIME=391
|
337
|
+
|
338
|
+
# - If the USERS message is handled by a server, the
|
339
|
+
# replies RPL_USERSTART, RPL_USERS, RPL_ENDOFUSERS and
|
340
|
+
# RPL_NOUSERS are used. RPL_USERSSTART MUST be sent
|
341
|
+
# first, following by either a sequence of RPL_USERS
|
342
|
+
# or a single RPL_NOUSER. Following this is
|
343
|
+
# RPL_ENDOFUSERS.
|
344
|
+
|
291
345
|
# ":UserID Terminal Host"
|
292
|
-
|
346
|
+
RPL_USERSSTART=392
|
347
|
+
|
293
348
|
# ":<username> <ttyline> <hostname>"
|
294
|
-
|
349
|
+
RPL_USERS=393
|
350
|
+
|
295
351
|
# ":End of users"
|
296
|
-
|
352
|
+
RPL_ENDOFUSERS=394
|
353
|
+
|
297
354
|
# ":Nobody logged in"
|
355
|
+
RPL_NOUSERS=395
|
356
|
+
|
357
|
+
# - The RPL_TRACE* are all returned by the server in
|
358
|
+
# response to the TRACE message. How many are
|
359
|
+
# returned is dependent on the TRACE message and
|
360
|
+
# whether it was sent by an operator or not. There
|
361
|
+
# is no predefined order for which occurs first.
|
362
|
+
# Replies RPL_TRACEUNKNOWN, RPL_TRACECONNECTING and
|
363
|
+
# RPL_TRACEHANDSHAKE are all used for connections
|
364
|
+
# which have not been fully established and are either
|
365
|
+
# unknown, still attempting to connect or in the
|
366
|
+
# process of completing the 'server handshake'.
|
367
|
+
# RPL_TRACELINK is sent by any server which handles
|
368
|
+
# a TRACE message and has to pass it on to another
|
369
|
+
# server. The list of RPL_TRACELINKs sent in
|
370
|
+
# response to a TRACE command traversing the IRC
|
371
|
+
# network should reflect the actual connectivity of
|
372
|
+
# the servers themselves along that path.
|
298
373
|
#
|
299
|
-
#
|
300
|
-
#
|
301
|
-
#
|
302
|
-
#
|
303
|
-
|
304
|
-
# RPL_ENDOFUSERS.
|
305
|
-
#
|
306
|
-
RPL_TRACELINK=200
|
374
|
+
# RPL_TRACENEWTYPE is to be used for any connection
|
375
|
+
# which does not fit in the other categories but is
|
376
|
+
# being displayed anyway.
|
377
|
+
# RPL_TRACEEND is sent to indicate the end of the list.
|
378
|
+
|
307
379
|
# "Link <version & debug level> <destination>
|
308
380
|
# <next server> V<protocol version>
|
309
381
|
# <link uptime in seconds> <backstream sendq>
|
310
382
|
# <upstream sendq>"
|
311
|
-
|
383
|
+
RPL_TRACELINK=200
|
384
|
+
|
312
385
|
# "Try. <class> <server>"
|
313
|
-
|
386
|
+
RPL_TRACECONNECTING=201
|
387
|
+
|
314
388
|
# "H.S. <class> <server>"
|
315
|
-
|
389
|
+
RPL_TRACEHANDSHAKE=202
|
390
|
+
|
316
391
|
# "???? <class> [<client IP address in dot form>]"
|
317
|
-
|
392
|
+
RPL_TRACEUNKNOWN=203
|
393
|
+
|
318
394
|
# "Oper <class> <nick>"
|
319
|
-
|
395
|
+
RPL_TRACEOPERATOR=204
|
396
|
+
|
320
397
|
# "User <class> <nick>"
|
321
|
-
|
398
|
+
RPL_TRACEUSER=205
|
399
|
+
|
322
400
|
# "Serv <class> <int>S <int>C <server>
|
323
401
|
# <nick!user|*!*>@<host|server> V<protocol version>"
|
324
|
-
|
402
|
+
RPL_TRACESERVER=206
|
403
|
+
|
325
404
|
# "Service <class> <name> <type> <active type>"
|
326
|
-
|
405
|
+
RPL_TRACESERVICE=207
|
406
|
+
|
327
407
|
# "<newtype> 0 <client name>"
|
328
|
-
|
408
|
+
RPL_TRACENEWTYPE=208
|
409
|
+
|
329
410
|
# "Class <class> <count>"
|
330
|
-
|
411
|
+
RPL_TRACECLASS=209
|
412
|
+
|
331
413
|
# Unused.
|
332
|
-
|
414
|
+
RPL_TRACERECONNECT=210
|
415
|
+
|
333
416
|
# "File <logfile> <debug level>"
|
334
|
-
|
417
|
+
RPL_TRACELOG=261
|
418
|
+
|
335
419
|
# "<server name> <version & debug level> :End of TRACE"
|
336
|
-
|
337
|
-
|
338
|
-
# response to the TRACE message. How many are
|
339
|
-
# returned is dependent on the TRACE message and
|
340
|
-
# whether it was sent by an operator or not. There
|
341
|
-
# is no predefined order for which occurs first.
|
342
|
-
# Replies RPL_TRACEUNKNOWN, RPL_TRACECONNECTING and
|
343
|
-
# RPL_TRACEHANDSHAKE are all used for connections
|
344
|
-
# which have not been fully established and are either
|
345
|
-
# unknown, still attempting to connect or in the
|
346
|
-
# process of completing the 'server handshake'.
|
347
|
-
# RPL_TRACELINK is sent by any server which handles
|
348
|
-
# a TRACE message and has to pass it on to another
|
349
|
-
# server. The list of RPL_TRACELINKs sent in
|
350
|
-
# response to a TRACE command traversing the IRC
|
351
|
-
# network should reflect the actual connectivity of
|
352
|
-
# the servers themselves along that path.
|
353
|
-
#
|
354
|
-
# RPL_TRACENEWTYPE is to be used for any connection
|
355
|
-
# which does not fit in the other categories but is
|
356
|
-
# being displayed anyway.
|
357
|
-
# RPL_TRACEEND is sent to indicate the end of the list.
|
358
|
-
#
|
359
|
-
RPL_LOCALUSERS=265
|
420
|
+
RPL_TRACEEND=262
|
421
|
+
|
360
422
|
# ":Current local users: 3 Max: 4"
|
361
|
-
|
423
|
+
RPL_LOCALUSERS=265
|
424
|
+
|
362
425
|
# ":Current global users: 3 Max: 4"
|
363
|
-
|
426
|
+
RPL_GLOBALUSERS=266
|
427
|
+
|
364
428
|
# "::Highest connection count: 4 (4 clients) (251 since server was
|
365
429
|
# (re)started)"
|
366
|
-
|
430
|
+
RPL_STATSCONN=250
|
431
|
+
|
367
432
|
# "<linkname> <sendq> <sent messages>
|
368
433
|
# <sent Kbytes> <received messages>
|
369
434
|
# <received Kbytes> <time open>"
|
370
435
|
#
|
371
436
|
# - reports statistics on a connection. <linkname>
|
372
|
-
#
|
373
|
-
#
|
374
|
-
#
|
375
|
-
#
|
376
|
-
#
|
377
|
-
#
|
378
|
-
#
|
379
|
-
#
|
380
|
-
#
|
437
|
+
# identifies the particular connection, <sendq> is
|
438
|
+
# the amount of data that is queued and waiting to be
|
439
|
+
# sent <sent messages> the number of messages sent,
|
440
|
+
# and <sent Kbytes> the amount of data sent, in
|
441
|
+
# Kbytes. <received messages> and <received Kbytes>
|
442
|
+
# are the equivalent of <sent messages> and <sent
|
443
|
+
# Kbytes> for received data, respectively. <time
|
444
|
+
# open> indicates how long ago the connection was
|
445
|
+
# opened, in seconds.
|
381
446
|
#
|
382
|
-
|
447
|
+
RPL_STATSLINKINFO=211
|
448
|
+
|
383
449
|
# "<command> <count> <byte count> <remote count>"
|
384
450
|
#
|
385
451
|
# - reports statistics on commands usage.
|
386
452
|
#
|
387
|
-
|
453
|
+
RPL_STATSCOMMANDS=212
|
454
|
+
|
388
455
|
# "<stats letter> :End of STATS report"
|
389
456
|
#
|
390
|
-
|
457
|
+
RPL_ENDOFSTATS=219
|
458
|
+
|
391
459
|
# ":Server Up %d days %d:%02d:%02d"
|
392
460
|
#
|
393
461
|
# - reports the server uptime.
|
394
462
|
#
|
395
|
-
|
463
|
+
RPL_STATSUPTIME=242
|
464
|
+
|
396
465
|
# "O <hostmask> * <name>"
|
397
466
|
#
|
398
467
|
# - reports the allowed hosts from where user may become IRC
|
399
|
-
#
|
468
|
+
# operators.
|
400
469
|
#
|
401
|
-
|
470
|
+
RPL_STATSOLINE=243
|
471
|
+
|
402
472
|
# "<user mode string>"
|
403
473
|
#
|
404
474
|
# - To answer a query about a client's own mode,
|
405
|
-
#
|
475
|
+
# RPL_UMODEIS is sent back.
|
406
476
|
#
|
407
|
-
|
477
|
+
RPL_UMODEIS=221
|
478
|
+
|
479
|
+
# - When listing services in reply to a SERVLIST message,
|
480
|
+
# a server is required to send the list back using the
|
481
|
+
# RPL_SERVLIST and RPL_SERVLISTEND messages. A separate
|
482
|
+
# RPL_SERVLIST is sent for each service. After the
|
483
|
+
# services have been listed (or if none present) a
|
484
|
+
# RPL_SERVLISTEND MUST be sent.
|
485
|
+
|
408
486
|
# "<name> <server> <mask> <type> <hopcount> <info>"
|
409
|
-
|
410
|
-
|
487
|
+
RPL_SERVLIST=234
|
488
|
+
|
411
489
|
# "<mask> <type> :End of service listing"
|
412
|
-
|
413
|
-
|
414
|
-
#
|
415
|
-
#
|
416
|
-
#
|
417
|
-
#
|
418
|
-
#
|
419
|
-
#
|
420
|
-
|
490
|
+
RPL_SERVLISTEND=235
|
491
|
+
|
492
|
+
# - In processing an LUSERS message, the server
|
493
|
+
# sends a set of replies from RPL_LUSERCLIENT,
|
494
|
+
# RPL_LUSEROP, RPL_USERUNKNOWN,
|
495
|
+
# RPL_LUSERCHANNELS and RPL_LUSERME. When
|
496
|
+
# replying, a server MUST send back
|
497
|
+
# RPL_LUSERCLIENT and RPL_LUSERME. The other
|
498
|
+
# replies are only sent back if a non-zero count
|
499
|
+
# is found for them.
|
500
|
+
|
421
501
|
# ":There are <integer> users and <integer>
|
422
502
|
# services on <integer> servers"
|
423
|
-
|
503
|
+
RPL_LUSERCLIENT=251
|
504
|
+
|
424
505
|
# "<integer> :operator(s) online"
|
425
|
-
|
506
|
+
RPL_LUSEROP=252
|
507
|
+
|
426
508
|
# "<integer> :unknown connection(s)"
|
427
|
-
|
509
|
+
RPL_LUSERUNKNOWN=253
|
510
|
+
|
428
511
|
# "<integer> :channels formed"
|
512
|
+
RPL_LUSERCHANNELS=254
|
513
|
+
|
514
|
+
# ":I have <integer> clients and <integer> servers"
|
429
515
|
RPL_LUSERME=255
|
430
|
-
|
431
|
-
# servers"
|
432
|
-
#
|
433
|
-
# - In processing an LUSERS message, the server
|
434
|
-
# sends a set of replies from RPL_LUSERCLIENT,
|
435
|
-
# RPL_LUSEROP, RPL_USERUNKNOWN,
|
436
|
-
# RPL_LUSERCHANNELS and RPL_LUSERME. When
|
437
|
-
# replying, a server MUST send back
|
438
|
-
# RPL_LUSERCLIENT and RPL_LUSERME. The other
|
439
|
-
# replies are only sent back if a non-zero count
|
440
|
-
# is found for them.
|
441
|
-
#
|
442
|
-
RPL_ADMINME=256
|
443
|
-
# "<server> :Administrative info"
|
444
|
-
RPL_ADMINLOC1=257
|
445
|
-
# ":<admin info>"
|
446
|
-
RPL_ADMINLOC2=258
|
447
|
-
# ":<admin info>"
|
448
|
-
RPL_ADMINEMAIL=259
|
449
|
-
# ":<admin info>"
|
450
|
-
#
|
516
|
+
|
451
517
|
# - When replying to an ADMIN message, a server
|
452
518
|
# is expected to use replies RPL_ADMINME
|
453
519
|
# through to RPL_ADMINEMAIL and provide a text
|
@@ -458,323 +524,385 @@ module Irc
|
|
458
524
|
# and finally the administrative contact for the
|
459
525
|
# server (an email address here is REQUIRED)
|
460
526
|
# in RPL_ADMINEMAIL.
|
461
|
-
|
462
|
-
|
527
|
+
|
528
|
+
# "<server> :Administrative info"
|
529
|
+
RPL_ADMINME=256
|
530
|
+
|
531
|
+
# ":<admin info>"
|
532
|
+
RPL_ADMINLOC1=257
|
533
|
+
|
534
|
+
# ":<admin info>"
|
535
|
+
RPL_ADMINLOC2=258
|
536
|
+
|
537
|
+
# ":<admin info>"
|
538
|
+
RPL_ADMINEMAIL=259
|
539
|
+
|
463
540
|
# "<command> :Please wait a while and try again."
|
464
541
|
#
|
465
542
|
# - When a server drops a command without processing it,
|
466
|
-
#
|
467
|
-
#
|
468
|
-
|
543
|
+
# it MUST use the reply RPL_TRYAGAIN to inform the
|
544
|
+
# originating client.
|
545
|
+
RPL_TRYAGAIN=263
|
546
|
+
|
469
547
|
# 5.2 Error Replies
|
470
548
|
#
|
471
549
|
# Error replies are found in the range from 400 to 599.
|
472
|
-
|
473
|
-
ERR_NOSUCHNICK=401
|
550
|
+
|
474
551
|
# "<nickname> :No such nick/channel"
|
475
552
|
#
|
476
553
|
# - Used to indicate the nickname parameter supplied to a
|
477
|
-
#
|
554
|
+
# command is currently unused.
|
478
555
|
#
|
479
|
-
|
556
|
+
ERR_NOSUCHNICK=401
|
557
|
+
|
480
558
|
# "<server name> :No such server"
|
481
559
|
#
|
482
560
|
# - Used to indicate the server name given currently
|
483
|
-
#
|
561
|
+
# does not exist.
|
484
562
|
#
|
485
|
-
|
563
|
+
ERR_NOSUCHSERVER=402
|
564
|
+
|
486
565
|
# "<channel name> :No such channel"
|
487
566
|
#
|
488
567
|
# - Used to indicate the given channel name is invalid.
|
489
568
|
#
|
490
|
-
|
569
|
+
ERR_NOSUCHCHANNEL=403
|
570
|
+
|
491
571
|
# "<channel name> :Cannot send to channel"
|
492
572
|
#
|
493
573
|
# - Sent to a user who is either (a) not on a channel
|
494
|
-
#
|
495
|
-
#
|
496
|
-
#
|
497
|
-
#
|
574
|
+
# which is mode +n or (b) not a chanop (or mode +v) on
|
575
|
+
# a channel which has mode +m set or where the user is
|
576
|
+
# banned and is trying to send a PRIVMSG message to
|
577
|
+
# that channel.
|
498
578
|
#
|
499
|
-
|
579
|
+
ERR_CANNOTSENDTOCHAN=404
|
580
|
+
|
500
581
|
# "<channel name> :You have joined too many channels"
|
501
582
|
#
|
502
583
|
# - Sent to a user when they have joined the maximum
|
503
|
-
#
|
504
|
-
#
|
584
|
+
# number of allowed channels and they try to join
|
585
|
+
# another channel.
|
505
586
|
#
|
506
|
-
|
587
|
+
ERR_TOOMANYCHANNELS=405
|
588
|
+
|
507
589
|
# "<nickname> :There was no such nickname"
|
508
590
|
#
|
509
591
|
# - Returned by WHOWAS to indicate there is no history
|
510
|
-
#
|
592
|
+
# information for that nickname.
|
511
593
|
#
|
512
|
-
|
594
|
+
ERR_WASNOSUCHNICK=406
|
595
|
+
|
513
596
|
# "<target> :<error code> recipients. <abort message>"
|
514
597
|
#
|
515
598
|
# - Returned to a client which is attempting to send a
|
516
|
-
#
|
517
|
-
#
|
599
|
+
# PRIVMSG/NOTICE using the user@host destination format
|
600
|
+
# and for a user@host which has several occurrences.
|
518
601
|
#
|
519
602
|
# - Returned to a client which trying to send a
|
520
|
-
#
|
603
|
+
# PRIVMSG/NOTICE to too many recipients.
|
521
604
|
#
|
522
605
|
# - Returned to a client which is attempting to JOIN a safe
|
523
|
-
#
|
524
|
-
#
|
606
|
+
# channel using the shortname when there are more than one
|
607
|
+
# such channel.
|
525
608
|
#
|
526
|
-
|
609
|
+
ERR_TOOMANYTARGETS=407
|
610
|
+
|
527
611
|
# "<service name> :No such service"
|
528
612
|
#
|
529
613
|
# - Returned to a client which is attempting to send a SQUERY
|
530
|
-
#
|
614
|
+
# to a service which does not exist.
|
531
615
|
#
|
532
|
-
|
616
|
+
ERR_NOSUCHSERVICE=408
|
617
|
+
|
533
618
|
# ":No origin specified"
|
534
619
|
#
|
535
620
|
# - PING or PONG message missing the originator parameter.
|
536
621
|
#
|
537
|
-
|
622
|
+
ERR_NOORIGIN=409
|
623
|
+
|
538
624
|
# ":No recipient given (<command>)"
|
539
|
-
|
625
|
+
ERR_NORECIPIENT=411
|
626
|
+
|
627
|
+
# - 412 - 415 are returned by PRIVMSG to indicate that
|
628
|
+
# the message wasn't delivered for some reason.
|
629
|
+
# ERR_NOTOPLEVEL and ERR_WILDTOPLEVEL are errors that
|
630
|
+
# are returned when an invalid use of
|
631
|
+
# "PRIVMSG $<server>" or "PRIVMSG #<host>" is attempted.
|
632
|
+
|
540
633
|
# ":No text to send"
|
541
|
-
|
634
|
+
ERR_NOTEXTTOSEND=412
|
635
|
+
|
542
636
|
# "<mask> :No toplevel domain specified"
|
543
|
-
|
637
|
+
ERR_NOTOPLEVEL=413
|
638
|
+
|
544
639
|
# "<mask> :Wildcard in toplevel domain"
|
545
|
-
|
640
|
+
ERR_WILDTOPLEVEL=414
|
641
|
+
|
546
642
|
# "<mask> :Bad Server/host mask"
|
547
|
-
|
548
|
-
|
549
|
-
# the message wasn't delivered for some reason.
|
550
|
-
# ERR_NOTOPLEVEL and ERR_WILDTOPLEVEL are errors that
|
551
|
-
# are returned when an invalid use of
|
552
|
-
# "PRIVMSG $<server>" or "PRIVMSG #<host>" is attempted.
|
553
|
-
#
|
554
|
-
ERR_UNKNOWNCOMMAND=421
|
643
|
+
ERR_BADMASK=415
|
644
|
+
|
555
645
|
# "<command> :Unknown command"
|
556
646
|
#
|
557
647
|
# - Returned to a registered client to indicate that the
|
558
|
-
#
|
648
|
+
# command sent is unknown by the server.
|
559
649
|
#
|
560
|
-
|
650
|
+
ERR_UNKNOWNCOMMAND=421
|
651
|
+
|
561
652
|
# ":MOTD File is missing"
|
562
653
|
#
|
563
654
|
# - Server's MOTD file could not be opened by the server.
|
564
655
|
#
|
565
|
-
|
656
|
+
ERR_NOMOTD=422
|
657
|
+
|
566
658
|
# "<server> :No administrative info available"
|
567
659
|
#
|
568
660
|
# - Returned by a server in response to an ADMIN message
|
569
|
-
#
|
570
|
-
#
|
661
|
+
# when there is an error in finding the appropriate
|
662
|
+
# information.
|
571
663
|
#
|
572
|
-
|
664
|
+
ERR_NOADMININFO=423
|
665
|
+
|
573
666
|
# ":File error doing <file op> on <file>"
|
574
667
|
#
|
575
668
|
# - Generic error message used to report a failed file
|
576
|
-
#
|
669
|
+
# operation during the processing of a message.
|
577
670
|
#
|
578
|
-
|
671
|
+
ERR_FILEERROR=424
|
672
|
+
|
579
673
|
# ":No nickname given"
|
580
674
|
#
|
581
675
|
# - Returned when a nickname parameter expected for a
|
582
|
-
#
|
676
|
+
# command and isn't found.
|
583
677
|
#
|
584
|
-
|
678
|
+
ERR_NONICKNAMEGIVEN=431
|
679
|
+
|
585
680
|
# "<nick> :Erroneous nickname"
|
586
681
|
#
|
587
682
|
# - Returned after receiving a NICK message which contains
|
588
|
-
#
|
589
|
-
#
|
683
|
+
# characters which do not fall in the defined set. See
|
684
|
+
# section 2.3.1 for details on valid nicknames.
|
590
685
|
#
|
591
|
-
|
686
|
+
ERR_ERRONEUSNICKNAME=432
|
687
|
+
|
592
688
|
# "<nick> :Nickname is already in use"
|
593
689
|
#
|
594
690
|
# - Returned when a NICK message is processed that results
|
595
|
-
#
|
596
|
-
#
|
691
|
+
# in an attempt to change to a currently existing
|
692
|
+
# nickname.
|
597
693
|
#
|
598
|
-
|
694
|
+
ERR_NICKNAMEINUSE=433
|
695
|
+
|
599
696
|
# "<nick> :Nickname collision KILL from <user>@<host>"
|
600
697
|
#
|
601
698
|
# - Returned by a server to a client when it detects a
|
602
|
-
#
|
603
|
-
#
|
699
|
+
# nickname collision (registered of a NICK that
|
700
|
+
# already exists by another server).
|
604
701
|
#
|
605
|
-
|
702
|
+
ERR_NICKCOLLISION=436
|
703
|
+
|
606
704
|
# "<nick/channel> :Nick/channel is temporarily unavailable"
|
607
705
|
#
|
608
706
|
# - Returned by a server to a user trying to join a channel
|
609
|
-
#
|
707
|
+
# currently blocked by the channel delay mechanism.
|
610
708
|
#
|
611
709
|
# - Returned by a server to a user trying to change nickname
|
612
|
-
#
|
613
|
-
#
|
710
|
+
# when the desired nickname is blocked by the nick delay
|
711
|
+
# mechanism.
|
614
712
|
#
|
615
|
-
|
713
|
+
ERR_UNAVAILRESOURCE=437
|
714
|
+
|
616
715
|
# "<nick> <channel> :They aren't on that channel"
|
617
716
|
#
|
618
717
|
# - Returned by the server to indicate that the target
|
619
|
-
#
|
718
|
+
# user of the command is not on the given channel.
|
620
719
|
#
|
621
|
-
|
720
|
+
ERR_USERNOTINCHANNEL=441
|
721
|
+
|
622
722
|
# "<channel> :You're not on that channel"
|
623
723
|
#
|
624
724
|
# - Returned by the server whenever a client tries to
|
625
|
-
#
|
626
|
-
#
|
725
|
+
# perform a channel affecting command for which the
|
726
|
+
# client isn't a member.
|
627
727
|
#
|
628
|
-
|
728
|
+
ERR_NOTONCHANNEL=442
|
729
|
+
|
629
730
|
# "<user> <channel> :is already on channel"
|
630
731
|
#
|
631
732
|
# - Returned when a client tries to invite a user to a
|
632
|
-
#
|
733
|
+
# channel they are already on.
|
633
734
|
#
|
634
|
-
|
735
|
+
ERR_USERONCHANNEL=443
|
736
|
+
|
635
737
|
# "<user> :User not logged in"
|
636
738
|
#
|
637
739
|
# - Returned by the summon after a SUMMON command for a
|
638
|
-
#
|
639
|
-
#
|
740
|
+
# user was unable to be performed since they were not
|
741
|
+
# logged in.
|
640
742
|
#
|
641
|
-
|
642
|
-
|
743
|
+
ERR_NOLOGIN=444
|
744
|
+
|
643
745
|
# ":SUMMON has been disabled"
|
644
746
|
#
|
645
747
|
# - Returned as a response to the SUMMON command. MUST be
|
646
|
-
#
|
748
|
+
# returned by any server which doesn't implement it.
|
647
749
|
#
|
648
|
-
|
750
|
+
ERR_SUMMONDISABLED=445
|
751
|
+
|
649
752
|
# ":USERS has been disabled"
|
650
753
|
#
|
651
754
|
# - Returned as a response to the USERS command. MUST be
|
652
|
-
#
|
755
|
+
# returned by any server which does not implement it.
|
653
756
|
#
|
654
|
-
|
757
|
+
ERR_USERSDISABLED=446
|
758
|
+
|
655
759
|
# ":You have not registered"
|
656
760
|
#
|
657
761
|
# - Returned by the server to indicate that the client
|
658
|
-
#
|
659
|
-
#
|
762
|
+
# MUST be registered before the server will allow it
|
763
|
+
# to be parsed in detail.
|
660
764
|
#
|
661
|
-
|
765
|
+
ERR_NOTREGISTERED=451
|
766
|
+
|
662
767
|
# "<command> :Not enough parameters"
|
663
768
|
#
|
664
769
|
# - Returned by the server by numerous commands to
|
665
|
-
#
|
666
|
-
#
|
770
|
+
# indicate to the client that it didn't supply enough
|
771
|
+
# parameters.
|
667
772
|
#
|
668
|
-
|
773
|
+
ERR_NEEDMOREPARAMS=461
|
774
|
+
|
669
775
|
# ":Unauthorized command (already registered)"
|
670
776
|
#
|
671
777
|
# - Returned by the server to any link which tries to
|
672
|
-
#
|
673
|
-
#
|
778
|
+
# change part of the registered details (such as
|
779
|
+
# password or user details from second USER message).
|
674
780
|
#
|
675
|
-
|
781
|
+
ERR_ALREADYREGISTRED=462
|
782
|
+
|
676
783
|
# ":Your host isn't among the privileged"
|
677
784
|
#
|
678
785
|
# - Returned to a client which attempts to register with
|
679
|
-
#
|
680
|
-
#
|
681
|
-
#
|
786
|
+
# a server which does not been setup to allow
|
787
|
+
# connections from the host the attempted connection
|
788
|
+
# is tried.
|
682
789
|
#
|
683
|
-
|
790
|
+
ERR_NOPERMFORHOST=463
|
791
|
+
|
684
792
|
# ":Password incorrect"
|
685
793
|
#
|
686
794
|
# - Returned to indicate a failed attempt at registering
|
687
|
-
#
|
688
|
-
#
|
795
|
+
# a connection for which a password was required and
|
796
|
+
# was either not given or incorrect.
|
689
797
|
#
|
690
|
-
|
798
|
+
ERR_PASSWDMISMATCH=464
|
799
|
+
|
691
800
|
# ":You are banned from this server"
|
692
801
|
#
|
693
802
|
# - Returned after an attempt to connect and register
|
694
|
-
#
|
695
|
-
#
|
696
|
-
#
|
697
|
-
ERR_YOUWILLBEBANNED=466
|
803
|
+
# yourself with a server which has been setup to
|
804
|
+
# explicitly deny connections to you.
|
698
805
|
#
|
806
|
+
ERR_YOUREBANNEDCREEP=465
|
807
|
+
|
699
808
|
# - Sent by a server to a user to inform that access to the
|
700
|
-
#
|
809
|
+
# server will soon be denied.
|
701
810
|
#
|
702
|
-
|
811
|
+
ERR_YOUWILLBEBANNED=466
|
812
|
+
|
703
813
|
# "<channel> :Channel key already set"
|
704
|
-
|
814
|
+
ERR_KEYSET=467
|
815
|
+
|
705
816
|
# "<channel> :Cannot join channel (+l)"
|
706
|
-
|
817
|
+
ERR_CHANNELISFULL=471
|
818
|
+
|
707
819
|
# "<char> :is unknown mode char to me for <channel>"
|
708
|
-
|
820
|
+
ERR_UNKNOWNMODE=472
|
821
|
+
|
709
822
|
# "<channel> :Cannot join channel (+i)"
|
710
|
-
|
823
|
+
ERR_INVITEONLYCHAN=473
|
824
|
+
|
711
825
|
# "<channel> :Cannot join channel (+b)"
|
712
|
-
|
826
|
+
ERR_BANNEDFROMCHAN=474
|
827
|
+
|
713
828
|
# "<channel> :Cannot join channel (+k)"
|
714
|
-
|
829
|
+
ERR_BADCHANNELKEY=475
|
830
|
+
|
715
831
|
# "<channel> :Bad Channel Mask"
|
716
|
-
|
832
|
+
ERR_BADCHANMASK=476
|
833
|
+
|
717
834
|
# "<channel> :Channel doesn't support modes"
|
718
|
-
|
835
|
+
ERR_NOCHANMODES=477
|
836
|
+
|
719
837
|
# "<channel> <char> :Channel list is full"
|
720
838
|
#
|
721
|
-
|
839
|
+
ERR_BANLISTFULL=478
|
840
|
+
|
722
841
|
# ":Permission Denied- You're not an IRC operator"
|
723
842
|
#
|
724
843
|
# - Any command requiring operator privileges to operate
|
725
|
-
#
|
726
|
-
#
|
844
|
+
# MUST return this error to indicate the attempt was
|
845
|
+
# unsuccessful.
|
727
846
|
#
|
728
|
-
|
847
|
+
ERR_NOPRIVILEGES=481
|
848
|
+
|
729
849
|
# "<channel> :You're not channel operator"
|
730
850
|
#
|
731
851
|
# - Any command requiring 'chanop' privileges (such as
|
732
|
-
#
|
733
|
-
#
|
734
|
-
#
|
852
|
+
# MODE messages) MUST return this error if the client
|
853
|
+
# making the attempt is not a chanop on the specified
|
854
|
+
# channel.
|
735
855
|
#
|
736
856
|
#
|
737
|
-
|
857
|
+
ERR_CHANOPRIVSNEEDED=482
|
858
|
+
|
738
859
|
# ":You can't kill a server!"
|
739
860
|
#
|
740
861
|
# - Any attempts to use the KILL command on a server
|
741
|
-
#
|
742
|
-
#
|
862
|
+
# are to be refused and this error returned directly
|
863
|
+
# to the client.
|
743
864
|
#
|
744
|
-
|
865
|
+
ERR_CANTKILLSERVER=483
|
866
|
+
|
745
867
|
# ":Your connection is restricted!"
|
746
868
|
#
|
747
869
|
# - Sent by the server to a user upon connection to indicate
|
748
|
-
#
|
870
|
+
# the restricted nature of the connection (user mode "+r").
|
749
871
|
#
|
750
|
-
|
872
|
+
ERR_RESTRICTED=484
|
873
|
+
|
751
874
|
# ":You're not the original channel operator"
|
752
875
|
#
|
753
876
|
# - Any MODE requiring "channel creator" privileges MUST
|
754
|
-
#
|
755
|
-
#
|
877
|
+
# return this error if the client making the attempt is not
|
878
|
+
# a chanop on the specified channel.
|
756
879
|
#
|
757
|
-
|
880
|
+
ERR_UNIQOPPRIVSNEEDED=485
|
881
|
+
|
758
882
|
# ":No O-lines for your host"
|
759
883
|
#
|
760
884
|
# - If a client sends an OPER message and the server has
|
761
|
-
#
|
762
|
-
#
|
763
|
-
#
|
885
|
+
# not been configured to allow connections from the
|
886
|
+
# client's host as an operator, this error MUST be
|
887
|
+
# returned.
|
764
888
|
#
|
765
|
-
|
889
|
+
ERR_NOOPERHOST=491
|
890
|
+
|
766
891
|
# ":Unknown MODE flag"
|
767
892
|
#
|
768
893
|
# - Returned by the server to indicate that a MODE
|
769
|
-
#
|
770
|
-
#
|
894
|
+
# message was sent with a nickname parameter and that
|
895
|
+
# the a mode flag sent was not recognized.
|
771
896
|
#
|
772
|
-
|
897
|
+
ERR_UMODEUNKNOWNFLAG=501
|
898
|
+
|
773
899
|
# ":Cannot change mode for other users"
|
774
900
|
#
|
775
901
|
# - Error sent to any user trying to view or change the
|
776
|
-
#
|
902
|
+
# user mode for a user other than themselves.
|
777
903
|
#
|
904
|
+
ERR_USERSDONTMATCH=502
|
905
|
+
|
778
906
|
# 5.3 Reserved numerics
|
779
907
|
#
|
780
908
|
# These numerics are not described above since they fall into one of
|
@@ -785,7 +913,8 @@ module Irc
|
|
785
913
|
# 2. reserved for future planned use;
|
786
914
|
#
|
787
915
|
# 3. in current use but are part of a non-generic 'feature' of
|
788
|
-
#
|
916
|
+
# the current IRC server.
|
917
|
+
#
|
789
918
|
RPL_SERVICEINFO=231
|
790
919
|
RPL_ENDOFSERVICES=232
|
791
920
|
RPL_SERVICE=233
|
@@ -811,14 +940,33 @@ module Irc
|
|
811
940
|
ERR_NOSERVICEHOST=492
|
812
941
|
RPL_DATASTR=290
|
813
942
|
|
814
|
-
#
|
815
|
-
#
|
816
|
-
#
|
817
|
-
class
|
818
|
-
|
943
|
+
# Implements RFC 2812 and prior IRC RFCs.
|
944
|
+
#
|
945
|
+
# Clients should register Proc{}s to handle the various server events, and
|
946
|
+
# the Client class will handle dispatch.
|
947
|
+
class Client
|
948
|
+
|
949
|
+
# the Server we're connected to
|
950
|
+
attr_reader :server
|
951
|
+
# the User representing us on that server
|
952
|
+
attr_reader :user
|
953
|
+
|
954
|
+
# Create a new Client instance
|
819
955
|
def initialize
|
956
|
+
@server = Server.new # The Server
|
957
|
+
@user = @server.user("*!*@*") # The User representing the client on this Server
|
958
|
+
|
820
959
|
@handlers = Hash.new
|
821
|
-
|
960
|
+
|
961
|
+
# This is used by some messages to build lists of users that
|
962
|
+
# will be delegated when the ENDOF... message is received
|
963
|
+
@tmpusers = []
|
964
|
+
end
|
965
|
+
|
966
|
+
# Clear the server and reset the user
|
967
|
+
def reset
|
968
|
+
@server.clear
|
969
|
+
@user = @server.user("*!*@*")
|
822
970
|
end
|
823
971
|
|
824
972
|
# key:: server event to handle
|
@@ -827,8 +975,13 @@ module Irc
|
|
827
975
|
#
|
828
976
|
# ==server events currently supported:
|
829
977
|
#
|
830
|
-
#
|
978
|
+
# TODO handle errors ERR_NOSUCHNICK, ERR_NOSUCHCHANNEL
|
979
|
+
# TODO handle errors ERR_CHANOPRIVSNEEDED, ERR_CANNOTSENDTOCHAN
|
980
|
+
#
|
981
|
+
# welcome:: server welcome message on connect
|
831
982
|
# yourhost:: your host details (on connection)
|
983
|
+
# created:: when the server was started
|
984
|
+
# isupport:: information about what this server supports
|
832
985
|
# ping:: server pings you (default handler returns a pong)
|
833
986
|
# nicktaken:: you tried to change nick to one that's in use
|
834
987
|
# badnick:: you tried to change nick to one that's invalid
|
@@ -836,7 +989,6 @@ module Irc
|
|
836
989
|
# topicinfo:: on joining a channel or asking for the topic, tells you
|
837
990
|
# who set it and when
|
838
991
|
# names:: server sends list of channel members when you join
|
839
|
-
# welcome:: server welcome message on connect
|
840
992
|
# motd:: server message of the day
|
841
993
|
# privmsg:: privmsg, the core of IRC, a message to you from someone
|
842
994
|
# public:: optionally instead of getting privmsg you can hook to only
|
@@ -869,17 +1021,35 @@ module Irc
|
|
869
1021
|
data = Hash.new
|
870
1022
|
data[:serverstring] = serverstring
|
871
1023
|
|
872
|
-
unless serverstring =~ /^(:(\S+)\s)?(\S+)(\s(.*))
|
873
|
-
raise "Unparseable Server Message!!!: #{serverstring}"
|
1024
|
+
unless serverstring.chomp =~ /^(:(\S+)\s)?(\S+)(\s(.*))?$/
|
1025
|
+
raise "Unparseable Server Message!!!: #{serverstring.inspect}"
|
874
1026
|
end
|
875
1027
|
|
876
1028
|
prefix, command, params = $2, $3, $5
|
877
1029
|
|
878
1030
|
if prefix != nil
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
1031
|
+
# Most servers will send a full nick!user@host prefix for
|
1032
|
+
# messages from users. Therefore, when the prefix doesn't match this
|
1033
|
+
# syntax it's usually the server hostname.
|
1034
|
+
#
|
1035
|
+
# This is not always true, though, since some servers do not send a
|
1036
|
+
# full hostmask for user messages.
|
1037
|
+
#
|
1038
|
+
if prefix =~ /^#{Regexp::Irc::BANG_AT}$/
|
1039
|
+
data[:source] = @server.user(prefix)
|
1040
|
+
else
|
1041
|
+
if @server.hostname
|
1042
|
+
if @server.hostname != prefix
|
1043
|
+
# TODO do we want to be able to differentiate messages that are passed on to us from /other/ servers?
|
1044
|
+
debug "Origin #{prefix} for message\n\t#{serverstring.inspect}\nis neither a user hostmask nor the server hostname\nI'll pretend that it's from the server anyway"
|
1045
|
+
data[:source] = @server
|
1046
|
+
else
|
1047
|
+
data[:source] = @server
|
1048
|
+
end
|
1049
|
+
else
|
1050
|
+
@server.instance_variable_set(:@hostname, prefix)
|
1051
|
+
data[:source] = @server
|
1052
|
+
end
|
883
1053
|
end
|
884
1054
|
end
|
885
1055
|
|
@@ -887,19 +1057,36 @@ module Irc
|
|
887
1057
|
argv = []
|
888
1058
|
params.scan(/(?!:)(\S+)|:(.*)/) { argv << ($1 || $2) } if params
|
889
1059
|
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
1060
|
+
if command =~ /^(\d+)$/ # Numeric replies
|
1061
|
+
data[:target] = argv[0]
|
1062
|
+
# A numeric reply /should/ be directed at the client, except when we're connecting with a used nick, in which case
|
1063
|
+
# it's directed at '*'
|
1064
|
+
not_us = !([@user.nick, '*'].include?(data[:target]))
|
1065
|
+
if not_us
|
1066
|
+
warning "Server reply #{serverstring.inspect} directed at #{data[:target]} instead of client (#{@user.nick})"
|
1067
|
+
end
|
1068
|
+
|
898
1069
|
num=command.to_i
|
899
1070
|
case num
|
1071
|
+
when RPL_WELCOME
|
1072
|
+
data[:message] = argv[1]
|
1073
|
+
# "Welcome to the Internet Relay Network
|
1074
|
+
# <nick>!<user>@<host>"
|
1075
|
+
if not_us
|
1076
|
+
warning "Server thinks client (#{@user.inspect}) has a different nick"
|
1077
|
+
@user.nick = data[:target]
|
1078
|
+
end
|
1079
|
+
if data[:message] =~ /([^@!\s]+)(?:!([^@!\s]+?))?@(\S+)/
|
1080
|
+
nick = $1
|
1081
|
+
user = $2
|
1082
|
+
host = $3
|
1083
|
+
warning "Welcome message nick mismatch (#{nick} vs #{data[:target]})" if nick != data[:target]
|
1084
|
+
@user.user = user if user
|
1085
|
+
@user.host = host if host
|
1086
|
+
end
|
1087
|
+
handle(:welcome, data)
|
900
1088
|
when RPL_YOURHOST
|
901
1089
|
# "Your host is <servername>, running version <ver>"
|
902
|
-
# TODO how standard is this "version <ver>? should i parse it?
|
903
1090
|
data[:message] = argv[1]
|
904
1091
|
handle(:yourhost, data)
|
905
1092
|
when RPL_CREATED
|
@@ -909,10 +1096,21 @@ module Irc
|
|
909
1096
|
when RPL_MYINFO
|
910
1097
|
# "<servername> <version> <available user modes>
|
911
1098
|
# <available channel modes>"
|
912
|
-
|
913
|
-
data[:
|
914
|
-
data[:
|
915
|
-
data[:
|
1099
|
+
@server.parse_my_info(params.split(' ', 2).last)
|
1100
|
+
data[:servername] = @server.hostname
|
1101
|
+
data[:version] = @server.version
|
1102
|
+
data[:usermodes] = @server.usermodes
|
1103
|
+
data[:chanmodes] = @server.chanmodes
|
1104
|
+
handle(:myinfo, data)
|
1105
|
+
when RPL_ISUPPORT
|
1106
|
+
# "PREFIX=(ov)@+ CHANTYPES=#& :are supported by this server"
|
1107
|
+
# "MODES=4 CHANLIMIT=#:20 NICKLEN=16 USERLEN=10 HOSTLEN=63
|
1108
|
+
# TOPICLEN=450 KICKLEN=450 CHANNELLEN=30 KEYLEN=23 CHANTYPES=#
|
1109
|
+
# PREFIX=(ov)@+ CASEMAPPING=ascii CAPAB IRCD=dancer :are available
|
1110
|
+
# on this server"
|
1111
|
+
#
|
1112
|
+
@server.parse_isupport(argv[1..-2].join(' '))
|
1113
|
+
handle(:isupport, data)
|
916
1114
|
when ERR_NICKNAMEINUSE
|
917
1115
|
# "* <nick> :Nickname is already in use"
|
918
1116
|
data[:nick] = argv[1]
|
@@ -924,49 +1122,65 @@ module Irc
|
|
924
1122
|
data[:message] = argv[2]
|
925
1123
|
handle(:badnick, data)
|
926
1124
|
when RPL_TOPIC
|
927
|
-
data[:channel] = argv[1]
|
1125
|
+
data[:channel] = @server.channel(argv[1])
|
928
1126
|
data[:topic] = argv[2]
|
1127
|
+
data[:channel].topic.text = data[:topic]
|
1128
|
+
|
929
1129
|
handle(:topic, data)
|
930
1130
|
when RPL_TOPIC_INFO
|
931
|
-
data[:nick] = argv[0]
|
932
|
-
data[:channel] = argv[1]
|
933
|
-
|
934
|
-
|
1131
|
+
data[:nick] = @server.user(argv[0])
|
1132
|
+
data[:channel] = @server.channel(argv[1])
|
1133
|
+
|
1134
|
+
# This must not be an IRC::User because it might not be an actual User,
|
1135
|
+
# and we risk overwriting valid User data
|
1136
|
+
data[:source] = argv[2].to_irc_netmask(:server => @server)
|
1137
|
+
|
1138
|
+
data[:time] = Time.at(argv[3].to_i)
|
1139
|
+
|
1140
|
+
data[:channel].topic.set_by = data[:source]
|
1141
|
+
data[:channel].topic.set_on = data[:time]
|
1142
|
+
|
935
1143
|
handle(:topicinfo, data)
|
936
1144
|
when RPL_NAMREPLY
|
937
1145
|
# "( "=" / "*" / "@" ) <channel>
|
938
1146
|
# :[ "@" / "+" ] <nick> *( " " [ "@" / "+" ] <nick> )
|
939
1147
|
# - "@" is used for secret channels, "*" for private
|
940
1148
|
# channels, and "=" for others (public channels).
|
1149
|
+
data[:channeltype] = argv[1]
|
1150
|
+
data[:channel] = argv[2]
|
1151
|
+
|
1152
|
+
chan = @server.get_channel(data[:channel])
|
1153
|
+
unless chan
|
1154
|
+
warning "Received names #{data[:topic].inspect} for channel #{data[:channel].inspect} I was not on"
|
1155
|
+
return
|
1156
|
+
end
|
1157
|
+
|
1158
|
+
users = []
|
941
1159
|
argv[3].scan(/\S+/).each { |u|
|
942
|
-
|
943
|
-
|
1160
|
+
# FIXME beware of servers that allow multiple prefixes
|
1161
|
+
if(u =~ /^([#{@server.supports[:prefix][:prefixes].join}])?(.*)$/)
|
1162
|
+
umode = $1
|
944
1163
|
user = $2
|
945
|
-
|
1164
|
+
users << [user, umode]
|
946
1165
|
end
|
947
1166
|
}
|
1167
|
+
|
1168
|
+
users.each { |ar|
|
1169
|
+
u = @server.user(ar[0])
|
1170
|
+
chan.add_user(u, :silent => true)
|
1171
|
+
debug "Adding user #{u}"
|
1172
|
+
if ar[1]
|
1173
|
+
ms = @server.mode_for_prefix(ar[1].to_sym)
|
1174
|
+
debug "\twith mode #{ar[1]} (#{ms})"
|
1175
|
+
chan.mode[ms].set(u)
|
1176
|
+
end
|
1177
|
+
}
|
1178
|
+
@tmpusers += users
|
948
1179
|
when RPL_ENDOFNAMES
|
949
1180
|
data[:channel] = argv[1]
|
950
|
-
data[:users] = @
|
1181
|
+
data[:users] = @tmpusers
|
951
1182
|
handle(:names, data)
|
952
|
-
@
|
953
|
-
when RPL_ISUPPORT
|
954
|
-
# "PREFIX=(ov)@+ CHANTYPES=#& :are supported by this server"
|
955
|
-
# "MODES=4 CHANLIMIT=#:20 NICKLEN=16 USERLEN=10 HOSTLEN=63
|
956
|
-
# TOPICLEN=450 KICKLEN=450 CHANNELLEN=30 KEYLEN=23 CHANTYPES=#
|
957
|
-
# PREFIX=(ov)@+ CASEMAPPING=ascii CAPAB IRCD=dancer :are available
|
958
|
-
# on this server"
|
959
|
-
#
|
960
|
-
argv[0,argv.length-1].each {|a|
|
961
|
-
if a =~ /^(.*)=(.*)$/
|
962
|
-
data[$1.downcase.to_sym] = $2
|
963
|
-
debug "server's #{$1.downcase.to_sym} is #{$2}"
|
964
|
-
else
|
965
|
-
data[a.downcase.to_sym] = true
|
966
|
-
debug "server supports #{a.downcase.to_sym}"
|
967
|
-
end
|
968
|
-
}
|
969
|
-
handle(:isupport, data)
|
1183
|
+
@tmpusers = Array.new
|
970
1184
|
when RPL_LUSERCLIENT
|
971
1185
|
# ":There are <integer> users and <integer>
|
972
1186
|
# services on <integer> servers"
|
@@ -1005,28 +1219,14 @@ module Irc
|
|
1005
1219
|
# (re)started)"
|
1006
1220
|
data[:message] = argv[1]
|
1007
1221
|
handle(:statsconn, data)
|
1008
|
-
when RPL_WELCOME
|
1009
|
-
# "Welcome to the Internet Relay Network
|
1010
|
-
# <nick>!<user>@<host>"
|
1011
|
-
case argv[1]
|
1012
|
-
when /((\S+)!(\S+))/
|
1013
|
-
data[:netmask] = $1
|
1014
|
-
data[:nick] = $2
|
1015
|
-
data[:address] = $3
|
1016
|
-
when /Welcome to the Internet Relay Network\s(\S+)/
|
1017
|
-
data[:nick] = $1
|
1018
|
-
when /Welcome.*\s+(\S+)$/
|
1019
|
-
data[:nick] = $1
|
1020
|
-
when /^(\S+)$/
|
1021
|
-
data[:nick] = $1
|
1022
|
-
end
|
1023
|
-
handle(:welcome, data)
|
1024
1222
|
when RPL_MOTDSTART
|
1025
1223
|
# "<nick> :- <server> Message of the Day -"
|
1026
1224
|
if argv[1] =~ /^-\s+(\S+)\s/
|
1027
1225
|
server = $1
|
1028
|
-
|
1226
|
+
else
|
1227
|
+
warning "Server doesn't have an RFC compliant MOTD start."
|
1029
1228
|
end
|
1229
|
+
@motd = ""
|
1030
1230
|
when RPL_MOTD
|
1031
1231
|
if(argv[1] =~ /^-\s+(.*)$/)
|
1032
1232
|
@motd << $1
|
@@ -1038,65 +1238,168 @@ module Irc
|
|
1038
1238
|
when RPL_DATASTR
|
1039
1239
|
data[:text] = argv[1]
|
1040
1240
|
handle(:datastr, data)
|
1241
|
+
when RPL_WHOREPLY
|
1242
|
+
data[:channel] = argv[1]
|
1243
|
+
data[:user] = argv[2]
|
1244
|
+
data[:host] = argv[3]
|
1245
|
+
data[:userserver] = argv[4]
|
1246
|
+
data[:nick] = argv[5]
|
1247
|
+
if argv[6] =~ /^(H|G)(\*)?(.*)?$/
|
1248
|
+
data[:away] = ($1 == 'G')
|
1249
|
+
data[:ircop] = $2
|
1250
|
+
data[:modes] = $3.scan(/./).map { |mode|
|
1251
|
+
m = @server.supports[:prefix][:prefixes].index(mode.to_sym)
|
1252
|
+
@server.supports[:prefix][:modes][m]
|
1253
|
+
} rescue []
|
1254
|
+
else
|
1255
|
+
warning "Strange WHO reply: #{serverstring.inspect}"
|
1256
|
+
end
|
1257
|
+
data[:hopcount], data[:real_name] = argv[7].split(" ", 2)
|
1258
|
+
|
1259
|
+
user = @server.get_user(data[:nick])
|
1260
|
+
|
1261
|
+
user.user = data[:user]
|
1262
|
+
user.host = data[:host]
|
1263
|
+
user.away = data[:away] # FIXME doesn't provide the actual message
|
1264
|
+
# TODO ircop status
|
1265
|
+
# TODO userserver
|
1266
|
+
# TODO hopcount
|
1267
|
+
user.real_name = data[:real_name]
|
1268
|
+
|
1269
|
+
channel = @server.get_channel(data[:channel])
|
1270
|
+
|
1271
|
+
channel.add_user(user, :silent=>true)
|
1272
|
+
data[:modes].map { |mode|
|
1273
|
+
channel.mode[mode].set(user)
|
1274
|
+
}
|
1275
|
+
|
1276
|
+
handle(:who, data)
|
1277
|
+
when RPL_ENDOFWHO
|
1278
|
+
handle(:eowho, data)
|
1279
|
+
when RPL_CHANNELMODEIS
|
1280
|
+
parse_mode(serverstring, argv[1..-1], data)
|
1281
|
+
handle(:mode, data)
|
1041
1282
|
else
|
1283
|
+
warning "Unknown message #{serverstring.inspect}"
|
1042
1284
|
handle(:unknown, data)
|
1043
1285
|
end
|
1044
|
-
|
1045
|
-
|
1286
|
+
return # We've processed the numeric reply
|
1287
|
+
end
|
1288
|
+
|
1289
|
+
# Otherwise, the command should be a single word
|
1290
|
+
case command.to_sym
|
1291
|
+
when :PING
|
1292
|
+
data[:pingid] = argv[0]
|
1293
|
+
handle(:ping, data)
|
1294
|
+
when :PONG
|
1295
|
+
data[:pingid] = argv[0]
|
1296
|
+
handle(:pong, data)
|
1297
|
+
when :PRIVMSG
|
1046
1298
|
# you can either bind to 'PRIVMSG', to get every one and
|
1047
1299
|
# parse it yourself, or you can bind to 'MSG', 'PUBLIC',
|
1048
1300
|
# etc and get it all nicely split up for you.
|
1049
|
-
|
1301
|
+
|
1302
|
+
begin
|
1303
|
+
data[:target] = @server.user_or_channel(argv[0])
|
1304
|
+
rescue
|
1305
|
+
# The previous may fail e.g. when the target is a server or something
|
1306
|
+
# like that (e.g. $<mask>). In any of these cases, we just use the
|
1307
|
+
# String as a target
|
1308
|
+
# FIXME we probably want to explicitly check for the #<mask> $<mask>
|
1309
|
+
data[:target] = argv[0]
|
1310
|
+
end
|
1050
1311
|
data[:message] = argv[1]
|
1051
1312
|
handle(:privmsg, data)
|
1052
1313
|
|
1053
1314
|
# Now we split it
|
1054
|
-
if
|
1315
|
+
if data[:target].kind_of?(Channel)
|
1055
1316
|
handle(:public, data)
|
1056
1317
|
else
|
1057
1318
|
handle(:msg, data)
|
1058
1319
|
end
|
1059
|
-
when
|
1060
|
-
|
1061
|
-
|
1320
|
+
when :NOTICE
|
1321
|
+
begin
|
1322
|
+
data[:target] = @server.user_or_channel(argv[0])
|
1323
|
+
rescue
|
1324
|
+
# The previous may fail e.g. when the target is a server or something
|
1325
|
+
# like that (e.g. $<mask>). In any of these cases, we just use the
|
1326
|
+
# String as a target
|
1327
|
+
# FIXME we probably want to explicitly check for the #<mask> $<mask>
|
1328
|
+
data[:target] = argv[0]
|
1329
|
+
end
|
1330
|
+
data[:message] = argv[1]
|
1331
|
+
case data[:source]
|
1332
|
+
when User
|
1333
|
+
handle(:notice, data)
|
1334
|
+
else
|
1335
|
+
# "server notice" (not from user, noone to reply to)
|
1336
|
+
handle(:snotice, data)
|
1337
|
+
end
|
1338
|
+
when :KICK
|
1339
|
+
data[:channel] = @server.channel(argv[0])
|
1340
|
+
data[:target] = @server.user(argv[1])
|
1062
1341
|
data[:message] = argv[2]
|
1342
|
+
|
1343
|
+
@server.delete_user_from_channel(data[:target], data[:channel])
|
1344
|
+
if data[:target] == @user
|
1345
|
+
@server.delete_channel(data[:channel])
|
1346
|
+
end
|
1347
|
+
|
1063
1348
|
handle(:kick, data)
|
1064
|
-
when
|
1065
|
-
data[:channel] = argv[0]
|
1349
|
+
when :PART
|
1350
|
+
data[:channel] = @server.channel(argv[0])
|
1066
1351
|
data[:message] = argv[1]
|
1352
|
+
|
1353
|
+
@server.delete_user_from_channel(data[:source], data[:channel])
|
1354
|
+
if data[:source] == @user
|
1355
|
+
@server.delete_channel(data[:channel])
|
1356
|
+
end
|
1357
|
+
|
1067
1358
|
handle(:part, data)
|
1068
|
-
when
|
1359
|
+
when :QUIT
|
1069
1360
|
data[:message] = argv[0]
|
1361
|
+
data[:was_on] = @server.channels.inject(ChannelList.new) { |list, ch|
|
1362
|
+
list << ch if ch.has_user?(data[:source])
|
1363
|
+
list
|
1364
|
+
}
|
1365
|
+
|
1366
|
+
@server.delete_user(data[:source])
|
1367
|
+
|
1070
1368
|
handle(:quit, data)
|
1071
|
-
when
|
1072
|
-
data[:channel] = argv[0]
|
1369
|
+
when :JOIN
|
1370
|
+
data[:channel] = @server.channel(argv[0])
|
1371
|
+
data[:channel].add_user(data[:source])
|
1372
|
+
|
1073
1373
|
handle(:join, data)
|
1074
|
-
when
|
1075
|
-
data[:channel] = argv[0]
|
1076
|
-
data[:topic] = argv[1]
|
1374
|
+
when :TOPIC
|
1375
|
+
data[:channel] = @server.channel(argv[0])
|
1376
|
+
data[:topic] = Channel::Topic.new(argv[1], data[:source], Time.new)
|
1377
|
+
data[:channel].topic.replace(data[:topic])
|
1378
|
+
|
1077
1379
|
handle(:changetopic, data)
|
1078
|
-
when
|
1079
|
-
data[:target] = argv[0]
|
1080
|
-
data[:channel] = argv[1]
|
1380
|
+
when :INVITE
|
1381
|
+
data[:target] = @server.user(argv[0])
|
1382
|
+
data[:channel] = @server.channel(argv[1])
|
1383
|
+
|
1081
1384
|
handle(:invite, data)
|
1082
|
-
when
|
1083
|
-
data[:
|
1385
|
+
when :NICK
|
1386
|
+
data[:is_on] = @server.channels.inject(ChannelList.new) { |list, ch|
|
1387
|
+
list << ch if ch.has_user?(data[:source])
|
1388
|
+
list
|
1389
|
+
}
|
1390
|
+
|
1391
|
+
data[:newnick] = argv[0]
|
1392
|
+
data[:oldnick] = data[:source].nick.dup
|
1393
|
+
data[:source].nick = data[:newnick]
|
1394
|
+
|
1395
|
+
debug "#{data[:oldnick]} (now #{data[:newnick]}) was on #{data[:is_on].join(', ')}"
|
1396
|
+
|
1084
1397
|
handle(:nick, data)
|
1085
|
-
when
|
1086
|
-
|
1087
|
-
data[:modestring] = argv[1]
|
1088
|
-
data[:targets] = argv[2]
|
1398
|
+
when :MODE
|
1399
|
+
parse_mode(serverstring, argv, data)
|
1089
1400
|
handle(:mode, data)
|
1090
|
-
when 'NOTICE'
|
1091
|
-
data[:target] = argv[0]
|
1092
|
-
data[:message] = argv[1]
|
1093
|
-
if data[:sourcenick]
|
1094
|
-
handle(:notice, data)
|
1095
|
-
else
|
1096
|
-
# "server notice" (not from user, noone to reply to
|
1097
|
-
handle(:snotice, data)
|
1098
|
-
end
|
1099
1401
|
else
|
1402
|
+
warning "Unknown message #{serverstring.inspect}"
|
1100
1403
|
handle(:unknown, data)
|
1101
1404
|
end
|
1102
1405
|
end
|
@@ -1111,5 +1414,110 @@ module Irc
|
|
1111
1414
|
@handlers[key].call(data)
|
1112
1415
|
end
|
1113
1416
|
end
|
1417
|
+
|
1418
|
+
# RPL_CHANNELMODEIS
|
1419
|
+
# MODE ([+-]<modes> (<params>)*)*
|
1420
|
+
# When a MODE message is received by a server,
|
1421
|
+
# Type C will have parameters too, so we must
|
1422
|
+
# be able to consume parameters for all
|
1423
|
+
# but Type D modes
|
1424
|
+
def parse_mode(serverstring, argv, data)
|
1425
|
+
data[:target] = @server.user_or_channel(argv[0])
|
1426
|
+
data[:modestring] = argv[1..-1].join(" ")
|
1427
|
+
# data[:modes] is an array where each element
|
1428
|
+
# is an array with two elements, the first of which
|
1429
|
+
# is either :set or :reset, and the second symbol
|
1430
|
+
# is the mode letter. An optional third element
|
1431
|
+
# is present e.g. for channel modes that need
|
1432
|
+
# a parameter
|
1433
|
+
data[:modes] = []
|
1434
|
+
case data[:target]
|
1435
|
+
when User
|
1436
|
+
# User modes aren't currently handled internally,
|
1437
|
+
# but we still parse them and delegate to the client
|
1438
|
+
warning "Unhandled user mode message '#{serverstring}'"
|
1439
|
+
argv[1..-1].each { |arg|
|
1440
|
+
setting = arg[0].chr
|
1441
|
+
if "+-".include?(setting)
|
1442
|
+
setting = setting == "+" ? :set : :reset
|
1443
|
+
arg[1..-1].each_byte { |b|
|
1444
|
+
m = b.chr.intern
|
1445
|
+
data[:modes] << [setting, m]
|
1446
|
+
}
|
1447
|
+
else
|
1448
|
+
# Although typically User modes don't take an argument,
|
1449
|
+
# this is not true for all modes on all servers. Since
|
1450
|
+
# we have no knowledge of which modes take parameters
|
1451
|
+
# and which don't we just assign it to the last
|
1452
|
+
# mode. This is not going to do strange things often,
|
1453
|
+
# as usually User modes are only set one at a time
|
1454
|
+
warning "Unhandled user mode parameter #{arg} found"
|
1455
|
+
data[:modes].last << arg
|
1456
|
+
end
|
1457
|
+
}
|
1458
|
+
else
|
1459
|
+
# array of indices in data[:modes] where parameters
|
1460
|
+
# are needed
|
1461
|
+
who_wants_params = []
|
1462
|
+
|
1463
|
+
modes = argv[1..-1].dup
|
1464
|
+
debug modes
|
1465
|
+
getting_args = false
|
1466
|
+
while arg = modes.shift
|
1467
|
+
debug arg
|
1468
|
+
if getting_args
|
1469
|
+
# getting args for previously set modes
|
1470
|
+
idx = who_wants_params.shift
|
1471
|
+
if idx.nil?
|
1472
|
+
warning "Oops, problems parsing #{serverstring.inspect}"
|
1473
|
+
break
|
1474
|
+
end
|
1475
|
+
data[:modes][idx] << arg
|
1476
|
+
getting_args = false if who_wants_params.empty?
|
1477
|
+
else
|
1478
|
+
debug @server.supports[:chanmodes]
|
1479
|
+
setting = :set
|
1480
|
+
arg.each_byte do |c|
|
1481
|
+
m = c.chr.intern
|
1482
|
+
case m
|
1483
|
+
when :+
|
1484
|
+
setting = :set
|
1485
|
+
when :-
|
1486
|
+
setting = :reset
|
1487
|
+
else
|
1488
|
+
data[:modes] << [setting, m]
|
1489
|
+
case m
|
1490
|
+
when *@server.supports[:chanmodes][:typea]
|
1491
|
+
who_wants_params << data[:modes].length - 1
|
1492
|
+
when *@server.supports[:chanmodes][:typeb]
|
1493
|
+
who_wants_params << data[:modes].length - 1
|
1494
|
+
when *@server.supports[:chanmodes][:typec]
|
1495
|
+
if setting == :set
|
1496
|
+
who_wants_params << data[:modes].length - 1
|
1497
|
+
end
|
1498
|
+
when *@server.supports[:chanmodes][:typed]
|
1499
|
+
# Nothing to do
|
1500
|
+
when *@server.supports[:prefix][:modes]
|
1501
|
+
who_wants_params << data[:modes].length - 1
|
1502
|
+
else
|
1503
|
+
warning "Ignoring unknown mode #{m} in #{serverstring.inspect}"
|
1504
|
+
data[:modes].pop
|
1505
|
+
end
|
1506
|
+
end
|
1507
|
+
end
|
1508
|
+
getting_args = true unless who_wants_params.empty?
|
1509
|
+
end
|
1510
|
+
end
|
1511
|
+
|
1512
|
+
data[:modes].each { |mode|
|
1513
|
+
set, key, val = mode
|
1514
|
+
if val
|
1515
|
+
data[:target].mode[key].send(set, val)
|
1516
|
+
else
|
1517
|
+
data[:target].mode[key].send(set)
|
1518
|
+
end
|
1519
|
+
}
|
1520
|
+
end
|
1521
|
+
end
|
1114
1522
|
end
|
1115
1523
|
end
|