mod_spox 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +31 -1
- data/LICENSE +674 -0
- data/README.rdoc +73 -0
- data/bin/mod_spox +28 -28
- data/data/mod_spox/extras/AOLSpeak.rb +2 -3
- data/data/mod_spox/extras/AutoKick.rb +10 -23
- data/data/mod_spox/extras/AutoMode.rb +12 -23
- data/data/mod_spox/extras/Bash.rb +55 -0
- data/data/mod_spox/extras/Bouncer.rb +85 -57
- data/data/mod_spox/extras/Bullshit.rb +1 -1
- data/data/mod_spox/extras/Bytes.rb +1 -2
- data/data/mod_spox/extras/Confess.rb +27 -29
- data/data/mod_spox/extras/DCC.rb +11 -20
- data/data/mod_spox/extras/DevWatch.rb +21 -23
- data/data/mod_spox/extras/DownForEveryoneOrJustMe.rb +47 -0
- data/data/mod_spox/extras/EightBall.rb +1 -1
- data/data/mod_spox/extras/FML.rb +35 -0
- data/data/mod_spox/extras/Headers.rb +31 -50
- data/data/mod_spox/extras/Karma.rb +81 -29
- data/data/mod_spox/extras/Logger.rb +2 -2
- data/data/mod_spox/extras/LolSpeak.rb +1 -2
- data/data/mod_spox/extras/PhpCli.rb +138 -8
- data/data/mod_spox/extras/PhpFuncLookup.rb +20 -23
- data/data/mod_spox/extras/Pinger.rb +1 -1
- data/data/mod_spox/extras/Quotes.rb +8 -10
- data/data/mod_spox/extras/RegexTracker.rb +2 -4
- data/data/mod_spox/extras/Roulette.rb +20 -27
- data/data/mod_spox/extras/RubyCli.rb +93 -0
- data/data/mod_spox/extras/Search.rb +17 -3
- data/data/mod_spox/extras/Seen.rb +150 -0
- data/data/mod_spox/extras/SlashdotHeadlineGenerator.rb +500 -0
- data/data/mod_spox/extras/Talk.rb +2 -4
- data/data/mod_spox/extras/Topten.rb +10 -12
- data/data/mod_spox/extras/TracTicket.rb +3 -5
- data/data/mod_spox/extras/Translate.rb +20 -22
- data/data/mod_spox/extras/Twitter.rb +118 -33
- data/data/mod_spox/extras/UrbanDictionary.rb +8 -17
- data/data/mod_spox/extras/Weather.rb +1 -2
- data/data/mod_spox/plugins/Authenticator.rb +93 -98
- data/data/mod_spox/plugins/Banner.rb +26 -56
- data/data/mod_spox/plugins/Helper.rb +5 -6
- data/data/mod_spox/plugins/Initializer.rb +4 -14
- data/data/mod_spox/plugins/Joiner.rb +1 -1
- data/data/mod_spox/plugins/Nicker.rb +13 -0
- data/data/mod_spox/plugins/Parter.rb +2 -2
- data/data/mod_spox/plugins/Permissions.rb +60 -0
- data/data/mod_spox/plugins/PluginLoader.rb +7 -12
- data/data/mod_spox/plugins/Ponger.rb +51 -0
- data/data/mod_spox/plugins/Quitter.rb +1 -2
- data/data/mod_spox/plugins/Servers.rb +57 -0
- data/data/mod_spox/plugins/Status.rb +3 -2
- data/data/mod_spox/plugins/Triggers.rb +9 -9
- data/lib/mod_spox/Bot.rb +109 -33
- data/lib/mod_spox/BotConfig.rb +2 -2
- data/lib/mod_spox/ConfigurationWizard.rb +12 -12
- data/lib/mod_spox/Database.rb +1 -4
- data/lib/mod_spox/Exceptions.rb +26 -0
- data/lib/mod_spox/Helpers.rb +29 -68
- data/lib/mod_spox/Loader.rb +23 -24
- data/lib/mod_spox/Logger.rb +19 -17
- data/lib/mod_spox/MessageFactory.rb +50 -24
- data/lib/mod_spox/Pipeline.rb +21 -7
- data/lib/mod_spox/Plugin.rb +27 -3
- data/lib/mod_spox/PluginManager.rb +28 -15
- data/lib/mod_spox/PriorityQueue.rb +69 -0
- data/lib/mod_spox/Socket.rb +93 -51
- data/lib/mod_spox/Sockets.rb +76 -63
- data/lib/mod_spox/Timer.rb +21 -141
- data/lib/mod_spox/Version.rb +14 -0
- data/lib/mod_spox/handlers/BadNick.rb +1 -1
- data/lib/mod_spox/handlers/Bounce.rb +5 -5
- data/lib/mod_spox/handlers/Created.rb +13 -5
- data/lib/mod_spox/handlers/Handler.rb +12 -3
- data/lib/mod_spox/handlers/Invite.rb +14 -8
- data/lib/mod_spox/handlers/Join.rb +24 -20
- data/lib/mod_spox/handlers/Kick.rb +22 -13
- data/lib/mod_spox/handlers/Mode.rb +42 -36
- data/lib/mod_spox/handlers/Motd.rb +4 -0
- data/lib/mod_spox/handlers/Names.rb +66 -39
- data/lib/mod_spox/handlers/Nick.rb +20 -14
- data/lib/mod_spox/handlers/Part.rb +25 -8
- data/lib/mod_spox/handlers/Ping.rb +11 -5
- data/lib/mod_spox/handlers/Pong.rb +9 -5
- data/lib/mod_spox/handlers/Privmsg.rb +25 -17
- data/lib/mod_spox/handlers/Quit.rb +13 -8
- data/lib/mod_spox/handlers/Topic.rb +4 -0
- data/lib/mod_spox/handlers/Welcome.rb +16 -24
- data/lib/mod_spox/handlers/Who.rb +64 -48
- data/lib/mod_spox/handlers/Whois.rb +92 -60
- data/lib/mod_spox/messages/incoming/Nick.rb +2 -2
- data/lib/mod_spox/messages/incoming/Privmsg.rb +1 -1
- data/lib/mod_spox/messages/incoming/Whois.rb +1 -0
- data/lib/mod_spox/messages/internal/EstablishConnection.rb +1 -1
- data/lib/mod_spox/messages/internal/PluginsReady.rb +10 -0
- data/lib/mod_spox/messages/internal/QueueSocket.rb +8 -0
- data/lib/mod_spox/messages/internal/Reconnect.rb +8 -0
- data/lib/mod_spox/messages/internal/UnqueueSocket.rb +8 -0
- data/lib/mod_spox/migrations/002_persistent_sigs.rb +14 -0
- data/lib/mod_spox/migrations/003_auth_restructure.rb +31 -0
- data/lib/mod_spox/migrations/004_mode_index_fix.rb +18 -0
- data/lib/mod_spox/migrations/005_nick_mode_nopark.rb +18 -0
- data/lib/mod_spox/models/Auth.rb +16 -46
- data/lib/mod_spox/models/AuthMask.rb +13 -0
- data/lib/mod_spox/models/Channel.rb +46 -27
- data/lib/mod_spox/models/Config.rb +10 -19
- data/lib/mod_spox/models/Group.rb +20 -8
- data/lib/mod_spox/models/Models.rb +1 -1
- data/lib/mod_spox/models/Nick.rb +105 -113
- data/lib/mod_spox/models/NickMode.rb +23 -9
- data/lib/mod_spox/models/Server.rb +12 -1
- data/lib/mod_spox/models/Setting.rb +12 -16
- data/lib/mod_spox/models/Signature.rb +28 -8
- data/tests/BotHolder.rb +24 -0
- data/tests/handlers/tc_BadNick.rb +21 -0
- data/tests/handlers/tc_Created.rb +24 -0
- data/tests/handlers/tc_Invite.rb +50 -0
- data/tests/handlers/tc_Join.rb +33 -0
- data/tests/handlers/tc_Kick.rb +32 -0
- data/tests/handlers/tc_Mode.rb +85 -0
- data/tests/handlers/tc_Names.rb +35 -0
- data/tests/handlers/tc_Nick.rb +55 -0
- data/tests/handlers/tc_Part.rb +44 -0
- data/tests/handlers/tc_Ping.rb +40 -0
- data/tests/handlers/tc_Pong.rb +28 -0
- data/tests/handlers/tc_Privmsg.rb +85 -0
- data/tests/handlers/tc_Quit.rb +40 -0
- data/tests/handlers/tc_Who.rb +50 -0
- data/tests/handlers/tc_Whois.rb +61 -0
- data/tests/models/tc_Auth.rb +34 -0
- data/tests/models/tc_Channel.rb +52 -0
- data/tests/models/tc_Config.rb +19 -0
- data/tests/models/tc_Nick.rb +142 -0
- data/tests/models/tc_NickMode.rb +40 -0
- data/tests/models/tc_Setting.rb +21 -0
- data/tests/models/tc_Signature.rb +14 -0
- data/tests/run_tests.rb +4 -0
- metadata +284 -212
- data/README +0 -36
- data/lib/mod_spox/Cache.rb +0 -57
- data/lib/mod_spox/Monitors.rb +0 -84
- data/lib/mod_spox/Pool.rb +0 -164
- data/lib/mod_spox/models/AuthGroup.rb +0 -16
- data/lib/mod_spox/models/ChannelMode.rb +0 -14
- data/lib/mod_spox/models/NickChannel.rb +0 -45
- data/lib/mod_spox/models/NickGroup.rb +0 -16
@@ -4,17 +4,15 @@ class Helper < ModSpox::Plugin
|
|
4
4
|
|
5
5
|
def initialize(pipeline)
|
6
6
|
super(pipeline)
|
7
|
-
|
8
|
-
|
9
|
-
Signature.find_or_create(:signature => 'help (\S+)', :plugin => name, :method => 'plugin_help',
|
10
|
-
:description => 'Display help information from given plugin').params = [:plugin]
|
7
|
+
add_sig(:sig => 'help', :method => :default_help, :desc => 'Display default help information')
|
8
|
+
add_sig(:sig => 'help (\S+)', :method => :plugin_help, :desc => 'Display help information from given plugin', :params => [:plugin])
|
11
9
|
end
|
12
10
|
|
13
11
|
def default_help(message, params)
|
14
12
|
plugins = Signature.select(:plugin).map(:plugin)
|
15
13
|
plugins.uniq!
|
16
14
|
reply message.replyto, "Plugins currently available for help: #{plugins.sort.join(', ')}"
|
17
|
-
reply message.replyto, "Request help on a plugin:
|
15
|
+
reply message.replyto, "Request help on a plugin: #{Models::Trigger.filter(:active => true).first.trigger}help Plugin"
|
18
16
|
end
|
19
17
|
|
20
18
|
def plugin_help(message, params)
|
@@ -29,6 +27,7 @@ class Helper < ModSpox::Plugin
|
|
29
27
|
help << "\2Parameters:\2 [#{sig.params.join(' | ')}]" if sig.params
|
30
28
|
help << "\2Auth Group:\2 #{Group[sig.group_id].name}" if sig.group_id
|
31
29
|
help << "\2Description:\2 #{sig.description}" if sig.description
|
30
|
+
help << "\2Requirement:\2 #{['public', 'private'].include?(sig.requirement) ? sig.requirement : 'both'}"
|
32
31
|
output << help.join(' ')
|
33
32
|
end
|
34
33
|
if(message.is_dcc?)
|
@@ -37,7 +36,7 @@ class Helper < ModSpox::Plugin
|
|
37
36
|
reply message.source, output
|
38
37
|
end
|
39
38
|
else
|
40
|
-
Signature.all.each{|s| sigs << s.plugin if /#{s.signature.gsub(
|
39
|
+
Signature.all.each{|s| sigs << s.plugin if /#{s.signature.gsub(/(\s|\().*$/, '')}/ =~ params[:plugin]}
|
41
40
|
if(sigs.count > 0)
|
42
41
|
sigs.uniq!
|
43
42
|
reply message.replyto, "Possible plugin matches for \2#{params[:plugin]}\2: #{sigs.sort.join(', ')}"
|
@@ -12,30 +12,20 @@ class Initializer < ModSpox::Plugin
|
|
12
12
|
# message:: ModSpox::Messages::Internal::BotInitialized
|
13
13
|
# Instructs bot to connect to server
|
14
14
|
def connect(message)
|
15
|
-
|
16
|
-
s = @servers.pop
|
17
|
-
@pipeline << Messages::Internal::EstablishConnection.new(s.host, s.port)
|
15
|
+
@pipeline << Messages::Internal::EstablishConnection.new
|
18
16
|
end
|
19
17
|
|
20
18
|
# message:: ModSpox::Messages::Internal::Connected
|
21
19
|
# Send bot information to server when connection is established
|
22
20
|
def send_info(message)
|
23
|
-
@pipeline << Messages::Outgoing::Nick.new(Models::Config
|
24
|
-
@pipeline << Messages::Outgoing::User.new(Models::Config
|
21
|
+
@pipeline << Messages::Outgoing::Nick.new(Models::Config.val(:bot_nick))
|
22
|
+
@pipeline << Messages::Outgoing::User.new(Models::Config.val(:bot_username), Models::Config.val(:bot_realname), 8)
|
25
23
|
end
|
26
24
|
|
27
25
|
# message:: ModSpox::Messages::Internal::ConnectionFailed or ModSpox::Messages::Internal::Disconnected
|
28
26
|
# Reconnect to server on disconnection or connection failure
|
29
27
|
def reconnect(message)
|
30
|
-
@pipeline << Messages::Internal::
|
31
|
-
end
|
32
|
-
|
33
|
-
private
|
34
|
-
|
35
|
-
def populate_servers
|
36
|
-
Models::Server.reverse_order(:priority).each{|s|
|
37
|
-
@servers << s
|
38
|
-
}
|
28
|
+
@pipeline << Messages::Internal::Reconnect.new
|
39
29
|
end
|
40
30
|
|
41
31
|
end
|
@@ -2,7 +2,7 @@ class Joiner < ModSpox::Plugin
|
|
2
2
|
def initialize(pipeline)
|
3
3
|
super(pipeline)
|
4
4
|
admin = Models::Group.filter(:name => 'admin').first
|
5
|
-
|
5
|
+
add_sig(:sig => 'join (\S+)', :method => :join, :group => admin, :params => [:channel])
|
6
6
|
@pipeline.hook(self, :send_who, :Incoming_Join)
|
7
7
|
end
|
8
8
|
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class Nicker < ModSpox::Plugin
|
2
|
+
def initialize(pipeline)
|
3
|
+
super(pipeline)
|
4
|
+
admin = Models::Group.filter(:name => 'admin').first
|
5
|
+
add_sig(:sig => 'nick (\S+)', :method => :change_nick, :group => admin, :params => [:nick])
|
6
|
+
end
|
7
|
+
|
8
|
+
# message:: ModSpox::Messages::Incoming::Privmsg
|
9
|
+
# Join the given channel
|
10
|
+
def change_nick(message, params)
|
11
|
+
@pipeline << Messages::Outgoing::Nick.new(params[:nick])
|
12
|
+
end
|
13
|
+
end
|
@@ -3,8 +3,8 @@ class Parter < ModSpox::Plugin
|
|
3
3
|
def initialize(pipeline)
|
4
4
|
super(pipeline)
|
5
5
|
admin = Models::Group.filter(:name => 'admin').first
|
6
|
-
|
7
|
-
|
6
|
+
add_sig(:sig => 'part (\S+)', :method => :part, :group => admin, :params => [:channel])
|
7
|
+
add_sig(:sig => 'part', :method => :direct_part, :group => admin)
|
8
8
|
end
|
9
9
|
|
10
10
|
# message:: ModSpox::Messages::Incoming::Privmsg
|
@@ -0,0 +1,60 @@
|
|
1
|
+
class Permissions < ModSpox::Plugin
|
2
|
+
|
3
|
+
def initialize(pipe)
|
4
|
+
super
|
5
|
+
admin = Models::Group.find_or_create(:name => 'admin')
|
6
|
+
add_sig(:sig => 'perm (\S+)', :group => admin, :method => :show_perm, :desc => 'Display permissions for plugin', :params => [:plugin])
|
7
|
+
add_sig(:sig => 'perm (\d+) (\S+)', :group => admin, :method => :set_perm, :desc => 'Sets permission for signature with given ID', :params => [:id, :group])
|
8
|
+
add_sig(:sig => 'group add (\S+)', :group => admin, :method => :add_group, :desc => 'Add a new authentication group', :params => [:group])
|
9
|
+
add_sig(:sig => 'invalid', :group => admin, :method => :invalid, :desc => 'foobar')
|
10
|
+
end
|
11
|
+
|
12
|
+
def show_perm(m, params)
|
13
|
+
output = ["Permissions for signatures owned by \2#{params[:plugin]}\2"]
|
14
|
+
Models::Signature.filter(:plugin => params[:plugin]).each do |s|
|
15
|
+
g = s.group
|
16
|
+
output << "[#{s.pk}] \2#{g.is_a?(Models::Group) ? g.name : 'unset'}\2 - #{s.signature} - #{s.description}"
|
17
|
+
end
|
18
|
+
if(output.size > 1)
|
19
|
+
reply m.replyto, output
|
20
|
+
else
|
21
|
+
error m.replyto, "Failed to locate signatures for given plugin: #{params[:plugin]}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def set_perm(m, params)
|
26
|
+
s = Models::Signature[params[:id].to_i]
|
27
|
+
if(s)
|
28
|
+
if(params[:group] == 'none')
|
29
|
+
g = true
|
30
|
+
else
|
31
|
+
g = Models::Group.filter(:name => params[:group]).first
|
32
|
+
end
|
33
|
+
if(g)
|
34
|
+
s.group_id = g.is_a?(Models::Group) ? g.pk : nil
|
35
|
+
s.save
|
36
|
+
information m.replyto, "Signature with ID #{s.pk} has been updated to group: #{g.is_a?(Models::Group) ? g.name : 'unset'}"
|
37
|
+
else
|
38
|
+
error m.replyto, "Group name is invalid. If it is a new group, add it first. (#{params[:group]})"
|
39
|
+
end
|
40
|
+
else
|
41
|
+
error m.replyto, "Failed to find signature with ID: #{params[:id]}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def add_group(m, params)
|
46
|
+
begin
|
47
|
+
raise 'Invalid group name: none' if params[:group] == 'none'
|
48
|
+
Models::Group.find_or_create(:name => params[:group])
|
49
|
+
information m.replyto, "New group \2#{params[:group]}\2 is now available"
|
50
|
+
rescue Object => boom
|
51
|
+
error m.replyto, "Unknown error when adding new group: #{params[:group]}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def invalid(m, params)
|
56
|
+
Models::Signature.dataset.update(:enabled => false)
|
57
|
+
information m.replyto, 'ok'
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -3,16 +3,11 @@ class PluginLoader < ModSpox::Plugin
|
|
3
3
|
def initialize(pipeline)
|
4
4
|
super(pipeline)
|
5
5
|
admin = Models::Group.filter(:name => 'admin').first
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
:group_id => admin.pk, :description => 'Load the given plugin').params = [:plugin]
|
12
|
-
Models::Signature.find_or_create(:signature => 'plugins unload (\S+)', :plugin => name, :method => 'unload_plugin',
|
13
|
-
:group_id => admin.pk, :description => 'Unload given plugin').params = [:plugin]
|
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]
|
6
|
+
add_sig(:sig => 'plugins available', :method => :available_plugins, :group => admin, :desc => 'List all available plugins')
|
7
|
+
add_sig(:sig => 'plugins loaded', :method => :loaded_plugins, :group => admin, :desc => 'List all plugins currently loaded')
|
8
|
+
add_sig(:sig => 'plugins load (\S+)', :method => :load_plugin, :group => admin, :desc => 'Load the given plugin', :params => [:plugin])
|
9
|
+
add_sig(:sig => 'plugins unload (\S+)', :method => :unload_plugin, :group => admin, :desc => 'Unload given plugin', :params => [:plugin])
|
10
|
+
add_sig(:sig => 'plugins reload ?(\S+)?', :method => :reload_plugin, :group => admin, :desc => 'Reload single plugin or all plugins if names not provided', :params => [:plugin])
|
16
11
|
@pipeline.hook(self, :get_module, :Internal_PluginModuleResponse)
|
17
12
|
@plugins_mod = nil
|
18
13
|
end
|
@@ -93,7 +88,7 @@ class PluginLoader < ModSpox::Plugin
|
|
93
88
|
|
94
89
|
# Upgrades extra plugins to latest version
|
95
90
|
def extras_upgrade
|
96
|
-
Logger.info("Starting plugin upgrade to current version: #{
|
91
|
+
Logger.info("Starting plugin upgrade to current version: #{ModSpox.botversion}")
|
97
92
|
extras = plugin_discovery(BotConfig[:pluginextraspath])
|
98
93
|
pl = plugin_list
|
99
94
|
extras.keys.each{|d| extras.delete(d) unless pl.include?(d)}
|
@@ -107,7 +102,7 @@ class PluginLoader < ModSpox::Plugin
|
|
107
102
|
extras.each do |name, path|
|
108
103
|
@pipeline << Messages::Internal::PluginLoadRequest.new(self, path)
|
109
104
|
end
|
110
|
-
Logger.info("Plugin upgrade is now complete. Upgraded to version: #{
|
105
|
+
Logger.info("Plugin upgrade is now complete. Upgraded to version: #{ModSpox.botversion}")
|
111
106
|
end
|
112
107
|
|
113
108
|
private
|
@@ -2,7 +2,16 @@ class Ponger < ModSpox::Plugin
|
|
2
2
|
|
3
3
|
def initialize(pipeline)
|
4
4
|
super(pipeline)
|
5
|
+
@lag = nil
|
6
|
+
@last = nil
|
7
|
+
@attempts = 0
|
8
|
+
add_sig(:sig => 'lag', :method => :print_lag, :desc => 'Shows bot\'s current lag to server')
|
5
9
|
@pipeline.hook(self, :ping, :Incoming_Ping)
|
10
|
+
@pipeline.hook(self, :get_lag_pong, :Incoming_Pong)
|
11
|
+
@lock = Mutex.new
|
12
|
+
@pipeline.hook(self, :check_start_ponger, :Internal_PluginsReady)
|
13
|
+
@running = false
|
14
|
+
send_lag_ping
|
6
15
|
end
|
7
16
|
|
8
17
|
# message:: ModSpox::Messages::Incoming::Ping
|
@@ -10,5 +19,47 @@ class Ponger < ModSpox::Plugin
|
|
10
19
|
def ping(message)
|
11
20
|
@pipeline << Messages::Outgoing::Pong.new(message.server, message.string)
|
12
21
|
end
|
22
|
+
|
23
|
+
def send_lag_ping
|
24
|
+
if(@attempts > 5)
|
25
|
+
@pipeline << Messages::Internal::Reconnect.new
|
26
|
+
@lag = nil
|
27
|
+
@last = nil
|
28
|
+
@attempts = 0
|
29
|
+
else
|
30
|
+
t = Time.now
|
31
|
+
@last = t.to_f.to_s
|
32
|
+
@pipeline << Messages::Outgoing::Ping.new("#{@last}")
|
33
|
+
@attempts += 1
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def get_lag_pong(m)
|
38
|
+
@lock.synchronize do
|
39
|
+
t = m.string.to_f
|
40
|
+
return unless m.string == @last
|
41
|
+
@lag = Time.now.to_f - t
|
42
|
+
@last = nil
|
43
|
+
@attempts = 0
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def print_lag(m, params)
|
48
|
+
if(@lag.nil?)
|
49
|
+
warning m.replyto, 'Lag time currently unavailable'
|
50
|
+
else
|
51
|
+
information m.replyto, "Current lag time: #{sprintf('%0.4f', @lag)} seconds"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def start_ponger(m)
|
56
|
+
@running = true
|
57
|
+
send_lag_ping
|
58
|
+
@pipeline << Messages::Internal::TimerAdd.new(self, 60){ send_lag_ping }
|
59
|
+
end
|
60
|
+
|
61
|
+
def check_start_ponger(m)
|
62
|
+
@pipeline << Messages::Internal::TimerAdd.new(self, 30, nil, true){ @lock.synchronize{start_ponger(nil) unless @running} }
|
63
|
+
end
|
13
64
|
|
14
65
|
end
|
@@ -2,8 +2,7 @@ class Quitter < ModSpox::Plugin
|
|
2
2
|
|
3
3
|
def initialize(pipeline)
|
4
4
|
super(pipeline)
|
5
|
-
|
6
|
-
:group_id => Models::Group.filter(:name => 'admin').first.pk).params = [:channel, :message]
|
5
|
+
add_sig(:sig => 'quit(\s.+)?', :method => :quit, :group => Models::Group.filter(:name => 'admin').first, :params => [:channel, :message])
|
7
6
|
end
|
8
7
|
|
9
8
|
# message:: ModSpox::Messages::Incoming::Privmsg
|
@@ -0,0 +1,57 @@
|
|
1
|
+
class Servers < ModSpox::Plugin
|
2
|
+
def initialize(pipeline)
|
3
|
+
super
|
4
|
+
admin = Models::Group.find_or_create(:name => 'admin')
|
5
|
+
add_sig(:sig => 'servers list', :method => :list, :group => admin, :desc => 'Show server list')
|
6
|
+
add_sig(:sig => 'servers add (\S+) (\d+)( \d+)?', :method => :add, :group => admin, :desc => 'Add server to list', :params => [:server, :port, :prio])
|
7
|
+
add_sig(:sig => 'servers del (\d+)', :method => :remove, :group => admin, :desc => 'Remove server from list', :params => [:id])
|
8
|
+
add_sig(:sig => 'servers prio (\d+) (\+|\-|\d+)', :method => :prio, :group => admin, :desc => 'Prioritize server', :params => [:id, :move])
|
9
|
+
end
|
10
|
+
|
11
|
+
def list(m, params)
|
12
|
+
output = ["\2Server list:\2"]
|
13
|
+
Models::Server.reverse_order(:priority).each do |s|
|
14
|
+
output << "\2[#{s.id}]\2 #{s.host}:#{s.port} \2Priority:\2 #{s.priority}"
|
15
|
+
end
|
16
|
+
reply m.replyto, output
|
17
|
+
end
|
18
|
+
|
19
|
+
def add(m, params)
|
20
|
+
begin
|
21
|
+
s = Models::Server.new(:host => params[:server], :port => params[:port].to_i)
|
22
|
+
s.priority = params[:prio].to_i if params[:prio]
|
23
|
+
s.save
|
24
|
+
information m.replyto, "New server has been added: #{params[:server]}:#{params[:port]}"
|
25
|
+
rescue Object => boom
|
26
|
+
error m.replyto, "Failed to add new server. Reason: #{boom}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def remove(m, params)
|
31
|
+
begin
|
32
|
+
raise "List must contain one server" unless Models::Server.count > 1
|
33
|
+
Models::Server[params[:id].to_i].destroy
|
34
|
+
information m.replyto, 'Server has been removed'
|
35
|
+
rescue Object => boom
|
36
|
+
error m.replyto, "Failed to remove server. Reason: #{boom}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def prio(m, params)
|
41
|
+
begin
|
42
|
+
s = Models::Server[params[:id].to_i]
|
43
|
+
if(params[:move] == '+')
|
44
|
+
s.priority += 1
|
45
|
+
elsif(params[:move] == '-')
|
46
|
+
s.priority -= 1 if s.priority > 0
|
47
|
+
else
|
48
|
+
s.priority = params[:move].to_i
|
49
|
+
end
|
50
|
+
s.save_changes
|
51
|
+
information m.replyto, 'Server priority has been updated.'
|
52
|
+
rescue Object => boom
|
53
|
+
error m.replyto, "Failed to update priority. Reason: #{boom}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -4,6 +4,7 @@ class Status < ModSpox::Plugin
|
|
4
4
|
super
|
5
5
|
add_sig(:sig => 'status', :method => :status, :desc => 'Show current status')
|
6
6
|
add_sig(:sig => 'version', :method => :version, :desc => 'Show version information')
|
7
|
+
add_sig(:sig => 'VERSION', :method => :version, :desc => 'Show version information')
|
7
8
|
@pipeline.hook(self, :get_status, :Internal_StatusResponse)
|
8
9
|
@resp = []
|
9
10
|
end
|
@@ -14,13 +15,13 @@ class Status < ModSpox::Plugin
|
|
14
15
|
end
|
15
16
|
|
16
17
|
def version(message, params)
|
17
|
-
reply message.replyto, "mod_spox IRC bot - Version: \2#{
|
18
|
+
reply message.replyto, "mod_spox IRC bot - Version: \2#{ModSpox.botversion}\2 (#{ModSpox.botcodename}) [http://modspox.rubyforge.org]"
|
18
19
|
end
|
19
20
|
|
20
21
|
def get_status(m)
|
21
22
|
@resp.uniq!
|
22
23
|
@resp.each do |c|
|
23
|
-
reply c, "\2Status:\2 \2Uptime:\2 #{m.status[:uptime]} \2Plugins:\2 #{m.status[:plugins]} loaded \2Lines sent:\2 #{m.status[:sent]} \2Lines Received:\2 #{m.status[:received]}"
|
24
|
+
reply c, "\2Status:\2 \2Uptime:\2 #{m.status[:uptime]} \2Plugins:\2 #{m.status[:plugins]} loaded \2Socket Connected:\2 #{m.status[:socket_connect].strftime("%Y/%m/%d-%H:%M:%S")} \2Lines sent:\2 #{m.status[:sent]} \2Lines Received:\2 #{m.status[:received]}"
|
24
25
|
@resp.delete(c)
|
25
26
|
end
|
26
27
|
end
|
@@ -5,12 +5,12 @@ include Messages::Outgoing
|
|
5
5
|
def initialize(pipeline)
|
6
6
|
super(pipeline)
|
7
7
|
admin = Models::Group.filter(:name => 'admin').first
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
add_sig(:sig => 'triggers active', :method => :active, :group => admin, :desc => 'List all currently active triggers')
|
9
|
+
add_sig(:sig => 'triggers list', :method => :list, :group => admin, :desc => 'List all triggers and their current status')
|
10
|
+
add_sig(:sig => 'triggers add (\S+)', :method => :add, :group => admin, :desc => 'Add a new trigger and activate it', :params => [:trigger])
|
11
|
+
add_sig(:sig => 'triggers remove (\d+)', :method => :remove, :group => admin, :desc => 'Remove trigger', :params => [:id])
|
12
|
+
add_sig(:sig => 'triggers activate (\d+)', :method => :activate, :group => admin, :desc => 'Activate the trigger', :params => [:id])
|
13
|
+
add_sig(:sig => 'triggers deactivate (\d+)', :method => :deactivate, :group => admin, :desc => 'Deactivate the trigger', :params => [:id])
|
14
14
|
end
|
15
15
|
|
16
16
|
def active(message, params)
|
@@ -40,7 +40,7 @@ include Messages::Outgoing
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def add(message, params)
|
43
|
-
Models::Trigger.find_or_create(:trigger => params[:trigger]).
|
43
|
+
Models::Trigger.find_or_create(:trigger => params[:trigger]).update(:active => true)
|
44
44
|
@pipeline << Privmsg.new(message.replyto, "Trigger #{params[:trigger]} is now active")
|
45
45
|
@pipeline << Messages::Internal::TriggersUpdate.new
|
46
46
|
end
|
@@ -60,7 +60,7 @@ include Messages::Outgoing
|
|
60
60
|
def activate(message, params)
|
61
61
|
trigger = Models::Trigger[params[:id]]
|
62
62
|
if(trigger)
|
63
|
-
trigger.
|
63
|
+
trigger.update(:active => true)
|
64
64
|
@pipeline << Privmsg.new(message.replyto, "Trigger #{trigger.trigger} has been activated")
|
65
65
|
@pipeline << Messages::Internal::TriggersUpdate.new
|
66
66
|
else
|
@@ -71,7 +71,7 @@ include Messages::Outgoing
|
|
71
71
|
def deactivate(message, params)
|
72
72
|
trigger = Models::Trigger[params[:id]]
|
73
73
|
if(trigger)
|
74
|
-
trigger.
|
74
|
+
trigger.update(:active => false)
|
75
75
|
@pipeline << Privmsg.new(message.replyto, "Trigger #{trigger.trigger} has been deactivated")
|
76
76
|
@pipeline << Messages::Internal::TriggersUpdate.new
|
77
77
|
else
|
data/lib/mod_spox/Bot.rb
CHANGED
@@ -4,17 +4,22 @@
|
|
4
4
|
'mod_spox/PluginManager',
|
5
5
|
'mod_spox/MessageFactory',
|
6
6
|
'mod_spox/BaseConfig',
|
7
|
-
'mod_spox/Timer',
|
8
7
|
'mod_spox/messages/Messages',
|
9
8
|
'mod_spox/models/Models',
|
10
9
|
'mod_spox/Helpers',
|
11
|
-
'mod_spox/
|
10
|
+
'mod_spox/Timer'].each{|f|require f}
|
11
|
+
require 'actionpool'
|
12
|
+
require 'actiontimer'
|
13
|
+
|
12
14
|
module ModSpox
|
13
15
|
|
14
16
|
class Bot
|
15
17
|
|
16
18
|
# bot timer
|
17
19
|
attr_reader :timer
|
20
|
+
|
21
|
+
# thread pool
|
22
|
+
attr_reader :pool
|
18
23
|
|
19
24
|
# message pipeline
|
20
25
|
attr_reader :pipeline
|
@@ -30,15 +35,19 @@ module ModSpox
|
|
30
35
|
|
31
36
|
# Create a Bot
|
32
37
|
def initialize
|
33
|
-
|
34
|
-
|
38
|
+
unless(ModSpox.logto.nil?)
|
39
|
+
logger = ::Logger.new(ModSpox.logto, 'daily')
|
40
|
+
Logger.initialize(logger, ModSpox.loglevel)
|
41
|
+
end
|
35
42
|
clean_models
|
43
|
+
@servers = Array.new
|
44
|
+
@channels = Array.new
|
36
45
|
@start_time = Time.now
|
37
|
-
@
|
38
|
-
@
|
39
|
-
@timer.
|
46
|
+
@pool = ActionPool::Pool.new(10, 100, 60, nil, logger)
|
47
|
+
@pipeline = Pipeline.new(@pool)
|
48
|
+
@timer = Timer.new(ActionTimer::Timer.new(@pool, logger), @pipeline)
|
40
49
|
@config = BaseConfig.new(BotConfig[:userconfigpath])
|
41
|
-
@factory = MessageFactory.new(@pipeline)
|
50
|
+
@factory = MessageFactory.new(@pipeline, @pool)
|
42
51
|
@socket = nil
|
43
52
|
@plugin_manager = PluginManager.new(@pipeline)
|
44
53
|
if(@config[:plugin_upgrade] == 'yes')
|
@@ -60,10 +69,10 @@ module ModSpox
|
|
60
69
|
|
61
70
|
# Run the bot
|
62
71
|
def run
|
63
|
-
trap('SIGTERM'){ Logger.warn("Caught SIGTERM");
|
64
|
-
trap('SIGKILL'){ Logger.warn("Caught SIGKILL");
|
65
|
-
trap('SIGINT'){ Logger.warn("Caught SIGINT");
|
66
|
-
trap('SIGQUIT'){ Logger.warn("Caught SIGQUIT");
|
72
|
+
trap('SIGTERM'){ Logger.warn("Caught SIGTERM"); halt }
|
73
|
+
trap('SIGKILL'){ Logger.warn("Caught SIGKILL"); halt }
|
74
|
+
trap('SIGINT'){ Logger.warn("Caught SIGINT"); halt }
|
75
|
+
trap('SIGQUIT'){ Logger.warn("Caught SIGQUIT"); halt }
|
67
76
|
until @shutdown do
|
68
77
|
@pipeline << Messages::Internal::BotInitialized.new
|
69
78
|
begin
|
@@ -106,10 +115,28 @@ module ModSpox
|
|
106
115
|
begin
|
107
116
|
@socket = Sockets.new(self) if @socket.nil?
|
108
117
|
@socket.irc_connect(message.server, message.port)
|
109
|
-
@pipeline << Messages::Internal::Connected.new(message.server, message.port)
|
110
118
|
rescue Object => boom
|
111
119
|
Logger.warn("Failed connection to server: #{boom}")
|
112
|
-
@pipeline << Messages::Internal::ConnectionFailed.new(
|
120
|
+
@pipeline << Messages::Internal::ConnectionFailed.new(@socket.irc_socket.server, @socket.irc_socket.port)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# message:: Messages::Internal::Reconnect
|
125
|
+
# instructs bot to reconnect to IRC server
|
126
|
+
def reconnect(message=nil)
|
127
|
+
begin
|
128
|
+
@plugin_manager.reload_plugins
|
129
|
+
@socket.irc_reconnect
|
130
|
+
rescue Object => boom
|
131
|
+
Logger.warn("Initial reconnect failed. (#{boom}) Starting timed reconnect process.")
|
132
|
+
begin
|
133
|
+
@socket.irc_reconnect
|
134
|
+
rescue Object => boom
|
135
|
+
Logger.warn("Failed to connect to server. Reason: #{boom}")
|
136
|
+
Logger.warn("Will retry in 20 seconds")
|
137
|
+
sleep(20)
|
138
|
+
retry
|
139
|
+
end
|
113
140
|
end
|
114
141
|
end
|
115
142
|
|
@@ -123,6 +150,7 @@ module ModSpox
|
|
123
150
|
def bot_stats
|
124
151
|
return {:uptime => Helpers::format_seconds(Time.now - @start_time),
|
125
152
|
:plugins => @plugin_manager.plugins.size,
|
153
|
+
:socket_connect => @socket.irc_socket.connected_at,
|
126
154
|
:sent => @socket.irc_socket.sent,
|
127
155
|
:received => @socket.irc_socket.received}
|
128
156
|
end
|
@@ -154,7 +182,8 @@ module ModSpox
|
|
154
182
|
:Internal_StatusRequest => :status, :Internal_ChangeNick => :set_nick,
|
155
183
|
:Internal_NickRequest => :get_nick, :Internal_HaltBot => :halt,
|
156
184
|
:Internal_Disconnected => :disconnected, :Internal_TimerClear => :clear_timer,
|
157
|
-
:Outgoing_Raw => :raw
|
185
|
+
:Outgoing_Raw => :raw, :Internal_Reconnect => :reconnect,
|
186
|
+
:Incoming_Join => :check_join, :Incoming_Part => :check_part
|
158
187
|
}.each_pair{ |type,method| @pipeline.hook(self, method, type) }
|
159
188
|
end
|
160
189
|
|
@@ -167,12 +196,11 @@ module ModSpox
|
|
167
196
|
# message:: Messages::Internal::Disconnected
|
168
197
|
# Disconnect the bot from the IRC server
|
169
198
|
def disconnected(message)
|
170
|
-
|
171
|
-
@socket = nil
|
199
|
+
reload
|
172
200
|
end
|
173
201
|
|
174
202
|
# Stop the bot
|
175
|
-
def halt(message)
|
203
|
+
def halt(message=nil)
|
176
204
|
@shutdown = true
|
177
205
|
reload
|
178
206
|
end
|
@@ -282,6 +310,7 @@ module ModSpox
|
|
282
310
|
# message:: Messages::Outgoing::Invite message
|
283
311
|
# Sends INVITE message to server
|
284
312
|
def invite(message)
|
313
|
+
okay_to_send(message.channel)
|
285
314
|
nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
|
286
315
|
channel = message.channel.is_a?(Models::Channel) ? message.channel.name : message.channel
|
287
316
|
@socket << "INVITE #{nick} #{channel}"
|
@@ -290,6 +319,7 @@ module ModSpox
|
|
290
319
|
# message:: Messages::Outgoing::Kick message
|
291
320
|
# Sends KICK message to server
|
292
321
|
def kick(message)
|
322
|
+
okay_to_send(message.channel)
|
293
323
|
nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
|
294
324
|
channel = message.channel.is_a?(Models::Channel) ? message.channel.name : message.channel
|
295
325
|
@socket << "KICK #{channel} #{nick} :#{message.reason}"
|
@@ -298,18 +328,19 @@ module ModSpox
|
|
298
328
|
# message:: Messages::Outgoing::Privmsg message
|
299
329
|
# Sends PRIVMSG message to server
|
300
330
|
def privmsg(message)
|
331
|
+
okay_to_send(message.target)
|
301
332
|
target = message.target.name if message.target.is_a?(Models::Channel)
|
302
333
|
target = message.target.nick if message.target.is_a?(Models::Nick)
|
303
334
|
target = message.target unless target
|
304
335
|
messages = message.message.is_a?(Array) ? message.message : [message.message]
|
305
336
|
messages.each do |part|
|
306
337
|
part.split("\n").each do |content|
|
307
|
-
while(content.size >
|
308
|
-
output = content[0..
|
309
|
-
content.slice!(0,
|
310
|
-
@socket
|
338
|
+
while(content.size > 400)
|
339
|
+
output = content[0..400]
|
340
|
+
content.slice!(0, 401) #(450, content.size)
|
341
|
+
@socket.prioritize_message(target, "PRIVMSG #{target} :#{message.is_ctcp? ? "\cA#{message.ctcp_type} #{output}\cA" : output}")
|
311
342
|
end
|
312
|
-
@socket
|
343
|
+
@socket.prioritize_message(target, "PRIVMSG #{target} :#{message.is_ctcp? ? "\cA#{message.ctcp_type} #{content}\cA" : content}")
|
313
344
|
end
|
314
345
|
end
|
315
346
|
end
|
@@ -317,6 +348,7 @@ module ModSpox
|
|
317
348
|
# message:: Messages::Outgoing::Notice message
|
318
349
|
# Sends NOTICE message to server
|
319
350
|
def notice(message)
|
351
|
+
okay_to_send(message.target)
|
320
352
|
target = message.target.name if message.target.is_a?(Models::Channel)
|
321
353
|
target = message.target.nick if message.target.is_a?(Models::Nick)
|
322
354
|
@socket << "NOTICE #{target} :#{message}"
|
@@ -399,14 +431,14 @@ module ModSpox
|
|
399
431
|
# Sends WHO message to server
|
400
432
|
def who(message)
|
401
433
|
o = message.only_ops? ? 'o' : ''
|
402
|
-
@socket
|
434
|
+
@socket.prioritize_message('*who', "WHO #{message.mask} #{o}")
|
403
435
|
end
|
404
436
|
|
405
437
|
# message:: Messages::Outgoing::Whois message
|
406
438
|
# Sends WHOIS message to server
|
407
439
|
def whois(message)
|
408
440
|
nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
|
409
|
-
@socket
|
441
|
+
@socket.prioritize_message('*whois', "WHOIS #{message.target_server} #{nick}")
|
410
442
|
end
|
411
443
|
|
412
444
|
# message:: Messages::Outgoing::WhoWas message
|
@@ -502,22 +534,66 @@ module ModSpox
|
|
502
534
|
@socket << message.message
|
503
535
|
end
|
504
536
|
|
537
|
+
def check_join(m)
|
538
|
+
if(m.nick.botnick)
|
539
|
+
@channels << m.channel.name.downcase
|
540
|
+
end
|
541
|
+
end
|
542
|
+
|
543
|
+
def check_part(m)
|
544
|
+
if(m.nick.botnick)
|
545
|
+
@channels.delete(m.channel.name.downcase)
|
546
|
+
end
|
547
|
+
end
|
548
|
+
|
505
549
|
private
|
506
550
|
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
551
|
+
# channel:: channel to check
|
552
|
+
# checks if the bot is parked in the given channel
|
553
|
+
# and raises an exception (and logs) if the bot
|
554
|
+
# is not in the given channel
|
555
|
+
def okay_to_send(channel)
|
556
|
+
if(channel.is_a?(String) && ['&', '#', '+', '!'].include?(channel[0]))
|
557
|
+
channel = Helpers.find_model(channel)
|
511
558
|
end
|
559
|
+
return unless channel.is_a?(Models::Channel)
|
560
|
+
if(channel.quiet)
|
561
|
+
Logger.error("Attempted to send to channel where bot is not allowed to speak: #{channel.name}")
|
562
|
+
raise Exceptions::QuietChannel.new(channel)
|
563
|
+
end
|
564
|
+
unless(in_channel?(channel))
|
565
|
+
Logger.error("Attempted to send to channel where bot is not parked: #{channel.name}.")
|
566
|
+
raise Exceptions::NotInChannel.new(channel)
|
567
|
+
end
|
568
|
+
end
|
569
|
+
|
570
|
+
def in_channel?(channel)
|
571
|
+
unless(@channels.include?(channel.name.downcase))
|
572
|
+
repopulate_channels
|
573
|
+
return @channels.include?(channel.name.downcase)
|
574
|
+
else
|
575
|
+
return true
|
576
|
+
end
|
577
|
+
end
|
578
|
+
|
579
|
+
def repopulate_channels
|
580
|
+
bot = Models::Nick.filter(:botnick => true).first
|
581
|
+
raise Exceptions::BotException.new("I DON'T KNOW WHO I AM") unless bot
|
582
|
+
@channels.clear
|
583
|
+
bot.channels.each{|c| @channels << c.name.downcase}
|
512
584
|
end
|
513
585
|
|
514
586
|
# Cleans information from models to avoid
|
515
587
|
# stale values
|
516
588
|
def clean_models
|
517
|
-
Models::
|
518
|
-
Models::Channel.
|
519
|
-
Models::
|
520
|
-
|
589
|
+
Models::NickMode.destroy
|
590
|
+
Models::Channel.update(:topic => nil)
|
591
|
+
Models::Nick.update(:username => nil, :real_name => nil, :address => nil,
|
592
|
+
:source => nil, :connected_at => nil, :connected_to => nil,
|
593
|
+
:seconds_idle => nil, :away => false, :visible => false, :botnick => false)
|
594
|
+
Models::Auth.update(:authed => false)
|
595
|
+
Database.db[:auth_masks_nicks].delete
|
596
|
+
Database.db[:nick_channels].delete
|
521
597
|
end
|
522
598
|
end
|
523
599
|
|