rbot 0.9.14 → 0.9.15
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +6 -2
- data/REQUIREMENTS +7 -1
- data/Rakefile +10 -32
- data/bin/rbot +6 -1
- data/bin/svnwatch-postcommit-hook +68 -0
- data/data/rbot/contrib/plugins/stats.rb +3 -3
- data/data/rbot/contrib/plugins/vandale.rb +1 -1
- data/data/rbot/filters/rss.rb +72 -0
- data/data/rbot/languages/finnish.lang +50 -0
- data/data/rbot/plugins/alias.rb +6 -6
- data/data/rbot/plugins/autorejoin.rb +41 -2
- data/data/rbot/plugins/bans.rb +100 -6
- data/data/rbot/plugins/bash.rb +9 -4
- data/data/rbot/plugins/cal.rb +1 -1
- data/data/rbot/plugins/chucknorris.rb +6 -6
- data/data/rbot/plugins/debugger.rb +7 -3
- data/data/rbot/plugins/deepthoughts.rb +1 -1
- data/data/rbot/plugins/delicious.rb +6 -2
- data/data/rbot/plugins/dice.rb +7 -7
- data/data/rbot/plugins/dict.rb +4 -3
- data/data/rbot/plugins/dictclient.rb +17 -13
- data/data/rbot/plugins/digg.rb +3 -3
- data/data/rbot/plugins/eightball.rb +1 -1
- data/data/rbot/plugins/factoids.rb +13 -4
- data/data/rbot/plugins/figlet.rb +4 -4
- data/data/rbot/plugins/forecast.rb +3 -3
- data/data/rbot/plugins/fortune.rb +14 -8
- data/data/rbot/plugins/freshmeat.rb +2 -2
- data/data/rbot/plugins/games/azgame.rb +72 -19
- data/data/rbot/plugins/games/hangman.rb +499 -0
- data/data/rbot/plugins/games/quiz.rb +15 -13
- data/data/rbot/plugins/games/roshambo.rb +1 -1
- data/data/rbot/plugins/games/roulette.rb +4 -4
- data/data/rbot/plugins/games/shiritori.rb +31 -31
- data/data/rbot/plugins/games/uno.rb +28 -6
- data/data/rbot/plugins/games/wheelfortune.rb +1 -3
- data/data/rbot/plugins/geoip.rb +83 -28
- data/data/rbot/plugins/googlefight.rb +64 -0
- data/data/rbot/plugins/greet.rb +45 -0
- data/data/rbot/plugins/grouphug.rb +40 -12
- data/data/rbot/plugins/imdb.rb +4 -4
- data/data/rbot/plugins/insult.rb +2 -2
- data/data/rbot/plugins/karma.rb +6 -5
- data/data/rbot/plugins/keywords.rb +26 -22
- data/data/rbot/plugins/lart.rb +5 -6
- data/data/rbot/plugins/lastfm.rb +488 -125
- data/data/rbot/plugins/lib_spotify.rb +84 -0
- data/data/rbot/plugins/linkbot.rb +1 -1
- data/data/rbot/plugins/markov.rb +567 -78
- data/data/rbot/plugins/math.rb +3 -3
- data/data/rbot/plugins/modes.rb +1 -1
- data/data/rbot/plugins/nickrecover.rb +1 -1
- data/data/rbot/plugins/nickserv.rb +7 -7
- data/data/rbot/plugins/note.rb +55 -0
- data/data/rbot/plugins/nslookup.rb +2 -2
- data/data/rbot/plugins/quakeauth.rb +4 -4
- data/data/rbot/plugins/quotes.rb +53 -19
- data/data/rbot/plugins/reaction.rb +76 -19
- data/data/rbot/plugins/remind.rb +3 -96
- data/data/rbot/plugins/ri.rb +1 -1
- data/data/rbot/plugins/rot13.rb +1 -1
- data/data/rbot/plugins/rss.rb +296 -190
- data/data/rbot/plugins/salut.rb +8 -8
- data/data/rbot/plugins/script.rb +48 -11
- data/data/rbot/plugins/search.rb +124 -28
- data/data/rbot/plugins/seen.rb +162 -31
- data/data/rbot/plugins/shortenurls.rb +1 -1
- data/data/rbot/plugins/slashdot.rb +19 -6
- data/data/rbot/plugins/spotify.rb +78 -0
- data/data/rbot/plugins/theyfightcrime.rb +10 -10
- data/data/rbot/plugins/time.rb +2 -2
- data/data/rbot/plugins/translator.rb +161 -85
- data/data/rbot/plugins/tube.rb +2 -2
- data/data/rbot/plugins/tumblr.rb +143 -0
- data/data/rbot/plugins/twitter.rb +25 -6
- data/data/rbot/plugins/urban.rb +6 -4
- data/data/rbot/plugins/url.rb +49 -10
- data/data/rbot/plugins/weather.rb +6 -6
- data/data/rbot/plugins/wserver.rb +5 -5
- data/data/rbot/plugins/youtube.rb +12 -12
- data/data/rbot/templates/lart/larts-italian +1 -1
- data/launch_here.rb +68 -0
- data/lib/rbot/botuser.rb +1 -1
- data/lib/rbot/compat19.rb +70 -0
- data/lib/rbot/config.rb +8 -6
- data/lib/rbot/core/auth.rb +37 -21
- data/lib/rbot/core/basics.rb +33 -2
- data/lib/rbot/core/config.rb +24 -17
- data/lib/rbot/core/filters_ui.rb +2 -2
- data/lib/rbot/core/irclog.rb +20 -11
- data/lib/rbot/core/remote.rb +9 -9
- data/lib/rbot/core/unicode.rb +4 -0
- data/lib/rbot/core/userdata.rb +16 -1
- data/lib/rbot/core/utils/extends.rb +76 -0
- data/lib/rbot/core/utils/filters.rb +47 -0
- data/lib/rbot/core/utils/httputil.rb +36 -26
- data/lib/rbot/core/utils/parse_time.rb +193 -0
- data/lib/rbot/core/utils/utils.rb +81 -56
- data/lib/rbot/core/utils/wordlist.rb +66 -0
- data/lib/rbot/core/wordlist_ui.rb +27 -0
- data/lib/rbot/irc.rb +59 -19
- data/lib/rbot/ircbot.rb +190 -58
- data/lib/rbot/ircsocket.rb +14 -8
- data/lib/rbot/language.rb +4 -3
- data/lib/rbot/load-gettext.rb +22 -9
- data/lib/rbot/message.rb +89 -18
- data/lib/rbot/messagemapper.rb +71 -19
- data/lib/rbot/plugins.rb +112 -44
- data/lib/rbot/{registry.rb → registry/bdb.rb} +226 -22
- data/lib/rbot/registry/tc.rb +531 -0
- data/lib/rbot/rfc2812.rb +33 -8
- data/lib/rbot/timer.rb +12 -20
- data/po/en_US/rbot-autorejoin.po +3 -0
- data/po/en_US/rbot-azgame.po +51 -43
- data/po/en_US/rbot-bash.po +15 -0
- data/po/en_US/rbot-dictclient.po +20 -20
- data/po/en_US/rbot-factoids.po +9 -9
- data/po/en_US/rbot-geoip.po +0 -0
- data/po/en_US/rbot-googlefight.po +24 -0
- data/po/en_US/rbot-grouphug.po +4 -4
- data/po/en_US/rbot-hangman.po +114 -0
- data/po/en_US/rbot-keywords.po +3 -3
- data/po/en_US/rbot-lastfm.po +268 -70
- data/po/en_US/rbot-markov.po +73 -2
- data/po/en_US/rbot-quotes.po +21 -21
- data/po/en_US/rbot-rss.po +6 -2
- data/po/en_US/rbot-script.po +3 -0
- data/po/en_US/rbot-seen.po +72 -0
- data/po/en_US/rbot-spell.po +2 -2
- data/po/en_US/rbot-translator.po +13 -13
- data/po/en_US/rbot-twitter.po +3 -3
- data/po/en_US/rbot-uno.po +131 -114
- data/po/en_US/rbot-wall.po +12 -13
- data/po/en_US/rbot-wheelfortune.po +41 -41
- data/po/en_US/rbot.po +254 -194
- data/po/fi/rbot-alias.po +82 -0
- data/po/fi/rbot-autoop.po +0 -0
- data/po/fi/rbot-autorejoin.po +20 -0
- data/po/fi/rbot-azgame.po +194 -0
- data/po/fi/rbot-bans.po +0 -0
- data/po/fi/rbot-bash.po +32 -0
- data/po/fi/rbot-botsnack.po +0 -0
- data/po/fi/rbot-cal.po +20 -0
- data/po/fi/rbot-chanserv.po +0 -0
- data/po/fi/rbot-chucknorris.po +0 -0
- data/po/fi/rbot-debugger.po +0 -0
- data/po/fi/rbot-deepthoughts.po +0 -0
- data/po/fi/rbot-delicious.po +0 -0
- data/po/fi/rbot-dice.po +0 -0
- data/po/fi/rbot-dict.po +0 -0
- data/po/fi/rbot-dictclient.po +111 -0
- data/po/fi/rbot-digg.po +0 -0
- data/po/fi/rbot-eightball.po +0 -0
- data/po/fi/rbot-excuse.po +0 -0
- data/po/fi/rbot-factoids.po +107 -0
- data/po/fi/rbot-figlet.po +36 -0
- data/po/fi/rbot-fish.po +0 -0
- data/po/fi/rbot-forecast.po +0 -0
- data/po/fi/rbot-fortune.po +0 -0
- data/po/fi/rbot-freshmeat.po +0 -0
- data/po/fi/rbot-geoip.po +0 -0
- data/po/fi/rbot-googlefight.po +24 -0
- data/po/fi/rbot-grouphug.po +35 -0
- data/po/fi/rbot-hangman.po +121 -0
- data/po/fi/rbot-hl2.po +0 -0
- data/po/fi/rbot-host.po +20 -0
- data/po/fi/rbot-imdb.po +0 -0
- data/po/fi/rbot-insult.po +0 -0
- data/po/fi/rbot-iplookup.po +0 -0
- data/po/fi/rbot-karma.po +0 -0
- data/po/fi/rbot-keywords.po +24 -0
- data/po/fi/rbot-lart.po +0 -0
- data/po/fi/rbot-lastfm.po +377 -0
- data/po/fi/rbot-linkbot.po +0 -0
- data/po/fi/rbot-markov.po +91 -0
- data/po/fi/rbot-math.po +0 -0
- data/po/fi/rbot-modes.po +0 -0
- data/po/fi/rbot-nickrecover.po +36 -0
- data/po/fi/rbot-nickserv.po +104 -0
- data/po/fi/rbot-nslookup.po +0 -0
- data/po/fi/rbot-quakeauth.po +0 -0
- data/po/fi/rbot-quiz.po +0 -0
- data/po/fi/rbot-quotes.po +108 -0
- data/po/fi/rbot-reaction.po +0 -0
- data/po/fi/rbot-remind.po +0 -0
- data/po/fi/rbot-remotectl.po +0 -0
- data/po/fi/rbot-ri.po +0 -0
- data/po/fi/rbot-roshambo.po +0 -0
- data/po/fi/rbot-rot13.po +0 -0
- data/po/fi/rbot-roulette.po +0 -0
- data/po/fi/rbot-rss.po +24 -0
- data/po/fi/rbot-salut.po +0 -0
- data/po/fi/rbot-script.po +20 -0
- data/po/fi/rbot-search.po +0 -0
- data/po/fi/rbot-seen.po +92 -0
- data/po/fi/rbot-shiritori.po +102 -0
- data/po/fi/rbot-shortenurls.po +0 -0
- data/po/fi/rbot-slashdot.po +0 -0
- data/po/fi/rbot-spell.po +54 -0
- data/po/fi/rbot-theyfightcrime.po +0 -0
- data/po/fi/rbot-threat.po +0 -0
- data/po/fi/rbot-time.po +0 -0
- data/po/fi/rbot-topic.po +0 -0
- data/po/fi/rbot-translator.po +77 -0
- data/po/fi/rbot-tube.po +0 -0
- data/po/fi/rbot-twitter.po +24 -0
- data/po/fi/rbot-uno.po +529 -0
- data/po/fi/rbot-urban.po +0 -0
- data/po/fi/rbot-url.po +0 -0
- data/po/fi/rbot-usermodes.po +0 -0
- data/po/fi/rbot-wall.po +32 -0
- data/po/fi/rbot-weather.po +0 -0
- data/po/fi/rbot-wheelfortune.po +205 -0
- data/po/fi/rbot-wow.po +0 -0
- data/po/fi/rbot-wserver.po +0 -0
- data/po/fi/rbot-youtube.po +58 -0
- data/po/fi/rbot.po +1152 -0
- data/po/fr/rbot-autorejoin.po +3 -0
- data/po/fr/rbot-azgame.po +51 -43
- data/po/fr/rbot-bash.po +15 -0
- data/po/fr/rbot-dictclient.po +20 -20
- data/po/fr/rbot-factoids.po +9 -9
- data/po/fr/rbot-geoip.po +0 -0
- data/po/fr/rbot-googlefight.po +24 -0
- data/po/fr/rbot-grouphug.po +4 -4
- data/po/fr/rbot-hangman.po +114 -0
- data/po/fr/rbot-keywords.po +3 -3
- data/po/fr/rbot-lastfm.po +268 -70
- data/po/fr/rbot-markov.po +74 -2
- data/po/fr/rbot-quotes.po +21 -21
- data/po/fr/rbot-rss.po +6 -2
- data/po/fr/rbot-script.po +3 -0
- data/po/fr/rbot-seen.po +72 -0
- data/po/fr/rbot-spell.po +2 -2
- data/po/fr/rbot-translator.po +13 -13
- data/po/fr/rbot-twitter.po +3 -3
- data/po/fr/rbot-uno.po +132 -114
- data/po/fr/rbot-wall.po +8 -9
- data/po/fr/rbot-wheelfortune.po +41 -41
- data/po/fr/rbot.po +268 -197
- data/po/it/rbot-autorejoin.po +3 -0
- data/po/it/rbot-azgame.po +50 -42
- data/po/it/rbot-bash.po +15 -0
- data/po/it/rbot-dictclient.po +20 -20
- data/po/it/rbot-factoids.po +9 -9
- data/po/it/rbot-geoip.po +0 -0
- data/po/it/rbot-googlefight.po +24 -0
- data/po/it/rbot-grouphug.po +4 -4
- data/po/it/rbot-hangman.po +114 -0
- data/po/it/rbot-keywords.po +3 -3
- data/po/it/rbot-lastfm.po +268 -70
- data/po/it/rbot-markov.po +75 -3
- data/po/it/rbot-quotes.po +21 -21
- data/po/it/rbot-rss.po +7 -3
- data/po/it/rbot-script.po +19 -0
- data/po/it/rbot-seen.po +72 -0
- data/po/it/rbot-spell.po +2 -2
- data/po/it/rbot-translator.po +13 -13
- data/po/it/rbot-twitter.po +3 -3
- data/po/it/rbot-uno.po +137 -116
- data/po/it/rbot-wall.po +8 -9
- data/po/it/rbot-wheelfortune.po +41 -41
- data/po/it/rbot.po +265 -208
- data/po/ja/rbot-autorejoin.po +3 -0
- data/po/ja/rbot-azgame.po +51 -43
- data/po/ja/rbot-bash.po +15 -0
- data/po/ja/rbot-dictclient.po +20 -20
- data/po/ja/rbot-factoids.po +9 -9
- data/po/ja/rbot-geoip.po +0 -0
- data/po/ja/rbot-googlefight.po +24 -0
- data/po/ja/rbot-grouphug.po +4 -4
- data/po/ja/rbot-hangman.po +114 -0
- data/po/ja/rbot-keywords.po +3 -3
- data/po/ja/rbot-lastfm.po +268 -70
- data/po/ja/rbot-markov.po +73 -2
- data/po/ja/rbot-quotes.po +21 -21
- data/po/ja/rbot-rss.po +6 -2
- data/po/ja/rbot-script.po +3 -0
- data/po/ja/rbot-seen.po +72 -0
- data/po/ja/rbot-spell.po +2 -2
- data/po/ja/rbot-translator.po +13 -13
- data/po/ja/rbot-twitter.po +3 -3
- data/po/ja/rbot-uno.po +131 -114
- data/po/ja/rbot-wall.po +8 -9
- data/po/ja/rbot-wheelfortune.po +41 -41
- data/po/ja/rbot.po +248 -192
- data/po/rbot-alias.pot +2 -2
- data/po/rbot-autorejoin.pot +21 -0
- data/po/rbot-azgame.pot +51 -43
- data/po/rbot-bash.pot +33 -0
- data/po/rbot-cal.pot +2 -2
- data/po/rbot-dictclient.pot +21 -21
- data/po/rbot-factoids.pot +10 -10
- data/po/rbot-figlet.pot +2 -2
- data/po/rbot-geoip.pot +0 -0
- data/po/rbot-googlefight.pot +25 -0
- data/po/rbot-grouphug.pot +6 -6
- data/po/rbot-hangman.pot +115 -0
- data/po/rbot-host.pot +2 -2
- data/po/rbot-keywords.pot +4 -4
- data/po/rbot-lastfm.pot +270 -72
- data/po/rbot-markov.pot +74 -3
- data/po/rbot-nickrecover.pot +2 -2
- data/po/rbot-nickserv.pot +2 -2
- data/po/rbot-quotes.pot +22 -22
- data/po/rbot-rss.pot +7 -3
- data/po/rbot-script.pot +21 -0
- data/po/rbot-seen.pot +90 -0
- data/po/rbot-shiritori.pot +2 -2
- data/po/rbot-spell.pot +3 -3
- data/po/rbot-translator.pot +14 -14
- data/po/rbot-twitter.pot +4 -4
- data/po/rbot-uno.pot +132 -115
- data/po/rbot-wall.pot +2 -2
- data/po/rbot-wheelfortune.pot +42 -42
- data/po/rbot-youtube.pot +2 -2
- data/po/rbot.pot +249 -193
- data/po/zh_CN/rbot-autorejoin.po +3 -0
- data/po/zh_CN/rbot-azgame.po +50 -42
- data/po/zh_CN/rbot-bash.po +15 -0
- data/po/zh_CN/rbot-dictclient.po +20 -20
- data/po/zh_CN/rbot-factoids.po +9 -9
- data/po/zh_CN/rbot-geoip.po +0 -0
- data/po/zh_CN/rbot-googlefight.po +24 -0
- data/po/zh_CN/rbot-grouphug.po +4 -4
- data/po/zh_CN/rbot-hangman.po +114 -0
- data/po/zh_CN/rbot-keywords.po +3 -3
- data/po/zh_CN/rbot-lastfm.po +268 -70
- data/po/zh_CN/rbot-markov.po +73 -2
- data/po/zh_CN/rbot-quotes.po +21 -21
- data/po/zh_CN/rbot-rss.po +6 -2
- data/po/zh_CN/rbot-script.po +3 -0
- data/po/zh_CN/rbot-seen.po +72 -0
- data/po/zh_CN/rbot-spell.po +2 -2
- data/po/zh_CN/rbot-translator.po +13 -13
- data/po/zh_CN/rbot-twitter.po +3 -3
- data/po/zh_CN/rbot-uno.po +131 -114
- data/po/zh_CN/rbot-wall.po +7 -8
- data/po/zh_CN/rbot-wheelfortune.po +41 -41
- data/po/zh_CN/rbot.po +248 -192
- data/po/zh_TW/rbot-autorejoin.po +3 -0
- data/po/zh_TW/rbot-azgame.po +50 -42
- data/po/zh_TW/rbot-bash.po +15 -0
- data/po/zh_TW/rbot-dictclient.po +20 -20
- data/po/zh_TW/rbot-factoids.po +9 -9
- data/po/zh_TW/rbot-geoip.po +0 -0
- data/po/zh_TW/rbot-googlefight.po +24 -0
- data/po/zh_TW/rbot-grouphug.po +4 -4
- data/po/zh_TW/rbot-hangman.po +114 -0
- data/po/zh_TW/rbot-keywords.po +3 -3
- data/po/zh_TW/rbot-lastfm.po +268 -70
- data/po/zh_TW/rbot-markov.po +73 -2
- data/po/zh_TW/rbot-quotes.po +21 -21
- data/po/zh_TW/rbot-rss.po +6 -2
- data/po/zh_TW/rbot-script.po +3 -0
- data/po/zh_TW/rbot-seen.po +72 -0
- data/po/zh_TW/rbot-spell.po +2 -2
- data/po/zh_TW/rbot-translator.po +13 -13
- data/po/zh_TW/rbot-twitter.po +3 -3
- data/po/zh_TW/rbot-uno.po +131 -114
- data/po/zh_TW/rbot-wall.po +7 -8
- data/po/zh_TW/rbot-wheelfortune.po +41 -41
- data/po/zh_TW/rbot.po +253 -194
- data/setup.rb +4 -4
- metadata +127 -18
- data/README +0 -43
- data/data/rbot/plugins/fish.rb +0 -121
- data/lib/rbot/dbhash.rb +0 -199
data/lib/rbot/core/unicode.rb
CHANGED
@@ -10,6 +10,9 @@
|
|
10
10
|
# encoding. The plugin takes care of translation to/from utf-8 on server IO,
|
11
11
|
# if necessary (translation charsets are configurable).
|
12
12
|
|
13
|
+
# TODO autoconfigure using server-provided allowed charset when these are
|
14
|
+
# available, see also comment in irc.rb
|
15
|
+
|
13
16
|
require 'iconv'
|
14
17
|
|
15
18
|
class UnicodePlugin < CoreBotModule
|
@@ -21,6 +24,7 @@ class UnicodePlugin < CoreBotModule
|
|
21
24
|
Config.register Config::ArrayValue.new(
|
22
25
|
'encoding.charsets', :default => ['utf-8', 'cp1252', 'iso-8859-15'],
|
23
26
|
:desc => "Ordered list of iconv(3) charsets the bot should try",
|
27
|
+
:validate_item => Proc.new { |x| !!(Iconv.new('utf-8', x) rescue nil) },
|
24
28
|
:on_change => Proc.new { |bot, v| reconfigure_filter(bot) })
|
25
29
|
|
26
30
|
class UnicodeFilter
|
data/lib/rbot/core/userdata.rb
CHANGED
@@ -25,7 +25,7 @@ module ::Irc
|
|
25
25
|
#
|
26
26
|
# If you have to do large-scale editing of the Bot data Hash,
|
27
27
|
# please use with_botdata.
|
28
|
-
#
|
28
|
+
#
|
29
29
|
def set_botdata(key, value=nil, &block)
|
30
30
|
Irc::Utils.bot.plugins['userdata'].set_data(self, key, value, &block)
|
31
31
|
end
|
@@ -38,6 +38,13 @@ module ::Irc
|
|
38
38
|
Irc::Utils.bot.plugins['userdata'].with_data(self, &block)
|
39
39
|
end
|
40
40
|
|
41
|
+
# This method removes the data associated with the key, returning
|
42
|
+
# the value of the deleted key.
|
43
|
+
|
44
|
+
def delete_botdata(*keys)
|
45
|
+
Irc::Utils.bot.plugins['userdata'].delete_data(self, *keys)
|
46
|
+
end
|
47
|
+
|
41
48
|
end
|
42
49
|
end
|
43
50
|
|
@@ -138,6 +145,14 @@ class UserDataModule < CoreBotModule
|
|
138
145
|
return h
|
139
146
|
end
|
140
147
|
|
148
|
+
def delete_data(user, *keys)
|
149
|
+
h = get_data_hash(user)
|
150
|
+
debug h
|
151
|
+
rv = keys.map { |k| h.delete k }
|
152
|
+
set_data_hash(user, h)
|
153
|
+
rv.size == 1 ? rv.first : rv
|
154
|
+
end
|
155
|
+
|
141
156
|
def handle_get(m, params)
|
142
157
|
user = m.server.get_user(params[:nick]) || m.source
|
143
158
|
key = params[:key].intern
|
@@ -124,7 +124,50 @@ class ::Array
|
|
124
124
|
replace shuffle
|
125
125
|
end
|
126
126
|
end
|
127
|
+
end
|
128
|
+
|
129
|
+
module ::Enumerable
|
130
|
+
# This method is an advanced version of #join
|
131
|
+
# allowing fine control of separators:
|
132
|
+
#
|
133
|
+
# [1,2,3].conjoin(', ', ' and ')
|
134
|
+
# => "1, 2 and 3
|
135
|
+
#
|
136
|
+
# [1,2,3,4].conjoin{ |i, a, b| i % 2 == 0 ? '.' : '-' }
|
137
|
+
# => "1.2-3.4"
|
138
|
+
#
|
139
|
+
# Code lifted from the ruby facets project:
|
140
|
+
# <http://facets.rubyforge.org>
|
141
|
+
# git-rev: c8b7395255b977d3c7de268ff563e3c5bc7f1441
|
142
|
+
# file: lib/core/facets/array/conjoin.rb
|
143
|
+
def conjoin(*args, &block)
|
144
|
+
num = count - 1
|
145
|
+
|
146
|
+
return first.to_s if num < 1
|
147
|
+
|
148
|
+
sep = []
|
149
|
+
|
150
|
+
if block_given?
|
151
|
+
num.times do |i|
|
152
|
+
sep << yield(i, *slice(i, 2))
|
153
|
+
end
|
154
|
+
else
|
155
|
+
options = (Hash === args.last) ? args.pop : {}
|
156
|
+
separator = args.shift || ""
|
157
|
+
options[-1] = args.shift unless args.empty?
|
158
|
+
|
159
|
+
sep = [separator] * num
|
160
|
+
|
161
|
+
if options.key?(:last)
|
162
|
+
options[-1] = options.delete(:last)
|
163
|
+
end
|
164
|
+
options[-1] ||= _(" and ")
|
127
165
|
|
166
|
+
options.each{ |i, s| sep[i] = s }
|
167
|
+
end
|
168
|
+
|
169
|
+
zip(sep).join
|
170
|
+
end
|
128
171
|
end
|
129
172
|
|
130
173
|
# Extensions to the Range class
|
@@ -202,6 +245,29 @@ class ::String
|
|
202
245
|
warning "unknown :a_href option #{val} passed to ircify_html" if val
|
203
246
|
end
|
204
247
|
|
248
|
+
# If opts[:img] is defined, it should be a String. Each image
|
249
|
+
# will be replaced by the string itself, replacing occurrences of
|
250
|
+
# %{alt} %{dimensions} and %{src} with the alt text, image dimensions
|
251
|
+
# and URL
|
252
|
+
if val = opts[:img]
|
253
|
+
if val.kind_of? String
|
254
|
+
txt.gsub!(/<img\s+(.*?)\s*\/?>/) do |imgtag|
|
255
|
+
attrs = Hash.new
|
256
|
+
imgtag.scan(/([[:alpha:]]+)\s*=\s*(['"])?(.*?)\2/) do |key, quote, value|
|
257
|
+
k = key.downcase.intern rescue 'junk'
|
258
|
+
attrs[k] = value
|
259
|
+
end
|
260
|
+
attrs[:alt] ||= attrs[:title]
|
261
|
+
attrs[:width] ||= '...'
|
262
|
+
attrs[:height] ||= '...'
|
263
|
+
attrs[:dimensions] ||= "#{attrs[:width]}x#{attrs[:height]}"
|
264
|
+
val % attrs
|
265
|
+
end
|
266
|
+
else
|
267
|
+
warning ":img option is not a string"
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
205
271
|
# Paragraph and br tags are converted to whitespace
|
206
272
|
txt.gsub!(/<\/?(p|br)(?:\s+[^>]*)?\s*\/?\s*>/i, ' ')
|
207
273
|
txt.gsub!("\n", ' ')
|
@@ -283,6 +349,16 @@ class ::String
|
|
283
349
|
def ircify_html_title
|
284
350
|
self.get_html_title.ircify_html rescue nil
|
285
351
|
end
|
352
|
+
|
353
|
+
# This method is used to wrap a nonempty String by adding
|
354
|
+
# the prefix and postfix
|
355
|
+
def wrap_nonempty(pre, post, opts={})
|
356
|
+
if self.empty?
|
357
|
+
String.new
|
358
|
+
else
|
359
|
+
"#{pre}#{self}#{post}"
|
360
|
+
end
|
361
|
+
end
|
286
362
|
end
|
287
363
|
|
288
364
|
|
@@ -148,6 +148,53 @@ module ::Irc
|
|
148
148
|
|
149
149
|
register_filter(:identity) { |stream| stream }
|
150
150
|
end
|
151
|
+
|
152
|
+
module Plugins
|
153
|
+
class BotModule
|
154
|
+
# read accessor for the default filter group for this BotModule
|
155
|
+
def filter_group
|
156
|
+
@filter_group ||= name
|
157
|
+
end
|
158
|
+
|
159
|
+
# write accessor for the default filter group for this BotModule
|
160
|
+
def filter_group=(name)
|
161
|
+
@filter_group = name
|
162
|
+
end
|
163
|
+
|
164
|
+
# define a filter defaulting to the default filter group
|
165
|
+
# for this BotModule
|
166
|
+
def define_filter(filter, &block)
|
167
|
+
@bot.register_filter(filter, self.filter_group, &block)
|
168
|
+
end
|
169
|
+
|
170
|
+
# load filters associated with the BotModule by looking in
|
171
|
+
# the path(s) specified by the :path option, defaulting to
|
172
|
+
# * Config::datadir/filters/<name>.rb
|
173
|
+
# * botclass/filters/<name>.rb
|
174
|
+
# (note that as <name> we use #dirname() rather than #name(),
|
175
|
+
# since we're looking for datafiles; this is only relevant
|
176
|
+
# for the very few plugins whose dirname differs from name)
|
177
|
+
def load_filters(options={})
|
178
|
+
case options[:path]
|
179
|
+
when nil
|
180
|
+
file = "#{self.dirname}.rb"
|
181
|
+
paths = [
|
182
|
+
File.join(Config::datadir, 'filters', file),
|
183
|
+
@bot.path('filters', file)
|
184
|
+
]
|
185
|
+
when Array
|
186
|
+
paths = options[:path]
|
187
|
+
else
|
188
|
+
paths = [options[:path]]
|
189
|
+
end
|
190
|
+
|
191
|
+
paths.each do |file|
|
192
|
+
instance_eval(File.read(file), file) if File.exist?(file)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
151
198
|
end
|
152
199
|
end
|
153
200
|
|
@@ -25,7 +25,7 @@ require 'zlib'
|
|
25
25
|
module ::Net
|
26
26
|
class HTTPResponse
|
27
27
|
attr_accessor :no_cache
|
28
|
-
|
28
|
+
unless method_defined? :raw_body
|
29
29
|
alias :raw_body :body
|
30
30
|
end
|
31
31
|
|
@@ -99,7 +99,7 @@ module ::Net
|
|
99
99
|
end
|
100
100
|
when 'deflate'
|
101
101
|
debug "inflating body"
|
102
|
-
# From http://www.koders.com/ruby/fid927B4382397E5115AC0ABE21181AB5C1CBDD5C17.aspx?s=thread:
|
102
|
+
# From http://www.koders.com/ruby/fid927B4382397E5115AC0ABE21181AB5C1CBDD5C17.aspx?s=thread:
|
103
103
|
# -MAX_WBITS stops zlib from looking for a zlib header
|
104
104
|
inflater = Zlib::Inflate.new(-Zlib::MAX_WBITS)
|
105
105
|
begin
|
@@ -190,7 +190,7 @@ class HttpUtil
|
|
190
190
|
Bot::Config.register Bot::Config::IntegerValue.new('http.max_cache_time',
|
191
191
|
:default => 60*24,
|
192
192
|
:desc => "After how many minutes since first use a cached document is considered to be expired")
|
193
|
-
Bot::Config.register Bot::Config::
|
193
|
+
Bot::Config.register Bot::Config::BooleanValue.new('http.no_expire_cache',
|
194
194
|
:default => false,
|
195
195
|
:desc => "Set this to true if you want the bot to never expire the cached pages")
|
196
196
|
Bot::Config.register Bot::Config::IntegerValue.new('http.info_bytes',
|
@@ -389,7 +389,7 @@ class HttpUtil
|
|
389
389
|
end
|
390
390
|
end
|
391
391
|
|
392
|
-
h = Net::HTTP.new(uri.host, uri.port, proxy_host, proxy_port, proxy_user,
|
392
|
+
h = Net::HTTP.new(uri.host, uri.port, proxy_host, proxy_port, proxy_user, proxy_pass)
|
393
393
|
h.use_ssl = true if uri.scheme == "https"
|
394
394
|
|
395
395
|
h.read_timeout = opts[:read_timeout]
|
@@ -482,6 +482,14 @@ class HttpUtil
|
|
482
482
|
#
|
483
483
|
def get_response(uri_or_s, options = {}, &block) # :yields: resp
|
484
484
|
uri = uri_or_s.kind_of?(URI) ? uri_or_s : URI.parse(uri_or_s.to_s)
|
485
|
+
unless URI::HTTP === uri
|
486
|
+
if uri.scheme
|
487
|
+
raise "#{uri.scheme.inspect} URI scheme is not supported"
|
488
|
+
else
|
489
|
+
raise "don't know what to do with #{uri.to_s.inspect}"
|
490
|
+
end
|
491
|
+
end
|
492
|
+
|
485
493
|
opts = {
|
486
494
|
:max_redir => @bot.config['http.max_redir'],
|
487
495
|
:yield => :final,
|
@@ -490,7 +498,6 @@ class HttpUtil
|
|
490
498
|
}.merge(options)
|
491
499
|
|
492
500
|
resp = nil
|
493
|
-
cached = nil
|
494
501
|
|
495
502
|
req_class = case opts[:method].to_s.downcase.intern
|
496
503
|
when :head, :"net::http::head"
|
@@ -524,7 +531,9 @@ class HttpUtil
|
|
524
531
|
|
525
532
|
debug "get_response(#{uri}, #{opts.inspect})"
|
526
533
|
|
527
|
-
|
534
|
+
cached = @cache[cache_key]
|
535
|
+
|
536
|
+
if opts[:cache] && cached
|
528
537
|
debug "got cached"
|
529
538
|
if !cached.expired?
|
530
539
|
debug "using cached"
|
@@ -537,7 +546,10 @@ class HttpUtil
|
|
537
546
|
headers['Range'] = opts[:range] if opts[:range]
|
538
547
|
headers['Authorization'] = opts[:auth_head] if opts[:auth_head]
|
539
548
|
|
540
|
-
|
549
|
+
if opts[:cache] && cached && (req_class == Net::HTTP::Get)
|
550
|
+
cached.setup_headers headers
|
551
|
+
end
|
552
|
+
|
541
553
|
req = req_class.new(uri.request_uri, headers)
|
542
554
|
if uri.user && uri.password
|
543
555
|
req.basic_auth(uri.user, uri.password)
|
@@ -547,22 +559,23 @@ class HttpUtil
|
|
547
559
|
debug "prepared request: #{req.to_hash.inspect}"
|
548
560
|
|
549
561
|
begin
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
562
|
+
get_proxy(uri, opts).start do |http|
|
563
|
+
http.request(req) do |resp|
|
564
|
+
resp['x-rbot-location'] = uri.to_s
|
565
|
+
if Net::HTTPNotModified === resp
|
566
|
+
debug "not modified"
|
567
|
+
begin
|
568
|
+
cached.revalidate(resp)
|
569
|
+
rescue Exception => e
|
570
|
+
error e
|
571
|
+
end
|
572
|
+
debug "reusing cached"
|
573
|
+
resp = cached.response
|
574
|
+
elsif Net::HTTPServerError === resp || Net::HTTPClientError === resp
|
575
|
+
debug "http error, deleting cached obj" if cached
|
576
|
+
@cache.delete(cache_key)
|
559
577
|
end
|
560
|
-
|
561
|
-
resp = cached.response
|
562
|
-
elsif Net::HTTPServerError === resp || Net::HTTPClientError === resp
|
563
|
-
debug "http error, deleting cached obj" if cached
|
564
|
-
@cache.delete(cache_key)
|
565
|
-
elsif opts[:cache]
|
578
|
+
|
566
579
|
begin
|
567
580
|
return handle_response(uri, resp, opts, &block)
|
568
581
|
ensure
|
@@ -571,11 +584,8 @@ class HttpUtil
|
|
571
584
|
@cache[cache_key] = cached
|
572
585
|
end
|
573
586
|
end
|
574
|
-
return ret
|
575
587
|
end
|
576
|
-
return handle_response(uri, resp, opts, &block)
|
577
588
|
end
|
578
|
-
end
|
579
589
|
rescue Exception => e
|
580
590
|
error e
|
581
591
|
raise e.message
|
@@ -630,7 +640,7 @@ class HttpUtil
|
|
630
640
|
opts = {:method => :post, :body => data, :cache => false}.merge(options)
|
631
641
|
begin
|
632
642
|
resp = get_response(uri, opts, &block)
|
633
|
-
raise 'http error' unless Net::HTTPOK === resp
|
643
|
+
raise 'http error' unless Net::HTTPOK === resp or Net::HTTPCreated === resp
|
634
644
|
return resp
|
635
645
|
rescue Exception => e
|
636
646
|
error e
|
@@ -0,0 +1,193 @@
|
|
1
|
+
#-- vim:sw=2:et
|
2
|
+
#++
|
3
|
+
#
|
4
|
+
# :title: rbot time parsing utilities
|
5
|
+
#
|
6
|
+
# Author:: Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com>
|
7
|
+
#
|
8
|
+
# These routines read a string and return the number of seconds they
|
9
|
+
# represent.
|
10
|
+
|
11
|
+
module ::Irc
|
12
|
+
module Utils
|
13
|
+
module ParseTime
|
14
|
+
FLOAT_RX = /((?:\d*\.)?\d+)/
|
15
|
+
|
16
|
+
ONE_TO_NINE = {
|
17
|
+
:one => 1,
|
18
|
+
:two => 2,
|
19
|
+
:three => 3,
|
20
|
+
:four => 4,
|
21
|
+
:five => 5,
|
22
|
+
:six => 6,
|
23
|
+
:seven => 7,
|
24
|
+
:eight => 8,
|
25
|
+
:nine => 9,
|
26
|
+
}
|
27
|
+
|
28
|
+
ONE_TO_NINE_RX = Regexp.new ONE_TO_NINE.keys.join('|')
|
29
|
+
|
30
|
+
TEENS_ETC = {
|
31
|
+
:an => 1,
|
32
|
+
:a => 1,
|
33
|
+
:ten => 10,
|
34
|
+
:eleven => 11,
|
35
|
+
:twelve => 12,
|
36
|
+
:thirteen => 13,
|
37
|
+
:fourteen => 14,
|
38
|
+
:fifteen => 15,
|
39
|
+
:sixteen => 16,
|
40
|
+
:seventeen => 17,
|
41
|
+
:eighteen => 18,
|
42
|
+
:nineteen => 19,
|
43
|
+
}
|
44
|
+
|
45
|
+
TEENS_ETC_RX = Regexp.new TEENS_ETC.keys.join('|')
|
46
|
+
|
47
|
+
ENTIES = {
|
48
|
+
:twenty => 20,
|
49
|
+
:thirty => 30,
|
50
|
+
:forty => 40,
|
51
|
+
:fifty => 50,
|
52
|
+
:sixty => 60,
|
53
|
+
}
|
54
|
+
|
55
|
+
ENTIES_RX = Regexp.new ENTIES.keys.join('|')
|
56
|
+
|
57
|
+
LITNUM_RX = /(#{ONE_TO_NINE_RX})|(#{TEENS_ETC_RX})|(#{ENTIES_RX})\s*(#{ONE_TO_NINE_RX})?/
|
58
|
+
|
59
|
+
FRACTIONS = {
|
60
|
+
:"half" => 0.5,
|
61
|
+
:"half a" => 0.5,
|
62
|
+
:"half an" => 0.5,
|
63
|
+
:"a half" => 0.5,
|
64
|
+
:"a quarter" => 0.25,
|
65
|
+
:"a quarter of" => 0.25,
|
66
|
+
:"a quarter of a" => 0.25,
|
67
|
+
:"a quarter of an" => 0.25,
|
68
|
+
:"three quarter" => 0.75,
|
69
|
+
:"three quarters" => 0.75,
|
70
|
+
:"three quarter of" => 0.75,
|
71
|
+
:"three quarters of" => 0.75,
|
72
|
+
:"three quarter of a" => 0.75,
|
73
|
+
:"three quarters of a" => 0.75,
|
74
|
+
:"three quarter of an" => 0.75,
|
75
|
+
:"three quarters of an" => 0.75,
|
76
|
+
}
|
77
|
+
|
78
|
+
FRACTION_RX = Regexp.new FRACTIONS.keys.join('|')
|
79
|
+
|
80
|
+
UNITSPEC_RX = /(years?|months?|s(?:ec(?:ond)?s?)?|m(?:in(?:ute)?s?)?|h(?:(?:ou)?rs?)?|d(?:ays?)?|weeks?)/
|
81
|
+
|
82
|
+
# str must much UNITSPEC_RX
|
83
|
+
def ParseTime.time_unit(str)
|
84
|
+
case str[0,1].intern
|
85
|
+
when :s
|
86
|
+
1
|
87
|
+
when :m
|
88
|
+
if str[1,1] == 'o'
|
89
|
+
# months
|
90
|
+
3600*24*30
|
91
|
+
else
|
92
|
+
#minutes
|
93
|
+
60
|
94
|
+
end
|
95
|
+
when :h
|
96
|
+
3600
|
97
|
+
when :d
|
98
|
+
3600*24
|
99
|
+
when :w
|
100
|
+
3600*24*7
|
101
|
+
when :y
|
102
|
+
3600*24*365
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# example: half an hour, two and a half weeks, 5 seconds, an hour and 5 minutes
|
107
|
+
def ParseTime.parse_period(str)
|
108
|
+
clean = str.gsub(/\s+/, ' ').strip
|
109
|
+
|
110
|
+
sofar = 0
|
111
|
+
until clean.empty?
|
112
|
+
if clean.sub!(/^(#{FRACTION_RX})\s+#{UNITSPEC_RX}/, '')
|
113
|
+
# fraction followed by unit
|
114
|
+
num = FRACTIONS[$1.intern]
|
115
|
+
unit = ParseTime.time_unit($2)
|
116
|
+
elsif clean.sub!(/^#{FLOAT_RX}\s*(?:\s+and\s+(#{FRACTION_RX})\s+)?#{UNITSPEC_RX}/, '')
|
117
|
+
# float plus optional fraction followed by unit
|
118
|
+
num = $1.to_f
|
119
|
+
frac = $2
|
120
|
+
unit = ParseTime.time_unit($3)
|
121
|
+
clean.strip!
|
122
|
+
if frac.nil? and clean.sub!(/^and\s+(#{FRACTION_RX})/, '')
|
123
|
+
frac = $1
|
124
|
+
end
|
125
|
+
if frac
|
126
|
+
num += FRACTIONS[frac.intern]
|
127
|
+
end
|
128
|
+
elsif clean.sub!(/^(?:#{LITNUM_RX})\s+(?:and\s+(#{FRACTION_RX})\s+)?#{UNITSPEC_RX}/, '')
|
129
|
+
if $1
|
130
|
+
num = ONE_TO_NINE[$1.intern]
|
131
|
+
elsif $2
|
132
|
+
num = TEENS_ETC[$2.intern]
|
133
|
+
elsif $3
|
134
|
+
num = ENTIES[$3.intern]
|
135
|
+
if $4
|
136
|
+
num += ONE_TO_NINE[$4.intern]
|
137
|
+
end
|
138
|
+
end
|
139
|
+
frac = $5
|
140
|
+
unit = ParseTime.time_unit($6)
|
141
|
+
clean.strip!
|
142
|
+
if frac.nil? and clean.sub!(/^and\s+(#{FRACTION_RX})/, '')
|
143
|
+
frac = $1
|
144
|
+
end
|
145
|
+
if frac
|
146
|
+
num += FRACTIONS[frac.intern]
|
147
|
+
end
|
148
|
+
else
|
149
|
+
raise "invalid time string: #{clean} (parsed #{sofar} so far)"
|
150
|
+
end
|
151
|
+
sofar += num * unit
|
152
|
+
clean.sub!(/^and\s+/, '')
|
153
|
+
end
|
154
|
+
return sofar
|
155
|
+
end
|
156
|
+
|
157
|
+
# TODO 'at hh:mm:ss', 'next week, 'tomorrow', 'saturday' etc
|
158
|
+
end
|
159
|
+
|
160
|
+
def Utils.parse_time_offset(str)
|
161
|
+
case str
|
162
|
+
when /^(\d+):(\d+)(?:\:(\d+))?$/ # TODO refactor
|
163
|
+
hour = $1.to_i
|
164
|
+
min = $2.to_i
|
165
|
+
sec = $3.to_i
|
166
|
+
now = Time.now
|
167
|
+
later = Time.mktime(now.year, now.month, now.day, hour, min, sec)
|
168
|
+
|
169
|
+
# if the given hour is earlier than current hour, given timestr
|
170
|
+
# must have been meant to be in the future
|
171
|
+
if hour < now.hour || hour <= now.hour && min < now.min
|
172
|
+
later += 60*60*24
|
173
|
+
end
|
174
|
+
|
175
|
+
return later - now
|
176
|
+
when /^(\d+):(\d+)(am|pm)$/ # TODO refactor
|
177
|
+
hour = $1.to_i
|
178
|
+
min = $2.to_i
|
179
|
+
ampm = $3
|
180
|
+
if ampm == "pm"
|
181
|
+
hour += 12
|
182
|
+
end
|
183
|
+
now = Time.now
|
184
|
+
later = Time.mktime(now.year, now.month, now.day, hour, min, now.sec)
|
185
|
+
return later - now
|
186
|
+
else
|
187
|
+
ParseTime.parse_period(str)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|