mod_spox 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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')
|