mod_spox 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +15 -0
- data/bin/mod_spox +1 -1
- data/data/mod_spox/extras/Karma.rb +67 -0
- data/data/mod_spox/extras/Pinger.rb +11 -0
- data/data/mod_spox/extras/Roulette.rb +233 -0
- data/data/mod_spox/extras/Search.rb +33 -0
- data/data/mod_spox/extras/UrbanDictionary.rb +53 -0
- data/data/mod_spox/plugins/Authenticator.rb +27 -26
- data/data/mod_spox/plugins/Banner.rb +392 -0
- data/data/mod_spox/plugins/Joiner.rb +7 -0
- data/data/mod_spox/plugins/PluginLoader.rb +18 -14
- data/data/mod_spox/plugins/Triggers.rb +80 -0
- data/lib/mod_spox/Bot.rb +3 -3
- data/lib/mod_spox/ConfigurationWizard.rb +2 -1
- data/lib/mod_spox/Helpers.rb +30 -7
- data/lib/mod_spox/Pipeline.rb +29 -9
- data/lib/mod_spox/Plugin.rb +20 -0
- data/lib/mod_spox/PluginManager.rb +16 -8
- data/lib/mod_spox/Pool.rb +1 -1
- data/lib/mod_spox/handlers/Handler.rb +1 -1
- data/lib/mod_spox/handlers/Kick.rb +1 -1
- data/lib/mod_spox/handlers/Mode.rb +39 -33
- data/lib/mod_spox/handlers/Part.rb +1 -1
- data/lib/mod_spox/handlers/Who.rb +5 -4
- data/lib/mod_spox/messages/incoming/Privmsg.rb +7 -1
- data/lib/mod_spox/messages/outgoing/Invite.rb +1 -1
- data/lib/mod_spox/messages/outgoing/Who.rb +4 -0
- data/lib/mod_spox/models/Channel.rb +5 -1
- data/lib/mod_spox/models/Nick.rb +15 -2
- metadata +38 -32
- data/data/mod_spox/extras/Tester.rb +0 -14
@@ -0,0 +1,392 @@
|
|
1
|
+
class Banner < ModSpox::Plugin
|
2
|
+
|
3
|
+
include Models
|
4
|
+
include Messages::Outgoing
|
5
|
+
|
6
|
+
def initialize(pipeline)
|
7
|
+
super(pipeline)
|
8
|
+
admin = Group.find_or_create(:name => 'banner')
|
9
|
+
Signature.find_or_create(:signature => 'ban (\S+)', :plugin => name, :method => 'default_ban', :group_id => admin.pk,
|
10
|
+
:description => 'Kickban given nick from current channel').params = [:nick]
|
11
|
+
Signature.find_or_create(:signature => 'ban (\S+) (\S+)', :plugin => name, :method => 'channel_ban', :group_id => admin.pk,
|
12
|
+
:description => 'Kickban given nick from given channel').params = [:nick, :channel]
|
13
|
+
Signature.find_or_create(:signature => 'ban (\S+) (\S+) (\d+) ?(.+)?', :plugin => name, :method => 'full_ban', :group_id => admin.pk,
|
14
|
+
:description => 'Kickban given nick from given channel for given number of seconds').params = [:nick, :channel, :time, :message]
|
15
|
+
Signature.find_or_create(:signature => 'banmask (\S+) (\S+) (\d+) ?(.+)?', :plugin => name, :method => 'message_mask_ban', :group_id => admin.pk,
|
16
|
+
:description => 'Kickban given mask from given channel for given number of seconds providing an optional message'
|
17
|
+
).params = [:mask, :message, :time, :channel]
|
18
|
+
Signature.find_or_create(:signature => 'banmask list', :plugin => name, :method => 'mask_list', :group_id => admin.pk,
|
19
|
+
:description => 'List all currently active banmasks')
|
20
|
+
Signature.find_or_create(:signature => 'banmask remove (\d+)', :plugin => name, :method => 'mask_remove', :group_id => admin.pk,
|
21
|
+
:description => 'Remove a currently enabled ban mask').params = [:id]
|
22
|
+
Signature.find_or_create(:signature => 'banlist', :plugin => name, :method => 'ban_list', :group_id => admin.pk,
|
23
|
+
:description => 'List all currently active bans generated from the bot')
|
24
|
+
Signature.find_or_create(:signature => 'banlist remove (\d+)', :plugin => name, :method => 'ban_remove', :group_id => admin.pk,
|
25
|
+
:description => 'Remove a current ban').params = [:id]
|
26
|
+
@pipeline.hook(self, :mode_check, :Incoming_Mode)
|
27
|
+
@pipeline.hook(self, :join_check, :Incoming_Join)
|
28
|
+
@pipeline.hook(self, :who_check, :Incoming_Who)
|
29
|
+
@pipeline.hook(self, :get_action, :Internal_TimerResponse)
|
30
|
+
BanRecord.create_table unless BanRecord.table_exists?
|
31
|
+
BanMask.create_table unless BanMask.table_exists?
|
32
|
+
@actions = []
|
33
|
+
@up_sync = Mutex.new
|
34
|
+
@timer_sync = Mutex.new
|
35
|
+
updater
|
36
|
+
end
|
37
|
+
|
38
|
+
def destroy
|
39
|
+
do_update
|
40
|
+
end
|
41
|
+
|
42
|
+
# message:: ModSpox::Messages::Incoming::Privmsg
|
43
|
+
# params:: parameters
|
44
|
+
# Perform a simple ban with default values
|
45
|
+
def default_ban(message, params)
|
46
|
+
params[:time] = 86400
|
47
|
+
params[:channel] = message.target.name
|
48
|
+
full_ban(message, params)
|
49
|
+
end
|
50
|
+
|
51
|
+
# message:: ModSpox::Messages::Incoming::Privmsg
|
52
|
+
# params:: parameters
|
53
|
+
# Ban given nick in given channel
|
54
|
+
def channel_ban(message, params)
|
55
|
+
params[:time] = 86400
|
56
|
+
full_ban(message, params)
|
57
|
+
end
|
58
|
+
|
59
|
+
# message:: ModSpox::Messages::Incoming::Privmsg
|
60
|
+
# params:: parameters
|
61
|
+
# Ban nick in given channel for given time providing given message
|
62
|
+
def full_ban(message, params)
|
63
|
+
nick = Models::Nick.filter(:nick => params[:nick]).first
|
64
|
+
channel = Channel.filter(:name => params[:channel]).first
|
65
|
+
if(!me.is_op?(message.target))
|
66
|
+
reply(message.replyto, "Error: I'm not a channel operator")
|
67
|
+
elsif(!nick)
|
68
|
+
reply(message.replyto, "#{message.source.nick}: Failed to find nick #{params[:nick]}")
|
69
|
+
elsif(!channel)
|
70
|
+
reply(message.replyto, "#{message.source.nick}: Failed to find channel #{params[:channel]}")
|
71
|
+
else
|
72
|
+
ban(nick, channel, params[:time], params[:message])
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# nick:: ModSpox::Models::Nick to ban
|
77
|
+
# channel:: ModSpox::Models::Channel to ban nick from
|
78
|
+
# time:: number of seconds ban should last
|
79
|
+
# reason:: reason for the ban
|
80
|
+
# invite:: invite nick back to channel when ban expires
|
81
|
+
# show_time:: show ban time in kick message
|
82
|
+
def ban(nick, channel, time, reason, invite=false, show_time=true)
|
83
|
+
raise Exceptions::InvalidType.new("Nick given is not a nick model") unless nick.is_a?(Models::Nick)
|
84
|
+
raise Exceptions::InvalidType.new("Channel given is not a channel model") unless channel.is_a?(Models::Channel)
|
85
|
+
if(!me.is_op?(channel))
|
86
|
+
raise Exceptions::NotOperator.new("I am not an operator in #{channel.name}")
|
87
|
+
elsif(!nick.channels.include?(channel))
|
88
|
+
raise Exceptions::NotInChannel.new("#{nick.nick} is not in channel: #{channel.name}")
|
89
|
+
else
|
90
|
+
mask = nick.source.nil? || nick.source.empty? ? "#{nick.nick}!*@*" : "*!*@#{nick.address}"
|
91
|
+
BanRecord.new(:nick_id => nick.pk, :bantime => time.to_i, :remaining => time.to_i,
|
92
|
+
:invite => invite, :channel_id => channel.pk, :mask => mask).save
|
93
|
+
message = reason ? reason : 'no soup for you!'
|
94
|
+
message = "#{message} (Duration: #{Helpers.format_seconds(time.to_i)})" if show_time
|
95
|
+
@pipeline << ChannelMode.new(channel, '+b', mask)
|
96
|
+
@pipeline << Kick.new(nick, channel, message)
|
97
|
+
updater
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# mask:: mask to match against source (Regexp)
|
102
|
+
# channel:: ModSpox::Models::Channel to ban from
|
103
|
+
# message:: kick message
|
104
|
+
# time:: time ban on mask should stay in place
|
105
|
+
# Bans all users who's source matches the given mask
|
106
|
+
def mask_ban(mask, channel, message, time)
|
107
|
+
raise NotInChannel.new("I am not in channel: #{channel.name}") unless me.channels.include?(channel)
|
108
|
+
BanMask.new(:mask => mask, :channel_id => channel.pk, :message => message, :bantime => time.to_i, :stamp => Object::Time.now).save
|
109
|
+
check_masks
|
110
|
+
updater
|
111
|
+
end
|
112
|
+
|
113
|
+
# message:: ModSpox::Messages::Incoming::Privmsg
|
114
|
+
# params:: parameters
|
115
|
+
# Set a ban on any nick with a source match given regex
|
116
|
+
def message_mask_ban(message, params)
|
117
|
+
channel = params[:channel] ? Channel.filter(:name => params[:channel]).first : message.target
|
118
|
+
if(channel)
|
119
|
+
begin
|
120
|
+
mask_ban(params[:mask], channel, params[:message], params[:time])
|
121
|
+
reply(message.replyto, "Okay")
|
122
|
+
rescue Object => boom
|
123
|
+
reply(message.replyto, "Error: Failed to ban mask. Reason: #{boom}")
|
124
|
+
Logger.log("ERROR: #{boom} #{boom.backtrace.join("\n")}")
|
125
|
+
end
|
126
|
+
else
|
127
|
+
reply(message.replyto, "Error: No record of channel: #{params[:channel]}")
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# message:: ModSpox::Messages::Incoming::Privmsg
|
132
|
+
# params:: parameters
|
133
|
+
# List all ban masks
|
134
|
+
def mask_list(message, params)
|
135
|
+
updater
|
136
|
+
if(BanMask.all.size > 0)
|
137
|
+
reply(message.replyto, "Masks currently banned:")
|
138
|
+
BanMask.all.each do |mask|
|
139
|
+
reply(message.replyto, "\2ID:\2 #{mask.pk} \2Mask:\2 #{mask.mask} \2Time:\2 #{Helpers.format_seconds(mask.bantime.to_i)} \2Channel:\2 #{mask.channel.name}")
|
140
|
+
end
|
141
|
+
else
|
142
|
+
reply(message.replyto, "No ban masks currently enabled")
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# message:: ModSpox::Messages::Incoming::Privmsg
|
147
|
+
# params:: parameters
|
148
|
+
# Remove ban mask with given ID
|
149
|
+
def mask_remove(message, params)
|
150
|
+
mask = BanMask[params[:id].to_i]
|
151
|
+
if(mask)
|
152
|
+
mask.destroy
|
153
|
+
updater
|
154
|
+
reply(message.replyto, 'Okay')
|
155
|
+
else
|
156
|
+
reply(message.replyto, "\2Error:\2 Failed to find ban mask with ID: #{params[:id]}")
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# message:: ModSpox::Messages::Incoming::Privmsg
|
161
|
+
# params:: parameters
|
162
|
+
# List all currently active bans originating from the bot
|
163
|
+
def ban_list(message, params)
|
164
|
+
updater
|
165
|
+
set = BanRecord.filter(:removed => false)
|
166
|
+
if(set.size > 0)
|
167
|
+
reply(message.replyto, "Currently active bans:")
|
168
|
+
set.each do |record|
|
169
|
+
reply(message.replyto, "\2ID:\2 #{record.pk} \2Nick:\2 #{record.nick.nick} \2Channel:\2 #{record.channel.name} \2Initial time:\2 #{Helpers.format_seconds(record.bantime.to_i)} \2Time remaining:\2 #{Helpers.format_seconds(record.remaining.to_i)}")
|
170
|
+
end
|
171
|
+
else
|
172
|
+
reply(message.replyto, "No bans currently active")
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# message:: ModSpox::Messages::Incoming::Privmsg
|
177
|
+
# params:: parameters
|
178
|
+
# Remove given ban
|
179
|
+
def ban_remove(message, params)
|
180
|
+
record = BanRecord[params[:id].to_i]
|
181
|
+
if(record)
|
182
|
+
record.set(:remaining => 0)
|
183
|
+
updater
|
184
|
+
reply(message.replyto, 'Okay')
|
185
|
+
else
|
186
|
+
reply(message.replyto, "\2Error:\2 Failed to find ban record with ID: #{params[:id]}")
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
# Check all enabled ban masks and ban any matches found
|
191
|
+
def check_masks
|
192
|
+
masks = BanMask.map_masks
|
193
|
+
masks.keys.each do |channel_name|
|
194
|
+
channel = Channel.filter(:name => channel_name).first
|
195
|
+
if(me.is_op?(channel))
|
196
|
+
channel.nicks.each do |nick|
|
197
|
+
match = nil
|
198
|
+
masks[channel.name].each do |mask|
|
199
|
+
if(nick.source =~ /#{mask[:mask]}/)
|
200
|
+
match = mask if match.nil? || mask[:bantime].to_i > match[:bantime].to_i
|
201
|
+
end
|
202
|
+
end
|
203
|
+
unless match.nil?
|
204
|
+
begin
|
205
|
+
ban(nick, channel, match[:bantime], match[:message])
|
206
|
+
rescue Object => boom
|
207
|
+
Logger.log("Mask based ban failed. Reason: #{boom}")
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
else
|
212
|
+
Logger.log("Ban masks will not be processed due to lack of operator status")
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
# nick:: ModSpox::Models::Nick
|
218
|
+
# channel:: ModSpox::Models::Channel
|
219
|
+
# Check if the nick in the channel matches any ban masks
|
220
|
+
def mask_check(nick, channel)
|
221
|
+
return unless me.is_op?(channel)
|
222
|
+
updater
|
223
|
+
match = nil
|
224
|
+
BanMask.filter(:channel_id => channel.pk).each do |bm|
|
225
|
+
if(nick.source =~ /#{bm.mask}/)
|
226
|
+
match = bm if match.nil? || match.bantime < bm.bantime
|
227
|
+
end
|
228
|
+
end
|
229
|
+
unless(match.nil?)
|
230
|
+
begin
|
231
|
+
ban(nick, channel, match.bantime, match.message)
|
232
|
+
rescue Object => boom
|
233
|
+
Logger.log("Mask based ban failed. Reason: #{boom}")
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
# message:: ModSpox::Messages::Incoming::Mode
|
239
|
+
# Check for mode changes. Remove pending ban removals if
|
240
|
+
# done manually
|
241
|
+
def mode_check(message)
|
242
|
+
if(message.target.is_a?(String) && message.source != me)
|
243
|
+
if(message.mode == '-b')
|
244
|
+
update = false
|
245
|
+
BanRecord.filter(:mask => message.target, :channel_id => message.channel.pk).each do |match|
|
246
|
+
match.set(:remaining => 0)
|
247
|
+
match.set(:removed => true)
|
248
|
+
update = true
|
249
|
+
end
|
250
|
+
updater if update
|
251
|
+
end
|
252
|
+
end
|
253
|
+
if(message.target == me && message.mode == '+o')
|
254
|
+
check_masks
|
255
|
+
updater
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
# message:: ModSpox::Messages::Incoming::Join
|
260
|
+
# Check is nick is banned
|
261
|
+
def join_check(message)
|
262
|
+
mask_check(message.nick, message.channel)
|
263
|
+
end
|
264
|
+
|
265
|
+
# message:: ModSpox::Messages::Incoming::Who
|
266
|
+
# Check if we updated any addresses
|
267
|
+
def who_check(message)
|
268
|
+
check_masks
|
269
|
+
end
|
270
|
+
|
271
|
+
# message:: ModSpox::Messages::Internal::TimerResponse
|
272
|
+
# Store any timer actions we have registered
|
273
|
+
def get_action(message)
|
274
|
+
if(message.action_added? && message.origin == self)
|
275
|
+
@actions << message.action
|
276
|
+
elsif(message.action_removed? && @actions.include?(message.action))
|
277
|
+
@actions.delete(message.action)
|
278
|
+
end
|
279
|
+
end
|
280
|
+
|
281
|
+
# Update all BanMask and BanRecords
|
282
|
+
def updater
|
283
|
+
@up_sync.synchronize do
|
284
|
+
unless(@actions.empty?)
|
285
|
+
@actions.each{|a|@pipeline << Messages::Internal::TimerRemove.new(a)}
|
286
|
+
Logger.log("Waiting for actions to become empty")
|
287
|
+
sleep(0.01) until @actions.empty?
|
288
|
+
Logger.log("Actions has now become empty")
|
289
|
+
end
|
290
|
+
do_update
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
# Completes update
|
295
|
+
def do_update
|
296
|
+
@timer_sync.synchronize do
|
297
|
+
begin
|
298
|
+
time = @sleep.nil? ? 0 : (Object::Time.now - @sleep).to_i
|
299
|
+
if(time > 0)
|
300
|
+
BanRecord.filter{:remaining > 0}.update("remaining = remaining - #{time}")
|
301
|
+
BanMask.filter{:bantime > 0}.update("bantime = bantime - #{time}")
|
302
|
+
end
|
303
|
+
BanRecord.filter{:remaining <= 0 && :removed == false}.each do |record|
|
304
|
+
if(me.is_op?(record.channel))
|
305
|
+
@pipeline << ChannelMode.new(record.channel, '-b', record.mask)
|
306
|
+
record.set(:removed => true)
|
307
|
+
@pipeline << Invite.new(record.nick, record.channel) if record.invite
|
308
|
+
end
|
309
|
+
end
|
310
|
+
BanMask.filter{:bantime < 1}.destroy
|
311
|
+
next_ban_record = BanRecord.filter{:remaining > 0}.order(:remaining.ASC).first
|
312
|
+
next_mask_record = BanMask.filter{:bantime > 0}.order(:bantime.ASC).first
|
313
|
+
if(next_ban_record && next_mask_record)
|
314
|
+
time = next_ban_record.bantime < next_mask_record.bantime ? next_ban_record.bantime : next_mask_record.bantime
|
315
|
+
elsif(next_ban_record)
|
316
|
+
time = next_ban_record.bantime
|
317
|
+
elsif(next_mask_record)
|
318
|
+
time = next_mask_record.bantime
|
319
|
+
else
|
320
|
+
time = nil
|
321
|
+
end
|
322
|
+
Logger.log("Time left to sleep is now: #{time}")
|
323
|
+
unless(time.nil?)
|
324
|
+
@sleep = Object::Time.now
|
325
|
+
@pipeline << Messages::Internal::TimerAdd.new(self, time, nil, true){ do_update }
|
326
|
+
else
|
327
|
+
@sleep = nil
|
328
|
+
end
|
329
|
+
rescue Object => boom
|
330
|
+
Logger.log("Updating encountered an unexpected error: #{boom}")
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
class BanRecord < Sequel::Model
|
336
|
+
set_schema do
|
337
|
+
primary_key :id
|
338
|
+
timestamp :stamp, :null => false
|
339
|
+
integer :bantime, :null => false, :default => 1
|
340
|
+
integer :remaining, :null => false, :default => 1
|
341
|
+
text :mask, :null => false
|
342
|
+
boolean :invite, :null => false, :default => false
|
343
|
+
boolean :removed, :null => false, :default => false
|
344
|
+
foreign_key :channel_id, :null => false, :table => :channels
|
345
|
+
foreign_key :nick_id, :null => false, :table => :nicks
|
346
|
+
end
|
347
|
+
|
348
|
+
before_create do
|
349
|
+
set :stamp => Time.now
|
350
|
+
end
|
351
|
+
|
352
|
+
def channel
|
353
|
+
ModSpox::Models::Channel[channel_id]
|
354
|
+
end
|
355
|
+
|
356
|
+
def nick
|
357
|
+
ModSpox::Models::Nick[nick_id]
|
358
|
+
end
|
359
|
+
end
|
360
|
+
|
361
|
+
class BanMask < Sequel::Model
|
362
|
+
set_schema do
|
363
|
+
primary_key :id
|
364
|
+
text :mask, :unique => true, :null => false
|
365
|
+
timestamp :stamp, :null => false
|
366
|
+
integer :bantime, :null => false, :default => 1
|
367
|
+
text :message
|
368
|
+
foreign_key :channel_id, :null => false, :table => :channels
|
369
|
+
end
|
370
|
+
|
371
|
+
def channel
|
372
|
+
ModSpox::Models::Channel[channel_id]
|
373
|
+
end
|
374
|
+
|
375
|
+
def self.map_masks
|
376
|
+
masks = {}
|
377
|
+
BanMask.all.each do |mask|
|
378
|
+
Logger.log("Processing mask for channel: #{mask.channel.name}")
|
379
|
+
masks[mask.channel.name] = [] unless masks.has_key?(mask.channel.name)
|
380
|
+
masks[mask.channel.name] << {:mask => mask.mask, :message => mask.message, :bantime => mask.bantime, :channel => mask.channel}
|
381
|
+
end
|
382
|
+
return masks
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
class NotOperator < Exceptions::BotException
|
387
|
+
end
|
388
|
+
|
389
|
+
class NotInChannel < Exceptions::BotException
|
390
|
+
end
|
391
|
+
|
392
|
+
end
|
@@ -3,6 +3,7 @@ class Joiner < ModSpox::Plugin
|
|
3
3
|
super(pipeline)
|
4
4
|
admin = Models::Group.filter(:name => 'admin').first
|
5
5
|
Models::Signature.find_or_create(:signature => 'join (\S+)', :plugin => name, :method => 'join', :group_id => admin.pk).params = [:channel]
|
6
|
+
@pipeline.hook(self, :send_who, :Incoming_Join)
|
6
7
|
end
|
7
8
|
|
8
9
|
# message:: ModSpox::Messages::Incoming::Privmsg
|
@@ -10,4 +11,10 @@ class Joiner < ModSpox::Plugin
|
|
10
11
|
def join(message, params)
|
11
12
|
@pipeline << Messages::Outgoing::Join.new(params[:channel])
|
12
13
|
end
|
14
|
+
|
15
|
+
# message:: ModSpox::Messages::Incoming::Join
|
16
|
+
# Send a WHO request for channel on join
|
17
|
+
def send_who(message)
|
18
|
+
@pipeline << ModSpox::Messages::Outgoing::Who.new(message.channel.name) if message.nick == me
|
19
|
+
end
|
13
20
|
end
|
@@ -21,9 +21,9 @@ class PluginLoader < ModSpox::Plugin
|
|
21
21
|
# params:: matching signature params
|
22
22
|
# Output currently available plugins for loading
|
23
23
|
def available_plugins(message, params)
|
24
|
-
@pipeline << Messages::Outgoing::Privmsg.new(message.
|
24
|
+
@pipeline << Messages::Outgoing::Privmsg.new(message.replyto, "\2Currently available plugins:\2")
|
25
25
|
find_plugins.each_pair do | plugin, path |
|
26
|
-
@pipeline << Messages::Outgoing::Privmsg.new(message.
|
26
|
+
@pipeline << Messages::Outgoing::Privmsg.new(message.replyto, "\2#{plugin}:\2 #{path}")
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
@@ -31,7 +31,7 @@ class PluginLoader < ModSpox::Plugin
|
|
31
31
|
# params:: matching signature params
|
32
32
|
# Output currently loaded plugins
|
33
33
|
def loaded_plugins(message, params)
|
34
|
-
@pipeline << Messages::Outgoing::Privmsg.new(message.
|
34
|
+
@pipeline << Messages::Outgoing::Privmsg.new(message.replyto, "\2Currently loaded plugins:\2 #{plugin_list.join(', ')}")
|
35
35
|
end
|
36
36
|
# message:: ModSpox::Messages::Incoming::Privmsg
|
37
37
|
# params:: matching signature params
|
@@ -41,9 +41,9 @@ class PluginLoader < ModSpox::Plugin
|
|
41
41
|
if(plugins.has_key?(params[:plugin]))
|
42
42
|
name = plugin_discovery(BotConfig[:pluginextraspath]).keys.include?(params[:plugin]) ? nil : "#{params[:plugin]}.rb"
|
43
43
|
@pipeline << Messages::Internal::PluginLoadRequest.new(self, plugins[params[:plugin]], name)
|
44
|
-
@pipeline << Messages::Outgoing::Privmsg.new(message.
|
44
|
+
@pipeline << Messages::Outgoing::Privmsg.new(message.replyto, "Okay")
|
45
45
|
else
|
46
|
-
@pipeline << Messages::Outgoing::Privmsg.new(message.
|
46
|
+
@pipeline << Messages::Outgoing::Privmsg.new(message.replyto, "Failed to find plugin: #{params[:plugin]}")
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
@@ -55,9 +55,9 @@ class PluginLoader < ModSpox::Plugin
|
|
55
55
|
unless(path.nil?)
|
56
56
|
name = plugin_discovery(BotConfig[:pluginextraspath]).keys.include?(params[:plugin]) ? nil : ".#{params[:plugin]}.rb"
|
57
57
|
@pipeline << Messages::Internal::PluginUnloadRequest.new(self, path, name)
|
58
|
-
@pipeline << Messages::Outgoing::Privmsg.new(message.
|
58
|
+
@pipeline << Messages::Outgoing::Privmsg.new(message.replyto, "Okay")
|
59
59
|
else
|
60
|
-
@pipeline << Messages::Outgoing::Privmsg.new(message.
|
60
|
+
@pipeline << Messages::Outgoing::Privmsg.new(message.replyto, "Failed to find loaded plugin named: #{params[:plugin]}")
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
@@ -66,7 +66,7 @@ class PluginLoader < ModSpox::Plugin
|
|
66
66
|
# Reloads plugins
|
67
67
|
def reload_plugin(message, params)
|
68
68
|
@pipeline << Messages::Internal::PluginReload.new
|
69
|
-
@pipeline << Messages::Outgoing::Privmsg.new(message.
|
69
|
+
@pipeline << Messages::Outgoing::Privmsg.new(message.replyto, 'Okay')
|
70
70
|
end
|
71
71
|
|
72
72
|
# message:: ModSpox::Messages::Internal::PluginModuleResponse
|
@@ -108,12 +108,16 @@ class PluginLoader < ModSpox::Plugin
|
|
108
108
|
def plugin_discovery(path)
|
109
109
|
plugins = Hash.new
|
110
110
|
Dir.new(path).each do |file|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
111
|
+
begin
|
112
|
+
next unless file =~ /\.rb$/
|
113
|
+
sandbox = Module.new
|
114
|
+
sandbox.module_eval(IO.readlines("#{path}/#{file}").join("\n"))
|
115
|
+
sandbox.constants.each do |const|
|
116
|
+
klass = sandbox.const_get(const)
|
117
|
+
plugins[const] = "#{path}/#{file}" if klass < Plugin
|
118
|
+
end
|
119
|
+
rescue Object => boom
|
120
|
+
Logger.log("Failed to parse file: #{path}/#{file}. Reason: #{boom}")
|
117
121
|
end
|
118
122
|
end
|
119
123
|
return plugins
|
@@ -0,0 +1,80 @@
|
|
1
|
+
class Triggers < ModSpox::Plugin
|
2
|
+
|
3
|
+
include Messages::Outgoing
|
4
|
+
|
5
|
+
def initialize(pipeline)
|
6
|
+
super(pipeline)
|
7
|
+
admin = Models::Group.filter(:name => 'admin').first
|
8
|
+
Models::Signature.find_or_create(:signature => 'triggers active', :plugin => name, :method => 'active', :group_id => admin.pk, :description => 'List all currently active triggers')
|
9
|
+
Models::Signature.find_or_create(:signature => 'triggers list', :plugin => name, :method => 'list', :group_id => admin.pk, :description => 'List all triggers and their current status')
|
10
|
+
Models::Signature.find_or_create(:signature => 'triggers add (\S+)', :plugin => name, :method => 'add', :group_id => admin.pk, :description => 'Add a new trigger and activate it').params = [:trigger]
|
11
|
+
Models::Signature.find_or_create(:signature => 'triggers remove (\d+)', :plugin => name, :method => 'remove', :group_id => admin.pk, :description => 'Remove trigger').params = [:id]
|
12
|
+
Models::Signature.find_or_create(:signature => 'triggers activate (\d+)', :plugin => name, :method => 'activate', :group_id => admin.pk, :description => 'Activate the trigger').params = [:id]
|
13
|
+
Models::Signature.find_or_create(:signature => 'triggers deactivate (\d+)', :plugin => name, :method => 'deactivate', :group_id => admin.pk, :description => 'Deactivate the trigger').params = [:id]
|
14
|
+
end
|
15
|
+
|
16
|
+
def active(message, params)
|
17
|
+
triggers = Models::Trigger.filter(:active => true)
|
18
|
+
if(triggers)
|
19
|
+
@pipeline << Privmsg.new(message.replyto, "\2Currently active triggers:\2")
|
20
|
+
triggers.each do |t|
|
21
|
+
@pipeline << Privmsg.new(message.replyto, "#{t.pk}: #{t.trigger}")
|
22
|
+
end
|
23
|
+
else
|
24
|
+
@pipeline << Privmsg.new(message.replyto, 'No triggers are currently active')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def list(message, params)
|
29
|
+
triggers = Models::Trigger.all
|
30
|
+
if(triggers)
|
31
|
+
@pipeline << Privmsg.new(message.replyto, "\2Trigger listing:\2")
|
32
|
+
triggers.each do |t|
|
33
|
+
@pipeline << Privmsg.new(message.replyto, "#{t.pk}: #{t.trigger} -> \2#{t.active ? "activated" : "not activated"}\2")
|
34
|
+
end
|
35
|
+
else
|
36
|
+
@pipeline << Privmsg.new(message.replyto, 'No triggers found')
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def add(message, params)
|
41
|
+
Models::Trigger.find_or_create(:trigger => params[:trigger]).set(:active => true)
|
42
|
+
@pipeline << Privmsg.new(message.replyto, "Trigger #{params[:trigger]} is now active")
|
43
|
+
@pipeline << Messages::Internal::TriggersUpdate.new
|
44
|
+
end
|
45
|
+
|
46
|
+
def remove(message, params)
|
47
|
+
trigger = Models::Trigger[params[:id]]
|
48
|
+
if(trigger)
|
49
|
+
trig = trigger.trigger
|
50
|
+
trigger.destroy
|
51
|
+
@pipeline << Privmsg.new(message.replyto, "Trigger #{trig} has been removed")
|
52
|
+
@pipeline << Messages::Internal::TriggersUpdate.new
|
53
|
+
else
|
54
|
+
@pipeline << Privmsg.new(message.replyto, "Failed to find trigger with ID: #{params[:id]}")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def activate(message, params)
|
59
|
+
trigger = Models::Trigger[params[:id]]
|
60
|
+
if(trigger)
|
61
|
+
trigger.set(:active => true)
|
62
|
+
@pipeline << Privmsg.new(message.replyto, "Trigger #{trigger.trigger} has been activated")
|
63
|
+
@pipeline << Messages::Internal::TriggersUpdate.new
|
64
|
+
else
|
65
|
+
@pipeline << Privmsg.new(message.replyto, "Failed to find trigger with ID: #{params[:id]}")
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def deactivate(message, params)
|
70
|
+
trigger = Models::Trigger[params[:id]]
|
71
|
+
if(trigger)
|
72
|
+
trigger.set(:active => false)
|
73
|
+
@pipeline << Privmsg.new(message.replyto, "Trigger #{trigger.trigger} has been deactivated")
|
74
|
+
@pipeline << Messages::Internal::TriggersUpdate.new
|
75
|
+
else
|
76
|
+
@pipeline << Privmsg.new(message.replyto, "Failed to find trigger with ID: #{params[:id]}")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
data/lib/mod_spox/Bot.rb
CHANGED
@@ -102,7 +102,7 @@ module ModSpox
|
|
102
102
|
# Adds hooks to pipeline for processing messages
|
103
103
|
def hook_pipeline
|
104
104
|
{:Outgoing_Admin => :admin, :Outgoing_Away => :away,
|
105
|
-
:Outgoing_ChannelMode => :
|
105
|
+
:Outgoing_ChannelMode => :channel_mode, :Outgoing_Connect => :connect,
|
106
106
|
:Outgoing_Die => :die, :Outgoing_Info => :info,
|
107
107
|
:Outgoing_Invite => :invite, :Outgoing_Ison => :ison,
|
108
108
|
:Outgoing_Join => :join, :Outgoing_Kick => :kick,
|
@@ -119,7 +119,7 @@ module ModSpox
|
|
119
119
|
:Outgoing_Summon => :summon, :Outgoing_Time => :time,
|
120
120
|
:Outgoing_Topic => :topic, :Outgoing_Trace => :trace,
|
121
121
|
:Outgoing_Unaway => :unaway, :Outgoing_User => :user,
|
122
|
-
:Outgoing_UserHost => :userhost, :Outgoing_UserMode => :
|
122
|
+
:Outgoing_UserHost => :userhost, :Outgoing_UserMode => :user_mode,
|
123
123
|
:Outgoing_Users => :users, :Outgoing_Version => :version,
|
124
124
|
:Outgoing_Who => :who, :Outgoing_WhoWas => :whowas,
|
125
125
|
:Outgoing_Whois => :whois, :Internal_EstablishConnection => :bot_connect,
|
@@ -359,7 +359,7 @@ module ModSpox
|
|
359
359
|
# message:: Messages::Outgoing::Who message
|
360
360
|
# Sends WHO message to server
|
361
361
|
def who(message)
|
362
|
-
o = message.only_ops ? 'o' : ''
|
362
|
+
o = message.only_ops? ? 'o' : ''
|
363
363
|
@socket << "WHO #{message.mask} #{o}"
|
364
364
|
end
|
365
365
|
|
@@ -164,7 +164,8 @@ module ModSpox
|
|
164
164
|
Database.db << "CREATE TABLE if not exists nick_channels (channel_id integer NOT NULL REFERENCES channels, nick_id integer NOT NULL REFERENCES nicks, primary key (channel_id, nick_id))"
|
165
165
|
Database.db << "CREATE TABLE if not exists nick_modes (id integer PRIMARY KEY AUTOINCREMENT, mode string NOT NULL, nick_id integer NOT NULL REFERENCES nicks, channel_id integer REFERENCES channels)"
|
166
166
|
Database.db << "CREATE UNIQUE INDEX if not exists nick_modes_nick_id_channel_id_index ON nick_modes (nick_id, channel_id)"
|
167
|
-
Database.db << "CREATE TABLE if not exists servers (id integer primary key autoincrement, host string NOT NULL, port integer NOT NULL DEFAULT 6667, priority integer NOT NULL DEFAULT 0, connected boolean NOT NULL DEFAULT 'f'
|
167
|
+
Database.db << "CREATE TABLE if not exists servers (id integer primary key autoincrement, host string NOT NULL, port integer NOT NULL DEFAULT 6667, priority integer NOT NULL DEFAULT 0, connected boolean NOT NULL DEFAULT 'f')"
|
168
|
+
Database.db << "CREATE UNIQUE INDEX if not exists servers_host_port_index on servers (host, port)"
|
168
169
|
Database.db << "CREATE TABLE if not exists settings (id integer PRIMARY KEY AUTOINCREMENT, name string UNIQUE NOT NULL, value text)"
|
169
170
|
Database.db << "CREATE TABLE if not exists signatures (id integer PRIMARY KEY AUTOINCREMENT, signature string NOT NULL UNIQUE, params string, group_id integer DEFAULT NULL REFERENCES groups, method string NOT NULL, plugin string NOT NULL, description text)"
|
170
171
|
Database.db << "CREATE TABLE if not exists triggers (id integer PRIMARY KEY AUTOINCREMENT, trigger string UNIQUE NOT NULL, active boolean NOT NULL DEFAULT 'f')"
|
data/lib/mod_spox/Helpers.rb
CHANGED
@@ -1,17 +1,22 @@
|
|
1
1
|
require 'timeout'
|
2
|
+
require 'net/http'
|
2
3
|
module ModSpox
|
3
4
|
module Helpers
|
4
5
|
# secs:: number of seconds
|
5
6
|
# Converts seconds into a human readable string
|
6
7
|
def Helpers.format_seconds(secs)
|
8
|
+
str = []
|
7
9
|
d = (secs / 86400).to_i
|
8
10
|
secs = secs % 86400
|
9
|
-
|
11
|
+
h = (secs / 3600).to_i
|
10
12
|
secs = secs % 3600
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
m = (secs / 60).to_i
|
14
|
+
secs = secs % 60
|
15
|
+
{:day => d, :hour => h, :minute => m, :second => secs}.each_pair do |type, value|
|
16
|
+
if(value > 0)
|
17
|
+
str << "#{value} #{type}#{value == 1 ? '':'s'}"
|
18
|
+
end
|
19
|
+
end
|
15
20
|
return str.join(' ')
|
16
21
|
end
|
17
22
|
|
@@ -29,7 +34,25 @@ module ModSpox
|
|
29
34
|
Logger.log("Command generated an exception (command: #{command} | error: #{boom})")
|
30
35
|
end
|
31
36
|
end
|
32
|
-
|
33
|
-
|
37
|
+
|
38
|
+
# url:: URL to shorten
|
39
|
+
# Gets a tinyurl for given URL
|
40
|
+
def Helpers.tinyurl(url)
|
41
|
+
begin
|
42
|
+
connection = Net::HTTP.new('tinyurl.com', 80)
|
43
|
+
resp, data = connection.get("/create.php?url=#{url}", nil)
|
44
|
+
if(resp.code !~ /^200$/)
|
45
|
+
raise "Failed to make the URL small."
|
46
|
+
end
|
47
|
+
data.gsub!(/[\n\r]/, '')
|
48
|
+
if(data =~ /<input type=hidden name=tinyurl value="(.+?)">/)
|
49
|
+
return $1
|
50
|
+
else
|
51
|
+
raise "Failed to locate the small URL."
|
52
|
+
end
|
53
|
+
rescue Object => boom
|
54
|
+
raise "Failed to process URL. #{boom}"
|
55
|
+
end
|
56
|
+
end
|
34
57
|
end
|
35
58
|
end
|