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,201 @@
1
+ ['iconv',
2
+ 'mod_spox/Logger',
3
+ 'mod_spox/Exceptions',
4
+ 'mod_spox/messages/internal/Connected',
5
+ 'mod_spox/messages/internal/Disconnected',
6
+ 'mod_spox/models/Models',
7
+ 'mod_spox/Pipeline',
8
+ 'mod_spox/PriorityQueue'].each{|f|require f}
9
+
10
+ module ModSpox
11
+
12
+ class Socket
13
+
14
+ attr_reader :sent
15
+ attr_reader :received
16
+ attr_reader :burst
17
+ attr_reader :burst_in
18
+ attr_reader :delay
19
+ attr_reader :server
20
+ attr_reader :port
21
+ attr_reader :socket
22
+ attr_reader :connected_at
23
+
24
+ # factory:: MessageFactory to parse messages
25
+ # server:: Server to connect to
26
+ # port:: Port number to connect to
27
+ # delay:: Number of seconds to delay between bursts
28
+ # burst_in:: Number of seconds allowed to burst
29
+ # burst:: Number of lines allowed to be sent within the burst_in time limit
30
+ # Create a new Socket
31
+ def initialize(bot, server=nil, port=nil, delay=2, burst_in=2, burst=4)
32
+ @pool = bot.pool
33
+ @factory = bot.factory
34
+ @pipeline = bot.pipeline
35
+ @dcc = bot.dcc_sockets
36
+ @server = server
37
+ @port = port
38
+ @sent = 0
39
+ @received = 0
40
+ @delay = delay.to_f > 0 ? delay.to_f : 2.0
41
+ @burst = burst.to_i > 0 ? burst.to_i : 4
42
+ @burst_in = 2
43
+ @kill = false
44
+ @time_check = nil
45
+ @check_burst = 0
46
+ @pause = false
47
+ @sendq = PriorityQueue.new
48
+ @lock = Mutex.new
49
+ @connected_at = nil
50
+ @empty_lines = 0
51
+ @max_empty = 5
52
+ @servers = Array.new
53
+ @connect_locker = Mutex.new
54
+ end
55
+
56
+ # Connects to the IRC server
57
+ def connect
58
+ return unless @connect_locker.try_lock
59
+ begin
60
+ populate_servers if @servers.empty?
61
+ s = @servers.pop
62
+ @server = s.host
63
+ @port = s.port.to_i
64
+ Logger.info("Establishing connection to #{@server}:#{@port}")
65
+ @socket = TCPSocket.new(@server, @port)
66
+ @socket.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_KEEPALIVE, true)
67
+ @empty_lines = 0
68
+ s.connected = true
69
+ s.save
70
+ @connected_at = Time.now
71
+ @pipeline << Messages::Internal::Connected.new(@server, @port)
72
+ ensure
73
+ @connect_locker.unlock
74
+ end
75
+ end
76
+
77
+ # new_delay:: Seconds to delay between bursts
78
+ # Resets the delay
79
+ def delay=(new_delay)
80
+ raise Exceptions::InvalidValue('Send delay must be a positive number') unless new_delay.to_f > 0
81
+ @delay = new_delay.to_f
82
+ end
83
+
84
+ # new_burst:: Number of lines allowed in burst
85
+ # Resets the burst
86
+ def burst=(new_burst)
87
+ raise Exceptions::InvalidValue('Burst value must be a positive number') unless new_burst.to_i > 0
88
+ @burst = new_burst
89
+ end
90
+
91
+ # new_burst_in:: Number of seconds allowed to burst
92
+ # Resets the burst_in
93
+ def burst_in=(new_burst_in)
94
+ raise Exceptions::InvalidValue('Burst in value must be positive') unless new_burst_in.to_i > 0
95
+ @burst_in = new_burst_in
96
+ end
97
+
98
+ # message:: String to send to server
99
+ # Sends a string to the IRC server
100
+ def puts(message)
101
+ write(message)
102
+ end
103
+
104
+ # message:: String to send to server
105
+ # Sends a string to the IRC server
106
+ def write(message)
107
+ return if message.nil?
108
+ begin
109
+ @socket.puts(message + "\n")
110
+ @socket.flush
111
+ Logger.info("<< #{message}")
112
+ @last_send = Time.new
113
+ @sent += 1
114
+ @check_burst += 1
115
+ @time_check = Time.now.to_i if @time_check.nil?
116
+ rescue Object => boom
117
+ Logger.warn("Failed to write message to server. #{boom}")
118
+ @pipeline << Messages::Internal::Disconnected.new
119
+ raise Exceptions::Disconnected.new
120
+ end
121
+ end
122
+
123
+ # string:: string to be processed
124
+ # Process a string
125
+ def process(string)
126
+ string.strip!
127
+ Logger.info(">> #{string}")
128
+ if(string[0,5] == 'ERROR')
129
+ @pipeline << Messages::Internal::Disconnected.new
130
+ raise Exceptions::Disconnected.new
131
+ end
132
+ @received += 1
133
+ @factory << string
134
+ end
135
+
136
+ # message:: String to be sent to server
137
+ # Queues a message up to be sent to the IRC server
138
+ def <<(message)
139
+ @sendq.direct_queue(message)
140
+ @pool.process{ processor }
141
+ end
142
+
143
+ # target:: Target for outgoing message
144
+ # message:: Message to send
145
+ # This queues a message to be sent out of a prioritized
146
+ # queue. This allows for even message distribution rather
147
+ # than only on target at a time being flooded.
148
+ def prioritize_message(target, message)
149
+ @sendq.priority_queue(target, message)
150
+ @pool.process{ processor }
151
+ end
152
+
153
+ # Starts the thread for sending messages to the server
154
+ def processor
155
+ return unless @lock.try_lock
156
+ did_write = false
157
+ begin
158
+ loop do
159
+ write(@sendq.pop)
160
+ did_write = true
161
+ if((Time.now.to_i - @time_check) > @burst_in)
162
+ @time_check = nil
163
+ @check_burst = 0
164
+ elsif((Time.now.to_i - @time_check) <= @burst_in && @check_burst >= @burst)
165
+ Logger.warn("Burst limit hit. Output paused for: #{@delay} seconds")
166
+ sleep(@delay)
167
+ @time_check = nil
168
+ @check_burst = 0
169
+ end
170
+ end
171
+ rescue Exceptions::EmptyQueue => boom
172
+ Logger.info('Socket reached an empty queue.')
173
+ ensure
174
+ @lock.unlock
175
+ @pool.process{ processor } if did_write
176
+ end
177
+ end
178
+
179
+ # restart:: Reconnect after closing connection
180
+ # Closes connection to IRC server
181
+ def shutdown(restart=false)
182
+ @socket.close unless @socket.nil? || @socket.closed?
183
+ @kill = true
184
+ server = Models::Server.find_or_create(:host => @server, :port => @port)
185
+ server.connected = false
186
+ server.save
187
+ sleep(0.1)
188
+ connect if restart
189
+ end
190
+
191
+ private
192
+
193
+ def populate_servers
194
+ Models::Server.reverse_order(:priority).each{|s|
195
+ @servers << s
196
+ }
197
+ end
198
+
199
+ end
200
+
201
+ end
@@ -0,0 +1,226 @@
1
+ ['ipaddr',
2
+ 'iconv',
3
+ 'mod_spox/Bot',
4
+ 'mod_spox/Pipeline',
5
+ 'mod_spox/MessageFactory',
6
+ 'mod_spox/Socket',
7
+ 'mod_spox/messages/internal/DCCSocket',
8
+ 'mod_spox/messages/outgoing/Privmsg'
9
+ ].each{|f| require f}
10
+
11
+ require 'spockets'
12
+
13
+ module ModSpox
14
+
15
+ class Sockets
16
+
17
+ attr_reader :irc_socket
18
+
19
+ def initialize(bot)
20
+ @bot = bot
21
+ @irc_socket = nil
22
+ @dcc_sockets = []
23
+ @mapped_sockets = {}
24
+ @spockets = Spockets::Spockets.new(:pool => bot.pool)
25
+ @listening_dcc = []
26
+ @dcc_ports = {:start => 49152, :end => 65535}
27
+ @dcc_wait = 30
28
+ @pipeline = bot.pipeline
29
+ @factory = bot.factory
30
+ @pipeline.hook(self, :check_dcc, :Incoming_Privmsg)
31
+ @pipeline.hook(self, :return_socket, :Internal_DCCRequest)
32
+ @pipeline.hook(self, :dcc_listener, :Internal_DCCListener)
33
+ @pipeline.hook(self, :disconnect_irc, :Internal_Disconnected)
34
+ @pipeline.hook(self, :queue_messages, :Internal_QueueSocket)
35
+ @pipeline.hook(self, :unqueue_messages, :Internal_UnqueueSocket)
36
+ @queues = {:irc => Queue.new, :dcc => Queue.new}
37
+ @queue_messages = false
38
+ end
39
+
40
+ # server:: IRC server string
41
+ # port:: IRC port
42
+ # Connect to the given IRC server
43
+ def irc_connect(server=nil, port=nil)
44
+ if(@irc_socket.nil?)
45
+ @irc_socket = Socket.new(@bot, server, port)
46
+ @irc_socket.connect
47
+ @spockets.add(@irc_socket.socket){|string| process_irc_string(string)}
48
+ @spockets.on_close(@irc_socket.socket){ irc_reconnect }
49
+ else
50
+ irc_reconnect
51
+ end
52
+ end
53
+
54
+ def irc_reconnect
55
+ unless(@irc_socket.nil?)
56
+ disconnect_irc
57
+ @spockets.remove(@irc_socket.socket) if @spockets.include?(@irc_socket)
58
+ @irc_socket.shutdown(true)
59
+ @spockets.add(@irc_socket.socket){|string| process_irc_string(string)}
60
+ else
61
+ irc_connect
62
+ end
63
+ end
64
+
65
+ def <<(message)
66
+ if(message =~ /::(\S+)::\s:(.+)$/)
67
+ id = $1.to_i
68
+ message = $2 + "\r\n"
69
+ sock_info = @mapped_sockets[id]
70
+ sock_info[:socket] << message
71
+ else
72
+ @irc_socket << message
73
+ end
74
+ end
75
+
76
+ def prioritize_message(target, message)
77
+ @irc_socket.prioritize_message(target, message)
78
+ end
79
+
80
+ # message:: ModSpox::Messages::Incoming::Privmsg
81
+ # Checks if incoming message is a request to
82
+ # start a DCC chat session and builds the connection
83
+ def check_dcc(message)
84
+ if(message.is_ctcp? && message.ctcp_type == 'DCC')
85
+ if(message.message =~ /^CHAT chat (\S+) (\S+)/)
86
+ if(message.source.in_group?('dcc') || message.source.in_group?('admin'))
87
+ ip = IPAddr.new($1.to_i, Object::Socket::AF_INET).to_s
88
+ port = $2.to_i
89
+ build_connection(ip, port, message.source)
90
+ else
91
+ Logger.warn("Error: #{message.source.nick} is attempting to establish DCC connection without permission.")
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ # message:: ModSpox::Messages::Internal::DCCRequest
98
+ # Returns the DCC Socket requested in a ModSpox::Messages::Internal::DCCSocket
99
+ # message.
100
+ def return_socket(message)
101
+ socket = nick = nil
102
+ if(@mapped_socks.has_key?(message.socket_id))
103
+ socket = @mapped_socks[message.socket_id][:socket]
104
+ nick = @mapped_socks[message.socket_id][:nick]
105
+ end
106
+ @pipeline << Messages::Internal::DCCSocket.new(message.socket_id, nick, socket)
107
+ end
108
+
109
+ # message:: ModSpox::Messages::Internal::DCCListener
110
+ # Sets up a new socket for a user to connect to. Helpful
111
+ # if the user wants a DCC chat session but is firewalled
112
+ def dcc_listener(message)
113
+ Thread.new do
114
+ me = Models::Nick.filter(:botnick => true).first
115
+ return if me.nil?
116
+ port = rand(@dcc_ports[:end] - @dcc_ports[:start]) + @dcc_ports[:start]
117
+ socket = Object::Socket.new(Object::Socket::AF_INET, Object::Socket::SOCK_STREAM, 0)
118
+ addr = Object::Socket.pack_sockaddr_in(port, me.address)
119
+ socket.bind(addr)
120
+ client = nil
121
+ addrinfo = nil
122
+ cport = nil
123
+ cip = nil
124
+ begin
125
+ Timeout::timeout(@dcc_wait) do
126
+ @pipeline << Messages::Outgoing::Privmsg.new(message.nick, "CHAT chat #{IPAddr.new(me.address).to_i} #{port}", false, true, 'DCC')
127
+ socket.listen(5)
128
+ client, addrinfo = socket.accept
129
+ cport, cip = Object::Socket.unpack_sockaddr_in(addrinfo)
130
+ end
131
+ Logger.info("New DCC socket created for #{message.nick.nick} has connected from: #{cip}:#{cport}")
132
+ @dcc_sockets << client
133
+ @mapped_sockets[client.object_id] = {:socket => client, :nick => message.nick}
134
+ @spockets.add(socket){|string| process_dcc_string(string, socket)}
135
+ rescue Timeout::Error => boom
136
+ Logger.warn("Timeout reached waiting for #{message.nick.nick} to connect to DCC socket. Closing.")
137
+ client.close
138
+ rescue Object => boom
139
+ Logger.warn("Unknown error encountered while building DCC listener for: #{message.nick.nick}. Error: #{boom}")
140
+ client.close
141
+ ensure
142
+ socket.close
143
+ end
144
+ end
145
+ end
146
+
147
+ # Shuts down all active sockets
148
+ def shutdown
149
+ @spockets.clear
150
+ @irc_socket.shutdown
151
+ @dcc_sockets.each do |sock|
152
+ close_dcc(sock)
153
+ end
154
+ end
155
+
156
+ def disconnect_irc(m=nil)
157
+ @spockets.remove(@irc_socket.socket) if @spockets.include?(@irc_socket.socket)
158
+ end
159
+
160
+ def unqueue_messages(m)
161
+ @queue_messages = false
162
+ flush_queues
163
+ end
164
+
165
+ def queue_messages(m)
166
+ @queue_messages = true
167
+ end
168
+
169
+ private
170
+
171
+ # ip:: IP address to connect to
172
+ # port:: Port to connect to
173
+ # nick:: Nick this connection is associated with
174
+ # Builds a DCC connection to given location
175
+ def build_connection(ip, port, nick)
176
+ begin
177
+ socket = TCPSocket.new(ip, port)
178
+ @spockets.add(socket){|string| process_dcc_string(string, socket)}
179
+ @mapped_sockets[socket.object_id] = {:socket => socket, :nick => nick}
180
+ @dcc_sockets << socket
181
+ Logger.info("New DCC connection established to #{nick.nick} on #{ip}:#{port}")
182
+ rescue Object => boom
183
+ Logger.warn("DCC connection to #{nick.nick} on #{ip}:#{port} failed. #{boom}")
184
+ end
185
+ end
186
+
187
+ def close_dcc(sock)
188
+ @spockets.remove(sock)
189
+ @dcc_sockets.delete(sock)
190
+ @mapped_sockets.delete(sock.object_id)
191
+ end
192
+
193
+ def process_irc_string(string)
194
+ if(@queue_messages)
195
+ @queues[:irc] << string
196
+ else
197
+ @irc_socket.process(string)
198
+ end
199
+ end
200
+
201
+ def process_dcc_string(string, socket)
202
+ if(@queue_messages)
203
+ @queues[:dcc] = {:string => string, :socket => socket}
204
+ else
205
+ Logger.info("DCC >> #{string}")
206
+ if(socket.closed? || string.nil?)
207
+ socket.close
208
+ close_dcc(socket)
209
+ else
210
+ @pipeline << Messages::Incoming::Privmsg.new(string, @mapped_sockets[socket.object_id][:nick], "::#{sock.object_id}::", string)
211
+ end
212
+ end
213
+ end
214
+
215
+ def flush_queues
216
+ until(@queues[:irc].empty?)
217
+ process_irc_string(@queues[:irc].pop)
218
+ end
219
+ until(@queues[:dcc].empty?)
220
+ con = @queues[:dcc].pop
221
+ process_dcc_string(con[:string], con[:socket])
222
+ end
223
+ end
224
+
225
+ end
226
+ end
@@ -0,0 +1,60 @@
1
+ ['mod_spox/Logger',
2
+ 'mod_spox/Pipeline',
3
+ 'mod_spox/messages/internal/TimerResponse'].each{|f|require f}
4
+
5
+ module ModSpox
6
+
7
+ class Timer
8
+
9
+ # timer:: ActionTimer to use
10
+ # pipeline:: Message pipeline
11
+ # Creates a timer handler for interactions
12
+ # with the ActionTimer
13
+ def initialize(timer, pipeline)
14
+ @pipeline = pipeline
15
+ @timer = timer
16
+ {:Internal_TimerAdd => :add_message,
17
+ :Internal_TimerRemove => :remove_message,
18
+ :Internal_TimerClear => :clear}.each_pair do |type,method|
19
+ @pipeline.hook(self, method, type)
20
+ end
21
+ end
22
+
23
+ # message:: TimerAdd message
24
+ # Add a recurring code block
25
+ def add_message(message)
26
+ Logger.info("New block is being added to the timer")
27
+ begin
28
+ action = @timer.add(message.period, message.once, message.data, message.requester, &message.block)
29
+ @pipeline << Messages::Internal::TimerResponse.new(message.requester, action, true, message.id)
30
+ rescue Object => boom
31
+ Logger.error("Failed to add new block to timer: #{boom}")
32
+ @pipeline << Messages::Internal::TimerResponse.new(message.requester, nil, false, message.id)
33
+ end
34
+ end
35
+
36
+ # message:: TimerRemove message
37
+ # Remove an action from the timer
38
+ def remove_message(message)
39
+ @timer.remove(message.action)
40
+ Logger.info("Action has been removed from the Timer")
41
+ @pipeline << Messages::Internal::TimerResponse.new(nil, message.action, false, message.id)
42
+ end
43
+
44
+ # Clears all actions in the timer's queue
45
+ def clear(message=nil)
46
+ if(message.nil? || message.plugin.nil?)
47
+ @timer.clear
48
+ else
49
+ @timer.clear(message.plugin)
50
+ end
51
+ end
52
+
53
+ # stop the timer
54
+ def stop
55
+ @timer.stop
56
+ end
57
+
58
+ end
59
+
60
+ end
@@ -0,0 +1,14 @@
1
+ module ModSpox
2
+ @botversion='0.3.1'
3
+ @botcodename='potato shotgun'
4
+ @verbosity = 0
5
+ @mod_spox_path = nil
6
+ @daemon_bot = false
7
+ @logto = nil
8
+ @loglevel = :fatal
9
+ @jdbc = false
10
+ class << self
11
+ attr_reader :botversion, :botcodename
12
+ attr_accessor :verbosity, :mod_spox_path, :daemon_bot, :logto, :loglevel, :jdbc
13
+ end
14
+ end
@@ -0,0 +1,19 @@
1
+ require 'mod_spox/handlers/Handler'
2
+ require 'mod_spox/messages/incoming/BadNick'
3
+ module ModSpox
4
+ module Handlers
5
+ class BadNick < Handler
6
+ def initialize(handlers)
7
+ handlers[RFC[:ERR_ERRONEOUSNICKNAME][:value]] = self
8
+ end
9
+ def process(string)
10
+ if(string =~ /#{RFC[:ERR_ERRONEOUSNICKNAME][:value]}\s\S+\s(\S+)\s:/)
11
+ return Messages::Incoming::BadNick.new(string, $1)
12
+ else
13
+ Logger.warn('Failed to process RPL_ERRORONEOUSNICK message')
14
+ return nil
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,24 @@
1
+ require 'mod_spox/handlers/Handler'
2
+ require 'mod_spox/messages/incoming/Bounce'
3
+ module ModSpox
4
+ module Handlers
5
+ class Bounce < Handler
6
+ def initialize(handlers)
7
+ handlers[RFC[:RPL_BOUNCE][:value]] = self
8
+ end
9
+
10
+ def process(string)
11
+ begin
12
+ orig = string.dup
13
+ 2.times{string.slice!(0..string.index(' '))}
14
+ server = string.slice!(0..string.index(',')-1)
15
+ string.slice!(0..string.index(' ',4))
16
+ return Messages::Incoming::Bounce.new(orig, server, string)
17
+ rescue Object => boom
18
+ Logger.error("Failed to parse BOUNCE message: #{orig}")
19
+ raise Exceptions::GeneralException.new(boom)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,27 @@
1
+ require 'mod_spox/handlers/Handler'
2
+ require 'mod_spox/messages/incoming/Created'
3
+ require 'time'
4
+ module ModSpox
5
+ module Handlers
6
+ class Created < Handler
7
+ def initialize(handlers)
8
+ handlers[RFC[:RPL_CREATED][:value]] = self
9
+ end
10
+ # :not.configured 003 spox :This server was created Tue Mar 24 2009 at 15:42:36 PDT'
11
+ def process(string)
12
+ string = string.dup
13
+ begin
14
+ orig = string.dup
15
+ 2.times{string.slice!(0..string.index(':'))}
16
+ 4.times{string.slice!(0..string.index(' '))}
17
+ time = Time.parse(string)
18
+ time = nil if Time.now == time
19
+ return time.nil? ? nil : Messages::Incoming::Created.new(orig, time)
20
+ rescue Object => boom
21
+ Logger.error("Failed to parse RPL_CREATED message: #{orig}")
22
+ raise Exceptions::GeneralException.new(boom)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,39 @@
1
+ require 'mod_spox/rfc2812'
2
+ require 'mod_spox/Helpers'
3
+ require 'mod_spox/Exceptions'
4
+ module ModSpox
5
+ module Handlers
6
+
7
+ class Handler
8
+
9
+ # handlers:: array of handlers
10
+ # initialize handler and add self to available
11
+ # handlers
12
+ def initialize(handlers)
13
+ raise Exceptions::NotImplemented.new('Method has not been implemented')
14
+ end
15
+
16
+ # data:: string of data
17
+ # Process the string and create the proper object
18
+ def process(data)
19
+ raise Exceptions::NotImplemented.new('Method has not been implemented')
20
+ end
21
+
22
+ # data:: any expected data
23
+ # Preprocessing allows for actions to be taken
24
+ # while messages are still in a synchronized state
25
+ def preprocess(data)
26
+ end
27
+
28
+ protected
29
+
30
+ # deprecated. here basically so old handlers
31
+ # don't break
32
+ def find_model(string)
33
+ Helpers.find_model(string)
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,28 @@
1
+ require 'mod_spox/handlers/Handler'
2
+ require 'mod_spox/messages/incoming/Invite'
3
+ module ModSpox
4
+ module Handlers
5
+ class Invite < Handler
6
+ def initialize(handlers)
7
+ handlers[:INVITE] = self
8
+ end
9
+ # :spax!~spox@host INVITE spox :#m
10
+ def process(string)
11
+ orig = string.dup
12
+ string = string.dup
13
+ begin
14
+ string.slice!(0)
15
+ source = find_model(string.slice!(0..string.index('!')-1))
16
+ 2.times{ string.slice!(0..string.index(' ')) }
17
+ target = find_model(string.slice!(0..string.index(' ')-1))
18
+ string.slice!(0..string.index(':'))
19
+ channel = find_model(string.strip)
20
+ return Messages::Incoming::Invite.new(orig, source, target, channel)
21
+ rescue Object => boom
22
+ Logger.error("Failed to parse INVITE message: #{orig}")
23
+ raise Exceptions::GeneralException.new(boom)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,38 @@
1
+ require 'mod_spox/handlers/Handler'
2
+ require 'mod_spox/messages/incoming/Join'
3
+ module ModSpox
4
+ module Handlers
5
+ class Join < Handler
6
+ def initialize(handlers)
7
+ handlers[:JOIN] = self
8
+ end
9
+
10
+ # :mod_spox!~mod_spox@host JOIN :#m
11
+
12
+ def process(string)
13
+ orig = string.dup
14
+ string = string.dup
15
+ begin
16
+ string.slice!(0)
17
+ source = string.slice!(0..string.index(' ')-1)
18
+ string.slice!(0..string.index(':'))
19
+ channel = find_model(string.strip)
20
+ nick = find_model(source.slice(0..source.index('!')-1))
21
+ nick.source = source.dup
22
+ source.slice!(0..source.index('!'))
23
+ nick.username = source.slice!(0..source.index('@')-1)
24
+ source.slice!(0)
25
+ nick.address = source.slice!(0..source.size)
26
+ nick.visible = true
27
+ nick.save_changes
28
+ channel.add_nick(nick)
29
+ channel.save
30
+ return Messages::Incoming::Join.new(orig, channel, nick)
31
+ rescue Object => boom
32
+ Logger.warn("Failed to parse JOIN message: #{orig}")
33
+ raise Exceptions::GeneralException.new(boom)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end