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,267 @@
1
+ require 'mod_spox/messages/internal/PluginRequest'
2
+
3
+ class Roulette < ModSpox::Plugin
4
+
5
+ include Models
6
+
7
+ def initialize(pipeline)
8
+ super(pipeline)
9
+ add_sig(:sig => 'roulette', :method => :roulette, :req => 'public')
10
+ add_sig(:sig => 'suicide', :method => :suicide, :req => 'public')
11
+ add_sig(:sig => 'shoot (\S+)', :method => :shoot, :req => 'public', :params => [:nick])
12
+ add_sig(:sig => 'roulette topten', :method => :topten, :req => 'public')
13
+ add_sig(:sig => 'roulette stats ?(\S+)?', :method => :stats, :req => 'public', :params => [:nick])
14
+ add_sig(:sig => 'roulette chambers', :method => :chambers, :req => 'public')
15
+ Game.create_table unless Game.table_exists?
16
+ Info.create_table unless Info.table_exists?
17
+ @banner = nil
18
+ @pipeline.hook(self, :get_banner, :Internal_PluginResponse)
19
+ end
20
+
21
+ # message:: ModSpox::Messages::Incoming::Privmsg
22
+ # Display chamber statistics
23
+ def chambers(m, p)
24
+ total = Game.all.size
25
+ result = Game.group(:chamber).select(:chamber, 'COUNT(chamber) as total'.lit).reverse_order(:total)
26
+ if(result)
27
+ output = []
28
+ result.each do |res|
29
+ percent = sprintf('%.2d', ((res[:total].to_f / total.to_f) * 100.0))
30
+ output << "chamber #{res.chamber}: #{percent}% (#{res[:total]})"
31
+ end
32
+ reply m.replyto, "\2Chamber stats:\2 #{output.join(', ')}"
33
+ else
34
+ reply m.replyto, "\2Error:\2 No games found"
35
+ end
36
+ end
37
+
38
+ # message:: ModSpox::Messages::Internal::PluginResponse
39
+ # Get the banner plugin
40
+ def get_banner(message)
41
+ @banner = message.plugin if message.found?
42
+ end
43
+
44
+ # message:: ModSpox::Messages::Incoming::Privmsg
45
+ # params:: empty
46
+ # Play roulette
47
+ def roulette(message, params)
48
+ return unless message.is_public?
49
+ do_shot(message.source, message.target)
50
+ end
51
+
52
+ # message:: ModSpox::Messages::Incoming::Privmsg
53
+ # params:: empty
54
+ # Kill self
55
+ def suicide(message, params)
56
+ return unless message.is_public?
57
+ do_suicide(message.source, message.target)
58
+ end
59
+
60
+ # message:: ModSpox::Messages::Incoming::Privmsg
61
+ # params:: nick
62
+ # Shoot other person playing current game
63
+ def shoot(message, params)
64
+ return unless message.is_public?
65
+ cur_game = game(message.target)
66
+ nick = Helpers.find_model(params[:nick], false)
67
+ if(cur_game.shots == 1 && nick && Info.filter(:game_id => cur_game.pk, :nick_id => nick.pk))
68
+ do_shot(nick, message.target)
69
+ else
70
+ do_suicide(message.source, message.target)
71
+ end
72
+ end
73
+
74
+ # message:: ModSpox::Messages::Incoming::Privmsg
75
+ # params:: empty
76
+ # List topten players
77
+ def topten(message, params)
78
+ return unless message.is_public?
79
+ ds = Database.db[:infos].left_outer_join(:games, :id => :game_id)
80
+ res = ds.select(:nick_id, 'COUNT(win) as wins'.lit).where(:channel_id => message.target.pk, :win => true).group(:nick_id).reverse_order(:wins).limit(10)
81
+ ids = res.map(:nick_id)
82
+ top = []
83
+ ids.each do |id|
84
+ nick = Nick[id]
85
+ top << "#{nick.nick} (#{win_loss_ratio(nick, message.target)}% survival with #{games_won(nick, message.target)} wins)"
86
+ end
87
+ if(top.empty?)
88
+ reply(message.replyto, "\2Error:\2 No one has survived")
89
+ else
90
+ reply(message.replyto, "Roulette topten: #{top.join(', ')}")
91
+ end
92
+ end
93
+
94
+ # message:: ModSpox::Messages::Incoming::Privmsg
95
+ # params:: empty | nick
96
+ # List statistics on self or given nick
97
+ def stats(message, params)
98
+ return unless message.is_public?
99
+ if(params[:nick])
100
+ nick = Helpers.find_model(params[:nick], false)
101
+ unless(nick)
102
+ reply(message.replyto, "\2Error:\2 Failed to find record of #{params[:nick]}")
103
+ return
104
+ end
105
+ else
106
+ nick = message.source
107
+ end
108
+ reply(message.replyto, "\2Roulette stats #{nick.nick}:\2 #{win_loss_ratio(nick, message.target)}% survival rate. Has won #{games_won(nick, message.target)} games and lost #{games_lost(nick, message.target)} games, taking a total of #{total_shots(nick, message.target)} shots.")
109
+ end
110
+
111
+ private
112
+
113
+ # nick:: ModSpox::Models::Nick
114
+ # channel:: ModSpox::Models::Channel
115
+ # Report win/loss ratio for nick
116
+ def win_loss_ratio(nick, channel)
117
+ if(games_lost(nick, channel) > 0)
118
+ val = (games_won(nick, channel).to_f / games_total(nick, channel).to_f) * 100
119
+ elsif(games_lost(nick, channel) == 0 && games_won(nick, channel) == 0)
120
+ val = 0
121
+ else
122
+ val = 100
123
+ end
124
+ return sprintf("%.2f", val)
125
+ end
126
+
127
+ # nick:: ModSpox::Models::Nick
128
+ # channel:: ModSpox::Models::Channel
129
+ # Return number of games nick has won
130
+ def games_won(nick, channel)
131
+ Info.left_outer_join(:games, :id => :game_id).filter('nick_id = ?', nick.pk).filter('channel_id = ?', channel.pk).filter('win = ?', true).count
132
+ end
133
+
134
+ # nick:: ModSpox::Models::Nick
135
+ # channel:: ModSpox::Models::Channel
136
+ # Return number of games nick has lost
137
+ def games_lost(nick, channel)
138
+ games_total(nick, channel) - games_won(nick, channel)
139
+ end
140
+
141
+ # nick:: ModSpox::Models::Nick
142
+ # channel:: ModSpox::Models::Channel
143
+ # Return number of games nick has played
144
+ def games_total(nick, channel)
145
+ Info.left_outer_join(:games, :id => :game_id).filter('nick_id = ?', nick.pk).filter('channel_id = ?', channel.pk).exclude(:game_id => game(channel).pk).count
146
+ end
147
+
148
+ # nick:: ModSpox::Models::Nick
149
+ # channel:: ModSpox::Models::Channel
150
+ # Return number of shots nick has taken
151
+ def total_shots(nick, channel)
152
+ v = Info.left_outer_join(:games, :id => :game_id).filter('nick_id = ?', nick.pk).filter('channel_id = ?', channel.pk).exclude(:game_id => game(channel).pk).sum(:infos__shots)
153
+ v = 0 unless v
154
+ return v
155
+ end
156
+
157
+ # nick:: ModSpox::Models::Nick
158
+ # channel:: ModSpox::Models::Channel
159
+ # Fire shot
160
+ def do_shot(nick, channel)
161
+ begin
162
+ shot(nick, channel)
163
+ reply(channel, "#{nick.nick}: *click*")
164
+ rescue Bullet => bang
165
+ game_over(nick, bang.game)
166
+ kill_nick(nick, channel)
167
+ end
168
+ end
169
+
170
+ # nick:: ModSpox::Models::Nick
171
+ # channel:: ModSpox::Models::Channel
172
+ # Commit suicide
173
+ def do_suicide(nick, channel)
174
+ begin
175
+ 6.times do
176
+ shot(nick, channel)
177
+ end
178
+ rescue Bullet => bang
179
+ game_over(nick, bang.game)
180
+ kill_nick(nick, channel)
181
+ end
182
+ end
183
+
184
+ def kill_nick(nick, channel)
185
+ unless(@banner.nil?)
186
+ begin
187
+ @banner.plugin.ban(nick, channel, 30, '*BANG*', true, false)
188
+ rescue Banner::NotOperator => boom
189
+ reply(channel, "#{nick.nick}: *BANG*")
190
+ rescue Object => boom
191
+ reply(channel, "#{nick.nick}: *BANG*")
192
+ Logger.warn("Error: Roulette ban generated an unexpected error: #{boom}")
193
+ end
194
+ else
195
+ reply(channel, "#{nick.nick}: *BANG*")
196
+ end
197
+ end
198
+
199
+ # channel:: ModSpox::Models::Channel
200
+ # Return current game
201
+ def game(channel)
202
+ @pipeline << Messages::Internal::PluginRequest.new(self, 'Banner') if @banner.nil?
203
+ game = Game.filter('shots > ?', 0).filter('channel_id = ?', channel.pk).first
204
+ unless(game)
205
+ chamber = rand(6) + 1
206
+ game = Game.new(:chamber => chamber, :shots => chamber, :channel_id => channel.pk)
207
+ game.save
208
+ end
209
+ return game
210
+ end
211
+
212
+ # nick:: ModSpox::Models::Nick
213
+ # channel:: ModSpox::Models::Channel
214
+ # Process shot
215
+ def shot(nick, channel)
216
+ cur_game = game(channel)
217
+ info = Info.find_or_create(:game_id => cur_game.pk, :nick_id => nick.pk)
218
+ info.update(:shots => info.shots + 1)
219
+ cur_game.update(:shots => cur_game.shots - 1)
220
+ raise Bullet.new(cur_game) if cur_game.shots < 1
221
+ end
222
+
223
+ # nick:: ModSpox::Models::Nick
224
+ # game:: Game
225
+ # Return number of games nick has won
226
+ def game_over(nick, game)
227
+ Info.filter(:game_id => game.pk).each do |info|
228
+ info.update(:win => true) unless info.nick_id == nick.pk
229
+ end
230
+ end
231
+
232
+ class Game < Sequel::Model
233
+ set_schema do
234
+ primary_key :id
235
+ timestamp :stamp, :null => false
236
+ integer :shots, :null => false, :default => 6
237
+ integer :chamber, :null => false, :default => 1
238
+ foreign_key :channel_id, :null => false, :table => :channels
239
+ end
240
+
241
+ many_to_one :channel, :class => ModSpox::Models::Channel
242
+
243
+ def before_create
244
+ self.stamp = Time.now
245
+ end
246
+ end
247
+
248
+ class Info < Sequel::Model
249
+ set_schema do
250
+ primary_key :id
251
+ integer :shots, :null => false, :default => 0
252
+ boolean :win, :null => false, :default => false
253
+ foreign_key :nick_id, :null => false, :table => :nicks
254
+ foreign_key :game_id, :null => false, :table => :games
255
+ end
256
+
257
+ many_to_one :nick, :class => ModSpox::Models::Nick
258
+ many_to_one :game, :class => Game
259
+ end
260
+
261
+ class Bullet < Exception
262
+ attr_reader :game
263
+ def initialize(game)
264
+ @game = game
265
+ end
266
+ end
267
+ end
@@ -0,0 +1,93 @@
1
+
2
+ require 'timeout'
3
+ class RubyCli < ModSpox::Plugin
4
+
5
+ include Models
6
+ include Messages::Outgoing
7
+
8
+ def initialize(pipeline)
9
+ super(pipeline)
10
+ ruby = Group.find_or_create(:name => 'ruby')
11
+ admin = Group.filter(:name => 'admin').first
12
+ add_sig(:sig => 'ruby (on|off)', :method => :set_channel, :group => admin, :desc => 'Add or remove channel from allowing ruby command', :params => [:action])
13
+ add_sig(:sig => 'ruby (?!on|off)(.+)', :method => :execute_ruby, :group => ruby, :desc => 'Execute ruby code', :params => [:code])
14
+ add_sig(:sig => 'rubyq (?!on|off)(.+)', :method => :quiet_ruby, :group => ruby, :params => [:code], :desc => 'Execute ruby quietly')
15
+ @channels = Setting.filter(:name => 'rubycli').first
16
+ @channels = @channels.nil? ? [] : @channels.value
17
+ end
18
+
19
+ def set_channel(message, params)
20
+ return unless message.is_public?
21
+ if(params[:action] == 'on')
22
+ unless(@channels.include?(message.target.pk))
23
+ @channels << message.target.pk
24
+ tmp = Setting.find_or_create(:name => 'rubycli')
25
+ tmp.value = @channels
26
+ tmp.save
27
+ end
28
+ information message.replyto, 'Ruby command now active'
29
+ else
30
+ unless(@channels.include?(message.target.pk))
31
+ warning message.replyto, 'Ruby command is not currently active in this channel'
32
+ else
33
+ @channels.delete(message.target.pk)
34
+ tmp = Setting.find_or_create(:name => 'rubycli')
35
+ tmp.value = @channels
36
+ tmp.save
37
+ information message.replyto, 'Ruby command is now disabled'
38
+ end
39
+ end
40
+ end
41
+
42
+ def quiet_ruby(message, params)
43
+ execute_ruby(message, params, true)
44
+ end
45
+
46
+ # we fork into a separate process for more control
47
+ # over untrusted code
48
+ def execute_ruby(message, params, shh=false)
49
+ return unless @channels.include?(message.target.pk)
50
+ rd, wr = IO.pipe
51
+ cid = Kernel.fork do
52
+ rd.close
53
+ result = nil
54
+ begin
55
+ result = lambda{$SAFE=4; eval(params[:code])}.call
56
+ rescue Object => boom
57
+ result = boom
58
+ ensure
59
+ wr.write [Marshal.dump(result)].pack('m')
60
+ end
61
+ end
62
+ if(cid)
63
+ Database.reset_connections
64
+ begin
65
+ result = nil
66
+ Timeout::timeout(5) do
67
+ wr.close
68
+ result = rd.read
69
+ rd.close
70
+ end
71
+ result = result.size > 0 ? Marshal.load(result.unpack('m')[0]) : ''
72
+ if(result.is_a?(Exception))
73
+ error message.replyto, "Exception generated: #{result.to_s.index(' for ').nil? ? result.to_s : result.to_s.slice(0..result.to_s.index(' for '))}"
74
+ else
75
+ result = result.to_s
76
+ reply message.replyto, "#{message.source.nick}: Your result has been truncated. Don't print so much." if result.size > 300
77
+ reply message.replyto, "#{shh ? '' : 'Result: '}#{result.slice(0..300)}"
78
+ end
79
+ rescue Timeout::Error
80
+ error message.replyto, 'Execution timeout reached.'
81
+ Logger.warn("Child process #{cid} to be killed")
82
+ Process.kill('KILL', cid)
83
+ Logger.warn("Child process #{cid} has been killed")
84
+ rescue Object => boom
85
+ error message.replyto, "Unknown error encountered: #{boom}"
86
+ ensure
87
+ Process.wait(cid, Process::WNOHANG)
88
+ Logger.info("RubyCli process has exited.")
89
+ end
90
+ end
91
+ end
92
+
93
+ end
@@ -0,0 +1,49 @@
1
+ require 'net/http'
2
+ require 'open-uri'
3
+ require 'cgi'
4
+ class Search < ModSpox::Plugin
5
+
6
+ include Messages::Outgoing
7
+
8
+ def initialize(pipeline)
9
+ super(pipeline)
10
+ add_sig(:sig => 'search count (.+)', :method => 'search_count', :params => [:terms], :desc => 'Show number of results for given search')
11
+ add_sig(:sig => 'search (?!count)(\d+)? ?(.+)', :method => 'search', :desc => 'Search the internet', :params => [:number, :terms])
12
+ end
13
+
14
+ def search(message, params)
15
+ limit = params[:number] ? params[:number].to_i : 1
16
+ limit = limit > 5 || limit < 1 ? 1 : limit
17
+ begin
18
+ resp = Net::HTTP.new('www.scroogle.org', 80).request_get("/cgi-bin/nbbw.cgi?Gw=#{CGI::escape(params[:terms])}")
19
+ resp.value
20
+ page = resp.body
21
+ results = []
22
+ page.scan(/<A Href="(.+?)">(.+?)<\/a>/) do |url,title|
23
+ title.gsub!(/<.*?>/, '')
24
+ title = CGI::unescapeHTML(title)
25
+ results.push [title, url]
26
+ end
27
+ output = []
28
+ results.slice(0, limit).each do |title, url|
29
+ output << "#{Helpers.convert_entities(title)} -> #{Helpers.tinyurl(url)} [#{url.scan(/^http:\/\/.+?\//)[0]}]"
30
+ end
31
+ output = output.empty? ? "No results for: \2#{params[:terms]}\2" : ["Search results for \2#{params[:terms]}:\2"] + output
32
+ reply message.replyto, output
33
+ rescue Object => boom
34
+ reply message.replyto, "Failed to find any results for: #{params[:terms]} Reason: #{boom}"
35
+ Logger.warn("Error: #{boom}\n#{boom.backtrace.join("\n")}")
36
+ end
37
+ end
38
+
39
+ def search_count(m, params)
40
+ buf = open("http://www.google.com/search?hl=en&q=#{CGI::escape(params[:terms])}", 'UserAgent' => 'mod_spox IRC bot').read
41
+ output = ''
42
+ if(buf =~ /of\s+about.+?([\d,]+)/)
43
+ output = "There are about \2#{$1}\2 results for the term \2#{params[:terms]}\2"
44
+ else
45
+ output = "There are no results found for the term \2#{params[:terms]}\2"
46
+ end
47
+ reply m.replyto, output
48
+ end
49
+ end
@@ -0,0 +1,150 @@
1
+ class Seen < ModSpox::Plugin
2
+ def initialize(pipe)
3
+ super
4
+ SeenLog.create_table unless SeenLog.table_exists?
5
+ @pipeline.hook(self, :log_privmsg, :Incoming_Privmsg)
6
+ @pipeline.hook(self, :log_join, :Incoming_Join)
7
+ @pipeline.hook(self, :log_part, :Incoming_Part)
8
+ @pipeline.hook(self, :log_quit, :Incoming_Quit)
9
+ @pipeline.hook(self, :log_kick, :Incoming_Kick)
10
+ @pipeline.hook(self, :log_privmsg, :Incoming_Notice)
11
+ @pipeline.hook(self, :log_outpriv, :Outgoing_Privmsg)
12
+ @pipeline.hook(self, :log_outpriv, :Outgoing_Notice)
13
+ add_sig(:sig => 'seen (\S+)', :method => :seen, :desc => 'Report last sighting of nick', :params => [:nick])
14
+ end
15
+
16
+ def seen(m, params)
17
+ nick = Models::Nick.filter(:nick => params[:nick]).first
18
+ log = SeenLog.filter(:nick_id => nick.pk).first if nick
19
+ if(nick && log)
20
+ message = "I last saw #{params[:nick]} on #{log.received} "
21
+ case log.type
22
+ when 'join'
23
+ message << "joining #{log.channel.name}"
24
+ when 'part'
25
+ message << "parting #{log.channel.name} "
26
+ message << "reason: #{log.message}" unless log.message.nil? || log.message.empty?
27
+ when 'privmsg'
28
+ message << "in #{log.channel.name} " unless log.channel.nil?
29
+ message << "saying #{log.message}" unless log.action
30
+ message << "doing: #{log.message}" if log.action
31
+ when 'notice'
32
+ message << "in #{log.channel.name} " unless log.channel.nil?
33
+ message << "sending notice: #{log.message}"
34
+ when 'kicking'
35
+ mes = log.message.dup
36
+ k = mes.slice!(0..mes.index('|')-1)
37
+ mes.slice!(0)
38
+ k = Models::Nick[k.to_i]
39
+ message << "kicking #{k.nick} from #{log.channel.name} (Reason: #{mes})"
40
+ when 'kicked'
41
+ mes = log.message.dup
42
+ k = mes.slice!(0..mes.index('|')-1)
43
+ mes.slice!(0)
44
+ k = Models::Nick[k.to_i]
45
+ message << "kicked from #{log.channel.name} by #{k.nick} (Reason: #{mes})"
46
+ end
47
+ information m.replyto, message
48
+ else
49
+ error m.replyto, "Failed to find record of given nick: #{params[:nick]}"
50
+ end
51
+ end
52
+
53
+ def log_outpriv(message)
54
+ type = message.instance_of?(Messages::Outgoing::Privmsg) ? 'privmsg' : 'notice'
55
+ target = message.target.is_a?(Sequel::Model) ? message.target : Helpers.find_model(message.target)
56
+ target = nil unless target.is_a?(Models::Channel)
57
+ log = get_log(me.pk)
58
+ log.action = message.is_action?
59
+ log.message = message.message
60
+ log.type = type
61
+ log.channel = target unless target.nil?
62
+ log.received = Time.now
63
+ log.save
64
+ end
65
+
66
+ def log_privmsg(message)
67
+ return unless message.source.is_a?(Models::Nick)
68
+ type = message.instance_of?(Messages::Incoming::Privmsg) ? 'privmsg' : 'notice'
69
+ target = message.target.is_a?(Sequel::Model) ? message.target : Helpers.find_model(message.target)
70
+ target = nil unless target.is_a?(Models::Channel)
71
+ log = get_log(message.source.pk)
72
+ log.action = message.is_action?
73
+ log.message = message.message
74
+ log.type = type
75
+ log.channel = target unless target.nil?
76
+ log.received = message.time
77
+ log.save
78
+ end
79
+
80
+ def log_join(message)
81
+ log = get_log(message.nick.pk)
82
+ log.action = false
83
+ log.message = nil
84
+ log.type = 'join'
85
+ log.channel = message.channel
86
+ log.received = message.time
87
+ log.save
88
+ end
89
+
90
+ def log_part(message)
91
+ log = get_log(message.nick.pk)
92
+ log.action = false
93
+ log.type = 'part'
94
+ log.message = message.reason
95
+ log.channel = message.channel
96
+ log.received = message.time
97
+ log.save
98
+ end
99
+
100
+ def log_quit(message)
101
+ log = get_log(message.nick.pk)
102
+ log.action = false
103
+ log.type = 'quit'
104
+ log.message = message.message
105
+ log.channel = nil
106
+ log.received = message.time
107
+ log.save
108
+ end
109
+
110
+ def log_kick(message)
111
+ # log kicker
112
+ log = get_log(message.kicker.pk)
113
+ log.action = false
114
+ log.type = 'kicking'
115
+ log.channel = message.channel
116
+ log.received = message.time
117
+ log.message = "#{message.kickee.pk}|#{message.reason}"
118
+ log.save
119
+ # log kickee
120
+ log = get_log(message.kickee.pk)
121
+ log.action = false
122
+ log.type = 'kicked'
123
+ log.channel = message.channel
124
+ log.received = message.time
125
+ log.message = "#{message.kicker.pk}|#{message.reason}"
126
+ log.save
127
+ end
128
+
129
+ private
130
+
131
+ def get_log(pk)
132
+ log = SeenLog.filter(:nick_id => pk).first
133
+ log = SeenLog.new(:nick_id => pk) unless log
134
+ return log
135
+ end
136
+
137
+ class SeenLog < Sequel::Model
138
+ set_schema do
139
+ foreign_key :nick_id, :table => :nicks, :null => false
140
+ foreign_key :channel_id, :table => :channels
141
+ varchar :type, :default => 'privmsg'
142
+ timestamp :received, :null => false
143
+ boolean :action, :null => false, :default => true
144
+ text :message
145
+ primary_key :nick_id
146
+ end
147
+ many_to_one :nick, :class => ModSpox::Models::Nick
148
+ many_to_one :channel, :class => ModSpox::Models::Channel
149
+ end
150
+ end
@@ -0,0 +1,35 @@
1
+ require 'rexml/document'
2
+ require 'open-uri'
3
+
4
+ class Slashdot < ModSpox::Plugin
5
+
6
+ def initialize(pipeline)
7
+ begin
8
+ require 'htmlentities'
9
+ rescue Object => boom
10
+ Logger.warn('Error: This plugin requires the HTMLEntities gem. Please install and reload plugin.')
11
+ raise Exceptions::BotException.new("Missing required HTMLEntities library")
12
+ end
13
+ super
14
+ add_sig(:sig => '(slashdot|\/\.) ?(\d+)?', :method => 'show_slashdot', :desc => 'Slashdot headlines', :params => [:trig, :num])
15
+ @coder = HTMLEntities.new
16
+ end
17
+
18
+ def show_slashdot(message, params)
19
+ src = open('http://rss.slashdot.org/Slashdot/slashdot')
20
+ doc = REXML::Document.new(src.read)
21
+ num = params[:num].nil? || params[:num].to_i < 1 ? 1 : params[:num].to_i
22
+ num = 5 if num > 5
23
+ output = []
24
+ doc.elements.each('rdf:RDF/item') do |item|
25
+ num -= 1
26
+ title = CGI::unescapeHTML(item.elements['title'].text)
27
+ title = title.gsub(/<.+?>/, ' ').gsub(/[\r\n]/, '').gsub(/\s+/, ' ')
28
+ title = @coder.decode(title)
29
+ output << "\2/.\2 #{title.strip} \2->\2 #{Helpers.tinyurl(item.elements['link'].text)}"
30
+ break if num < 1
31
+ end
32
+ reply message.replyto, output
33
+ end
34
+
35
+ end