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.
- data/CHANGELOG +31 -1
- data/LICENSE +674 -0
- data/README.rdoc +73 -0
- data/bin/mod_spox +28 -28
- data/data/mod_spox/extras/AOLSpeak.rb +2 -3
- data/data/mod_spox/extras/AutoKick.rb +10 -23
- data/data/mod_spox/extras/AutoMode.rb +12 -23
- data/data/mod_spox/extras/Bash.rb +55 -0
- data/data/mod_spox/extras/Bouncer.rb +85 -57
- data/data/mod_spox/extras/Bullshit.rb +1 -1
- data/data/mod_spox/extras/Bytes.rb +1 -2
- data/data/mod_spox/extras/Confess.rb +27 -29
- data/data/mod_spox/extras/DCC.rb +11 -20
- data/data/mod_spox/extras/DevWatch.rb +21 -23
- data/data/mod_spox/extras/DownForEveryoneOrJustMe.rb +47 -0
- data/data/mod_spox/extras/EightBall.rb +1 -1
- data/data/mod_spox/extras/FML.rb +35 -0
- data/data/mod_spox/extras/Headers.rb +31 -50
- data/data/mod_spox/extras/Karma.rb +81 -29
- data/data/mod_spox/extras/Logger.rb +2 -2
- data/data/mod_spox/extras/LolSpeak.rb +1 -2
- data/data/mod_spox/extras/PhpCli.rb +138 -8
- data/data/mod_spox/extras/PhpFuncLookup.rb +20 -23
- data/data/mod_spox/extras/Pinger.rb +1 -1
- data/data/mod_spox/extras/Quotes.rb +8 -10
- data/data/mod_spox/extras/RegexTracker.rb +2 -4
- data/data/mod_spox/extras/Roulette.rb +20 -27
- data/data/mod_spox/extras/RubyCli.rb +93 -0
- data/data/mod_spox/extras/Search.rb +17 -3
- data/data/mod_spox/extras/Seen.rb +150 -0
- data/data/mod_spox/extras/SlashdotHeadlineGenerator.rb +500 -0
- data/data/mod_spox/extras/Talk.rb +2 -4
- data/data/mod_spox/extras/Topten.rb +10 -12
- data/data/mod_spox/extras/TracTicket.rb +3 -5
- data/data/mod_spox/extras/Translate.rb +20 -22
- data/data/mod_spox/extras/Twitter.rb +118 -33
- data/data/mod_spox/extras/UrbanDictionary.rb +8 -17
- data/data/mod_spox/extras/Weather.rb +1 -2
- data/data/mod_spox/plugins/Authenticator.rb +93 -98
- data/data/mod_spox/plugins/Banner.rb +26 -56
- data/data/mod_spox/plugins/Helper.rb +5 -6
- data/data/mod_spox/plugins/Initializer.rb +4 -14
- data/data/mod_spox/plugins/Joiner.rb +1 -1
- data/data/mod_spox/plugins/Nicker.rb +13 -0
- data/data/mod_spox/plugins/Parter.rb +2 -2
- data/data/mod_spox/plugins/Permissions.rb +60 -0
- data/data/mod_spox/plugins/PluginLoader.rb +7 -12
- data/data/mod_spox/plugins/Ponger.rb +51 -0
- data/data/mod_spox/plugins/Quitter.rb +1 -2
- data/data/mod_spox/plugins/Servers.rb +57 -0
- data/data/mod_spox/plugins/Status.rb +3 -2
- data/data/mod_spox/plugins/Triggers.rb +9 -9
- data/lib/mod_spox/Bot.rb +109 -33
- data/lib/mod_spox/BotConfig.rb +2 -2
- data/lib/mod_spox/ConfigurationWizard.rb +12 -12
- data/lib/mod_spox/Database.rb +1 -4
- data/lib/mod_spox/Exceptions.rb +26 -0
- data/lib/mod_spox/Helpers.rb +29 -68
- data/lib/mod_spox/Loader.rb +23 -24
- data/lib/mod_spox/Logger.rb +19 -17
- data/lib/mod_spox/MessageFactory.rb +50 -24
- data/lib/mod_spox/Pipeline.rb +21 -7
- data/lib/mod_spox/Plugin.rb +27 -3
- data/lib/mod_spox/PluginManager.rb +28 -15
- data/lib/mod_spox/PriorityQueue.rb +69 -0
- data/lib/mod_spox/Socket.rb +93 -51
- data/lib/mod_spox/Sockets.rb +76 -63
- data/lib/mod_spox/Timer.rb +21 -141
- data/lib/mod_spox/Version.rb +14 -0
- data/lib/mod_spox/handlers/BadNick.rb +1 -1
- data/lib/mod_spox/handlers/Bounce.rb +5 -5
- data/lib/mod_spox/handlers/Created.rb +13 -5
- data/lib/mod_spox/handlers/Handler.rb +12 -3
- data/lib/mod_spox/handlers/Invite.rb +14 -8
- data/lib/mod_spox/handlers/Join.rb +24 -20
- data/lib/mod_spox/handlers/Kick.rb +22 -13
- data/lib/mod_spox/handlers/Mode.rb +42 -36
- data/lib/mod_spox/handlers/Motd.rb +4 -0
- data/lib/mod_spox/handlers/Names.rb +66 -39
- data/lib/mod_spox/handlers/Nick.rb +20 -14
- data/lib/mod_spox/handlers/Part.rb +25 -8
- data/lib/mod_spox/handlers/Ping.rb +11 -5
- data/lib/mod_spox/handlers/Pong.rb +9 -5
- data/lib/mod_spox/handlers/Privmsg.rb +25 -17
- data/lib/mod_spox/handlers/Quit.rb +13 -8
- data/lib/mod_spox/handlers/Topic.rb +4 -0
- data/lib/mod_spox/handlers/Welcome.rb +16 -24
- data/lib/mod_spox/handlers/Who.rb +64 -48
- data/lib/mod_spox/handlers/Whois.rb +92 -60
- data/lib/mod_spox/messages/incoming/Nick.rb +2 -2
- data/lib/mod_spox/messages/incoming/Privmsg.rb +1 -1
- data/lib/mod_spox/messages/incoming/Whois.rb +1 -0
- data/lib/mod_spox/messages/internal/EstablishConnection.rb +1 -1
- data/lib/mod_spox/messages/internal/PluginsReady.rb +10 -0
- data/lib/mod_spox/messages/internal/QueueSocket.rb +8 -0
- data/lib/mod_spox/messages/internal/Reconnect.rb +8 -0
- data/lib/mod_spox/messages/internal/UnqueueSocket.rb +8 -0
- data/lib/mod_spox/migrations/002_persistent_sigs.rb +14 -0
- data/lib/mod_spox/migrations/003_auth_restructure.rb +31 -0
- data/lib/mod_spox/migrations/004_mode_index_fix.rb +18 -0
- data/lib/mod_spox/migrations/005_nick_mode_nopark.rb +18 -0
- data/lib/mod_spox/models/Auth.rb +16 -46
- data/lib/mod_spox/models/AuthMask.rb +13 -0
- data/lib/mod_spox/models/Channel.rb +46 -27
- data/lib/mod_spox/models/Config.rb +10 -19
- data/lib/mod_spox/models/Group.rb +20 -8
- data/lib/mod_spox/models/Models.rb +1 -1
- data/lib/mod_spox/models/Nick.rb +105 -113
- data/lib/mod_spox/models/NickMode.rb +23 -9
- data/lib/mod_spox/models/Server.rb +12 -1
- data/lib/mod_spox/models/Setting.rb +12 -16
- data/lib/mod_spox/models/Signature.rb +28 -8
- data/tests/BotHolder.rb +24 -0
- data/tests/handlers/tc_BadNick.rb +21 -0
- data/tests/handlers/tc_Created.rb +24 -0
- data/tests/handlers/tc_Invite.rb +50 -0
- data/tests/handlers/tc_Join.rb +33 -0
- data/tests/handlers/tc_Kick.rb +32 -0
- data/tests/handlers/tc_Mode.rb +85 -0
- data/tests/handlers/tc_Names.rb +35 -0
- data/tests/handlers/tc_Nick.rb +55 -0
- data/tests/handlers/tc_Part.rb +44 -0
- data/tests/handlers/tc_Ping.rb +40 -0
- data/tests/handlers/tc_Pong.rb +28 -0
- data/tests/handlers/tc_Privmsg.rb +85 -0
- data/tests/handlers/tc_Quit.rb +40 -0
- data/tests/handlers/tc_Who.rb +50 -0
- data/tests/handlers/tc_Whois.rb +61 -0
- data/tests/models/tc_Auth.rb +34 -0
- data/tests/models/tc_Channel.rb +52 -0
- data/tests/models/tc_Config.rb +19 -0
- data/tests/models/tc_Nick.rb +142 -0
- data/tests/models/tc_NickMode.rb +40 -0
- data/tests/models/tc_Setting.rb +21 -0
- data/tests/models/tc_Signature.rb +14 -0
- data/tests/run_tests.rb +4 -0
- metadata +284 -212
- data/README +0 -36
- data/lib/mod_spox/Cache.rb +0 -57
- data/lib/mod_spox/Monitors.rb +0 -84
- data/lib/mod_spox/Pool.rb +0 -164
- data/lib/mod_spox/models/AuthGroup.rb +0 -16
- data/lib/mod_spox/models/ChannelMode.rb +0 -14
- data/lib/mod_spox/models/NickChannel.rb +0 -45
- data/lib/mod_spox/models/NickGroup.rb +0 -16
@@ -7,18 +7,16 @@ class Karma < ModSpox::Plugin
|
|
7
7
|
Datatype::Karma.create_table unless Datatype::Karma.table_exists?
|
8
8
|
Datatype::Alias.create_table unless Datatype::Alias.table_exists?
|
9
9
|
alias_group = Models::Group.find_or_create(:name => 'alias')
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
:group_id => alias_group.pk, :description => 'Remove a karma alias').params = [:thing, :otherthing]
|
17
|
-
Models::Signature.find_or_create(:signature => 'karma aliases (\S+|\(.+?\))', :plugin => name, :method => 'show_aliases',
|
18
|
-
:description => 'Show all aliases for given thing').params = [:thing]
|
19
|
-
Models::Signature.find_or_create(:signature => 'karma fight (\S+|\(.+?\)) (\S+|\(.+?\))', :plugin => name, :method => 'fight',
|
20
|
-
:description => 'Make two karma objects fight').params = [:thing, :thang]
|
10
|
+
add_sig(:sig => 'karma (?!topten|bottomten$)(?!(fight|alias|dealias|aliases|reset) (\S+|\(.+?\)) ?(\S+|\(.+?\))?$)(\S+|\(.+?\))', :method => :score, :desc => 'Returns karma for given thing', :params => [:crap, :crap2, :crap3, :thing])
|
11
|
+
add_sig(:sig => 'karma reset (\S+|\(.+?\))', :method => :reset, :group => Models::Group.filter(:name => 'admin').first, :desc => 'Reset a karma score', :params => [:thing])
|
12
|
+
add_sig(:sig => 'karma alias (\S+|\(.+?\)) (\S+|\(.+?\))', :method => :aka, :group => alias_group, :desc => 'Alias a karma object to another karma object', :params => [:thing, :thang])
|
13
|
+
add_sig(:sig => 'karma dealias (\S+|\(.+?\)) (\S+|\(.+?\))', :method => :dealias, :group => alias_group, :desc => 'Remove a karma alias', :params => [:thing, :otherthing])
|
14
|
+
add_sig(:sig => 'karma aliases (\S+|\(.+?\))', :method => :show_aliases, :desc => 'Show all aliases for given thing', :params => [:thing])
|
15
|
+
add_sig(:sig => 'karma fight (\S+|\(.+?\)) (\S+|\(.+?\))', :method => :fight, :desc => 'Make two karma objects fight', :params => [:thing, :thang])
|
21
16
|
add_sig(:sig => 'antikarma (\S+|\(.+?\))', :method => :antikarma, :desc => 'Show things antikarma', :params => [:thing])
|
17
|
+
add_sig(:sig => 'antikarma fight (\S+|\(.+?\)) (\S+|\(.+?\))', :method => :antifight, :desc => 'Make two antikarma objects fight', :params => [:thing, :thang])
|
18
|
+
add_sig(:sig => 'karma topten', :method => :topten, :desc => 'Show top ten highest karma objects')
|
19
|
+
add_sig(:sig => 'karma bottomten', :method => :bottomten, :desc => 'Show bottom ten lowest karma objects')
|
22
20
|
@pipeline.hook(self, :check, :Incoming_Privmsg)
|
23
21
|
@thing_maxlen = 32
|
24
22
|
@karma_regex = /(\(.{1,#@thing_maxlen}?\)|\S{1,#@thing_maxlen})([+-]{2})(?:\s|$)/
|
@@ -32,10 +30,14 @@ class Karma < ModSpox::Plugin
|
|
32
30
|
|
33
31
|
def check(message)
|
34
32
|
if(message.is_public?)
|
33
|
+
@dupes = {}
|
35
34
|
message.message.scan(@karma_regex) do |match|
|
36
35
|
thing, adj = match
|
37
36
|
thing.downcase!
|
38
37
|
thing = thing[1..-2] if thing[0..0] == '(' && thing[-1..-1] == ')'
|
38
|
+
next if @dupes.has_key?(thing) && @dupes[thing].include?(adj)
|
39
|
+
@dupes[thing] = [] unless @dupes[thing]
|
40
|
+
@dupes[thing] << adj
|
39
41
|
adj = adj == '++' ? +1 : -1
|
40
42
|
things = [thing]
|
41
43
|
karma = Datatype::Karma.find_or_create(:thing => thing, :channel_id => message.target.pk)
|
@@ -68,6 +70,32 @@ class Karma < ModSpox::Plugin
|
|
68
70
|
@pipeline << Messages::Internal::TimerAdd.new(self, rand(5) + 1, nil, true){ egg(params[:thing].downcase, message) }
|
69
71
|
end
|
70
72
|
end
|
73
|
+
|
74
|
+
def bottomten(m, params)
|
75
|
+
set = Datatype::Karma.filter(:channel_id => m.target.pk).order(:thing.asc).order(:score.asc).limit(10)
|
76
|
+
if(set.count > 0)
|
77
|
+
output = []
|
78
|
+
set.each do |thing|
|
79
|
+
output << "#{thing.thing} (#{thing.score.to_s.slice(0) == '-' ? '' : '+'}#{thing.score})"
|
80
|
+
end
|
81
|
+
reply m.replyto, "\2Karma bottom ten:\2 #{output.join(', ')}"
|
82
|
+
else
|
83
|
+
error m.replyto, 'No karma objects stored'
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def topten(m, params)
|
88
|
+
set = Datatype::Karma.filter(:channel_id => m.target.pk).order(:thing.asc).order(:score.desc).limit(10)
|
89
|
+
if(set.count > 0)
|
90
|
+
output = []
|
91
|
+
set.each do |thing|
|
92
|
+
output << "#{thing.thing} (#{thing.score.to_s.slice(0) == '-' ? '' : '+'}#{thing.score})"
|
93
|
+
end
|
94
|
+
reply m.replyto, "\2Karma topten:\2 #{output.join(', ')}"
|
95
|
+
else
|
96
|
+
error m.replyto, 'No karma objects stored'
|
97
|
+
end
|
98
|
+
end
|
71
99
|
|
72
100
|
def antikarma(message, params)
|
73
101
|
return unless message.is_public?
|
@@ -89,7 +117,7 @@ class Karma < ModSpox::Plugin
|
|
89
117
|
return unless message.is_public?
|
90
118
|
karma = Datatype::Karma.filter(:thing => sthing, :channel_id => message.target.pk).first
|
91
119
|
if(karma)
|
92
|
-
karma.
|
120
|
+
karma.update(:score => 0)
|
93
121
|
@pipeline << Privmsg.new(message.replyto, "Karma for \2#{karma.thing}\2 has been reset")
|
94
122
|
else
|
95
123
|
@pipeline << Privmsg.new(message.replyto, "\2Error:\2 #{sthing} has no karma")
|
@@ -108,12 +136,34 @@ class Karma < ModSpox::Plugin
|
|
108
136
|
winner = thing_score > thang_score ? thing : thang
|
109
137
|
loser = thing_score > thang_score ? thang : thing
|
110
138
|
distance = (thing_score - thang_score).abs
|
111
|
-
output = "\2KARMA FIGHT RESULTS:\2 "
|
139
|
+
output = ["\2KARMA FIGHT RESULTS:\2 "]
|
112
140
|
if(distance > 0)
|
113
|
-
|
141
|
+
output << "\2#{winner}\2 #{winner[-1] == 's' || winner[-1] == 115 ? 'have' : 'has'} beaten \2#{loser}\2 #{distance > 50 ? 'like a redheaded step child' : ''} (+#{distance} points)"
|
114
142
|
else
|
115
|
-
|
143
|
+
output << "\2#{winner}\2 #{winner[-1] == 's' || winner[-1] == 115 ? 'have' : 'has'} tied \2#{loser}\2"
|
116
144
|
end
|
145
|
+
reply message.replyto, output
|
146
|
+
end
|
147
|
+
|
148
|
+
def antifight(message, params)
|
149
|
+
thing = params[:thing]
|
150
|
+
thang = params[:thang]
|
151
|
+
thing = thing[1..-2] if thing[0..0] == '(' && thing[-1..-1] == ')'
|
152
|
+
thang = thang[1..-2] if thang[0..0] == '(' && thang[-1..-1] == ')'
|
153
|
+
rthing = Datatype::Karma.find_or_create(:thing => thing.downcase, :channel_id => message.target.pk)
|
154
|
+
rthang = Datatype::Karma.find_or_create(:thing => thang.downcase, :channel_id => message.target.pk)
|
155
|
+
thing_score = Datatype::Alias.score_object(rthing.pk) * -1
|
156
|
+
thang_score = Datatype::Alias.score_object(rthang.pk) * -1
|
157
|
+
winner = thing_score > thang_score ? thing : thang
|
158
|
+
loser = thing_score > thang_score ? thang : thing
|
159
|
+
distance = (thing_score - thang_score).abs
|
160
|
+
output = ["\2ANTI-KARMA FIGHT RESULTS:\2 "]
|
161
|
+
if(distance > 0)
|
162
|
+
output << "\2#{winner}\2 #{winner[-1] == 's' || winner[-1] == 115 ? 'have' : 'has'} beaten \2#{loser}\2 #{distance > 50 ? 'like a redheaded step child' : ''} (+#{distance} points)"
|
163
|
+
else
|
164
|
+
output << "\2#{winner}\2 #{winner[-1] == 's' || winner[-1] == 115 ? 'have' : 'has'} tied \2#{loser}\2"
|
165
|
+
end
|
166
|
+
reply message.replyto, output
|
117
167
|
end
|
118
168
|
|
119
169
|
def aka(message, params)
|
@@ -140,7 +190,7 @@ class Karma < ModSpox::Plugin
|
|
140
190
|
otherthing = Datatype::Karma.filter(:thing => sotherthing, :channel_id => message.target.pk).first
|
141
191
|
if(thing && otherthing)
|
142
192
|
set = Datatype::Alias.filter('(thing_id = ? AND aka_id = ?) OR (thing_id = ? AND aka_id = ?)', thing.pk, otherthing.pk, otherthing.pk, thing.pk)
|
143
|
-
if(set.
|
193
|
+
if(set.count < 1)
|
144
194
|
reply message.replyto, "\2Error:\2 No alias found between #{thing.thing} and #{otherthing.thing}"
|
145
195
|
else
|
146
196
|
set.destroy
|
@@ -155,18 +205,22 @@ class Karma < ModSpox::Plugin
|
|
155
205
|
thing = params[:thing].downcase
|
156
206
|
thing = thing[1..-2] if thing[0..0] == '(' && thing[-1..-1] == ')'
|
157
207
|
thing = Datatype::Karma.filter(:thing => thing, :channel_id => message.target.pk).first
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
208
|
+
begin
|
209
|
+
if(thing)
|
210
|
+
things = []
|
211
|
+
Datatype::Alias.get_aliases(thing.pk).each do |id|
|
212
|
+
things << Datatype::Karma[id].thing
|
213
|
+
end
|
214
|
+
if(things.empty?)
|
215
|
+
reply message.replyto, "#{thing.thing} is not currently aliased"
|
216
|
+
else
|
217
|
+
reply message.replyto, "#{thing.thing} is currently aliased to: #{things.sort.join(', ')}"
|
218
|
+
end
|
165
219
|
else
|
166
|
-
reply message.replyto, "#{thing
|
220
|
+
reply message.replyto, "\2Error:\2 #{params[:thing]} has never been used and has no aliases"
|
167
221
|
end
|
168
|
-
|
169
|
-
|
222
|
+
rescue Object
|
223
|
+
error message.replyto, "No aliases found"
|
170
224
|
end
|
171
225
|
end
|
172
226
|
|
@@ -186,9 +240,7 @@ class Karma < ModSpox::Plugin
|
|
186
240
|
index [:thing, :channel_id], :unique => true
|
187
241
|
end
|
188
242
|
|
189
|
-
|
190
|
-
ModSpox::Models::Channel[channel_id]
|
191
|
-
end
|
243
|
+
many_to_one :channel, :class => ModSpox::Models::Channel
|
192
244
|
end
|
193
245
|
class Alias < Sequel::Model
|
194
246
|
set_schema do
|
@@ -22,8 +22,8 @@ class ChatLogger < ModSpox::Plugin
|
|
22
22
|
@pipeline.hook(self, :log_privmsg, :Incoming_Notice)
|
23
23
|
@pipeline.hook(self, :log_outpriv, :Outgoing_Privmsg)
|
24
24
|
@pipeline.hook(self, :log_outpriv, :Outgoing_Notice)
|
25
|
-
|
26
|
-
|
25
|
+
add_sig(:sig => 'seen (\S+)', :method => :seen, :desc => 'Report last sighting of nick', :params => [:nick])
|
26
|
+
add_sig(:sig => 'lastspoke (\S+)', :method => :spoke, :desc => 'Report last time nick spoke', :params => [:nick])
|
27
27
|
end
|
28
28
|
|
29
29
|
def log_outpriv(message)
|
@@ -11,8 +11,7 @@ class LolSpeak < ModSpox::Plugin
|
|
11
11
|
Logger.warn('Error: This plugins requires the lolspeak gem. Please install gem and reload plugin.')
|
12
12
|
raise BotException.new("Failed to initialize plugin. Missing lolspeak gem.")
|
13
13
|
end
|
14
|
-
|
15
|
-
:description => 'Translate text to lolspeak').params = [:text]
|
14
|
+
add_sig(:sig => 'lolspeak (.+)', :method => :translate, :desc => 'Translate text to lolspeak', :params => [:text])
|
16
15
|
end
|
17
16
|
|
18
17
|
def translate(message, params)
|
@@ -6,7 +6,7 @@ class PhpCli < ModSpox::Plugin
|
|
6
6
|
|
7
7
|
def initialize(pipeline)
|
8
8
|
super(pipeline)
|
9
|
-
@path = Config
|
9
|
+
@path = Config.val(:plugin_directory) + '/phpcli'
|
10
10
|
@botini = @path + '/bot.ini'
|
11
11
|
unless(File.directory?(@path))
|
12
12
|
FileUtils.mkdir_p(@path)
|
@@ -18,12 +18,20 @@ class PhpCli < ModSpox::Plugin
|
|
18
18
|
ini.write($ini)
|
19
19
|
ini.close
|
20
20
|
end
|
21
|
+
PhpFunction.create_table unless PhpFunction.table_exists?
|
21
22
|
php = Group.find_or_create(:name => 'php')
|
23
|
+
phpfunc = Group.find_or_create(:name => 'phpfunc')
|
22
24
|
admin = Group.filter(:name => 'admin').first
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
add_sig(:sig => 'php (on|off)', :method => :set_channel, :group => admin, :desc => 'Add or remove channel from allowing PHP command', :params => [:action])
|
26
|
+
add_sig(:sig => 'php (?!on|off)(.+)', :method => :execute_php, :group => php, :desc => 'Execute PHP code', :params => [:code])
|
27
|
+
add_sig(:sig => 'phpq (?!on|off)(.+)', :method => :quiet_php, :group => php, :params => [:code], :desc => 'Execute PHP quietly')
|
28
|
+
add_sig(:sig => 'pf add (.+)', :method => :add, :params => [:function], :group => phpfunc, :desc => 'Add a custom PHP function')
|
29
|
+
add_sig(:sig => 'pf remove (\d+)', :method => :remove, :params => [:func_id], :group => phpfunc, :desc => 'Remove a custom PHP function')
|
30
|
+
add_sig(:sig => 'pf list', :method => :list, :desc => 'List custom PHP functions')
|
31
|
+
add_sig(:sig => 'pf edit (.+)', :method => :edit, :params => [:function], :group => phpfunc, :desc => 'Overwrite existing custom PHP function')
|
32
|
+
add_sig(:sig => 'pf show (\d+)', :method => :show, :params => [:func_id], :group => phpfunc, :desc => 'Show given PHP function source')
|
33
|
+
@customfuncs = []
|
34
|
+
populate_customs
|
27
35
|
@channels = Setting.filter(:name => 'phpcli').first
|
28
36
|
@channels = @channels.nil? ? [] : @channels.value
|
29
37
|
end
|
@@ -51,11 +59,15 @@ class PhpCli < ModSpox::Plugin
|
|
51
59
|
end
|
52
60
|
end
|
53
61
|
|
54
|
-
def
|
62
|
+
def quiet_php(message, params)
|
63
|
+
execute_php(message, params, true)
|
64
|
+
end
|
65
|
+
|
66
|
+
def execute_php(message, params, shh=false)
|
55
67
|
return unless @channels.include?(message.target.pk)
|
56
68
|
filepath = @path + "/#{rand(99999)}.bot.php"
|
57
69
|
file = File.open(filepath, 'w')
|
58
|
-
file.write("<? $_SERVER = $_ENV = array(); #{params[:code]} ?>")
|
70
|
+
file.write("<? $_SERVER = $_ENV = $GLOBALS = array(); #{@customfuncs.join(' ')} #{params[:code]} ?>")
|
59
71
|
file.close
|
60
72
|
begin
|
61
73
|
output = Helpers.safe_exec("php -c #{@path}/bot.ini -d max_execution_time=10 #{filepath} 2>&1 | head -n 4")
|
@@ -75,7 +87,7 @@ class PhpCli < ModSpox::Plugin
|
|
75
87
|
reply message.replyto, "PHP #{type}: "+warning
|
76
88
|
end
|
77
89
|
if(warning.nil? || type !~ /(Fatal|Parse)/)
|
78
|
-
reply message.replyto, "Result: "+output
|
90
|
+
reply message.replyto, "#{shh ? '' : 'Result: '}"+output
|
79
91
|
end
|
80
92
|
File.delete(filepath)
|
81
93
|
rescue Timeout::Error => boom
|
@@ -85,9 +97,127 @@ class PhpCli < ModSpox::Plugin
|
|
85
97
|
File.delete(filepath)
|
86
98
|
end
|
87
99
|
end
|
100
|
+
|
101
|
+
def add(m, params)
|
102
|
+
if(params[:function].scan(/function\s+([^\(]+)\(/).size > 1)
|
103
|
+
error m.replyto, 'Only one function can be added at a time'
|
104
|
+
return
|
105
|
+
end
|
106
|
+
if(params[:function] =~ /^function\s+([^\(]+)\(/)
|
107
|
+
name = $1.downcase
|
108
|
+
f = PhpFunction.filter(:name => name).first
|
109
|
+
unless(f)
|
110
|
+
begin
|
111
|
+
parse(params[:function])
|
112
|
+
save(params[:function], name, m.source)
|
113
|
+
information m.replyto, "New function \2#{name}\2 added to custom PHP functions"
|
114
|
+
populate_customs
|
115
|
+
rescue Object => boom
|
116
|
+
error m.replyto, "Failed to add function #{name}. Error: #{boom}"
|
117
|
+
end
|
118
|
+
else
|
119
|
+
error m.replyto, "Function with name: #{name} already exists"
|
120
|
+
end
|
121
|
+
else
|
122
|
+
error m.replyto, "Function is not in proper format"
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def remove(m, params)
|
127
|
+
f = PhpFunction[params[:func_id].to_i]
|
128
|
+
if(f)
|
129
|
+
name = f.name
|
130
|
+
f.destroy
|
131
|
+
information m.replyto, "Function \2#{name}\2 has been removed"
|
132
|
+
populate_customs
|
133
|
+
else
|
134
|
+
error m.replyto, "Failed to locate function with ID: #{params[:func_id]}"
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def list(m, params)
|
139
|
+
output = ["\2Custom PHP functions:\2"]
|
140
|
+
PhpFunction.all.each do |f|
|
141
|
+
output << "\2ID:\2 #{f.pk} \2Name:\2 #{f.name} \2Author:\2 #{f.nick.nick} \2Added:\2 #{f.added.strftime("%Y/%m/%d-%H:%M:%S")}"
|
142
|
+
end
|
143
|
+
reply m.replyto, output
|
144
|
+
end
|
145
|
+
|
146
|
+
def edit(m, params)
|
147
|
+
if(params[:function] =~ /^function\s+([^\(]+)\(/)
|
148
|
+
name = $1.downcase
|
149
|
+
begin
|
150
|
+
parse(params[:function])
|
151
|
+
save(params[:function], name, m.source)
|
152
|
+
information m.replyto, "New function \2#{name}\2 added to custom PHP functions"
|
153
|
+
populate_customs
|
154
|
+
rescue Object => boom
|
155
|
+
error m.replyto, "Failed to add function #{name}. Error: #{boom}"
|
156
|
+
end
|
157
|
+
else
|
158
|
+
error m.replyto, "Function is not in proper format"
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def show(m, params)
|
163
|
+
f = PhpFunction[params[:func_id].to_i]
|
164
|
+
if(f)
|
165
|
+
reply m.replyto, ["Source for function \2#{f.name}\2:", f.php_function]
|
166
|
+
else
|
167
|
+
error m.replyto, "Failed to find custom PHP function with ID: #{params[:func_id]}"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def parse(func)
|
172
|
+
filepath = @path + "/#{rand(99999)}.bot.php"
|
173
|
+
file = File.open(filepath, 'w')
|
174
|
+
file.write("<? #{func} ?>")
|
175
|
+
file.close
|
176
|
+
output = Helpers.safe_exec("php -l #{filepath} 2>&1 | head -n 4").strip.gsub(/\s{2,}/, ' ').gsub(/[\r\n]+/, ' ')
|
177
|
+
File.delete(filepath)
|
178
|
+
if(output =~ /(Parse error.+) in/)
|
179
|
+
raise "#{$1}"
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def save(func, name, nick)
|
184
|
+
f = PhpFunction.filter(:name => name).first
|
185
|
+
f = PhpFunction.new unless f
|
186
|
+
f.name = name
|
187
|
+
f.php_function = func
|
188
|
+
f.added = ::Time.now
|
189
|
+
f.nick = nick
|
190
|
+
f.save
|
191
|
+
end
|
192
|
+
|
193
|
+
def populate_customs
|
194
|
+
@customfuncs = []
|
195
|
+
PhpFunction.all.each{|f| @customfuncs << f.php_function }
|
196
|
+
end
|
88
197
|
|
89
198
|
class NoInterpreter < Exceptions::BotException
|
90
199
|
end
|
200
|
+
|
201
|
+
class PhpFunction < Sequel::Model
|
202
|
+
set_schema do
|
203
|
+
text :php_function, :null => false
|
204
|
+
varchar :name, :null => false, :unique => true
|
205
|
+
timestamp :added, :null => false
|
206
|
+
foreign_key :nick_id, :null => false
|
207
|
+
primary_key :id
|
208
|
+
end
|
209
|
+
|
210
|
+
Sequel::Model.plugin :serialization, :marshal, :php_function
|
211
|
+
# serialize(:php_function, :format => :marshal)
|
212
|
+
|
213
|
+
def nick
|
214
|
+
Models::Nick[nick_id]
|
215
|
+
end
|
216
|
+
|
217
|
+
def nick=(n)
|
218
|
+
values[:nick_id] = n.pk
|
219
|
+
end
|
220
|
+
end
|
91
221
|
|
92
222
|
end
|
93
223
|
|
@@ -12,8 +12,8 @@ class PhpFuncLookup < ModSpox::Plugin
|
|
12
12
|
def initialize(pipeline)
|
13
13
|
super(pipeline)
|
14
14
|
setup_setting
|
15
|
-
@path = Setting
|
16
|
-
@trigger = Setting
|
15
|
+
@path = Setting.val(:phpfunc)[:directory]
|
16
|
+
@trigger = Setting.val(:phpfunc)[:trigger]
|
17
17
|
@manual = "#{@path}/html"
|
18
18
|
@classlist = []
|
19
19
|
fetch_manual unless File.exists?("#{@path}/manual.tar.gz")
|
@@ -65,15 +65,12 @@ class PhpFuncLookup < ModSpox::Plugin
|
|
65
65
|
"->" => [ "?", "Object member accessor thingy","" ],
|
66
66
|
}
|
67
67
|
admin = Group.filter(:name => 'admin').first
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
Signature.find_or_create(:signature => 'pfunc (add|remove) (\S+)', :plugin => name, :method => 'set_channels', :group_id => admin.pk,
|
75
|
-
:description => 'Add or remove channels from auto-lookups').params = [:action, :channel]
|
76
|
-
Signature.find_or_create(:signature => 'pfunc show channels', :plugin => name, :method => 'list_channels', :description => 'Show channels with auto lookup enabled')
|
68
|
+
add_sig(:sig => 'pfunc (\S+)', :method => :phpfunc, :desc => 'Lookup PHP function', :params => [:name])
|
69
|
+
add_sig(:sig => 'fetch php manual', :method => :fetch, :group => admin, :desc => 'Download and extract PHP manual')
|
70
|
+
add_sig(:sig => 'pfunc trigger (\S+)', :method => :set_trigger, :group => admin, :desc => 'Set the trigger for auto-lookups', :params => [:trigger])
|
71
|
+
add_sig(:sig => 'pfunc show trigger', :method => :show_trigger, :desc => 'Show current trigger')
|
72
|
+
add_sig(:sig => 'pfunc (add|remove) (\S+)', :method => :set_channels, :group => admin, :desc => 'Add or remove channels from auto-lookups', :params => [:action, :channel])
|
73
|
+
add_sig(:sig => 'pfunc show channels', :method => :list_channels, :desc => 'Show channels with auto lookup enabled')
|
77
74
|
@pipeline.hook(self, :listen, :Incoming_Privmsg)
|
78
75
|
populate_classes
|
79
76
|
end
|
@@ -100,7 +97,7 @@ class PhpFuncLookup < ModSpox::Plugin
|
|
100
97
|
end
|
101
98
|
|
102
99
|
def listen(m)
|
103
|
-
if(m.target.is_a?(Channel) && Setting
|
100
|
+
if(m.target.is_a?(Channel) && Setting.val(:phpfunc)[:channels].include?(m.target.pk))
|
104
101
|
if m.message =~ /^#{Regexp.escape(@trigger)}(\S+)$/
|
105
102
|
phpfunc(m, {:name => $1})
|
106
103
|
end
|
@@ -108,7 +105,7 @@ class PhpFuncLookup < ModSpox::Plugin
|
|
108
105
|
end
|
109
106
|
|
110
107
|
def set_trigger(message, params)
|
111
|
-
vals = Setting
|
108
|
+
vals = Setting.val(:phpfunc)
|
112
109
|
vals[:trigger] = params[:trigger]
|
113
110
|
Setting.filter(:name => 'phpfunc').first.value = vals
|
114
111
|
@trigger = params[:trigger]
|
@@ -118,12 +115,12 @@ class PhpFuncLookup < ModSpox::Plugin
|
|
118
115
|
def set_channels(message, params)
|
119
116
|
channel = Channel.filter(:name => params[:channel]).first
|
120
117
|
if(channel)
|
121
|
-
vals = Setting
|
118
|
+
vals = Setting.val(:phpfunc)
|
122
119
|
if(params[:action] == 'add')
|
123
|
-
vals[:channels] << channel.pk unless Setting
|
120
|
+
vals[:channels] << channel.pk unless Setting.val(:phpfunc)[:channels].include?(channel.pk)
|
124
121
|
reply message.replyto, "Channel \2#{params[:channel]}\2 added to PHP auto lookup"
|
125
122
|
else
|
126
|
-
vals[:channels].delete(channel.pk) if Setting
|
123
|
+
vals[:channels].delete(channel.pk) if Setting.val(:phpfunc)[:channels].include?(channel.pk)
|
127
124
|
reply message.replyto, "Channel \2#{params[:channel]}\2 has been removed from PHP auto lookup"
|
128
125
|
end
|
129
126
|
Setting.filter(:name => 'phpfunc').first.value = vals
|
@@ -133,9 +130,9 @@ class PhpFuncLookup < ModSpox::Plugin
|
|
133
130
|
end
|
134
131
|
|
135
132
|
def list_channels(message, params)
|
136
|
-
if(Setting
|
133
|
+
if(Setting.val(:phpfunc)[:channels].size > 0)
|
137
134
|
chans = []
|
138
|
-
Setting
|
135
|
+
Setting.val(:phpfunc)[:channels].each do |id|
|
139
136
|
chans << Channel[id].name
|
140
137
|
end
|
141
138
|
reply message.replyto, "PHP auto lookup enabled channels: #{chans.join(', ')}"
|
@@ -145,7 +142,7 @@ class PhpFuncLookup < ModSpox::Plugin
|
|
145
142
|
end
|
146
143
|
|
147
144
|
def show_trigger(message, p)
|
148
|
-
reply message.replyto, "PHP auto lookup trigger: \2#{Setting
|
145
|
+
reply message.replyto, "PHP auto lookup trigger: \2#{Setting.val(:phpfunc)[:trigger]}\2"
|
149
146
|
end
|
150
147
|
|
151
148
|
private
|
@@ -179,10 +176,10 @@ class PhpFuncLookup < ModSpox::Plugin
|
|
179
176
|
s = Setting.filter(:name => 'phpfunc').first
|
180
177
|
unless(s)
|
181
178
|
s = Setting.find_or_create(:name => 'phpfunc')
|
182
|
-
s.value = {:directory => Config
|
179
|
+
s.value = {:directory => Config.val(:plugin_directory) + '/php', :trigger => '@', :channels => []}
|
183
180
|
end
|
184
|
-
unless(File.directory?(Setting
|
185
|
-
FileUtils.mkdir_p(Setting
|
181
|
+
unless(File.directory?(Setting.val(:phpfunc)[:directory]))
|
182
|
+
FileUtils.mkdir_p(Setting.val(:phpfunc)[:directory])
|
186
183
|
end
|
187
184
|
end
|
188
185
|
|
@@ -242,7 +239,7 @@ class PhpFuncLookup < ModSpox::Plugin
|
|
242
239
|
desc = CGI::unescapeHTML(desc.gsub(/<.+?>/, ' ').gsub(/[\s]+/, ' '))
|
243
240
|
output = [versions]
|
244
241
|
output << "\2#{proto}\2"
|
245
|
-
output << desc
|
242
|
+
output << Helpers.convert_entities(desc)
|
246
243
|
output << "http://www.php.net/manual/en/#{filename.gsub(/\.html$/, '.php')}"
|
247
244
|
reply m.replyto, output
|
248
245
|
end
|