mod_spox 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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