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.
@@ -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.source.nick, "\2Currently available plugins:\2")
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.source.nick, "\2#{plugin}:\2 #{path}")
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.source.nick, "\2Currently loaded plugins:\2 #{plugin_list.join(', ')}")
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.source.nick, "Okay")
44
+ @pipeline << Messages::Outgoing::Privmsg.new(message.replyto, "Okay")
45
45
  else
46
- @pipeline << Messages::Outgoing::Privmsg.new(message.source.nick, "Failed to find plugin: #{params[:plugin]}")
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.source.nick, "Okay")
58
+ @pipeline << Messages::Outgoing::Privmsg.new(message.replyto, "Okay")
59
59
  else
60
- @pipeline << Messages::Outgoing::Privmsg.new(message.source.nick, "Failed to find loaded plugin named: #{params[:plugin]}")
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.source.nick, 'Okay')
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
- next unless file =~ /\.rb$/
112
- sandbox = Module.new
113
- sandbox.module_eval(IO.readlines("#{path}/#{file}").join("\n"))
114
- sandbox.constants.each do |const|
115
- klass = sandbox.const_get(const)
116
- plugins[const] = "#{path}/#{file}" if klass < Plugin
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 => :chanmode, :Outgoing_Connect => :connect,
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 => :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', unique index servers_server_port_index (server, port))"
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')"
@@ -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
- m = (secs / 3600).to_i
11
+ h = (secs / 3600).to_i
10
12
  secs = secs % 3600
11
- str = Array.new
12
- str << d == 1 ? "#{d} day" : "#{d} days" if d > 0
13
- str << m == 1 ? "#{m} minute" : "#{m} minutes" if m > 0
14
- str << secs == 1 ? "#{secs} second" : "#{secs} seconds" if secs > 0
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