mod_spox 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +16 -0
- data/INSTALL +4 -1
- data/bin/mod_spox +3 -1
- data/data/mod_spox/extras/AOLSpeak.rb +2 -2
- data/data/mod_spox/extras/AutoKick.rb +3 -8
- data/data/mod_spox/extras/AutoMode.rb +135 -0
- data/data/mod_spox/extras/EightBall.rb +1 -0
- data/data/mod_spox/extras/Headers.rb +4 -3
- data/data/mod_spox/extras/PhpFuncLookup.rb +14 -11
- data/data/mod_spox/extras/Roulette.rb +3 -3
- data/data/mod_spox/extras/Search.rb +3 -2
- data/data/mod_spox/extras/Talk.rb +1 -9
- data/data/mod_spox/extras/Translate.rb +3 -3
- data/data/mod_spox/extras/UrbanDictionary.rb +5 -3
- data/data/mod_spox/extras/Weather.rb +5 -4
- data/data/mod_spox/plugins/Authenticator.rb +2 -2
- data/data/mod_spox/plugins/Banner.rb +207 -2
- data/data/mod_spox/plugins/Helper.rb +1 -1
- data/data/mod_spox/plugins/PluginLoader.rb +22 -6
- data/data/mod_spox/plugins/Triggers.rb +6 -4
- data/lib/mod_spox/Action.rb +2 -0
- data/lib/mod_spox/BaseConfig.rb +2 -0
- data/lib/mod_spox/Bot.rb +32 -6
- data/lib/mod_spox/BotConfig.rb +3 -0
- data/lib/mod_spox/Cache.rb +57 -0
- data/lib/mod_spox/ConfigurationWizard.rb +6 -2
- data/lib/mod_spox/Helpers.rb +36 -18
- data/lib/mod_spox/Loader.rb +5 -54
- data/lib/mod_spox/Logger.rb +49 -3
- data/lib/mod_spox/MessageFactory.rb +5 -0
- data/lib/mod_spox/Monitors.rb +14 -12
- data/lib/mod_spox/Pipeline.rb +38 -6
- data/lib/mod_spox/Plugin.rb +3 -0
- data/lib/mod_spox/PluginHolder.rb +22 -0
- data/lib/mod_spox/PluginManager.rb +123 -25
- data/lib/mod_spox/Pool.rb +52 -23
- data/lib/mod_spox/Socket.rb +21 -10
- data/lib/mod_spox/Timer.rb +32 -6
- data/lib/mod_spox/handlers/BadNick.rb +2 -0
- data/lib/mod_spox/handlers/Bounce.rb +3 -0
- data/lib/mod_spox/handlers/Created.rb +2 -0
- data/lib/mod_spox/handlers/Handler.rb +5 -0
- data/lib/mod_spox/handlers/Invite.rb +2 -0
- data/lib/mod_spox/handlers/Join.rb +21 -5
- data/lib/mod_spox/handlers/Kick.rb +2 -0
- data/lib/mod_spox/handlers/LuserChannels.rb +2 -0
- data/lib/mod_spox/handlers/LuserClient.rb +1 -0
- data/lib/mod_spox/handlers/LuserMe.rb +1 -0
- data/lib/mod_spox/handlers/LuserOp.rb +2 -0
- data/lib/mod_spox/handlers/LuserUnknown.rb +2 -0
- data/lib/mod_spox/handlers/Mode.rb +2 -0
- data/lib/mod_spox/handlers/Motd.rb +5 -2
- data/lib/mod_spox/handlers/MyInfo.rb +2 -0
- data/lib/mod_spox/handlers/Names.rb +5 -1
- data/lib/mod_spox/handlers/Nick.rb +2 -0
- data/lib/mod_spox/handlers/NickInUse.rb +2 -0
- data/lib/mod_spox/handlers/Notice.rb +16 -4
- data/lib/mod_spox/handlers/Part.rb +2 -0
- data/lib/mod_spox/handlers/Ping.rb +2 -0
- data/lib/mod_spox/handlers/Pong.rb +2 -0
- data/lib/mod_spox/handlers/Privmsg.rb +16 -4
- data/lib/mod_spox/handlers/Quit.rb +2 -0
- data/lib/mod_spox/handlers/Topic.rb +2 -0
- data/lib/mod_spox/handlers/Welcome.rb +3 -0
- data/lib/mod_spox/handlers/Who.rb +3 -1
- data/lib/mod_spox/handlers/Whois.rb +8 -0
- data/lib/mod_spox/handlers/YourHost.rb +2 -0
- data/lib/mod_spox/messages/Messages.rb +6 -0
- data/lib/mod_spox/messages/incoming/BadNick.rb +1 -0
- data/lib/mod_spox/messages/incoming/Bounce.rb +1 -0
- data/lib/mod_spox/messages/incoming/Created.rb +1 -0
- data/lib/mod_spox/messages/incoming/Invite.rb +1 -0
- data/lib/mod_spox/messages/incoming/Join.rb +1 -0
- data/lib/mod_spox/messages/incoming/Kick.rb +1 -0
- data/lib/mod_spox/messages/incoming/LuserChannels.rb +1 -0
- data/lib/mod_spox/messages/incoming/LuserClient.rb +1 -0
- data/lib/mod_spox/messages/incoming/LuserMe.rb +1 -0
- data/lib/mod_spox/messages/incoming/LuserOp.rb +1 -0
- data/lib/mod_spox/messages/incoming/LuserUnknown.rb +1 -0
- data/lib/mod_spox/messages/incoming/Mode.rb +1 -0
- data/lib/mod_spox/messages/incoming/Motd.rb +1 -0
- data/lib/mod_spox/messages/incoming/MyInfo.rb +1 -0
- data/lib/mod_spox/messages/incoming/Names.rb +1 -0
- data/lib/mod_spox/messages/incoming/Nick.rb +1 -0
- data/lib/mod_spox/messages/incoming/NickInUse.rb +1 -0
- data/lib/mod_spox/messages/incoming/Notice.rb +1 -0
- data/lib/mod_spox/messages/incoming/Part.rb +1 -0
- data/lib/mod_spox/messages/incoming/Ping.rb +1 -0
- data/lib/mod_spox/messages/incoming/Pong.rb +1 -0
- data/lib/mod_spox/messages/incoming/Privmsg.rb +1 -0
- data/lib/mod_spox/messages/incoming/Quit.rb +1 -0
- data/lib/mod_spox/messages/incoming/Topic.rb +1 -0
- data/lib/mod_spox/messages/incoming/TopicInfo.rb +1 -0
- data/lib/mod_spox/messages/incoming/Welcome.rb +1 -0
- data/lib/mod_spox/messages/incoming/Who.rb +1 -0
- data/lib/mod_spox/messages/incoming/Whois.rb +1 -0
- data/lib/mod_spox/messages/incoming/YourHost.rb +1 -0
- data/lib/mod_spox/messages/internal/NickRequest.rb +1 -0
- data/lib/mod_spox/messages/internal/NickResponse.rb +1 -0
- data/lib/mod_spox/messages/internal/PluginLoadRequest.rb +1 -0
- data/lib/mod_spox/messages/internal/PluginLoadResponse.rb +1 -0
- data/lib/mod_spox/messages/internal/PluginModuleRequest.rb +1 -0
- data/lib/mod_spox/messages/internal/PluginModuleResponse.rb +1 -0
- data/lib/mod_spox/messages/internal/PluginReload.rb +10 -0
- data/lib/mod_spox/messages/internal/PluginRequest.rb +1 -0
- data/lib/mod_spox/messages/internal/PluginResponse.rb +1 -0
- data/lib/mod_spox/messages/internal/PluginUnloadRequest.rb +1 -0
- data/lib/mod_spox/messages/internal/PluginUnloadResponse.rb +1 -0
- data/lib/mod_spox/messages/internal/StatusResponse.rb +1 -0
- data/lib/mod_spox/messages/internal/TimerAdd.rb +1 -0
- data/lib/mod_spox/messages/internal/TimerClear.rb +8 -0
- data/lib/mod_spox/messages/internal/TimerResponse.rb +1 -0
- data/lib/mod_spox/messages/outgoing/Away.rb +1 -0
- data/lib/mod_spox/messages/outgoing/Notice.rb +1 -0
- data/lib/mod_spox/messages/outgoing/Ping.rb +1 -0
- data/lib/mod_spox/messages/outgoing/Quit.rb +1 -0
- data/lib/mod_spox/messages/outgoing/Raw.rb +16 -0
- data/lib/mod_spox/models/Models.rb +4 -0
- data/lib/mod_spox/models/Nick.rb +9 -0
- data/lib/mod_spox/models/Setting.rb +3 -5
- data/lib/mod_spox/models/Signature.rb +2 -3
- metadata +8 -2
|
@@ -23,12 +23,25 @@ class Banner < ModSpox::Plugin
|
|
|
23
23
|
:description => 'List all currently active bans generated from the bot')
|
|
24
24
|
Signature.find_or_create(:signature => 'banlist remove (\d+)', :plugin => name, :method => 'ban_remove', :group_id => admin.pk,
|
|
25
25
|
:description => 'Remove a current ban').params = [:id]
|
|
26
|
+
Signature.find_or_create(:signature => 'exempt mode ([ov]) ?(\S+)?', :plugin => name, :method => 'exempt_mode', :group_id => admin.pk,
|
|
27
|
+
:description => 'Exempt given modes from kick. Apply to all channels if one is not provided').params = [:mode, :channel]
|
|
28
|
+
Signature.find_or_create(:signature => 'exempt nick (\S+) ?(\S+)?', :plugin => name, :method => 'exempt_nick', :group_id => admin.pk,
|
|
29
|
+
:description => 'Exempt a nick from kicks globally or per channel').params = [:nick, :channel]
|
|
30
|
+
Signature.find_or_create(:signature => 'exempt source (\S+)', :plugin => name, :method => 'exempt_source', :group_id => admin.pk,
|
|
31
|
+
:description => 'Exempt a source from kicks globally or per channel').params = [:source, :channel]
|
|
32
|
+
Signature.find_or_create(:signature => 'exempt list (nick|mode|source)', :plugin => name, :method => 'exempt_list', :group_id => admin.pk,
|
|
33
|
+
:description => 'List current exemptions of given type').params = [:type]
|
|
34
|
+
Signature.find_or_create(:signature => 'exempt remove (nick|mode|source) (\d+)', :plugin => name, :method => 'exempt_remove', :group_id => admin.pk,
|
|
35
|
+
:description => 'Remove exemption from given type').params = [:type, :id]
|
|
26
36
|
@pipeline.hook(self, :mode_check, :Incoming_Mode)
|
|
27
37
|
@pipeline.hook(self, :join_check, :Incoming_Join)
|
|
28
38
|
@pipeline.hook(self, :who_check, :Incoming_Who)
|
|
29
39
|
@pipeline.hook(self, :get_action, :Internal_TimerResponse)
|
|
30
40
|
BanRecord.create_table unless BanRecord.table_exists?
|
|
31
41
|
BanMask.create_table unless BanMask.table_exists?
|
|
42
|
+
BanNickExempt.create_table unless BanNickExempt.table_exists?
|
|
43
|
+
BanModeExempt.create_table unless BanModeExempt.table_exists?
|
|
44
|
+
BanSourceExempt.create_table unless BanSourceExempt.table_exists?
|
|
32
45
|
@actions = []
|
|
33
46
|
@up_sync = Mutex.new
|
|
34
47
|
@timer_sync = Mutex.new
|
|
@@ -60,7 +73,7 @@ class Banner < ModSpox::Plugin
|
|
|
60
73
|
# params:: parameters
|
|
61
74
|
# Ban nick in given channel for given time providing given message
|
|
62
75
|
def full_ban(message, params)
|
|
63
|
-
nick =
|
|
76
|
+
nick = Helpers.find_model(params[:nick], false)
|
|
64
77
|
channel = Channel.filter(:name => params[:channel]).first
|
|
65
78
|
if(!me.is_op?(message.target))
|
|
66
79
|
reply(message.replyto, "Error: I'm not a channel operator")
|
|
@@ -86,6 +99,8 @@ class Banner < ModSpox::Plugin
|
|
|
86
99
|
raise NotOperator.new("I am not an operator in #{channel.name}")
|
|
87
100
|
elsif(!nick.channels.include?(channel))
|
|
88
101
|
raise NotInChannel.new("#{nick.nick} is not in channel: #{channel.name}")
|
|
102
|
+
elsif(check_exempt(nick, channel))
|
|
103
|
+
raise BanExemption.new("This nick is exempt from bans: #{nick.nick}")
|
|
89
104
|
else
|
|
90
105
|
mask = nick.source.nil? || nick.source.empty? ? "#{nick.nick}!*@*" : "*!*@#{nick.address}"
|
|
91
106
|
BanRecord.new(:nick_id => nick.pk, :bantime => time.to_i, :remaining => time.to_i,
|
|
@@ -332,6 +347,144 @@ class Banner < ModSpox::Plugin
|
|
|
332
347
|
end
|
|
333
348
|
end
|
|
334
349
|
|
|
350
|
+
# message:: ModSpox::Messages::Incoming::Privmsg
|
|
351
|
+
# params:: parameters
|
|
352
|
+
# Add ban exemption for a given mode
|
|
353
|
+
def exempt_mode(message, params)
|
|
354
|
+
response = nil
|
|
355
|
+
if(params[:channel])
|
|
356
|
+
channel = Helpers.find_model(params[:channel])
|
|
357
|
+
if(channel.is_a?(Models::Channel))
|
|
358
|
+
BanModeExempt.find_or_create(:channel_id => channel.pk, :mode => params[:mode])
|
|
359
|
+
response = 'Mode exemption has been added'
|
|
360
|
+
else
|
|
361
|
+
response = "Failed to find given channel: #{params[:channel]}"
|
|
362
|
+
end
|
|
363
|
+
else
|
|
364
|
+
BanModeExempt.find_or_create(:channel_id => nil, :mode => params[:mode])
|
|
365
|
+
response = 'Mode exemption has been added'
|
|
366
|
+
end
|
|
367
|
+
reply message.replyto, response
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
# message:: ModSpox::Messages::Incoming::Privmsg
|
|
371
|
+
# params:: parameters
|
|
372
|
+
# Add ban exemption for a given nick
|
|
373
|
+
def exempt_nick(message, params)
|
|
374
|
+
response = ''
|
|
375
|
+
nick = Helpers.find_model(params[:nick])
|
|
376
|
+
unless(nick.is_a?(Models::Nick))
|
|
377
|
+
reply message.replyto, "\2Error:\2 Failed to find record of: #{params[:nick]}"
|
|
378
|
+
return
|
|
379
|
+
end
|
|
380
|
+
channel = params[:channel] ? Helpers.find_model(params[:channel]) : nil
|
|
381
|
+
if(channel)
|
|
382
|
+
if(channel.is_a?(Models::Channel))
|
|
383
|
+
BanNickExempt.find_or_create(:channel_id => channel.pk, :nick_id => nick.pk)
|
|
384
|
+
response = "Nick exemption for \2#{params[:nick]}\2 has been added to channel: \2#{params[:channel]}\2"
|
|
385
|
+
else
|
|
386
|
+
response = "Failed to find given channel: #{params[:channel]}"
|
|
387
|
+
end
|
|
388
|
+
else
|
|
389
|
+
BanNickExempt.find_or_create(:nick_id => nick.pk)
|
|
390
|
+
response = "Nick exemption for \2#{params[:nick]}\2 has been added for all channels"
|
|
391
|
+
end
|
|
392
|
+
reply message.replyto, response
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
# message:: ModSpox::Messages::Incoming::Privmsg
|
|
396
|
+
# params:: parameters
|
|
397
|
+
# Add ban exemption for sources matching a given mask
|
|
398
|
+
def exempt_source(message, params)
|
|
399
|
+
channel = params[:channel] ? Helpers.find_model(params[:channel]) : nil
|
|
400
|
+
response = ''
|
|
401
|
+
if(channel)
|
|
402
|
+
if(channel.is_a?(Models::Channel))
|
|
403
|
+
BanSourceExempt.find_or_create(:channel_id => channel.pk, :source => params[:source])
|
|
404
|
+
reponse = "Added exempt source: #{params[:source]} to channel: #{params[:channel]}"
|
|
405
|
+
else
|
|
406
|
+
response = "Failed to find given channel: #{params[:channel]}"
|
|
407
|
+
end
|
|
408
|
+
else
|
|
409
|
+
BanSourceExempt.find_or_create(:channel_id => nil, :source => params[:source])
|
|
410
|
+
response = "Added global exemption for source: #{params[:source]}"
|
|
411
|
+
end
|
|
412
|
+
reply message.replyto, response
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
# message:: ModSpox::Messages::Incoming::Privmsg
|
|
416
|
+
# params:: parameters
|
|
417
|
+
# List given type of current ban exemptions
|
|
418
|
+
def exempt_list(message, params)
|
|
419
|
+
output = []
|
|
420
|
+
if(params[:type] == 'nick')
|
|
421
|
+
output << 'Current nick exemptions:'
|
|
422
|
+
BanNickExempt.all.each do |record|
|
|
423
|
+
if(record.channel)
|
|
424
|
+
output << "\2#{record.pk}:\2 \2#{record.nick.nick}\2 is exempt in \2#{record.channel.name}\2"
|
|
425
|
+
else
|
|
426
|
+
output << "\2#{record.pk}:\2 \2#{record.nick.nick}\2 is exempt in \2all\2 channels"
|
|
427
|
+
end
|
|
428
|
+
end
|
|
429
|
+
elsif(params[:type] == 'mode')
|
|
430
|
+
output << 'Current mode exemptions:'
|
|
431
|
+
BanModeExempt.all.each do |record|
|
|
432
|
+
mode = record.mode == 'o' ? 'operator' : 'voice'
|
|
433
|
+
if(record.channel)
|
|
434
|
+
output << "\2#{record.pk}:\2 mode: \2#{mode}\2 is exempt in \2#{record.channel.name}\2"
|
|
435
|
+
else
|
|
436
|
+
output << "\2#{record.pk}:\2 mode: \2#{mode}\2 is exempt in \2all\2 channels"
|
|
437
|
+
end
|
|
438
|
+
end
|
|
439
|
+
elsif(params[:type] == 'source')
|
|
440
|
+
output << 'Current source exemptions:'
|
|
441
|
+
BanSourceExempt.all.each do |record|
|
|
442
|
+
if(record.channel)
|
|
443
|
+
output << "\2#{record.pk}:\2 sources matching: #{record.source} are exempt in \2#{record.channel.name}\2"
|
|
444
|
+
else
|
|
445
|
+
output << "\2#{record.pk}:\2 sources matching: #{record.source} are exempt in \2all\2 channels"
|
|
446
|
+
end
|
|
447
|
+
end
|
|
448
|
+
end
|
|
449
|
+
reply message.replyto, output
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
# message:: ModSpox::Messages::Incoming::Privmsg
|
|
453
|
+
# params:: parameters
|
|
454
|
+
# Remove given exemption from given list
|
|
455
|
+
def exempt_remove(message, params)
|
|
456
|
+
response = 'Exemption has been removed'
|
|
457
|
+
record = nil
|
|
458
|
+
case params[:type]
|
|
459
|
+
when 'nick'
|
|
460
|
+
record = BanNickExempt[params[:id].to_i]
|
|
461
|
+
when 'mode'
|
|
462
|
+
record = BanModeExempt[params[:id].to_i]
|
|
463
|
+
when 'source'
|
|
464
|
+
record = BanSourceExempt[params[:id].to_i]
|
|
465
|
+
end
|
|
466
|
+
if(record)
|
|
467
|
+
record.destroy
|
|
468
|
+
else
|
|
469
|
+
response = "Failed to find exemption of type: #{params[:type]} with ID: #{params[:id]}"
|
|
470
|
+
end
|
|
471
|
+
reply message.replyto, response
|
|
472
|
+
end
|
|
473
|
+
|
|
474
|
+
# nick:: ModSpox::Models::Nick
|
|
475
|
+
# channel:: ModSpox::Models::Channel
|
|
476
|
+
# Check if nick is currently exempt from bans
|
|
477
|
+
def check_exempt(nick, channel)
|
|
478
|
+
return true unless BanNickExempt.filter('nick_id = ? AND (channel_id = ? OR channel_id is null)', nick.pk, channel.pk).first.nil?
|
|
479
|
+
return true if !BanModeExempt.filter("mode = 'o' AND (channel_id = ? OR channel_id is null)", channel.pk).first.nil? && nick.is_op?(channel)
|
|
480
|
+
return true if !BanModeExempt.filter("mode = 'v' AND (channel_id = ? OR channel_id is null)", channel.pk).first.nil? && nick.is_voice?(channel)
|
|
481
|
+
BanSourceExempt.filter('channel_id = ? OR channel_id is null', channel.pk).each do |record|
|
|
482
|
+
regex = Regexp.new(record.source)
|
|
483
|
+
return true unless regex.match(nick.source).nil?
|
|
484
|
+
end
|
|
485
|
+
return false
|
|
486
|
+
end
|
|
487
|
+
|
|
335
488
|
class BanRecord < Sequel::Model
|
|
336
489
|
set_schema do
|
|
337
490
|
primary_key :id
|
|
@@ -346,7 +499,7 @@ class Banner < ModSpox::Plugin
|
|
|
346
499
|
end
|
|
347
500
|
|
|
348
501
|
before_create do
|
|
349
|
-
|
|
502
|
+
update_values(:stamp => Time.now)
|
|
350
503
|
end
|
|
351
504
|
|
|
352
505
|
def channel
|
|
@@ -383,10 +536,62 @@ class Banner < ModSpox::Plugin
|
|
|
383
536
|
end
|
|
384
537
|
end
|
|
385
538
|
|
|
539
|
+
class BanNickExempt < Sequel::Model
|
|
540
|
+
set_schema do
|
|
541
|
+
primary_key :id
|
|
542
|
+
foreign_key :nick_id, :table => :nicks, :null => false
|
|
543
|
+
foreign_key :channel_id, :table => :channels
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
def nick
|
|
547
|
+
return Models::Nick[nick_id]
|
|
548
|
+
end
|
|
549
|
+
|
|
550
|
+
def channel
|
|
551
|
+
return Models::Channel[channel_id]
|
|
552
|
+
end
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
class BanSourceExempt < Sequel::Model
|
|
556
|
+
set_schema do
|
|
557
|
+
primary_key :id
|
|
558
|
+
varchar :source, :null => false
|
|
559
|
+
foreign_key :channel_id, :table => :channels
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
def channel
|
|
563
|
+
return Models::Channel[channel_id]
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
def mask
|
|
567
|
+
return values[:source] ? Marshal.load(values[:source].unpack('m')[0]) : nil
|
|
568
|
+
end
|
|
569
|
+
|
|
570
|
+
def mask=(val)
|
|
571
|
+
update_values(:source => [Marshal.dump(val)].pack('m'))
|
|
572
|
+
end
|
|
573
|
+
|
|
574
|
+
end
|
|
575
|
+
|
|
576
|
+
class BanModeExempt < Sequel::Model
|
|
577
|
+
set_schema do
|
|
578
|
+
primary_key :id
|
|
579
|
+
varchar :mode, :null => false
|
|
580
|
+
foreign_key :channel_id, :table => :channels, :unique => true
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
def channel
|
|
584
|
+
return Models::Channel[channel_id]
|
|
585
|
+
end
|
|
586
|
+
end
|
|
587
|
+
|
|
386
588
|
class NotOperator < Exceptions::BotException
|
|
387
589
|
end
|
|
388
590
|
|
|
389
591
|
class NotInChannel < Exceptions::BotException
|
|
390
592
|
end
|
|
593
|
+
|
|
594
|
+
class BanExemption < Exceptions::BotException
|
|
595
|
+
end
|
|
391
596
|
|
|
392
597
|
end
|
|
@@ -11,7 +11,7 @@ class Helper < ModSpox::Plugin
|
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def default_help(message, params)
|
|
14
|
-
plugins = Signature.map(:plugin)
|
|
14
|
+
plugins = Signature.select(:plugin).map(:plugin)
|
|
15
15
|
plugins.uniq!
|
|
16
16
|
reply message.replyto, "Plugins currently available for help: #{plugins.join(', ')}"
|
|
17
17
|
reply message.replyto, "Request help on a plugin: !help Plugin"
|
|
@@ -11,8 +11,8 @@ class PluginLoader < ModSpox::Plugin
|
|
|
11
11
|
:group_id => admin.pk, :description => 'Load the given plugin').params = [:plugin]
|
|
12
12
|
Models::Signature.find_or_create(:signature => 'plugins unload (\S+)', :plugin => name, :method => 'unload_plugin',
|
|
13
13
|
:group_id => admin.pk, :description => 'Unload given plugin').params = [:plugin]
|
|
14
|
-
Models::Signature.find_or_create(:signature => 'plugins reload', :plugin => name, :method => 'reload_plugin',
|
|
15
|
-
:group_id => admin.pk, :description => 'Reload plugins')
|
|
14
|
+
Models::Signature.find_or_create(:signature => 'plugins reload ?(\S+)?', :plugin => name, :method => 'reload_plugin',
|
|
15
|
+
:group_id => admin.pk, :description => 'Reload single plugin or all plugins if names not provided').params = [:plugin]
|
|
16
16
|
@pipeline.hook(self, :get_module, :Internal_PluginModuleResponse)
|
|
17
17
|
@plugins_mod = nil
|
|
18
18
|
end
|
|
@@ -21,10 +21,11 @@ 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
|
-
|
|
24
|
+
output = ["\2Currently available plugins:\2"]
|
|
25
25
|
find_plugins.each_pair do | plugin, path |
|
|
26
|
-
|
|
26
|
+
output << "\2#{plugin}:\2 #{path}"
|
|
27
27
|
end
|
|
28
|
+
reply message.replyto, output
|
|
28
29
|
end
|
|
29
30
|
|
|
30
31
|
# message:: ModSpox::Messages::Incoming::Privmsg
|
|
@@ -65,8 +66,23 @@ class PluginLoader < ModSpox::Plugin
|
|
|
65
66
|
# params:: matching signature params
|
|
66
67
|
# Reloads plugins
|
|
67
68
|
def reload_plugin(message, params)
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
if(params[:plugin])
|
|
70
|
+
users = plugin_discovery(BotConfig[:userpluginpath])
|
|
71
|
+
extras = plugin_discovery(BotConfig[:pluginextraspath])
|
|
72
|
+
fresh = nil
|
|
73
|
+
stale = nil
|
|
74
|
+
users.each_pair{|name, path| stale = path if name == params[:plugin]}
|
|
75
|
+
extras.each_pair{|name, path| fresh = path if name == params[:plugin]}
|
|
76
|
+
if(fresh && stale)
|
|
77
|
+
@pipeline << Messages::Internal::PluginReload.new(fresh, stale)
|
|
78
|
+
reply message.replyto, "Reloading #{params[:plugin]}"
|
|
79
|
+
else
|
|
80
|
+
reply message.replyto, "\2Error:\2 Failed to find new and stale versions of: #{params[:plugin]}"
|
|
81
|
+
end
|
|
82
|
+
else
|
|
83
|
+
@pipeline << Messages::Internal::PluginReload.new
|
|
84
|
+
@pipeline << Messages::Outgoing::Privmsg.new(message.replyto, 'Full plugin reload requested')
|
|
85
|
+
end
|
|
70
86
|
end
|
|
71
87
|
|
|
72
88
|
# message:: ModSpox::Messages::Internal::PluginModuleResponse
|
|
@@ -16,10 +16,11 @@ include Messages::Outgoing
|
|
|
16
16
|
def active(message, params)
|
|
17
17
|
triggers = Models::Trigger.filter(:active => true)
|
|
18
18
|
if(triggers)
|
|
19
|
-
|
|
19
|
+
output = ["\2Currently active triggers:\2"]
|
|
20
20
|
triggers.each do |t|
|
|
21
|
-
|
|
21
|
+
output << "#{t.pk}: #{t.trigger}"
|
|
22
22
|
end
|
|
23
|
+
reply message.replyto, output
|
|
23
24
|
else
|
|
24
25
|
@pipeline << Privmsg.new(message.replyto, 'No triggers are currently active')
|
|
25
26
|
end
|
|
@@ -28,10 +29,11 @@ include Messages::Outgoing
|
|
|
28
29
|
def list(message, params)
|
|
29
30
|
triggers = Models::Trigger.all
|
|
30
31
|
if(triggers)
|
|
31
|
-
|
|
32
|
+
output = ["\2Trigger listing:\2"]
|
|
32
33
|
triggers.each do |t|
|
|
33
|
-
|
|
34
|
+
output << "#{t.pk}: #{t.trigger} -> \2#{t.active ? "activated" : "not activated"}\2"
|
|
34
35
|
end
|
|
36
|
+
reply message.replyto, output
|
|
35
37
|
else
|
|
36
38
|
@pipeline << Privmsg.new(message.replyto, 'No triggers found')
|
|
37
39
|
end
|
data/lib/mod_spox/Action.rb
CHANGED
data/lib/mod_spox/BaseConfig.rb
CHANGED
data/lib/mod_spox/Bot.rb
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
['mod_spox/Logger',
|
|
2
|
+
'mod_spox/Socket',
|
|
3
|
+
'mod_spox/Pipeline',
|
|
4
|
+
'mod_spox/PluginManager',
|
|
5
|
+
'mod_spox/MessageFactory',
|
|
6
|
+
'mod_spox/BaseConfig',
|
|
7
|
+
'mod_spox/Timer',
|
|
8
|
+
'mod_spox/messages/Messages',
|
|
9
|
+
'mod_spox/models/Models',
|
|
10
|
+
'mod_spox/Monitors',
|
|
11
|
+
'mod_spox/Helpers'].each{|f|require f}
|
|
1
12
|
module ModSpox
|
|
2
13
|
|
|
3
14
|
class Bot
|
|
@@ -36,10 +47,10 @@ module ModSpox
|
|
|
36
47
|
|
|
37
48
|
# Run the bot
|
|
38
49
|
def run
|
|
39
|
-
trap('SIGTERM'){ Logger.log("Caught SIGTERM"); @shutdown = true; @waiter.wakeup; sleep(0.1); Thread.current.exit }
|
|
40
|
-
trap('SIGKILL'){ Logger.log("Caught SIGKILL"); @shutdown = true; @waiter.wakeup; sleep(0.1); Thread.current.exit }
|
|
41
|
-
trap('SIGINT'){ Logger.log("Caught SIGINT"); @shutdown = true; @waiter.wakeup; sleep(0.1); Thread.current.exit }
|
|
42
|
-
trap('SIGQUIT'){ Logger.log("Caught SIGQUIT"); @shutdown = true; @waiter.wakeup; sleep(0.1); Thread.current.exit }
|
|
50
|
+
trap('SIGTERM'){ Logger.log("Caught SIGTERM"); @shutdown = true; @waiter.wakeup; sleep(0.1); Thread.current.exit; Logger.kill; }
|
|
51
|
+
trap('SIGKILL'){ Logger.log("Caught SIGKILL"); @shutdown = true; @waiter.wakeup; sleep(0.1); Thread.current.exit; Logger.kill; }
|
|
52
|
+
trap('SIGINT'){ Logger.log("Caught SIGINT"); @shutdown = true; @waiter.wakeup; sleep(0.1); Thread.current.exit; Logger.kill; }
|
|
53
|
+
trap('SIGQUIT'){ Logger.log("Caught SIGQUIT"); @shutdown = true; @waiter.wakeup; sleep(0.1); Thread.current.exit; Logger.kill; }
|
|
43
54
|
until @shutdown do
|
|
44
55
|
@timer.start
|
|
45
56
|
@pipeline << Messages::Internal::BotInitialized.new
|
|
@@ -126,7 +137,8 @@ module ModSpox
|
|
|
126
137
|
:Outgoing_Whois => :whois, :Internal_EstablishConnection => :bot_connect,
|
|
127
138
|
:Internal_StatusRequest => :status, :Internal_ChangeNick => :set_nick,
|
|
128
139
|
:Internal_NickRequest => :get_nick, :Internal_HaltBot => :halt,
|
|
129
|
-
:Internal_Disconnected => :disconnected, :Internal_TimerClear => :clear_timer
|
|
140
|
+
:Internal_Disconnected => :disconnected, :Internal_TimerClear => :clear_timer,
|
|
141
|
+
:Outgoing_Raw => :raw
|
|
130
142
|
}.each_pair{ |type,method| @pipeline.hook(self, method, type) }
|
|
131
143
|
end
|
|
132
144
|
|
|
@@ -273,7 +285,15 @@ module ModSpox
|
|
|
273
285
|
target = message.target.name if message.target.is_a?(Models::Channel)
|
|
274
286
|
target = message.target.nick if message.target.is_a?(Models::Nick)
|
|
275
287
|
target = message.target unless target
|
|
276
|
-
|
|
288
|
+
messages = message.message.is_a?(Array) ? message.message : [message.message]
|
|
289
|
+
messages.each do |content|
|
|
290
|
+
while(content.size > 450)
|
|
291
|
+
output = content[0..449]
|
|
292
|
+
content.slice!(0, 449) #(450, content.size)
|
|
293
|
+
@socket << "PRIVMSG #{target} :#{message.is_action? ? "\cAACTION #{output}\cA" : output}"
|
|
294
|
+
end
|
|
295
|
+
@socket << "PRIVMSG #{target} :#{message.is_action? ? "\cAACTION #{content}\cA" : content}"
|
|
296
|
+
end
|
|
277
297
|
end
|
|
278
298
|
|
|
279
299
|
# message:: Messages::Outgoing::Notice message
|
|
@@ -458,6 +478,12 @@ module ModSpox
|
|
|
458
478
|
@socket << "ISON #{nick}"
|
|
459
479
|
end
|
|
460
480
|
|
|
481
|
+
# message:: Messages::Outoing::Raw message
|
|
482
|
+
# Send raw message to server
|
|
483
|
+
def raw(message)
|
|
484
|
+
@socket << message.message
|
|
485
|
+
end
|
|
486
|
+
|
|
461
487
|
private
|
|
462
488
|
|
|
463
489
|
# Cleans information from models to avoid
|
data/lib/mod_spox/BotConfig.rb
CHANGED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module ModSpox
|
|
2
|
+
class Cache
|
|
3
|
+
def initialize(size)
|
|
4
|
+
@size = size
|
|
5
|
+
@cache = Hash.new
|
|
6
|
+
@times = Hash.new
|
|
7
|
+
@store_lock = Mutex.new
|
|
8
|
+
@read_lock = Mutex.new
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def [](key)
|
|
12
|
+
if(@cache.has_key?(key.to_sym))
|
|
13
|
+
@times[key.to_sym] = Time.now
|
|
14
|
+
return @cache[key.to_sym]
|
|
15
|
+
else
|
|
16
|
+
return nil
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def has_key?(key)
|
|
21
|
+
@read_lock.synchronize do
|
|
22
|
+
return @cache.has_key?(key.to_sym)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def []=(key, value)
|
|
27
|
+
@store_lock.synchronize do
|
|
28
|
+
if(@cache.size > @size)
|
|
29
|
+
del_key = oldest_key
|
|
30
|
+
unless(key.nil?)
|
|
31
|
+
@cache.delete(del_key)
|
|
32
|
+
@times.delete(del_key)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
@cache[key.to_sym] = value
|
|
36
|
+
@times[key.to_sym] = Time.now
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def delete(key)
|
|
41
|
+
@read_lock.synchronize do
|
|
42
|
+
@cache.delete(key.to_sym) if @cache.has_key?(key.to_sym)
|
|
43
|
+
@times.delete(key.to_sym) if @times.has_key?(key.to_sym)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def oldest_key
|
|
50
|
+
result = nil
|
|
51
|
+
@read_lock.synchronize do
|
|
52
|
+
result = @times.sort{|a,b| a[1] <=> b[1]}[0][0]
|
|
53
|
+
end
|
|
54
|
+
return result
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
['etc',
|
|
2
|
-
'mod_spox/
|
|
1
|
+
['etc',
|
|
2
|
+
'mod_spox/Database',
|
|
3
|
+
'mod_spox/BotConfig',
|
|
4
|
+
'mod_spox/BaseConfig'
|
|
5
|
+
'mod_spox/models/Models',
|
|
6
|
+
'mod_spox/Helpers'].each{|f|require f}
|
|
3
7
|
|
|
4
8
|
|
|
5
9
|
module ModSpox
|
data/lib/mod_spox/Helpers.rb
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
['timeout',
|
|
2
|
+
'net/http',
|
|
3
|
+
'mod_spox/models/Nick',
|
|
4
|
+
'mod_spox/models/Channel',
|
|
5
|
+
'mod_spox/models/Server',
|
|
6
|
+
'mod_spox/Cache',
|
|
7
|
+
'mod_spox/Logger'].each{|f|require f}
|
|
8
|
+
|
|
3
9
|
module ModSpox
|
|
4
10
|
module Helpers
|
|
5
11
|
# secs:: number of seconds
|
|
@@ -60,48 +66,60 @@ module ModSpox
|
|
|
60
66
|
# or channel name. If the string given does not match the required
|
|
61
67
|
# pattern for a channel or nick, the string is returned.
|
|
62
68
|
def Helpers.find_model(string, create=true)
|
|
63
|
-
|
|
64
|
-
@@nick_cache = {} unless Helpers.class_variable_defined?(:@@nick_cache)
|
|
69
|
+
Helpers.initialize_caches
|
|
65
70
|
if(string =~ /^[A-Za-z\|\\\{\}\[\]\^\`~\_\-]+[A-Za-z0-9\|\\\{\}\[\]\^\`~\_\-]*$/)
|
|
66
|
-
Logger.log("Model: #{string} -> Nick")
|
|
71
|
+
Logger.log("Model: #{string} -> Nick", 30)
|
|
67
72
|
nick = nil
|
|
68
|
-
if(@@nick_cache.has_key?(string.to_sym))
|
|
73
|
+
if(@@nick_cache.has_key?(string.downcase.to_sym))
|
|
69
74
|
begin
|
|
70
|
-
nick = Models::Nick[@@nick_cache[string.to_sym]]
|
|
75
|
+
nick = Models::Nick[@@nick_cache[string.downcase.to_sym]]
|
|
71
76
|
Logger.log("Handler cache hit for nick: #{string}", 30)
|
|
77
|
+
if(nick.nick.downcase != string.downcase)
|
|
78
|
+
Logger.log("Nick returned from cache invalid. Expecting #{string} but got #{nick.nick}", 30)
|
|
79
|
+
nick = nil
|
|
80
|
+
end
|
|
72
81
|
rescue Object => boom
|
|
73
|
-
Logger.log("Failed to grab cached nick: #{boom}")
|
|
82
|
+
Logger.log("Failed to grab cached nick: #{boom}", 30)
|
|
74
83
|
end
|
|
75
84
|
end
|
|
76
85
|
unless(nick)
|
|
77
86
|
nick = Models::Nick.locate(string, create)
|
|
78
|
-
@@nick_cache[string.to_sym] = nick.pk if nick.is_a?(Models::Nick)
|
|
79
|
-
Logger.log("Nick was retrieved from database")
|
|
87
|
+
@@nick_cache[string.downcase.to_sym] = nick.pk if nick.is_a?(Models::Nick)
|
|
88
|
+
Logger.log("Nick was retrieved from database", 30)
|
|
80
89
|
end
|
|
81
90
|
return nick
|
|
82
91
|
elsif(string =~ /^[&#+!]/)
|
|
83
|
-
Logger.log("Model: #{string} -> Channel")
|
|
84
|
-
if(@@channel_cache.has_key?(string.to_sym))
|
|
92
|
+
Logger.log("Model: #{string} -> Channel", 30)
|
|
93
|
+
if(@@channel_cache.has_key?(string.downcase.to_sym))
|
|
85
94
|
begin
|
|
86
|
-
channel = Models::Channel[@@channel_cache[string.to_sym]]
|
|
95
|
+
channel = Models::Channel[@@channel_cache[string.downcase.to_sym]]
|
|
87
96
|
Logger.log("Handler cache hit for channel: #{string}", 30)
|
|
97
|
+
if(string.downcase != channel.name.downcase)
|
|
98
|
+
Logger.log("Channel returned from cache invalid. Expecting #{string} but got #{channel.name}", 30)
|
|
99
|
+
channel = nil
|
|
100
|
+
end
|
|
88
101
|
rescue Object => boom
|
|
89
|
-
Logger.log("Failed to grab cached channel: #{boom}")
|
|
102
|
+
Logger.log("Failed to grab cached channel: #{boom}", 30)
|
|
90
103
|
end
|
|
91
104
|
end
|
|
92
105
|
unless(channel)
|
|
93
106
|
channel = Models::Channel.locate(string, create)
|
|
94
|
-
@@channel_cache[string.to_sym] = channel.pk if channel.is_a?(Models::Channel)
|
|
95
|
-
Logger.log("Channel was retrieved from database")
|
|
107
|
+
@@channel_cache[string.downcase.to_sym] = channel.pk if channel.is_a?(Models::Channel)
|
|
108
|
+
Logger.log("Channel was retrieved from database", 30)
|
|
96
109
|
end
|
|
97
110
|
return channel
|
|
98
111
|
elsif(model = Models::Server.filter(:host => string, :connected => true).first)
|
|
99
|
-
Logger.log("Model: #{string} -> Server")
|
|
112
|
+
Logger.log("Model: #{string} -> Server", 30)
|
|
100
113
|
return model
|
|
101
114
|
else
|
|
102
|
-
Logger.log("FAIL Model: #{string} -> No match")
|
|
115
|
+
Logger.log("FAIL Model: #{string} -> No match", 30)
|
|
103
116
|
return string
|
|
104
117
|
end
|
|
105
118
|
end
|
|
119
|
+
|
|
120
|
+
def Helpers.initialize_caches
|
|
121
|
+
@@nick_cache = Cache.new(20) unless Helpers.class_variable_defined?(:@@nick_cache)
|
|
122
|
+
@@channel_cache = Cache.new(5) unless Helpers.class_variable_defined?(:@@channel_cache)
|
|
123
|
+
end
|
|
106
124
|
end
|
|
107
125
|
end
|
data/lib/mod_spox/Loader.rb
CHANGED
|
@@ -1,66 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
['mod_spox/Exceptions',
|
|
2
|
+
'mod_spox/BotConfig',
|
|
3
|
+
'mod_spox/BaseConfig',
|
|
4
|
+
'mod_spox/Database'].each{|f|require f}
|
|
2
5
|
|
|
3
|
-
|
|
4
|
-
# Requires all .rb files found within the given directory
|
|
5
|
-
# and all its subdirectories
|
|
6
|
-
def load_directory(directory='')
|
|
7
|
-
base = File.dirname(__FILE__)
|
|
8
|
-
Dir.new("#{base}/#{directory}").each{|item|
|
|
9
|
-
next if ['.', '..'].include?(item)
|
|
10
|
-
if(File.directory?("#{base}/#{directory}/#{item}"))
|
|
11
|
-
load_directory("#{directory}/#{item}")
|
|
12
|
-
elsif(item =~ /\.rb$/)
|
|
13
|
-
item = "#{directory}/#{item}" if directory.length > 0
|
|
14
|
-
begin
|
|
15
|
-
require "mod_spox/#{item}"
|
|
16
|
-
rescue Object => boom
|
|
17
|
-
@@failed << item
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
}
|
|
21
|
-
@@failed.each{|f|
|
|
22
|
-
begin
|
|
23
|
-
require "mod_spox/#{f}"
|
|
24
|
-
@@failed.delete(f)
|
|
25
|
-
rescue Object => boom
|
|
26
|
-
# do nothing #
|
|
27
|
-
end
|
|
28
|
-
}
|
|
29
|
-
end
|
|
6
|
+
module ModSpox
|
|
30
7
|
|
|
31
8
|
# Loads all files needed by the bot
|
|
32
9
|
def initialize_bot
|
|
33
10
|
setup_adapter
|
|
34
|
-
@@failed = Array.new
|
|
35
|
-
load_directory
|
|
36
|
-
tries = 0
|
|
37
|
-
message = nil
|
|
38
|
-
until @@failed.empty? || tries > 5 do
|
|
39
|
-
@@failed.each{|f|
|
|
40
|
-
begin
|
|
41
|
-
require "mod_spox/#{f}"
|
|
42
|
-
@@failed.delete(f)
|
|
43
|
-
rescue Object => boom
|
|
44
|
-
message = boom
|
|
45
|
-
end
|
|
46
|
-
}
|
|
47
|
-
tries += 1
|
|
48
|
-
end
|
|
49
|
-
if(tries > 5)
|
|
50
|
-
puts 'Failed'
|
|
51
|
-
puts "ERROR: Failed to load required libraries"
|
|
52
|
-
puts "Reason: #{message}"
|
|
53
|
-
puts "#{message.backtrace.join("\n")}"
|
|
54
|
-
exit
|
|
55
|
-
end
|
|
56
11
|
end
|
|
57
12
|
|
|
58
13
|
# Setup the DataMapper adapter
|
|
59
14
|
def setup_adapter
|
|
60
|
-
require 'mod_spox/Exceptions'
|
|
61
|
-
require 'mod_spox/BotConfig'
|
|
62
|
-
require 'mod_spox/BaseConfig'
|
|
63
|
-
require 'mod_spox/Database'
|
|
64
15
|
memcache = false
|
|
65
16
|
config = BaseConfig.new(BotConfig[:userconfigpath])
|
|
66
17
|
if(config[:memcache] == 'on')
|