mod_spox 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (191) hide show
  1. data/CHANGELOG +2 -0
  2. data/INSTALL +9 -0
  3. data/README +33 -0
  4. data/bin/mod_spox +60 -0
  5. data/data/mod_spox/extras/Tester.rb +14 -0
  6. data/data/mod_spox/plugins/Authenticator.rb +245 -0
  7. data/data/mod_spox/plugins/BotNick.rb +18 -0
  8. data/data/mod_spox/plugins/Initializer.rb +41 -0
  9. data/data/mod_spox/plugins/Joiner.rb +13 -0
  10. data/data/mod_spox/plugins/Parter.rb +22 -0
  11. data/data/mod_spox/plugins/PluginLoader.rb +136 -0
  12. data/data/mod_spox/plugins/Ponger.rb +14 -0
  13. data/data/mod_spox/plugins/Quitter.rb +14 -0
  14. data/lib/mod_spox/Action.rb +73 -0
  15. data/lib/mod_spox/BaseConfig.rb +48 -0
  16. data/lib/mod_spox/Bot.rb +472 -0
  17. data/lib/mod_spox/BotConfig.rb +54 -0
  18. data/lib/mod_spox/ConfigurationWizard.rb +178 -0
  19. data/lib/mod_spox/Database.rb +25 -0
  20. data/lib/mod_spox/Exceptions.rb +35 -0
  21. data/lib/mod_spox/Helpers.rb +35 -0
  22. data/lib/mod_spox/Loader.rb +79 -0
  23. data/lib/mod_spox/Logger.rb +31 -0
  24. data/lib/mod_spox/MessageFactory.rb +73 -0
  25. data/lib/mod_spox/Monitors.rb +59 -0
  26. data/lib/mod_spox/Pipeline.rb +148 -0
  27. data/lib/mod_spox/Plugin.rb +18 -0
  28. data/lib/mod_spox/PluginManager.rb +105 -0
  29. data/lib/mod_spox/Pool.rb +50 -0
  30. data/lib/mod_spox/Socket.rb +171 -0
  31. data/lib/mod_spox/Timer.rb +138 -0
  32. data/lib/mod_spox/handlers/BadNick.rb +16 -0
  33. data/lib/mod_spox/handlers/Bounce.rb +15 -0
  34. data/lib/mod_spox/handlers/Created.rb +16 -0
  35. data/lib/mod_spox/handlers/Handler.rb +31 -0
  36. data/lib/mod_spox/handlers/Invite.rb +19 -0
  37. data/lib/mod_spox/handlers/Join.rb +30 -0
  38. data/lib/mod_spox/handlers/Kick.rb +24 -0
  39. data/lib/mod_spox/handlers/LuserChannels.rb +16 -0
  40. data/lib/mod_spox/handlers/LuserClient.rb +16 -0
  41. data/lib/mod_spox/handlers/LuserMe.rb +14 -0
  42. data/lib/mod_spox/handlers/LuserOp.rb +16 -0
  43. data/lib/mod_spox/handlers/LuserUnknown.rb +16 -0
  44. data/lib/mod_spox/handlers/Mode.rb +47 -0
  45. data/lib/mod_spox/handlers/Motd.rb +30 -0
  46. data/lib/mod_spox/handlers/MyInfo.rb +21 -0
  47. data/lib/mod_spox/handlers/Names.rb +54 -0
  48. data/lib/mod_spox/handlers/Nick.rb +24 -0
  49. data/lib/mod_spox/handlers/NickInUse.rb +16 -0
  50. data/lib/mod_spox/handlers/Notice.rb +32 -0
  51. data/lib/mod_spox/handlers/Part.rb +19 -0
  52. data/lib/mod_spox/handlers/Ping.rb +16 -0
  53. data/lib/mod_spox/handlers/Pong.rb +16 -0
  54. data/lib/mod_spox/handlers/Privmsg.rb +27 -0
  55. data/lib/mod_spox/handlers/Quit.rb +21 -0
  56. data/lib/mod_spox/handlers/Topic.rb +29 -0
  57. data/lib/mod_spox/handlers/Welcome.rb +34 -0
  58. data/lib/mod_spox/handlers/Who.rb +60 -0
  59. data/lib/mod_spox/handlers/Whois.rb +63 -0
  60. data/lib/mod_spox/handlers/YourHost.rb +17 -0
  61. data/lib/mod_spox/messages/incoming/BadNick.rb +15 -0
  62. data/lib/mod_spox/messages/incoming/Bounce.rb +17 -0
  63. data/lib/mod_spox/messages/incoming/Created.rb +14 -0
  64. data/lib/mod_spox/messages/incoming/Invite.rb +20 -0
  65. data/lib/mod_spox/messages/incoming/Join.rb +18 -0
  66. data/lib/mod_spox/messages/incoming/Kick.rb +25 -0
  67. data/lib/mod_spox/messages/incoming/LuserChannels.rb +14 -0
  68. data/lib/mod_spox/messages/incoming/LuserClient.rb +23 -0
  69. data/lib/mod_spox/messages/incoming/LuserMe.rb +17 -0
  70. data/lib/mod_spox/messages/incoming/LuserOp.rb +14 -0
  71. data/lib/mod_spox/messages/incoming/LuserUnknown.rb +14 -0
  72. data/lib/mod_spox/messages/incoming/Message.rb +22 -0
  73. data/lib/mod_spox/messages/incoming/Mode.rb +41 -0
  74. data/lib/mod_spox/messages/incoming/Motd.rb +17 -0
  75. data/lib/mod_spox/messages/incoming/MyInfo.rb +23 -0
  76. data/lib/mod_spox/messages/incoming/Names.rb +23 -0
  77. data/lib/mod_spox/messages/incoming/Nick.rb +25 -0
  78. data/lib/mod_spox/messages/incoming/NickInUse.rb +14 -0
  79. data/lib/mod_spox/messages/incoming/Notice.rb +8 -0
  80. data/lib/mod_spox/messages/incoming/Part.rb +20 -0
  81. data/lib/mod_spox/messages/incoming/Ping.rb +17 -0
  82. data/lib/mod_spox/messages/incoming/Pong.rb +8 -0
  83. data/lib/mod_spox/messages/incoming/Privmsg.rb +64 -0
  84. data/lib/mod_spox/messages/incoming/Quit.rb +17 -0
  85. data/lib/mod_spox/messages/incoming/Topic.rb +20 -0
  86. data/lib/mod_spox/messages/incoming/TopicInfo.rb +20 -0
  87. data/lib/mod_spox/messages/incoming/Welcome.rb +26 -0
  88. data/lib/mod_spox/messages/incoming/Who.rb +17 -0
  89. data/lib/mod_spox/messages/incoming/Whois.rb +47 -0
  90. data/lib/mod_spox/messages/incoming/YourHost.rb +17 -0
  91. data/lib/mod_spox/messages/internal/BotInitialized.rb +11 -0
  92. data/lib/mod_spox/messages/internal/ChangeNick.rb +15 -0
  93. data/lib/mod_spox/messages/internal/Connected.rb +20 -0
  94. data/lib/mod_spox/messages/internal/ConnectionFailed.rb +23 -0
  95. data/lib/mod_spox/messages/internal/Disconnected.rb +8 -0
  96. data/lib/mod_spox/messages/internal/Disconnecting.rb +8 -0
  97. data/lib/mod_spox/messages/internal/EstablishConnection.rb +22 -0
  98. data/lib/mod_spox/messages/internal/HaltBot.rb +8 -0
  99. data/lib/mod_spox/messages/internal/NickRequest.rb +8 -0
  100. data/lib/mod_spox/messages/internal/NickResponse.rb +14 -0
  101. data/lib/mod_spox/messages/internal/PluginLoadRequest.rb +20 -0
  102. data/lib/mod_spox/messages/internal/PluginLoadResponse.rb +16 -0
  103. data/lib/mod_spox/messages/internal/PluginModuleRequest.rb +13 -0
  104. data/lib/mod_spox/messages/internal/PluginModuleResponse.rb +17 -0
  105. data/lib/mod_spox/messages/internal/PluginReload.rb +8 -0
  106. data/lib/mod_spox/messages/internal/PluginRequest.rb +17 -0
  107. data/lib/mod_spox/messages/internal/PluginResponse.rb +20 -0
  108. data/lib/mod_spox/messages/internal/PluginUnloadRequest.rb +8 -0
  109. data/lib/mod_spox/messages/internal/PluginUnloadResponse.rb +8 -0
  110. data/lib/mod_spox/messages/internal/Request.rb +15 -0
  111. data/lib/mod_spox/messages/internal/Response.rb +15 -0
  112. data/lib/mod_spox/messages/internal/Shutdown.rb +8 -0
  113. data/lib/mod_spox/messages/internal/SignaturesUpdate.rb +8 -0
  114. data/lib/mod_spox/messages/internal/StatusRequest.rb +9 -0
  115. data/lib/mod_spox/messages/internal/StatusResponse.rb +17 -0
  116. data/lib/mod_spox/messages/internal/TimerAdd.rb +27 -0
  117. data/lib/mod_spox/messages/internal/TimerClear.rb +8 -0
  118. data/lib/mod_spox/messages/internal/TimerRemove.rb +15 -0
  119. data/lib/mod_spox/messages/internal/TimerResponse.rb +26 -0
  120. data/lib/mod_spox/messages/internal/TriggersUpdate.rb +8 -0
  121. data/lib/mod_spox/messages/outgoing/Admin.rb +15 -0
  122. data/lib/mod_spox/messages/outgoing/Away.rb +10 -0
  123. data/lib/mod_spox/messages/outgoing/ChannelMode.rb +25 -0
  124. data/lib/mod_spox/messages/outgoing/Connect.rb +24 -0
  125. data/lib/mod_spox/messages/outgoing/Die.rb +9 -0
  126. data/lib/mod_spox/messages/outgoing/Info.rb +15 -0
  127. data/lib/mod_spox/messages/outgoing/Invite.rb +19 -0
  128. data/lib/mod_spox/messages/outgoing/Ison.rb +15 -0
  129. data/lib/mod_spox/messages/outgoing/Join.rb +19 -0
  130. data/lib/mod_spox/messages/outgoing/Kick.rb +23 -0
  131. data/lib/mod_spox/messages/outgoing/Kill.rb +19 -0
  132. data/lib/mod_spox/messages/outgoing/Links.rb +19 -0
  133. data/lib/mod_spox/messages/outgoing/List.rb +19 -0
  134. data/lib/mod_spox/messages/outgoing/Lusers.rb +19 -0
  135. data/lib/mod_spox/messages/outgoing/Motd.rb +16 -0
  136. data/lib/mod_spox/messages/outgoing/Names.rb +20 -0
  137. data/lib/mod_spox/messages/outgoing/Nick.rb +16 -0
  138. data/lib/mod_spox/messages/outgoing/Notice.rb +11 -0
  139. data/lib/mod_spox/messages/outgoing/Oper.rb +19 -0
  140. data/lib/mod_spox/messages/outgoing/Part.rb +19 -0
  141. data/lib/mod_spox/messages/outgoing/Pass.rb +16 -0
  142. data/lib/mod_spox/messages/outgoing/Ping.rb +10 -0
  143. data/lib/mod_spox/messages/outgoing/Pong.rb +17 -0
  144. data/lib/mod_spox/messages/outgoing/Privmsg.rb +19 -0
  145. data/lib/mod_spox/messages/outgoing/Quit.rb +10 -0
  146. data/lib/mod_spox/messages/outgoing/Rehash.rb +9 -0
  147. data/lib/mod_spox/messages/outgoing/Restart.rb +9 -0
  148. data/lib/mod_spox/messages/outgoing/ServList.rb +19 -0
  149. data/lib/mod_spox/messages/outgoing/Simple.rb +12 -0
  150. data/lib/mod_spox/messages/outgoing/Squery.rb +19 -0
  151. data/lib/mod_spox/messages/outgoing/Squit.rb +19 -0
  152. data/lib/mod_spox/messages/outgoing/Stats.rb +18 -0
  153. data/lib/mod_spox/messages/outgoing/Summon.rb +23 -0
  154. data/lib/mod_spox/messages/outgoing/Time.rb +15 -0
  155. data/lib/mod_spox/messages/outgoing/Topic.rb +19 -0
  156. data/lib/mod_spox/messages/outgoing/Trace.rb +15 -0
  157. data/lib/mod_spox/messages/outgoing/Unaway.rb +9 -0
  158. data/lib/mod_spox/messages/outgoing/User.rb +23 -0
  159. data/lib/mod_spox/messages/outgoing/UserHost.rb +15 -0
  160. data/lib/mod_spox/messages/outgoing/UserMode.rb +19 -0
  161. data/lib/mod_spox/messages/outgoing/Users.rb +15 -0
  162. data/lib/mod_spox/messages/outgoing/Version.rb +16 -0
  163. data/lib/mod_spox/messages/outgoing/Who.rb +19 -0
  164. data/lib/mod_spox/messages/outgoing/WhoWas.rb +23 -0
  165. data/lib/mod_spox/messages/outgoing/Whois.rb +19 -0
  166. data/lib/mod_spox/migration/001_create_auths.rb +13 -0
  167. data/lib/mod_spox/migration/001_create_channel.rb +13 -0
  168. data/lib/mod_spox/migration/001_create_channel_modes.rb +13 -0
  169. data/lib/mod_spox/migration/001_create_config.rb +13 -0
  170. data/lib/mod_spox/migration/001_create_nick_channels.rb +13 -0
  171. data/lib/mod_spox/migration/001_create_nick_modes.rb +13 -0
  172. data/lib/mod_spox/migration/001_create_nicks.rb +13 -0
  173. data/lib/mod_spox/migration/001_create_servers.rb +13 -0
  174. data/lib/mod_spox/migration/001_create_settings.rb +13 -0
  175. data/lib/mod_spox/migration/001_create_signatures.rb +13 -0
  176. data/lib/mod_spox/migration/001_create_triggers.rb +13 -0
  177. data/lib/mod_spox/models/Auth.rb +79 -0
  178. data/lib/mod_spox/models/AuthGroup.rb +15 -0
  179. data/lib/mod_spox/models/Channel.rb +47 -0
  180. data/lib/mod_spox/models/ChannelMode.rb +14 -0
  181. data/lib/mod_spox/models/Config.rb +31 -0
  182. data/lib/mod_spox/models/Group.rb +13 -0
  183. data/lib/mod_spox/models/Nick.rb +110 -0
  184. data/lib/mod_spox/models/NickChannel.rb +43 -0
  185. data/lib/mod_spox/models/NickMode.rb +18 -0
  186. data/lib/mod_spox/models/Server.rb +12 -0
  187. data/lib/mod_spox/models/Setting.rb +40 -0
  188. data/lib/mod_spox/models/Signature.rb +30 -0
  189. data/lib/mod_spox/models/Trigger.rb +9 -0
  190. data/lib/mod_spox/rfc2812.rb +171 -0
  191. 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