mod_spox 0.0.1
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 +2 -0
- data/INSTALL +9 -0
- data/README +33 -0
- data/bin/mod_spox +60 -0
- data/data/mod_spox/extras/Tester.rb +14 -0
- data/data/mod_spox/plugins/Authenticator.rb +245 -0
- data/data/mod_spox/plugins/BotNick.rb +18 -0
- data/data/mod_spox/plugins/Initializer.rb +41 -0
- data/data/mod_spox/plugins/Joiner.rb +13 -0
- data/data/mod_spox/plugins/Parter.rb +22 -0
- data/data/mod_spox/plugins/PluginLoader.rb +136 -0
- data/data/mod_spox/plugins/Ponger.rb +14 -0
- data/data/mod_spox/plugins/Quitter.rb +14 -0
- data/lib/mod_spox/Action.rb +73 -0
- data/lib/mod_spox/BaseConfig.rb +48 -0
- data/lib/mod_spox/Bot.rb +472 -0
- data/lib/mod_spox/BotConfig.rb +54 -0
- data/lib/mod_spox/ConfigurationWizard.rb +178 -0
- data/lib/mod_spox/Database.rb +25 -0
- data/lib/mod_spox/Exceptions.rb +35 -0
- data/lib/mod_spox/Helpers.rb +35 -0
- data/lib/mod_spox/Loader.rb +79 -0
- data/lib/mod_spox/Logger.rb +31 -0
- data/lib/mod_spox/MessageFactory.rb +73 -0
- data/lib/mod_spox/Monitors.rb +59 -0
- data/lib/mod_spox/Pipeline.rb +148 -0
- data/lib/mod_spox/Plugin.rb +18 -0
- data/lib/mod_spox/PluginManager.rb +105 -0
- data/lib/mod_spox/Pool.rb +50 -0
- data/lib/mod_spox/Socket.rb +171 -0
- data/lib/mod_spox/Timer.rb +138 -0
- data/lib/mod_spox/handlers/BadNick.rb +16 -0
- data/lib/mod_spox/handlers/Bounce.rb +15 -0
- data/lib/mod_spox/handlers/Created.rb +16 -0
- data/lib/mod_spox/handlers/Handler.rb +31 -0
- data/lib/mod_spox/handlers/Invite.rb +19 -0
- data/lib/mod_spox/handlers/Join.rb +30 -0
- data/lib/mod_spox/handlers/Kick.rb +24 -0
- data/lib/mod_spox/handlers/LuserChannels.rb +16 -0
- data/lib/mod_spox/handlers/LuserClient.rb +16 -0
- data/lib/mod_spox/handlers/LuserMe.rb +14 -0
- data/lib/mod_spox/handlers/LuserOp.rb +16 -0
- data/lib/mod_spox/handlers/LuserUnknown.rb +16 -0
- data/lib/mod_spox/handlers/Mode.rb +47 -0
- data/lib/mod_spox/handlers/Motd.rb +30 -0
- data/lib/mod_spox/handlers/MyInfo.rb +21 -0
- data/lib/mod_spox/handlers/Names.rb +54 -0
- data/lib/mod_spox/handlers/Nick.rb +24 -0
- data/lib/mod_spox/handlers/NickInUse.rb +16 -0
- data/lib/mod_spox/handlers/Notice.rb +32 -0
- data/lib/mod_spox/handlers/Part.rb +19 -0
- data/lib/mod_spox/handlers/Ping.rb +16 -0
- data/lib/mod_spox/handlers/Pong.rb +16 -0
- data/lib/mod_spox/handlers/Privmsg.rb +27 -0
- data/lib/mod_spox/handlers/Quit.rb +21 -0
- data/lib/mod_spox/handlers/Topic.rb +29 -0
- data/lib/mod_spox/handlers/Welcome.rb +34 -0
- data/lib/mod_spox/handlers/Who.rb +60 -0
- data/lib/mod_spox/handlers/Whois.rb +63 -0
- data/lib/mod_spox/handlers/YourHost.rb +17 -0
- data/lib/mod_spox/messages/incoming/BadNick.rb +15 -0
- data/lib/mod_spox/messages/incoming/Bounce.rb +17 -0
- data/lib/mod_spox/messages/incoming/Created.rb +14 -0
- data/lib/mod_spox/messages/incoming/Invite.rb +20 -0
- data/lib/mod_spox/messages/incoming/Join.rb +18 -0
- data/lib/mod_spox/messages/incoming/Kick.rb +25 -0
- data/lib/mod_spox/messages/incoming/LuserChannels.rb +14 -0
- data/lib/mod_spox/messages/incoming/LuserClient.rb +23 -0
- data/lib/mod_spox/messages/incoming/LuserMe.rb +17 -0
- data/lib/mod_spox/messages/incoming/LuserOp.rb +14 -0
- data/lib/mod_spox/messages/incoming/LuserUnknown.rb +14 -0
- data/lib/mod_spox/messages/incoming/Message.rb +22 -0
- data/lib/mod_spox/messages/incoming/Mode.rb +41 -0
- data/lib/mod_spox/messages/incoming/Motd.rb +17 -0
- data/lib/mod_spox/messages/incoming/MyInfo.rb +23 -0
- data/lib/mod_spox/messages/incoming/Names.rb +23 -0
- data/lib/mod_spox/messages/incoming/Nick.rb +25 -0
- data/lib/mod_spox/messages/incoming/NickInUse.rb +14 -0
- data/lib/mod_spox/messages/incoming/Notice.rb +8 -0
- data/lib/mod_spox/messages/incoming/Part.rb +20 -0
- data/lib/mod_spox/messages/incoming/Ping.rb +17 -0
- data/lib/mod_spox/messages/incoming/Pong.rb +8 -0
- data/lib/mod_spox/messages/incoming/Privmsg.rb +64 -0
- data/lib/mod_spox/messages/incoming/Quit.rb +17 -0
- data/lib/mod_spox/messages/incoming/Topic.rb +20 -0
- data/lib/mod_spox/messages/incoming/TopicInfo.rb +20 -0
- data/lib/mod_spox/messages/incoming/Welcome.rb +26 -0
- data/lib/mod_spox/messages/incoming/Who.rb +17 -0
- data/lib/mod_spox/messages/incoming/Whois.rb +47 -0
- data/lib/mod_spox/messages/incoming/YourHost.rb +17 -0
- data/lib/mod_spox/messages/internal/BotInitialized.rb +11 -0
- data/lib/mod_spox/messages/internal/ChangeNick.rb +15 -0
- data/lib/mod_spox/messages/internal/Connected.rb +20 -0
- data/lib/mod_spox/messages/internal/ConnectionFailed.rb +23 -0
- data/lib/mod_spox/messages/internal/Disconnected.rb +8 -0
- data/lib/mod_spox/messages/internal/Disconnecting.rb +8 -0
- data/lib/mod_spox/messages/internal/EstablishConnection.rb +22 -0
- data/lib/mod_spox/messages/internal/HaltBot.rb +8 -0
- data/lib/mod_spox/messages/internal/NickRequest.rb +8 -0
- data/lib/mod_spox/messages/internal/NickResponse.rb +14 -0
- data/lib/mod_spox/messages/internal/PluginLoadRequest.rb +20 -0
- data/lib/mod_spox/messages/internal/PluginLoadResponse.rb +16 -0
- data/lib/mod_spox/messages/internal/PluginModuleRequest.rb +13 -0
- data/lib/mod_spox/messages/internal/PluginModuleResponse.rb +17 -0
- data/lib/mod_spox/messages/internal/PluginReload.rb +8 -0
- data/lib/mod_spox/messages/internal/PluginRequest.rb +17 -0
- data/lib/mod_spox/messages/internal/PluginResponse.rb +20 -0
- data/lib/mod_spox/messages/internal/PluginUnloadRequest.rb +8 -0
- data/lib/mod_spox/messages/internal/PluginUnloadResponse.rb +8 -0
- data/lib/mod_spox/messages/internal/Request.rb +15 -0
- data/lib/mod_spox/messages/internal/Response.rb +15 -0
- data/lib/mod_spox/messages/internal/Shutdown.rb +8 -0
- data/lib/mod_spox/messages/internal/SignaturesUpdate.rb +8 -0
- data/lib/mod_spox/messages/internal/StatusRequest.rb +9 -0
- data/lib/mod_spox/messages/internal/StatusResponse.rb +17 -0
- data/lib/mod_spox/messages/internal/TimerAdd.rb +27 -0
- data/lib/mod_spox/messages/internal/TimerClear.rb +8 -0
- data/lib/mod_spox/messages/internal/TimerRemove.rb +15 -0
- data/lib/mod_spox/messages/internal/TimerResponse.rb +26 -0
- data/lib/mod_spox/messages/internal/TriggersUpdate.rb +8 -0
- data/lib/mod_spox/messages/outgoing/Admin.rb +15 -0
- data/lib/mod_spox/messages/outgoing/Away.rb +10 -0
- data/lib/mod_spox/messages/outgoing/ChannelMode.rb +25 -0
- data/lib/mod_spox/messages/outgoing/Connect.rb +24 -0
- data/lib/mod_spox/messages/outgoing/Die.rb +9 -0
- data/lib/mod_spox/messages/outgoing/Info.rb +15 -0
- data/lib/mod_spox/messages/outgoing/Invite.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Ison.rb +15 -0
- data/lib/mod_spox/messages/outgoing/Join.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Kick.rb +23 -0
- data/lib/mod_spox/messages/outgoing/Kill.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Links.rb +19 -0
- data/lib/mod_spox/messages/outgoing/List.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Lusers.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Motd.rb +16 -0
- data/lib/mod_spox/messages/outgoing/Names.rb +20 -0
- data/lib/mod_spox/messages/outgoing/Nick.rb +16 -0
- data/lib/mod_spox/messages/outgoing/Notice.rb +11 -0
- data/lib/mod_spox/messages/outgoing/Oper.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Part.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Pass.rb +16 -0
- data/lib/mod_spox/messages/outgoing/Ping.rb +10 -0
- data/lib/mod_spox/messages/outgoing/Pong.rb +17 -0
- data/lib/mod_spox/messages/outgoing/Privmsg.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Quit.rb +10 -0
- data/lib/mod_spox/messages/outgoing/Rehash.rb +9 -0
- data/lib/mod_spox/messages/outgoing/Restart.rb +9 -0
- data/lib/mod_spox/messages/outgoing/ServList.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Simple.rb +12 -0
- data/lib/mod_spox/messages/outgoing/Squery.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Squit.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Stats.rb +18 -0
- data/lib/mod_spox/messages/outgoing/Summon.rb +23 -0
- data/lib/mod_spox/messages/outgoing/Time.rb +15 -0
- data/lib/mod_spox/messages/outgoing/Topic.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Trace.rb +15 -0
- data/lib/mod_spox/messages/outgoing/Unaway.rb +9 -0
- data/lib/mod_spox/messages/outgoing/User.rb +23 -0
- data/lib/mod_spox/messages/outgoing/UserHost.rb +15 -0
- data/lib/mod_spox/messages/outgoing/UserMode.rb +19 -0
- data/lib/mod_spox/messages/outgoing/Users.rb +15 -0
- data/lib/mod_spox/messages/outgoing/Version.rb +16 -0
- data/lib/mod_spox/messages/outgoing/Who.rb +19 -0
- data/lib/mod_spox/messages/outgoing/WhoWas.rb +23 -0
- data/lib/mod_spox/messages/outgoing/Whois.rb +19 -0
- data/lib/mod_spox/migration/001_create_auths.rb +13 -0
- data/lib/mod_spox/migration/001_create_channel.rb +13 -0
- data/lib/mod_spox/migration/001_create_channel_modes.rb +13 -0
- data/lib/mod_spox/migration/001_create_config.rb +13 -0
- data/lib/mod_spox/migration/001_create_nick_channels.rb +13 -0
- data/lib/mod_spox/migration/001_create_nick_modes.rb +13 -0
- data/lib/mod_spox/migration/001_create_nicks.rb +13 -0
- data/lib/mod_spox/migration/001_create_servers.rb +13 -0
- data/lib/mod_spox/migration/001_create_settings.rb +13 -0
- data/lib/mod_spox/migration/001_create_signatures.rb +13 -0
- data/lib/mod_spox/migration/001_create_triggers.rb +13 -0
- data/lib/mod_spox/models/Auth.rb +79 -0
- data/lib/mod_spox/models/AuthGroup.rb +15 -0
- data/lib/mod_spox/models/Channel.rb +47 -0
- data/lib/mod_spox/models/ChannelMode.rb +14 -0
- data/lib/mod_spox/models/Config.rb +31 -0
- data/lib/mod_spox/models/Group.rb +13 -0
- data/lib/mod_spox/models/Nick.rb +110 -0
- data/lib/mod_spox/models/NickChannel.rb +43 -0
- data/lib/mod_spox/models/NickMode.rb +18 -0
- data/lib/mod_spox/models/Server.rb +12 -0
- data/lib/mod_spox/models/Setting.rb +40 -0
- data/lib/mod_spox/models/Signature.rb +30 -0
- data/lib/mod_spox/models/Trigger.rb +9 -0
- data/lib/mod_spox/rfc2812.rb +171 -0
- metadata +261 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
module ModSpox
|
|
2
|
+
|
|
3
|
+
class Action
|
|
4
|
+
|
|
5
|
+
# timer:: Timer the action is being added to
|
|
6
|
+
# period:: number of seconds between runs
|
|
7
|
+
# data:: data to be available for the action
|
|
8
|
+
# once:: only run the action once
|
|
9
|
+
# &func:: block of code to run
|
|
10
|
+
# Create a new Action
|
|
11
|
+
def initialize(timer, period, data=nil, once=false, &func)
|
|
12
|
+
@period = period.to_f
|
|
13
|
+
@func = func
|
|
14
|
+
@data = data
|
|
15
|
+
@once = once
|
|
16
|
+
@due = false
|
|
17
|
+
@timer = timer
|
|
18
|
+
@completed = false
|
|
19
|
+
@wait_remaining = @period
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# amount:: number of seconds passed
|
|
23
|
+
# Decrement wait time by given number of seconds
|
|
24
|
+
def tick(amount)
|
|
25
|
+
@wait_remaining = @wait_remaining - amount
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Returns true if action is due to run
|
|
29
|
+
def due?
|
|
30
|
+
@wait_remaining <= 0
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Returns the remaining number of seconds
|
|
34
|
+
def remaining
|
|
35
|
+
@wait_remaining <= 0 ? 0 : @wait_remaining
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# new_time:: number of seconds between runs
|
|
39
|
+
# Resets the wait time between runs
|
|
40
|
+
def reset_period(new_time)
|
|
41
|
+
@period = new_time.to_f
|
|
42
|
+
@wait_remaining = @period
|
|
43
|
+
@timer.wakeup
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Returns if the Action has completed all its runs
|
|
47
|
+
def is_complete?
|
|
48
|
+
@completed
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Used for scheduling with Timer. Resets its internal
|
|
52
|
+
# timer and returns itself
|
|
53
|
+
def schedule
|
|
54
|
+
@wait_remaining = @period
|
|
55
|
+
return self
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Runs the function block of the action
|
|
59
|
+
def run
|
|
60
|
+
begin
|
|
61
|
+
unless @data.nil?
|
|
62
|
+
@func.call(@data)
|
|
63
|
+
else
|
|
64
|
+
@func.call
|
|
65
|
+
end
|
|
66
|
+
rescue Object => boom
|
|
67
|
+
Logger.log("Action generated an exception during run: #{boom}\n#{boom.backtrace.join("\n")}", 10)
|
|
68
|
+
end
|
|
69
|
+
@completed = true if @once
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module ModSpox
|
|
2
|
+
|
|
3
|
+
class BaseConfig
|
|
4
|
+
|
|
5
|
+
# file_path:: path to configuration file
|
|
6
|
+
# Creates new BaseConfig
|
|
7
|
+
def initialize(file_path)
|
|
8
|
+
@config = Hash.new
|
|
9
|
+
@file_path = file_path
|
|
10
|
+
parse_configuration
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# name:: key of config item wanted
|
|
14
|
+
# Provides access to configuration data
|
|
15
|
+
def [](name)
|
|
16
|
+
name = name.to_sym unless name.is_a?(Symbol)
|
|
17
|
+
raise Exceptions::UnknownKey.new("Configuration has no value named: #{name.to_s}") unless @config.has_key?(name)
|
|
18
|
+
return @config[name]
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def []=(key, value)
|
|
22
|
+
key = key.to_sym unless key.is_a?(Symbol)
|
|
23
|
+
@config[key] = value
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Parses the configuration file into a usable Hash
|
|
27
|
+
def parse_configuration
|
|
28
|
+
return unless File.exists?(BotConfig[:userconfigpath])
|
|
29
|
+
IO.readlines(BotConfig[:userconfigpath]).each{|line|
|
|
30
|
+
if(line =~ /^(\S+)\s*=\s*(\S*)\s*$/)
|
|
31
|
+
@config[$1.to_sym] = $2
|
|
32
|
+
end
|
|
33
|
+
}
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Writes the configuration file out to the provided file_path
|
|
37
|
+
# during initialization
|
|
38
|
+
def write_configuration
|
|
39
|
+
file = File.open(BotConfig[:userconfigpath], 'w')
|
|
40
|
+
@config.each_pair{|k,v|
|
|
41
|
+
file.puts("#{k.to_s}=#{v}")
|
|
42
|
+
}
|
|
43
|
+
file.close
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
end
|
data/lib/mod_spox/Bot.rb
ADDED
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
module ModSpox
|
|
2
|
+
|
|
3
|
+
class Bot
|
|
4
|
+
|
|
5
|
+
# bot timer
|
|
6
|
+
attr_reader :timer
|
|
7
|
+
|
|
8
|
+
# message pipeline
|
|
9
|
+
attr_reader :pipeline
|
|
10
|
+
|
|
11
|
+
# plugin manager
|
|
12
|
+
attr_reader :plugin_manager
|
|
13
|
+
|
|
14
|
+
# message factory
|
|
15
|
+
attr_reader :factory
|
|
16
|
+
|
|
17
|
+
# Create a Bot
|
|
18
|
+
def initialize
|
|
19
|
+
Logger.severity($VERBOSITY)
|
|
20
|
+
Logger.fd
|
|
21
|
+
clean_models
|
|
22
|
+
@start_time = Time.now
|
|
23
|
+
@pipeline = Pipeline.new
|
|
24
|
+
@timer = Timer.new(@pipeline)
|
|
25
|
+
@config = BaseConfig.new(BotConfig[:userconfigpath])
|
|
26
|
+
@factory = MessageFactory.new(@pipeline)
|
|
27
|
+
@socket = nil
|
|
28
|
+
@plugin_manager = PluginManager.new(@pipeline)
|
|
29
|
+
@shutdown = false
|
|
30
|
+
@socket = nil
|
|
31
|
+
@nick = nil
|
|
32
|
+
@thread = Thread.current
|
|
33
|
+
hook_pipeline
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Run the bot
|
|
37
|
+
def run
|
|
38
|
+
trap('SIGTERM'){ Logger.log("Caught SIGTERM"); Thread.current.exit }
|
|
39
|
+
trap('SIGKILL'){ Logger.log("Caught SIGKILL"); Thread.current.exit }
|
|
40
|
+
trap('SIGINT'){ Logger.log("Caught SIGINT"); Thread.current.exit }
|
|
41
|
+
trap('SIGQUIT'){ Logger.log("Caught SIGQUIT"); Thread.current.exit }
|
|
42
|
+
until @shutdown do
|
|
43
|
+
@timer.start
|
|
44
|
+
@pipeline << Messages::Internal::BotInitialized.new
|
|
45
|
+
begin
|
|
46
|
+
Thread.stop
|
|
47
|
+
rescue Object => boom
|
|
48
|
+
Logger.log("Caught exception: #{boom}")
|
|
49
|
+
end
|
|
50
|
+
shutdown
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Shut the bot down
|
|
55
|
+
def shutdown
|
|
56
|
+
@shutdown = true
|
|
57
|
+
@plugin_manager.destroy_plugins
|
|
58
|
+
@thread.run
|
|
59
|
+
@timer.stop
|
|
60
|
+
@timer.destroy
|
|
61
|
+
@factory.destroy
|
|
62
|
+
@pipeline << Messages::Internal::Shutdown.new
|
|
63
|
+
sleep(0.1)
|
|
64
|
+
@pipeline.destroy
|
|
65
|
+
@socket.shutdown unless @socket.nil?
|
|
66
|
+
clean_models
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Reload the bot (basically a restart)
|
|
70
|
+
def reload
|
|
71
|
+
@thread.run
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# message:: Messages::Internal::EstablishConnection message
|
|
75
|
+
# Initialize connection to IRC server
|
|
76
|
+
def bot_connect(message)
|
|
77
|
+
Logger.log("Received a connection command", 10)
|
|
78
|
+
begin
|
|
79
|
+
@socket = Socket.new(self, message.server, message.port)
|
|
80
|
+
@socket.connect
|
|
81
|
+
@pipeline << Messages::Internal::Connected.new(message.server, message.port)
|
|
82
|
+
rescue Object => boom
|
|
83
|
+
Logger.log("Failed connection to server: #{boom}")
|
|
84
|
+
@pipeline << Messages::Internal::ConnectionFailed.new(message.server, message.port)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# message:: Messages::Internal::StatusRequest message
|
|
89
|
+
# Returns the current status of the bot
|
|
90
|
+
def status(message)
|
|
91
|
+
@pipeline << Messages::Internal::StatusResponse(message.requester, stats)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# Returns status of the bot in a formatted string
|
|
95
|
+
def stats
|
|
96
|
+
return ["Uptime: #{Helpers::format_seconds(@start_time - Time.now)}",
|
|
97
|
+
"Plugins: #{@plugins.plugins.size} loaded",
|
|
98
|
+
"Lines sent: #{@socket.sent}",
|
|
99
|
+
"Lines received: #{@socket.received}"].join(' ')
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Adds hooks to pipeline for processing messages
|
|
103
|
+
def hook_pipeline
|
|
104
|
+
{:Outgoing_Admin => :admin, :Outgoing_Away => :away,
|
|
105
|
+
:Outgoing_ChannelMode => :chanmode, :Outgoing_Connect => :connect,
|
|
106
|
+
:Outgoing_Die => :die, :Outgoing_Info => :info,
|
|
107
|
+
:Outgoing_Invite => :invite, :Outgoing_Ison => :ison,
|
|
108
|
+
:Outgoing_Join => :join, :Outgoing_Kick => :kick,
|
|
109
|
+
:Outgoing_Kill => :kill, :Outgoing_Links => :links,
|
|
110
|
+
:Outgoing_List => :list, :Outgoing_Lusers => :lusers,
|
|
111
|
+
:Outgoing_Motd => :motd, :Outgoing_Names => :names,
|
|
112
|
+
:Outgoing_Nick => :nick, :Outgoing_Notice => :notice,
|
|
113
|
+
:Outgoing_Oper => :oper, :Outgoing_Part => :part,
|
|
114
|
+
:Outgoing_Pass => :pass, :Outgoing_Ping => :ping,
|
|
115
|
+
:Outgoing_Pong => :pong, :Outgoing_Privmsg => :privmsg,
|
|
116
|
+
:Outgoing_Quit => :quit, :Outgoing_Rehash => :rehash,
|
|
117
|
+
:Outgoing_ServList => :servlist, :Outgoing_Squery => :squery,
|
|
118
|
+
:Outgoing_Squit => :squit, :Outgoing_Stats => :stats,
|
|
119
|
+
:Outgoing_Summon => :summon, :Outgoing_Time => :time,
|
|
120
|
+
:Outgoing_Topic => :topic, :Outgoing_Trace => :trace,
|
|
121
|
+
:Outgoing_Unaway => :unaway, :Outgoing_User => :user,
|
|
122
|
+
:Outgoing_UserHost => :userhost, :Outgoing_UserMode => :usermode,
|
|
123
|
+
:Outgoing_Users => :users, :Outgoing_Version => :version,
|
|
124
|
+
:Outgoing_Who => :who, :Outgoing_WhoWas => :whowas,
|
|
125
|
+
:Outgoing_Whois => :whois, :Internal_EstablishConnection => :bot_connect,
|
|
126
|
+
:Internal_StatusRequest => :status, :Internal_ChangeNick => :set_nick,
|
|
127
|
+
:Internal_NickRequest => :get_nick, :Internal_HaltBot => :halt,
|
|
128
|
+
:Internal_Disconnected => :disconnected, :Internal_TimerClear => :clear_timer
|
|
129
|
+
}.each_pair{ |type,method| @pipeline.hook(self, method, type) }
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# message:: Messages::Internal::TimerClear
|
|
133
|
+
# Clear all actions from timer
|
|
134
|
+
def clear_timer(message)
|
|
135
|
+
@timer.clear
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# message:: Messages::Internal::Disconnected
|
|
139
|
+
# Disconnect the bot from the IRC server
|
|
140
|
+
def disconnected(message)
|
|
141
|
+
@socket.shutdown
|
|
142
|
+
@socket = nil
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# Stop the bot
|
|
146
|
+
def halt(message)
|
|
147
|
+
@shutdown = true
|
|
148
|
+
@thread.run
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
# message:: Messages::Internal::ChangeNick message
|
|
152
|
+
# Changes the bot's nick to the given nick
|
|
153
|
+
def set_nick(message)
|
|
154
|
+
@nick = message.new_nick
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# message:: Messages::Internal::NickRequest
|
|
158
|
+
# Sends the bot's nick to plugins
|
|
159
|
+
def get_nick(message)
|
|
160
|
+
@pipeline << Messages::Internal::NickResponse(message.requester, @nick)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# message:: Messages::Outgoing::Pass message
|
|
164
|
+
# Sends PASS message to server
|
|
165
|
+
def pass(message)
|
|
166
|
+
@socket << "PASS #{message.password}"
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# message:: Messages::Outgoing::Nick message
|
|
170
|
+
# Sends NICK message to server
|
|
171
|
+
def nick(message)
|
|
172
|
+
nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
|
|
173
|
+
@socket << "NICK #{nick}"
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# message:: Messages::Outgoing::User message
|
|
177
|
+
# Sends USER message to server
|
|
178
|
+
def user(message)
|
|
179
|
+
@socket << "USER #{message.username} #{message.mode} * :#{message.real_name}"
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# message:: Messages::Outgoing::Oper message
|
|
183
|
+
# Sends Oper message to server
|
|
184
|
+
def oper(message)
|
|
185
|
+
@socket << "OPER #{message.name} #{message.password}"
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# message:: Messages::Outgoing::UserMode message
|
|
189
|
+
# Sends MODE message to server
|
|
190
|
+
def user_mode(message)
|
|
191
|
+
raise Exceptions::InvalidValue.new('Mode must be in the form of: [+-][a-z]+') unless message.mode =~ /^[+\-][a-z]+$/
|
|
192
|
+
nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
|
|
193
|
+
@socket << "MODE #{nick} #{message.mode}"
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# message:: Messages::Outgoing::Quit message
|
|
197
|
+
# Sends QUIT message to server
|
|
198
|
+
def quit(message)
|
|
199
|
+
@socket << "QUIT :#{message.message}"
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# message:: Messages::Outgoing::Squit message
|
|
203
|
+
# Sends SQUIT message to server
|
|
204
|
+
def squit(message)
|
|
205
|
+
@socket << "SQUIT #{message.server} :#{message.comment}"
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# message:: Messages::Outgoing::Join message
|
|
209
|
+
# Sends JOIN message to server
|
|
210
|
+
def join(message)
|
|
211
|
+
channel = message.channel.is_a?(Models::Channel) ? message.channel.name : message.channel
|
|
212
|
+
@socket << "JOIN #{channel} #{message.key}"
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# message:: Messages::Outgoing::Part message
|
|
216
|
+
# Sends PART message to server
|
|
217
|
+
def part(message)
|
|
218
|
+
channel = message.channel.is_a?(Models::Channel) ? message.channel.name : message.channel
|
|
219
|
+
@socket << "PART #{channel} :#{message.reason}"
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# message:: Messages::Outgoing::ChannelMode message
|
|
223
|
+
# Sends MODE message to server
|
|
224
|
+
def channel_mode(message)
|
|
225
|
+
target = message.target
|
|
226
|
+
channel = message.channel
|
|
227
|
+
target = target.nick if target.is_a?(Models::Nick)
|
|
228
|
+
channel = channel.name if channel.is_a?(Models::Channel)
|
|
229
|
+
@socket << "MODE #{channel} #{message.mode} #{target}"
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# message:: Messages::Outgoing::Topic message
|
|
233
|
+
# Sends TOPIC message to server
|
|
234
|
+
def topic(message)
|
|
235
|
+
channel = message.channel.is_a?(Models::Channel) ? message.channel.name : message.channel
|
|
236
|
+
@socket << "TOPIC #{channel} :#{message.topic}"
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# message:: Messages::Outgoing::Names message
|
|
240
|
+
# Sends NAMES message to server
|
|
241
|
+
def names(message)
|
|
242
|
+
channel = message.channel.is_a?(Models::Channel) ? message.channel.name : message.channel
|
|
243
|
+
@socket << "NAMES #{channel} #{message.target}"
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
# message:: Messages::Outgoing::List message
|
|
247
|
+
# Sends LIST message to server
|
|
248
|
+
def list(message)
|
|
249
|
+
channel = message.channel.is_a?(Models::Channel) ? message.channel.name : message.channel
|
|
250
|
+
@socket << "LIST #{channel}"
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
# message:: Messages::Outgoing::Invite message
|
|
254
|
+
# Sends INVITE message to server
|
|
255
|
+
def invite(message)
|
|
256
|
+
nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
|
|
257
|
+
channel = message.channel.is_a?(Models::Channel) ? message.channel.name : message.channel
|
|
258
|
+
@socket << "INVITE #{nick} #{channel}"
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
# message:: Messages::Outgoing::Kick message
|
|
262
|
+
# Sends KICK message to server
|
|
263
|
+
def kick(message)
|
|
264
|
+
nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
|
|
265
|
+
channel = message.channel.is_a?(Models::Channel) ? message.channel.name : message.channel
|
|
266
|
+
@socket << "KICK #{channel} #{nick} :#{message.reason}"
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# message:: Messages::Outgoing::Privmsg message
|
|
270
|
+
# Sends PRIVMSG message to server
|
|
271
|
+
def privmsg(message)
|
|
272
|
+
target = message.target.name if message.target.is_a?(Models::Channel)
|
|
273
|
+
target = message.target.nick if message.target.is_a?(Models::Nick)
|
|
274
|
+
target = message.target unless target
|
|
275
|
+
@socket << "PRIVMSG #{target} :#{message.message}"
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
# message:: Messages::Outgoing::Notice message
|
|
279
|
+
# Sends NOTICE message to server
|
|
280
|
+
def notice(message)
|
|
281
|
+
target = message.target.name if message.target.is_a?(Models::Channel)
|
|
282
|
+
target = message.target.nick if message.target.is_a?(Models::Nick)
|
|
283
|
+
@socket << "NOTICE #{target} :#{message}"
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
# message:: Messages::Outgoing::Motd message
|
|
287
|
+
# Sends MOTD message to server
|
|
288
|
+
def motd(message)
|
|
289
|
+
@socket << "MOTD #{message.target}"
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
# message:: Messages::Outgoing::Lusers message
|
|
293
|
+
# Sends LUSERS message to server
|
|
294
|
+
def lusers(message)
|
|
295
|
+
@socket << "LUSERS #{message.mask} #{message.target}"
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
# message:: Messages::Outgoing::Version message
|
|
299
|
+
# Sends VERSION message to server
|
|
300
|
+
def version(message)
|
|
301
|
+
@socket << "VERSION #{message.target}"
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
# message:: Messages::Outgoing::Stats message
|
|
305
|
+
# Sends STATS message to server
|
|
306
|
+
def stats(message)
|
|
307
|
+
raise Exceptions::InvalidValue.new('Query must be a single character') unless message.query =~ /^[a-z]$/
|
|
308
|
+
@socket << "STATS #{message.query} #{message.target}"
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
# message:: Messages::Outgoing::Links message
|
|
312
|
+
# Sends LINKS message to server
|
|
313
|
+
def links(message)
|
|
314
|
+
@socket << "LIST #{message.server} #{message.mask}"
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
# message:: Messages::Outgoing::Time message
|
|
318
|
+
# Sends TIME message to server
|
|
319
|
+
def time(message)
|
|
320
|
+
@socket << "TIME #{message.target}"
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
# message:: Messages::Outgoing::Connect message
|
|
324
|
+
# Sends CONNECT message to server
|
|
325
|
+
def connect(message)
|
|
326
|
+
@socket << "CONNECT #{message.target_server} #{message.port} #{message.remote_server}"
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
# message:: Messages::Outgoing::Trace message
|
|
330
|
+
# Sends TRACE message to server
|
|
331
|
+
def trace(message)
|
|
332
|
+
@socket << "TRACE #{message.target}"
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
# message:: Messages::Outgoing::Admin message
|
|
336
|
+
# Sends ADMIN message to server
|
|
337
|
+
def admin(message)
|
|
338
|
+
@socket << "ADMIN #{message.target}"
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
# message:: Messages::Outgoing::Info message
|
|
342
|
+
# Sends INFO message to server
|
|
343
|
+
def info(message)
|
|
344
|
+
@socket << "INFO #{message.target}"
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
# message:: Messages::Outgoing::ServList message
|
|
348
|
+
# Sends SERVLIST message to server
|
|
349
|
+
def servlist(message)
|
|
350
|
+
@socket << "SERVLIST #{message.mask} #{message.type}"
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
# message:: Messages::Outgoing::Squery message
|
|
354
|
+
# Sends SQUERY message to server
|
|
355
|
+
def squery(message)
|
|
356
|
+
@socket << "SQUERY #{message.service_name} #{message.message}"
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
# message:: Messages::Outgoing::Who message
|
|
360
|
+
# Sends WHO message to server
|
|
361
|
+
def who(message)
|
|
362
|
+
o = message.only_ops ? 'o' : ''
|
|
363
|
+
@socket << "WHO #{message.mask} #{o}"
|
|
364
|
+
end
|
|
365
|
+
|
|
366
|
+
# message:: Messages::Outgoing::Whois message
|
|
367
|
+
# Sends WHOIS message to server
|
|
368
|
+
def whois(message)
|
|
369
|
+
nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
|
|
370
|
+
@socket << "WHOIS #{message.target_server} #{nick}"
|
|
371
|
+
end
|
|
372
|
+
|
|
373
|
+
# message:: Messages::Outgoing::WhoWas message
|
|
374
|
+
# Sends WHOWAS message to server
|
|
375
|
+
def whowas(message)
|
|
376
|
+
nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
|
|
377
|
+
@socket << "WHOWAS #{message.nick} #{message.count} #{message.target}"
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
# message:: Messages::Outgoing::Kill message
|
|
381
|
+
# Sends KILL message to server
|
|
382
|
+
def kill(message)
|
|
383
|
+
nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
|
|
384
|
+
@socket << "KILL #{nick} :#{message.comment}"
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
# message:: Messages::Outgoing::Ping message
|
|
388
|
+
# Sends PING message to server
|
|
389
|
+
def ping(message)
|
|
390
|
+
@socket << "PING #{message.message}"
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
# message:: Messages::Outgoing::Pong message
|
|
394
|
+
# Sends PONG message to server
|
|
395
|
+
def pong(message)
|
|
396
|
+
@socket << "PONG #{message.server} #{message.string.nil? ? '' : ":#{message.string}"}"
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
# message:: Messages::Outgoing::Away message
|
|
400
|
+
# Sends AWAY message to server
|
|
401
|
+
def away(message)
|
|
402
|
+
@socket << "AWAY :#{message.message}"
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
# message:: Messages::Outgoing::Unaway message
|
|
406
|
+
# Sends AWAY message to server
|
|
407
|
+
def unaway(message)
|
|
408
|
+
@socket << "AWAY"
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
# message:: Messages::Outgoing::Rehash message
|
|
412
|
+
# Sends REHASH message to server
|
|
413
|
+
def rehash(message)
|
|
414
|
+
@socket << "REHASH"
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
# message:: Messages::Outgoing::Die message
|
|
418
|
+
# Sends DIE message to server
|
|
419
|
+
def die(message)
|
|
420
|
+
@socket << "DIE"
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
# message:: Messages::Outgoing::Restart message
|
|
424
|
+
# Sends RESTART message to server
|
|
425
|
+
def restart(message)
|
|
426
|
+
@socket << "RESTART"
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
# message:: Messages::Outgoing::Summon message
|
|
430
|
+
# Sends SUMMON message to server
|
|
431
|
+
def summon(message)
|
|
432
|
+
nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
|
|
433
|
+
channel = message.channel.is_a?(Models::Channel) ? message.channel.name : message.channel
|
|
434
|
+
@socket << "SUMMON #{nick} #{message.target} #{channel}"
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
# message:: Messages::Outgoing::Users message
|
|
438
|
+
# Sends USERS message to server
|
|
439
|
+
def users(message)
|
|
440
|
+
@socket << "USERS #{message.target}"
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
def wallops
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
# message:: Messages::Outgoing::UserHost message
|
|
447
|
+
# Sends USERHOST message to server
|
|
448
|
+
def userhost(message)
|
|
449
|
+
nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
|
|
450
|
+
@socket << "USERHOST #{nick}"
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
# message:: Messages::Outgoing::Ison message
|
|
454
|
+
# Sends ISON message to server
|
|
455
|
+
def ison(message)
|
|
456
|
+
nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
|
|
457
|
+
@socket << "ISON #{nick}"
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
private
|
|
461
|
+
|
|
462
|
+
# Cleans information from models to avoid
|
|
463
|
+
# stale values
|
|
464
|
+
def clean_models
|
|
465
|
+
Models::Nick.clean
|
|
466
|
+
Models::Channel.clean
|
|
467
|
+
Models::NickChannel.destroy_all
|
|
468
|
+
Models::Signature.delete_all
|
|
469
|
+
end
|
|
470
|
+
end
|
|
471
|
+
|
|
472
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module ModSpox
|
|
2
|
+
|
|
3
|
+
class BotConfig
|
|
4
|
+
|
|
5
|
+
@@config = nil
|
|
6
|
+
|
|
7
|
+
# Populates all important paths. This does not need to
|
|
8
|
+
# be explicitly called though nothing bad will happen if
|
|
9
|
+
# it is. Keys available are:
|
|
10
|
+
# :basepath => path to gem directory
|
|
11
|
+
# :libpath => path to lib directory
|
|
12
|
+
# :datapath => path to data directory
|
|
13
|
+
# :pluginpath => path to plugin directory
|
|
14
|
+
# :pluginextraspath => path to extra functionality plugins
|
|
15
|
+
# :userpath => path to mod_spox directory in user's home directory
|
|
16
|
+
# :userpluginpath => path to user's plugin directory
|
|
17
|
+
# :userconfigpath => path to the user configuration file
|
|
18
|
+
def self.populate
|
|
19
|
+
gemname, gem = Gem.source_index.find{|name, spec|
|
|
20
|
+
spec.name == 'mod_spox' && spec.version.version = $BOTVERSION
|
|
21
|
+
}
|
|
22
|
+
if(gem)
|
|
23
|
+
p = gem.full_gem_path
|
|
24
|
+
up = Etc.getpwnam(Etc.getlogin).dir
|
|
25
|
+
@@config = {:basepath => p,
|
|
26
|
+
:libpath => "#{p}/lib/mod_spox",
|
|
27
|
+
:datapath => "#{p}/data/mod_spox",
|
|
28
|
+
:pluginpath => "#{p}/data/mod_spox/plugins",
|
|
29
|
+
:pluginextraspath => "#{p}/data/mod_spox/extras",
|
|
30
|
+
:userpath => "#{up}/.mod_spox",
|
|
31
|
+
:userpluginpath => "#{up}/.mod_spox/plugins",
|
|
32
|
+
:userconfigpath => "#{up}/.mod_spox/config"}
|
|
33
|
+
[@@config[:userpath], @@config[:userpluginpath]].each do |path|
|
|
34
|
+
Dir.mkdir(path) unless File.exists?(path)
|
|
35
|
+
end
|
|
36
|
+
else
|
|
37
|
+
p gem
|
|
38
|
+
p gemname
|
|
39
|
+
raise Exceptions::InstallationError.new('Failed to find mod_spox gem')
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# name:: Name of the path string you would like
|
|
44
|
+
# Provides access to important path values
|
|
45
|
+
def self.[](name)
|
|
46
|
+
BotConfig.populate unless @@config
|
|
47
|
+
name = name.to_sym unless name.is_a?(Symbol)
|
|
48
|
+
raise Exceptions::UnknownKey.new("Failed to find given key: #{name}") unless @@config.has_key?(name)
|
|
49
|
+
return @@config[name]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
end
|