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
@@ -16,15 +16,6 @@ require 'set'
|
|
16
16
|
begin
|
17
17
|
require 'htmlentities'
|
18
18
|
rescue LoadError
|
19
|
-
gems = nil
|
20
|
-
begin
|
21
|
-
gems = require 'rubygems'
|
22
|
-
rescue LoadError
|
23
|
-
gems = false
|
24
|
-
end
|
25
|
-
if gems
|
26
|
-
retry
|
27
|
-
else
|
28
19
|
module ::Irc
|
29
20
|
module Utils
|
30
21
|
UNESCAPE_TABLE = {
|
@@ -108,7 +99,6 @@ rescue LoadError
|
|
108
99
|
}
|
109
100
|
end
|
110
101
|
end
|
111
|
-
end
|
112
102
|
end
|
113
103
|
|
114
104
|
begin
|
@@ -121,15 +111,6 @@ begin
|
|
121
111
|
end
|
122
112
|
end
|
123
113
|
rescue LoadError
|
124
|
-
gems = nil
|
125
|
-
begin
|
126
|
-
gems = require 'rubygems'
|
127
|
-
rescue LoadError
|
128
|
-
gems = false
|
129
|
-
end
|
130
|
-
if gems
|
131
|
-
retry
|
132
|
-
else
|
133
114
|
module ::Irc
|
134
115
|
module Utils
|
135
116
|
# Some regular expressions to manage HTML data
|
@@ -150,7 +131,6 @@ rescue LoadError
|
|
150
131
|
AFTER_PAR2_REGEX = /<br(?:\s+[^>]*)?\/?>.*?<\/?(?:br|p|div|html|body|table|td|tr)(?:\s+[^>]*)?\/?>/im
|
151
132
|
end
|
152
133
|
end
|
153
|
-
end
|
154
134
|
end
|
155
135
|
|
156
136
|
module ::Irc
|
@@ -169,7 +149,7 @@ module ::Irc
|
|
169
149
|
def Utils.bot=(b)
|
170
150
|
debug "initializing utils"
|
171
151
|
@@bot = b
|
172
|
-
@@safe_save_dir =
|
152
|
+
@@safe_save_dir = @@bot.path('safe_save')
|
173
153
|
end
|
174
154
|
|
175
155
|
|
@@ -179,10 +159,12 @@ module ::Irc
|
|
179
159
|
SEC_PER_HR = SEC_PER_MIN * 60
|
180
160
|
# Seconds per day
|
181
161
|
SEC_PER_DAY = SEC_PER_HR * 24
|
162
|
+
# Seconds per week
|
163
|
+
SEC_PER_WK = SEC_PER_DAY * 7
|
182
164
|
# Seconds per (30-day) month
|
183
165
|
SEC_PER_MNTH = SEC_PER_DAY * 30
|
184
|
-
# Second per (
|
185
|
-
SEC_PER_YR =
|
166
|
+
# Second per (non-leap) year
|
167
|
+
SEC_PER_YR = SEC_PER_DAY * 365
|
186
168
|
|
187
169
|
# Auxiliary method needed by Utils.secs_to_string
|
188
170
|
def Utils.secs_to_string_case(array, var, string, plural)
|
@@ -244,44 +226,54 @@ module ::Irc
|
|
244
226
|
# :date_format, used with <tt>to_formatted_s<tt>, default to :default
|
245
227
|
def Utils.timeago(time, options = {})
|
246
228
|
start_date = options.delete(:start_date) || Time.new
|
247
|
-
date_format = options.delete(:date_format) ||
|
248
|
-
|
249
|
-
if
|
250
|
-
|
251
|
-
|
229
|
+
date_format = options.delete(:date_format) || "%x"
|
230
|
+
delta = (start_date - time).round
|
231
|
+
if delta.abs < 2
|
232
|
+
_("right now")
|
233
|
+
else
|
234
|
+
distance = Utils.age_string(delta)
|
235
|
+
if delta < 0
|
252
236
|
_("%{d} from now") % {:d => distance}
|
253
237
|
else
|
254
238
|
_("%{d} ago") % {:d => distance}
|
255
239
|
end
|
256
|
-
else
|
257
|
-
return _("on %{date}") % {:date => system_date.to_formatted_s(date_format)}
|
258
240
|
end
|
259
241
|
end
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
when
|
266
|
-
|
267
|
-
when
|
268
|
-
_("%{m}
|
269
|
-
when
|
270
|
-
_("
|
271
|
-
when
|
272
|
-
_("%{m}
|
273
|
-
when
|
274
|
-
_("
|
275
|
-
when
|
276
|
-
_("
|
242
|
+
|
243
|
+
# Converts age in seconds to "nn units". Inspired by previous attempts
|
244
|
+
# but also gitweb's age_string() sub
|
245
|
+
def Utils.age_string(secs)
|
246
|
+
case
|
247
|
+
when secs < 0
|
248
|
+
Utils.age_string(-secs)
|
249
|
+
when secs > 2*SEC_PER_YR
|
250
|
+
_("%{m} years") % { :m => secs/SEC_PER_YR }
|
251
|
+
when secs > 2*SEC_PER_MNTH
|
252
|
+
_("%{m} months") % { :m => secs/SEC_PER_MNTH }
|
253
|
+
when secs > 2*SEC_PER_WK
|
254
|
+
_("%{m} weeks") % { :m => secs/SEC_PER_WK }
|
255
|
+
when secs > 2*SEC_PER_DAY
|
256
|
+
_("%{m} days") % { :m => secs/SEC_PER_DAY }
|
257
|
+
when secs > 2*SEC_PER_HR
|
258
|
+
_("%{m} hours") % { :m => secs/SEC_PER_HR }
|
259
|
+
when (20*SEC_PER_MIN..40*SEC_PER_MIN).include?(secs)
|
260
|
+
_("half an hour")
|
261
|
+
when (50*SEC_PER_MIN..70*SEC_PER_MIN).include?(secs)
|
262
|
+
# _("about one hour")
|
263
|
+
_("an hour")
|
264
|
+
when (80*SEC_PER_MIN..100*SEC_PER_MIN).include?(secs)
|
265
|
+
_("an hour and a half")
|
266
|
+
when secs > 2*SEC_PER_MIN
|
267
|
+
_("%{m} minutes") % { :m => secs/SEC_PER_MIN }
|
268
|
+
when secs > 1
|
269
|
+
_("%{m} seconds") % { :m => secs }
|
277
270
|
else
|
278
|
-
_("
|
271
|
+
_("one second")
|
272
|
+
end
|
279
273
|
end
|
280
|
-
end
|
281
|
-
|
282
274
|
|
283
275
|
# Execute an external program, returning a String obtained by redirecting
|
284
|
-
# the program's standards errors and output
|
276
|
+
# the program's standards errors and output
|
285
277
|
#
|
286
278
|
def Utils.safe_exec(command, *args)
|
287
279
|
IO.popen("-") { |p|
|
@@ -292,15 +284,34 @@ module ::Irc
|
|
292
284
|
$stderr.reopen($stdout)
|
293
285
|
exec(command, *args)
|
294
286
|
rescue Exception => e
|
295
|
-
puts "
|
296
|
-
Kernel::exit!
|
287
|
+
puts "exception #{e.pretty_inspect} trying to run #{command}"
|
288
|
+
Kernel::exit! 1
|
297
289
|
end
|
298
290
|
puts "exec of #{command} failed"
|
299
|
-
Kernel::exit!
|
291
|
+
Kernel::exit! 1
|
300
292
|
end
|
301
293
|
}
|
302
294
|
end
|
303
295
|
|
296
|
+
# Try executing an external program, returning true if the run was successful
|
297
|
+
# and false otherwise
|
298
|
+
def Utils.try_exec(command, *args)
|
299
|
+
IO.popen("-") { |p|
|
300
|
+
if p.nil?
|
301
|
+
begin
|
302
|
+
$stderr.reopen($stdout)
|
303
|
+
exec(command, *args)
|
304
|
+
rescue Exception => e
|
305
|
+
Kernel::exit! 1
|
306
|
+
end
|
307
|
+
Kernel::exit! 1
|
308
|
+
else
|
309
|
+
debug p.readlines
|
310
|
+
end
|
311
|
+
}
|
312
|
+
debug $?
|
313
|
+
return $?.success?
|
314
|
+
end
|
304
315
|
|
305
316
|
# Safely (atomically) save to _file_, by passing a tempfile to the block
|
306
317
|
# and then moving the tempfile to its final location when done.
|
@@ -620,7 +631,7 @@ module ::Irc
|
|
620
631
|
# returns non-nil, its results are merged in _ds_ and returned. Otherwise
|
621
632
|
# nil is returned.
|
622
633
|
#
|
623
|
-
# The input DataStream
|
634
|
+
# The input DataStream should have the downloaded HTML as primary key
|
624
635
|
# (:text) and possibly a :headers key holding the resonse headers.
|
625
636
|
#
|
626
637
|
def Utils.try_htmlinfo_filters(ds)
|
@@ -629,7 +640,7 @@ module ::Irc
|
|
629
640
|
cur = nil
|
630
641
|
# TODO filter priority
|
631
642
|
filters.each { |n|
|
632
|
-
debug "testing filter #{n}"
|
643
|
+
debug "testing htmlinfo filter #{n}"
|
633
644
|
cur = @@bot.filter(@@bot.global_filter_name(n, :htmlinfo), ds)
|
634
645
|
debug "returned #{cur.pretty_inspect}"
|
635
646
|
break if cur
|
@@ -711,6 +722,20 @@ module ::Irc
|
|
711
722
|
return retval
|
712
723
|
end
|
713
724
|
|
725
|
+
# Returns a comma separated list except for the last element
|
726
|
+
# which is joined in with specified conjunction
|
727
|
+
#
|
728
|
+
def Utils.comma_list(words, options={})
|
729
|
+
defaults = { :join_with => ", ", :join_last_with => _(" and ") }
|
730
|
+
opts = defaults.merge(options)
|
731
|
+
|
732
|
+
if words.size < 2
|
733
|
+
words.last
|
734
|
+
else
|
735
|
+
[words[0..-2].join(opts[:join_with]), words.last].join(opts[:join_last_with])
|
736
|
+
end
|
737
|
+
end
|
738
|
+
|
714
739
|
end
|
715
740
|
end
|
716
741
|
|
@@ -0,0 +1,66 @@
|
|
1
|
+
#-- vim:sw=2:et
|
2
|
+
#++
|
3
|
+
#
|
4
|
+
# :title: rbot wordlist provider
|
5
|
+
#
|
6
|
+
# Author:: Raine Virta <rane@kapsi.fi>
|
7
|
+
|
8
|
+
require "find"
|
9
|
+
|
10
|
+
module ::Irc
|
11
|
+
class Bot
|
12
|
+
class Wordlist
|
13
|
+
def self.wordlist_base
|
14
|
+
@@wordlist_base ||= Utils.bot.path 'wordlists'
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.get(path, options={})
|
18
|
+
opts = { :spaces => false }.merge(options)
|
19
|
+
|
20
|
+
wordlist_path = File.join(wordlist_base, path)
|
21
|
+
raise "wordlist not found: #{wordlist_path}" unless File.exist?(wordlist_path)
|
22
|
+
|
23
|
+
# Location is a directory -> combine all lists beneath it
|
24
|
+
wordlist = if File.directory?(wordlist_path)
|
25
|
+
wordlists = []
|
26
|
+
Find.find(wordlist_path) do |path|
|
27
|
+
next if path == wordlist_path
|
28
|
+
wordlists << path unless File.directory?(path)
|
29
|
+
end
|
30
|
+
|
31
|
+
wordlists.map { |list| File.readlines(list) }.flatten
|
32
|
+
else
|
33
|
+
File.readlines(wordlist_path)
|
34
|
+
end
|
35
|
+
|
36
|
+
# wordlists are assumed to be UTF-8, but we need to strip the BOM, if present
|
37
|
+
wordlist.map! { |l| l.sub("\xef\xbb\xbf",'').strip }
|
38
|
+
wordlist.reject do |word|
|
39
|
+
word =~ /\s/ && !opts[:spaces] ||
|
40
|
+
word.empty?
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Return an array with the list of available wordlists.
|
45
|
+
# Available options:
|
46
|
+
# pattern:: pattern that should be matched by the wordlist filename
|
47
|
+
def self.list(options={})
|
48
|
+
pattern = options[:pattern] || "**"
|
49
|
+
# refuse patterns that contain ../
|
50
|
+
return [] if pattern =~ /\.\.\//
|
51
|
+
striplen = self.wordlist_base.length+1
|
52
|
+
Dir.glob(File.join(self.wordlist_base, pattern)).map { |name|
|
53
|
+
name[striplen..-1]
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.exist?(path)
|
58
|
+
fn = path.to_s
|
59
|
+
# refuse to check outside of the wordlist base directory
|
60
|
+
return false if fn =~ /\.\.\//
|
61
|
+
File.exist?(File.join(self.wordlist_base, fn))
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#-- vim:sw=2:et
|
2
|
+
#++
|
3
|
+
#
|
4
|
+
# :title: wordlist management from IRC
|
5
|
+
#
|
6
|
+
# Author:: Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com>
|
7
|
+
|
8
|
+
class WordlistModule < CoreBotModule
|
9
|
+
def help(plugin, topic="")
|
10
|
+
_("wordlist list [<pattern>] => list wordlists (matching <pattern>)")
|
11
|
+
end
|
12
|
+
|
13
|
+
def do_list(m, p)
|
14
|
+
found = Wordlist.list(p)
|
15
|
+
if found.empty?
|
16
|
+
m.reply _("no wordlist found")
|
17
|
+
else
|
18
|
+
m.reply _("Wordlists: %{found}") % {
|
19
|
+
:found => found.sort.join(', ')
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
plugin = WordlistModule.new
|
26
|
+
|
27
|
+
plugin.map "wordlist list [:pattern]", :action => :do_list
|
data/lib/rbot/irc.rb
CHANGED
@@ -21,6 +21,21 @@
|
|
21
21
|
|
22
22
|
require 'singleton'
|
23
23
|
|
24
|
+
# The following monkeypatch is to fix a bug in Singleton where marshaling would
|
25
|
+
# fail when trying to restore a marshaled Singleton due to _load being declared
|
26
|
+
# private.
|
27
|
+
if RUBY_VERSION < '1.9'
|
28
|
+
module ::Singleton
|
29
|
+
public :_dump
|
30
|
+
end
|
31
|
+
|
32
|
+
class << Singleton
|
33
|
+
module SingletonClassMethods
|
34
|
+
public :_load
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
24
39
|
class Object
|
25
40
|
|
26
41
|
# We extend the Object class with a method that
|
@@ -33,7 +48,7 @@ class Object
|
|
33
48
|
|
34
49
|
# We alias the to_s method to __to_s__ to make
|
35
50
|
# it accessible in all classes
|
36
|
-
alias :__to_s__ :to_s
|
51
|
+
alias :__to_s__ :to_s
|
37
52
|
end
|
38
53
|
|
39
54
|
# The Irc module is used to keep all IRC-related classes
|
@@ -129,7 +144,7 @@ module Irc
|
|
129
144
|
include Singleton
|
130
145
|
|
131
146
|
def initialize
|
132
|
-
super('rfc1459', "\x41-\
|
147
|
+
super('rfc1459', "\x41-\x5a\x7b-\x7e", "\x61-\x7a\x5b-\x5e")
|
133
148
|
end
|
134
149
|
|
135
150
|
end
|
@@ -141,7 +156,7 @@ module Irc
|
|
141
156
|
include Singleton
|
142
157
|
|
143
158
|
def initialize
|
144
|
-
super('strict-rfc1459', "\x41-\
|
159
|
+
super('strict-rfc1459', "\x41-\x5a\x7b-\x7d", "\x61-\x7a\x5b-\x5d")
|
145
160
|
end
|
146
161
|
|
147
162
|
end
|
@@ -258,7 +273,13 @@ class String
|
|
258
273
|
# This method returns the Irc::Casemap whose name is the receiver
|
259
274
|
#
|
260
275
|
def to_irc_casemap
|
261
|
-
|
276
|
+
begin
|
277
|
+
Irc::Casemap.get(self)
|
278
|
+
rescue
|
279
|
+
# raise TypeError, "Unkown Irc::Casemap #{self.inspect}"
|
280
|
+
error "Unkown Irc::Casemap #{self.inspect} requested, defaulting to rfc1459"
|
281
|
+
Irc::Casemap.get('rfc1459')
|
282
|
+
end
|
262
283
|
end
|
263
284
|
|
264
285
|
# This method returns a string which is the downcased version of the
|
@@ -542,7 +563,7 @@ class Regexp
|
|
542
563
|
GEN_HOST = /#{HOSTNAME}|#{HOSTADDR}/
|
543
564
|
|
544
565
|
# # FreeNode network replaces the host of affiliated users with
|
545
|
-
# # 'virtual hosts'
|
566
|
+
# # 'virtual hosts'
|
546
567
|
# # FIXME we need the true syntax to match it properly ...
|
547
568
|
# PDPC_HOST_PART = /[0-9A-Za-z.-]+/
|
548
569
|
# PDPC_HOST = /#{PDPC_HOST_PART}(?:\/#{PDPC_HOST_PART})+/
|
@@ -550,7 +571,7 @@ class Regexp
|
|
550
571
|
# # NOTE: the final optional and non-greedy dot is needed because some
|
551
572
|
# # servers (e.g. FreeNode) send the hostname of the services as "services."
|
552
573
|
# # which is not RFC compliant, but sadly done.
|
553
|
-
# GEN_HOST_EXT = /#{PDPC_HOST}|#{GEN_HOST}\.??/
|
574
|
+
# GEN_HOST_EXT = /#{PDPC_HOST}|#{GEN_HOST}\.??/
|
554
575
|
|
555
576
|
# Sadly, different networks have different, RFC-breaking ways of cloaking
|
556
577
|
# the actualy host address: see above for an example to handle FreeNode.
|
@@ -1308,6 +1329,13 @@ module Irc
|
|
1308
1329
|
#
|
1309
1330
|
class Channel
|
1310
1331
|
|
1332
|
+
# Return the non-prefixed part of a channel name.
|
1333
|
+
# Also works with ## channels found on some networks
|
1334
|
+
# (e.g. FreeNode)
|
1335
|
+
def self.npname(str)
|
1336
|
+
return str.to_s.sub(/^[&#+!]+/,'')
|
1337
|
+
end
|
1338
|
+
|
1311
1339
|
include ServerOrCasemap
|
1312
1340
|
attr_reader :name, :topic, :mode, :users
|
1313
1341
|
alias :to_s :name
|
@@ -1350,7 +1378,7 @@ module Irc
|
|
1350
1378
|
# Adds a user to the channel
|
1351
1379
|
#
|
1352
1380
|
def add_user(user, opts={})
|
1353
|
-
silent = opts.fetch(:silent, false)
|
1381
|
+
silent = opts.fetch(:silent, false)
|
1354
1382
|
if has_user?(user)
|
1355
1383
|
warn "Trying to add user #{user} to channel #{self} again" unless silent
|
1356
1384
|
else
|
@@ -1366,7 +1394,7 @@ module Irc
|
|
1366
1394
|
#
|
1367
1395
|
def initialize(name, topic=nil, users=[], opts={})
|
1368
1396
|
raise ArgumentError, "Channel name cannot be empty" if name.to_s.empty?
|
1369
|
-
warn "Unknown channel prefix #{name[0]
|
1397
|
+
warn "Unknown channel prefix #{name[0,1]}" if name !~ /^[&#+!]/
|
1370
1398
|
raise ArgumentError, "Invalid character in #{name.inspect}" if name =~ /[ \x07,]/
|
1371
1399
|
|
1372
1400
|
init_server_or_casemap(opts)
|
@@ -1403,31 +1431,31 @@ module Irc
|
|
1403
1431
|
# The channel prefix
|
1404
1432
|
#
|
1405
1433
|
def prefix
|
1406
|
-
name[0]
|
1434
|
+
name[0,1]
|
1407
1435
|
end
|
1408
1436
|
|
1409
1437
|
# A channel is local to a server if it has the '&' prefix
|
1410
1438
|
#
|
1411
1439
|
def local?
|
1412
|
-
name[0] ==
|
1440
|
+
name[0,1] == '&'
|
1413
1441
|
end
|
1414
1442
|
|
1415
1443
|
# A channel is modeless if it has the '+' prefix
|
1416
1444
|
#
|
1417
1445
|
def modeless?
|
1418
|
-
name[0] ==
|
1446
|
+
name[0,1] == '+'
|
1419
1447
|
end
|
1420
1448
|
|
1421
1449
|
# A channel is safe if it has the '!' prefix
|
1422
1450
|
#
|
1423
1451
|
def safe?
|
1424
|
-
name[0] ==
|
1452
|
+
name[0,1] == '!'
|
1425
1453
|
end
|
1426
1454
|
|
1427
1455
|
# A channel is normal if it has the '#' prefix
|
1428
1456
|
#
|
1429
1457
|
def normal?
|
1430
|
-
name[0] ==
|
1458
|
+
name[0,1] == '#'
|
1431
1459
|
end
|
1432
1460
|
|
1433
1461
|
# Create a new mode
|
@@ -1646,7 +1674,7 @@ module Irc
|
|
1646
1674
|
def parse_isupport(line)
|
1647
1675
|
debug "Parsing ISUPPORT #{line.inspect}"
|
1648
1676
|
ar = line.split(' ')
|
1649
|
-
reparse =
|
1677
|
+
reparse = []
|
1650
1678
|
ar.each { |en|
|
1651
1679
|
prekey, val = en.split('=', 2)
|
1652
1680
|
if prekey =~ /^-(.*)/
|
@@ -1658,7 +1686,15 @@ module Irc
|
|
1658
1686
|
case key
|
1659
1687
|
when :casemapping
|
1660
1688
|
noval_warn(key, val) {
|
1661
|
-
|
1689
|
+
if val == 'charset'
|
1690
|
+
reparse << "CASEMAPPING=(charset)"
|
1691
|
+
else
|
1692
|
+
# TODO some servers offer non-standard CASEMAPPINGs in the form
|
1693
|
+
# locale.charset[-options], which indicate an extended set of
|
1694
|
+
# allowed characters (mostly for nicks). This might be supported
|
1695
|
+
# with hooks for the unicode core module
|
1696
|
+
@supports[key] = val.to_irc_casemap
|
1697
|
+
end
|
1662
1698
|
}
|
1663
1699
|
when :chanlimit, :idchan, :maxlist, :targmax
|
1664
1700
|
noval_warn(key, val) {
|
@@ -1696,7 +1732,7 @@ module Irc
|
|
1696
1732
|
@supports[key] = val
|
1697
1733
|
when :maxchannels
|
1698
1734
|
noval_warn(key, val) {
|
1699
|
-
reparse
|
1735
|
+
reparse << "CHANLIMIT=(chantypes):#{val} "
|
1700
1736
|
}
|
1701
1737
|
when :maxtargets
|
1702
1738
|
noval_warn(key, val) {
|
@@ -1737,8 +1773,12 @@ module Irc
|
|
1737
1773
|
@supports[key] = val.nil? ? true : val
|
1738
1774
|
end
|
1739
1775
|
}
|
1740
|
-
reparse.
|
1741
|
-
|
1776
|
+
unless reparse.empty?
|
1777
|
+
reparse_str = reparse.join(" ")
|
1778
|
+
reparse_str.gsub!("(chantypes)",@supports[:chantypes])
|
1779
|
+
reparse_str.gsub!("(charset)",@supports[:charset] || 'rfc1459')
|
1780
|
+
parse_isupport(reparse_str)
|
1781
|
+
end
|
1742
1782
|
end
|
1743
1783
|
|
1744
1784
|
# Returns the casemap of the server.
|
@@ -1803,7 +1843,7 @@ module Irc
|
|
1803
1843
|
return ex
|
1804
1844
|
else
|
1805
1845
|
|
1806
|
-
prefix = name[0]
|
1846
|
+
prefix = name[0,1]
|
1807
1847
|
|
1808
1848
|
# Give a warning if the new Channel goes over some server limits.
|
1809
1849
|
#
|