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.
- 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
|