spox-mod_spox 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (268) hide show
  1. data/CHANGELOG +174 -0
  2. data/INSTALL +15 -0
  3. data/LICENSE +674 -0
  4. data/README.rdoc +73 -0
  5. data/bin/mod_spox +112 -0
  6. data/data/mod_spox/extras/AOLSpeak.rb +257 -0
  7. data/data/mod_spox/extras/AutoKick.rb +152 -0
  8. data/data/mod_spox/extras/AutoMode.rb +122 -0
  9. data/data/mod_spox/extras/AutoRejoin.rb +37 -0
  10. data/data/mod_spox/extras/Bash.rb +55 -0
  11. data/data/mod_spox/extras/Bouncer.rb +220 -0
  12. data/data/mod_spox/extras/Bullshit.rb +19 -0
  13. data/data/mod_spox/extras/Bytes.rb +11 -0
  14. data/data/mod_spox/extras/Confess.rb +244 -0
  15. data/data/mod_spox/extras/DCC.rb +182 -0
  16. data/data/mod_spox/extras/DevWatch.rb +153 -0
  17. data/data/mod_spox/extras/DownForEveryoneOrJustMe.rb +47 -0
  18. data/data/mod_spox/extras/EightBall.rb +33 -0
  19. data/data/mod_spox/extras/FML.rb +35 -0
  20. data/data/mod_spox/extras/FloodKicker.rb +129 -0
  21. data/data/mod_spox/extras/Fortune.rb +76 -0
  22. data/data/mod_spox/extras/GoogleIt.rb +13 -0
  23. data/data/mod_spox/extras/Headers.rb +59 -0
  24. data/data/mod_spox/extras/Karma.rb +302 -0
  25. data/data/mod_spox/extras/Locator.rb +44 -0
  26. data/data/mod_spox/extras/Logger.rb +182 -0
  27. data/data/mod_spox/extras/LolSpeak.rb +21 -0
  28. data/data/mod_spox/extras/NickServ.rb +84 -0
  29. data/data/mod_spox/extras/PhpCli.rb +308 -0
  30. data/data/mod_spox/extras/PhpFuncLookup.rb +297 -0
  31. data/data/mod_spox/extras/Pinger.rb +11 -0
  32. data/data/mod_spox/extras/Quotes.rb +79 -0
  33. data/data/mod_spox/extras/RegexTracker.rb +158 -0
  34. data/data/mod_spox/extras/Roulette.rb +267 -0
  35. data/data/mod_spox/extras/RubyCli.rb +93 -0
  36. data/data/mod_spox/extras/Search.rb +49 -0
  37. data/data/mod_spox/extras/Seen.rb +150 -0
  38. data/data/mod_spox/extras/Slashdot.rb +35 -0
  39. data/data/mod_spox/extras/SlashdotHeadlineGenerator.rb +500 -0
  40. data/data/mod_spox/extras/Talk.rb +32 -0
  41. data/data/mod_spox/extras/Topten.rb +103 -0
  42. data/data/mod_spox/extras/TracTicket.rb +66 -0
  43. data/data/mod_spox/extras/Translate.rb +132 -0
  44. data/data/mod_spox/extras/Twitter.rb +458 -0
  45. data/data/mod_spox/extras/UrbanDictionary.rb +55 -0
  46. data/data/mod_spox/extras/Weather.rb +55 -0
  47. data/data/mod_spox/plugins/Authenticator.rb +289 -0
  48. data/data/mod_spox/plugins/Banner.rb +585 -0
  49. data/data/mod_spox/plugins/BotNick.rb +18 -0
  50. data/data/mod_spox/plugins/Helper.rb +49 -0
  51. data/data/mod_spox/plugins/Initializer.rb +35 -0
  52. data/data/mod_spox/plugins/Joiner.rb +23 -0
  53. data/data/mod_spox/plugins/Nicker.rb +14 -0
  54. data/data/mod_spox/plugins/Parter.rb +23 -0
  55. data/data/mod_spox/plugins/Permissions.rb +60 -0
  56. data/data/mod_spox/plugins/PluginLoader.rb +180 -0
  57. data/data/mod_spox/plugins/Ponger.rb +70 -0
  58. data/data/mod_spox/plugins/PoolConfig.rb +52 -0
  59. data/data/mod_spox/plugins/Quitter.rb +15 -0
  60. data/data/mod_spox/plugins/Servers.rb +57 -0
  61. data/data/mod_spox/plugins/Status.rb +31 -0
  62. data/data/mod_spox/plugins/Triggers.rb +85 -0
  63. data/lib/mod_spox/BaseConfig.rb +51 -0
  64. data/lib/mod_spox/Bot.rb +604 -0
  65. data/lib/mod_spox/BotConfig.rb +65 -0
  66. data/lib/mod_spox/ConfigurationWizard.rb +180 -0
  67. data/lib/mod_spox/Database.rb +51 -0
  68. data/lib/mod_spox/Exceptions.rb +84 -0
  69. data/lib/mod_spox/Helpers.rb +122 -0
  70. data/lib/mod_spox/Loader.rb +60 -0
  71. data/lib/mod_spox/Logger.rb +37 -0
  72. data/lib/mod_spox/MessageFactory.rb +112 -0
  73. data/lib/mod_spox/Pipeline.rb +207 -0
  74. data/lib/mod_spox/Plugin.rb +97 -0
  75. data/lib/mod_spox/PluginHolder.rb +22 -0
  76. data/lib/mod_spox/PluginManager.rb +257 -0
  77. data/lib/mod_spox/PriorityQueue.rb +69 -0
  78. data/lib/mod_spox/Socket.rb +201 -0
  79. data/lib/mod_spox/Sockets.rb +226 -0
  80. data/lib/mod_spox/Timer.rb +60 -0
  81. data/lib/mod_spox/Version.rb +14 -0
  82. data/lib/mod_spox/handlers/BadNick.rb +19 -0
  83. data/lib/mod_spox/handlers/Bounce.rb +24 -0
  84. data/lib/mod_spox/handlers/Created.rb +27 -0
  85. data/lib/mod_spox/handlers/Handler.rb +39 -0
  86. data/lib/mod_spox/handlers/Invite.rb +28 -0
  87. data/lib/mod_spox/handlers/Join.rb +38 -0
  88. data/lib/mod_spox/handlers/Kick.rb +36 -0
  89. data/lib/mod_spox/handlers/LuserChannels.rb +19 -0
  90. data/lib/mod_spox/handlers/LuserClient.rb +18 -0
  91. data/lib/mod_spox/handlers/LuserMe.rb +16 -0
  92. data/lib/mod_spox/handlers/LuserOp.rb +19 -0
  93. data/lib/mod_spox/handlers/LuserUnknown.rb +19 -0
  94. data/lib/mod_spox/handlers/Mode.rb +62 -0
  95. data/lib/mod_spox/handlers/Motd.rb +38 -0
  96. data/lib/mod_spox/handlers/MyInfo.rb +24 -0
  97. data/lib/mod_spox/handlers/Names.rb +86 -0
  98. data/lib/mod_spox/handlers/Nick.rb +50 -0
  99. data/lib/mod_spox/handlers/NickInUse.rb +19 -0
  100. data/lib/mod_spox/handlers/Notice.rb +35 -0
  101. data/lib/mod_spox/handlers/Part.rb +39 -0
  102. data/lib/mod_spox/handlers/Ping.rb +25 -0
  103. data/lib/mod_spox/handlers/Pong.rb +23 -0
  104. data/lib/mod_spox/handlers/Privmsg.rb +39 -0
  105. data/lib/mod_spox/handlers/Quit.rb +29 -0
  106. data/lib/mod_spox/handlers/Topic.rb +38 -0
  107. data/lib/mod_spox/handlers/Welcome.rb +30 -0
  108. data/lib/mod_spox/handlers/Who.rb +83 -0
  109. data/lib/mod_spox/handlers/Whois.rb +117 -0
  110. data/lib/mod_spox/handlers/YourHost.rb +20 -0
  111. data/lib/mod_spox/messages/Messages.rb +6 -0
  112. data/lib/mod_spox/messages/incoming/BadNick.rb +16 -0
  113. data/lib/mod_spox/messages/incoming/Bounce.rb +18 -0
  114. data/lib/mod_spox/messages/incoming/Created.rb +15 -0
  115. data/lib/mod_spox/messages/incoming/Invite.rb +21 -0
  116. data/lib/mod_spox/messages/incoming/Join.rb +19 -0
  117. data/lib/mod_spox/messages/incoming/Kick.rb +26 -0
  118. data/lib/mod_spox/messages/incoming/LuserChannels.rb +15 -0
  119. data/lib/mod_spox/messages/incoming/LuserClient.rb +24 -0
  120. data/lib/mod_spox/messages/incoming/LuserMe.rb +18 -0
  121. data/lib/mod_spox/messages/incoming/LuserOp.rb +15 -0
  122. data/lib/mod_spox/messages/incoming/LuserUnknown.rb +15 -0
  123. data/lib/mod_spox/messages/incoming/Message.rb +22 -0
  124. data/lib/mod_spox/messages/incoming/Mode.rb +42 -0
  125. data/lib/mod_spox/messages/incoming/Motd.rb +18 -0
  126. data/lib/mod_spox/messages/incoming/MyInfo.rb +24 -0
  127. data/lib/mod_spox/messages/incoming/Names.rb +24 -0
  128. data/lib/mod_spox/messages/incoming/Nick.rb +26 -0
  129. data/lib/mod_spox/messages/incoming/NickInUse.rb +15 -0
  130. data/lib/mod_spox/messages/incoming/Notice.rb +9 -0
  131. data/lib/mod_spox/messages/incoming/Part.rb +21 -0
  132. data/lib/mod_spox/messages/incoming/Ping.rb +18 -0
  133. data/lib/mod_spox/messages/incoming/Pong.rb +9 -0
  134. data/lib/mod_spox/messages/incoming/Privmsg.rb +90 -0
  135. data/lib/mod_spox/messages/incoming/Quit.rb +18 -0
  136. data/lib/mod_spox/messages/incoming/Topic.rb +21 -0
  137. data/lib/mod_spox/messages/incoming/TopicInfo.rb +21 -0
  138. data/lib/mod_spox/messages/incoming/Welcome.rb +27 -0
  139. data/lib/mod_spox/messages/incoming/Who.rb +18 -0
  140. data/lib/mod_spox/messages/incoming/Whois.rb +49 -0
  141. data/lib/mod_spox/messages/incoming/YourHost.rb +18 -0
  142. data/lib/mod_spox/messages/internal/BotInitialized.rb +11 -0
  143. data/lib/mod_spox/messages/internal/ChangeNick.rb +15 -0
  144. data/lib/mod_spox/messages/internal/Connected.rb +20 -0
  145. data/lib/mod_spox/messages/internal/ConnectionFailed.rb +23 -0
  146. data/lib/mod_spox/messages/internal/DCCListener.rb +12 -0
  147. data/lib/mod_spox/messages/internal/DCCRequest.rb +12 -0
  148. data/lib/mod_spox/messages/internal/DCCSocket.rb +19 -0
  149. data/lib/mod_spox/messages/internal/Disconnected.rb +8 -0
  150. data/lib/mod_spox/messages/internal/Disconnecting.rb +8 -0
  151. data/lib/mod_spox/messages/internal/EstablishConnection.rb +22 -0
  152. data/lib/mod_spox/messages/internal/HaltBot.rb +8 -0
  153. data/lib/mod_spox/messages/internal/NickRequest.rb +9 -0
  154. data/lib/mod_spox/messages/internal/NickResponse.rb +15 -0
  155. data/lib/mod_spox/messages/internal/PluginLoadRequest.rb +21 -0
  156. data/lib/mod_spox/messages/internal/PluginLoadResponse.rb +17 -0
  157. data/lib/mod_spox/messages/internal/PluginModuleRequest.rb +14 -0
  158. data/lib/mod_spox/messages/internal/PluginModuleResponse.rb +18 -0
  159. data/lib/mod_spox/messages/internal/PluginReload.rb +18 -0
  160. data/lib/mod_spox/messages/internal/PluginRequest.rb +18 -0
  161. data/lib/mod_spox/messages/internal/PluginResponse.rb +21 -0
  162. data/lib/mod_spox/messages/internal/PluginUnloadRequest.rb +9 -0
  163. data/lib/mod_spox/messages/internal/PluginUnloadResponse.rb +9 -0
  164. data/lib/mod_spox/messages/internal/PluginsReady.rb +10 -0
  165. data/lib/mod_spox/messages/internal/QueueSocket.rb +8 -0
  166. data/lib/mod_spox/messages/internal/Reconnect.rb +8 -0
  167. data/lib/mod_spox/messages/internal/Request.rb +15 -0
  168. data/lib/mod_spox/messages/internal/Response.rb +15 -0
  169. data/lib/mod_spox/messages/internal/Shutdown.rb +8 -0
  170. data/lib/mod_spox/messages/internal/SignaturesUpdate.rb +8 -0
  171. data/lib/mod_spox/messages/internal/StatusRequest.rb +10 -0
  172. data/lib/mod_spox/messages/internal/StatusResponse.rb +18 -0
  173. data/lib/mod_spox/messages/internal/TimerAdd.rb +36 -0
  174. data/lib/mod_spox/messages/internal/TimerClear.rb +16 -0
  175. data/lib/mod_spox/messages/internal/TimerRemove.rb +23 -0
  176. data/lib/mod_spox/messages/internal/TimerResponse.rb +34 -0
  177. data/lib/mod_spox/messages/internal/TriggersUpdate.rb +8 -0
  178. data/lib/mod_spox/messages/internal/UnqueueSocket.rb +8 -0
  179. data/lib/mod_spox/messages/outgoing/Admin.rb +15 -0
  180. data/lib/mod_spox/messages/outgoing/Away.rb +11 -0
  181. data/lib/mod_spox/messages/outgoing/ChannelMode.rb +25 -0
  182. data/lib/mod_spox/messages/outgoing/Connect.rb +24 -0
  183. data/lib/mod_spox/messages/outgoing/Die.rb +9 -0
  184. data/lib/mod_spox/messages/outgoing/Info.rb +15 -0
  185. data/lib/mod_spox/messages/outgoing/Invite.rb +19 -0
  186. data/lib/mod_spox/messages/outgoing/Ison.rb +15 -0
  187. data/lib/mod_spox/messages/outgoing/Join.rb +19 -0
  188. data/lib/mod_spox/messages/outgoing/Kick.rb +23 -0
  189. data/lib/mod_spox/messages/outgoing/Kill.rb +19 -0
  190. data/lib/mod_spox/messages/outgoing/Links.rb +19 -0
  191. data/lib/mod_spox/messages/outgoing/List.rb +19 -0
  192. data/lib/mod_spox/messages/outgoing/Lusers.rb +19 -0
  193. data/lib/mod_spox/messages/outgoing/Motd.rb +16 -0
  194. data/lib/mod_spox/messages/outgoing/Names.rb +20 -0
  195. data/lib/mod_spox/messages/outgoing/Nick.rb +16 -0
  196. data/lib/mod_spox/messages/outgoing/Notice.rb +12 -0
  197. data/lib/mod_spox/messages/outgoing/Oper.rb +19 -0
  198. data/lib/mod_spox/messages/outgoing/Part.rb +19 -0
  199. data/lib/mod_spox/messages/outgoing/Pass.rb +16 -0
  200. data/lib/mod_spox/messages/outgoing/Ping.rb +11 -0
  201. data/lib/mod_spox/messages/outgoing/Pong.rb +17 -0
  202. data/lib/mod_spox/messages/outgoing/Privmsg.rb +43 -0
  203. data/lib/mod_spox/messages/outgoing/Quit.rb +11 -0
  204. data/lib/mod_spox/messages/outgoing/Raw.rb +16 -0
  205. data/lib/mod_spox/messages/outgoing/Rehash.rb +9 -0
  206. data/lib/mod_spox/messages/outgoing/Restart.rb +9 -0
  207. data/lib/mod_spox/messages/outgoing/ServList.rb +19 -0
  208. data/lib/mod_spox/messages/outgoing/Simple.rb +12 -0
  209. data/lib/mod_spox/messages/outgoing/Squery.rb +19 -0
  210. data/lib/mod_spox/messages/outgoing/Squit.rb +19 -0
  211. data/lib/mod_spox/messages/outgoing/Stats.rb +18 -0
  212. data/lib/mod_spox/messages/outgoing/Summon.rb +23 -0
  213. data/lib/mod_spox/messages/outgoing/Time.rb +15 -0
  214. data/lib/mod_spox/messages/outgoing/Topic.rb +19 -0
  215. data/lib/mod_spox/messages/outgoing/Trace.rb +15 -0
  216. data/lib/mod_spox/messages/outgoing/Unaway.rb +9 -0
  217. data/lib/mod_spox/messages/outgoing/User.rb +23 -0
  218. data/lib/mod_spox/messages/outgoing/UserHost.rb +15 -0
  219. data/lib/mod_spox/messages/outgoing/UserMode.rb +19 -0
  220. data/lib/mod_spox/messages/outgoing/Users.rb +15 -0
  221. data/lib/mod_spox/messages/outgoing/Version.rb +16 -0
  222. data/lib/mod_spox/messages/outgoing/Who.rb +23 -0
  223. data/lib/mod_spox/messages/outgoing/WhoWas.rb +23 -0
  224. data/lib/mod_spox/messages/outgoing/Whois.rb +19 -0
  225. data/lib/mod_spox/migrations/001_initialize_models.rb +115 -0
  226. data/lib/mod_spox/migrations/002_persistent_sigs.rb +14 -0
  227. data/lib/mod_spox/migrations/003_auth_restructure.rb +31 -0
  228. data/lib/mod_spox/migrations/004_mode_index_fix.rb +18 -0
  229. data/lib/mod_spox/migrations/005_nick_mode_nopark.rb +18 -0
  230. data/lib/mod_spox/models/Auth.rb +65 -0
  231. data/lib/mod_spox/models/AuthMask.rb +13 -0
  232. data/lib/mod_spox/models/Channel.rb +89 -0
  233. data/lib/mod_spox/models/Config.rb +30 -0
  234. data/lib/mod_spox/models/Group.rb +30 -0
  235. data/lib/mod_spox/models/Models.rb +4 -0
  236. data/lib/mod_spox/models/Nick.rb +195 -0
  237. data/lib/mod_spox/models/NickMode.rb +32 -0
  238. data/lib/mod_spox/models/Server.rb +27 -0
  239. data/lib/mod_spox/models/Setting.rb +52 -0
  240. data/lib/mod_spox/models/Signature.rb +52 -0
  241. data/lib/mod_spox/models/Trigger.rb +9 -0
  242. data/lib/mod_spox/rfc2812.rb +49 -0
  243. data/populate_gemspec.rb +15 -0
  244. data/tests/BotHolder.rb +24 -0
  245. data/tests/handlers/tc_BadNick.rb +21 -0
  246. data/tests/handlers/tc_Created.rb +24 -0
  247. data/tests/handlers/tc_Invite.rb +50 -0
  248. data/tests/handlers/tc_Join.rb +33 -0
  249. data/tests/handlers/tc_Kick.rb +32 -0
  250. data/tests/handlers/tc_Mode.rb +85 -0
  251. data/tests/handlers/tc_Names.rb +35 -0
  252. data/tests/handlers/tc_Nick.rb +55 -0
  253. data/tests/handlers/tc_Part.rb +44 -0
  254. data/tests/handlers/tc_Ping.rb +40 -0
  255. data/tests/handlers/tc_Pong.rb +28 -0
  256. data/tests/handlers/tc_Privmsg.rb +85 -0
  257. data/tests/handlers/tc_Quit.rb +40 -0
  258. data/tests/handlers/tc_Who.rb +50 -0
  259. data/tests/handlers/tc_Whois.rb +61 -0
  260. data/tests/models/tc_Auth.rb +39 -0
  261. data/tests/models/tc_Channel.rb +52 -0
  262. data/tests/models/tc_Config.rb +19 -0
  263. data/tests/models/tc_Nick.rb +144 -0
  264. data/tests/models/tc_NickMode.rb +40 -0
  265. data/tests/models/tc_Setting.rb +21 -0
  266. data/tests/models/tc_Signature.rb +14 -0
  267. data/tests/run_tests.rb +6 -0
  268. metadata +362 -0
@@ -0,0 +1,180 @@
1
+ ['etc',
2
+ 'mod_spox/Database',
3
+ 'mod_spox/BotConfig',
4
+ 'mod_spox/BaseConfig'].each{|f|require f}
5
+
6
+
7
+ module ModSpox
8
+
9
+ class ConfigurationWizard
10
+
11
+ def initialize
12
+ @echo = nil
13
+ @config = Array.new
14
+ @config_db = Hash.new
15
+ @stuck_visible = true
16
+ begin
17
+ require 'termios'
18
+ @stuck_visible = false
19
+ rescue Object => boom
20
+ end
21
+ end
22
+
23
+ # Run the configuration wizard
24
+ def run
25
+ config = {}
26
+ puts "*********************************"
27
+ puts "* mod_spox Configuration Wizard *"
28
+ puts "*********************************"
29
+ puts ""
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|sqlite|mysql): ', '(pgsql|sqlite|mysql)', 'sqlite')
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}"
67
+ ensure
68
+ $stdout.flush
69
+ end
70
+ end
71
+ print "Storing configuration values... "
72
+ begin
73
+ save_configuration(config)
74
+ puts 'OK'
75
+ puts 'mod_spox is now configured and ready for use'
76
+ rescue Object => boom
77
+ puts 'Failed'
78
+ puts "Error: #{boom}"
79
+ puts 'Please try running the configuration again'
80
+ end
81
+ end
82
+
83
+ def update
84
+ run
85
+ end
86
+
87
+ private
88
+
89
+ def test_connection(type, username=nil, password=nil, host=nil, name=nil)
90
+ case type
91
+ when 'mysql'
92
+ c = Sequel.mysql(name, :user => username, :password => password, :host => host)
93
+ c.test_connection
94
+ when 'pgsql'
95
+ c = Sequel.connect("#{ModSpox.jdbc ? 'jdbc:' : ''}postgres://#{username}:#{password}@#{host}/#{name}")
96
+ c.test_connection
97
+ when 'sqlite'
98
+ return true
99
+ end
100
+ end
101
+
102
+ # Save our configuration values
103
+ def save_configuration(uconfig)
104
+ config = BaseConfig.new(BotConfig[:userconfigpath])
105
+ uconfig.each_pair do |key,value|
106
+ config[key] = value if key.to_s =~ /^(db|memcache)/
107
+ end
108
+ config.write_configuration
109
+ ModSpox.initialize_bot
110
+ require 'mod_spox/models/Models'
111
+ require 'mod_spox/Helpers'
112
+ Sequel::Migrator.apply(Database.db, BotConfig[:libpath] + '/migrations')
113
+ uconfig.each_pair do |key,value|
114
+ unless key.to_s =~ /^(db|irc|admin|trigger)/
115
+ m = Models::Config.find_or_create(:name => key.to_s)
116
+ m.value = value
117
+ m.save
118
+ end
119
+ end
120
+ s = Models::Server.find_or_create(:host => uconfig[:irc_server], :port => uconfig[:irc_port])
121
+ n = Models::Nick.find_or_create(:nick => uconfig[:admin_nick])
122
+ a = Models::Auth.find_or_create(:nick_id => n.pk)
123
+ g = Models::Group.find_or_create(:name => 'admin')
124
+ a.add_group(g)
125
+ a.password = uconfig[:admin_password]
126
+ a.save
127
+ t = Models::Trigger.find_or_create(:trigger => uconfig[:trigger])
128
+ t.active = true
129
+ t.save
130
+ end
131
+
132
+ # echo:: echo user input
133
+ # Turns echoing of user input on or off
134
+ def input_echo(echo=true)
135
+ return if echo == @echo || @stuck_visible
136
+ term = Termios::getattr($stdin)
137
+ term.c_lflag |= Termios::ECHO if echo
138
+ term.c_lflag &= ~Termios::ECHO unless echo
139
+ Termios::setattr($stdin, Termios::TCSANOW, term)
140
+ @echo = echo
141
+ end
142
+
143
+ # pattern:: regex response must match
144
+ # default:: default value if response is empty
145
+ # echo:: echo user's input
146
+ # Reads users input
147
+ def read_input(pattern=nil, default=nil)
148
+ #input_echo(echo)
149
+ response = $stdin.readline
150
+ response.strip!
151
+ set = response.length > 0
152
+ unless(pattern.nil?)
153
+ response = nil unless response =~ /^#{pattern}$/
154
+ end
155
+ if(default && !set)
156
+ response = default
157
+ end
158
+ #input_echo(true) unless echo
159
+ #puts "" unless echo
160
+ return response
161
+ end
162
+
163
+ # output:: to send before user input
164
+ # regex:: pattern user input must match (^ and $ not needed. applied automatically)
165
+ # echo:: echo user's input
166
+ # default:: default value if no value is entered
167
+ def get_input(output, regex, default=nil)
168
+ response = nil
169
+ until(response) do
170
+ print output
171
+ print "[#{default}]: " unless default.nil?
172
+ $stdout.flush
173
+ response = read_input(regex, default)
174
+ end
175
+ return response
176
+ end
177
+
178
+ end
179
+
180
+ end
@@ -0,0 +1,51 @@
1
+ module ModSpox
2
+
3
+ class Database
4
+
5
+ def Database.db=(database)
6
+ @@db = nil
7
+ @@db = database
8
+ end
9
+
10
+ def Database.type=(type)
11
+ @@type = nil
12
+ @@type = type
13
+ end
14
+
15
+ def Database.cache=(cache)
16
+ @@cache = nil
17
+ @@cache = cache
18
+ end
19
+
20
+ def Database.cache
21
+ return Database.class_variable_defined?(:@@cache) ? @@cache : nil
22
+ end
23
+
24
+ def Database.type
25
+ return Database.class_variable_defined?(:@@type) ? @@type : nil
26
+ end
27
+
28
+ def Database.db
29
+ return Database.class_variable_defined?(:@@db) ? @@db : nil
30
+ end
31
+
32
+ def Database.reset_connections
33
+ @@db.disconnect
34
+ end
35
+
36
+ def Database.reconnect
37
+ begin
38
+ @@db.test_connection
39
+ Logger.warn('Database connection appears to be active. Closing.')
40
+ @@db.disconnect
41
+ rescue Object => boom
42
+ Logger.warn('Database connection does not appear to be active.')
43
+ ensure
44
+ Logger.warn('Reconnecting to database.')
45
+ ModSpox.setup_adapter
46
+ end
47
+ end
48
+
49
+ end
50
+
51
+ end
@@ -0,0 +1,84 @@
1
+ module ModSpox
2
+ module Exceptions
3
+
4
+ class BotException < Exception
5
+ end
6
+
7
+ class GeneralException < Exception
8
+ attr_reader :original
9
+ def initialize(o)
10
+ @original = o
11
+ end
12
+ def to_s
13
+ @original.to_s
14
+ end
15
+ end
16
+
17
+ class NotImplemented < BotException
18
+ end
19
+
20
+ class InvalidType < BotException
21
+ end
22
+
23
+ class InvalidValue < BotException
24
+ end
25
+
26
+ class AlreadyRunning < BotException
27
+ end
28
+
29
+ class NotRunning < BotException
30
+ end
31
+
32
+ class UnknownKey < BotException
33
+ end
34
+
35
+ class InstallationError < BotException
36
+ end
37
+
38
+ class LockedObject < BotException
39
+ end
40
+
41
+ class TimerInUse < BotException
42
+ end
43
+
44
+ class EmptyQueue < BotException
45
+ end
46
+
47
+ class Disconnected < BotException
48
+ end
49
+
50
+ class HandlerNotFound < BotException
51
+ attr_reader :message_type
52
+ def initialize(type)
53
+ @message_type = type
54
+ end
55
+ end
56
+
57
+ class NotInChannel < BotException
58
+ attr_reader :channel
59
+ def initialize(channel)
60
+ @channel = channel
61
+ end
62
+ def to_s
63
+ "Bot is not currently in channel: #{@channel}"
64
+ end
65
+ end
66
+
67
+ class QuietChannel < BotException
68
+ attr_reader :channel
69
+ def initialize(channel)
70
+ @channel = channel
71
+ end
72
+ def to_s
73
+ "Bot is not allowed to speak in channel: #{@channel}"
74
+ end
75
+ end
76
+
77
+ class PluginMissing < BotException
78
+ end
79
+
80
+ class PluginFileNotFound < BotException
81
+ end
82
+
83
+ end
84
+ end
@@ -0,0 +1,122 @@
1
+ ['timeout',
2
+ 'net/http',
3
+ 'mod_spox/models/Nick',
4
+ 'mod_spox/models/Channel',
5
+ 'mod_spox/models/Server',
6
+ 'mod_spox/models/Models',
7
+ 'mod_spox/Logger'].each{|f|require f}
8
+
9
+ module ModSpox
10
+ module Helpers
11
+ # secs:: number of seconds
12
+ # Converts seconds into a human readable string
13
+ def Helpers.format_seconds(secs)
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
27
+ end
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
+ "", # 1024^0
37
+ "Kilo", # 1024^1
38
+ "Mega", # 1024^2
39
+ "Giga", # 1024^3
40
+ "Tera", # 1024^4
41
+ "Peta", # 1024^5
42
+ "Exa", # 1024^6
43
+ "Zetta", # 1024^7
44
+ "Yotta" # 1024^8
45
+ ]
46
+ def Helpers.format_size(bytes)
47
+ mag = (Math.log(bytes) / Math.log(1024)).floor
48
+ mag = [ Suff.length - 1, mag ].min
49
+ val = bytes.to_f / (1024 ** mag)
50
+ "%7.3f %sbyte%s" % [ val, Suff[mag], val == 1 ? "" : "s" ]
51
+ end
52
+
53
+ # command:: command to execute
54
+ # timeout:: maximum number of seconds to run
55
+ # Execute a system command (use with care)
56
+ def Helpers.safe_exec(command, timeout=10)
57
+ begin
58
+ Timeout::timeout(timeout) do
59
+ result = `#{command}`
60
+ end
61
+ rescue Timeout::Error => boom
62
+ Logger.warn("Command execution exceeded allowed time (command: #{command} | timeout: #{timeout})")
63
+ raise boom
64
+ rescue Object => boom
65
+ Logger.warn("Command generated an exception (command: #{command} | error: #{boom})")
66
+ raise boom
67
+ end
68
+ end
69
+
70
+ # url:: URL to shorten
71
+ # Gets a tinyurl for given URL
72
+ def Helpers.tinyurl(url)
73
+ begin
74
+ connection = Net::HTTP.new('tinyurl.com', 80)
75
+ resp, data = connection.get("/api-create.php?url=#{url}")
76
+ if(resp.code !~ /^200$/)
77
+ raise "Failed to make the URL small."
78
+ end
79
+ return data.strip
80
+ rescue Object => boom
81
+ raise "Failed to process URL. #{boom}"
82
+ end
83
+ end
84
+
85
+ # string:: name of target
86
+ # Locates target model and returns it. String can be a nick
87
+ # or channel name. If the string given does not match the required
88
+ # pattern for a channel or nick, the string is returned.
89
+ def Helpers.find_model(string, create=true)
90
+ result = nil
91
+ if(string =~ /^[A-Za-z\|\\\{\}\[\]\^\`~\_\-]+[A-Za-z0-9\|\\\{\}\[\]\^\`~\_\-]*$/)
92
+ result = Models::Nick.find_or_create(:nick => string.downcase)
93
+ elsif(['&', '#', '+', '!'].include?(string[0]))
94
+ result = Models::Channel.find_or_create(:name => string.downcase)
95
+ elsif(Models::Server.filter(:host => string, :connected => true).count > 0)
96
+ result = Models::Server.filter(:host => string, :connected => true).first
97
+ else
98
+ Logger.warn("Failed to match string to model: #{string} -> No match")
99
+ end
100
+ return result
101
+ end
102
+
103
+ # string:: string to convert
104
+ # Converts HTML entities found in a string
105
+ def Helpers.convert_entities(string)
106
+ begin
107
+ require 'htmlentities'
108
+ @@coder = HTMLEntities.new unless Helpers.class_variable_defined?(:@@coder)
109
+ return @@coder.decode(string)
110
+ rescue Object
111
+ return string
112
+ end
113
+ end
114
+
115
+ # kind:: (:internal|:incoming|:outgoing)
116
+ # type:: message type (Example: :Privmsg)
117
+ # Easy loader for messages
118
+ def load_message(kind, type)
119
+ require "mod_spox/messages/#{kind}/#{type}"
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,60 @@
1
+ ['mod_spox/Exceptions',
2
+ 'mod_spox/BotConfig',
3
+ 'mod_spox/BaseConfig',
4
+ 'mod_spox/Database',
5
+ 'logger'].each{|f|require f}
6
+
7
+ module ModSpox
8
+
9
+ # Loads all files needed by the bot
10
+ def self.initialize_bot(db=nil)
11
+ setup_adapter(db)
12
+ check_upgrade
13
+ end
14
+
15
+ # Setup the DataMapper adapter
16
+ def self.setup_adapter(db=nil)
17
+ memcache = false
18
+ config = BaseConfig.new(BotConfig[:userconfigpath])
19
+ if(config[:memcache] == 'on')
20
+ begin
21
+ require 'memcache'
22
+ memcache = true
23
+ Database.cache = MemCache.new('localhost:11211', :namespace => 'modspox')
24
+ rescue Object => boom
25
+ puts "FAILED TO LOAD MEMCACHE SUPPORT: #{boom}"
26
+ # do nothing #
27
+ end
28
+ end
29
+ unless(db.nil?)
30
+ Database.db = db
31
+ else
32
+ case config[:db_adapter]
33
+ when 'mysql'
34
+ Database.db = Sequel.mysql(config[:db_database], :user => config[:db_username],
35
+ :password => config[:db_password], :host => config[:db_host], :max_connections => 20)
36
+ Database.type = :mysql
37
+ when 'pgsql'
38
+ Database.db = Sequel.connect("#{ModSpox.jdbc ? 'jdbc:' : ''}postgres://#{config[:db_username]}:#{config[:db_password]}@#{config[:db_host]}/#{config[:db_database]}")
39
+ Database.type = :pgsql
40
+ when 'sqlite'
41
+ Database.db = Sequel.sqlite("#{BotConfig[:userpath]}/mod_spox.db", :pool_timeout => 20, :timeout => 5000)
42
+ Database.type = :sqlite
43
+ end
44
+ end
45
+ end
46
+
47
+ # check if the bot has been upgraded
48
+ def self.check_upgrade
49
+ Sequel::Migrator.apply(Database.db, BotConfig[:libpath] + '/migrations')
50
+ config = BaseConfig.new(BotConfig[:userconfigpath])
51
+ config[:plugin_upgrade] = 'no'
52
+ begin
53
+ config[:plugin_upgrade] = 'yes' if config[:last_version] != ModSpox.botversion
54
+ rescue Exceptions::UnknownKey => boom
55
+ config[:plugin_upgrade] = 'yes'
56
+ end
57
+ config[:last_version] = ModSpox.botversion
58
+ end
59
+
60
+ end
@@ -0,0 +1,37 @@
1
+ require 'logger'
2
+ module ModSpox
3
+
4
+ class Logger
5
+
6
+ def Logger.initialize(logger, level)
7
+ l = {:info => ::Logger::INFO, :error => ::Logger::ERROR, :warn => ::Logger::WARN, :fatal => ::Logger::FATAL}
8
+ @@log = logger.is_a?(::Logger) ? logger : nil
9
+ @@log.level = l[level]
10
+ end
11
+
12
+ def Logger.warn(s)
13
+ @@log.warn(s) if Logger.log?
14
+ end
15
+
16
+ def Logger.info(s)
17
+ @@log.info(s) if Logger.log?
18
+ end
19
+
20
+ def Logger.fatal(s)
21
+ @@log.fatal(s) if Logger.log?
22
+ end
23
+
24
+ def Logger.error(s)
25
+ @@log.error(s) if Logger.log?
26
+ end
27
+
28
+ def Logger.log?
29
+ Logger.class_variable_defined?(:@@log)
30
+ end
31
+
32
+ def Logger.raw
33
+ Logger.log? ? @@log : nil
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,112 @@
1
+ ['mod_spox/handlers/Handler',
2
+ 'mod_spox/Logger',
3
+ 'mod_spox/Pipeline'].each{|f|require f}
4
+
5
+ module ModSpox
6
+
7
+ class MessageFactory
8
+
9
+ # access to handlers. (only really needed for testing)
10
+ attr_reader :handlers
11
+
12
+ # pipeline:: Message pipeline
13
+ # Create a new MessageFactory
14
+ def initialize(pipeline, pool)
15
+ @pipeline = pipeline
16
+ @pool = pool
17
+ @sync_pool = ActionPool::Pool.new(1, 1, nil, 2, Logger.raw)
18
+ @handlers = Hash.new
19
+ @available = {}
20
+ RFC.each_pair{|k,v| @available[v[:value]] = v[:handlers]}
21
+ @sync = [:RPL_MOTDSTART, :RPL_MOTD, :RPL_ENDOFMOTD, :RPL_WHOREPLY, :RPL_ENDOFWHO,
22
+ :RPL_NAMREPLY, :RPL_ENDOFNAMES, :RPL_WHOISUSER, :RPL_WHOISSERVER, :RPL_WHOISOPERATOR,
23
+ :RPL_WHOISIDLE, :RPL_WHOISCHANNELS, :RPL_WHOISIDENTIFIED, :RPL_ENDOFWHOIS].map{|s| RFC[s][:value]}
24
+ end
25
+
26
+ # string:: server message to be parsed
27
+ # Parses messages from server. This is placed in a queue to
28
+ # be processed thus there is now wait for processing to be
29
+ # completed.
30
+ def <<(string)
31
+ @pool.process{ parse_message(string) }
32
+ end
33
+
34
+ # s:: string from server
35
+ # determine type of message from server
36
+ def find_key(s)
37
+ s = s.dup
38
+ begin
39
+ key = nil
40
+ if(s[0].chr == ':')
41
+ s.slice!(0..s.index(' '))
42
+ key = s.slice!(0..s.index(' ')-1)
43
+ else
44
+ key = s.slice(0..s.index(' ')-1)
45
+ end
46
+ key.strip!
47
+ key = key.to_sym if key.to_i == 0
48
+ return key
49
+ rescue Object
50
+ Logger.info("Failed to find key for message: #{s}")
51
+ raise Exceptions::UnknownKey.new
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ # message:: server message
58
+ # Parses the server message and passes it to the proper handler
59
+ def parse_message(message)
60
+ Logger.info("Processing message: #{message}")
61
+ loaded = false
62
+ begin
63
+ key = find_key(message)
64
+ if(@handlers.has_key?(key))
65
+ Logger.info("Message of type #{key} is now being handled by #{@handlers[key]}")
66
+ if(@sync.include?(key))
67
+ Logger.info("Message of type #{key} requires synchronized processing")
68
+ @sync_pool.process do
69
+ message = @handlers[key].process(message)
70
+ @pipeline << message unless message.nil?
71
+ end
72
+ else
73
+ @pool.process do
74
+ message = @handlers[key].process(message)
75
+ @pipeline << message unless message.nil?
76
+ end
77
+ end
78
+ else
79
+ Logger.error("No handler was found to process message of type: #{key} Message: #{message}")
80
+ raise Exceptions::HandlerNotFound.new(key)
81
+ end
82
+ rescue Exceptions::HandlerNotFound => boom
83
+ unless(loaded)
84
+ if(@available[boom.message_type])
85
+ @available[boom.message_type].each do|f|
86
+ require "mod_spox/handlers/#{f}"
87
+ klass = ModSpox::Handlers.const_get(f)
88
+ if(klass.nil?)
89
+ Logger.error("File name does not seem to match class name. Now what? #{boom}")
90
+ else
91
+ klass.new(@handlers)
92
+ end
93
+ end
94
+ Logger.info("Loaded handler for message type: #{boom.message_type}. Reprocessing message")
95
+ loaded = true
96
+ retry
97
+ end
98
+ end
99
+ raise boom
100
+ rescue Object => boom
101
+ if(boom.class.to_s == 'SQLite3::BusyException' || boom.class.to_s == 'PGError')
102
+ Database.reset_connections
103
+ retry
104
+ else
105
+ Logger.warn("Failed to parse message from server: #{boom}\n#{boom.backtrace.join("\n")}")
106
+ end
107
+ end
108
+ end
109
+
110
+ end
111
+
112
+ end