mod_spox 0.1.0.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +36 -0
- data/INSTALL +2 -2
- data/README +0 -1
- data/bin/mod_spox +51 -12
- data/data/mod_spox/extras/AOLSpeak.rb +5 -18
- data/data/mod_spox/extras/AutoKick.rb +44 -23
- data/data/mod_spox/extras/AutoMode.rb +2 -5
- data/data/mod_spox/extras/AutoRejoin.rb +21 -0
- data/data/mod_spox/extras/Bouncer.rb +10 -10
- data/data/mod_spox/extras/Bytes.rb +12 -0
- data/data/mod_spox/extras/Confess.rb +131 -52
- data/data/mod_spox/extras/DCC.rb +189 -0
- data/data/mod_spox/extras/DevWatch.rb +32 -33
- data/data/mod_spox/extras/FloodKicker.rb +129 -0
- data/data/mod_spox/extras/GoogleIt.rb +13 -0
- data/data/mod_spox/extras/Headers.rb +31 -4
- data/data/mod_spox/extras/Karma.rb +103 -49
- data/data/mod_spox/extras/Logger.rb +45 -30
- data/data/mod_spox/extras/LolSpeak.rb +1 -1
- data/data/mod_spox/extras/NickServ.rb +83 -0
- data/data/mod_spox/extras/PhpCli.rb +12 -15
- data/data/mod_spox/extras/PhpFuncLookup.rb +57 -25
- data/data/mod_spox/extras/Quotes.rb +5 -4
- data/data/mod_spox/extras/RegexTracker.rb +160 -0
- data/data/mod_spox/extras/Roulette.rb +22 -23
- data/data/mod_spox/extras/Search.rb +3 -2
- data/data/mod_spox/extras/Slashdot.rb +35 -0
- data/data/mod_spox/extras/Topten.rb +5 -5
- data/data/mod_spox/extras/TracTicket.rb +68 -0
- data/data/mod_spox/extras/Translate.rb +69 -30
- data/data/mod_spox/extras/Twitter.rb +372 -0
- data/data/mod_spox/extras/UrbanDictionary.rb +21 -12
- data/data/mod_spox/extras/Weather.rb +1 -1
- data/data/mod_spox/plugins/Authenticator.rb +63 -30
- data/data/mod_spox/plugins/Banner.rb +164 -151
- data/data/mod_spox/plugins/Helper.rb +18 -7
- data/data/mod_spox/plugins/PluginLoader.rb +46 -22
- data/data/mod_spox/plugins/PoolConfig.rb +52 -0
- data/data/mod_spox/plugins/Quitter.rb +1 -1
- data/data/mod_spox/plugins/Status.rb +28 -0
- data/lib/mod_spox/Action.rb +20 -3
- data/lib/mod_spox/BaseConfig.rb +1 -0
- data/lib/mod_spox/Bot.rb +98 -75
- data/lib/mod_spox/BotConfig.rb +14 -6
- data/lib/mod_spox/ConfigurationWizard.rb +94 -105
- data/lib/mod_spox/Database.rb +33 -13
- data/lib/mod_spox/Helpers.rb +67 -38
- data/lib/mod_spox/Loader.rb +25 -5
- data/lib/mod_spox/Logger.rb +20 -62
- data/lib/mod_spox/MessageFactory.rb +34 -25
- data/lib/mod_spox/Monitors.rb +5 -0
- data/lib/mod_spox/Pipeline.rb +40 -51
- data/lib/mod_spox/Plugin.rb +40 -9
- data/lib/mod_spox/PluginManager.rb +46 -38
- data/lib/mod_spox/Pool.rb +129 -143
- data/lib/mod_spox/Socket.rb +41 -50
- data/lib/mod_spox/Sockets.rb +211 -0
- data/lib/mod_spox/Timer.rb +86 -69
- data/lib/mod_spox/handlers/BadNick.rb +1 -1
- data/lib/mod_spox/handlers/Created.rb +1 -1
- data/lib/mod_spox/handlers/Handler.rb +9 -0
- data/lib/mod_spox/handlers/Invite.rb +1 -1
- data/lib/mod_spox/handlers/Join.rb +2 -2
- data/lib/mod_spox/handlers/Kick.rb +1 -1
- data/lib/mod_spox/handlers/LuserChannels.rb +1 -1
- data/lib/mod_spox/handlers/LuserOp.rb +1 -1
- data/lib/mod_spox/handlers/LuserUnknown.rb +1 -1
- data/lib/mod_spox/handlers/Mode.rb +2 -2
- data/lib/mod_spox/handlers/MyInfo.rb +1 -1
- data/lib/mod_spox/handlers/Names.rb +1 -1
- data/lib/mod_spox/handlers/Nick.rb +20 -3
- data/lib/mod_spox/handlers/NickInUse.rb +3 -3
- data/lib/mod_spox/handlers/Notice.rb +5 -15
- data/lib/mod_spox/handlers/Part.rb +1 -1
- data/lib/mod_spox/handlers/Ping.rb +1 -1
- data/lib/mod_spox/handlers/Pong.rb +1 -1
- data/lib/mod_spox/handlers/Privmsg.rb +2 -2
- data/lib/mod_spox/handlers/Quit.rb +1 -1
- data/lib/mod_spox/handlers/Topic.rb +2 -1
- data/lib/mod_spox/handlers/Welcome.rb +3 -3
- data/lib/mod_spox/handlers/Who.rb +9 -7
- data/lib/mod_spox/handlers/Whois.rb +29 -16
- data/lib/mod_spox/handlers/YourHost.rb +1 -1
- data/lib/mod_spox/messages/incoming/Privmsg.rb +38 -19
- data/lib/mod_spox/messages/internal/DCCListener.rb +12 -0
- data/lib/mod_spox/messages/internal/DCCRequest.rb +12 -0
- data/lib/mod_spox/messages/internal/DCCSocket.rb +19 -0
- data/lib/mod_spox/messages/internal/StatusRequest.rb +2 -1
- data/lib/mod_spox/messages/outgoing/Privmsg.rb +21 -5
- data/lib/mod_spox/migrations/001_initialize_models.rb +115 -0
- data/lib/mod_spox/models/Auth.rb +24 -16
- data/lib/mod_spox/models/AuthGroup.rb +4 -3
- data/lib/mod_spox/models/Channel.rb +20 -12
- data/lib/mod_spox/models/ChannelMode.rb +2 -2
- data/lib/mod_spox/models/Config.rb +11 -3
- data/lib/mod_spox/models/Group.rb +6 -1
- data/lib/mod_spox/models/Nick.rb +93 -33
- data/lib/mod_spox/models/NickChannel.rb +8 -6
- data/lib/mod_spox/models/NickGroup.rb +16 -0
- data/lib/mod_spox/models/NickMode.rb +3 -3
- data/lib/mod_spox/models/Server.rb +6 -2
- data/lib/mod_spox/models/Setting.rb +12 -6
- data/lib/mod_spox/models/Signature.rb +7 -13
- data/lib/mod_spox/models/Trigger.rb +1 -1
- metadata +125 -100
@@ -1,7 +1,7 @@
|
|
1
1
|
class Roulette < ModSpox::Plugin
|
2
2
|
|
3
3
|
include Models
|
4
|
-
|
4
|
+
|
5
5
|
def initialize(pipeline)
|
6
6
|
super(pipeline)
|
7
7
|
Signature.find_or_create(:signature => 'roulette', :plugin => name, :method => 'roulette', :requirement => 'public')
|
@@ -15,7 +15,7 @@ class Roulette < ModSpox::Plugin
|
|
15
15
|
@banner = nil
|
16
16
|
@pipeline.hook(self, :get_banner, :Internal_PluginResponse)
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
# message:: ModSpox::Messages::Incoming::Privmsg
|
20
20
|
# Display chamber statistics
|
21
21
|
def chambers(m, p)
|
@@ -32,13 +32,13 @@ class Roulette < ModSpox::Plugin
|
|
32
32
|
reply m.replyto, "\2Error:\2 No games found"
|
33
33
|
end
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
# message:: ModSpox::Messages::Internal::PluginResponse
|
37
37
|
# Get the banner plugin
|
38
38
|
def get_banner(message)
|
39
39
|
@banner = message.plugin if message.found?
|
40
40
|
end
|
41
|
-
|
41
|
+
|
42
42
|
# message:: ModSpox::Messages::Incoming::Privmsg
|
43
43
|
# params:: empty
|
44
44
|
# Play roulette
|
@@ -46,7 +46,7 @@ class Roulette < ModSpox::Plugin
|
|
46
46
|
return unless message.is_public?
|
47
47
|
do_shot(message.source, message.target)
|
48
48
|
end
|
49
|
-
|
49
|
+
|
50
50
|
# message:: ModSpox::Messages::Incoming::Privmsg
|
51
51
|
# params:: empty
|
52
52
|
# Kill self
|
@@ -54,7 +54,7 @@ class Roulette < ModSpox::Plugin
|
|
54
54
|
return unless message.is_public?
|
55
55
|
do_suicide(message.source, message.target)
|
56
56
|
end
|
57
|
-
|
57
|
+
|
58
58
|
# message:: ModSpox::Messages::Incoming::Privmsg
|
59
59
|
# params:: nick
|
60
60
|
# Shoot other person playing current game
|
@@ -76,7 +76,6 @@ class Roulette < ModSpox::Plugin
|
|
76
76
|
return unless message.is_public?
|
77
77
|
ds = Database.db[:infos].left_outer_join(:games, :id => :game_id)
|
78
78
|
ds.select!(:nick_id, :COUNT[:win] => :wins).where!(:channel_id => message.target.pk, :win => true).group!(:nick_id).reverse_order!(:wins).limit!(10)
|
79
|
-
Logger.log(ds.sql)
|
80
79
|
ids = ds.map(:nick_id)
|
81
80
|
top = []
|
82
81
|
ids.each do |id|
|
@@ -106,9 +105,9 @@ class Roulette < ModSpox::Plugin
|
|
106
105
|
end
|
107
106
|
reply(message.replyto, "\2Roulette stats #{nick.nick}:\2 #{win_loss_ratio(nick, message.target)}% survival rate. Has won #{games_won(nick, message.target)} games and lost #{games_lost(nick, message.target)} games, taking a total of #{total_shots(nick, message.target)} shots.")
|
108
107
|
end
|
109
|
-
|
108
|
+
|
110
109
|
private
|
111
|
-
|
110
|
+
|
112
111
|
# nick:: ModSpox::Models::Nick
|
113
112
|
# channel:: ModSpox::Models::Channel
|
114
113
|
# Report win/loss ratio for nick
|
@@ -129,7 +128,7 @@ class Roulette < ModSpox::Plugin
|
|
129
128
|
def games_won(nick, channel)
|
130
129
|
Info.left_outer_join(:games, :id => :game_id).filter('nick_id = ?', nick.pk).filter('channel_id = ?', channel.pk).filter('win = ?', true).size
|
131
130
|
end
|
132
|
-
|
131
|
+
|
133
132
|
# nick:: ModSpox::Models::Nick
|
134
133
|
# channel:: ModSpox::Models::Channel
|
135
134
|
# Return number of games nick has lost
|
@@ -155,7 +154,7 @@ class Roulette < ModSpox::Plugin
|
|
155
154
|
|
156
155
|
# nick:: ModSpox::Models::Nick
|
157
156
|
# channel:: ModSpox::Models::Channel
|
158
|
-
# Fire shot
|
157
|
+
# Fire shot
|
159
158
|
def do_shot(nick, channel)
|
160
159
|
begin
|
161
160
|
shot(nick, channel)
|
@@ -165,7 +164,7 @@ class Roulette < ModSpox::Plugin
|
|
165
164
|
kill_nick(nick, channel)
|
166
165
|
end
|
167
166
|
end
|
168
|
-
|
167
|
+
|
169
168
|
# nick:: ModSpox::Models::Nick
|
170
169
|
# channel:: ModSpox::Models::Channel
|
171
170
|
# Commit suicide
|
@@ -179,7 +178,7 @@ class Roulette < ModSpox::Plugin
|
|
179
178
|
kill_nick(nick, channel)
|
180
179
|
end
|
181
180
|
end
|
182
|
-
|
181
|
+
|
183
182
|
def kill_nick(nick, channel)
|
184
183
|
unless(@banner.nil?)
|
185
184
|
begin
|
@@ -188,7 +187,7 @@ class Roulette < ModSpox::Plugin
|
|
188
187
|
reply(channel, "#{nick.nick}: *BANG*")
|
189
188
|
rescue Object => boom
|
190
189
|
reply(channel, "#{nick.nick}: *BANG*")
|
191
|
-
Logger.
|
190
|
+
Logger.warn("Error: Roulette ban generated an unexpected error: #{boom}")
|
192
191
|
end
|
193
192
|
else
|
194
193
|
reply(channel, "#{nick.nick}: *BANG*")
|
@@ -207,7 +206,7 @@ class Roulette < ModSpox::Plugin
|
|
207
206
|
end
|
208
207
|
return game
|
209
208
|
end
|
210
|
-
|
209
|
+
|
211
210
|
# nick:: ModSpox::Models::Nick
|
212
211
|
# channel:: ModSpox::Models::Channel
|
213
212
|
# Process shot
|
@@ -218,7 +217,7 @@ class Roulette < ModSpox::Plugin
|
|
218
217
|
cur_game.update_with_params(:shots => cur_game.shots - 1)
|
219
218
|
raise Bullet.new(cur_game) if cur_game.shots < 1
|
220
219
|
end
|
221
|
-
|
220
|
+
|
222
221
|
# nick:: ModSpox::Models::Nick
|
223
222
|
# game:: Game
|
224
223
|
# Return number of games nick has won
|
@@ -227,7 +226,7 @@ class Roulette < ModSpox::Plugin
|
|
227
226
|
info.update_with_params(:win => true) unless info.nick_id == nick.pk
|
228
227
|
end
|
229
228
|
end
|
230
|
-
|
229
|
+
|
231
230
|
class Game < Sequel::Model
|
232
231
|
set_schema do
|
233
232
|
primary_key :id
|
@@ -236,16 +235,16 @@ class Roulette < ModSpox::Plugin
|
|
236
235
|
integer :chamber, :null => false, :default => 1
|
237
236
|
foreign_key :channel_id, :null => false, :table => :channels
|
238
237
|
end
|
239
|
-
|
238
|
+
|
240
239
|
before_create do
|
241
240
|
self.stamp = Time.now
|
242
241
|
end
|
243
|
-
|
242
|
+
|
244
243
|
def channel
|
245
244
|
Models::Channel[channel_id]
|
246
245
|
end
|
247
246
|
end
|
248
|
-
|
247
|
+
|
249
248
|
class Info < Sequel::Model
|
250
249
|
set_schema do
|
251
250
|
primary_key :id
|
@@ -254,16 +253,16 @@ class Roulette < ModSpox::Plugin
|
|
254
253
|
foreign_key :nick_id, :null => false, :table => :nicks
|
255
254
|
foreign_key :game_id, :null => false, :table => :games
|
256
255
|
end
|
257
|
-
|
256
|
+
|
258
257
|
def nick
|
259
258
|
Models::Nick[nick_id]
|
260
259
|
end
|
261
|
-
|
260
|
+
|
262
261
|
def game
|
263
262
|
Models::Game[game_id]
|
264
263
|
end
|
265
264
|
end
|
266
|
-
|
265
|
+
|
267
266
|
class Bullet < Exception
|
268
267
|
attr_reader :game
|
269
268
|
def initialize(game)
|
@@ -8,12 +8,12 @@ class Search < ModSpox::Plugin
|
|
8
8
|
super(pipeline)
|
9
9
|
Models::Signature.find_or_create(:signature => 'search (\d+)? ?(.+)', :plugin => name, :method => 'search', :description => 'Search the internet').params = [:number, :terms]
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
def search(message, params)
|
13
13
|
limit = params[:number] ? params[:number].to_i : 1
|
14
14
|
limit = limit > 5 || limit < 1 ? 1 : limit
|
15
15
|
begin
|
16
|
-
resp = Net::HTTP.new('www.scroogle.org', 80).request_get("/cgi-bin/nbbw.cgi?Gw=#{CGI::escape(params[:terms])}"
|
16
|
+
resp = Net::HTTP.new('www.scroogle.org', 80).request_get("/cgi-bin/nbbw.cgi?Gw=#{CGI::escape(params[:terms])}")
|
17
17
|
resp.value
|
18
18
|
page = resp.body
|
19
19
|
results = []
|
@@ -29,6 +29,7 @@ class Search < ModSpox::Plugin
|
|
29
29
|
reply message.replyto, output
|
30
30
|
rescue Object => boom
|
31
31
|
@pipeline << Privmsg.new(message.replyto, "Failed to find any results for: #{params[:terms]} Reason: #{boom}")
|
32
|
+
Logger.warn("Error: #{boom}\n#{boom.backtrace.join("\n")}")
|
32
33
|
end
|
33
34
|
end
|
34
35
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
class Slashdot < ModSpox::Plugin
|
5
|
+
|
6
|
+
def initialize(pipeline)
|
7
|
+
begin
|
8
|
+
require 'htmlentities'
|
9
|
+
rescue Object => boom
|
10
|
+
Logger.warn('Error: This plugin requires the HTMLEntities gem. Please install and reload plugin.')
|
11
|
+
raise Exceptions::BotException.new("Missing required HTMLEntities library")
|
12
|
+
end
|
13
|
+
super
|
14
|
+
add_sig(:sig => '(slashdot|\/\.) ?(\d+)?', :method => 'show_slashdot', :desc => 'Slashdot headlines', :params => [:trig, :num])
|
15
|
+
@coder = HTMLEntities.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def show_slashdot(message, params)
|
19
|
+
src = open('http://rss.slashdot.org/Slashdot/slashdot')
|
20
|
+
doc = REXML::Document.new(src.read)
|
21
|
+
num = params[:num].nil? || params[:num].to_i < 1 ? 1 : params[:num].to_i
|
22
|
+
num = 5 if num > 5
|
23
|
+
output = []
|
24
|
+
doc.elements.each('rdf:RDF/item') do |item|
|
25
|
+
num -= 1
|
26
|
+
title = CGI::unescapeHTML(item.elements['title'].text)
|
27
|
+
title = title.gsub(/<.+?>/, ' ').gsub(/[\r\n]/, '').gsub(/\s+/, ' ')
|
28
|
+
title = @coder.decode(title)
|
29
|
+
output << "\2/.\2 #{title.strip} \2->\2 #{Helpers.tinyurl(item.elements['link'].text)}"
|
30
|
+
break if num < 1
|
31
|
+
end
|
32
|
+
reply message.replyto, output
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -11,7 +11,7 @@ class Topten < ModSpox::Plugin
|
|
11
11
|
:description => 'Show topten from given date', :requirement => 'public').params = [:date]
|
12
12
|
Signature.find_or_create(:signature => 'stats ?(\S+)?', :plugin => name, :method => 'stats', :description => 'Show stats on nick',
|
13
13
|
:requirement => 'public').params = [:nick]
|
14
|
-
Signature.find_or_create(:signature => 'stats lifetime
|
14
|
+
Signature.find_or_create(:signature => 'stats lifetime (\S+)?', :plugin => name, :method => 'life_stats',
|
15
15
|
:description => 'Show stat totals for given nick', :requirement => 'public').params = [:nick]
|
16
16
|
@pipeline.hook(self, :log_stats, :Incoming_Privmsg)
|
17
17
|
end
|
@@ -62,9 +62,9 @@ class Topten < ModSpox::Plugin
|
|
62
62
|
def life_stats(m, p)
|
63
63
|
nick = p[:nick] ? Nick.locate(p[:nick], false) : m.source
|
64
64
|
if(nick)
|
65
|
-
result = ChatStat.group(:nick_id).select(:SUM[:bytes]
|
66
|
-
bytes = (result
|
67
|
-
reply m.replyto, "#{nick.nick} (total): #{bytes} logged, #{result
|
65
|
+
result = ChatStat.group(:nick_id).select(:SUM[:bytes].as(:tbytes), :SUM[:words].as(:twords), :SUM[:questions].as(:tquestions)).filter(:nick_id => nick.pk).first
|
66
|
+
bytes = (result[:tbytes] > 1023) ? "#{sprintf('%.2f', (result[:tbytes] / 1024.0))}kb" : "#{result[:tbytes]}b"
|
67
|
+
reply m.replyto, "#{nick.nick} (total): #{bytes} logged, #{result[:twords]} words spoken and #{result[:tquestions]} questions asked"
|
68
68
|
else
|
69
69
|
reply m.replyto, "\2Error:\2 Failed to find #{p[:nick]}"
|
70
70
|
end
|
@@ -76,7 +76,7 @@ class Topten < ModSpox::Plugin
|
|
76
76
|
stat = ChatStat.find_or_create(:nick_id => m.source.pk, :channel_id => m.target.pk, :daykey => key)
|
77
77
|
words = m.message.scan(/([^ ]+ |[^ ]$)/).size
|
78
78
|
bytes = m.message.gsub(/[^a-zA-Z0-9`\~\!@#\$%\^&\*\(\)_\+\[\]\}\{;:'"\/\?\.>,<\\|\-=]/, '').length
|
79
|
-
questions = m.message.scan(/.+?(
|
79
|
+
questions = m.message.scan(/.+?(!?\?!? |!?\?!?$)/).size
|
80
80
|
stat.words += words
|
81
81
|
stat.bytes += bytes
|
82
82
|
stat.questions += questions
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
|
3
|
+
class TracTicket < ModSpox::Plugin
|
4
|
+
|
5
|
+
def initialize(pipeline)
|
6
|
+
super
|
7
|
+
admin = Group.find_or_create(:name => 'admin')
|
8
|
+
add_sig(:sig => 'ticket (defect|enhancement|task) (.+?)( # (.+))?', :method => :add_ticket,
|
9
|
+
:desc => 'Add new ticket to trac ticket tracker', :params => [:type, :short, :trash, :long])
|
10
|
+
add_sig(:sig => 'ticket trac( (\S+))?', :method => :trac_location, :group => admin,
|
11
|
+
:desc => 'Show/set trac site', :params => [:trash, :site])
|
12
|
+
add_sig(:sig => 'ticket site', :method => :trac_location, :desc => 'Show trac site')
|
13
|
+
@site = Config[:trac]
|
14
|
+
end
|
15
|
+
|
16
|
+
def trac_location(message, params)
|
17
|
+
if(params[:site])
|
18
|
+
site = Config.find_or_create(:name => 'trac')
|
19
|
+
site.value = params[:site]
|
20
|
+
site.save
|
21
|
+
@site = params[:site]
|
22
|
+
reply message.replyto, "\2Trac Update:\2 Location of trac system has been updated: #{params[:site]}"
|
23
|
+
else
|
24
|
+
output = "\2Error:\2 Trac site has not yet been set"
|
25
|
+
unless(@site.nil?)
|
26
|
+
output = "\2Trac location:\2 #{@site}"
|
27
|
+
end
|
28
|
+
reply message.replyto, output
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def add_ticket(message, params)
|
33
|
+
if(@site =~ /(http:\/\/)?([^\/:]+)(:\d+)?(.+)$/)
|
34
|
+
addr = $2
|
35
|
+
port = $3
|
36
|
+
path = $4
|
37
|
+
port = port.nil? ? 80 : port.gsub(/:/, '').to_i
|
38
|
+
con = Net::HTTP.new(addr, port)
|
39
|
+
begin
|
40
|
+
cookie, fid = get_form_info(con, path)
|
41
|
+
long = params[:long] ? params[:long] : params[:short]
|
42
|
+
headers = {
|
43
|
+
'Cookie' => cookie,
|
44
|
+
'Referer' => @site,
|
45
|
+
'Content-Type' => 'application/x-www-form-urlencoded'
|
46
|
+
}
|
47
|
+
data = "reporter=#{URI.escape(message.source.nick)}&summary=#{URI.escape(params[:short])}&description=#{URI.escape(long)}&type=#{URI.escape(params[:type])}&action=create&status=new&priority=minor&__FORM_TOKEN=#{URI.escape(fid)}"
|
48
|
+
resp, data = con.post(path, data, headers)
|
49
|
+
reply message.replyto, 'Ticket was successfully added to tracker'
|
50
|
+
rescue Object => boom
|
51
|
+
reply message.replyto, "\2Error:\2 Encountered unexpected error while submitting ticket: #{boom}"
|
52
|
+
end
|
53
|
+
else
|
54
|
+
reply message.replyto, "\2Error:\2 Trac location has not been set"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def get_form_info(con, path)
|
59
|
+
res, content = con.get(path, {})
|
60
|
+
cookie = res['set-cookie']
|
61
|
+
if(content =~ /name="__FORM_TOKEN" value="(.+?)"/i)
|
62
|
+
return cookie, $1
|
63
|
+
else
|
64
|
+
raise 'Failed to locate proper identification'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -4,37 +4,64 @@ class Translate < ModSpox::Plugin
|
|
4
4
|
|
5
5
|
def initialize(pipeline)
|
6
6
|
super(pipeline)
|
7
|
+
begin
|
8
|
+
require 'htmlentities'
|
9
|
+
rescue Object => boom
|
10
|
+
Logger.warn('Error: This plugin requires the HTMLEntities gem. Please install and reload plugin.')
|
11
|
+
raise Exceptions::BotException.new("Missing required HTMLEntities library")
|
12
|
+
end
|
7
13
|
Signature.find_or_create(:signature => 'translate ([a-z]{2}\|[a-z]{2}) (.+)', :plugin => name, :method => 'translate',
|
8
14
|
:description => 'Translate text').params = [:lang, :text]
|
9
15
|
Signature.find_or_create(:signature => 'autotranslate add ([a-z]{2}) (\S+)', :plugin => name, :method => 'auto_add',
|
10
16
|
:description => 'Add a nick to the autotranslate service').params = [:lang, :nick]
|
11
17
|
Signature.find_or_create(:signature => 'autotranslate remove (\S+)', :plugin => name, :method => 'auto_remove',
|
12
18
|
:description => 'Remove a nick from the autotranslate service').params = [:nick]
|
19
|
+
add_sig(:sig => 'translate languages', :method => 'langs', :description => 'Show available languages')
|
20
|
+
@pipeline.hook(self, :listener, :Incoming_Privmsg)
|
13
21
|
@watchers = {}
|
14
22
|
@cache = {}
|
23
|
+
@coder = HTMLEntities.new
|
24
|
+
@allowed = {'zh'=>'Chinese-simplified','zt'=>'Chinese-traditional','en'=>'English','nl'=>'Dutch',
|
25
|
+
'fr'=>'French','de'=>'German','el'=>'Greek','it'=>'Italian','ja'=>'Japanese',
|
26
|
+
'ko'=>'Korean','pt'=>'Portuguese','ru'=>'Russian','es'=>'Spanish'}
|
27
|
+
@allowed_trans = ['zh_en','zh_zt', 'zt_en', 'zt_zh', 'en_zh', 'en_zt', 'en_nl', 'en_fr', 'en_de',
|
28
|
+
'en_el', 'en_it', 'en_ja', 'en_ko', 'en_pt', 'en_ru', 'en_es', 'nl_en', 'nl_fr',
|
29
|
+
'fr_nl', 'fr_en', 'fr_de', 'fr_el', 'fr_it', 'fr_pt', 'fr_es', 'de_en', 'de_fr',
|
30
|
+
'el_en', 'el_fr', 'it_en', 'it_fr', 'ja_en', 'ko_en', 'pt_en', 'pt_fr', 'ru_en',
|
31
|
+
'es_en', 'es_fr']
|
32
|
+
end
|
33
|
+
|
34
|
+
def langs(m, params)
|
35
|
+
output = ['Available languages for translate:']
|
36
|
+
s = []
|
37
|
+
@allowed.each_pair{|k,v| s << "#{v} (\2#{k}\2)"}
|
38
|
+
output << s.join(', ')
|
39
|
+
reply m.replyto, output
|
15
40
|
end
|
16
41
|
|
17
42
|
def auto_add(message, params)
|
18
43
|
return unless message.is_public?
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
44
|
+
if(@allowed_trans.include?("en_#{params[:lang]}") && @allowed_trans.include?("#{params[:lang]}_en"))
|
45
|
+
nick = Helpers.find_model(params[:nick], false)
|
46
|
+
if(nick && nick.channels.include?(message.target))
|
47
|
+
@watchers[message.target.pk] = {} unless @watchers.has_key?(message.target.pk)
|
48
|
+
@watchers[message.target.pk][nick.pk] = params[:lang] unless @watchers[message.target.pk].has_key?(nick.pk)
|
49
|
+
reply message.replyto, "#{params[:nick]} is now being tracked for auto translation"
|
50
|
+
else
|
51
|
+
reply message.replyto, "\2Error:\2 Failed to locate #{params[:nick]}"
|
52
|
+
end
|
25
53
|
else
|
26
|
-
reply message.
|
54
|
+
reply message.replyt, "\2Error:\2 Unsupported bi-directional translation"
|
27
55
|
end
|
28
56
|
end
|
29
57
|
|
30
58
|
def auto_remove(message, params)
|
31
59
|
return unless message.is_public?
|
32
|
-
nick =
|
60
|
+
nick = Models::Nick.locate(params[:nick], false)
|
33
61
|
if(nick)
|
34
62
|
if(@watchers.has_key?(message.target.pk))
|
35
63
|
@watchers[message.target.pk].delete(nick.pk) if @watchers[message.target.pk].has_key?(nick.pk)
|
36
64
|
@watchers.delete(message.target.pk) if @watchers[message.target.pk].empty?
|
37
|
-
hook
|
38
65
|
reply message.replyto, "#{params[:nick]} is no longer being tracked for auto translation"
|
39
66
|
else
|
40
67
|
reply message.replyto, "No one is currently being tracked"
|
@@ -45,15 +72,20 @@ class Translate < ModSpox::Plugin
|
|
45
72
|
end
|
46
73
|
|
47
74
|
def translate(message, params)
|
48
|
-
|
75
|
+
begin
|
76
|
+
reply message.replyto, "\2Translation:\2 #{do_translation(params[:lang], params[:text])}"
|
77
|
+
rescue Object => boom
|
78
|
+
reply message.replyto, "\2Error:\2 #{boom}"
|
79
|
+
end
|
49
80
|
end
|
50
81
|
|
51
82
|
def listener(message)
|
52
83
|
if(message.is_public? && @watchers.has_key?(message.target.pk))
|
53
84
|
if(@watchers[message.target.pk].has_key?(message.source.pk))
|
54
|
-
|
85
|
+
trans_message = do_translation("#{@watchers[message.target.pk][message.source.pk]}en", message.message)
|
86
|
+
reply message.replyto, "\2Translation (#{message.source.nick}):\2 #{trans_message}" unless trans_message == message.message
|
55
87
|
elsif(message.message =~ /^(\S+)[:,]/)
|
56
|
-
Logger.
|
88
|
+
Logger.info("Translate matched a followed nick: #{$1}")
|
57
89
|
nick = Helpers.find_model($1, false)
|
58
90
|
return unless nick
|
59
91
|
if(@watchers[message.target.pk].has_key?(nick.pk))
|
@@ -66,29 +98,36 @@ class Translate < ModSpox::Plugin
|
|
66
98
|
private
|
67
99
|
|
68
100
|
def do_translation(langs, text)
|
101
|
+
raise 'Unsupported language combination for translation' unless @allowed_trans.include?(langs.gsub(/\|/, '_'))
|
69
102
|
if(@cache.has_key?(langs) && @cache[langs].has_key?(text))
|
70
103
|
return @cache[langs][text]
|
71
104
|
end
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
105
|
+
content = Net::HTTP.post_form(URI.parse('http://babelfish.yahoo.com/translate_txt'), {
|
106
|
+
'ei' => 'UTF-8',
|
107
|
+
'doit' => 'done',
|
108
|
+
'fr' => 'bf-home',
|
109
|
+
'intl' => '1',
|
110
|
+
'tt' => 'urltext',
|
111
|
+
'trtext' => text,
|
112
|
+
'lp' => langs.gsub(/\|/, '_'),
|
113
|
+
'btnTrTxt' => 'Translate'
|
114
|
+
}).body
|
115
|
+
if(content)
|
116
|
+
if(content =~ /<div id="result">(.+?)<input/im)
|
117
|
+
tr = $1
|
118
|
+
tr.gsub!(/<.+?>/, '')
|
119
|
+
tr.gsub!(/[\r\n]/, ' ')
|
120
|
+
tr.gsub!(/\s+/, ' ')
|
121
|
+
if(text.length < 15)
|
122
|
+
@cache[langs] = {} unless @cache.has_key?(langs)
|
123
|
+
@cache[langs][text] = tr
|
124
|
+
end
|
125
|
+
return @coder.decode(tr).strip
|
126
|
+
else
|
127
|
+
raise 'Failed to locate translation'
|
80
128
|
end
|
81
|
-
return result.gsub(/\s+/, ' ')
|
82
|
-
else
|
83
|
-
raise "Failed to extract translation"
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def hook
|
88
|
-
if(@watchers.size > 0)
|
89
|
-
@pipeline.hook(self, :listener, :Incoming_Privmsg)
|
90
129
|
else
|
91
|
-
|
130
|
+
raise "Failed to receive result from server"
|
92
131
|
end
|
93
132
|
end
|
94
133
|
|