mod_spox 0.0.2 → 0.0.3
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.
- data/CHANGELOG +1 -1
- data/README +6 -2
- data/bin/mod_spox +15 -9
- data/data/mod_spox/extras/AOLSpeak.rb +271 -0
- data/data/mod_spox/extras/AutoKick.rb +119 -0
- data/data/mod_spox/extras/AutoRejoin.rb +14 -0
- data/data/mod_spox/extras/Bullshit.rb +19 -0
- data/data/mod_spox/extras/Confess.rb +166 -0
- data/data/mod_spox/extras/DevWatch.rb +154 -0
- data/data/mod_spox/extras/EightBall.rb +31 -0
- data/data/mod_spox/extras/Headers.rb +50 -0
- data/data/mod_spox/extras/Karma.rb +16 -17
- data/data/mod_spox/extras/LolSpeak.rb +22 -0
- data/data/mod_spox/extras/PhpCli.rb +146 -0
- data/data/mod_spox/extras/PhpFuncLookup.rb +261 -0
- data/data/mod_spox/extras/Quotes.rb +80 -0
- data/data/mod_spox/extras/Roulette.rb +24 -3
- data/data/mod_spox/extras/Talk.rb +41 -0
- data/data/mod_spox/extras/Translate.rb +95 -0
- data/data/mod_spox/extras/Weather.rb +55 -0
- data/data/mod_spox/plugins/Authenticator.rb +12 -0
- data/data/mod_spox/plugins/Banner.rb +3 -3
- data/data/mod_spox/plugins/Helper.rb +37 -0
- data/lib/mod_spox/Bot.rb +1 -1
- data/lib/mod_spox/ConfigurationWizard.rb +12 -5
- data/lib/mod_spox/MessageFactory.rb +1 -2
- data/lib/mod_spox/Monitors.rb +26 -8
- data/lib/mod_spox/Pipeline.rb +13 -13
- data/lib/mod_spox/PluginManager.rb +12 -1
- data/lib/mod_spox/Pool.rb +212 -29
- data/lib/mod_spox/Socket.rb +6 -6
- data/lib/mod_spox/Timer.rb +6 -8
- data/lib/mod_spox/handlers/Handler.rb +1 -1
- data/lib/mod_spox/handlers/Privmsg.rb +1 -0
- data/lib/mod_spox/handlers/Who.rb +1 -0
- data/lib/mod_spox/messages/internal/PluginRequest.rb +1 -1
- data/lib/mod_spox/messages/outgoing/Privmsg.rb +9 -1
- data/lib/mod_spox/models/Setting.rb +3 -3
- data/lib/mod_spox/models/Signature.rb +1 -1
- metadata +18 -20
@@ -0,0 +1,261 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
# Inspired from an old plugin for the original mod_spox
|
4
|
+
# Original development: spox & Ryan "pizza_milkshake" Flynn
|
5
|
+
# Ported: 2008
|
6
|
+
|
7
|
+
class PhpFuncLookup < ModSpox::Plugin
|
8
|
+
|
9
|
+
include Models
|
10
|
+
|
11
|
+
def initialize(pipeline)
|
12
|
+
super(pipeline)
|
13
|
+
setup_setting
|
14
|
+
@path = Setting[:phpfunc][:directory]
|
15
|
+
@trigger = Setting[:phpfunc][:trigger]
|
16
|
+
@manual = "#{@path}/html"
|
17
|
+
@classlist = []
|
18
|
+
fetch_manual unless File.exists?("#{@path}/manual.tar.gz")
|
19
|
+
@ops = {
|
20
|
+
"-" => [ "arithmetic", "Subtraction or Negation", "3 - 2 == 1" ],
|
21
|
+
"+" => [ "arithmetic", "Addition", "3 + 2 == 5" ],
|
22
|
+
"*" => [ "arithmetic", "Multiplication", "3 * 2 == 6" ],
|
23
|
+
"/" => [ "arithmetic", "Division", "3 / 2 == 1.5" ],
|
24
|
+
"%" => [ "arithmetic", "Modulus", "3 % 2 == 1" ],
|
25
|
+
"=" => [ "assignment", "Assignment", "$foo = 1; -> $foo == 1" ],
|
26
|
+
"&" => [
|
27
|
+
[ "bitwise", "references" ],
|
28
|
+
[ "Bitwise And", "Reference" ],
|
29
|
+
[ "0x3 & 0x1 -> 1", "$foo=1; $bar=&$foo; $bar++; -> $foo == 2" ]
|
30
|
+
],
|
31
|
+
"|" => [ "bitwise", "Bitwise Or", "" ],
|
32
|
+
"^" => [ "bitwise", "Bitwise Xor", "" ],
|
33
|
+
"~" => [ "bitwise", "Bitwise Not", "" ],
|
34
|
+
"<<" => [ "bitwise", "Bitwise Shift left", "" ],
|
35
|
+
">>" => [ "bitwise", "Bitwise Shift right", "" ],
|
36
|
+
"==" => [ "comparison", "Equal", "" ],
|
37
|
+
"===" => [ "comparison", "Identical", "" ],
|
38
|
+
"!=" => [ "comparison", "Not Equal", "" ],
|
39
|
+
"<>" => [ "comparison", "Not Equal", "" ],
|
40
|
+
"!==" => [ "comparison", "Not Identical", "" ],
|
41
|
+
"<" => [ "comparison", "Less Than", "" ],
|
42
|
+
">" => [ "comparison", "Greater Than", "" ],
|
43
|
+
"<=" => [ "comparison", "Less Than Or Equal To", "" ],
|
44
|
+
">=" => [ "comparison", "Greater Than Or Equal To", "" ],
|
45
|
+
"@" => [ "errorcontrol","Error Control", "" ],
|
46
|
+
"`" => [ "execution", "Execution", "" ],
|
47
|
+
"++" => [ "increment", "Pre- or Post-Increment", "" ],
|
48
|
+
"--" => [ "increment", "Pre- or Post-Decrement", "" ],
|
49
|
+
"and" => [ "logical", "And", "" ],
|
50
|
+
"or" => [ "logical", "Or", "" ],
|
51
|
+
"xor" => [ "logical", "Xor", "" ],
|
52
|
+
"!" => [ "logical", "Not", "" ],
|
53
|
+
"&&" => [ "logical", "And", "" ],
|
54
|
+
"||" => [ "logical", "Or", "" ],
|
55
|
+
"." => [ "string", "Concatenation", "" ],
|
56
|
+
".=" => [ "string", "Concatenation Assignment", "" ],
|
57
|
+
"instanceof" => [ "type", "Instance Of", "" ],
|
58
|
+
"new" => [ "", "New Object", "" ],
|
59
|
+
"+=" => [ "assignment", "Addition Assignment", "" ],
|
60
|
+
"-=" => [ "assignment", "Subtraction Assignment", "" ],
|
61
|
+
"/=" => [ "assignment", "Division Assignment", "" ],
|
62
|
+
"*=" => [ "assignment", "Multiplication Assignment", "" ],
|
63
|
+
"%=" => [ "assignment", "Modulus Assignment", "" ],
|
64
|
+
"->" => [ "?", "Object member accessor thingy","" ],
|
65
|
+
}
|
66
|
+
admin = Group.filter(:name => 'admin').first
|
67
|
+
Signature.find_or_create(:signature => 'pfunc (\S+)', :plugin => name, :method => 'phpfunc', :description => 'Lookup PHP function').params = [:name]
|
68
|
+
Signature.find_or_create(:signature => 'fetch php manual', :plugin => name, :method => 'fetch', :group_id => admin.pk,
|
69
|
+
:description => 'Download and extract PHP manual')
|
70
|
+
Signature.find_or_create(:signature => 'pfunc trigger (\S+)', :plugin => name, :method => 'set_trigger', :group_id => admin.pk,
|
71
|
+
:description => 'Set the trigger for auto-lookups').params = [:trigger]
|
72
|
+
Signature.find_or_create(:signature => 'pfunc show trigger', :plugin => name, :method => 'show_trigger', :description => 'Show current trigger')
|
73
|
+
Signature.find_or_create(:signature => 'pfunc (add|remove) (\S+)', :plugin => name, :method => 'set_channels', :group_id => admin.pk,
|
74
|
+
:description => 'Add or remove channels from auto-lookups').params = [:action, :channel]
|
75
|
+
Signature.find_or_create(:signature => 'pfunc show channels', :plugin => name, :method => 'list_channels', :description => 'Show channels with auto lookup enabled')
|
76
|
+
@pipeline.hook(self, :listen, :Incoming_Privmsg)
|
77
|
+
populate_classes
|
78
|
+
end
|
79
|
+
|
80
|
+
def phpfunc(m, params)
|
81
|
+
name = params[:name].downcase
|
82
|
+
Logger.log "phpfunc name=#{name}"
|
83
|
+
if name =~ /^\S+$/ && name =~ /\*/
|
84
|
+
parse_wildcard(m, name)
|
85
|
+
elsif name =~ /^\$/
|
86
|
+
parse_predefined(m, name)
|
87
|
+
elsif name =~ /^\S+$/ && filename = find_file(name)
|
88
|
+
parse_function(m, name, filename)
|
89
|
+
elsif @ops.has_key?(name)
|
90
|
+
parse_operator(m, name)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def fetch(m, params)
|
95
|
+
reply m.replyto, "Fetching PHP manual (This could take a few minutes)"
|
96
|
+
fetch_manual
|
97
|
+
end
|
98
|
+
|
99
|
+
def listen(m)
|
100
|
+
if(m.target.is_a?(Channel) && Setting[:phpfunc][:channels].include?(m.target.pk))
|
101
|
+
if m.message =~ /^#{Regexp.escape(@trigger)}(\S+)$/
|
102
|
+
phpfunc(m, {:name => $1})
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def set_trigger(message, params)
|
108
|
+
vals = Setting[:phpfunc]
|
109
|
+
vals[:trigger] = params[:trigger]
|
110
|
+
Setting.filter(:name => 'phpfunc').first.value = vals
|
111
|
+
@trigger = params[:trigger]
|
112
|
+
reply message.replyto, "PHP function lookup trigger set to: #{params[:trigger]}"
|
113
|
+
end
|
114
|
+
|
115
|
+
def set_channels(message, params)
|
116
|
+
channel = Channel.filter(:name => params[:channel]).first
|
117
|
+
if(channel)
|
118
|
+
vals = Setting[:phpfunc]
|
119
|
+
if(params[:action] == 'add')
|
120
|
+
vals[:channels] << channel.pk unless Setting[:phpfunc][:channels].include?(channel.pk)
|
121
|
+
reply message.replyto, "Channel \2#{params[:channel]}\2 added to PHP auto lookup"
|
122
|
+
else
|
123
|
+
vals[:channels].delete(channel.pk) if Setting[:phpfunc][:channels].include?(channel.pk)
|
124
|
+
reply message.replyto, "Channel \2#{params[:channel]}\2 has been removed from PHP auto lookup"
|
125
|
+
end
|
126
|
+
Setting.filter(:name => 'phpfunc').first.value = vals
|
127
|
+
else
|
128
|
+
reply message.replyto, "Error: No record of channel #{params[:channel]}"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def list_channels(message, params)
|
133
|
+
if(Setting[:phpfunc][:channels].size > 0)
|
134
|
+
chans = []
|
135
|
+
Setting[:phpfunc][:channels].each do |id|
|
136
|
+
chans << Channel[id].name
|
137
|
+
end
|
138
|
+
reply message.replyto, "PHP auto lookup enabled channels: #{chans.join(', ')}"
|
139
|
+
else
|
140
|
+
reply message.replyto, 'No channels currently enabled for PHP auto lookup'
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def show_trigger(message, p)
|
145
|
+
reply message.replyto, "PHP auto lookup trigger: \2#{Setting[:phpfunc][:trigger]}\2"
|
146
|
+
end
|
147
|
+
|
148
|
+
private
|
149
|
+
|
150
|
+
def find_file(name)
|
151
|
+
Dir.new(@manual).each do |filename|
|
152
|
+
return filename if filename.downcase == "function.#{name.gsub(/(_|->)/, '-').downcase}.html"
|
153
|
+
end
|
154
|
+
return nil
|
155
|
+
end
|
156
|
+
|
157
|
+
def fetch_manual(message=nil, params=nil)
|
158
|
+
Thread.new do
|
159
|
+
manual_site = 'http://us.php.net/'
|
160
|
+
Logger.log "Fetching PHP manual from #{manual_site}"
|
161
|
+
connection = Net::HTTP.new("us.php.net", 80)
|
162
|
+
File.open("#{@path}/manual.tar.gz", 'w'){ |manual|
|
163
|
+
connection.get('/distributions/manual/php_manual_en.tar.gz', nil){ |line|
|
164
|
+
manual.write(line)
|
165
|
+
}
|
166
|
+
}
|
167
|
+
Dir.chdir(@path)
|
168
|
+
Helpers.safe_exec("tar -xzf #{@path}/manual.tar.gz", 60)
|
169
|
+
Logger.log "PHP manual fetching complete."
|
170
|
+
reply message.replyto, "PHP manual fetch is now complete" unless message.nil?
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def setup_setting
|
175
|
+
s = Setting.filter(:name => 'phpfunc').first
|
176
|
+
unless(s)
|
177
|
+
s = Setting.find_or_create(:name => 'phpfunc')
|
178
|
+
s.value = {:directory => Config[:plugin_directory] + '/php', :trigger => '@', :channels => []}
|
179
|
+
end
|
180
|
+
unless(File.directory?(Setting[:phpfunc][:directory]))
|
181
|
+
FileUtils.mkdir_p(Setting[:phpfunc][:directory])
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def parse_predefined(m, name)
|
186
|
+
name.upcase!
|
187
|
+
page = File.open("#{@manual}/language.variables.predefined.html").readlines.join(' ').gsub(/[\n\r]/, '')
|
188
|
+
if page =~ /<dt>\s*<span class="term"><a href="reserved\.variables\.html.+? class="link">#{name.gsub(/\$/, '\$')}<\/a><\/span>\s*<dd>\s*<span class="simpara">(.+?)<\/span>/
|
189
|
+
desc = $1
|
190
|
+
desc.gsub!(/[\r\n]/, ' ')
|
191
|
+
desc.gsub!(/<.+?>/, ' ')
|
192
|
+
desc = CGI::unescapeHTML(desc.gsub(/\s+/, ' '))
|
193
|
+
reply m.replyto, "\2PHP Superglobal\2"
|
194
|
+
reply m.replyto, "\2#{name}:\2 #{desc}"
|
195
|
+
else
|
196
|
+
reply m.replyto, "No superglobal found matching: #{name}"
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def parse_wildcard(m, name)
|
201
|
+
matches = []
|
202
|
+
pattern = name.gsub(/\*/, '.*?')
|
203
|
+
Dir.open(@manual).each do |file|
|
204
|
+
if(file =~ /^(.+?#{pattern}.+?)\.html/)
|
205
|
+
match = $1
|
206
|
+
if(match =~ /^function\.(.+?)\-/)
|
207
|
+
if(@classlist.include?($1.downcase))
|
208
|
+
match.gsub!(/[-]/, '_')
|
209
|
+
match.sub!(/_/, '->')
|
210
|
+
else
|
211
|
+
match.gsub!(/[-]/, '_')
|
212
|
+
end
|
213
|
+
match.gsub!(/^function\./, '')
|
214
|
+
else
|
215
|
+
match = nil
|
216
|
+
end
|
217
|
+
matches << match unless match.nil?
|
218
|
+
end
|
219
|
+
end
|
220
|
+
matches.sort!
|
221
|
+
reply m.replyto, "Lots of matching functions. Truncating list to 20 results."
|
222
|
+
reply m.replyto, matches.values_at(0..19).join(', ')
|
223
|
+
end
|
224
|
+
|
225
|
+
def parse_function(m, name, filename)
|
226
|
+
page = File.open("#{@manual}/#{filename}", 'r').readlines.join('')
|
227
|
+
page.gsub!(/[\r\n]/, '')
|
228
|
+
versions = page =~ /<p class="verinfo">(.+?)<\/p>/i ? $1 : '(UNKNOWN)'
|
229
|
+
proto = page =~ /<div class="methodsynopsis dc-description">(.+?)<\/div>/i ? $1 : name
|
230
|
+
desc = page =~ /<p class="refpurpose dc-title">.+? — (.+?)<\/p>/i ? $1 : '(UNKNOWN)'
|
231
|
+
versions = CGI::unescapeHTML(versions)
|
232
|
+
proto = CGI::unescapeHTML(proto.gsub(/<.+?>/, ' ').gsub(/[\s]+/, ' '))
|
233
|
+
desc = CGI::unescapeHTML(desc.gsub(/<.+?>/, ' ').gsub(/[\s]+/, ' '))
|
234
|
+
reply m.replyto, versions
|
235
|
+
reply m.replyto, "\2#{proto}\2"
|
236
|
+
reply m.replyto, desc
|
237
|
+
reply m.replyto, "http://www.php.net/manual/en/#{filename.gsub(/\.html$/, '.php')}"
|
238
|
+
end
|
239
|
+
|
240
|
+
def parse_operator(m, name)
|
241
|
+
Logger.log "parse_operator name=#{name}"
|
242
|
+
name.downcase!
|
243
|
+
type, title, ejemplo = @ops[name]
|
244
|
+
reply m.replyto, "\2#{name}\2 is the \2#{title.to_a.join("\2 or \2")}\2 operator"
|
245
|
+
type.to_a.each do |t|
|
246
|
+
reply m.replyto, "http://php.net/manual/en/language.operators.#{t}.php"
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
def populate_classes
|
251
|
+
if(@classlist.empty?)
|
252
|
+
Dir.open(@manual).each do |file|
|
253
|
+
if(file =~ /^class\.(.+?)\.html/)
|
254
|
+
@classlist << $1
|
255
|
+
end
|
256
|
+
end
|
257
|
+
@classlist.uniq!
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
class Quotes < ModSpox::Plugin
|
2
|
+
|
3
|
+
include Models
|
4
|
+
|
5
|
+
def initialize(pipeline)
|
6
|
+
super
|
7
|
+
Quote.create_table unless Quote.table_exists?
|
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]
|
17
|
+
end
|
18
|
+
|
19
|
+
def quote(message, params)
|
20
|
+
quote = nil
|
21
|
+
reg = false
|
22
|
+
if(params[:term])
|
23
|
+
if(params[:term] =~ /^\d+$/)
|
24
|
+
quote = Quote[params[:term].to_i]
|
25
|
+
else
|
26
|
+
quote = Quote.filter(:quote => Regexp.new(params[:term])).first
|
27
|
+
reg = true
|
28
|
+
end
|
29
|
+
else
|
30
|
+
ids = Quote.map(:id)
|
31
|
+
quote = Quote[ids[rand(ids.size - 1)].to_i]
|
32
|
+
end
|
33
|
+
if(quote)
|
34
|
+
reply message.replyto, "\2[\2#{quote.pk}\2|\2#{quote.added.year}/#{quote.added.month}/#{quote.added.day}\2]:\2 #{reg ? quote.quote.gsub(/(#{params[:term]})/, "\2\\1\2") : quote.quote}"
|
35
|
+
else
|
36
|
+
reply message.replyto, "\2Error:\2 Failed to find quote"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def addquote(message, params)
|
41
|
+
quote = Quote.new(:nick_id => message.source.pk, :channel_id => message.target.pk)
|
42
|
+
quote.quote = params[:quote]
|
43
|
+
quote.added = Time.now
|
44
|
+
quote.save
|
45
|
+
reply message.replyto, "\2Quote added:\2 ##{quote.pk}"
|
46
|
+
end
|
47
|
+
|
48
|
+
def searchquote(message, params)
|
49
|
+
result = Quote.filter(:quote => Regexp.new(params[:term]))
|
50
|
+
if(result.size > 0)
|
51
|
+
ids = result.map(:id)
|
52
|
+
ids.sort!
|
53
|
+
ids = ids.slice(0, 20)
|
54
|
+
reply message.replyto, "Quotes matching term (#{params[:term]}): #{ids.join(', ')}"
|
55
|
+
else
|
56
|
+
reply message.replyto, "\2Error:\2 No quotes match search term: #{params[:term]}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def delquote(message, params)
|
61
|
+
result = Quote.filter(:id => params[:id].to_i)
|
62
|
+
if(result.size < 1)
|
63
|
+
reply message.replyto, "\2Error:\2 Failed to find quote with ID: #{params[:id]}"
|
64
|
+
else
|
65
|
+
result.destroy
|
66
|
+
reply message.replyto, "\2Quote deleted:\2 ##{params[:id]}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class Quote < Sequel::Model
|
71
|
+
set_schema do
|
72
|
+
primary_key :id
|
73
|
+
text :quote, :null => false
|
74
|
+
timestamp :added, :null => false
|
75
|
+
foreign_key :nick_id, :table => :nicks
|
76
|
+
foreign_key :channel_id, :table => :channels
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
@@ -11,6 +11,14 @@ class Roulette < ModSpox::Plugin
|
|
11
11
|
Signature.find_or_create(:signature => 'roulette stats ?(\S+)?', :plugin => name, :method => 'stats').params = [:nick]
|
12
12
|
Game.create_table unless Game.table_exists?
|
13
13
|
Info.create_table unless Info.table_exists?
|
14
|
+
@banner = nil
|
15
|
+
@pipeline.hook(:self, :get_banner, :Internal_PluginResponse)
|
16
|
+
end
|
17
|
+
|
18
|
+
# message:: ModSpox::Messages::Internal::PluginResponse
|
19
|
+
# Get the banner plugin
|
20
|
+
def get_banner(message)
|
21
|
+
@banner = message.plugin if message.found?
|
14
22
|
end
|
15
23
|
|
16
24
|
# message:: ModSpox::Messages::Incoming::Privmsg
|
@@ -136,8 +144,7 @@ class Roulette < ModSpox::Plugin
|
|
136
144
|
reply(channel, "#{nick.nick}: *click*")
|
137
145
|
rescue Bullet => bang
|
138
146
|
game_over(nick, bang.game)
|
139
|
-
|
140
|
-
reply(channel, "#{nick.nick}: *BANG*")
|
147
|
+
kill_nick(nick, channel)
|
141
148
|
end
|
142
149
|
end
|
143
150
|
|
@@ -151,7 +158,20 @@ class Roulette < ModSpox::Plugin
|
|
151
158
|
end
|
152
159
|
rescue Bullet => bang
|
153
160
|
game_over(nick, bang.game)
|
154
|
-
|
161
|
+
kill_nick(nick, channel)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def kill_nick(nick, channel)
|
166
|
+
unless(@banner.nil?)
|
167
|
+
begin
|
168
|
+
@banner.ban(nick, channel, '*BANG*', true, false)
|
169
|
+
rescue NotOperator => boom
|
170
|
+
reply(channel, "#{nick.nick}: *BANG*")
|
171
|
+
rescue Object => boom
|
172
|
+
Logger.log("Error: Roulette ban generated an unexpected error: #{boom}")
|
173
|
+
end
|
174
|
+
else
|
155
175
|
reply(channel, "#{nick.nick}: *BANG*")
|
156
176
|
end
|
157
177
|
end
|
@@ -159,6 +179,7 @@ class Roulette < ModSpox::Plugin
|
|
159
179
|
# channel:: ModSpox::Models::Channel
|
160
180
|
# Return current game
|
161
181
|
def game(channel)
|
182
|
+
@pipeline << Messages::Internal::PluginRequest.new(self, 'Banner') if @banner.nil?
|
162
183
|
game = Game.filter{:shots > 0 && :channel_id == channel.pk}.first
|
163
184
|
unless(game)
|
164
185
|
chamber = rand(5) + 1
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class Talk < ModSpox::Plugin
|
2
|
+
|
3
|
+
include Models
|
4
|
+
|
5
|
+
def initialize(pipeline)
|
6
|
+
super
|
7
|
+
group = Group.find_or_create(:name => 'talk')
|
8
|
+
Signature.find_or_create(:signature => 'say (\S+) (.+)', :plugin => name, :method => 'talk', :group_id => group.pk,
|
9
|
+
:description => 'Make bot speak given text to target', :requirement => 'private').params = [:target, :text]
|
10
|
+
Signature.find_or_create(:signature => 'action (\S+) (.+)', :plugin => name, :method => 'action', :group_id => group.pk,
|
11
|
+
:description => 'Make bot perform action for target', :requirement => 'private').params = [:target, :text]
|
12
|
+
end
|
13
|
+
|
14
|
+
def talk(message, params)
|
15
|
+
send_p(message, params)
|
16
|
+
end
|
17
|
+
|
18
|
+
def action(message, params)
|
19
|
+
send_p(message, params, true)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def send_p(message, params, action=false)
|
25
|
+
target = find_target(params[:target])
|
26
|
+
if(target.nil?)
|
27
|
+
reply message.replyto, "\2Error:\2 Failed to locate target: #{params[:target]}"
|
28
|
+
else
|
29
|
+
@pipeline << Messages::Outgoing::Privmsg.new(target, params[:text], action)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def find_target(string)
|
34
|
+
result = Channel.filter(:name => string).first
|
35
|
+
return result if result
|
36
|
+
result = Nick.filter(:nick => string).first
|
37
|
+
return result if result
|
38
|
+
return nil
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
class Translate < ModSpox::Plugin
|
2
|
+
|
3
|
+
include Models
|
4
|
+
|
5
|
+
def initialize(pipeline)
|
6
|
+
super(pipeline)
|
7
|
+
Signature.find_or_create(:signature => 'translate ([a-z]{2}\|[a-z]{2}) (.+)', :plugin => name, :method => 'translate',
|
8
|
+
:description => 'Translate text').params = [:lang, :text]
|
9
|
+
Signature.find_or_create(:signature => 'autotranslate add ([a-z]{2}) (\S+)', :plugin => name, :method => 'auto_add',
|
10
|
+
:description => 'Add a nick to the autotranslate service').params = [:lang, :nick]
|
11
|
+
Signature.find_or_create(:signature => 'autotranslate remove (\S+)', :plugin => name, :method => 'auto_remove',
|
12
|
+
:description => 'Remove a nick from the autotranslate service').params = [:nick]
|
13
|
+
@watchers = {}
|
14
|
+
@cache = {}
|
15
|
+
end
|
16
|
+
|
17
|
+
def auto_add(message, params)
|
18
|
+
return unless message.is_public?
|
19
|
+
nick = Nick.filter(:nick => params[:nick]).first
|
20
|
+
if(nick && nick.channels.include?(message.target))
|
21
|
+
@watchers[message.target.pk] = {} unless @watchers.has_key?(message.target.pk)
|
22
|
+
@watchers[message.target.pk][nick.pk] = params[:lang] unless @watchers[message.target.pk].has_key?(nick.pk)
|
23
|
+
hook
|
24
|
+
reply message.replyto, "#{params[:nick]} is now being tracked for auto translation"
|
25
|
+
else
|
26
|
+
reply message.replyto, "\2Error:\2 Failed to locate #{params[:nick]}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def auto_remove(message, params)
|
31
|
+
return unless message.is_public?
|
32
|
+
nick = Nick.filter(:nick => params[:nick]).first
|
33
|
+
if(nick)
|
34
|
+
if(@watchers.has_key?(message.target.pk))
|
35
|
+
@watchers[message.target.pk].delete(nick.pk) if @watchers[message.target.pk].has_key?(nick.pk)
|
36
|
+
@watchers.delete(message.target.pk) if @watchers[message.target.pk].empty?
|
37
|
+
hook
|
38
|
+
reply message.replyto, "#{params[:nick]} is no longer being tracked for auto translation"
|
39
|
+
else
|
40
|
+
reply message.replyto, "No one is currently being tracked"
|
41
|
+
end
|
42
|
+
else
|
43
|
+
reply message.replyto, "\2Error:\2 Failed to locate #{params[:nick]}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def translate(message, params)
|
48
|
+
reply message.replyto, "\2Translation:\2 #{do_translation(params[:lang], params[:text])}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def listener(message)
|
52
|
+
if(message.is_public? && @watchers.has_key?(message.target.pk))
|
53
|
+
if(@watchers[message.target.pk].has_key?(message.source.pk))
|
54
|
+
reply message.replyto, "\2Translation (#{message.source.nick}):\2 #{do_translation("#{@watchers[message.target.pk][message.source.pk]}en", message.message)}"
|
55
|
+
elsif(message.message =~ /^(\S+)[:,]/)
|
56
|
+
Logger.log("Matched a nick: #{$1}")
|
57
|
+
nick = Nick.filter(:nick => $1).first
|
58
|
+
return unless nick
|
59
|
+
if(@watchers[message.target.pk].has_key?(nick.pk))
|
60
|
+
reply message.replyto, "\2(#{do_translation("en|#{@watchers[message.target.pk][nick.pk]}", 'translation')})\2 #{do_translation("en|#{@watchers[message.target.pk][nick.pk]}", message.message)}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def do_translation(langs, text)
|
69
|
+
if(@cache.has_key?(langs) && @cache[langs].has_key?(text))
|
70
|
+
return @cache[langs][text]
|
71
|
+
end
|
72
|
+
connection = Net::HTTP.new('babelfish.altavista.com', 80)
|
73
|
+
response = connection.request_get("/tr?tt=urltext&trtext=#{CGI::escape(text)}&lp=#{langs.gsub(/\|/, '_')}", nil)
|
74
|
+
response.value()
|
75
|
+
if response.body.gsub(/[\r\n]/, '') =~ /<div style=padding:10px;>(.+?)<\/div>/
|
76
|
+
result = $1
|
77
|
+
if(text.length < 15)
|
78
|
+
@cache[langs] = {} unless @cache.has_key?(langs)
|
79
|
+
@cache[langs][text] = result
|
80
|
+
end
|
81
|
+
return result.gsub(/\s+/, ' ')
|
82
|
+
else
|
83
|
+
raise "Failed to extract translation"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def hook
|
88
|
+
if(@watchers.size > 0)
|
89
|
+
@pipeline.hook(self, :listener, :Incoming_Privmsg)
|
90
|
+
else
|
91
|
+
@pipeline.unhook(self, :listener, :Incoming_Privmsg)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
class Weather < ModSpox::Plugin
|
2
|
+
|
3
|
+
include Models
|
4
|
+
|
5
|
+
def initialize(pipeline)
|
6
|
+
super
|
7
|
+
Signature.find_or_create(:signature => 'weather (\d+)', :plugin => name, :method => 'weather',
|
8
|
+
:description => 'Show weather for given zipcode').params = [:zipcode]
|
9
|
+
end
|
10
|
+
|
11
|
+
def weather(message, params)
|
12
|
+
connection = Net::HTTP.new('www.weather.com', 80)
|
13
|
+
response = connection.request_get("/weather/local/#{params[:zipcode]}?lswe=96094&lwsa=WeatherLocalUndeclared&from=whatwhere", nil)
|
14
|
+
begin
|
15
|
+
response.value
|
16
|
+
page = response.body.gsub(/[\r\n]/, ' ')
|
17
|
+
if page =~ /R for (.+?) \(.+?>([0-9]+)&.+?Like<BR> ([0-9]+)&.+?UV In.+?TextA">(.+?)\s*<.+?Wind.+?TextA">(.+?)\s*<.+?idity.+?TextA">(.+?)\s*<.+?ssure.+?TextA">(.+?)\s*<.+?oint.+?TextA">(.+?)\s*<.+?bility.+?TextA">(.+?)\s*</
|
18
|
+
location = $1
|
19
|
+
curtemp = $2
|
20
|
+
feeltemp = $3
|
21
|
+
uv = $4
|
22
|
+
wind = $5
|
23
|
+
humid = $6
|
24
|
+
pressure = $7
|
25
|
+
dewpoint = $8
|
26
|
+
visibility = $9
|
27
|
+
future = Array.new
|
28
|
+
i = 0
|
29
|
+
page.scan(/.+?ialLink11"><B>(.+?)</).each{|match| future.push(match[0])}
|
30
|
+
page.scan(/font.+?lueFont10">([^<].+?)<\/nobr>/).each{|match|
|
31
|
+
future[i] << "|#{match[0].gsub(/<.+?>/, '').gsub(/&.+?;/, '').gsub(/\s+/, ' ')}"
|
32
|
+
i += 1
|
33
|
+
}
|
34
|
+
i = 0
|
35
|
+
for item in future do
|
36
|
+
if item =~ /^([^\|]+)\|(.+)$/
|
37
|
+
future[i] = "\2#{$1}:\2 #{$2}"
|
38
|
+
else
|
39
|
+
future.delete_at(i)
|
40
|
+
end
|
41
|
+
i += 1
|
42
|
+
end
|
43
|
+
reply message.replyto, "Weather for: \2#{location}\2"
|
44
|
+
reply message.replyto, "Current Temp: #{curtemp} - Feels like: #{feeltemp}"
|
45
|
+
reply message.replyto, "[UV Index: #{uv.gsub(/&.+?;/, '')}][Wind: #{wind.gsub(/&.+?;/, '')}][Humiditiy: #{humid.gsub(/&.+?;/, '')}][Pressure: #{pressure.gsub(/&.+?;/, '')}][Dew Point: #{dewpoint.gsub(/&.+?;/, '')}][Visibility: #{visibility.gsub(/&.+?;/, '')}]"
|
46
|
+
reply message.replyto, future.values_at(0..2).join(' ')
|
47
|
+
else
|
48
|
+
reply message.replyto, "Failed to retrieve weather data."
|
49
|
+
end
|
50
|
+
rescue Object => boom
|
51
|
+
reply message.replyto, "Error: Received invalid response from server"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -32,6 +32,8 @@ class Authenticator < ModSpox::Plugin
|
|
32
32
|
:group_id => group.pk, :description => 'List available authentication groups')
|
33
33
|
Models::Signature.find_or_create(:signature => 'auth group info (\S+)', :plugin => name, :method => 'group_info',
|
34
34
|
:group_id => group.pk, :description => 'List members of given group').params = [:group]
|
35
|
+
Models::Signature.find_or_create(:signature => 'groups', :plugin => name, :method => 'show_groups',
|
36
|
+
:description => 'Show user groups they are currently a member of')
|
35
37
|
end
|
36
38
|
|
37
39
|
# message:: ModSpox::Messages::Incoming::Privmsg
|
@@ -172,6 +174,16 @@ class Authenticator < ModSpox::Plugin
|
|
172
174
|
end
|
173
175
|
end
|
174
176
|
|
177
|
+
def show_groups(message, params)
|
178
|
+
groups = []
|
179
|
+
message.source.auth_groups.each{|g| groups << g.name}
|
180
|
+
if(groups.empty?)
|
181
|
+
reply message.replyto, "You are not currently a member of any groups"
|
182
|
+
else
|
183
|
+
reply message.replyto, "\2Groups (#{message.source.nick}):\2 #{groups.join(', ')}"
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
175
187
|
# message:: ModSpox::Messages::Incoming::Privmsg
|
176
188
|
# params:: Signature parameters
|
177
189
|
# Add given nick to authentication group
|
@@ -14,7 +14,7 @@ class Banner < ModSpox::Plugin
|
|
14
14
|
:description => 'Kickban given nick from given channel for given number of seconds').params = [:nick, :channel, :time, :message]
|
15
15
|
Signature.find_or_create(:signature => 'banmask (\S+) (\S+) (\d+) ?(.+)?', :plugin => name, :method => 'message_mask_ban', :group_id => admin.pk,
|
16
16
|
:description => 'Kickban given mask from given channel for given number of seconds providing an optional message'
|
17
|
-
).params = [:mask, :
|
17
|
+
).params = [:mask, :channel, :time, :message]
|
18
18
|
Signature.find_or_create(:signature => 'banmask list', :plugin => name, :method => 'mask_list', :group_id => admin.pk,
|
19
19
|
:description => 'List all currently active banmasks')
|
20
20
|
Signature.find_or_create(:signature => 'banmask remove (\d+)', :plugin => name, :method => 'mask_remove', :group_id => admin.pk,
|
@@ -83,9 +83,9 @@ class Banner < ModSpox::Plugin
|
|
83
83
|
raise Exceptions::InvalidType.new("Nick given is not a nick model") unless nick.is_a?(Models::Nick)
|
84
84
|
raise Exceptions::InvalidType.new("Channel given is not a channel model") unless channel.is_a?(Models::Channel)
|
85
85
|
if(!me.is_op?(channel))
|
86
|
-
raise
|
86
|
+
raise NotOperator.new("I am not an operator in #{channel.name}")
|
87
87
|
elsif(!nick.channels.include?(channel))
|
88
|
-
raise
|
88
|
+
raise NotInChannel.new("#{nick.nick} is not in channel: #{channel.name}")
|
89
89
|
else
|
90
90
|
mask = nick.source.nil? || nick.source.empty? ? "#{nick.nick}!*@*" : "*!*@#{nick.address}"
|
91
91
|
BanRecord.new(:nick_id => nick.pk, :bantime => time.to_i, :remaining => time.to_i,
|