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,604 @@
1
+ ['mod_spox/Logger',
2
+ 'mod_spox/Sockets',
3
+ 'mod_spox/Pipeline',
4
+ 'mod_spox/PluginManager',
5
+ 'mod_spox/MessageFactory',
6
+ 'mod_spox/BaseConfig',
7
+ 'mod_spox/models/Models',
8
+ 'mod_spox/Helpers',
9
+ 'mod_spox/Timer',
10
+ 'mod_spox/messages/internal/BotInitialized',
11
+ 'mod_spox/messages/internal/Shutdown',
12
+ 'mod_spox/messages/internal/ConnectionFailed',
13
+ 'mod_spox/messages/internal/StatusResponse',
14
+ 'mod_spox/messages/internal/NickResponse',
15
+ 'actionpool',
16
+ 'actiontimer'].each{|f|require f}
17
+
18
+ module ModSpox
19
+
20
+ class Bot
21
+
22
+ # bot timer
23
+ attr_reader :timer
24
+
25
+ # thread pool
26
+ attr_reader :pool
27
+
28
+ # message pipeline
29
+ attr_reader :pipeline
30
+
31
+ # plugin manager
32
+ attr_reader :plugin_manager
33
+
34
+ # message factory
35
+ attr_reader :factory
36
+
37
+ # DCC sockets
38
+ attr_reader :dcc_sockets
39
+
40
+ # Create a Bot
41
+ def initialize
42
+ unless(ModSpox.logto.nil?)
43
+ logger = ::Logger.new(ModSpox.logto, 'daily')
44
+ Logger.initialize(logger, ModSpox.loglevel)
45
+ end
46
+ clean_models
47
+ @servers = Array.new
48
+ @channels = Array.new
49
+ @start_time = Time.now
50
+ @pool = ActionPool::Pool.new(10, 100, 60, nil, logger)
51
+ @pipeline = Pipeline.new(@pool)
52
+ @timer = Timer.new(ActionTimer::Timer.new(@pool, logger), @pipeline)
53
+ @config = BaseConfig.new(BotConfig[:userconfigpath])
54
+ @factory = MessageFactory.new(@pipeline, @pool)
55
+ @socket = nil
56
+ @plugin_manager = PluginManager.new(@pipeline)
57
+ if(@config[:plugin_upgrade] == 'yes')
58
+ @plugin_manager.upgrade_plugins
59
+ Logger.info('Main bot thread is now sleeping for 10 seconds to allow upgrade to conclude')
60
+ sleep(10)
61
+ Logger.info('Main bot thread sleep completed. Continuing loading.')
62
+ end
63
+ @config[:plugin_upgrade] = 'no'
64
+ @config.write_configuration
65
+ @shutdown = false
66
+ @socket = Sockets.new(self)
67
+ @nick = nil
68
+ @thread = Thread.current
69
+ @lock = Mutex.new
70
+ @waiter = ConditionVariable.new
71
+ hook_pipeline
72
+ end
73
+
74
+ # Run the bot
75
+ def run
76
+ trap('SIGTERM'){ Logger.warn("Caught SIGTERM"); halt }
77
+ trap('SIGKILL'){ Logger.warn("Caught SIGKILL"); halt }
78
+ trap('SIGINT'){ Logger.warn("Caught SIGINT"); halt }
79
+ trap('SIGQUIT'){ Logger.warn("Caught SIGQUIT"); halt }
80
+ until @shutdown do
81
+ @pipeline << Messages::Internal::BotInitialized.new
82
+ begin
83
+ @lock.synchronize do
84
+ Logger.info('Putting main execution thread to sleep until shutdown')
85
+ @waiter.wait(@lock)
86
+ Logger.info('Main execution thread has been restored.')
87
+ end
88
+ rescue Object => boom
89
+ Logger.fatal("Caught exception: #{boom}")
90
+ ensure
91
+ shutdown
92
+ end
93
+ end
94
+ end
95
+
96
+ # Shut the bot down
97
+ def shutdown
98
+ @shutdown = true
99
+ Logger.info('Shutdown sequence initiated')
100
+ @plugin_manager.destroy_plugins
101
+ @timer.stop
102
+ @pipeline << Messages::Internal::Shutdown.new
103
+ sleep(0.1)
104
+ @socket.shutdown unless @socket.nil?
105
+ clean_models
106
+ end
107
+
108
+ # Reload the bot (basically a restart)
109
+ def reload
110
+ @lock.synchronize do
111
+ @waiter.signal
112
+ end
113
+ end
114
+
115
+ # message:: Messages::Internal::EstablishConnection message
116
+ # Initialize connection to IRC server
117
+ def bot_connect(message)
118
+ Logger.info("Received a connection command")
119
+ begin
120
+ @socket = Sockets.new(self) if @socket.nil?
121
+ @socket.irc_connect(message.server, message.port)
122
+ rescue Object => boom
123
+ Logger.warn("Failed connection to server: #{boom}")
124
+ @pipeline << Messages::Internal::ConnectionFailed.new(@socket.irc_socket.server, @socket.irc_socket.port)
125
+ end
126
+ end
127
+
128
+ # message:: Messages::Internal::Reconnect
129
+ # instructs bot to reconnect to IRC server
130
+ def reconnect(message=nil)
131
+ begin
132
+ @plugin_manager.reload_plugins
133
+ @socket.irc_reconnect
134
+ rescue Object => boom
135
+ Logger.warn("Initial reconnect failed. (#{boom}) Starting timed reconnect process.")
136
+ begin
137
+ @socket.irc_reconnect
138
+ rescue Object => boom
139
+ Logger.warn("Failed to connect to server. Reason: #{boom}")
140
+ Logger.warn("Will retry in 20 seconds")
141
+ sleep(20)
142
+ retry
143
+ end
144
+ end
145
+ end
146
+
147
+ # message:: Messages::Internal::StatusRequest message
148
+ # Returns the current status of the bot
149
+ def status(message)
150
+ @pipeline << Messages::Internal::StatusResponse.new(message.requester, bot_stats)
151
+ end
152
+
153
+ # Returns status of the bot in a formatted string
154
+ def bot_stats
155
+ return {:uptime => Helpers::format_seconds(Time.now - @start_time),
156
+ :plugins => @plugin_manager.plugins.size,
157
+ :socket_connect => @socket.irc_socket.connected_at,
158
+ :sent => @socket.irc_socket.sent,
159
+ :received => @socket.irc_socket.received}
160
+ end
161
+
162
+ # Adds hooks to pipeline for processing messages
163
+ def hook_pipeline
164
+ {:Outgoing_Admin => :admin, :Outgoing_Away => :away,
165
+ :Outgoing_ChannelMode => :channel_mode, :Outgoing_Connect => :connect,
166
+ :Outgoing_Die => :die, :Outgoing_Info => :info,
167
+ :Outgoing_Invite => :invite, :Outgoing_Ison => :ison,
168
+ :Outgoing_Join => :join, :Outgoing_Kick => :kick,
169
+ :Outgoing_Kill => :kill, :Outgoing_Links => :links,
170
+ :Outgoing_List => :list, :Outgoing_Lusers => :lusers,
171
+ :Outgoing_Motd => :motd, :Outgoing_Names => :names,
172
+ :Outgoing_Nick => :nick, :Outgoing_Notice => :notice,
173
+ :Outgoing_Oper => :oper, :Outgoing_Part => :part,
174
+ :Outgoing_Pass => :pass, :Outgoing_Ping => :ping,
175
+ :Outgoing_Pong => :pong, :Outgoing_Privmsg => :privmsg,
176
+ :Outgoing_Quit => :quit, :Outgoing_Rehash => :rehash,
177
+ :Outgoing_ServList => :servlist, :Outgoing_Squery => :squery,
178
+ :Outgoing_Squit => :squit, :Outgoing_Stats => :stats,
179
+ :Outgoing_Summon => :summon, :Outgoing_Time => :time,
180
+ :Outgoing_Topic => :topic, :Outgoing_Trace => :trace,
181
+ :Outgoing_Unaway => :unaway, :Outgoing_User => :user,
182
+ :Outgoing_UserHost => :userhost, :Outgoing_UserMode => :user_mode,
183
+ :Outgoing_Users => :users, :Outgoing_Version => :version,
184
+ :Outgoing_Who => :who, :Outgoing_WhoWas => :whowas,
185
+ :Outgoing_Whois => :whois, :Internal_EstablishConnection => :bot_connect,
186
+ :Internal_StatusRequest => :status, :Internal_ChangeNick => :set_nick,
187
+ :Internal_NickRequest => :get_nick, :Internal_HaltBot => :halt,
188
+ :Internal_Disconnected => :disconnected, :Internal_TimerClear => :clear_timer,
189
+ :Outgoing_Raw => :raw, :Internal_Reconnect => :reconnect,
190
+ :Incoming_Join => :check_join, :Incoming_Part => :check_part
191
+ }.each_pair{ |type,method| @pipeline.hook(self, method, type) }
192
+ end
193
+
194
+ # message:: Messages::Internal::TimerClear
195
+ # Clear all actions from timer
196
+ def clear_timer(message)
197
+ @timer.clear
198
+ end
199
+
200
+ # message:: Messages::Internal::Disconnected
201
+ # Disconnect the bot from the IRC server
202
+ def disconnected(message)
203
+ reload
204
+ end
205
+
206
+ # Stop the bot
207
+ def halt(message=nil)
208
+ @shutdown = true
209
+ reload
210
+ end
211
+
212
+ # message:: Messages::Internal::ChangeNick message
213
+ # Changes the bot's nick to the given nick
214
+ def set_nick(message)
215
+ @nick = message.new_nick
216
+ end
217
+
218
+ # message:: Messages::Internal::NickRequest
219
+ # Sends the bot's nick to plugins
220
+ def get_nick(message)
221
+ @pipeline << Messages::Internal::NickResponse(message.requester, @nick)
222
+ end
223
+
224
+ # message:: Messages::Outgoing::Pass message
225
+ # Sends PASS message to server
226
+ def pass(message)
227
+ @socket << "PASS #{message.password}"
228
+ end
229
+
230
+ # message:: Messages::Outgoing::Nick message
231
+ # Sends NICK message to server
232
+ def nick(message)
233
+ nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
234
+ @socket << "NICK #{nick}"
235
+ end
236
+
237
+ # message:: Messages::Outgoing::User message
238
+ # Sends USER message to server
239
+ def user(message)
240
+ @socket << "USER #{message.username} #{message.mode} * :#{message.real_name}"
241
+ end
242
+
243
+ # message:: Messages::Outgoing::Oper message
244
+ # Sends Oper message to server
245
+ def oper(message)
246
+ @socket << "OPER #{message.name} #{message.password}"
247
+ end
248
+
249
+ # message:: Messages::Outgoing::UserMode message
250
+ # Sends MODE message to server
251
+ def user_mode(message)
252
+ raise Exceptions::InvalidValue.new('Mode must be in the form of: [+-][a-z]+') unless message.mode =~ /^[+\-][a-z]+$/
253
+ nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
254
+ @socket << "MODE #{nick} #{message.mode}"
255
+ end
256
+
257
+ # message:: Messages::Outgoing::Quit message
258
+ # Sends QUIT message to server
259
+ def quit(message)
260
+ @socket << "QUIT :#{message.message}"
261
+ end
262
+
263
+ # message:: Messages::Outgoing::Squit message
264
+ # Sends SQUIT message to server
265
+ def squit(message)
266
+ @socket << "SQUIT #{message.server} :#{message.comment}"
267
+ end
268
+
269
+ # message:: Messages::Outgoing::Join message
270
+ # Sends JOIN message to server
271
+ def join(message)
272
+ channel = message.channel.is_a?(Models::Channel) ? message.channel.name : message.channel
273
+ @socket << "JOIN #{channel} #{message.key}"
274
+ end
275
+
276
+ # message:: Messages::Outgoing::Part message
277
+ # Sends PART message to server
278
+ def part(message)
279
+ channel = message.channel.is_a?(Models::Channel) ? message.channel.name : message.channel
280
+ @socket << "PART #{channel} :#{message.reason}"
281
+ end
282
+
283
+ # message:: Messages::Outgoing::ChannelMode message
284
+ # Sends MODE message to server
285
+ def channel_mode(message)
286
+ target = message.target
287
+ channel = message.channel
288
+ target = target.nick if target.is_a?(Models::Nick)
289
+ channel = channel.name if channel.is_a?(Models::Channel)
290
+ @socket << "MODE #{channel} #{message.mode} #{target}"
291
+ end
292
+
293
+ # message:: Messages::Outgoing::Topic message
294
+ # Sends TOPIC message to server
295
+ def topic(message)
296
+ channel = message.channel.is_a?(Models::Channel) ? message.channel.name : message.channel
297
+ @socket << "TOPIC #{channel} :#{message.topic}"
298
+ end
299
+
300
+ # message:: Messages::Outgoing::Names message
301
+ # Sends NAMES message to server
302
+ def names(message)
303
+ channel = message.channel.is_a?(Models::Channel) ? message.channel.name : message.channel
304
+ @socket << "NAMES #{channel} #{message.target}"
305
+ end
306
+
307
+ # message:: Messages::Outgoing::List message
308
+ # Sends LIST message to server
309
+ def list(message)
310
+ channel = message.channel.is_a?(Models::Channel) ? message.channel.name : message.channel
311
+ @socket << "LIST #{channel}"
312
+ end
313
+
314
+ # message:: Messages::Outgoing::Invite message
315
+ # Sends INVITE message to server
316
+ def invite(message)
317
+ okay_to_send(message.channel)
318
+ nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
319
+ channel = message.channel.is_a?(Models::Channel) ? message.channel.name : message.channel
320
+ @socket << "INVITE #{nick} #{channel}"
321
+ end
322
+
323
+ # message:: Messages::Outgoing::Kick message
324
+ # Sends KICK message to server
325
+ def kick(message)
326
+ okay_to_send(message.channel)
327
+ nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
328
+ channel = message.channel.is_a?(Models::Channel) ? message.channel.name : message.channel
329
+ @socket << "KICK #{channel} #{nick} :#{message.reason}"
330
+ end
331
+
332
+ # message:: Messages::Outgoing::Privmsg message
333
+ # Sends PRIVMSG message to server
334
+ def privmsg(message)
335
+ okay_to_send(message.target)
336
+ target = message.target.name if message.target.is_a?(Models::Channel)
337
+ target = message.target.nick if message.target.is_a?(Models::Nick)
338
+ target = message.target unless target
339
+ messages = message.message.is_a?(Array) ? message.message : [message.message]
340
+ messages.each do |part|
341
+ part.split("\n").each do |content|
342
+ while(content.size > 400)
343
+ output = content[0..400]
344
+ content.slice!(0, 401) #(450, content.size)
345
+ @socket.prioritize_message(target, "PRIVMSG #{target} :#{message.is_ctcp? ? "\cA#{message.ctcp_type} #{output}\cA" : output}")
346
+ end
347
+ @socket.prioritize_message(target, "PRIVMSG #{target} :#{message.is_ctcp? ? "\cA#{message.ctcp_type} #{content}\cA" : content}")
348
+ end
349
+ end
350
+ end
351
+
352
+ # message:: Messages::Outgoing::Notice message
353
+ # Sends NOTICE message to server
354
+ def notice(message)
355
+ okay_to_send(message.target)
356
+ target = message.target.name if message.target.is_a?(Models::Channel)
357
+ target = message.target.nick if message.target.is_a?(Models::Nick)
358
+ @socket << "NOTICE #{target} :#{message}"
359
+ end
360
+
361
+ # message:: Messages::Outgoing::Motd message
362
+ # Sends MOTD message to server
363
+ def motd(message)
364
+ @socket << "MOTD #{message.target}"
365
+ end
366
+
367
+ # message:: Messages::Outgoing::Lusers message
368
+ # Sends LUSERS message to server
369
+ def lusers(message)
370
+ @socket << "LUSERS #{message.mask} #{message.target}"
371
+ end
372
+
373
+ # message:: Messages::Outgoing::Version message
374
+ # Sends VERSION message to server
375
+ def version(message)
376
+ @socket << "VERSION #{message.target}"
377
+ end
378
+
379
+ # message:: Messages::Outgoing::Stats message
380
+ # Sends STATS message to server
381
+ def stats(message)
382
+ raise Exceptions::InvalidValue.new('Query must be a single character') unless message.query =~ /^[a-z]$/
383
+ @socket << "STATS #{message.query} #{message.target}"
384
+ end
385
+
386
+ # message:: Messages::Outgoing::Links message
387
+ # Sends LINKS message to server
388
+ def links(message)
389
+ @socket << "LIST #{message.server} #{message.mask}"
390
+ end
391
+
392
+ # message:: Messages::Outgoing::Time message
393
+ # Sends TIME message to server
394
+ def time(message)
395
+ @socket << "TIME #{message.target}"
396
+ end
397
+
398
+ # message:: Messages::Outgoing::Connect message
399
+ # Sends CONNECT message to server
400
+ def connect(message)
401
+ @socket << "CONNECT #{message.target_server} #{message.port} #{message.remote_server}"
402
+ end
403
+
404
+ # message:: Messages::Outgoing::Trace message
405
+ # Sends TRACE message to server
406
+ def trace(message)
407
+ @socket << "TRACE #{message.target}"
408
+ end
409
+
410
+ # message:: Messages::Outgoing::Admin message
411
+ # Sends ADMIN message to server
412
+ def admin(message)
413
+ @socket << "ADMIN #{message.target}"
414
+ end
415
+
416
+ # message:: Messages::Outgoing::Info message
417
+ # Sends INFO message to server
418
+ def info(message)
419
+ @socket << "INFO #{message.target}"
420
+ end
421
+
422
+ # message:: Messages::Outgoing::ServList message
423
+ # Sends SERVLIST message to server
424
+ def servlist(message)
425
+ @socket << "SERVLIST #{message.mask} #{message.type}"
426
+ end
427
+
428
+ # message:: Messages::Outgoing::Squery message
429
+ # Sends SQUERY message to server
430
+ def squery(message)
431
+ @socket << "SQUERY #{message.service_name} #{message.message}"
432
+ end
433
+
434
+ # message:: Messages::Outgoing::Who message
435
+ # Sends WHO message to server
436
+ def who(message)
437
+ o = message.only_ops? ? 'o' : ''
438
+ @socket.prioritize_message('*who', "WHO #{message.mask} #{o}")
439
+ end
440
+
441
+ # message:: Messages::Outgoing::Whois message
442
+ # Sends WHOIS message to server
443
+ def whois(message)
444
+ nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
445
+ @socket.prioritize_message('*whois', "WHOIS #{message.target_server} #{nick}")
446
+ end
447
+
448
+ # message:: Messages::Outgoing::WhoWas message
449
+ # Sends WHOWAS message to server
450
+ def whowas(message)
451
+ nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
452
+ @socket << "WHOWAS #{message.nick} #{message.count} #{message.target}"
453
+ end
454
+
455
+ # message:: Messages::Outgoing::Kill message
456
+ # Sends KILL message to server
457
+ def kill(message)
458
+ nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
459
+ @socket << "KILL #{nick} :#{message.comment}"
460
+ end
461
+
462
+ # message:: Messages::Outgoing::Ping message
463
+ # Sends PING message to server
464
+ def ping(message)
465
+ @socket << "PING #{message.message}"
466
+ end
467
+
468
+ # message:: Messages::Outgoing::Pong message
469
+ # Sends PONG message to server
470
+ def pong(message)
471
+ @socket << "PONG #{message.server} #{message.string.nil? ? '' : ":#{message.string}"}"
472
+ end
473
+
474
+ # message:: Messages::Outgoing::Away message
475
+ # Sends AWAY message to server
476
+ def away(message)
477
+ @socket << "AWAY :#{message.message}"
478
+ end
479
+
480
+ # message:: Messages::Outgoing::Unaway message
481
+ # Sends AWAY message to server
482
+ def unaway(message)
483
+ @socket << "AWAY"
484
+ end
485
+
486
+ # message:: Messages::Outgoing::Rehash message
487
+ # Sends REHASH message to server
488
+ def rehash(message)
489
+ @socket << "REHASH"
490
+ end
491
+
492
+ # message:: Messages::Outgoing::Die message
493
+ # Sends DIE message to server
494
+ def die(message)
495
+ @socket << "DIE"
496
+ end
497
+
498
+ # message:: Messages::Outgoing::Restart message
499
+ # Sends RESTART message to server
500
+ def restart(message)
501
+ @socket << "RESTART"
502
+ end
503
+
504
+ # message:: Messages::Outgoing::Summon message
505
+ # Sends SUMMON message to server
506
+ def summon(message)
507
+ nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
508
+ channel = message.channel.is_a?(Models::Channel) ? message.channel.name : message.channel
509
+ @socket << "SUMMON #{nick} #{message.target} #{channel}"
510
+ end
511
+
512
+ # message:: Messages::Outgoing::Users message
513
+ # Sends USERS message to server
514
+ def users(message)
515
+ @socket << "USERS #{message.target}"
516
+ end
517
+
518
+ def wallops
519
+ end
520
+
521
+ # message:: Messages::Outgoing::UserHost message
522
+ # Sends USERHOST message to server
523
+ def userhost(message)
524
+ nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
525
+ @socket << "USERHOST #{nick}"
526
+ end
527
+
528
+ # message:: Messages::Outgoing::Ison message
529
+ # Sends ISON message to server
530
+ def ison(message)
531
+ nick = message.nick.is_a?(Models::Nick) ? message.nick.nick : message.nick
532
+ @socket << "ISON #{nick}"
533
+ end
534
+
535
+ # message:: Messages::Outoing::Raw message
536
+ # Send raw message to server
537
+ def raw(message)
538
+ @socket << message.message
539
+ end
540
+
541
+ def check_join(m)
542
+ if(m.nick.botnick)
543
+ @channels << m.channel.name.downcase
544
+ end
545
+ end
546
+
547
+ def check_part(m)
548
+ if(m.nick.botnick)
549
+ @channels.delete(m.channel.name.downcase)
550
+ end
551
+ end
552
+
553
+ private
554
+
555
+ # channel:: channel to check
556
+ # checks if the bot is parked in the given channel
557
+ # and raises an exception (and logs) if the bot
558
+ # is not in the given channel
559
+ def okay_to_send(channel)
560
+ if(channel.is_a?(String) && ['&', '#', '+', '!'].include?(channel[0]))
561
+ channel = Helpers.find_model(channel)
562
+ end
563
+ return unless channel.is_a?(Models::Channel)
564
+ if(channel.quiet)
565
+ Logger.error("Attempted to send to channel where bot is not allowed to speak: #{channel.name}")
566
+ raise Exceptions::QuietChannel.new(channel)
567
+ end
568
+ unless(in_channel?(channel))
569
+ Logger.error("Attempted to send to channel where bot is not parked: #{channel.name}.")
570
+ raise Exceptions::NotInChannel.new(channel)
571
+ end
572
+ end
573
+
574
+ def in_channel?(channel)
575
+ unless(@channels.include?(channel.name.downcase))
576
+ repopulate_channels
577
+ return @channels.include?(channel.name.downcase)
578
+ else
579
+ return true
580
+ end
581
+ end
582
+
583
+ def repopulate_channels
584
+ bot = Models::Nick.filter(:botnick => true).first
585
+ raise Exceptions::BotException.new("I DON'T KNOW WHO I AM") unless bot
586
+ @channels.clear
587
+ bot.channels.each{|c| @channels << c.name.downcase}
588
+ end
589
+
590
+ # Cleans information from models to avoid
591
+ # stale values
592
+ def clean_models
593
+ Models::NickMode.destroy
594
+ Models::Channel.update(:topic => nil)
595
+ Models::Nick.update(:username => nil, :real_name => nil, :address => nil,
596
+ :source => nil, :connected_at => nil, :connected_to => nil,
597
+ :seconds_idle => nil, :away => false, :visible => false, :botnick => false)
598
+ Models::Auth.update(:authed => false)
599
+ Database.db[:auth_masks_nicks].delete
600
+ Database.db[:nick_channels].delete
601
+ end
602
+ end
603
+
604
+ end
@@ -0,0 +1,65 @@
1
+ require 'etc'
2
+ require 'mod_spox/Exceptions'
3
+
4
+ module ModSpox
5
+
6
+ class BotConfig
7
+
8
+ @@config = nil
9
+
10
+ # Populates all important paths. This does not need to
11
+ # be explicitly called though nothing bad will happen if
12
+ # it is. Keys available are:
13
+ # :basepath => path to gem directory
14
+ # :libpath => path to lib directory
15
+ # :datapath => path to data directory
16
+ # :pluginpath => path to plugin directory
17
+ # :pluginextraspath => path to extra functionality plugins
18
+ # :userpath => path to mod_spox directory in user's home directory
19
+ # :userpluginpath => path to user's plugin directory
20
+ # :userconfigpath => path to the user configuration file
21
+ def BotConfig.populate(createdir=true)
22
+ gemname, gem = Gem.source_index.find{|name, spec|
23
+ spec.name == 'mod_spox' && spec.version.version = ModSpox.botversion
24
+ }
25
+ if(gem)
26
+ p = gem.full_gem_path
27
+ up = ModSpox.mod_spox_path.nil? ? Etc.getpwnam(Etc.getlogin).dir : ModSpox.mod_spox.path
28
+ @@config = {:basepath => p,
29
+ :libpath => "#{p}/lib/mod_spox",
30
+ :datapath => "#{p}/data/mod_spox",
31
+ :pluginpath => "#{p}/data/mod_spox/plugins",
32
+ :pluginextraspath => "#{p}/data/mod_spox/extras",
33
+ :userpath => "#{up}/.mod_spox",
34
+ :userpluginpath => "#{up}/.mod_spox/plugins",
35
+ :userconfigpath => "#{up}/.mod_spox/config"}
36
+ if(createdir)
37
+ [@@config[:userpath], @@config[:userpluginpath]].each do |path|
38
+ Dir.mkdir(path) unless File.exists?(path)
39
+ end
40
+ end
41
+ else
42
+ raise Exceptions::InstallationError.new('Failed to find mod_spox gem')
43
+ end
44
+ end
45
+
46
+ # name:: Name of the path string you would like
47
+ # Provides access to important path values
48
+ def BotConfig.[](name)
49
+ BotConfig.populate unless @@config
50
+ name = name.to_sym unless name.is_a?(Symbol)
51
+ raise Exceptions::UnknownKey.new("Failed to find given key: #{name}") unless @@config.has_key?(name)
52
+ return @@config[name]
53
+ end
54
+
55
+ # Returns if the bot has been configured
56
+ def BotConfig.configured?
57
+ BotConfig.populate(false)
58
+ path = BotConfig[:userpath]
59
+ @@config = nil
60
+ return File.exists?(path)
61
+ end
62
+
63
+ end
64
+
65
+ end