cinch 2.2.8 → 2.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/docs/logging.md +35 -0
- data/lib/cinch/channel.rb +3 -0
- data/lib/cinch/isupport.rb +1 -1
- data/lib/cinch/log_filter.rb +21 -0
- data/lib/cinch/logger_list.rb +37 -9
- data/lib/cinch/message.rb +54 -12
- data/lib/cinch/plugin.rb +2 -1
- data/lib/cinch/user.rb +2 -3
- data/lib/cinch/version.rb +1 -1
- metadata +4 -3
- data/lib/cinch/#channel.rb# +0 -407
data/docs/logging.md
CHANGED
@@ -49,6 +49,41 @@ This will set all loggers to the `:debug` level (which actually is the
|
|
49
49
|
default already) and the first logger (which is the default STDOUT
|
50
50
|
logger) to `:info`.
|
51
51
|
|
52
|
+
# Log filtering
|
53
|
+
|
54
|
+
Sometimes it is undesirable to log a message unchanged. For example
|
55
|
+
when identifying to the network, passwords might be sent in plain
|
56
|
+
text. To prevent such information from appearing in logs, {Cinch::LogFilter log filters}
|
57
|
+
can be employed.
|
58
|
+
|
59
|
+
Log filters take a log message as input and return a new message. This
|
60
|
+
allows removing/masking out passwords or other undesired information.
|
61
|
+
Additionally, messages can be dropped entirely by returning nil.
|
62
|
+
|
63
|
+
It is possible to use more than one filter, in which case they will be
|
64
|
+
called in order, each acting on the previous filter's output.
|
65
|
+
|
66
|
+
Filters can be installed by adding them to {Cinch::LoggerList#filters}.
|
67
|
+
|
68
|
+
An example (and very simple) password filter might look like this:
|
69
|
+
|
70
|
+
class PasswordFilter
|
71
|
+
def initialize(bot)
|
72
|
+
@bot = bot
|
73
|
+
end
|
74
|
+
|
75
|
+
def filter(message, event)
|
76
|
+
message.gsub(@bot.config.password, "*" * @bot.config.password.size)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
This filter will replace the password in all log messages (except for
|
81
|
+
exceptions). It could further discriminate by looking at `event` and
|
82
|
+
only modify outgoing IRC messages. It could also use the
|
83
|
+
{Cinch::Message} class to parse the message and only operate on the
|
84
|
+
actual message component, not channel names and similar. How fancy
|
85
|
+
your filtering needs to be depends on you.
|
86
|
+
|
52
87
|
# Writing your own logger
|
53
88
|
|
54
89
|
This section will follow soon. For now just look at the code of
|
data/lib/cinch/channel.rb
CHANGED
@@ -43,6 +43,9 @@ module Cinch
|
|
43
43
|
# @return [Hash{String => Object}]
|
44
44
|
attr_reader :modes
|
45
45
|
synced_attr_reader :modes
|
46
|
+
|
47
|
+
# @note Generally, you shouldn't initialize new instances of this
|
48
|
+
# class. Use {ChannelList#find_ensured} instead.
|
46
49
|
def initialize(name, bot)
|
47
50
|
@bot = bot
|
48
51
|
@name = name
|
data/lib/cinch/isupport.rb
CHANGED
@@ -75,7 +75,7 @@ module Cinch
|
|
75
75
|
self["MAXTARGETS"] = 1
|
76
76
|
self["MAXCHANNELS"] = Float::INFINITY # deprecated
|
77
77
|
self["CHANLIMIT"] = {"#" => Float::INFINITY}
|
78
|
-
self["STATUSMSG"] = [
|
78
|
+
self["STATUSMSG"] = []
|
79
79
|
self["CASEMAPPING"] = :rfc1459
|
80
80
|
self["ELIST"] = []
|
81
81
|
self["MONITOR"] = 0
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Cinch
|
2
|
+
# LogFilter describes an interface for filtering log messages before
|
3
|
+
# they're printed.
|
4
|
+
#
|
5
|
+
# @abstract
|
6
|
+
# @since 2.3.0
|
7
|
+
class LogFilter
|
8
|
+
# filter is called for each log message, except for exceptions. It
|
9
|
+
# returns a new string, which is the one that should be printed, or
|
10
|
+
# further filtered by other filters. Returning nil will drop the
|
11
|
+
# message.
|
12
|
+
#
|
13
|
+
# @param [String] message The message that is to be logged
|
14
|
+
# @param [:debug, :incoming, :outgoing, :info, :warn, :exception,
|
15
|
+
# :error, :fatal] event The kind of message
|
16
|
+
# @return [String, nil] The modified message, as it should be
|
17
|
+
# logged, or nil if the message shouldn't be logged at all
|
18
|
+
def filter(message, event)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/cinch/logger_list.rb
CHANGED
@@ -9,6 +9,17 @@ module Cinch
|
|
9
9
|
# @attr_writer level
|
10
10
|
# @since 2.0.0
|
11
11
|
class LoggerList < Array
|
12
|
+
# A list of log filters that will be applied before emitting a log
|
13
|
+
# message.
|
14
|
+
#
|
15
|
+
# @return [Array<LogFilter>]
|
16
|
+
# @since 2.3.0
|
17
|
+
attr_accessor :filters
|
18
|
+
def initialize(*args)
|
19
|
+
@filters = []
|
20
|
+
super
|
21
|
+
end
|
22
|
+
|
12
23
|
# (see Logger#level=)
|
13
24
|
def level=(level)
|
14
25
|
each {|l| l.level = level}
|
@@ -16,47 +27,64 @@ module Cinch
|
|
16
27
|
|
17
28
|
# (see Logger#log)
|
18
29
|
def log(messages, event = :debug, level = event)
|
19
|
-
|
30
|
+
do_log(messages, event, level)
|
20
31
|
end
|
21
32
|
|
22
33
|
# (see Logger#debug)
|
23
34
|
def debug(message)
|
24
|
-
|
35
|
+
do_log(message, :debug)
|
25
36
|
end
|
26
37
|
|
27
38
|
# (see Logger#error)
|
28
39
|
def error(message)
|
29
|
-
|
40
|
+
do_log(message, :error)
|
30
41
|
end
|
31
42
|
|
32
43
|
# (see Logger#error)
|
33
44
|
def fatal(message)
|
34
|
-
|
45
|
+
do_log(message, :fatal)
|
35
46
|
end
|
36
47
|
|
37
48
|
# (see Logger#info)
|
38
49
|
def info(message)
|
39
|
-
|
50
|
+
do_log(message, :info)
|
40
51
|
end
|
41
52
|
|
42
53
|
# (see Logger#warn)
|
43
54
|
def warn(message)
|
44
|
-
|
55
|
+
do_log(message, :warn)
|
45
56
|
end
|
46
57
|
|
47
58
|
# (see Logger#incoming)
|
48
59
|
def incoming(message)
|
49
|
-
|
60
|
+
do_log(message, :incoming, :log)
|
50
61
|
end
|
51
62
|
|
52
63
|
# (see Logger#outgoing)
|
53
64
|
def outgoing(message)
|
54
|
-
|
65
|
+
do_log(message, :outgoing, :log)
|
55
66
|
end
|
56
67
|
|
57
68
|
# (see Logger#exception)
|
58
69
|
def exception(e)
|
59
|
-
|
70
|
+
do_log(e, :exception, :error)
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
def do_log(messages, event, level = event)
|
75
|
+
messages = Array(messages)
|
76
|
+
if event != :exception
|
77
|
+
messages.map! { |m|
|
78
|
+
@filters.each do |f|
|
79
|
+
m = f.filter(m, event)
|
80
|
+
if m.nil?
|
81
|
+
break
|
82
|
+
end
|
83
|
+
end
|
84
|
+
m
|
85
|
+
}.compact
|
86
|
+
end
|
87
|
+
each {|l| l.log(messages, event, level)}
|
60
88
|
end
|
61
89
|
end
|
62
90
|
end
|
data/lib/cinch/message.rb
CHANGED
@@ -66,12 +66,28 @@ module Cinch
|
|
66
66
|
# @return [Target]
|
67
67
|
attr_reader :target
|
68
68
|
|
69
|
+
# The STATUSMSG mode a channel message was sent to.
|
70
|
+
#
|
71
|
+
# Some IRC servers allow sending messages limited to people in a
|
72
|
+
# channel who have a certain mode. For example, by sending a
|
73
|
+
# message to `+#channel`, only people who are voiced, or have a
|
74
|
+
# higher mode (op) will receive the message.
|
75
|
+
#
|
76
|
+
# This attribute contains the mode character the message was sent
|
77
|
+
# to, or nil if it was a normal message. For the previous example,
|
78
|
+
# this attribute would be set to `"v"`, for voiced.
|
79
|
+
#
|
80
|
+
# @return [String, nil]
|
81
|
+
# @since 2.3.0
|
82
|
+
attr_reader :statusmsg_mode
|
83
|
+
|
69
84
|
def initialize(msg, bot)
|
70
85
|
@raw = msg
|
71
86
|
@bot = bot
|
72
87
|
@matches = {:ctcp => {}, :action => {}, :other => {}}
|
73
88
|
@events = []
|
74
89
|
@time = Time.now
|
90
|
+
@statusmsg_mode = nil
|
75
91
|
parse if msg
|
76
92
|
end
|
77
93
|
|
@@ -90,7 +106,7 @@ module Cinch
|
|
90
106
|
@params = parse_params(raw_params)
|
91
107
|
|
92
108
|
@user = parse_user
|
93
|
-
@channel = parse_channel
|
109
|
+
@channel, @statusmsg_mode = parse_channel
|
94
110
|
@target = @channel || @user
|
95
111
|
@server = parse_server
|
96
112
|
@error = parse_error
|
@@ -160,6 +176,11 @@ module Cinch
|
|
160
176
|
# Replies to a message, automatically determining if it was a
|
161
177
|
# channel or a private message.
|
162
178
|
#
|
179
|
+
# If the message is a STATUSMSG, i.e. it was send to `+#channel`
|
180
|
+
# or `@#channel` instead of `#channel`, the reply will be sent as
|
181
|
+
# the same kind of STATUSMSG. See {#statusmsg_mode} for more
|
182
|
+
# information on STATUSMSG.
|
183
|
+
#
|
163
184
|
# @param [String] text the message
|
164
185
|
# @param [Boolean] prefix if prefix is true and the message was in
|
165
186
|
# a channel, the reply will be prefixed by the nickname of whoever
|
@@ -171,10 +192,10 @@ module Cinch
|
|
171
192
|
text = text.split("\n").map {|l| "#{user.nick}: #{l}"}.join("\n")
|
172
193
|
end
|
173
194
|
|
174
|
-
|
195
|
+
reply_target.send(text)
|
175
196
|
end
|
176
197
|
|
177
|
-
# Like #reply, but using {Target#safe_send} instead
|
198
|
+
# Like {#reply}, but using {Target#safe_send} instead
|
178
199
|
#
|
179
200
|
# @param (see #reply)
|
180
201
|
# @return (see #reply)
|
@@ -183,25 +204,27 @@ module Cinch
|
|
183
204
|
if channel && prefix
|
184
205
|
text = "#{@user.nick}: #{text}"
|
185
206
|
end
|
186
|
-
|
207
|
+
reply_target.safe_send(text)
|
187
208
|
end
|
188
209
|
|
189
210
|
# Reply to a message with an action.
|
190
211
|
#
|
212
|
+
# For its behaviour with regard to STATUSMSG, see {#reply}.
|
213
|
+
#
|
191
214
|
# @param [String] text the action message
|
192
215
|
# @return [void]
|
193
216
|
def action_reply(text)
|
194
217
|
text = text.to_s
|
195
|
-
|
218
|
+
reply_target.action(text)
|
196
219
|
end
|
197
220
|
|
198
|
-
# Like #action_reply, but using {Target#safe_action} instead
|
221
|
+
# Like {#action_reply}, but using {Target#safe_action} instead
|
199
222
|
#
|
200
223
|
# @param (see #action_reply)
|
201
224
|
# @return (see #action_reply)
|
202
225
|
def safe_action_reply(text)
|
203
226
|
text = text.to_s
|
204
|
-
|
227
|
+
reply_target.safe_action(text)
|
205
228
|
end
|
206
229
|
|
207
230
|
# Reply to a CTCP message
|
@@ -221,6 +244,13 @@ module Cinch
|
|
221
244
|
end
|
222
245
|
|
223
246
|
private
|
247
|
+
def reply_target
|
248
|
+
if @channel.nil? || @statusmsg_mode.nil?
|
249
|
+
return @target
|
250
|
+
end
|
251
|
+
prefix = @bot.irc.isupport["PREFIX"][@statusmsg_mode]
|
252
|
+
return Target.new(prefix + @channel.name, @bot)
|
253
|
+
end
|
224
254
|
def regular_command?
|
225
255
|
!numeric_reply? # a command can only be numeric or "regular"…
|
226
256
|
end
|
@@ -262,15 +292,27 @@ module Cinch
|
|
262
292
|
# `QUIT :#sometext` will be interpreted as a channel. The
|
263
293
|
# alternative to the currently used heuristic would be to
|
264
294
|
# hardcode a list of commands that provide a channel argument.
|
265
|
-
|
266
|
-
if
|
267
|
-
|
268
|
-
|
269
|
-
|
295
|
+
ch, status = privmsg_channel_name(@params.first)
|
296
|
+
if ch.nil? && numeric_reply? && @params.size > 1
|
297
|
+
ch, status = privmsg_channel_name(@params[1])
|
298
|
+
end
|
299
|
+
if ch
|
300
|
+
return @bot.channel_list.find_ensured(ch), status
|
270
301
|
end
|
271
302
|
end
|
272
303
|
end
|
273
304
|
|
305
|
+
def privmsg_channel_name(s)
|
306
|
+
chantypes = @bot.irc.isupport["CHANTYPES"]
|
307
|
+
statusmsg = @bot.irc.isupport["STATUSMSG"]
|
308
|
+
if statusmsg.include?(s[0]) && chantypes.include?(s[1])
|
309
|
+
status = @bot.irc.isupport["PREFIX"].invert[s[0]]
|
310
|
+
return s[1..-1], status
|
311
|
+
elsif chantypes.include?(s[0])
|
312
|
+
return s, nil
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
274
316
|
def parse_server
|
275
317
|
return unless @prefix
|
276
318
|
return if @prefix.match(/[@!]/)
|
data/lib/cinch/plugin.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require "cinch/helpers"
|
2
2
|
|
3
|
-
# TODO more details in "message dropped" debug output
|
4
3
|
module Cinch
|
5
4
|
# This class represents the core of the plugin functionality of
|
6
5
|
# Cinch. It provides both the methods for users to write their own
|
@@ -512,3 +511,5 @@ module Cinch
|
|
512
511
|
end
|
513
512
|
end
|
514
513
|
end
|
514
|
+
|
515
|
+
# TODO more details in "message dropped" debug output
|
data/lib/cinch/user.rb
CHANGED
@@ -185,7 +185,8 @@ module Cinch
|
|
185
185
|
# @api private
|
186
186
|
attr_writer :monitored
|
187
187
|
|
188
|
-
|
188
|
+
# @note Generally, you shouldn't initialize new instances of this
|
189
|
+
# class. Use {UserList#find_ensured} instead.
|
189
190
|
def initialize(*args)
|
190
191
|
@data = {
|
191
192
|
:user => nil,
|
@@ -269,8 +270,6 @@ module Cinch
|
|
269
270
|
|
270
271
|
# @param [Hash, nil] values A hash of values gathered from WHOIS,
|
271
272
|
# or `nil` if no data was returned
|
272
|
-
# @param [Boolean] not_found Has to be true if WHOIS resulted in
|
273
|
-
# an unknown user
|
274
273
|
# @return [void]
|
275
274
|
# @api private
|
276
275
|
# @since 1.0.1
|
data/lib/cinch/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cinch
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-10-
|
12
|
+
date: 2015-10-26 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
14
|
description: A simple, friendly DSL for creating IRC bots
|
15
15
|
email:
|
@@ -35,6 +35,7 @@ files:
|
|
35
35
|
- lib/cinch/formatting.rb
|
36
36
|
- lib/cinch/channel.rb
|
37
37
|
- lib/cinch/timer.rb
|
38
|
+
- lib/cinch/log_filter.rb
|
38
39
|
- lib/cinch/sasl/diffie_hellman.rb
|
39
40
|
- lib/cinch/sasl/plain.rb
|
40
41
|
- lib/cinch/sasl/dh_blowfish.rb
|
@@ -44,7 +45,6 @@ files:
|
|
44
45
|
- lib/cinch/cached_list.rb
|
45
46
|
- lib/cinch/bot.rb
|
46
47
|
- lib/cinch/isupport.rb
|
47
|
-
- lib/cinch/#channel.rb#
|
48
48
|
- lib/cinch/helpers.rb
|
49
49
|
- lib/cinch/handler.rb
|
50
50
|
- lib/cinch/handler_list.rb
|
@@ -141,3 +141,4 @@ signing_key:
|
|
141
141
|
specification_version: 3
|
142
142
|
summary: An IRC Bot Building Framework
|
143
143
|
test_files: []
|
144
|
+
has_rdoc: yard
|
data/lib/cinch/#channel.rb#
DELETED
@@ -1,407 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
require "set"
|
3
|
-
require "cinch/target"
|
4
|
-
|
5
|
-
module Cinch
|
6
|
-
# @attr limit
|
7
|
-
# @attr secret
|
8
|
-
# @attr moderated
|
9
|
-
# @attr invite_only
|
10
|
-
# @attr key
|
11
|
-
#
|
12
|
-
# @version 2.0.0
|
13
|
-
class Channel < Target
|
14
|
-
include Syncable
|
15
|
-
include Helpers
|
16
|
-
|
17
|
-
def initialize(name, bot)
|
18
|
-
@bot = bot
|
19
|
-
@name = name
|
20
|
-
# TODO raise if not a channel
|
21
|
-
end
|
22
|
-
|
23
|
-
def users
|
24
|
-
sync_get(:users)
|
25
|
-
end
|
26
|
-
|
27
|
-
def topic
|
28
|
-
sync_get(:topic, lambda {@bot.irc.send "TOPIC #@name"})
|
29
|
-
end
|
30
|
-
|
31
|
-
def bans
|
32
|
-
sync_get(:bans, lambda {@bot.irc.send "MODE #@name +b"})
|
33
|
-
end
|
34
|
-
|
35
|
-
def owners
|
36
|
-
sync_get(:owners, lambda {
|
37
|
-
if !@bot.irc.network.owner_list_mode
|
38
|
-
sync_set(:owners, [])
|
39
|
-
return
|
40
|
-
end
|
41
|
-
@bot.irc.send "MODE #@name +#{@bot.irc.network.owner_list_mode}"
|
42
|
-
})
|
43
|
-
end
|
44
|
-
|
45
|
-
def modes
|
46
|
-
sync_get(:modes, lambda {@bot.irc.send "MODE #@name"})
|
47
|
-
end
|
48
|
-
|
49
|
-
# @group Checks
|
50
|
-
|
51
|
-
# @param [User, String] user An {User}-object or a nickname
|
52
|
-
# @return [Boolean] Check if a user is in the channel
|
53
|
-
# @since 1.1.0
|
54
|
-
# @version 1.1.2
|
55
|
-
def has_user?(user)
|
56
|
-
users.has_key?(User(user))
|
57
|
-
end
|
58
|
-
|
59
|
-
# @return [Boolean] true if `user` is opped in the channel
|
60
|
-
# @since 1.1.0
|
61
|
-
def opped?(user)
|
62
|
-
users[User(user)].include? "o"
|
63
|
-
end
|
64
|
-
|
65
|
-
# @return [Boolean] true if `user` is half-opped in the channel
|
66
|
-
# @since 1.1.0
|
67
|
-
def half_opped?(user)
|
68
|
-
users[User(user)].include? "h"
|
69
|
-
end
|
70
|
-
|
71
|
-
# @return [Boolean] true if `user` is voiced in the channel
|
72
|
-
# @since 1.1.0
|
73
|
-
def voiced?(user)
|
74
|
-
users[User(user)].include? "v"
|
75
|
-
end
|
76
|
-
|
77
|
-
# @endgroup
|
78
|
-
|
79
|
-
# @group User groups
|
80
|
-
# @return [Array<User>] All ops in the channel
|
81
|
-
# @since 2.0.0
|
82
|
-
def ops
|
83
|
-
users.select {|user, modes| modes.include?("o")}.keys
|
84
|
-
end
|
85
|
-
|
86
|
-
# @return [Array<User>] All half-ops in the channel
|
87
|
-
# @since 2.0.0
|
88
|
-
def half_ops
|
89
|
-
users.select {|user, modes| modes.include?("h")}.keys
|
90
|
-
end
|
91
|
-
|
92
|
-
# @return [Array<User>] All voiced users in the channel
|
93
|
-
# @since 2.0.0
|
94
|
-
def voiced
|
95
|
-
users.select {|user, modes| modes.include?("v")}.keys
|
96
|
-
end
|
97
|
-
|
98
|
-
# @return [Array<User>] All admins in the channel
|
99
|
-
# @since 2.0.0
|
100
|
-
def admins
|
101
|
-
users.select {|user, modes| modes.include?("a")}.keys
|
102
|
-
end
|
103
|
-
# @endgroup
|
104
|
-
|
105
|
-
# @return [Integer] The maximum number of allowed users in the
|
106
|
-
# channel. 0 if unlimited.
|
107
|
-
def limit
|
108
|
-
modes["l"].to_i
|
109
|
-
end
|
110
|
-
|
111
|
-
def limit=(val)
|
112
|
-
if val == -1 or val.nil?
|
113
|
-
mode "-l"
|
114
|
-
else
|
115
|
-
mode "+l #{val}"
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
# @return [Boolean] true if the channel is secret (+s)
|
120
|
-
def secret?
|
121
|
-
modes["s"]
|
122
|
-
end
|
123
|
-
alias_method :secret, :secret?
|
124
|
-
|
125
|
-
def secret=(bool)
|
126
|
-
if bool
|
127
|
-
mode "+s"
|
128
|
-
else
|
129
|
-
mode "-s"
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
# @return [Boolean] true if the channel is moderated
|
134
|
-
def moderated?
|
135
|
-
modes["m"]
|
136
|
-
end
|
137
|
-
alias_method :moderated, :moderated?
|
138
|
-
|
139
|
-
def moderated=(bool)
|
140
|
-
if bool
|
141
|
-
mode "+m"
|
142
|
-
else
|
143
|
-
mode "-m"
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
# @return [Boolean] true if the channel is invite only (+i)
|
148
|
-
def invite_only?
|
149
|
-
modes["i"]
|
150
|
-
end
|
151
|
-
alias_method :invite_only, :invite_only?
|
152
|
-
|
153
|
-
def invite_only=(bool)
|
154
|
-
if bool
|
155
|
-
mode "+i"
|
156
|
-
else
|
157
|
-
mode "-i"
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
# @return [String, nil] The channel's key (aka password)
|
162
|
-
def key
|
163
|
-
modes["k"]
|
164
|
-
end
|
165
|
-
|
166
|
-
def key=(new_key)
|
167
|
-
if new_key.nil?
|
168
|
-
mode "-k #{key}"
|
169
|
-
else
|
170
|
-
mode "+k #{new_key}"
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
# @api private
|
175
|
-
# @return [void]
|
176
|
-
def sync_modes
|
177
|
-
sync_await(:users)
|
178
|
-
sync_unset(:users)
|
179
|
-
|
180
|
-
if @bot.irc.isupport["WHOX"]
|
181
|
-
@bot.irc.send "WHO #@name %acfhnru"
|
182
|
-
else
|
183
|
-
@bot.irc.send "WHO #@name"
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
# @group Channel Manipulation
|
188
|
-
|
189
|
-
# Bans someone from the channel.
|
190
|
-
#
|
191
|
-
# @param [Mask, String, #mask] target the mask, or an object having a mask, to ban
|
192
|
-
# @return [Mask] the mask used for banning
|
193
|
-
# @see #unban #unban for unbanning users
|
194
|
-
def ban(target)
|
195
|
-
mask = Mask.from(target)
|
196
|
-
|
197
|
-
@bot.irc.send "MODE #@name +b #{mask}"
|
198
|
-
mask
|
199
|
-
end
|
200
|
-
|
201
|
-
# Unbans someone from the channel.
|
202
|
-
#
|
203
|
-
# @param [Mask, String, #mask] target the mask to unban
|
204
|
-
# @return [Mask] the mask used for unbanning
|
205
|
-
# @see #ban #ban for banning users
|
206
|
-
def unban(target)
|
207
|
-
mask = Mask.from(target)
|
208
|
-
|
209
|
-
@bot.irc.send "MODE #@name -b #{mask}"
|
210
|
-
mask
|
211
|
-
end
|
212
|
-
|
213
|
-
# Ops a user.
|
214
|
-
#
|
215
|
-
# @param [String, User] user the user to op
|
216
|
-
# @return [void]
|
217
|
-
def op(user)
|
218
|
-
@bot.irc.send "MODE #@name +o #{user}"
|
219
|
-
end
|
220
|
-
|
221
|
-
# Deops a user.
|
222
|
-
#
|
223
|
-
# @param [String, User] user the user to deop
|
224
|
-
# @return [void]
|
225
|
-
def deop(user)
|
226
|
-
@bot.irc.send "MODE #@name -o #{user}"
|
227
|
-
end
|
228
|
-
|
229
|
-
# Voices a user.
|
230
|
-
#
|
231
|
-
# @param [String, User] user the user to voice
|
232
|
-
# @return [void]
|
233
|
-
def voice(user)
|
234
|
-
@bot.irc.send "MODE #@name +v #{user}"
|
235
|
-
end
|
236
|
-
|
237
|
-
# Devoices a user.
|
238
|
-
#
|
239
|
-
# @param [String, User] user the user to devoice
|
240
|
-
# @return [void]
|
241
|
-
def devoice(user)
|
242
|
-
@bot.irc.send "MODE #@name -v #{user}"
|
243
|
-
end
|
244
|
-
|
245
|
-
# Invites a user to the channel.
|
246
|
-
#
|
247
|
-
# @param [String, User] user the user to invite
|
248
|
-
# @return [void]
|
249
|
-
def invite(user)
|
250
|
-
@bot.irc.send("INVITE #{user} #@name")
|
251
|
-
end
|
252
|
-
|
253
|
-
undef_method(:topic=)
|
254
|
-
# Sets the topic.
|
255
|
-
#
|
256
|
-
# @param [String] new_topic the new topic
|
257
|
-
# @raise [Exceptions::TopicTooLong] Raised if the bot is operating
|
258
|
-
# in {Bot#strict? strict mode} and when the new topic is too long.
|
259
|
-
def topic=(new_topic)
|
260
|
-
if new_topic.size > @bot.irc.isupport["TOPICLEN"] && @bot.strict?
|
261
|
-
raise Exceptions::TopicTooLong, new_topic
|
262
|
-
end
|
263
|
-
|
264
|
-
@bot.irc.send "TOPIC #@name :#{new_topic}"
|
265
|
-
end
|
266
|
-
|
267
|
-
# Kicks a user from the channel.
|
268
|
-
#
|
269
|
-
# @param [String, User] user the user to kick
|
270
|
-
# @param [String] reason a reason for the kick
|
271
|
-
# @raise [Exceptions::KickReasonTooLong]
|
272
|
-
# @return [void]
|
273
|
-
def kick(user, reason = nil)
|
274
|
-
if reason.to_s.size > @bot.irc.isupport["KICKLEN"] && @bot.strict?
|
275
|
-
raise Exceptions::KickReasonTooLong, reason
|
276
|
-
end
|
277
|
-
|
278
|
-
@bot.irc.send("KICK #@name #{user} :#{reason}")
|
279
|
-
end
|
280
|
-
|
281
|
-
# Removes a user from the channel.
|
282
|
-
#
|
283
|
-
# This uses the REMOVE command, which is a non-standardized
|
284
|
-
# extension. Unlike a kick, it makes a user part. This prevents
|
285
|
-
# auto-rejoin scripts from firing and might also be perceived as
|
286
|
-
# less aggressive by some. Not all IRC networks support this
|
287
|
-
# command.
|
288
|
-
#
|
289
|
-
# @param [User] user the user to remove
|
290
|
-
# @param [String] reason a reason for the removal
|
291
|
-
# @return [void]
|
292
|
-
def remove(user, reason = nil)
|
293
|
-
@bot.irc.send("REMOVE #@name #{user} :#{reason}")
|
294
|
-
end
|
295
|
-
|
296
|
-
# Sets or unsets modes. Most of the time you won't need this but
|
297
|
-
# use setter methods like {Channel#invite_only=}.
|
298
|
-
#
|
299
|
-
# @param [String] s a mode string
|
300
|
-
# @return [void]
|
301
|
-
# @example
|
302
|
-
# channel.mode "+n"
|
303
|
-
def mode(s)
|
304
|
-
@bot.irc.send "MODE #@name #{s}"
|
305
|
-
end
|
306
|
-
|
307
|
-
# Causes the bot to part from the channel.
|
308
|
-
#
|
309
|
-
# @param [String] message the part message.
|
310
|
-
# @return [void]
|
311
|
-
def part(message = nil)
|
312
|
-
@bot.irc.send "PART #@name :#{message}"
|
313
|
-
end
|
314
|
-
|
315
|
-
# Joins the channel
|
316
|
-
#
|
317
|
-
# @param [String] key the channel key, if any. If none is
|
318
|
-
# specified but @key is set, @key will be used
|
319
|
-
# @return [void]
|
320
|
-
def join(key = nil)
|
321
|
-
if key.nil? and self.key != true
|
322
|
-
key = self.key
|
323
|
-
end
|
324
|
-
@bot.irc.send "JOIN #{[@name, key].compact.join(" ")}"
|
325
|
-
end
|
326
|
-
|
327
|
-
# @endgroup
|
328
|
-
|
329
|
-
# @api private
|
330
|
-
# @return [User] The added user
|
331
|
-
def add_user(user, modes = [])
|
332
|
-
# XXX
|
333
|
-
@users[user] = modes
|
334
|
-
user
|
335
|
-
end
|
336
|
-
|
337
|
-
# @api private
|
338
|
-
# @return [User, nil] The removed user
|
339
|
-
def remove_user(user)
|
340
|
-
# XXX
|
341
|
-
@users.delete(user)
|
342
|
-
end
|
343
|
-
|
344
|
-
# Removes all users
|
345
|
-
#
|
346
|
-
# @api private
|
347
|
-
# @return [void]
|
348
|
-
def clear_users
|
349
|
-
# XXX
|
350
|
-
@users.clear
|
351
|
-
end
|
352
|
-
|
353
|
-
# @note The aliases `msg` and `privmsg` are deprecated and will be
|
354
|
-
# removed in a future version.
|
355
|
-
def send(text, notice = false)
|
356
|
-
# TODO deprecate 'notice' argument
|
357
|
-
text = text.to_s
|
358
|
-
if @modes["c"]
|
359
|
-
# Remove all formatting and colors if the channel doesn't
|
360
|
-
# allow colors.
|
361
|
-
text = Cinch::Formatting.unformat(text)
|
362
|
-
end
|
363
|
-
super(text, notice)
|
364
|
-
end
|
365
|
-
alias_method :msg, :send # deprecated
|
366
|
-
alias_method :privmsg, :send # deprecated
|
367
|
-
undef_method(:msg) # yardoc hack
|
368
|
-
undef_method(:privmsg) # yardoc hack
|
369
|
-
|
370
|
-
# @deprecated
|
371
|
-
def msg(*args)
|
372
|
-
Cinch::Utilities::Deprecation.print_deprecation("2.2.0", "Channel#msg", "Channel#send")
|
373
|
-
send(*args)
|
374
|
-
end
|
375
|
-
|
376
|
-
# @deprecated
|
377
|
-
def privmsg(*args)
|
378
|
-
Cinch::Utilities::Deprecation.print_deprecation("2.2.0", "Channel#privmsg", "Channel#send")
|
379
|
-
send(*args)
|
380
|
-
end
|
381
|
-
|
382
|
-
# @return [Fixnum]
|
383
|
-
def hash
|
384
|
-
@name.hash
|
385
|
-
end
|
386
|
-
|
387
|
-
# @return [String]
|
388
|
-
# @note The alias `to_str` is deprecated and will be removed in a
|
389
|
-
# future version. Channel objects should not be treated like
|
390
|
-
# strings.
|
391
|
-
def to_s
|
392
|
-
@name
|
393
|
-
end
|
394
|
-
alias_method :to_str, :to_s # deprecated
|
395
|
-
undef_method(:to_str) # yardoc hack
|
396
|
-
|
397
|
-
def to_str
|
398
|
-
Cinch::Utilities::Deprecation.print_deprecation("2.2.0", "Channel#to_str", "Channel#to_s")
|
399
|
-
to_s
|
400
|
-
end
|
401
|
-
|
402
|
-
# @return [String]
|
403
|
-
def inspect
|
404
|
-
"#<Channel name=#{@name.inspect}>"
|
405
|
-
end
|
406
|
-
end
|
407
|
-
end
|