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/data/rbot/plugins/tube.rb
CHANGED
@@ -1,62 +1,50 @@
|
|
1
1
|
#Tube Status Enquiry plugin for rbot
|
2
2
|
#Plugin by Colm Linehan
|
3
3
|
|
4
|
-
require 'rexml/document'
|
5
|
-
require 'uri/common'
|
6
|
-
|
7
4
|
class TubePlugin < Plugin
|
8
|
-
include REXML
|
9
5
|
def help(plugin, topic="")
|
10
|
-
"tube [district|circle|metropolitan|central|jubilee|bakerloo|
|
6
|
+
"tube [district|circle|metropolitan|central|jubilee|bakerloo|waterlooandcity|hammersmithandcity|victoria|eastlondon|northern|piccadilly] => display tube service status for the specified line(Docklands Light Railway is not currently supported)" # , tube stations => list tube stations (not lines) with problems"
|
11
7
|
end
|
12
8
|
|
13
9
|
def tube(m, params)
|
14
10
|
line = params[:line]
|
15
|
-
|
16
|
-
tube_page
|
17
|
-
|
18
|
-
|
19
|
-
return
|
20
|
-
end
|
21
|
-
unless tube_page
|
22
|
-
m.reply "Cannot contact Tube Service Status page"
|
23
|
-
return
|
24
|
-
end
|
25
|
-
next_line = false
|
26
|
-
tube_page.each_line {|l|
|
27
|
-
next if l == "\r\n"
|
28
|
-
next if l == "\n"
|
29
|
-
if (next_line)
|
30
|
-
if (l =~ /^<tr valign=top> <td>\s*(.*)<\/td><\/tr>/i)
|
31
|
-
m.reply $1.split(/<[^>]+>| /i).join(" ")
|
32
|
-
return
|
33
|
-
else
|
34
|
-
m.reply "There are problems on the #{line} line, but I didn't understand the page format. You should check out http://www.tfl.gov.uk/tfl/service_rt_tube.shtml for more details."
|
35
|
-
return
|
36
|
-
end
|
11
|
+
tube_page = @bot.httputil.get('http://www.tfl.gov.uk/tfl/livetravelnews/realtime/tube/default.html')
|
12
|
+
unless tube_page
|
13
|
+
m.reply "Cannot contact Tube Service Status page"
|
14
|
+
return
|
37
15
|
end
|
38
|
-
next_line =
|
16
|
+
next_line = false
|
17
|
+
tube_page.each_line {|l|
|
18
|
+
next if l == "\r\n"
|
19
|
+
next if l == "\n"
|
20
|
+
if (next_line)
|
21
|
+
if (l =~ /^<p>\s*(.*)<\/p>/i)
|
22
|
+
m.reply $1.split(/<[^>]+>| /i).join(" ")
|
23
|
+
return
|
24
|
+
elsif l =~ /ul|h3|"message"/
|
25
|
+
next
|
26
|
+
else
|
27
|
+
m.reply "There are problems on the #{line} line, but I didn't understand the page format. You should check out http://www.tfl.gov.uk/tfl/livetravelnews/realtime/tube/default.html for more details."
|
28
|
+
return
|
29
|
+
end
|
30
|
+
end
|
31
|
+
next_line = true if (l =~ /li class="#{line}"/i)
|
39
32
|
}
|
40
|
-
|
33
|
+
m.reply "No Problems on the #{line} line."
|
41
34
|
end
|
42
35
|
|
43
36
|
def check_stations(m, params)
|
44
|
-
|
45
|
-
tube_page = @bot.httputil.get(URI.parse("http://www.tfl.gov.uk/tfl/service_rt_tube.shtml"))
|
46
|
-
rescue URI::InvalidURIError, URI::BadURIError => e
|
47
|
-
m.reply "Cannot contact Tube Service Status page"
|
48
|
-
return
|
49
|
-
end
|
37
|
+
tube_page = @bot.httputil.get('http://www.tfl.gov.uk/tfl/service_rt_tube.shtml')
|
50
38
|
unless tube_page
|
51
39
|
m.reply "Cannot contact Tube Service Status page"
|
52
40
|
return
|
53
41
|
end
|
54
42
|
stations_array = Array.new
|
55
43
|
tube_page.each_line {|l|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
44
|
+
if (l =~ /<tr valign=top> <td valign="middle" class="Station"><b>(.*)<\/b><\/td><\/tr>\s*/i)
|
45
|
+
stations_array.push $1
|
46
|
+
end
|
47
|
+
}
|
60
48
|
if stations_array.empty?
|
61
49
|
m.reply "There are no station-specific announcements"
|
62
50
|
return
|
@@ -67,5 +55,5 @@ class TubePlugin < Plugin
|
|
67
55
|
end
|
68
56
|
end
|
69
57
|
plugin = TubePlugin.new
|
70
|
-
plugin.map 'tube stations', :action => 'check_stations'
|
58
|
+
# plugin.map 'tube stations', :action => 'check_stations'
|
71
59
|
plugin.map 'tube :line'
|
@@ -0,0 +1,187 @@
|
|
1
|
+
#-- vim:sw=2:et
|
2
|
+
#++
|
3
|
+
#
|
4
|
+
# :title: Twitter Status Update for rbot
|
5
|
+
#
|
6
|
+
# Author:: Carter Parks (carterparks) <carter@carterparks.com>
|
7
|
+
# Author:: Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com>
|
8
|
+
#
|
9
|
+
# Copyright:: (C) 2007 Carter Parks
|
10
|
+
# Copyright:: (C) 2007 Giuseppe Bilotta
|
11
|
+
#
|
12
|
+
# Users can setup their twitter username and password and then begin updating
|
13
|
+
# twitter whenever
|
14
|
+
|
15
|
+
require 'rexml/rexml'
|
16
|
+
require 'cgi'
|
17
|
+
|
18
|
+
class TwitterPlugin < Plugin
|
19
|
+
Config.register Config::IntegerValue.new('twitter.status_count',
|
20
|
+
:default => 1, :validate => Proc.new { |v| v > 0 && v <= 10},
|
21
|
+
:desc => "Maximum number of status updates shown by 'twitter status'")
|
22
|
+
Config.register Config::IntegerValue.new('twitter.friends_status_count',
|
23
|
+
:default => 3, :validate => Proc.new { |v| v > 0 && v <= 10},
|
24
|
+
:desc => "Maximum number of status updates shown by 'twitter friends status'")
|
25
|
+
|
26
|
+
def initialize
|
27
|
+
super
|
28
|
+
|
29
|
+
class << @registry
|
30
|
+
def store(val)
|
31
|
+
val
|
32
|
+
end
|
33
|
+
def restore(val)
|
34
|
+
val
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
@header = {
|
39
|
+
'X-Twitter-Client' => 'rbot twitter plugin'
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
# return a help string when the bot is asked for help on this plugin
|
44
|
+
def help(plugin, topic="")
|
45
|
+
return "twitter status [nick] => show nick's (or your) status, use 'twitter friends status [nick]' to also show the friends' timeline | twitter update [status] => updates your status on twitter | twitter identify [username] [password] => ties your nick to your twitter username and password | twitter actions [on|off] => enable/disable twitting of actions (/me does ...)"
|
46
|
+
end
|
47
|
+
|
48
|
+
# update the status on twitter
|
49
|
+
def get_status(m, params)
|
50
|
+
|
51
|
+
nick = params[:nick] || @registry[m.sourcenick + "_username"]
|
52
|
+
|
53
|
+
if not nick
|
54
|
+
m.reply "you should specify the username of the twitter touse, or identify using 'twitter identify [username] [password]'"
|
55
|
+
return false
|
56
|
+
end
|
57
|
+
|
58
|
+
user = URI.escape(nick)
|
59
|
+
|
60
|
+
count = @bot.config['twitter.status_count']
|
61
|
+
unless params[:friends]
|
62
|
+
uri = "http://twitter.com/statuses/user_timeline/#{user}.xml?count=#{count}"
|
63
|
+
else
|
64
|
+
count = @bot.config['twitter.friends_status_count']
|
65
|
+
uri = "http://twitter.com/statuses/friends_timeline/#{user}.xml"
|
66
|
+
end
|
67
|
+
|
68
|
+
response = @bot.httputil.get(uri, :headers => @header, :cache => false)
|
69
|
+
debug response
|
70
|
+
|
71
|
+
texts = []
|
72
|
+
|
73
|
+
if response
|
74
|
+
begin
|
75
|
+
rex = REXML::Document.new(response)
|
76
|
+
rex.root.elements.each("status") { |st|
|
77
|
+
# month, day, hour, min, sec, year = st.elements['created_at'].text.match(/\w+ (\w+) (\d+) (\d+):(\d+):(\d+) \S+ (\d+)/)[1..6]
|
78
|
+
# debug [year, month, day, hour, min, sec].inspect
|
79
|
+
# time = Time.local(year.to_i, month, day.to_i, hour.to_i, min.to_i, sec.to_i)
|
80
|
+
time = Time.parse(st.elements['created_at'].text)
|
81
|
+
now = Time.now
|
82
|
+
# Sometimes, time can be in the future; invert the relation in this case
|
83
|
+
delta = ((time > now) ? time - now : now - time)
|
84
|
+
msg = st.elements['text'].to_s + " (#{Utils.secs_to_string(delta.to_i)} ago via #{st.elements['source'].to_s})"
|
85
|
+
author = ""
|
86
|
+
if params[:friends]
|
87
|
+
author = Utils.decode_html_entities(st.elements['user'].elements['name'].text) + ": " rescue ""
|
88
|
+
end
|
89
|
+
texts << author+Utils.decode_html_entities(msg).ircify_html
|
90
|
+
}
|
91
|
+
if params[:friends]
|
92
|
+
# friends always return the latest 20 updates, so we clip the count
|
93
|
+
texts[count..-1]=nil
|
94
|
+
end
|
95
|
+
rescue
|
96
|
+
error $!
|
97
|
+
m.reply "could not parse status for #{nick}"
|
98
|
+
return false
|
99
|
+
end
|
100
|
+
m.reply texts.reverse.join("\n")
|
101
|
+
return true
|
102
|
+
else
|
103
|
+
m.reply "could not get status for #{nick}"
|
104
|
+
return false
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# update the status on twitter
|
109
|
+
def update_status(m, params)
|
110
|
+
|
111
|
+
|
112
|
+
unless @registry.has_key?(m.sourcenick + "_password") && @registry.has_key?(m.sourcenick + "_username")
|
113
|
+
m.reply "you must identify using 'twitter identify [username] [password]'"
|
114
|
+
return false
|
115
|
+
end
|
116
|
+
|
117
|
+
user = URI.escape(@registry[m.sourcenick + "_username"])
|
118
|
+
pass = URI.escape(@registry[m.sourcenick + "_password"])
|
119
|
+
uri = "http://#{user}:#{pass}@twitter.com/statuses/update.xml"
|
120
|
+
|
121
|
+
msg = params[:status].to_s
|
122
|
+
|
123
|
+
if msg.length > 160
|
124
|
+
m.reply "your status message update is too long, please keep it under 140 characters if possible, 160 characters maximum"
|
125
|
+
return
|
126
|
+
end
|
127
|
+
|
128
|
+
if msg.length > 140
|
129
|
+
m.reply "your status message is longer than 140 characters, which is not optimal, but I'm going to update anyway"
|
130
|
+
end
|
131
|
+
|
132
|
+
source = "source=rbot"
|
133
|
+
msg = "status=#{CGI.escape(msg)}"
|
134
|
+
body = [source,msg].join("&")
|
135
|
+
|
136
|
+
response = @bot.httputil.post(uri, body, :headers => @header)
|
137
|
+
debug response
|
138
|
+
|
139
|
+
reply_method = params[:notify] ? :notify : :reply
|
140
|
+
if response.class == Net::HTTPOK
|
141
|
+
m.__send__(reply_method, "status updated")
|
142
|
+
else
|
143
|
+
m.__send__(reply_method, "could not update status")
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# ties a nickname to a twitter username and password
|
148
|
+
def identify(m, params)
|
149
|
+
@registry[m.sourcenick + "_username"] = params[:username].to_s
|
150
|
+
@registry[m.sourcenick + "_password"] = params[:password].to_s
|
151
|
+
m.reply "you're all setup!"
|
152
|
+
end
|
153
|
+
|
154
|
+
# update on ACTION if the user has enabled the option
|
155
|
+
def ctcp_listen(m)
|
156
|
+
return unless m.action?
|
157
|
+
return unless @registry[m.sourcenick + "_actions"]
|
158
|
+
update_status(m, :status => m.message, :notify => true)
|
159
|
+
end
|
160
|
+
|
161
|
+
# show or toggle action twitting
|
162
|
+
def actions(m, params)
|
163
|
+
case params[:toggle]
|
164
|
+
when 'on'
|
165
|
+
@registry[m.sourcenick + "_actions"] = true
|
166
|
+
m.okay
|
167
|
+
when 'off'
|
168
|
+
@registry.delete(m.sourcenick + "_actions")
|
169
|
+
m.okay
|
170
|
+
else
|
171
|
+
if @registry[m.sourcenick + "_actions"]
|
172
|
+
m.reply _("actions will be twitted")
|
173
|
+
else
|
174
|
+
m.reply _("actions will not be twitted")
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
# create an instance of our plugin class and register for the "length" command
|
181
|
+
plugin = TwitterPlugin.new
|
182
|
+
plugin.map 'twitter identify :username :password', :action => "identify", :public => false
|
183
|
+
plugin.map 'twitter update *status', :action => "update_status", :threaded => true
|
184
|
+
plugin.map 'twitter status [:nick]', :action => "get_status", :threaded => true
|
185
|
+
plugin.map 'twitter actions [:toggle]', :action => "actions", :requirements => { :toggle => /^on|off$/ }
|
186
|
+
plugin.map 'twitter :friends [status] [:nick]', :action => "get_status", :requirements => { :friends => /^friends?$/ }, :threaded => true
|
187
|
+
|
data/data/rbot/plugins/urban.rb
CHANGED
@@ -1,71 +1,80 @@
|
|
1
|
-
require 'cgi'
|
2
|
-
begin
|
3
|
-
require 'rubyful_soup'
|
4
|
-
rescue
|
5
|
-
warning "could not load rubyful_soup, urban dictionary disabled"
|
6
|
-
warning "please get it from http://www.crummy.com/software/RubyfulSoup/"
|
7
|
-
warning "or install it via gem"
|
8
|
-
return
|
9
|
-
end
|
10
|
-
require 'uri/common'
|
11
|
-
|
12
1
|
class UrbanPlugin < Plugin
|
2
|
+
URBAN = 'http://www.urbandictionary.com/define.php?term='
|
13
3
|
|
14
4
|
def help( plugin, topic="")
|
15
|
-
"urban [word] [n]
|
5
|
+
"urban [word] [n]: give the [n]th definition of [word] from urbandictionary.com. urbanday: give the word-of-the-day at urban"
|
16
6
|
end
|
17
7
|
|
18
|
-
def
|
8
|
+
def format_definition(total, num, word, desc, ex)
|
9
|
+
"#{Bold}#{word} (#{num}/#{total})#{Bold}: " +
|
10
|
+
desc.ircify_html(:limit => 300) + " " +
|
11
|
+
"<i>#{ex}</i>".ircify_html(:limit => 100)
|
12
|
+
end
|
19
13
|
|
20
|
-
|
21
|
-
|
22
|
-
|
14
|
+
def get_def(m, word, n = nil)
|
15
|
+
n = n ? n.to_i : 1
|
16
|
+
p = (n-1)/7 + 1
|
17
|
+
u = URBAN + URI.escape(word)
|
18
|
+
u += '&page=' + p.to_s if p > 1
|
19
|
+
s = @bot.httputil.get(u)
|
20
|
+
return m.reply "Couldn't get the urban dictionary definition for #{word}" if s.nil?
|
21
|
+
|
22
|
+
notfound = s.match %r{<div style="color: #669FCE"><i>.*?</i> isn't defined}
|
23
|
+
|
24
|
+
numpages = s[%r{<div id='paginator'>.*?</div>}m].scan(/\d+/).collect {|x| x.to_i}.max || 1
|
25
|
+
|
26
|
+
rv = Array.new
|
27
|
+
s.scan(%r{<td class='index'[^>]*>.*?(\d+)\..*?</td>.*?<td class='word'>(?:<a.*?>)?([^>]+)(?:</a>)?</td>.*?<div class='definition'>(.+?)</div>.*?<div class='example'>(.+?)</div>}m) do |num, wrd, desc, ex|
|
28
|
+
rv << [num.to_i, wrd.strip, desc.strip, ex.strip]
|
23
29
|
end
|
24
30
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
query = m.params.chomp( paramArray.last )
|
33
|
-
query.rstrip!
|
34
|
-
else
|
35
|
-
query = m.params
|
36
|
-
end
|
37
|
-
uri = URI.parse( "http://www.urbandictionary.com/define.php?term=#{ URI.escape query}" )
|
31
|
+
maxnum = rv.collect {|x| x[0]}.max || 0
|
32
|
+
return m.reply("#{Bold}#{word}#{Bold} not found") if rv.empty?
|
33
|
+
|
34
|
+
if notfound
|
35
|
+
suggestions = rv.map { |s| Underline + s[1] + Underline }.uniq.join ', '
|
36
|
+
m.reply "#{Bold}#{word}#{Bold} not found. maybe you mean #{suggestions}?"
|
37
|
+
return
|
38
38
|
end
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
40
|
+
answer = rv.find { |a| a[0] == n }
|
41
|
+
answer ||= (n > maxnum ? rv.last : rv.first)
|
42
|
+
m.reply format_definition((p == numpages ? maxnum : "#{(numpages-1)*7 + 1}+"), *answer)
|
43
|
+
end
|
44
|
+
|
45
|
+
def urban(m, params)
|
46
|
+
words = params[:words].to_s
|
47
|
+
if words.empty?
|
48
|
+
resp = @bot.httputil.head('http://www.urbandictionary.com/random.php',
|
49
|
+
:max_redir => -1,
|
50
|
+
:cache => false)
|
51
|
+
return m.reply "Couldn't get a random urban dictionary word" if resp.nil?
|
52
|
+
if resp.code == "302" && (loc = resp['location'])
|
53
|
+
words = URI.unescape(loc.match(/define.php\?term=(.*)$/)[1]) rescue nil
|
51
54
|
end
|
52
|
-
else
|
53
|
-
m.reply "#{m.params} not found."
|
54
55
|
end
|
55
|
-
|
56
|
+
get_def(m, words, params[:n])
|
56
57
|
end
|
57
58
|
|
58
|
-
def
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
59
|
+
def uotd(m, params)
|
60
|
+
home = @bot.httputil.get("http://www.urbandictionary.com/daily.php")
|
61
|
+
if home.nil?
|
62
|
+
m.reply "Couldn't get the urban dictionary word of the day"
|
63
|
+
return
|
64
|
+
end
|
65
|
+
home.match(%r{href="/define.php\?term=.*?">(.*?)<})
|
66
|
+
wotd = $1
|
67
|
+
debug "Urban word of the day: #{wotd}"
|
68
|
+
if !wotd
|
69
|
+
m.reply "Couldn't get the urban dictionary word of the day"
|
70
|
+
return
|
71
|
+
end
|
72
|
+
get_def(m, wotd, 1)
|
67
73
|
end
|
68
74
|
end
|
69
75
|
|
70
76
|
plugin = UrbanPlugin.new
|
71
|
-
plugin.
|
77
|
+
plugin.map "urban *words :n", :requirements => { :n => /^-?\d+$/ }, :action => 'urban'
|
78
|
+
plugin.map "urban [*words]", :action => 'urban'
|
79
|
+
plugin.map "urbanday", :action => 'uotd'
|
80
|
+
|
data/data/rbot/plugins/url.rb
CHANGED
@@ -1,434 +1,218 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
UNESCAPE_TABLE = {
|
9
|
-
'raquo' => '>>',
|
10
|
-
'quot' => '"',
|
11
|
-
'micro' => 'u',
|
12
|
-
'copy' => '(c)',
|
13
|
-
'trade' => '(tm)',
|
14
|
-
'reg' => '(R)',
|
15
|
-
'#174' => '(R)',
|
16
|
-
'#8220' => '"',
|
17
|
-
'#8221' => '"',
|
18
|
-
'#8212' => '--',
|
19
|
-
'#39' => '\'',
|
20
|
-
=begin
|
21
|
-
# extras codes, for future use...
|
22
|
-
'zwnj' => '‌',
|
23
|
-
'aring' => '\xe5',
|
24
|
-
'gt' => '>',
|
25
|
-
'yen' => '\xa5',
|
26
|
-
'ograve' => '\xf2',
|
27
|
-
'Chi' => 'Χ',
|
28
|
-
'bull' => '•',
|
29
|
-
'Egrave' => '\xc8',
|
30
|
-
'Ntilde' => '\xd1',
|
31
|
-
'upsih' => 'ϒ',
|
32
|
-
'Yacute' => '\xdd',
|
33
|
-
'asymp' => '≈',
|
34
|
-
'radic' => '√',
|
35
|
-
'otimes' => '⊗',
|
36
|
-
'nabla' => '∇',
|
37
|
-
'aelig' => '\xe6',
|
38
|
-
'oelig' => 'œ',
|
39
|
-
'equiv' => '≡',
|
40
|
-
'Psi' => 'Ψ',
|
41
|
-
'auml' => '\xe4',
|
42
|
-
'circ' => 'ˆ',
|
43
|
-
'Acirc' => '\xc2',
|
44
|
-
'Epsilon' => 'Ε',
|
45
|
-
'Yuml' => 'Ÿ',
|
46
|
-
'Eta' => 'Η',
|
47
|
-
'lt' => '<',
|
48
|
-
'Icirc' => '\xce',
|
49
|
-
'Upsilon' => 'Υ',
|
50
|
-
'ndash' => '–',
|
51
|
-
'there4' => '∴',
|
52
|
-
'Prime' => '″',
|
53
|
-
'prime' => '′',
|
54
|
-
'psi' => 'ψ',
|
55
|
-
'Kappa' => 'Κ',
|
56
|
-
'rsaquo' => '›',
|
57
|
-
'Tau' => 'Τ',
|
58
|
-
'darr' => '↓',
|
59
|
-
'ocirc' => '\xf4',
|
60
|
-
'lrm' => '‎',
|
61
|
-
'zwj' => '‍',
|
62
|
-
'cedil' => '\xb8',
|
63
|
-
'Ecirc' => '\xca',
|
64
|
-
'not' => '\xac',
|
65
|
-
'amp' => '&',
|
66
|
-
'AElig' => '\xc6',
|
67
|
-
'oslash' => '\xf8',
|
68
|
-
'acute' => '\xb4',
|
69
|
-
'lceil' => '⌈',
|
70
|
-
'laquo' => '\xab',
|
71
|
-
'shy' => '\xad',
|
72
|
-
'rdquo' => '”',
|
73
|
-
'ge' => '≥',
|
74
|
-
'Igrave' => '\xcc',
|
75
|
-
'Ograve' => '\xd2',
|
76
|
-
'euro' => '€',
|
77
|
-
'dArr' => '⇓',
|
78
|
-
'sdot' => '⋅',
|
79
|
-
'nbsp' => '\xa0',
|
80
|
-
'lfloor' => '⌊',
|
81
|
-
'lArr' => '⇐',
|
82
|
-
'Auml' => '\xc4',
|
83
|
-
'larr' => '←',
|
84
|
-
'Atilde' => '\xc3',
|
85
|
-
'Otilde' => '\xd5',
|
86
|
-
'szlig' => '\xdf',
|
87
|
-
'clubs' => '♣',
|
88
|
-
'diams' => '♦',
|
89
|
-
'agrave' => '\xe0',
|
90
|
-
'Ocirc' => '\xd4',
|
91
|
-
'Iota' => 'Ι',
|
92
|
-
'Theta' => 'Θ',
|
93
|
-
'Pi' => 'Π',
|
94
|
-
'OElig' => 'Œ',
|
95
|
-
'Scaron' => 'Š',
|
96
|
-
'frac14' => '\xbc',
|
97
|
-
'egrave' => '\xe8',
|
98
|
-
'sub' => '⊂',
|
99
|
-
'iexcl' => '\xa1',
|
100
|
-
'frac12' => '\xbd',
|
101
|
-
'sbquo' => '‚',
|
102
|
-
'ordf' => '\xaa',
|
103
|
-
'sum' => '∑',
|
104
|
-
'prop' => '∝',
|
105
|
-
'Uuml' => '\xdc',
|
106
|
-
'ntilde' => '\xf1',
|
107
|
-
'sup' => '⊃',
|
108
|
-
'theta' => 'θ',
|
109
|
-
'prod' => '∏',
|
110
|
-
'nsub' => '⊄',
|
111
|
-
'hArr' => '⇔',
|
112
|
-
'rlm' => '‏',
|
113
|
-
'THORN' => '\xde',
|
114
|
-
'infin' => '∞',
|
115
|
-
'yuml' => '\xff',
|
116
|
-
'Mu' => 'Μ',
|
117
|
-
'le' => '≤',
|
118
|
-
'Eacute' => '\xc9',
|
119
|
-
'thinsp' => ' ',
|
120
|
-
'ecirc' => '\xea',
|
121
|
-
'bdquo' => '„',
|
122
|
-
'Sigma' => 'Σ',
|
123
|
-
'fnof' => 'ƒ',
|
124
|
-
'Aring' => '\xc5',
|
125
|
-
'tilde' => '˜',
|
126
|
-
'frac34' => '\xbe',
|
127
|
-
'emsp' => ' ',
|
128
|
-
'mdash' => '—',
|
129
|
-
'uarr' => '↑',
|
130
|
-
'permil' => '‰',
|
131
|
-
'Ugrave' => '\xd9',
|
132
|
-
'rarr' => '→',
|
133
|
-
'Agrave' => '\xc0',
|
134
|
-
'chi' => 'χ',
|
135
|
-
'forall' => '∀',
|
136
|
-
'eth' => '\xf0',
|
137
|
-
'rceil' => '⌉',
|
138
|
-
'iuml' => '\xef',
|
139
|
-
'gamma' => 'γ',
|
140
|
-
'lambda' => 'λ',
|
141
|
-
'harr' => '↔',
|
142
|
-
'rang' => '〉',
|
143
|
-
'xi' => 'ξ',
|
144
|
-
'dagger' => '†',
|
145
|
-
'divide' => '\xf7',
|
146
|
-
'Ouml' => '\xd6',
|
147
|
-
'image' => 'ℑ',
|
148
|
-
'alefsym' => 'ℵ',
|
149
|
-
'igrave' => '\xec',
|
150
|
-
'otilde' => '\xf5',
|
151
|
-
'Oacute' => '\xd3',
|
152
|
-
'sube' => '⊆',
|
153
|
-
'alpha' => 'α',
|
154
|
-
'frasl' => '⁄',
|
155
|
-
'ETH' => '\xd0',
|
156
|
-
'lowast' => '∗',
|
157
|
-
'Nu' => 'Ν',
|
158
|
-
'plusmn' => '\xb1',
|
159
|
-
'Euml' => '\xcb',
|
160
|
-
'real' => 'ℜ',
|
161
|
-
'sup1' => '\xb9',
|
162
|
-
'sup2' => '\xb2',
|
163
|
-
'sup3' => '\xb3',
|
164
|
-
'Oslash' => '\xd8',
|
165
|
-
'Aacute' => '\xc1',
|
166
|
-
'cent' => '\xa2',
|
167
|
-
'oline' => '‾',
|
168
|
-
'Beta' => 'Β',
|
169
|
-
'perp' => '⊥',
|
170
|
-
'Delta' => 'Δ',
|
171
|
-
'loz' => '◊',
|
172
|
-
'pi' => 'π',
|
173
|
-
'iota' => 'ι',
|
174
|
-
'empty' => '∅',
|
175
|
-
'euml' => '\xeb',
|
176
|
-
'brvbar' => '\xa6',
|
177
|
-
'iacute' => '\xed',
|
178
|
-
'para' => '\xb6',
|
179
|
-
'micro' => '\xb5',
|
180
|
-
'cup' => '∪',
|
181
|
-
'weierp' => '℘',
|
182
|
-
'uuml' => '\xfc',
|
183
|
-
'part' => '∂',
|
184
|
-
'icirc' => '\xee',
|
185
|
-
'delta' => 'δ',
|
186
|
-
'omicron' => 'ο',
|
187
|
-
'upsilon' => 'υ',
|
188
|
-
'Iuml' => '\xcf',
|
189
|
-
'Lambda' => 'Λ',
|
190
|
-
'Xi' => 'Ξ',
|
191
|
-
'kappa' => 'κ',
|
192
|
-
'ccedil' => '\xe7',
|
193
|
-
'Ucirc' => '\xdb',
|
194
|
-
'cap' => '∩',
|
195
|
-
'mu' => 'μ',
|
196
|
-
'scaron' => 'š',
|
197
|
-
'lsquo' => '‘',
|
198
|
-
'isin' => '∈',
|
199
|
-
'Zeta' => 'Ζ',
|
200
|
-
'supe' => '⊇',
|
201
|
-
'deg' => '\xb0',
|
202
|
-
'and' => '∧',
|
203
|
-
'tau' => 'τ',
|
204
|
-
'pound' => '\xa3',
|
205
|
-
'hellip' => '…',
|
206
|
-
'curren' => '\xa4',
|
207
|
-
'int' => '∫',
|
208
|
-
'ucirc' => '\xfb',
|
209
|
-
'rfloor' => '⌋',
|
210
|
-
'ensp' => ' ',
|
211
|
-
'crarr' => '↵',
|
212
|
-
'ugrave' => '\xf9',
|
213
|
-
'notin' => '∉',
|
214
|
-
'exist' => '∃',
|
215
|
-
'uArr' => '⇑',
|
216
|
-
'cong' => '≅',
|
217
|
-
'Dagger' => '‡',
|
218
|
-
'oplus' => '⊕',
|
219
|
-
'times' => '\xd7',
|
220
|
-
'atilde' => '\xe3',
|
221
|
-
'piv' => 'ϖ',
|
222
|
-
'ni' => '∋',
|
223
|
-
'Phi' => 'Φ',
|
224
|
-
'lsaquo' => '‹',
|
225
|
-
'Uacute' => '\xda',
|
226
|
-
'Omicron' => 'Ο',
|
227
|
-
'ang' => '∠',
|
228
|
-
'ne' => '≠',
|
229
|
-
'iquest' => '\xbf',
|
230
|
-
'eta' => 'η',
|
231
|
-
'yacute' => '\xfd',
|
232
|
-
'Rho' => 'Ρ',
|
233
|
-
'uacute' => '\xfa',
|
234
|
-
'Alpha' => 'Α',
|
235
|
-
'zeta' => 'ζ',
|
236
|
-
'Omega' => 'Ω',
|
237
|
-
'nu' => 'ν',
|
238
|
-
'sim' => '∼',
|
239
|
-
'sect' => '\xa7',
|
240
|
-
'phi' => 'φ',
|
241
|
-
'sigmaf' => 'ς',
|
242
|
-
'macr' => '\xaf',
|
243
|
-
'minus' => '−',
|
244
|
-
'Ccedil' => '\xc7',
|
245
|
-
'ordm' => '\xba',
|
246
|
-
'epsilon' => 'ε',
|
247
|
-
'beta' => 'β',
|
248
|
-
'rArr' => '⇒',
|
249
|
-
'rho' => 'ρ',
|
250
|
-
'aacute' => '\xe1',
|
251
|
-
'eacute' => '\xe9',
|
252
|
-
'omega' => 'ω',
|
253
|
-
'middot' => '\xb7',
|
254
|
-
'Gamma' => 'Γ',
|
255
|
-
'Iacute' => '\xcd',
|
256
|
-
'lang' => '〈',
|
257
|
-
'spades' => '♠',
|
258
|
-
'rsquo' => '’',
|
259
|
-
'uml' => '\xa8',
|
260
|
-
'thorn' => '\xfe',
|
261
|
-
'ouml' => '\xf6',
|
262
|
-
'thetasym' => 'ϑ',
|
263
|
-
'or' => '∨',
|
264
|
-
'raquo' => '\xbb',
|
265
|
-
'acirc' => '\xe2',
|
266
|
-
'ldquo' => '“',
|
267
|
-
'hearts' => '♥',
|
268
|
-
'sigma' => 'σ',
|
269
|
-
'oacute' => '\xf3',
|
270
|
-
=end
|
271
|
-
}
|
1
|
+
#-- vim:sw=2:et
|
2
|
+
#++
|
3
|
+
#
|
4
|
+
# :title: Url plugin
|
5
|
+
|
6
|
+
define_structure :Url, :channel, :nick, :time, :url, :info
|
272
7
|
|
273
8
|
class UrlPlugin < Plugin
|
274
|
-
|
9
|
+
LINK_INFO = "[Link Info]"
|
10
|
+
OUR_UNSAFE = Regexp.new("[^#{URI::PATTERN::UNRESERVED}#{URI::PATTERN::RESERVED}%# ]", false, 'N')
|
11
|
+
|
12
|
+
Config.register Config::IntegerValue.new('url.max_urls',
|
275
13
|
:default => 100, :validate => Proc.new{|v| v > 0},
|
276
14
|
:desc => "Maximum number of urls to store. New urls replace oldest ones.")
|
277
|
-
|
278
|
-
:default =>
|
279
|
-
:desc => "Get the title of
|
280
|
-
|
15
|
+
Config.register Config::IntegerValue.new('url.display_link_info',
|
16
|
+
:default => 0,
|
17
|
+
:desc => "Get the title of links pasted to the channel and display it (also tells if the link is broken or the site is down). Do it for at most this many links per line (set to 0 to disable)")
|
18
|
+
Config.register Config::BooleanValue.new('url.titles_only',
|
19
|
+
:default => false,
|
20
|
+
:desc => "Only show info for links that have <title> tags (in other words, don't display info for jpegs, mpegs, etc.)")
|
21
|
+
Config.register Config::BooleanValue.new('url.first_par',
|
22
|
+
:default => false,
|
23
|
+
:desc => "Also try to get the first paragraph of a web page")
|
24
|
+
Config.register Config::BooleanValue.new('url.info_on_list',
|
25
|
+
:default => false,
|
26
|
+
:desc => "Show link info when listing/searching for urls")
|
27
|
+
Config.register Config::ArrayValue.new('url.no_info_hosts',
|
28
|
+
:default => ['localhost', '^192\.168\.', '^10\.', '^127\.', '^172\.(1[6-9]|2\d|31)\.'],
|
29
|
+
:on_change => Proc.new { |bot, v| bot.plugins['url'].reset_no_info_hosts },
|
30
|
+
:desc => "A list of regular expressions matching hosts for which no info should be provided")
|
31
|
+
|
32
|
+
|
281
33
|
def initialize
|
282
34
|
super
|
283
35
|
@registry.set_default(Array.new)
|
36
|
+
unless @bot.config['url.display_link_info'].kind_of?(Integer)
|
37
|
+
@bot.config.items[:'url.display_link_info'].set_string(@bot.config['url.display_link_info'].to_s)
|
38
|
+
end
|
39
|
+
reset_no_info_hosts
|
284
40
|
end
|
285
41
|
|
286
|
-
def
|
287
|
-
|
42
|
+
def reset_no_info_hosts
|
43
|
+
@no_info_hosts = Regexp.new(@bot.config['url.no_info_hosts'].join('|'), true)
|
44
|
+
debug "no info hosts regexp set to #{@no_info_hosts}"
|
288
45
|
end
|
289
46
|
|
290
|
-
def
|
291
|
-
|
292
|
-
htmldata = CGI::unescapeHTML htmldata
|
293
|
-
|
294
|
-
# second pass -- destroy the remaining bits...
|
295
|
-
htmldata.gsub(/(&(.+?);)/) {
|
296
|
-
symbol = $2
|
297
|
-
|
298
|
-
# remove the 0-paddng from unicode integers
|
299
|
-
if symbol =~ /#(.+)/
|
300
|
-
symbol = "##{$1.to_i.to_s}"
|
301
|
-
end
|
302
|
-
|
303
|
-
# output the symbol's irc-translated character, or a * if it's unknown
|
304
|
-
UNESCAPE_TABLE[symbol] || '*'
|
305
|
-
}
|
47
|
+
def help(plugin, topic="")
|
48
|
+
"url info <url> => display link info for <url> (set url.display_link_info > 0 if you want the bot to do it automatically when someone writes an url), urls [<max>=4] => list <max> last urls mentioned in current channel, urls search [<max>=4] <regexp> => search for matching urls. In a private message, you must specify the channel to query, eg. urls <channel> [max], urls search <channel> [max] <regexp>"
|
306
49
|
end
|
307
50
|
|
308
51
|
def get_title_from_html(pagedata)
|
309
|
-
return
|
310
|
-
title = $1.strip.gsub(/\s*\n+\s*/, " ")
|
311
|
-
title = unescape_title title
|
312
|
-
title = title[0..255] if title.length > 255
|
313
|
-
"[Link Info] title: #{title}"
|
52
|
+
return pagedata.ircify_html_title
|
314
53
|
end
|
315
54
|
|
316
|
-
def
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
55
|
+
def get_title_for_url(uri_str, opts = {})
|
56
|
+
|
57
|
+
url = uri_str.kind_of?(URI) ? uri_str : URI.parse(uri_str)
|
58
|
+
return if url.scheme !~ /https?/
|
59
|
+
|
60
|
+
# also check the ip, the canonical name and the aliases
|
61
|
+
begin
|
62
|
+
checks = TCPSocket.gethostbyname(url.host)
|
63
|
+
checks.delete_at(-2)
|
64
|
+
rescue => e
|
65
|
+
return "Unable to retrieve info for #{url.host}: #{e.message}"
|
66
|
+
end
|
67
|
+
|
68
|
+
checks << url.host
|
69
|
+
checks.flatten!
|
70
|
+
|
71
|
+
unless checks.grep(@no_info_hosts).empty?
|
72
|
+
return "Sorry, info retrieval for #{url.host} (#{checks.first}) is disabled"
|
73
|
+
end
|
74
|
+
|
75
|
+
logopts = opts.dup
|
76
|
+
|
77
|
+
title = nil
|
78
|
+
extra = []
|
79
|
+
|
80
|
+
begin
|
81
|
+
debug "+ getting info for #{url.request_uri}"
|
82
|
+
info = @bot.filter(:htmlinfo, url)
|
83
|
+
debug info
|
84
|
+
resp = info[:headers]
|
85
|
+
|
86
|
+
logopts[:title] = title = info[:title]
|
87
|
+
|
88
|
+
if info[:content]
|
89
|
+
logopts[:extra] = info[:content]
|
90
|
+
extra << "#{Bold}text#{Bold}: #{info[:content]}" if @bot.config['url.first_par']
|
91
|
+
else
|
92
|
+
logopts[:extra] = String.new
|
93
|
+
logopts[:extra] << "Content Type: #{resp['content-type']}"
|
94
|
+
extra << "#{Bold}type#{Bold}: #{resp['content-type']}" unless title
|
95
|
+
if enc = resp['content-encoding']
|
96
|
+
logopts[:extra] << ", encoding: #{enc}"
|
97
|
+
extra << "#{Bold}encoding#{Bold}: #{enc}" if @bot.config['url.first_par'] or not title
|
98
|
+
end
|
99
|
+
|
100
|
+
size = resp['content-length'].first.gsub(/(\d)(?=\d{3}+(?:\.|$))(\d{3}\..*)?/,'\1,\2') rescue nil
|
101
|
+
if size
|
102
|
+
logopts[:extra] << ", size: #{size} bytes"
|
103
|
+
extra << "#{Bold}size#{Bold}: #{size} bytes" if @bot.config['url.first_par'] or not title
|
104
|
+
end
|
328
105
|
end
|
329
|
-
|
330
|
-
|
106
|
+
rescue Exception => e
|
107
|
+
case e
|
108
|
+
when UrlLinkError
|
109
|
+
raise e
|
110
|
+
else
|
111
|
+
error e
|
112
|
+
raise "connecting to site/processing information (#{e.message})"
|
113
|
+
end
|
114
|
+
end
|
331
115
|
|
332
|
-
|
333
|
-
|
116
|
+
call_event(:url_added, url.to_s, logopts)
|
117
|
+
if title
|
118
|
+
extra.unshift("#{Bold}title#{Bold}: #{title}")
|
334
119
|
end
|
335
|
-
|
336
|
-
chunks.join('')
|
337
|
-
|
120
|
+
return extra.join(", ") if title or not @bot.config['url.titles_only']
|
338
121
|
end
|
339
122
|
|
123
|
+
def handle_urls(m, urls, display_info=@bot.config['url.display_link_info'])
|
124
|
+
return if urls.empty?
|
125
|
+
debug "found urls #{urls.inspect}"
|
126
|
+
list = m.public? ? @registry[m.target] : nil
|
127
|
+
debug "display link info: #{display_info}"
|
128
|
+
urls_displayed = 0
|
129
|
+
urls.each do |urlstr|
|
130
|
+
debug "working on #{urlstr}"
|
131
|
+
next unless urlstr =~ /^https?:/
|
132
|
+
title = nil
|
133
|
+
debug "Getting title for #{urlstr}..."
|
134
|
+
reply = nil
|
135
|
+
begin
|
136
|
+
title = get_title_for_url(urlstr,
|
137
|
+
:nick => m.source.nick,
|
138
|
+
:channel => m.channel,
|
139
|
+
:ircline => m.message)
|
140
|
+
debug "Title #{title ? '' : 'not '} found"
|
141
|
+
reply = "#{LINK_INFO} #{title}" if title
|
142
|
+
rescue => e
|
143
|
+
debug e
|
144
|
+
# we might get a 404 because of trailing punctuation, so we try again
|
145
|
+
# with the last character stripped. this might generate invalid URIs
|
146
|
+
# (e.g. because "some.url" gets chopped to some.url%2, so catch that too
|
147
|
+
if e.message =~ /\(404 - Not Found\)/i or e.kind_of?(URI::InvalidURIError)
|
148
|
+
# chop off last character, and retry if we still have enough string to
|
149
|
+
# look like a minimal URL
|
150
|
+
retry if urlstr.chop! and urlstr =~ /^https?:\/\/./
|
151
|
+
end
|
152
|
+
reply = "Error #{e.message}"
|
153
|
+
end
|
154
|
+
|
155
|
+
if display_info > urls_displayed
|
156
|
+
if reply
|
157
|
+
m.plainreply(reply, :overlong => :truncate)
|
158
|
+
urls_displayed += 1
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
next unless list
|
340
163
|
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
164
|
+
# check to see if this url is already listed
|
165
|
+
next if list.find {|u| u.url == urlstr }
|
166
|
+
|
167
|
+
url = Url.new(m.target, m.sourcenick, Time.new, urlstr, title)
|
168
|
+
debug "#{list.length} urls so far"
|
169
|
+
list.pop if list.length > @bot.config['url.max_urls']
|
170
|
+
debug "storing url #{url.url}"
|
171
|
+
list.unshift url
|
172
|
+
debug "#{list.length} urls now"
|
347
173
|
end
|
348
|
-
|
349
|
-
|
350
|
-
url = URI.parse(uri_str)
|
351
|
-
return if url.scheme !~ /https?/
|
174
|
+
@registry[m.target] = list
|
175
|
+
end
|
352
176
|
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
http.start { |http|
|
358
|
-
url.path = '/' if url.path == ''
|
359
|
-
|
360
|
-
http.request_get(url.path, "User-Agent" => "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)") { |response|
|
361
|
-
|
362
|
-
case response
|
363
|
-
when Net::HTTPRedirection, Net::HTTPMovedPermanently then
|
364
|
-
# call self recursively if this is a redirect
|
365
|
-
redirect_to = response['location'] || './'
|
366
|
-
debug "+ redirect location: #{redirect_to.inspect}"
|
367
|
-
url = URI.join url.to_s, redirect_to
|
368
|
-
debug "+ whee, redirecting to #{url.to_s}!"
|
369
|
-
return get_title_for_url(url.to_s, depth-1)
|
370
|
-
when Net::HTTPSuccess then
|
371
|
-
if response['content-type'] =~ /^text\//
|
372
|
-
# since the content is 'text/*' and is small enough to
|
373
|
-
# be a webpage, retrieve the title from the page
|
374
|
-
debug "+ getting #{url.request_uri}"
|
375
|
-
data = read_data_from_response(response, 50000)
|
376
|
-
return get_title_from_html(data)
|
377
|
-
else
|
378
|
-
# content doesn't have title, just display info.
|
379
|
-
size = response['content-length'].gsub(/(\d)(?=\d{3}+(?:\.|$))(\d{3}\..*)?/,'\1,\2')
|
380
|
-
return "[Link Info] type: #{response['content-type']}#{size ? ", size: #{size} bytes" : ""}"
|
381
|
-
end
|
382
|
-
when Net::HTTPClientError then
|
383
|
-
return "[Link Info] Error getting link (#{response.code} - #{response.message})"
|
384
|
-
when Net::HTTPServerError then
|
385
|
-
return "[Link Info] Error getting link (#{response.code} - #{response.message})"
|
386
|
-
else
|
387
|
-
return nil
|
388
|
-
end # end of "case response"
|
389
|
-
|
390
|
-
} # end of request block
|
391
|
-
} # end of http start block
|
392
|
-
|
393
|
-
return title
|
394
|
-
|
395
|
-
rescue SocketError => e
|
396
|
-
return "[Link Info] Error connecting to site (#{e.message})"
|
177
|
+
def info(m, params)
|
178
|
+
escaped = URI.escape(params[:urls].to_s, OUR_UNSAFE)
|
179
|
+
urls = URI.extract(escaped)
|
180
|
+
Thread.new { handle_urls(m, urls, params[:urls].length) }
|
397
181
|
end
|
398
182
|
|
399
|
-
def
|
400
|
-
return unless m.kind_of?(PrivMessage)
|
183
|
+
def message(m)
|
401
184
|
return if m.address?
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
185
|
+
|
186
|
+
escaped = URI.escape(m.message, OUR_UNSAFE)
|
187
|
+
urls = URI.extract(escaped, ['http', 'https'])
|
188
|
+
return if urls.empty?
|
189
|
+
Thread.new { handle_urls(m, urls) }
|
190
|
+
end
|
191
|
+
|
192
|
+
def reply_urls(opts={})
|
193
|
+
list = opts[:list]
|
194
|
+
max = opts[:max]
|
195
|
+
channel = opts[:channel]
|
196
|
+
m = opts[:msg]
|
197
|
+
return unless list and max and m
|
198
|
+
list[0..(max-1)].each do |url|
|
199
|
+
disp = "[#{url.time.strftime('%Y/%m/%d %H:%M:%S')}] <#{url.nick}> #{url.url}"
|
200
|
+
if @bot.config['url.info_on_list']
|
201
|
+
title = url.info ||
|
202
|
+
get_title_for_url(url.url,
|
203
|
+
:nick => url.nick, :channel => channel) rescue nil
|
204
|
+
# If the url info was missing and we now have some, try to upgrade it
|
205
|
+
if channel and title and not url.info
|
206
|
+
ll = @registry[channel]
|
207
|
+
debug ll
|
208
|
+
if el = ll.find { |u| u.url == url.url }
|
209
|
+
el.info = title
|
210
|
+
@registry[channel] = ll
|
211
|
+
end
|
426
212
|
end
|
427
|
-
|
428
|
-
list.unshift url
|
429
|
-
debug "#{list.length} urls now"
|
430
|
-
@registry[m.target] = list
|
213
|
+
disp << " --> #{title}" if title
|
431
214
|
end
|
215
|
+
m.reply disp, :overlong => :truncate
|
432
216
|
end
|
433
217
|
end
|
434
218
|
|
@@ -441,9 +225,7 @@ class UrlPlugin < Plugin
|
|
441
225
|
if list.empty?
|
442
226
|
m.reply "no urls seen yet for channel #{channel}"
|
443
227
|
else
|
444
|
-
list
|
445
|
-
m.reply "[#{url.time.strftime('%Y/%m/%d %H:%M:%S')}] <#{url.nick}> #{url.url}"
|
446
|
-
end
|
228
|
+
reply_urls :msg => m, :channel => channel, :list => list, :max => max
|
447
229
|
end
|
448
230
|
end
|
449
231
|
|
@@ -455,18 +237,20 @@ class UrlPlugin < Plugin
|
|
455
237
|
max = 1 if max < 1
|
456
238
|
regex = Regexp.new(string, Regexp::IGNORECASE)
|
457
239
|
list = @registry[channel].find_all {|url|
|
458
|
-
regex.match(url.url) || regex.match(url.nick)
|
240
|
+
regex.match(url.url) || regex.match(url.nick) ||
|
241
|
+
(@bot.config['url.info_on_list'] && regex.match(url.info))
|
459
242
|
}
|
460
243
|
if list.empty?
|
461
244
|
m.reply "no matches for channel #{channel}"
|
462
245
|
else
|
463
|
-
list
|
464
|
-
m.reply "[#{url.time.strftime('%Y/%m/%d %H:%M:%S')}] <#{url.nick}> #{url.url}"
|
465
|
-
end
|
246
|
+
reply_urls :msg => m, :channel => channel, :list => list, :max => max
|
466
247
|
end
|
467
248
|
end
|
468
249
|
end
|
250
|
+
|
469
251
|
plugin = UrlPlugin.new
|
252
|
+
plugin.map 'urls info *urls', :action => 'info'
|
253
|
+
plugin.map 'url info *urls', :action => 'info'
|
470
254
|
plugin.map 'urls search :channel :limit :string', :action => 'search',
|
471
255
|
:defaults => {:limit => 4},
|
472
256
|
:requirements => {:limit => /^\d+$/},
|