mod_spox 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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,178 @@
|
|
1
|
+
['etc', 'termios', 'mod_spox/Loader',
|
2
|
+
'mod_spox/BotConfig', 'mod_spox/BaseConfig'].each{|f|require f}
|
3
|
+
|
4
|
+
|
5
|
+
module ModSpox
|
6
|
+
|
7
|
+
class ConfigurationWizard
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@echo = nil
|
11
|
+
@config = Array.new
|
12
|
+
@config << {:id => :db_username, :string => 'Database username: ', :regex => '[a-zA-Z].*', :default => 'mod_spox', :value => nil, :echo => true}
|
13
|
+
@config << {:id => :db_password, :string => 'Database password: ', :regex => '.*', :default => nil, :value => nil, :echo => false}
|
14
|
+
@config << {:id => :db_host, :string => 'Database host: ', :regex => '.+', :default => 'localhost', :value => nil, :echo => true}
|
15
|
+
@config << {:id => :db_database, :string => 'Database name: ', :regex => '.+', :default => 'mod_spox', :value => nil, :echo => true}
|
16
|
+
@config << {:id => :db_adapter, :string => 'Database type (mysql|pgsql|sqlite): ', :regex => '(mysql|pgsql|sqlite)', :default => nil, :value => nil, :echo => true}
|
17
|
+
@config << {:id => :irc_server, :string => 'IRC Server: ', :regex => '.+', :default => nil, :value => nil, :echo => true}
|
18
|
+
@config << {:id => :irc_port, :string => 'IRC Port: ', :regex => '[0-9]+', :default => nil, :value => nil, :echo => true}
|
19
|
+
@config << {:id => :reconnect_wait, :string => 'Reconnect wait time: ', :regex => '[0-9]+', :default => '10', :value => nil, :echo => true}
|
20
|
+
@config << {:id => :bot_nick, :string => 'IRC Nick: ', :regex => '[a-zA-Z].*', :default => 'mod_spox', :value => nil, :echo => true}
|
21
|
+
@config << {:id => :bot_password, :string => 'IRC Nick Password: ', :regex => '.*', :default => nil, :value => nil, :echo => false}
|
22
|
+
@config << {:id => :bot_username, :string => 'IRC Username: ', :regex => '.+', :default => 'mod_spox', :value => nil, :echo => true}
|
23
|
+
@config << {:id => :bot_realname, :string => 'IRC Real Name: ', :regex => '.+', :default => 'mod_spox IRC bot', :value => nil, :echo => true}
|
24
|
+
@config << {:id => :socket_burst, :string => 'Socket burst rate (lines): ', :regex => '[0-9]+', :default => '3', :value => nil, :echo => true}
|
25
|
+
@config << {:id => :socket_burst_in, :string => 'Socket burst time: ', :regex => '[0-9]+', :default => '2', :value => nil, :echo => true}
|
26
|
+
@config << {:id => :socket_burst_delay, :string => 'Socket burst delay: ', :regex => '[0-9]+', :default => '2', :value => nil, :echo => true}
|
27
|
+
@config << {:id => :admin_nick, :string => 'Administrator nick: ', :regex => '[a-zA-Z].*', :default => nil, :value => nil, :echo => true}
|
28
|
+
@config << {:id => :admin_password, :string => 'Administrator password: ', :regex => '.+', :default => nil, :value => nil, :echo => false}
|
29
|
+
@config << {:id => :plugin_directory, :string => 'Plugin directory (bot must have write priviliges): ', :regex => '.+', :default => nil, :echo => true}
|
30
|
+
@config << {:id => :trigger, :string => 'Trigger character for plugins: ', :regex => '.', :default => '!', :value => nil, :echo => true}
|
31
|
+
end
|
32
|
+
|
33
|
+
# Run the configuration wizard
|
34
|
+
def run
|
35
|
+
puts "*********************************"
|
36
|
+
puts "* mod_spox Configuration Wizard *"
|
37
|
+
puts "*********************************"
|
38
|
+
puts ""
|
39
|
+
@config.each{|v|
|
40
|
+
v[:value] = get_input(v[:string], v[:regex], v[:echo], v[:default])
|
41
|
+
}
|
42
|
+
print "Storing configuration values... "
|
43
|
+
save_configuration
|
44
|
+
puts "OK"
|
45
|
+
puts "mod_spox is now configured and ready for use"
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def find(key)
|
51
|
+
@config.each{|c|
|
52
|
+
if(c[:id] == key)
|
53
|
+
return c[:value]
|
54
|
+
end
|
55
|
+
}
|
56
|
+
return nil
|
57
|
+
end
|
58
|
+
|
59
|
+
# Save our configuration values
|
60
|
+
def save_configuration
|
61
|
+
config = BaseConfig.new(BotConfig[:userconfigpath])
|
62
|
+
@config.each{|value|
|
63
|
+
config[value[:id]] = value[:value] if value[:id].to_s =~ /^db/
|
64
|
+
}
|
65
|
+
config.write_configuration
|
66
|
+
initialize_bot
|
67
|
+
create_databases
|
68
|
+
#Migrators.constants.each{|m| Migrators.const_get(m).apply(Database.db, :up)}
|
69
|
+
@config.each{|value|
|
70
|
+
Models::Config[value[:id]] = value[:value] unless value[:id].to_s =~ /^(db|irc|admin|trigger)/
|
71
|
+
}
|
72
|
+
s = Models::Server.find_or_create(:host => find(:irc_server), :port => find(:irc_port))
|
73
|
+
n = Models::Nick.find_or_create(:nick => find(:admin_nick))
|
74
|
+
a = Models::Auth.find_or_create(:nick_id => n.pk)
|
75
|
+
a.group = Models::Group.find_or_create(:name => 'admin')
|
76
|
+
a.password = find(:admin_password)
|
77
|
+
a.save
|
78
|
+
t = Models::Trigger.find_or_create(:trigger => find(:trigger))
|
79
|
+
t.active = true
|
80
|
+
t.save
|
81
|
+
end
|
82
|
+
|
83
|
+
# echo:: echo user input
|
84
|
+
# Turns echoing of user input on or off
|
85
|
+
def input_echo(echo=true)
|
86
|
+
return if echo == @echo
|
87
|
+
term = Termios::getattr($stdin)
|
88
|
+
term.c_lflag |= Termios::ECHO if echo
|
89
|
+
term.c_lflag &= ~Termios::ECHO unless echo
|
90
|
+
Termios::setattr($stdin, Termios::TCSANOW, term)
|
91
|
+
@echo = echo
|
92
|
+
end
|
93
|
+
|
94
|
+
# pattern:: regex response must match
|
95
|
+
# default:: default value if response is empty
|
96
|
+
# echo:: echo user's input
|
97
|
+
# Reads users input
|
98
|
+
def read_input(pattern=nil, default=nil, echo=true)
|
99
|
+
input_echo(echo)
|
100
|
+
response = $stdin.readline
|
101
|
+
response.strip!
|
102
|
+
set = response.length > 0
|
103
|
+
unless(pattern.nil?)
|
104
|
+
response = nil unless response =~ /^#{pattern}$/
|
105
|
+
end
|
106
|
+
if(default && response.nil? && !set)
|
107
|
+
response = default
|
108
|
+
end
|
109
|
+
input_echo(true) unless echo
|
110
|
+
puts "" unless echo
|
111
|
+
return response
|
112
|
+
end
|
113
|
+
|
114
|
+
# output:: text to send before user input
|
115
|
+
# regex:: pattern user input must match (^ and $ not need. applied automatically)
|
116
|
+
# echo:: echo user's input
|
117
|
+
# default:: default value if no value is entered
|
118
|
+
def get_input(output, regex, echo=true, default=nil)
|
119
|
+
response = nil
|
120
|
+
until(response) do
|
121
|
+
print output
|
122
|
+
print "[#{default}]: " unless default.nil?
|
123
|
+
response = read_input(regex, default, echo)
|
124
|
+
end
|
125
|
+
return response
|
126
|
+
end
|
127
|
+
|
128
|
+
def create_databases
|
129
|
+
case Database.type
|
130
|
+
when :mysql
|
131
|
+
Database.db << "CREATE TABLE IF NOT EXISTS nicks (id int not null auto_increment primary key, nick varchar(255) unique not null, username varchar(255), real_name varchar(255), address varchar(255), source varchar(255), connected_at timestamp, connected_to varchar(255), seconds_idle int, visible boolean not null default false, away boolean not null default false, botnick boolean not null default false)"
|
132
|
+
Database.db << "CREATE TABLE IF NOT EXISTS channels (id int not null auto_increment primary key, name varchar(255) not null, password varchar(255), autojoin boolean not null default false, topic varchar(255), quiet boolean not null default false, parked boolean not null default false)"
|
133
|
+
Database.db << "CREATE TABLE IF NOT EXISTS auths (id int not null auto_increment primary key, password varchar(255), services boolean not null default false, mask varchar(255) unique, authed boolean not null default false, nick_id int unique references nicks)"
|
134
|
+
Database.db << "CREATE TABLE IF NOT EXISTS channel_modes (id int not null auto_increment primary key, mode varchar(255) not null, channel_id int unique not null references channels)"
|
135
|
+
Database.db << "CREATE TABLE IF NOT EXISTS configs (id int not null auto_increment primary key, name varchar(255) unique not null, value varchar(255))"
|
136
|
+
Database.db << "CREATE TABLE IF NOT EXISTS nick_channels (channel_id int not null unique references channels, nick_id int not null unique not null references nicks, primary key(channel_id, nick_id))"
|
137
|
+
Database.db << "CREATE TABLE IF NOT EXISTS nick_modes (id integer primary key auto_increment not null, mode varchar(255) not null, nick_id int not null references nicks, channel_id int references channels, unique index nick_modes_nick_id_channel_id_index (nick_id, channel_id))"
|
138
|
+
Database.db << "CREATE TABLE IF NOT EXISTS servers (id int not null auto_increment primary key, host varchar(255) not null, port int not null default 6667, priority int not null default 0, connected boolean not null default false, unique index servers_server_port_index (server, port))"
|
139
|
+
Database.db << "CREATE TABLE IF NOT EXISTS settings (id int not null auto_increment primary key, name varchar(255) not null unique, value text)"
|
140
|
+
Database.db << "CREATE TABLE IF NOT EXISTS signatures (id int not null auto_increment primary key, signature varchar(255) not null, params varchar(255), group_id int default null references groups, method varchar(255) not null, plugin varchar(255) not null, description text)"
|
141
|
+
Database.db << "CREATE TABLE IF NOT EXISTS triggers (id int not null auto_increment primary key, `trigger` varchar(255) unique not null, active boolean not null default false)"
|
142
|
+
Database.db << "CREATE TABLE IF NOT EXISTS groups (id int not null auto_increment primary key, name varchar(255) not null unique)"
|
143
|
+
Database.db << "CREATE TABLE IF NOT EXISTS auth_groups (auth_id int not null references auths, group_id int not null references groups, primary key(auth_id, group_id))"
|
144
|
+
when :pgsql
|
145
|
+
Database.db << "CREATE TABLE nicks (id serial not null primary key, nick text unique not null, username text, real_name text, address text, source text, connected_at timestamp, connected_to text, seconds_idle integer, visible boolean not null default false, away boolean not null default false, botnick boolean not null default false)"
|
146
|
+
Database.db << "CREATE TABLE channels (id serial not null primary key, name text unique not null, password text, autojoin boolean not null default false, topic text, quiet boolean not null default false, parked boolean not null default false)"
|
147
|
+
Database.db << "CREATE TABLE auths (id serial not null primary key, password text, services boolean not null default false, mask text unique, authed boolean not null default false, nick_id integer unique references nicks)"
|
148
|
+
Database.db << "CREATE TABLE groups (id serial not null primary key, name text unique not null)"
|
149
|
+
Database.db << "CREATE TABLE channel_modes (id serial not null primary key, mode text not null, channel_id integer unique not null references channels)"
|
150
|
+
Database.db << "CREATE TABLE configs (id serial not null primary key, name text unique not null, value text)"
|
151
|
+
Database.db << "CREATE TABLE nick_channels (channel_id integer not null references channels, nick_id integer not null references nicks, primary key(nick_id, channel_id))"
|
152
|
+
Database.db << "CREATE TABLE nick_modes (id serial not null primary key, mode text not null, nick_id integer not null references nicks, channel_id integer references channels, unique (nick_id, channel_id))"
|
153
|
+
Database.db << "CREATE TABLE servers (id serial not null primary key, host text not null, port integer not null default 6667, priority integer not null default 0, connected boolean not null default false, unique (host, port))"
|
154
|
+
Database.db << "CREATE TABLE signatures (id serial not null primary key, signature text not null, params text, group_id integer default null references groups, method text not null, plugin text not null, description text)"
|
155
|
+
Database.db << "CREATE TABLE settings (id serial not null primary key, name text unique not null, value text)"
|
156
|
+
Database.db << "CREATE TABLE triggers (id serial not null primary key, trigger text unique not null, active boolean not null default false)"
|
157
|
+
Database.db << "CREATE TABLE auth_groups (auth_id integer not null references auths, group_id integer not null references groups, primary key (auth_id, group_id))"
|
158
|
+
when :sqlite
|
159
|
+
Database.db << "CREATE TABLE if not exists nicks (id integer PRIMARY KEY AUTOINCREMENT, nick string UNIQUE NOT NULL COLLATE NOCASE, username string, real_name string, address string, source string, connected_at timestamp, connected_to string, seconds_idle integer, visible boolean NOT NULL DEFAULT 'f', away boolean NOT NULL DEFAULT 'f', botnick boolean NOT NULL DEFAULT 'f')"
|
160
|
+
Database.db << "CREATE TABLE if not exists channels (id integer PRIMARY KEY AUTOINCREMENT, name string UNIQUE NOT NULL COLLATE NOCASE, password string, autojoin boolean NOT NULL DEFAULT 'f', topic string, quiet boolean NOT NULL DEFAULT 'f', parked boolean NOT NULL DEFAULT 'f')"
|
161
|
+
Database.db << "CREATE TABLE if not exists auths (id integer PRIMARY KEY AUTOINCREMENT, password string, services boolean NOT NULL DEFAULT 'f', mask string UNIQUE, authed boolean NOT NULL DEFAULT 'f', nick_id integer UNIQUE REFERENCES nicks)"
|
162
|
+
Database.db << "CREATE TABLE if not exists channel_modes (id integer PRIMARY KEY AUTOINCREMENT, mode string NOT NULL, channel_id integer UNIQUE NOT NULL REFERENCES channels)"
|
163
|
+
Database.db << "CREATE TABLE if not exists configs (id integer PRIMARY KEY AUTOINCREMENT, name string UNIQUE NOT NULL, value string)"
|
164
|
+
Database.db << "CREATE TABLE if not exists nick_channels (channel_id integer NOT NULL REFERENCES channels, nick_id integer NOT NULL REFERENCES nicks, primary key (channel_id, nick_id))"
|
165
|
+
Database.db << "CREATE TABLE if not exists nick_modes (id integer PRIMARY KEY AUTOINCREMENT, mode string NOT NULL, nick_id integer NOT NULL REFERENCES nicks, channel_id integer REFERENCES channels)"
|
166
|
+
Database.db << "CREATE UNIQUE INDEX if not exists nick_modes_nick_id_channel_id_index ON nick_modes (nick_id, channel_id)"
|
167
|
+
Database.db << "CREATE TABLE if not exists servers (id integer primary key autoincrement, host string NOT NULL, port integer NOT NULL DEFAULT 6667, priority integer NOT NULL DEFAULT 0, connected boolean NOT NULL DEFAULT 'f', unique index servers_server_port_index (server, port))"
|
168
|
+
Database.db << "CREATE TABLE if not exists settings (id integer PRIMARY KEY AUTOINCREMENT, name string UNIQUE NOT NULL, value text)"
|
169
|
+
Database.db << "CREATE TABLE if not exists signatures (id integer PRIMARY KEY AUTOINCREMENT, signature string NOT NULL UNIQUE, params string, group_id integer DEFAULT NULL REFERENCES groups, method string NOT NULL, plugin string NOT NULL, description text)"
|
170
|
+
Database.db << "CREATE TABLE if not exists triggers (id integer PRIMARY KEY AUTOINCREMENT, trigger string UNIQUE NOT NULL, active boolean NOT NULL DEFAULT 'f')"
|
171
|
+
Database.db << "CREATE TABLE if not exists groups (id integer PRIMARY KEY AUTOINCREMENT, name string UNIQUE NOT NULL COLLATE NOCASE)"
|
172
|
+
Database.db << "CREATE TABLE if not exists auth_groups(auth_id integer REFERENCES auths, group_id integer REFERENCES groups)"
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
end
|
177
|
+
|
178
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ModSpox
|
2
|
+
|
3
|
+
class Database
|
4
|
+
|
5
|
+
def self.db=(database)
|
6
|
+
@@db = nil
|
7
|
+
@@db = database
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.type=(type)
|
11
|
+
@@type = nil
|
12
|
+
@@type = type
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.type
|
16
|
+
return Database.class_variable_defined?(:@@type) ? @@type : nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.db
|
20
|
+
return Database.class_variable_defined?(:@@db) ? @@db : nil
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module ModSpox
|
2
|
+
module Exceptions
|
3
|
+
|
4
|
+
class BotException < Exception
|
5
|
+
end
|
6
|
+
|
7
|
+
class NotImplemented < BotException
|
8
|
+
end
|
9
|
+
|
10
|
+
class InvalidType < BotException
|
11
|
+
end
|
12
|
+
|
13
|
+
class InvalidValue < BotException
|
14
|
+
end
|
15
|
+
|
16
|
+
class AlreadyRunning < BotException
|
17
|
+
end
|
18
|
+
|
19
|
+
class NotRunning < BotException
|
20
|
+
end
|
21
|
+
|
22
|
+
class UnknownKey < BotException
|
23
|
+
end
|
24
|
+
|
25
|
+
class InstallationError < BotException
|
26
|
+
end
|
27
|
+
|
28
|
+
class LockedObject < BotException
|
29
|
+
end
|
30
|
+
|
31
|
+
class TimerInUse < BotException
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
module ModSpox
|
3
|
+
module Helpers
|
4
|
+
# secs:: number of seconds
|
5
|
+
# Converts seconds into a human readable string
|
6
|
+
def Helpers.format_seconds(secs)
|
7
|
+
d = (secs / 86400).to_i
|
8
|
+
secs = secs % 86400
|
9
|
+
m = (secs / 3600).to_i
|
10
|
+
secs = secs % 3600
|
11
|
+
str = Array.new
|
12
|
+
str << d == 1 ? "#{d} day" : "#{d} days" if d > 0
|
13
|
+
str << m == 1 ? "#{m} minute" : "#{m} minutes" if m > 0
|
14
|
+
str << secs == 1 ? "#{secs} second" : "#{secs} seconds" if secs > 0
|
15
|
+
return str.join(' ')
|
16
|
+
end
|
17
|
+
|
18
|
+
# command:: command to execute
|
19
|
+
# timeout:: maximum number of seconds to run
|
20
|
+
# Execute a system command (use with care)
|
21
|
+
def Helpers.safe_exec(command, timeout=10)
|
22
|
+
begin
|
23
|
+
Timeout::timeout(timeout) do
|
24
|
+
result = `#{command}`
|
25
|
+
end
|
26
|
+
rescue Timeout::Error => boom
|
27
|
+
Logger.log("Command execution exceeded allowed time (command: #{command} | timeout: #{timeout})")
|
28
|
+
rescue Object => boom
|
29
|
+
Logger.log("Command generated an exception (command: #{command} | error: #{boom})")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module ModSpox
|
2
|
+
|
3
|
+
# directory:: path to directory
|
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
|
30
|
+
|
31
|
+
# Loads all files needed by the bot
|
32
|
+
def initialize_bot
|
33
|
+
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
|
+
end
|
57
|
+
|
58
|
+
# Setup the DataMapper adapter
|
59
|
+
def setup_adapter
|
60
|
+
require 'mod_spox/Exceptions'
|
61
|
+
require 'mod_spox/BotConfig'
|
62
|
+
require 'mod_spox/BaseConfig'
|
63
|
+
require 'mod_spox/Database'
|
64
|
+
config = BaseConfig.new(BotConfig[:userconfigpath])
|
65
|
+
case config[:db_adapter]
|
66
|
+
when 'mysql'
|
67
|
+
Database.db = Sequel.mysql(config[:db_database], :user => config[:db_username],
|
68
|
+
:password => config[:db_password], :host => config[:db_host])
|
69
|
+
Database.type = :mysql
|
70
|
+
when 'pgsql'
|
71
|
+
Database.db = Sequel.open("postgres://#{config[:db_username]}:#{config[:db_password]}@#{config[:db_host]}/#{config[:db_database]}")
|
72
|
+
Database.type = :pgsql
|
73
|
+
when 'sqlite'
|
74
|
+
Database.db = Sequel.sqlite "#{BotConfig[:userpath]}/mod_spox.db"
|
75
|
+
Database.type = :sqlite
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module ModSpox
|
2
|
+
|
3
|
+
class Logger
|
4
|
+
|
5
|
+
# severity:: minimum severity for visible logging
|
6
|
+
# Sets the maximum level of visible logs
|
7
|
+
def self.severity(severity=1)
|
8
|
+
@@severity = severity
|
9
|
+
end
|
10
|
+
|
11
|
+
# filedes:: file descriptor to log to
|
12
|
+
# Sets the file descriptor for logging. By default
|
13
|
+
# logs will be sent to STDOUT
|
14
|
+
def self.fd(filedes=nil)
|
15
|
+
@@fd = filedes.nil? ? $stdout : filedes
|
16
|
+
end
|
17
|
+
|
18
|
+
# message:: message to log
|
19
|
+
# severity:: severity level (lower is more severe)
|
20
|
+
# Log a message. It is important to note that the lower the
|
21
|
+
# severity level of a message, the better chance it has of
|
22
|
+
# being outputted
|
23
|
+
def self.log(message, severity=1)
|
24
|
+
Logger.fd(nil) unless Logger.class_variable_defined?(:@@fd)
|
25
|
+
Logger.severity unless Logger.class_variable_defined?(:@@severity)
|
26
|
+
@@fd.puts("LOGGER [#{Time.now}]: #{message}") unless @@severity < severity
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module ModSpox
|
2
|
+
|
3
|
+
class MessageFactory < Pool
|
4
|
+
|
5
|
+
# pipeline:: Message pipeline
|
6
|
+
# Create a new MessageFactory
|
7
|
+
def initialize(pipeline)
|
8
|
+
super(1)
|
9
|
+
@pipeline = pipeline
|
10
|
+
@handlers = Hash.new
|
11
|
+
@queue = Queue.new
|
12
|
+
Logger.log("Created new factory queue: #{@queue}", 15)
|
13
|
+
build_handlers
|
14
|
+
start_pool
|
15
|
+
end
|
16
|
+
|
17
|
+
# string:: server message to be parsed
|
18
|
+
# Parses messages from server. This is placed in a queue to
|
19
|
+
# be processed thus there is now wait for processing to be
|
20
|
+
# completed.
|
21
|
+
def <<(string)
|
22
|
+
@queue << string
|
23
|
+
end
|
24
|
+
|
25
|
+
# Builds the message handlers. This will load all Messages and Handlers
|
26
|
+
# found in the lib directory and then initialize all the Handlers
|
27
|
+
def build_handlers
|
28
|
+
# load our handlers in first
|
29
|
+
# note: the handlers add themselves to the @handlers hash
|
30
|
+
# during initialization
|
31
|
+
Handlers.constants.each{|name|
|
32
|
+
klass = Handlers.const_get(name)
|
33
|
+
if(klass < Handlers::Handler)
|
34
|
+
Logger.log("Building handler: #{name}")
|
35
|
+
begin
|
36
|
+
klass.new(@handlers)
|
37
|
+
rescue Object => boom
|
38
|
+
Logger.log("ERROR: Failed to build handler: #{name} -> #{boom}")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
}
|
42
|
+
Logger.log("Handlers now available:", 15)
|
43
|
+
@handlers.each_pair{|k,v| Logger.log("#{k} -> #{v}", 15)}
|
44
|
+
end
|
45
|
+
|
46
|
+
# message:: server message
|
47
|
+
# Parses the server message and passes it to the proper handler
|
48
|
+
def parse_message(message)
|
49
|
+
Logger.log("Processing message: #{message}", 15)
|
50
|
+
begin
|
51
|
+
if(message =~ /^:\S+ (\S+)/ || message =~ /^([A-Za-z0-9]+)\s/)
|
52
|
+
key = $1
|
53
|
+
key = key.to_sym unless key[0].chr =~ /\d/
|
54
|
+
if(@handlers.has_key?(key))
|
55
|
+
Logger.log("Message of type #{key} is now being handled by #{@handlers[key]}", 10)
|
56
|
+
message = @handlers[key].process(message)
|
57
|
+
@pipeline << message unless message.nil?
|
58
|
+
end
|
59
|
+
end
|
60
|
+
rescue Object => boom
|
61
|
+
Logger.log("Failed to parse message from server: #{boom}\n#{boom.backtrace.join("\n")}")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def processor
|
68
|
+
parse_message(@queue.pop)
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module ModSpox
|
2
|
+
module Monitors
|
3
|
+
|
4
|
+
# The Timer is a time based monitor (thus the
|
5
|
+
# "Timer" part of the name)
|
6
|
+
class Timer
|
7
|
+
|
8
|
+
# Create a new Timer Monitor
|
9
|
+
def initialize
|
10
|
+
@threads = Array.new
|
11
|
+
end
|
12
|
+
|
13
|
+
# Force the monitor to wake everyone up
|
14
|
+
def wakeup
|
15
|
+
@threads.each{|t|t.wakeup}
|
16
|
+
@threads.clear
|
17
|
+
end
|
18
|
+
|
19
|
+
# How long the monitor should wait
|
20
|
+
def wait(time=nil)
|
21
|
+
@threads << Thread.current
|
22
|
+
if(time.nil?)
|
23
|
+
sleep
|
24
|
+
else
|
25
|
+
sleep(time)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
# The Boolean is a boolean based monitor (thus the
|
32
|
+
# "Boolean" part of the name)
|
33
|
+
class Boolean
|
34
|
+
|
35
|
+
# Create a new Boolean Monitor
|
36
|
+
def initialize
|
37
|
+
@thread = nil
|
38
|
+
end
|
39
|
+
|
40
|
+
# Stop waiting
|
41
|
+
def wakeup
|
42
|
+
Logger.log("Sending wakeup for thread: #{@thread}", 5)
|
43
|
+
@thread.run unless @thread == nil
|
44
|
+
Logger.log("Status of thread to wakeup: #{@thread.status}", 5)
|
45
|
+
Logger.log("Calling thread is: #{Thread.current}", 5)
|
46
|
+
@thread = nil
|
47
|
+
end
|
48
|
+
|
49
|
+
# Start waiting
|
50
|
+
def wait
|
51
|
+
@thread = Thread.current
|
52
|
+
Logger.log("Stopping execution of thread: #{@thread}", 5)
|
53
|
+
Thread.stop
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|