zmb 0.1.1
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/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.markdown +39 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/bin/zmb +188 -0
- data/lib/zmb.rb +296 -0
- data/lib/zmb/commands.rb +63 -0
- data/lib/zmb/event.rb +15 -0
- data/lib/zmb/plugin.rb +110 -0
- data/lib/zmb/settings.rb +48 -0
- data/lib/zmb/timer.rb +28 -0
- data/plugins/bank.rb +101 -0
- data/plugins/commands.rb +119 -0
- data/plugins/irc.rb +230 -0
- data/plugins/quote.rb +100 -0
- data/plugins/relay.rb +70 -0
- data/plugins/users.rb +280 -0
- data/test/helper.rb +10 -0
- data/test/test_zmb.rb +7 -0
- data/zmb.gemspec +71 -0
- metadata +97 -0
data/plugins/irc.rb
ADDED
@@ -0,0 +1,230 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
require 'zmb/timer'
|
4
|
+
|
5
|
+
class Event
|
6
|
+
attr_accessor :delegate, :command, :args, :name, :userhost, :message
|
7
|
+
|
8
|
+
def initialize(sender, line)
|
9
|
+
puts line
|
10
|
+
|
11
|
+
if line[0,1] == ':' then
|
12
|
+
line = line[1..-1] # Remove the :
|
13
|
+
hostname, command, args = line.split(' ', 3)
|
14
|
+
args = "#{hostname} #{args}"
|
15
|
+
else
|
16
|
+
command, args = line.split(' ', 3)
|
17
|
+
end
|
18
|
+
|
19
|
+
@delegate = sender
|
20
|
+
@command = command.downcase
|
21
|
+
@args = args
|
22
|
+
|
23
|
+
case @command
|
24
|
+
when 'privmsg'
|
25
|
+
@userhost, @channel, @message = args.split(' ', 3)
|
26
|
+
@name, @userhost = @userhost.split('!', 2)
|
27
|
+
@message = @message[1..-1]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def private?
|
32
|
+
@channel == @delegate.nick
|
33
|
+
end
|
34
|
+
|
35
|
+
def sender
|
36
|
+
private? ? @name : @channel
|
37
|
+
end
|
38
|
+
|
39
|
+
def message?
|
40
|
+
@message != nil
|
41
|
+
end
|
42
|
+
|
43
|
+
def reply(m)
|
44
|
+
if message? then
|
45
|
+
m = m.split("\n") if not m.respond_to?('each')
|
46
|
+
m.each{ |mess| @delegate.message(sender, mess) }
|
47
|
+
else
|
48
|
+
@delegate.write m
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class IrcConnection
|
54
|
+
attr_accessor :host, :port, :channels, :nick, :name, :realname, :password, :throttle
|
55
|
+
|
56
|
+
def initialize(sender, settings={})
|
57
|
+
@delegate = sender
|
58
|
+
|
59
|
+
@host = settings['host'] if settings.has_key?('host')
|
60
|
+
begin
|
61
|
+
@port = Integer(settings['port']) if settings.has_key?('port')
|
62
|
+
rescue Exception
|
63
|
+
@port = 6667
|
64
|
+
end
|
65
|
+
|
66
|
+
@channels = Array.new
|
67
|
+
@channels = settings['channels'] if settings.has_key?('channels')
|
68
|
+
|
69
|
+
@nick = settings['nick'] if settings.has_key?('nick')
|
70
|
+
@name = settings['name'] if settings.has_key?('name')
|
71
|
+
@realname = settings['realname'] if settings.has_key?('realname')
|
72
|
+
@password = settings['password'] if settings.has_key?('password')
|
73
|
+
|
74
|
+
@throttle = 10
|
75
|
+
@throttle = settings['throttle'] if settings.has_key?('throttle')
|
76
|
+
|
77
|
+
sender.timer_add(Timer.new(self, :connect, 0.1, false)) if sender.running?
|
78
|
+
end
|
79
|
+
|
80
|
+
def socket=(value)
|
81
|
+
@socket = value
|
82
|
+
end
|
83
|
+
|
84
|
+
def to_json(*a)
|
85
|
+
{
|
86
|
+
'host' => @host,
|
87
|
+
'port' => @port,
|
88
|
+
|
89
|
+
'channels' => @channels,
|
90
|
+
|
91
|
+
'nick' => @nick,
|
92
|
+
'name' => @name,
|
93
|
+
'realname' => @realname,
|
94
|
+
'password' => @password,
|
95
|
+
|
96
|
+
'throttle' => @throttle,
|
97
|
+
'plugin' => 'irc',
|
98
|
+
}.to_json(*a)
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.wizard
|
102
|
+
{
|
103
|
+
'host' => { 'help' => 'Hostname', 'default' => 'localhost' },
|
104
|
+
'port' => { 'help' => 'Port', 'default' => 6667 },
|
105
|
+
'nick' => { 'help' => 'Nickname', 'default' => 'zmb' },
|
106
|
+
'name' => { 'help' => 'Name', 'default' => 'zmb' },
|
107
|
+
'realname' => { 'help' => 'Realname', 'default' => 'zmb' },
|
108
|
+
'password' => { 'help' => 'If the ircd requires a password, enter this here.', 'default' => nil },
|
109
|
+
}
|
110
|
+
end
|
111
|
+
|
112
|
+
def commands
|
113
|
+
require 'zmb/commands'
|
114
|
+
{
|
115
|
+
'join' => PermCommand.new('admin', self, :join_command),
|
116
|
+
'part' => PermCommand.new('admin', self, :part_command),
|
117
|
+
'raw' => PermCommand.new('admin', self, :raw_command),
|
118
|
+
'tell' => PermCommand.new('admin', self, :tell_command, 2),
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
def unloaded
|
123
|
+
write "Quit :ZMB"
|
124
|
+
@socket.close if @socket
|
125
|
+
end
|
126
|
+
|
127
|
+
def nick=(value)
|
128
|
+
@nick = value
|
129
|
+
write "NICK #{@nick}"
|
130
|
+
end
|
131
|
+
|
132
|
+
def connected?
|
133
|
+
@socket != nil
|
134
|
+
end
|
135
|
+
|
136
|
+
def connect
|
137
|
+
if @host and @port and not connected? then
|
138
|
+
Thread.new do
|
139
|
+
@socket = TCPSocket.new(@host, @port)
|
140
|
+
@delegate.socket_add(self, @socket)
|
141
|
+
perform
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def disconnected(sender, socket)
|
147
|
+
@socket = nil
|
148
|
+
sender.timer_add(Timer.new(self, :connect, @throttle))
|
149
|
+
end
|
150
|
+
|
151
|
+
def perform
|
152
|
+
write "PASS #{@password}" if @password
|
153
|
+
write "NICK #{@nick}" if @nick
|
154
|
+
write "USER #{@name} 0 0 :#{@realname}" if @name and @realname
|
155
|
+
end
|
156
|
+
|
157
|
+
def write(line)
|
158
|
+
@socket.write line + "\r\n" if @socket
|
159
|
+
end
|
160
|
+
|
161
|
+
def message(recipient, msg)
|
162
|
+
write "PRIVMSG #{recipient} :#{msg}"
|
163
|
+
end
|
164
|
+
|
165
|
+
def join(channel)
|
166
|
+
@channels << channel if not @channels.include?(channel)
|
167
|
+
write "JOIN #{channel}"
|
168
|
+
end
|
169
|
+
|
170
|
+
def part(channel)
|
171
|
+
@channels.delete(channel) if @channels.include?(channel)
|
172
|
+
write "PART #{channel}"
|
173
|
+
end
|
174
|
+
|
175
|
+
def received(sender, socket, data)
|
176
|
+
@buffer = '' if @buffer == nil
|
177
|
+
@buffer += data
|
178
|
+
line, @buffer = @buffer.split("\r\n", 2)
|
179
|
+
@buffer = '' if @buffer == nil
|
180
|
+
|
181
|
+
while line != nil do
|
182
|
+
e = Event.new(self, line)
|
183
|
+
|
184
|
+
# Catch some events
|
185
|
+
case e.command
|
186
|
+
when 'ping' then write "PONG #{e.args[1..-1]}"
|
187
|
+
when '001' then @channels.each{ |channel| write "JOIN #{channel}" }
|
188
|
+
when 'nick' then tmp, @nick = e.args.split(' :', 2)
|
189
|
+
when '433' then
|
190
|
+
@nick="#{@nick}_"
|
191
|
+
write "NICK #{@nick}"
|
192
|
+
end
|
193
|
+
|
194
|
+
@delegate.event(self, e)
|
195
|
+
line, @buffer = @buffer.split("\r\n", 2)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
def join_command(e, channel)
|
200
|
+
join channel
|
201
|
+
"#{channel} joined"
|
202
|
+
end
|
203
|
+
|
204
|
+
def part_command(e, channel)
|
205
|
+
part channel
|
206
|
+
"left #{channel}"
|
207
|
+
end
|
208
|
+
|
209
|
+
def raw_command(e, line)
|
210
|
+
write line
|
211
|
+
nil
|
212
|
+
end
|
213
|
+
|
214
|
+
def tell_command(e, to, message)
|
215
|
+
msg = msg.split("\n") if not msg.respond_to?('each')
|
216
|
+
msg.each{ |m| message(to, m) }
|
217
|
+
nil
|
218
|
+
end
|
219
|
+
|
220
|
+
def running(sender)
|
221
|
+
connect
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
Plugin.define do
|
226
|
+
name "irc"
|
227
|
+
description "A plugin which allows you to connect to irc servers."
|
228
|
+
object IrcConnection
|
229
|
+
multi_instances true
|
230
|
+
end
|
data/plugins/quote.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
class Quote
|
2
|
+
attr_accessor :quotes, :autoindex
|
3
|
+
|
4
|
+
def initialize(sender, settings={})
|
5
|
+
@quotes = Hash.new
|
6
|
+
@quotes = settings['quotes'] if settings.has_key?('quotes')
|
7
|
+
@autoindex = 1
|
8
|
+
@autoindex = settings['autoindex'] if settings.has_key?('autoindex')
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_json(*a)
|
12
|
+
{
|
13
|
+
'plugin' => 'quote',
|
14
|
+
'quotes' => @quotes,
|
15
|
+
'autoindex' => @autoindex,
|
16
|
+
}.to_json(*a)
|
17
|
+
end
|
18
|
+
|
19
|
+
def add(quote, username=nil)
|
20
|
+
@quotes["#{@autoindex}"] = {
|
21
|
+
'quote' => quote,
|
22
|
+
'time' => Time.now,
|
23
|
+
'username' => username,
|
24
|
+
}
|
25
|
+
|
26
|
+
@autoindex += 1
|
27
|
+
@autoindex - 1
|
28
|
+
end
|
29
|
+
|
30
|
+
def count
|
31
|
+
@quotes.keys.count
|
32
|
+
end
|
33
|
+
|
34
|
+
def commands
|
35
|
+
require 'zmb/commands'
|
36
|
+
{
|
37
|
+
'quote' => Command.new(self, :quote_command, 1, 'Show a random quote or the quote with matching id'),
|
38
|
+
'quote-add' => Command.new(self, :add_command, 1, 'Add a quote'),
|
39
|
+
'quote-del' => PermCommand.new('quote', self, :del_command, 1, 'Delete a quote by id'),
|
40
|
+
'quote-count' => Command.new(self, :count_command, 0, 'Show amount of quotes'),
|
41
|
+
'quote-last' => Command.new(self, :last_command, 0, 'Show the last quote'),
|
42
|
+
'quote-search' => Command.new(self, :search_command, 1, 'Search to find a quote'),
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
def quote_command(e, id=nil)
|
47
|
+
return "quote \##{id} not found" if id and not @quotes.has_key?(id)
|
48
|
+
return "\"#{@quotes[id]['quote']}\" by #{@quotes[id]['username']} at #{@quotes[id]['time']}" if id
|
49
|
+
return "no quotes" if count < 1
|
50
|
+
|
51
|
+
id = "#{rand(autoindex - 1) + 1}"
|
52
|
+
while not @quotes.has_key?(id)
|
53
|
+
id = "#{rand(autoindex - 1) + 1}"
|
54
|
+
end
|
55
|
+
|
56
|
+
"\"#{@quotes[id]['quote']}\" by #{@quotes[id]['username']} at #{@quotes[id]['time']}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def add_command(e, quote)
|
60
|
+
if e.user and e.user.respond_to?('authenticated?') and e.user.authenticated? then
|
61
|
+
"quote added \##{add(quote, e.user.username)}"
|
62
|
+
else
|
63
|
+
'permission denied'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def del_command(e, id)
|
68
|
+
if @quotes.has_key?(id) then
|
69
|
+
@quotes.delete id
|
70
|
+
"quote #{id} deleted"
|
71
|
+
else
|
72
|
+
"no quote found with id=#{id}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def count_command(e)
|
77
|
+
"#{count} quotes"
|
78
|
+
end
|
79
|
+
|
80
|
+
def last_command(e)
|
81
|
+
return "no quotes" if count < 1
|
82
|
+
quote_command(e, @quotes.keys.sort.reverse[0])
|
83
|
+
end
|
84
|
+
|
85
|
+
def search_command(e, search)
|
86
|
+
result = @quotes.map{ |id, quote| "#{id}: #{quote['quote']}" if quote['quote'].include?(search) }.reject{ |q| not q }
|
87
|
+
|
88
|
+
if result.count then
|
89
|
+
result.join("\n")
|
90
|
+
else
|
91
|
+
"no quotes found"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
Plugin.define do
|
97
|
+
name "quote"
|
98
|
+
description "quote database"
|
99
|
+
object Quote
|
100
|
+
end
|
data/plugins/relay.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
class Relay
|
2
|
+
attr_accessor :relays
|
3
|
+
|
4
|
+
def initialize(sender, settings={})
|
5
|
+
@relays = settings['relays'] if settings.has_key?('relays')
|
6
|
+
@relays = Hash.new if not @relays
|
7
|
+
|
8
|
+
@delegate = sender
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_json(*a)
|
12
|
+
{ 'relays' => @relays, 'plugin' => 'relay' }.to_json(*a)
|
13
|
+
end
|
14
|
+
|
15
|
+
def event(sender, e)
|
16
|
+
if e.message? and @delegate.instances.has_value?(sender) then
|
17
|
+
relay = "#{@delegate.instances.invert[sender]}:#{e.sender}"
|
18
|
+
|
19
|
+
if @relays.has_key?(relay) then
|
20
|
+
instance, recipient = @relays[relay].split(':', 2)
|
21
|
+
@delegate.instances[instance].message(recipient, "<#{e.name}> #{e.message}") if @delegate.instances.has_key?(instance)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def commands
|
27
|
+
require 'zmb/commands'
|
28
|
+
{
|
29
|
+
'relays' => PermCommand.new('admin', self, :relays_command, 0, 'Show all relays'),
|
30
|
+
'relay-add' => PermCommand.new('admin', self, :add_command, 2, 'Add a relay'),
|
31
|
+
'relay-del' => PermCommand.new('admin', self, :del_command, 1, 'Delete a relay'),
|
32
|
+
}
|
33
|
+
end
|
34
|
+
|
35
|
+
def relays_command(e)
|
36
|
+
if @relays.count < 1 then
|
37
|
+
"no relays"
|
38
|
+
else
|
39
|
+
@relays.map{ |relay, location| "#{relay} > #{location}"}.join("\n")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def add_command(e, relay, location)
|
44
|
+
if relay.include? ':' and location.include? ':' then
|
45
|
+
if @relays.has_key?(relay) then
|
46
|
+
"relays must be unique"
|
47
|
+
else
|
48
|
+
@relays[relay] = location
|
49
|
+
"relay setup #{relay} => #{location}"
|
50
|
+
end
|
51
|
+
else
|
52
|
+
"relays must be in the format: plugin:location, example (efnet:\#zmb)"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def del_command(e, relay)
|
57
|
+
if @relays.has_key?(relay) then
|
58
|
+
@relays.delete(relay)
|
59
|
+
"#{relay}: relay deleted"
|
60
|
+
else
|
61
|
+
"no such relay"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
Plugin.define do
|
67
|
+
name "relay"
|
68
|
+
description "This plugin allows you to relay messages from one channel/server to another."
|
69
|
+
object Relay
|
70
|
+
end
|
data/plugins/users.rb
ADDED
@@ -0,0 +1,280 @@
|
|
1
|
+
class Event
|
2
|
+
attr_accessor :user
|
3
|
+
end
|
4
|
+
|
5
|
+
class User
|
6
|
+
require 'digest/sha1'
|
7
|
+
|
8
|
+
attr_accessor :username, :password, :userhosts, :permissions, :seen
|
9
|
+
|
10
|
+
def to_json(*a)
|
11
|
+
{'username' => @username, 'password' => @password, 'userhosts' => @userhosts, 'permissions' => @permissions, 'seen' => @seen}.to_json(*a)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.create_settings(data)
|
15
|
+
require 'time'
|
16
|
+
user = new(data['username'], data['password'])
|
17
|
+
user.userhosts = data['userhosts'] if data.has_key?('userhosts')
|
18
|
+
user.permissions = data['permissions'] if data.has_key?('permissions')
|
19
|
+
user.seen = Time.parse(data['seen']) if data.has_key?('seen') and data['seen']
|
20
|
+
user
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(username=nil, password=nil, userhost=nil)
|
24
|
+
@username = username
|
25
|
+
@password = Digest::SHA1.hexdigest(password) if password
|
26
|
+
@userhosts = Array.new
|
27
|
+
@userhosts << userhost if userhost
|
28
|
+
@permissions = Array.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def concat(other_user)
|
32
|
+
@permissions += other_user.permissions
|
33
|
+
@userhosts += other_user.userhosts
|
34
|
+
end
|
35
|
+
|
36
|
+
def password=(new_password)
|
37
|
+
@password = Digest::SHA1.hexdigest(new_password)
|
38
|
+
end
|
39
|
+
|
40
|
+
def password?(check_password)
|
41
|
+
@password != nil and @password == Digest::SHA1.hexdigest(check_password)
|
42
|
+
end
|
43
|
+
|
44
|
+
def authenticated?
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
def admin?
|
49
|
+
@permissions.include?("owner") or @permissions.include?("admin")
|
50
|
+
end
|
51
|
+
|
52
|
+
def permission?(permission)
|
53
|
+
admin? or @permissions.include?(permission)
|
54
|
+
end
|
55
|
+
|
56
|
+
def permit(permission)
|
57
|
+
@permissions << permission
|
58
|
+
end
|
59
|
+
|
60
|
+
def deny(permission)
|
61
|
+
@permissions.delete(permission)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class AnonymousUser
|
66
|
+
def authenticated?
|
67
|
+
false
|
68
|
+
end
|
69
|
+
|
70
|
+
def permission?(permission)
|
71
|
+
false
|
72
|
+
end
|
73
|
+
|
74
|
+
def admin?
|
75
|
+
false
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
class Users
|
80
|
+
attr_accessor :users
|
81
|
+
|
82
|
+
def initialize(sender, settings={})
|
83
|
+
@delegate = sender
|
84
|
+
@users = settings['users'].map{ |user| User.create_settings(user) } if settings.has_key?('users')
|
85
|
+
@users = Array.new if not @users
|
86
|
+
end
|
87
|
+
|
88
|
+
def to_json(*a)
|
89
|
+
{'users' => @users, 'plugin' => 'users'}.to_json(*a)
|
90
|
+
end
|
91
|
+
|
92
|
+
def user!(search)
|
93
|
+
@users.find{|user| user.userhosts.include?(search) or user.username == search}
|
94
|
+
end
|
95
|
+
|
96
|
+
def user(search)
|
97
|
+
user!(search) or AnonymousUser.new
|
98
|
+
end
|
99
|
+
|
100
|
+
def pre_event(sender, e)
|
101
|
+
e.user = user(e.userhost) if e.respond_to?('userhost') and not e.user
|
102
|
+
e.user.seen = Time.now if e.user.respond_to?('seen')
|
103
|
+
end
|
104
|
+
|
105
|
+
def create_user(username, password=nil, userhost=nil)
|
106
|
+
user = User.new(username, password, userhost)
|
107
|
+
@users << user
|
108
|
+
user
|
109
|
+
end
|
110
|
+
|
111
|
+
def commands
|
112
|
+
require 'zmb/commands'
|
113
|
+
{
|
114
|
+
'meet' => Command.new(self, :meet, 1, 'Meet a new user'),
|
115
|
+
'forget' => AuthCommand.new(self, :forget, 0, "Forget about a user"),
|
116
|
+
'permit' => PermCommand.new('admin', self, :permit, 2),
|
117
|
+
'deny' => PermCommand.new('admin', self, :deny, 2),
|
118
|
+
'perms' => AuthCommand.new(self, :perms, 1, 'List all permissions a user has.'),
|
119
|
+
'merge' => PermCommand.new('admin', self, :merge, 2, 'Merge two users together'),
|
120
|
+
'password' => AuthCommand.new(self, :password, 1, 'Set the password for your account'),
|
121
|
+
'login' => Command.new(self, :login, 2, 'Add your current host to the username and password provided.'),
|
122
|
+
'logout' => AuthCommand.new(self, :logout, 0, 'Remove your current host from your account.'),
|
123
|
+
'whoami' => Command.new(self, :whoami, 0, 'Who are you logged in as?'),
|
124
|
+
'userhosts' => AuthCommand.new(self, :userhosts, 0, 'List all the hosts associated with your account'),
|
125
|
+
'adduserhost' => AuthCommand.new(self, :adduserhost, 1, 'Add a host to your account'),
|
126
|
+
'deluserhost' => AuthCommand.new(self, :deluserhost, 1, 'Remove a host to your account'),
|
127
|
+
'names' => Command.new(self, :names, 1, 'List all the users'),
|
128
|
+
'seen' => Command.new(self, :seen, 1, 'When was a user last seen'),
|
129
|
+
'sudo' => PermCommand.new('admin', self, :sudo, 2, 'Execute a command as another user.'),
|
130
|
+
}
|
131
|
+
end
|
132
|
+
|
133
|
+
def meet(e, username=nil)
|
134
|
+
if e.user.admin? and username then
|
135
|
+
return "#{username} already exists" if user!(username)
|
136
|
+
user = create_user(username)
|
137
|
+
"Hello #{username}"
|
138
|
+
elsif not e.user.authenticated? then
|
139
|
+
return "#{e.sender} already exists" if user!(e.sender)
|
140
|
+
if e.respond_to?('userhost') and e.respond_to?('user') then
|
141
|
+
user = create_user(e.name, nil, e.userhost)
|
142
|
+
end
|
143
|
+
"Hello #{user.username}"
|
144
|
+
else
|
145
|
+
"You already have an account #{e.user.username}"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def forget(e)
|
150
|
+
"user #{@e.users.delete(e.user).username} deleted"
|
151
|
+
end
|
152
|
+
|
153
|
+
def permit(e, username, permission)
|
154
|
+
if user = user!(username) then
|
155
|
+
user.permit(permission)
|
156
|
+
"permission added"
|
157
|
+
else
|
158
|
+
"#{username} does not exist"
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def deny(e, username, permission)
|
163
|
+
if user = user!(username) then
|
164
|
+
user.deny(permission)
|
165
|
+
'permission removed'
|
166
|
+
else
|
167
|
+
"#{username} does not exist"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def perms(e, username=nil)
|
172
|
+
e.user.permissions.empty? ? "#{e.user.username} has no permissions" : e.user.permissions.join(', ')
|
173
|
+
end
|
174
|
+
|
175
|
+
def merge(e, username, other_username)
|
176
|
+
user = user!(username)
|
177
|
+
other_user = user!(other_username)
|
178
|
+
|
179
|
+
if user and other_user then
|
180
|
+
user.concat other_user
|
181
|
+
@users.delete other_user
|
182
|
+
"#{other_user.username} now merged into #{user.username}"
|
183
|
+
else
|
184
|
+
'User(s) do not exist'
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
def password(e, password)
|
189
|
+
e.user.password = password
|
190
|
+
"#{e.user.username} password has been set to #{password}"
|
191
|
+
end
|
192
|
+
|
193
|
+
def login(e, username, password)
|
194
|
+
user = user!(username)
|
195
|
+
|
196
|
+
if e.user.authenticated? then
|
197
|
+
'already logged in'
|
198
|
+
elsif user and user.password?(password) then
|
199
|
+
user.hosts << e.userhost
|
200
|
+
"#{request.hostname} added to your account #{user.username}"
|
201
|
+
else
|
202
|
+
'user and/or password is incorrect'
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def logout(e)
|
207
|
+
e.user.hosts.delete(e.userhost)
|
208
|
+
"userhost #{e.hostname} removed from your account."
|
209
|
+
end
|
210
|
+
|
211
|
+
def whoami(e)
|
212
|
+
e.user.authenticated? ? "#{e.user.username}" : 'nobody'
|
213
|
+
end
|
214
|
+
|
215
|
+
def userhosts(e)
|
216
|
+
e.user.userhosts.empty? ? "#{e.user.username} has no userhosts" : e.user.userhosts.join(', ')
|
217
|
+
end
|
218
|
+
|
219
|
+
def adduserhost(e, userhost)
|
220
|
+
e.user.userhosts << userhost
|
221
|
+
"#{userhost} added to #{e.user.username}"
|
222
|
+
end
|
223
|
+
|
224
|
+
def deluserhost(e, userhost)
|
225
|
+
if e.user.userhosts.delete(userhost) then
|
226
|
+
"#{userhost} deleted from #{e.user.username}"
|
227
|
+
else
|
228
|
+
"#{e.user.username} doesn't have #{userhost}"
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def names(e, search=nil)
|
233
|
+
users = @users.map{|user| user.username}
|
234
|
+
users = users.grep(/#{search}/i) if search
|
235
|
+
|
236
|
+
if users.empty? then
|
237
|
+
"no users found"
|
238
|
+
else
|
239
|
+
users.join(', ')
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
def seen(e, username=nil)
|
244
|
+
if user = user!(username) and user.seen then
|
245
|
+
diff = Time.now - user.seen
|
246
|
+
|
247
|
+
if diff < 60 then
|
248
|
+
msg = "#{Integer(diff)} seconds ago"
|
249
|
+
elsif diff < 3600 then
|
250
|
+
msg = "#{Integer(diff/60)} minutes ago"
|
251
|
+
elsif diff < 86400 then
|
252
|
+
msg = "about #{Integer(diff/3600)} hours ago"
|
253
|
+
else
|
254
|
+
msg = "#{Integer(diff/86400)} days ago"
|
255
|
+
end
|
256
|
+
|
257
|
+
"#{username} last seen #{msg}"
|
258
|
+
else
|
259
|
+
"#{username} has never been seen"
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
def sudo(e, search, command)
|
264
|
+
if user = user!(search) then
|
265
|
+
new_event = e.clone
|
266
|
+
new_event.user = user
|
267
|
+
new_event.message = @delegate.instances['commands'].cc + command
|
268
|
+
@delegate.event(self, new_event)
|
269
|
+
nil
|
270
|
+
else
|
271
|
+
"#{search}: Username or userhost not found"
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
Plugin.define do
|
277
|
+
name "users"
|
278
|
+
description "users manager"
|
279
|
+
object Users
|
280
|
+
end
|