mod_spox 0.1.0.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +36 -0
- data/INSTALL +2 -2
- data/README +0 -1
- data/bin/mod_spox +51 -12
- data/data/mod_spox/extras/AOLSpeak.rb +5 -18
- data/data/mod_spox/extras/AutoKick.rb +44 -23
- data/data/mod_spox/extras/AutoMode.rb +2 -5
- data/data/mod_spox/extras/AutoRejoin.rb +21 -0
- data/data/mod_spox/extras/Bouncer.rb +10 -10
- data/data/mod_spox/extras/Bytes.rb +12 -0
- data/data/mod_spox/extras/Confess.rb +131 -52
- data/data/mod_spox/extras/DCC.rb +189 -0
- data/data/mod_spox/extras/DevWatch.rb +32 -33
- data/data/mod_spox/extras/FloodKicker.rb +129 -0
- data/data/mod_spox/extras/GoogleIt.rb +13 -0
- data/data/mod_spox/extras/Headers.rb +31 -4
- data/data/mod_spox/extras/Karma.rb +103 -49
- data/data/mod_spox/extras/Logger.rb +45 -30
- data/data/mod_spox/extras/LolSpeak.rb +1 -1
- data/data/mod_spox/extras/NickServ.rb +83 -0
- data/data/mod_spox/extras/PhpCli.rb +12 -15
- data/data/mod_spox/extras/PhpFuncLookup.rb +57 -25
- data/data/mod_spox/extras/Quotes.rb +5 -4
- data/data/mod_spox/extras/RegexTracker.rb +160 -0
- data/data/mod_spox/extras/Roulette.rb +22 -23
- data/data/mod_spox/extras/Search.rb +3 -2
- data/data/mod_spox/extras/Slashdot.rb +35 -0
- data/data/mod_spox/extras/Topten.rb +5 -5
- data/data/mod_spox/extras/TracTicket.rb +68 -0
- data/data/mod_spox/extras/Translate.rb +69 -30
- data/data/mod_spox/extras/Twitter.rb +372 -0
- data/data/mod_spox/extras/UrbanDictionary.rb +21 -12
- data/data/mod_spox/extras/Weather.rb +1 -1
- data/data/mod_spox/plugins/Authenticator.rb +63 -30
- data/data/mod_spox/plugins/Banner.rb +164 -151
- data/data/mod_spox/plugins/Helper.rb +18 -7
- data/data/mod_spox/plugins/PluginLoader.rb +46 -22
- data/data/mod_spox/plugins/PoolConfig.rb +52 -0
- data/data/mod_spox/plugins/Quitter.rb +1 -1
- data/data/mod_spox/plugins/Status.rb +28 -0
- data/lib/mod_spox/Action.rb +20 -3
- data/lib/mod_spox/BaseConfig.rb +1 -0
- data/lib/mod_spox/Bot.rb +98 -75
- data/lib/mod_spox/BotConfig.rb +14 -6
- data/lib/mod_spox/ConfigurationWizard.rb +94 -105
- data/lib/mod_spox/Database.rb +33 -13
- data/lib/mod_spox/Helpers.rb +67 -38
- data/lib/mod_spox/Loader.rb +25 -5
- data/lib/mod_spox/Logger.rb +20 -62
- data/lib/mod_spox/MessageFactory.rb +34 -25
- data/lib/mod_spox/Monitors.rb +5 -0
- data/lib/mod_spox/Pipeline.rb +40 -51
- data/lib/mod_spox/Plugin.rb +40 -9
- data/lib/mod_spox/PluginManager.rb +46 -38
- data/lib/mod_spox/Pool.rb +129 -143
- data/lib/mod_spox/Socket.rb +41 -50
- data/lib/mod_spox/Sockets.rb +211 -0
- data/lib/mod_spox/Timer.rb +86 -69
- data/lib/mod_spox/handlers/BadNick.rb +1 -1
- data/lib/mod_spox/handlers/Created.rb +1 -1
- data/lib/mod_spox/handlers/Handler.rb +9 -0
- data/lib/mod_spox/handlers/Invite.rb +1 -1
- data/lib/mod_spox/handlers/Join.rb +2 -2
- data/lib/mod_spox/handlers/Kick.rb +1 -1
- data/lib/mod_spox/handlers/LuserChannels.rb +1 -1
- data/lib/mod_spox/handlers/LuserOp.rb +1 -1
- data/lib/mod_spox/handlers/LuserUnknown.rb +1 -1
- data/lib/mod_spox/handlers/Mode.rb +2 -2
- data/lib/mod_spox/handlers/MyInfo.rb +1 -1
- data/lib/mod_spox/handlers/Names.rb +1 -1
- data/lib/mod_spox/handlers/Nick.rb +20 -3
- data/lib/mod_spox/handlers/NickInUse.rb +3 -3
- data/lib/mod_spox/handlers/Notice.rb +5 -15
- data/lib/mod_spox/handlers/Part.rb +1 -1
- data/lib/mod_spox/handlers/Ping.rb +1 -1
- data/lib/mod_spox/handlers/Pong.rb +1 -1
- data/lib/mod_spox/handlers/Privmsg.rb +2 -2
- data/lib/mod_spox/handlers/Quit.rb +1 -1
- data/lib/mod_spox/handlers/Topic.rb +2 -1
- data/lib/mod_spox/handlers/Welcome.rb +3 -3
- data/lib/mod_spox/handlers/Who.rb +9 -7
- data/lib/mod_spox/handlers/Whois.rb +29 -16
- data/lib/mod_spox/handlers/YourHost.rb +1 -1
- data/lib/mod_spox/messages/incoming/Privmsg.rb +38 -19
- data/lib/mod_spox/messages/internal/DCCListener.rb +12 -0
- data/lib/mod_spox/messages/internal/DCCRequest.rb +12 -0
- data/lib/mod_spox/messages/internal/DCCSocket.rb +19 -0
- data/lib/mod_spox/messages/internal/StatusRequest.rb +2 -1
- data/lib/mod_spox/messages/outgoing/Privmsg.rb +21 -5
- data/lib/mod_spox/migrations/001_initialize_models.rb +115 -0
- data/lib/mod_spox/models/Auth.rb +24 -16
- data/lib/mod_spox/models/AuthGroup.rb +4 -3
- data/lib/mod_spox/models/Channel.rb +20 -12
- data/lib/mod_spox/models/ChannelMode.rb +2 -2
- data/lib/mod_spox/models/Config.rb +11 -3
- data/lib/mod_spox/models/Group.rb +6 -1
- data/lib/mod_spox/models/Nick.rb +93 -33
- data/lib/mod_spox/models/NickChannel.rb +8 -6
- data/lib/mod_spox/models/NickGroup.rb +16 -0
- data/lib/mod_spox/models/NickMode.rb +3 -3
- data/lib/mod_spox/models/Server.rb +6 -2
- data/lib/mod_spox/models/Setting.rb +12 -6
- data/lib/mod_spox/models/Signature.rb +7 -13
- data/lib/mod_spox/models/Trigger.rb +1 -1
- metadata +125 -100
@@ -11,26 +11,7 @@ module ModSpox
|
|
11
11
|
def initialize
|
12
12
|
@echo = nil
|
13
13
|
@config = Array.new
|
14
|
-
@
|
15
|
-
@config << {:id => :db_password, :string => 'Database password: ', :regex => '.*', :default => nil, :value => nil, :echo => false}
|
16
|
-
@config << {:id => :db_host, :string => 'Database host: ', :regex => '.+', :default => 'localhost', :value => nil, :echo => true}
|
17
|
-
@config << {:id => :db_database, :string => 'Database name: ', :regex => '.+', :default => 'mod_spox', :value => nil, :echo => true}
|
18
|
-
@config << {:id => :db_adapter, :string => 'Database type (mysql|pgsql|sqlite): ', :regex => '(mysql|pgsql|sqlite)', :default => nil, :value => nil, :echo => true}
|
19
|
-
@config << {:id => :irc_server, :string => 'IRC Server: ', :regex => '.+', :default => nil, :value => nil, :echo => true}
|
20
|
-
@config << {:id => :irc_port, :string => 'IRC Port: ', :regex => '[0-9]+', :default => nil, :value => nil, :echo => true}
|
21
|
-
@config << {:id => :reconnect_wait, :string => 'Reconnect wait time: ', :regex => '[0-9]+', :default => '10', :value => nil, :echo => true}
|
22
|
-
@config << {:id => :bot_nick, :string => 'IRC Nick: ', :regex => '[a-zA-Z].*', :default => 'mod_spox', :value => nil, :echo => true}
|
23
|
-
@config << {:id => :bot_password, :string => 'IRC Nick Password: ', :regex => '.*', :default => nil, :value => nil, :echo => false}
|
24
|
-
@config << {:id => :bot_username, :string => 'IRC Username: ', :regex => '.+', :default => 'mod_spox', :value => nil, :echo => true}
|
25
|
-
@config << {:id => :bot_realname, :string => 'IRC Real Name: ', :regex => '.+', :default => 'mod_spox IRC bot', :value => nil, :echo => true}
|
26
|
-
@config << {:id => :socket_burst, :string => 'Socket burst rate (lines): ', :regex => '[0-9]+', :default => '3', :value => nil, :echo => true}
|
27
|
-
@config << {:id => :socket_burst_in, :string => 'Socket burst time: ', :regex => '[0-9]+', :default => '2', :value => nil, :echo => true}
|
28
|
-
@config << {:id => :socket_burst_delay, :string => 'Socket burst delay: ', :regex => '[0-9]+', :default => '2', :value => nil, :echo => true}
|
29
|
-
@config << {:id => :admin_nick, :string => 'Administrator nick: ', :regex => '[a-zA-Z].*', :default => nil, :value => nil, :echo => true}
|
30
|
-
@config << {:id => :admin_password, :string => 'Administrator password: ', :regex => '.+', :default => nil, :value => nil, :echo => false}
|
31
|
-
@config << {:id => :plugin_directory, :string => 'Plugin directory (bot must have write priviliges): ', :regex => '.+', :default => nil, :echo => true}
|
32
|
-
@config << {:id => :trigger, :string => 'Trigger character for plugins: ', :regex => '.', :default => '!', :value => nil, :echo => true}
|
33
|
-
@config << {:id => :memcache, :string => 'Use memcache (EXPERIMENTAL): ', :regex => '(yes|no)', :default => 'no', :value => nil, :echo => true}
|
14
|
+
@config_db = Hash.new
|
34
15
|
@stuck_visible = true
|
35
16
|
begin
|
36
17
|
require 'termios'
|
@@ -41,52 +22,109 @@ module ModSpox
|
|
41
22
|
|
42
23
|
# Run the configuration wizard
|
43
24
|
def run
|
25
|
+
config = {}
|
44
26
|
puts "*********************************"
|
45
27
|
puts "* mod_spox Configuration Wizard *"
|
46
28
|
puts "*********************************"
|
47
29
|
puts ""
|
48
|
-
|
49
|
-
|
50
|
-
|
30
|
+
config[:irc_server] = get_input('IRC Server: ', '.+', nil)
|
31
|
+
config[:irc_port] = get_input('IRC Port: ', '\d+', '6667')
|
32
|
+
config[:reconnect_wait] = get_input('Reconnect wait time: ', '\d+', 10)
|
33
|
+
config[:bot_nick] = get_input('IRC Nick: ', '[a-zA-Z].*', 'mod_spox')
|
34
|
+
config[:bot_password] = get_input('IRC Nick Password (for nickserv): ', '.*', nil)
|
35
|
+
config[:bot_username] = get_input('IRC Username: ', '.+', 'mod_spox')
|
36
|
+
config[:bot_realname] = get_input('IRC Real Name: ', '.+', 'mod_spox IRC bot')
|
37
|
+
config[:socket_burst] = get_input('Socket burst rate (lines): ', '\d+', '3')
|
38
|
+
config[:socket_burst_in] = get_input('Socket burst time: ', '\d+', '2')
|
39
|
+
config[:socket_burst_delay] = get_input('Socket burst delay: ', '\d+', '2')
|
40
|
+
config[:admin_nick] = get_input('Administator nick: ', '[a-zA-Z].*', nil)
|
41
|
+
config[:admin_password] = get_input('Administrator password: ', '.+', nil)
|
42
|
+
config[:plugin_directory] = get_input('Plugin temp data driectory (bot needs write permission): ', '.+', '/tmp')
|
43
|
+
config[:trigger] = get_input('Default trigger: ', '.+', '!')
|
44
|
+
config[:memcache] = get_input('Use memcache (EXPERIMENTAL): ', '(yes|no)', 'no')
|
45
|
+
valid_connection = false
|
46
|
+
until valid_connection do
|
47
|
+
config[:db_adapter] = get_input('Database type (pgsql): ', '(pgsql)', 'pgsql')
|
48
|
+
unless(config[:db_adapter] == 'sqlite')
|
49
|
+
config[:db_username] = get_input('Database username: ', '.+', 'mod_spox')
|
50
|
+
config[:db_password] = get_input('Database password: ', '.*', nil)
|
51
|
+
config[:db_host] = get_input('Database host: ', '.*', '127.0.0.1')
|
52
|
+
config[:db_database] = get_input('Database name: ', '.+', 'mod_spox')
|
53
|
+
end
|
54
|
+
begin
|
55
|
+
print 'Testing database connection... '
|
56
|
+
config[:db_adapter] == 'sqlite' ? test_connection(config[:db_adapter]) : test_connection(config[:db_adapter], config[:db_username], config[:db_password], config[:db_host], config[:db_database])
|
57
|
+
puts 'OK'
|
58
|
+
valid_connection = true
|
59
|
+
rescue Sequel::DatabaseError, URI::InvalidURIError => boom
|
60
|
+
puts 'Failed'
|
61
|
+
puts 'Error: Connection to database failed'
|
62
|
+
puts "Info: #{boom}"
|
63
|
+
rescue Object => boom
|
64
|
+
puts 'Failed'
|
65
|
+
puts 'Error: Unexpected error encountered.'
|
66
|
+
puts "Info: #{boom.class} #{boom}\n#{boom.backtrace.join("\n")}"
|
67
|
+
exit 1
|
68
|
+
ensure
|
69
|
+
$stdout.flush
|
70
|
+
end
|
71
|
+
end
|
51
72
|
print "Storing configuration values... "
|
52
|
-
|
53
|
-
|
54
|
-
|
73
|
+
begin
|
74
|
+
save_configuration(config)
|
75
|
+
puts 'OK'
|
76
|
+
puts 'mod_spox is now configured and ready for use'
|
77
|
+
rescue Object => boom
|
78
|
+
puts 'Failed'
|
79
|
+
puts "Error: #{boom}\n#{boom.backtrace.join("\n")}"
|
80
|
+
puts 'Please try running the configuration again'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def update
|
85
|
+
run
|
55
86
|
end
|
56
87
|
|
57
88
|
private
|
58
89
|
|
59
|
-
def
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
90
|
+
def test_connection(type, username=nil, password=nil, host=nil, name=nil)
|
91
|
+
case type
|
92
|
+
# when 'mysql'
|
93
|
+
# c = Sequel.mysql(name, :user => username, :password => password, :host => host)
|
94
|
+
# c.test_connection
|
95
|
+
when 'pgsql'
|
96
|
+
c = Sequel.connect("#{$JDBC ? 'jdbc:' : ''}postgres://#{username}:#{password}@#{host}/#{name}")
|
97
|
+
c.test_connection
|
98
|
+
when 'sqlite'
|
99
|
+
return true
|
100
|
+
end
|
66
101
|
end
|
67
102
|
|
68
103
|
# Save our configuration values
|
69
|
-
def save_configuration
|
104
|
+
def save_configuration(uconfig)
|
70
105
|
config = BaseConfig.new(BotConfig[:userconfigpath])
|
71
|
-
|
72
|
-
config[
|
73
|
-
|
106
|
+
uconfig.each_pair do |key,value|
|
107
|
+
config[key] = value if key.to_s =~ /^(db|memcache)/
|
108
|
+
end
|
74
109
|
config.write_configuration
|
75
110
|
initialize_bot
|
76
111
|
require 'mod_spox/models/Models'
|
77
112
|
require 'mod_spox/Helpers'
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
113
|
+
Sequel::Migrator.apply(Database.db, BotConfig[:libpath] + '/migrations')
|
114
|
+
uconfig.each_pair do |key,value|
|
115
|
+
unless key.to_s =~ /^(db|irc|admin|trigger)/
|
116
|
+
m = Models::Config.find_or_create(:name => key.to_s)
|
117
|
+
m.value = value
|
118
|
+
m.save
|
119
|
+
end
|
120
|
+
end
|
121
|
+
s = Models::Server.find_or_create(:host => uconfig[:irc_server], :port => uconfig[:irc_port])
|
122
|
+
n = Models::Nick.find_or_create(:nick => uconfig[:admin_nick])
|
85
123
|
a = Models::Auth.find_or_create(:nick_id => n.pk)
|
86
124
|
a.group = Models::Group.find_or_create(:name => 'admin')
|
87
|
-
a.password =
|
125
|
+
a.password = uconfig[:admin_password]
|
88
126
|
a.save
|
89
|
-
t = Models::Trigger.find_or_create(:trigger =>
|
127
|
+
t = Models::Trigger.find_or_create(:trigger => uconfig[:trigger])
|
90
128
|
t.update_with_params(:active => true)
|
91
129
|
t.save
|
92
130
|
end
|
@@ -106,85 +144,36 @@ module ModSpox
|
|
106
144
|
# default:: default value if response is empty
|
107
145
|
# echo:: echo user's input
|
108
146
|
# Reads users input
|
109
|
-
def read_input(pattern=nil, default=nil
|
110
|
-
input_echo(echo)
|
147
|
+
def read_input(pattern=nil, default=nil)
|
148
|
+
#input_echo(echo)
|
111
149
|
response = $stdin.readline
|
112
150
|
response.strip!
|
113
151
|
set = response.length > 0
|
114
152
|
unless(pattern.nil?)
|
115
153
|
response = nil unless response =~ /^#{pattern}$/
|
116
154
|
end
|
117
|
-
if(default &&
|
155
|
+
if(default && !set)
|
118
156
|
response = default
|
119
157
|
end
|
120
|
-
input_echo(true) unless echo
|
121
|
-
puts "" unless echo
|
158
|
+
#input_echo(true) unless echo
|
159
|
+
#puts "" unless echo
|
122
160
|
return response
|
123
161
|
end
|
124
162
|
|
125
|
-
# output::
|
126
|
-
# regex:: pattern user input must match (^ and $ not
|
163
|
+
# output:: to send before user input
|
164
|
+
# regex:: pattern user input must match (^ and $ not needed. applied automatically)
|
127
165
|
# echo:: echo user's input
|
128
166
|
# default:: default value if no value is entered
|
129
|
-
def get_input(output, regex,
|
167
|
+
def get_input(output, regex, default=nil)
|
130
168
|
response = nil
|
131
169
|
until(response) do
|
132
170
|
print output
|
133
171
|
print "[#{default}]: " unless default.nil?
|
134
|
-
|
172
|
+
$stdout.flush
|
173
|
+
response = read_input(regex, default)
|
135
174
|
end
|
136
175
|
return response
|
137
176
|
end
|
138
|
-
|
139
|
-
def create_databases
|
140
|
-
case Database.type
|
141
|
-
when :mysql
|
142
|
-
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)"
|
143
|
-
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)"
|
144
|
-
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)"
|
145
|
-
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)"
|
146
|
-
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))"
|
147
|
-
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))"
|
148
|
-
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))"
|
149
|
-
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))"
|
150
|
-
Database.db << "CREATE TABLE IF NOT EXISTS settings (id int not null auto_increment primary key, name varchar(255) not null unique, value text)"
|
151
|
-
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 varchar(255), requirement enum('public', 'private', 'both') default 'both' not null)"
|
152
|
-
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)"
|
153
|
-
Database.db << "CREATE TABLE IF NOT EXISTS groups (id int not null auto_increment primary key, name varchar(255) not null unique)"
|
154
|
-
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))"
|
155
|
-
when :pgsql
|
156
|
-
Database.db << "CREATE TABLE nicks (id serial not null 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 integer, visible boolean not null default false, away boolean not null default false, botnick boolean not null default false)"
|
157
|
-
Database.db << "CREATE INDEX nick_nicks_lower on nicks (lower(nick))"
|
158
|
-
Database.db << "CREATE TABLE channels (id serial not null primary key, name varchar(255) unique 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)"
|
159
|
-
Database.db << "CREATE TABLE auths (id serial not null primary key, password varchar(255), services boolean not null default false, mask varchar(255) unique, authed boolean not null default false, nick_id integer unique references nicks)"
|
160
|
-
Database.db << "CREATE TABLE groups (id serial not null primary key, name varchar(255) unique not null)"
|
161
|
-
Database.db << "CREATE TABLE channel_modes (id serial not null primary key, mode varchar(255) not null, channel_id integer unique not null references channels)"
|
162
|
-
Database.db << "CREATE TABLE configs (id serial not null primary key, name varchar(255) unique not null, value text)"
|
163
|
-
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))"
|
164
|
-
Database.db << "CREATE TABLE nick_modes (id serial not null primary key, mode varchar(255) not null, nick_id integer not null references nicks, channel_id integer references channels, unique (nick_id, channel_id))"
|
165
|
-
Database.db << "CREATE TABLE servers (id serial not null primary key, host varchar(255) not null, port integer not null default 6667, priority integer not null default 0, connected boolean not null default false, unique (host, port))"
|
166
|
-
Database.db << "CREATE TABLE signatures (id serial not null primary key, signature varchar(255) not null, params varchar(255), group_id integer default null references groups, method varchar(255) not null, plugin varchar(255) not null, description varchar(255), requirement varchar(255) default 'both' not null)"
|
167
|
-
Database.db << "CREATE TABLE settings (id serial not null primary key, name varchar(255) unique not null, value text)"
|
168
|
-
Database.db << "CREATE TABLE triggers (id serial not null primary key, trigger varchar(255) unique not null, active boolean not null default false)"
|
169
|
-
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))"
|
170
|
-
when :sqlite
|
171
|
-
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')"
|
172
|
-
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')"
|
173
|
-
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)"
|
174
|
-
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)"
|
175
|
-
Database.db << "CREATE TABLE if not exists configs (id integer PRIMARY KEY AUTOINCREMENT, name string UNIQUE NOT NULL, value string)"
|
176
|
-
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))"
|
177
|
-
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)"
|
178
|
-
Database.db << "CREATE UNIQUE INDEX if not exists nick_modes_nick_id_channel_id_index ON nick_modes (nick_id, channel_id)"
|
179
|
-
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')"
|
180
|
-
Database.db << "CREATE UNIQUE INDEX if not exists servers_host_port_index on servers (host, port)"
|
181
|
-
Database.db << "CREATE TABLE if not exists settings (id integer PRIMARY KEY AUTOINCREMENT, name string UNIQUE NOT NULL, value text)"
|
182
|
-
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 varchar(255), requirement varchar(255) not null default 'both')"
|
183
|
-
Database.db << "CREATE TABLE if not exists triggers (id integer PRIMARY KEY AUTOINCREMENT, trigger string UNIQUE NOT NULL, active boolean NOT NULL DEFAULT 'f')"
|
184
|
-
Database.db << "CREATE TABLE if not exists groups (id integer PRIMARY KEY AUTOINCREMENT, name string UNIQUE NOT NULL COLLATE NOCASE)"
|
185
|
-
Database.db << "CREATE TABLE if not exists auth_groups(auth_id integer REFERENCES auths, group_id integer REFERENCES groups)"
|
186
|
-
end
|
187
|
-
end
|
188
177
|
|
189
178
|
end
|
190
179
|
|
data/lib/mod_spox/Database.rb
CHANGED
@@ -1,34 +1,54 @@
|
|
1
1
|
module ModSpox
|
2
2
|
|
3
3
|
class Database
|
4
|
-
|
5
|
-
def
|
4
|
+
|
5
|
+
def Database.db=(database)
|
6
6
|
@@db = nil
|
7
7
|
@@db = database
|
8
8
|
end
|
9
|
-
|
10
|
-
def
|
9
|
+
|
10
|
+
def Database.type=(type)
|
11
11
|
@@type = nil
|
12
12
|
@@type = type
|
13
13
|
end
|
14
|
-
|
15
|
-
def
|
14
|
+
|
15
|
+
def Database.cache=(cache)
|
16
16
|
@@cache = nil
|
17
17
|
@@cache = cache
|
18
18
|
end
|
19
|
-
|
20
|
-
def
|
19
|
+
|
20
|
+
def Database.cache
|
21
21
|
return Database.class_variable_defined?(:@@cache) ? @@cache : nil
|
22
22
|
end
|
23
|
-
|
24
|
-
def
|
23
|
+
|
24
|
+
def Database.type
|
25
25
|
return Database.class_variable_defined?(:@@type) ? @@type : nil
|
26
26
|
end
|
27
|
-
|
28
|
-
def
|
27
|
+
|
28
|
+
def Database.db
|
29
29
|
return Database.class_variable_defined?(:@@db) ? @@db : nil
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
|
+
def Database.reset_connections
|
33
|
+
Logger.warn('Resetting database connections. Any active connections are being closed.')
|
34
|
+
Database.db.pool.allocated.each_pair do |thread, connection|
|
35
|
+
thread.kill
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def Database.reconnect
|
40
|
+
begin
|
41
|
+
@@db.test_connection
|
42
|
+
Logger.warn('Database connection appears to be active. Closing.')
|
43
|
+
@@db.disconnect
|
44
|
+
rescue Object => boom
|
45
|
+
Logger.warn('Database connection does not appear to be active.')
|
46
|
+
ensure
|
47
|
+
Logger.warn('Reconnecting to database.')
|
48
|
+
ModSpox.setup_adapter
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
32
52
|
end
|
33
53
|
|
34
54
|
end
|
data/lib/mod_spox/Helpers.rb
CHANGED
@@ -11,21 +11,45 @@ module ModSpox
|
|
11
11
|
# secs:: number of seconds
|
12
12
|
# Converts seconds into a human readable string
|
13
13
|
def Helpers.format_seconds(secs)
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
14
|
+
arg = {:year => 29030400,
|
15
|
+
:month => 2419200,
|
16
|
+
:week => 604800,
|
17
|
+
:day => 86400,
|
18
|
+
:hour => 3600,
|
19
|
+
:minute => 60,
|
20
|
+
:second => 1}
|
21
|
+
res = ''
|
22
|
+
arg.each_pair do |k,v|
|
23
|
+
z = (secs / v).to_i
|
24
|
+
next unless z > 0
|
25
|
+
res += " #{z} #{k}#{z == 1 ? '':'s'}"
|
26
|
+
secs = secs % v
|
25
27
|
end
|
26
|
-
|
28
|
+
res = '0 seconds' if res.empty?
|
29
|
+
return res.strip
|
30
|
+
end
|
31
|
+
|
32
|
+
# bytes:: number of bytes
|
33
|
+
# Converts bytes into easy human readable form
|
34
|
+
# O(1) version by Ryan "pizza_milkshake" Flynn
|
35
|
+
Suff = [
|
36
|
+
"", # 1000^0
|
37
|
+
"Kilo", # 1000^1
|
38
|
+
"Mega", # 1000^2
|
39
|
+
"Giga", # 1000^3
|
40
|
+
"Tera", # 1000^4
|
41
|
+
"Peta", # 1000^5
|
42
|
+
"Exa", # 1000^6
|
43
|
+
"Zetta", # 1000^7
|
44
|
+
"Yotta" # 1000^8
|
45
|
+
]
|
46
|
+
def Helpers.format_size(bytes)
|
47
|
+
mag = (Math.log(bytes) / Math.log(1000)).floor
|
48
|
+
mag = [ Suff.length - 1, mag ].min
|
49
|
+
val = bytes.to_f / (1000 ** mag)
|
50
|
+
"%7.3f %sbyte%s" % [ val, Suff[mag], val == 1 ? "" : "s" ]
|
27
51
|
end
|
28
|
-
|
52
|
+
|
29
53
|
# command:: command to execute
|
30
54
|
# timeout:: maximum number of seconds to run
|
31
55
|
# Execute a system command (use with care)
|
@@ -35,32 +59,29 @@ module ModSpox
|
|
35
59
|
result = `#{command}`
|
36
60
|
end
|
37
61
|
rescue Timeout::Error => boom
|
38
|
-
Logger.
|
62
|
+
Logger.warn("Command execution exceeded allowed time (command: #{command} | timeout: #{timeout})")
|
63
|
+
raise boom
|
39
64
|
rescue Object => boom
|
40
|
-
Logger.
|
65
|
+
Logger.warn("Command generated an exception (command: #{command} | error: #{boom})")
|
66
|
+
raise boom
|
41
67
|
end
|
42
68
|
end
|
43
|
-
|
69
|
+
|
44
70
|
# url:: URL to shorten
|
45
71
|
# Gets a tinyurl for given URL
|
46
72
|
def Helpers.tinyurl(url)
|
47
73
|
begin
|
48
74
|
connection = Net::HTTP.new('tinyurl.com', 80)
|
49
|
-
resp, data = connection.get("/create.php?url=#{url}"
|
75
|
+
resp, data = connection.get("/api-create.php?url=#{url}")
|
50
76
|
if(resp.code !~ /^200$/)
|
51
77
|
raise "Failed to make the URL small."
|
52
78
|
end
|
53
|
-
data.
|
54
|
-
if(data =~ /<input type=hidden name=tinyurl value="(.+?)">/)
|
55
|
-
return $1
|
56
|
-
else
|
57
|
-
raise "Failed to locate the small URL."
|
58
|
-
end
|
79
|
+
return data.strip
|
59
80
|
rescue Object => boom
|
60
81
|
raise "Failed to process URL. #{boom}"
|
61
82
|
end
|
62
83
|
end
|
63
|
-
|
84
|
+
|
64
85
|
# string:: name of target
|
65
86
|
# Locates target model and returns it. String can be a nick
|
66
87
|
# or channel name. If the string given does not match the required
|
@@ -68,55 +89,63 @@ module ModSpox
|
|
68
89
|
def Helpers.find_model(string, create=true)
|
69
90
|
Helpers.initialize_caches
|
70
91
|
if(string =~ /^[A-Za-z\|\\\{\}\[\]\^\`~\_\-]+[A-Za-z0-9\|\\\{\}\[\]\^\`~\_\-]*$/)
|
71
|
-
Logger.log("Model: #{string} -> Nick", 30)
|
72
92
|
nick = nil
|
73
93
|
if(@@nick_cache.has_key?(string.downcase.to_sym))
|
74
94
|
begin
|
75
95
|
nick = Models::Nick[@@nick_cache[string.downcase.to_sym]]
|
76
|
-
Logger.log("Handler cache hit for nick: #{string}", 30)
|
77
96
|
if(nick.nick.downcase != string.downcase)
|
78
|
-
Logger.
|
97
|
+
Logger.warn("Nick returned from cache invalid. Expecting #{string} but got #{nick.nick}")
|
79
98
|
nick = nil
|
80
99
|
end
|
81
100
|
rescue Object => boom
|
82
|
-
Logger.
|
101
|
+
Logger.info("Failed to grab cached nick: #{boom}")
|
83
102
|
end
|
84
103
|
end
|
85
104
|
unless(nick)
|
86
|
-
|
105
|
+
begin
|
106
|
+
nick = Models::Nick.locate(string, create)
|
107
|
+
if(nick.nil?)
|
108
|
+
Database.reconnect
|
109
|
+
return string
|
110
|
+
end
|
111
|
+
rescue Object => boom
|
112
|
+
Logger.warn("Caught an error. Assuming the database barfed: #{boom}")
|
113
|
+
Database.reconnect
|
114
|
+
end
|
87
115
|
@@nick_cache[string.downcase.to_sym] = nick.pk if nick.is_a?(Models::Nick)
|
88
|
-
Logger.
|
116
|
+
Logger.info('Nick was retrieved from database')
|
89
117
|
end
|
90
118
|
return nick
|
91
119
|
elsif(string =~ /^[&#+!]/)
|
92
|
-
Logger.log("Model: #{string} -> Channel", 30)
|
93
120
|
if(@@channel_cache.has_key?(string.downcase.to_sym))
|
94
121
|
begin
|
95
122
|
channel = Models::Channel[@@channel_cache[string.downcase.to_sym]]
|
96
|
-
Logger.log("Handler cache hit for channel: #{string}", 30)
|
97
123
|
if(string.downcase != channel.name.downcase)
|
98
|
-
Logger.
|
124
|
+
Logger.warn("Channel returned from cache invalid. Expecting #{string} but got #{channel.name}")
|
99
125
|
channel = nil
|
100
126
|
end
|
101
127
|
rescue Object => boom
|
102
|
-
Logger.
|
128
|
+
Logger.info("Failed to grab cached channel: #{boom}")
|
103
129
|
end
|
104
130
|
end
|
105
131
|
unless(channel)
|
106
132
|
channel = Models::Channel.locate(string, create)
|
133
|
+
if(channel.nil?)
|
134
|
+
Database.reconnect
|
135
|
+
return string
|
136
|
+
end
|
107
137
|
@@channel_cache[string.downcase.to_sym] = channel.pk if channel.is_a?(Models::Channel)
|
108
|
-
Logger.
|
138
|
+
Logger.info('Channel was retrieved from database')
|
109
139
|
end
|
110
140
|
return channel
|
111
141
|
elsif(model = Models::Server.filter(:host => string, :connected => true).first)
|
112
|
-
Logger.log("Model: #{string} -> Server", 30)
|
113
142
|
return model
|
114
143
|
else
|
115
|
-
Logger.
|
144
|
+
Logger.warn("Failed to match string to model: #{string} -> No match")
|
116
145
|
return string
|
117
146
|
end
|
118
147
|
end
|
119
|
-
|
148
|
+
|
120
149
|
def Helpers.initialize_caches
|
121
150
|
@@nick_cache = Cache.new(20) unless Helpers.class_variable_defined?(:@@nick_cache)
|
122
151
|
@@channel_cache = Cache.new(5) unless Helpers.class_variable_defined?(:@@channel_cache)
|
data/lib/mod_spox/Loader.rb
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
['mod_spox/Exceptions',
|
2
2
|
'mod_spox/BotConfig',
|
3
3
|
'mod_spox/BaseConfig',
|
4
|
-
'mod_spox/Database'
|
4
|
+
'mod_spox/Database',
|
5
|
+
'logger'].each{|f|require f}
|
5
6
|
|
6
7
|
module ModSpox
|
7
8
|
|
8
9
|
# Loads all files needed by the bot
|
9
10
|
def initialize_bot
|
10
11
|
setup_adapter
|
12
|
+
check_upgrade
|
11
13
|
end
|
12
14
|
|
13
15
|
# Setup the DataMapper adapter
|
@@ -27,15 +29,33 @@ module ModSpox
|
|
27
29
|
case config[:db_adapter]
|
28
30
|
when 'mysql'
|
29
31
|
Database.db = Sequel.mysql(config[:db_database], :user => config[:db_username],
|
30
|
-
:password => config[:db_password], :host => config[:db_host])
|
32
|
+
:password => config[:db_password], :host => config[:db_host], :max_connections => 20)
|
31
33
|
Database.type = :mysql
|
32
34
|
when 'pgsql'
|
33
|
-
Database.db = Sequel.
|
35
|
+
Database.db = Sequel.connect("#{$JDBC ? 'jdbc:' : ''}postgres://#{config[:db_username]}:#{config[:db_password]}@#{config[:db_host]}/#{config[:db_database]}")
|
34
36
|
Database.type = :pgsql
|
35
37
|
when 'sqlite'
|
36
|
-
Database.db = Sequel.sqlite
|
38
|
+
Database.db = Sequel.sqlite("#{BotConfig[:userpath]}/mod_spox.db")
|
37
39
|
Database.type = :sqlite
|
38
40
|
end
|
39
41
|
end
|
40
|
-
|
42
|
+
|
43
|
+
# check if the bot has been upgraded
|
44
|
+
def check_upgrade
|
45
|
+
config = BaseConfig.new(BotConfig[:userconfigpath])
|
46
|
+
config[:plugin_upgrade] = 'no'
|
47
|
+
begin
|
48
|
+
do_upgrade(config) if config[:last_version] != $BOTVERSION
|
49
|
+
rescue Exceptions::UnknownKey => boom
|
50
|
+
do_upgrade(config)
|
51
|
+
end
|
52
|
+
config[:last_version] = $BOTVERSION
|
53
|
+
end
|
54
|
+
|
55
|
+
# perform upgrade tasks
|
56
|
+
def do_upgrade(config)
|
57
|
+
Sequel::Migrator.apply(Database.db, BotConfig[:libpath] + '/migrations')
|
58
|
+
config[:plugin_upgrade] = 'yes'
|
59
|
+
end
|
60
|
+
|
41
61
|
end
|