mod_spox 0.2.0 → 0.3.0

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 (145) hide show
  1. data/CHANGELOG +31 -1
  2. data/LICENSE +674 -0
  3. data/README.rdoc +73 -0
  4. data/bin/mod_spox +28 -28
  5. data/data/mod_spox/extras/AOLSpeak.rb +2 -3
  6. data/data/mod_spox/extras/AutoKick.rb +10 -23
  7. data/data/mod_spox/extras/AutoMode.rb +12 -23
  8. data/data/mod_spox/extras/Bash.rb +55 -0
  9. data/data/mod_spox/extras/Bouncer.rb +85 -57
  10. data/data/mod_spox/extras/Bullshit.rb +1 -1
  11. data/data/mod_spox/extras/Bytes.rb +1 -2
  12. data/data/mod_spox/extras/Confess.rb +27 -29
  13. data/data/mod_spox/extras/DCC.rb +11 -20
  14. data/data/mod_spox/extras/DevWatch.rb +21 -23
  15. data/data/mod_spox/extras/DownForEveryoneOrJustMe.rb +47 -0
  16. data/data/mod_spox/extras/EightBall.rb +1 -1
  17. data/data/mod_spox/extras/FML.rb +35 -0
  18. data/data/mod_spox/extras/Headers.rb +31 -50
  19. data/data/mod_spox/extras/Karma.rb +81 -29
  20. data/data/mod_spox/extras/Logger.rb +2 -2
  21. data/data/mod_spox/extras/LolSpeak.rb +1 -2
  22. data/data/mod_spox/extras/PhpCli.rb +138 -8
  23. data/data/mod_spox/extras/PhpFuncLookup.rb +20 -23
  24. data/data/mod_spox/extras/Pinger.rb +1 -1
  25. data/data/mod_spox/extras/Quotes.rb +8 -10
  26. data/data/mod_spox/extras/RegexTracker.rb +2 -4
  27. data/data/mod_spox/extras/Roulette.rb +20 -27
  28. data/data/mod_spox/extras/RubyCli.rb +93 -0
  29. data/data/mod_spox/extras/Search.rb +17 -3
  30. data/data/mod_spox/extras/Seen.rb +150 -0
  31. data/data/mod_spox/extras/SlashdotHeadlineGenerator.rb +500 -0
  32. data/data/mod_spox/extras/Talk.rb +2 -4
  33. data/data/mod_spox/extras/Topten.rb +10 -12
  34. data/data/mod_spox/extras/TracTicket.rb +3 -5
  35. data/data/mod_spox/extras/Translate.rb +20 -22
  36. data/data/mod_spox/extras/Twitter.rb +118 -33
  37. data/data/mod_spox/extras/UrbanDictionary.rb +8 -17
  38. data/data/mod_spox/extras/Weather.rb +1 -2
  39. data/data/mod_spox/plugins/Authenticator.rb +93 -98
  40. data/data/mod_spox/plugins/Banner.rb +26 -56
  41. data/data/mod_spox/plugins/Helper.rb +5 -6
  42. data/data/mod_spox/plugins/Initializer.rb +4 -14
  43. data/data/mod_spox/plugins/Joiner.rb +1 -1
  44. data/data/mod_spox/plugins/Nicker.rb +13 -0
  45. data/data/mod_spox/plugins/Parter.rb +2 -2
  46. data/data/mod_spox/plugins/Permissions.rb +60 -0
  47. data/data/mod_spox/plugins/PluginLoader.rb +7 -12
  48. data/data/mod_spox/plugins/Ponger.rb +51 -0
  49. data/data/mod_spox/plugins/Quitter.rb +1 -2
  50. data/data/mod_spox/plugins/Servers.rb +57 -0
  51. data/data/mod_spox/plugins/Status.rb +3 -2
  52. data/data/mod_spox/plugins/Triggers.rb +9 -9
  53. data/lib/mod_spox/Bot.rb +109 -33
  54. data/lib/mod_spox/BotConfig.rb +2 -2
  55. data/lib/mod_spox/ConfigurationWizard.rb +12 -12
  56. data/lib/mod_spox/Database.rb +1 -4
  57. data/lib/mod_spox/Exceptions.rb +26 -0
  58. data/lib/mod_spox/Helpers.rb +29 -68
  59. data/lib/mod_spox/Loader.rb +23 -24
  60. data/lib/mod_spox/Logger.rb +19 -17
  61. data/lib/mod_spox/MessageFactory.rb +50 -24
  62. data/lib/mod_spox/Pipeline.rb +21 -7
  63. data/lib/mod_spox/Plugin.rb +27 -3
  64. data/lib/mod_spox/PluginManager.rb +28 -15
  65. data/lib/mod_spox/PriorityQueue.rb +69 -0
  66. data/lib/mod_spox/Socket.rb +93 -51
  67. data/lib/mod_spox/Sockets.rb +76 -63
  68. data/lib/mod_spox/Timer.rb +21 -141
  69. data/lib/mod_spox/Version.rb +14 -0
  70. data/lib/mod_spox/handlers/BadNick.rb +1 -1
  71. data/lib/mod_spox/handlers/Bounce.rb +5 -5
  72. data/lib/mod_spox/handlers/Created.rb +13 -5
  73. data/lib/mod_spox/handlers/Handler.rb +12 -3
  74. data/lib/mod_spox/handlers/Invite.rb +14 -8
  75. data/lib/mod_spox/handlers/Join.rb +24 -20
  76. data/lib/mod_spox/handlers/Kick.rb +22 -13
  77. data/lib/mod_spox/handlers/Mode.rb +42 -36
  78. data/lib/mod_spox/handlers/Motd.rb +4 -0
  79. data/lib/mod_spox/handlers/Names.rb +66 -39
  80. data/lib/mod_spox/handlers/Nick.rb +20 -14
  81. data/lib/mod_spox/handlers/Part.rb +25 -8
  82. data/lib/mod_spox/handlers/Ping.rb +11 -5
  83. data/lib/mod_spox/handlers/Pong.rb +9 -5
  84. data/lib/mod_spox/handlers/Privmsg.rb +25 -17
  85. data/lib/mod_spox/handlers/Quit.rb +13 -8
  86. data/lib/mod_spox/handlers/Topic.rb +4 -0
  87. data/lib/mod_spox/handlers/Welcome.rb +16 -24
  88. data/lib/mod_spox/handlers/Who.rb +64 -48
  89. data/lib/mod_spox/handlers/Whois.rb +92 -60
  90. data/lib/mod_spox/messages/incoming/Nick.rb +2 -2
  91. data/lib/mod_spox/messages/incoming/Privmsg.rb +1 -1
  92. data/lib/mod_spox/messages/incoming/Whois.rb +1 -0
  93. data/lib/mod_spox/messages/internal/EstablishConnection.rb +1 -1
  94. data/lib/mod_spox/messages/internal/PluginsReady.rb +10 -0
  95. data/lib/mod_spox/messages/internal/QueueSocket.rb +8 -0
  96. data/lib/mod_spox/messages/internal/Reconnect.rb +8 -0
  97. data/lib/mod_spox/messages/internal/UnqueueSocket.rb +8 -0
  98. data/lib/mod_spox/migrations/002_persistent_sigs.rb +14 -0
  99. data/lib/mod_spox/migrations/003_auth_restructure.rb +31 -0
  100. data/lib/mod_spox/migrations/004_mode_index_fix.rb +18 -0
  101. data/lib/mod_spox/migrations/005_nick_mode_nopark.rb +18 -0
  102. data/lib/mod_spox/models/Auth.rb +16 -46
  103. data/lib/mod_spox/models/AuthMask.rb +13 -0
  104. data/lib/mod_spox/models/Channel.rb +46 -27
  105. data/lib/mod_spox/models/Config.rb +10 -19
  106. data/lib/mod_spox/models/Group.rb +20 -8
  107. data/lib/mod_spox/models/Models.rb +1 -1
  108. data/lib/mod_spox/models/Nick.rb +105 -113
  109. data/lib/mod_spox/models/NickMode.rb +23 -9
  110. data/lib/mod_spox/models/Server.rb +12 -1
  111. data/lib/mod_spox/models/Setting.rb +12 -16
  112. data/lib/mod_spox/models/Signature.rb +28 -8
  113. data/tests/BotHolder.rb +24 -0
  114. data/tests/handlers/tc_BadNick.rb +21 -0
  115. data/tests/handlers/tc_Created.rb +24 -0
  116. data/tests/handlers/tc_Invite.rb +50 -0
  117. data/tests/handlers/tc_Join.rb +33 -0
  118. data/tests/handlers/tc_Kick.rb +32 -0
  119. data/tests/handlers/tc_Mode.rb +85 -0
  120. data/tests/handlers/tc_Names.rb +35 -0
  121. data/tests/handlers/tc_Nick.rb +55 -0
  122. data/tests/handlers/tc_Part.rb +44 -0
  123. data/tests/handlers/tc_Ping.rb +40 -0
  124. data/tests/handlers/tc_Pong.rb +28 -0
  125. data/tests/handlers/tc_Privmsg.rb +85 -0
  126. data/tests/handlers/tc_Quit.rb +40 -0
  127. data/tests/handlers/tc_Who.rb +50 -0
  128. data/tests/handlers/tc_Whois.rb +61 -0
  129. data/tests/models/tc_Auth.rb +34 -0
  130. data/tests/models/tc_Channel.rb +52 -0
  131. data/tests/models/tc_Config.rb +19 -0
  132. data/tests/models/tc_Nick.rb +142 -0
  133. data/tests/models/tc_NickMode.rb +40 -0
  134. data/tests/models/tc_Setting.rb +21 -0
  135. data/tests/models/tc_Signature.rb +14 -0
  136. data/tests/run_tests.rb +4 -0
  137. metadata +284 -212
  138. data/README +0 -36
  139. data/lib/mod_spox/Cache.rb +0 -57
  140. data/lib/mod_spox/Monitors.rb +0 -84
  141. data/lib/mod_spox/Pool.rb +0 -164
  142. data/lib/mod_spox/models/AuthGroup.rb +0 -16
  143. data/lib/mod_spox/models/ChannelMode.rb +0 -14
  144. data/lib/mod_spox/models/NickChannel.rb +0 -45
  145. data/lib/mod_spox/models/NickGroup.rb +0 -16
@@ -2,7 +2,7 @@ class Pinger < ModSpox::Plugin
2
2
 
3
3
  def initialize(pipeline)
4
4
  super(pipeline)
5
- Models::Signature.find_or_create(:signature => 'ping', :plugin => name, :method => 'ping')
5
+ add_sig(:sig => 'ping', :method => :ping)
6
6
  end
7
7
 
8
8
  def ping(message, params)
@@ -6,14 +6,10 @@ class Quotes < ModSpox::Plugin
6
6
  super
7
7
  Quote.create_table unless Quote.table_exists?
8
8
  group = Group.find_or_create(:name => 'quote')
9
- Signature.find_or_create(:signature => 'quote ?(.+)?', :plugin => name, :method => 'quote',
10
- :description => 'Display random quote, random quote containing search term, or quote with given ID').params = [:term]
11
- Signature.find_or_create(:signature => 'addquote (.+)', :plugin => name, :method => 'addquote',
12
- :description => 'Add a new quote').params = [:quote]
13
- Signature.find_or_create(:signature => 'searchquote (.+)', :plugin => name, :method => 'searchquote',
14
- :description => 'Return IDs of quotes matching term').params = [:term]
15
- Signature.find_or_create(:signature => 'delquote (\d+)', :plugin => name, :method => 'delquote', :group_id => group.pk,
16
- :description => 'Delete quote with given ID').params = [:id]
9
+ add_sig(:sig => 'quote ?(.+)?', :method => :quote, :desc => 'Display random quote, random quote containing search term, or quote with given ID', :params => [:term])
10
+ add_sig(:sig => 'addquote (.+)', :method => :addquote, :desc => 'Add a new quote', :params => [:quote])
11
+ add_sig(:sig => 'searchquote (.+)', :method => :searchquote, :desc => 'Return IDs of quotes matching term', :params => [:term])
12
+ add_sig(:sig => 'delquote (\d+)', :method => :delquote, :group => group, :desc => 'Delete quote with given ID', :params => [:id])
17
13
  end
18
14
 
19
15
  def quote(message, params)
@@ -48,7 +44,7 @@ class Quotes < ModSpox::Plugin
48
44
 
49
45
  def searchquote(message, params)
50
46
  result = Quote.filter(:quote => Regexp.new(params[:term], Regexp::IGNORECASE))
51
- if(result.size > 0)
47
+ if(result.count > 0)
52
48
  ids = result.map(:id)
53
49
  ids.sort!
54
50
  ids = ids.slice(0, 20)
@@ -60,7 +56,7 @@ class Quotes < ModSpox::Plugin
60
56
 
61
57
  def delquote(message, params)
62
58
  result = Quote.filter(:id => params[:id].to_i)
63
- if(result.size < 1)
59
+ if(result.count < 1)
64
60
  reply message.replyto, "\2Error:\2 Failed to find quote with ID: #{params[:id]}"
65
61
  else
66
62
  result.destroy
@@ -76,6 +72,8 @@ class Quotes < ModSpox::Plugin
76
72
  foreign_key :nick_id, :table => :nicks
77
73
  foreign_key :channel_id, :table => :channels
78
74
  end
75
+ many_to_one :nick, :class => ModSpox::Models::Nick
76
+ many_to_one :channel, :class => ModSpox::Models::Channel
79
77
  end
80
78
 
81
79
  end
@@ -137,10 +137,8 @@ class RegexTracker < ModSpox::Plugin
137
137
  foreign_key :channel_id, :table => :channels, :null => false
138
138
  index [:regex, :channel_id], :unique => true
139
139
  end
140
-
141
- def channel
142
- Channel[channel_id]
143
- end
140
+
141
+ many_to_one :channel, :class => ModSpox::Models::Channel
144
142
 
145
143
  def channel=(chan)
146
144
  raise Exceptions::InvalidType.new('Channel model was expected') unless chan.is_a?(Models::Channel)
@@ -4,12 +4,12 @@ class Roulette < ModSpox::Plugin
4
4
 
5
5
  def initialize(pipeline)
6
6
  super(pipeline)
7
- Signature.find_or_create(:signature => 'roulette', :plugin => name, :method => 'roulette', :requirement => 'public')
8
- Signature.find_or_create(:signature => 'suicide', :plugin => name, :method => 'suicide', :requirement => 'public')
9
- Signature.find_or_create(:signature => 'shoot (\S+)', :plugin => name, :method => 'shoot', :requirement => 'public').params = [:nick]
10
- Signature.find_or_create(:signature => 'roulette topten', :plugin => name, :method => 'topten', :requirement => 'public')
11
- Signature.find_or_create(:signature => 'roulette stats ?(\S+)?', :plugin => name, :method => 'stats', :requirement => 'public').params = [:nick]
12
- Signature.find_or_create(:signature => 'roulette chambers', :plugin => name, :method => 'chambers', :requirement => 'public')
7
+ add_sig(:sig => 'roulette', :method => :roulette, :req => 'public')
8
+ add_sig(:sig => 'suicide', :method => :suicide, :req => 'public')
9
+ add_sig(:sig => 'shoot (\S+)', :method => :shoot, :req => 'public', :params => [:nick])
10
+ add_sig(:sig => 'roulette topten', :method => :topten, :req => 'public')
11
+ add_sig(:sig => 'roulette stats ?(\S+)?', :method => :stats, :req => 'public', :params => [:nick])
12
+ add_sig(:sig => 'roulette chambers', :method => :chambers, :req => 'public')
13
13
  Game.create_table unless Game.table_exists?
14
14
  Info.create_table unless Info.table_exists?
15
15
  @banner = nil
@@ -20,7 +20,7 @@ class Roulette < ModSpox::Plugin
20
20
  # Display chamber statistics
21
21
  def chambers(m, p)
22
22
  total = Game.all.size
23
- result = Game.group(:chamber).select(:chamber, :COUNT[:chamber] => :total).reverse_order(:total)
23
+ result = Game.group(:chamber).select(:chamber, 'COUNT(chamber) as total'.lit).reverse_order(:total)
24
24
  if(result)
25
25
  output = []
26
26
  result.each do |res|
@@ -75,8 +75,8 @@ class Roulette < ModSpox::Plugin
75
75
  def topten(message, params)
76
76
  return unless message.is_public?
77
77
  ds = Database.db[:infos].left_outer_join(:games, :id => :game_id)
78
- ds.select!(:nick_id, :COUNT[:win] => :wins).where!(:channel_id => message.target.pk, :win => true).group!(:nick_id).reverse_order!(:wins).limit!(10)
79
- ids = ds.map(:nick_id)
78
+ 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)
79
+ ids = res.map(:nick_id)
80
80
  top = []
81
81
  ids.each do |id|
82
82
  nick = Nick[id]
@@ -126,7 +126,7 @@ class Roulette < ModSpox::Plugin
126
126
  # channel:: ModSpox::Models::Channel
127
127
  # Return number of games nick has won
128
128
  def games_won(nick, channel)
129
- Info.left_outer_join(:games, :id => :game_id).filter('nick_id = ?', nick.pk).filter('channel_id = ?', channel.pk).filter('win = ?', true).size
129
+ Info.left_outer_join(:games, :id => :game_id).filter('nick_id = ?', nick.pk).filter('channel_id = ?', channel.pk).filter('win = ?', true).count
130
130
  end
131
131
 
132
132
  # nick:: ModSpox::Models::Nick
@@ -140,7 +140,7 @@ class Roulette < ModSpox::Plugin
140
140
  # channel:: ModSpox::Models::Channel
141
141
  # Return number of games nick has played
142
142
  def games_total(nick, channel)
143
- Info.left_outer_join(:games, :id => :game_id).filter('nick_id = ?', nick.pk).filter('channel_id = ?', channel.pk).exclude(:game_id => game(channel).pk).size
143
+ 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
144
144
  end
145
145
 
146
146
  # nick:: ModSpox::Models::Nick
@@ -213,8 +213,8 @@ class Roulette < ModSpox::Plugin
213
213
  def shot(nick, channel)
214
214
  cur_game = game(channel)
215
215
  info = Info.find_or_create(:game_id => cur_game.pk, :nick_id => nick.pk)
216
- info.update_with_params(:shots => info.shots + 1)
217
- cur_game.update_with_params(:shots => cur_game.shots - 1)
216
+ info.update(:shots => info.shots + 1)
217
+ cur_game.update(:shots => cur_game.shots - 1)
218
218
  raise Bullet.new(cur_game) if cur_game.shots < 1
219
219
  end
220
220
 
@@ -223,7 +223,7 @@ class Roulette < ModSpox::Plugin
223
223
  # Return number of games nick has won
224
224
  def game_over(nick, game)
225
225
  Info.filter(:game_id => game.pk).each do |info|
226
- info.update_with_params(:win => true) unless info.nick_id == nick.pk
226
+ info.update(:win => true) unless info.nick_id == nick.pk
227
227
  end
228
228
  end
229
229
 
@@ -236,12 +236,10 @@ class Roulette < ModSpox::Plugin
236
236
  foreign_key :channel_id, :null => false, :table => :channels
237
237
  end
238
238
 
239
- before_create do
240
- self.stamp = Time.now
241
- end
239
+ many_to_one :channel, :class => ModSpox::Models::Channel
242
240
 
243
- def channel
244
- Models::Channel[channel_id]
241
+ def before_create
242
+ self.stamp = Time.now
245
243
  end
246
244
  end
247
245
 
@@ -253,14 +251,9 @@ class Roulette < ModSpox::Plugin
253
251
  foreign_key :nick_id, :null => false, :table => :nicks
254
252
  foreign_key :game_id, :null => false, :table => :games
255
253
  end
256
-
257
- def nick
258
- Models::Nick[nick_id]
259
- end
260
-
261
- def game
262
- Models::Game[game_id]
263
- end
254
+
255
+ many_to_one :nick, :class => ModSpox::Models::Nick
256
+ many_to_one :game, :class => Game
264
257
  end
265
258
 
266
259
  class Bullet < Exception
@@ -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 => 'php')
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
@@ -1,4 +1,5 @@
1
1
  require 'net/http'
2
+ require 'open-uri'
2
3
  require 'cgi'
3
4
  class Search < ModSpox::Plugin
4
5
 
@@ -6,7 +7,8 @@ class Search < ModSpox::Plugin
6
7
 
7
8
  def initialize(pipeline)
8
9
  super(pipeline)
9
- Models::Signature.find_or_create(:signature => 'search (\d+)? ?(.+)', :plugin => name, :method => 'search', :description => 'Search the internet').params = [:number, :terms]
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])
10
12
  end
11
13
 
12
14
  def search(message, params)
@@ -22,14 +24,26 @@ class Search < ModSpox::Plugin
22
24
  title = CGI::unescapeHTML(title)
23
25
  results.push [title, url]
24
26
  end
25
- output = ["Search results for \2#{params[:terms]}:\2"]
27
+ output = []
26
28
  results.slice(0, limit).each do |title, url|
27
- output << "#{title} -> #{Helpers.tinyurl(url)} [#{url.scan(/^http:\/\/.+?\//)[0]}]"
29
+ output << "#{Helpers.convert_entities(title)} -> #{Helpers.tinyurl(url)} [#{url.scan(/^http:\/\/.+?\//)[0]}]"
28
30
  end
31
+ output = output.empty? ? "No results for: \2#{params[:terms]}\2" : ["Search results for \2#{params[:terms]}:\2"] + output
29
32
  reply message.replyto, output
30
33
  rescue Object => boom
31
34
  @pipeline << Privmsg.new(message.replyto, "Failed to find any results for: #{params[:terms]} Reason: #{boom}")
32
35
  Logger.warn("Error: #{boom}\n#{boom.backtrace.join("\n")}")
33
36
  end
34
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
35
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