grinch 1.0.1 → 1.1.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.
- checksums.yaml +4 -4
- data/README.md +4 -2
- data/lib/cinch.rb +7 -5
- data/lib/cinch/ban.rb +6 -2
- data/lib/cinch/bot.rb +21 -31
- data/lib/cinch/cached_list.rb +2 -0
- data/lib/cinch/callback.rb +2 -0
- data/lib/cinch/channel.rb +43 -44
- data/lib/cinch/channel_list.rb +2 -0
- data/lib/cinch/configuration.rb +8 -6
- data/lib/cinch/configuration/bot.rb +35 -33
- data/lib/cinch/configuration/dcc.rb +4 -2
- data/lib/cinch/configuration/plugins.rb +8 -6
- data/lib/cinch/configuration/sasl.rb +6 -4
- data/lib/cinch/configuration/ssl.rb +7 -5
- data/lib/cinch/configuration/timeouts.rb +4 -2
- data/lib/cinch/constants.rb +3 -1
- data/lib/cinch/dcc.rb +2 -0
- data/lib/cinch/dcc/dccable_object.rb +6 -8
- data/lib/cinch/dcc/incoming.rb +2 -0
- data/lib/cinch/dcc/incoming/send.rb +10 -8
- data/lib/cinch/dcc/outgoing.rb +2 -0
- data/lib/cinch/dcc/outgoing/send.rb +13 -14
- data/lib/cinch/exceptions.rb +2 -0
- data/lib/cinch/formatting.rb +32 -30
- data/lib/cinch/handler.rb +15 -13
- data/lib/cinch/handler_list.rb +13 -13
- data/lib/cinch/helpers.rb +16 -16
- data/lib/cinch/irc.rb +118 -142
- data/lib/cinch/isupport.rb +22 -20
- data/lib/cinch/log_filter.rb +3 -2
- data/lib/cinch/logger.rb +7 -2
- data/lib/cinch/logger/formatted_logger.rb +17 -13
- data/lib/cinch/logger/zcbot_logger.rb +4 -0
- data/lib/cinch/logger_list.rb +15 -14
- data/lib/cinch/mask.rb +11 -9
- data/lib/cinch/message.rb +6 -6
- data/lib/cinch/message_queue.rb +5 -4
- data/lib/cinch/mode_parser.rb +7 -5
- data/lib/cinch/network.rb +2 -0
- data/lib/cinch/open_ended_queue.rb +5 -5
- data/lib/cinch/pattern.rb +11 -8
- data/lib/cinch/plugin.rb +43 -49
- data/lib/cinch/plugin_list.rb +4 -4
- data/lib/cinch/rubyext/float.rb +3 -3
- data/lib/cinch/rubyext/module.rb +2 -0
- data/lib/cinch/rubyext/string.rb +8 -6
- data/lib/cinch/sasl.rb +2 -0
- data/lib/cinch/sasl/dh_blowfish.rb +5 -3
- data/lib/cinch/sasl/diffie_hellman.rb +6 -3
- data/lib/cinch/sasl/mechanism.rb +2 -0
- data/lib/cinch/sasl/plain.rb +2 -0
- data/lib/cinch/syncable.rb +10 -9
- data/lib/cinch/target.rb +15 -17
- data/lib/cinch/timer.rb +9 -7
- data/lib/cinch/user.rb +52 -48
- data/lib/cinch/user_list.rb +8 -11
- data/lib/cinch/utilities/deprecation.rb +5 -5
- data/lib/cinch/utilities/encoding.rb +9 -9
- data/lib/cinch/utilities/kernel.rb +4 -1
- data/lib/cinch/version.rb +3 -1
- metadata +4 -4
data/lib/cinch/target.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Cinch
|
2
4
|
# @since 2.0.0
|
3
5
|
class Target
|
@@ -30,7 +32,7 @@ module Cinch
|
|
30
32
|
# @note The aliases `msg` and `privmsg` are deprecated and will be
|
31
33
|
# removed in a future version.
|
32
34
|
def send(text, notice = false)
|
33
|
-
# TODO deprecate `notice` argument, put splitting into own
|
35
|
+
# TODO: deprecate `notice` argument, put splitting into own
|
34
36
|
# method
|
35
37
|
text = text.to_s
|
36
38
|
split_start = @bot.config.message_split_start || ""
|
@@ -42,12 +44,12 @@ module Cinch
|
|
42
44
|
splitted = split_message(line, prefix, split_start, split_end)
|
43
45
|
|
44
46
|
splitted[0, (@bot.config.max_messages || splitted.size)].each do |string|
|
45
|
-
@bot.irc.send("#{command}
|
47
|
+
@bot.irc.send("#{command} #{@name} :#{string}")
|
46
48
|
end
|
47
49
|
end
|
48
50
|
end
|
49
|
-
|
50
|
-
|
51
|
+
alias msg send # deprecated
|
52
|
+
alias privmsg send # deprecated
|
51
53
|
undef_method(:msg) # yardoc hack
|
52
54
|
undef_method(:privmsg) # yardoc hack
|
53
55
|
|
@@ -78,8 +80,8 @@ module Cinch
|
|
78
80
|
def safe_send(text, notice = false)
|
79
81
|
send(Cinch::Helpers.sanitize(text), notice)
|
80
82
|
end
|
81
|
-
|
82
|
-
|
83
|
+
alias safe_msg safe_send # deprecated
|
84
|
+
alias safe_privmsg safe_msg # deprecated
|
83
85
|
undef_method(:safe_msg) # yardoc hack
|
84
86
|
undef_method(:safe_privmsg) # yardoc hack
|
85
87
|
|
@@ -95,7 +97,6 @@ module Cinch
|
|
95
97
|
send(*args)
|
96
98
|
end
|
97
99
|
|
98
|
-
|
99
100
|
# Like {#safe_msg} but for notices.
|
100
101
|
#
|
101
102
|
# @return (see #safe_msg)
|
@@ -113,7 +114,7 @@ module Cinch
|
|
113
114
|
# @see #safe_action
|
114
115
|
def action(text)
|
115
116
|
line = text.to_s.each_line.first.chomp
|
116
|
-
@bot.irc.send("PRIVMSG
|
117
|
+
@bot.irc.send("PRIVMSG #{@name} :\001ACTION #{line}\001")
|
117
118
|
end
|
118
119
|
|
119
120
|
# Like {#action}, but remove any non-printable characters from
|
@@ -163,28 +164,25 @@ module Cinch
|
|
163
164
|
left <=> other.name.irc_downcase(casemapping)
|
164
165
|
elsif other.is_a?(String)
|
165
166
|
left <=> other.irc_downcase(casemapping)
|
166
|
-
else
|
167
|
-
nil
|
168
167
|
end
|
169
168
|
end
|
170
169
|
|
171
170
|
private
|
171
|
+
|
172
172
|
def split_message(msg, prefix, split_start, split_end)
|
173
173
|
max_bytesize = 510 - prefix.bytesize
|
174
174
|
max_bytesize_without_end = max_bytesize - split_end.bytesize
|
175
175
|
|
176
|
-
if msg.bytesize <= max_bytesize
|
177
|
-
return [msg]
|
178
|
-
end
|
176
|
+
return [msg] if msg.bytesize <= max_bytesize
|
179
177
|
|
180
178
|
splitted = []
|
181
179
|
while msg.bytesize > max_bytesize_without_end
|
182
180
|
acc = 0
|
183
|
-
acc_rune_sizes = msg.each_char.map
|
181
|
+
acc_rune_sizes = msg.each_char.map do |ch|
|
184
182
|
acc += ch.bytesize
|
185
|
-
|
183
|
+
end
|
186
184
|
|
187
|
-
max_rune = acc_rune_sizes.rindex {|bs| bs <= max_bytesize_without_end} || 0
|
185
|
+
max_rune = acc_rune_sizes.rindex { |bs| bs <= max_bytesize_without_end } || 0
|
188
186
|
r = [msg.rindex(/\s/, max_rune) || (max_rune + 1), 1].max
|
189
187
|
|
190
188
|
splitted << (msg[0...r] + split_end)
|
@@ -193,7 +191,7 @@ module Cinch
|
|
193
191
|
splitted << msg
|
194
192
|
|
195
193
|
# clean string from any substitute characters
|
196
|
-
splitted.map {|string| string.tr("\cz", " ")}
|
194
|
+
splitted.map { |string| string.tr("\cz", " ") }
|
197
195
|
end
|
198
196
|
end
|
199
197
|
end
|
data/lib/cinch/timer.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "cinch/helpers"
|
2
4
|
|
3
5
|
module Cinch
|
@@ -41,8 +43,8 @@ module Cinch
|
|
41
43
|
# will stop. This value will automatically reset after
|
42
44
|
# restarting the timer.
|
43
45
|
attr_accessor :shots
|
44
|
-
|
45
|
-
|
46
|
+
alias threaded? threaded
|
47
|
+
alias started? started
|
46
48
|
|
47
49
|
# @return [ThreadGroup]
|
48
50
|
# @api private
|
@@ -62,7 +64,7 @@ module Cinch
|
|
62
64
|
# @option options [Boolean] :stop_automaticall (true) If true, the
|
63
65
|
# timer will automatically stop when the bot disconnects.
|
64
66
|
def initialize(bot, options, &block)
|
65
|
-
options = {:
|
67
|
+
options = { threaded: true, shots: Float::INFINITY, start_automatically: true, stop_automatically: true }.merge(options)
|
66
68
|
|
67
69
|
@bot = bot
|
68
70
|
@interval = options[:interval].to_f
|
@@ -76,13 +78,13 @@ module Cinch
|
|
76
78
|
@thread_group = ThreadGroup.new
|
77
79
|
|
78
80
|
if options[:start_automatically]
|
79
|
-
@bot.on :connect, //, self do |
|
81
|
+
@bot.on :connect, //, self do |_m, timer|
|
80
82
|
timer.start
|
81
83
|
end
|
82
84
|
end
|
83
85
|
|
84
86
|
if options[:stop_automatically]
|
85
|
-
@bot.on :disconnect, //, self do |
|
87
|
+
@bot.on :disconnect, //, self do |_m, timer|
|
86
88
|
timer.stop
|
87
89
|
end
|
88
90
|
end
|
@@ -104,7 +106,7 @@ module Cinch
|
|
104
106
|
@shots = @orig_shots
|
105
107
|
|
106
108
|
@thread_group.add Thread.new {
|
107
|
-
while @shots > 0
|
109
|
+
while @shots > 0
|
108
110
|
sleep @interval
|
109
111
|
if threaded?
|
110
112
|
Thread.new do
|
@@ -133,7 +135,7 @@ module Cinch
|
|
133
135
|
|
134
136
|
@bot.loggers.debug "[timer] Stopping timer #{self}"
|
135
137
|
|
136
|
-
@thread_group.list.each
|
138
|
+
@thread_group.list.each(&:kill)
|
137
139
|
@started = false
|
138
140
|
end
|
139
141
|
|
data/lib/cinch/user.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require "cinch/target"
|
3
4
|
require "timeout"
|
4
5
|
|
@@ -37,7 +38,7 @@ module Cinch
|
|
37
38
|
# @return [Boolean]
|
38
39
|
attr_reader :synced
|
39
40
|
# @since 2.1.0
|
40
|
-
|
41
|
+
alias synced? synced
|
41
42
|
|
42
43
|
# @return [Boolean]
|
43
44
|
# @api private
|
@@ -74,7 +75,7 @@ module Cinch
|
|
74
75
|
def unknown
|
75
76
|
attr(:unknown?, true, false)
|
76
77
|
end
|
77
|
-
|
78
|
+
alias unknown? unknown
|
78
79
|
|
79
80
|
# @note This attribute will be updated by various events, but
|
80
81
|
# unless {#monitor} is being used, this information cannot be
|
@@ -82,7 +83,7 @@ module Cinch
|
|
82
83
|
def online
|
83
84
|
attr(:online?, true, false)
|
84
85
|
end
|
85
|
-
|
86
|
+
alias online? online
|
86
87
|
|
87
88
|
def channels
|
88
89
|
attr(:channels, true, false)
|
@@ -91,13 +92,13 @@ module Cinch
|
|
91
92
|
def secure
|
92
93
|
attr(:secure?, true, false)
|
93
94
|
end
|
94
|
-
|
95
|
+
alias secure? secure
|
95
96
|
|
96
97
|
# @since 2.1.0
|
97
98
|
def oper
|
98
99
|
attr(:oper?, true, false)
|
99
100
|
end
|
100
|
-
|
101
|
+
alias oper? oper
|
101
102
|
|
102
103
|
# @private
|
103
104
|
def user_unsynced
|
@@ -180,7 +181,7 @@ module Cinch
|
|
180
181
|
# @note The attribute writer is in fact part of the private API
|
181
182
|
attr_reader :monitored
|
182
183
|
# @since 2.1.0
|
183
|
-
|
184
|
+
alias monitored? monitored
|
184
185
|
|
185
186
|
# @api private
|
186
187
|
attr_writer :monitored
|
@@ -189,18 +190,18 @@ module Cinch
|
|
189
190
|
# class. Use {UserList#find_ensured} instead.
|
190
191
|
def initialize(*args)
|
191
192
|
@data = {
|
192
|
-
:
|
193
|
-
:
|
194
|
-
:
|
195
|
-
:
|
196
|
-
:
|
197
|
-
:
|
198
|
-
|
199
|
-
|
200
|
-
:
|
201
|
-
|
202
|
-
:
|
203
|
-
|
193
|
+
user: nil,
|
194
|
+
host: nil,
|
195
|
+
realname: nil,
|
196
|
+
authname: nil,
|
197
|
+
idle: 0,
|
198
|
+
signed_on_at: nil,
|
199
|
+
unknown?: false,
|
200
|
+
online?: false,
|
201
|
+
channels: [],
|
202
|
+
secure?: false,
|
203
|
+
away: nil,
|
204
|
+
oper?: false,
|
204
205
|
}
|
205
206
|
case args.size
|
206
207
|
when 2
|
@@ -211,9 +212,9 @@ module Cinch
|
|
211
212
|
raise ArgumentError
|
212
213
|
end
|
213
214
|
|
214
|
-
@synced_attributes
|
215
|
+
@synced_attributes = Set.new
|
215
216
|
|
216
|
-
@when_requesting_synced_attribute = lambda {|attr|
|
217
|
+
@when_requesting_synced_attribute = lambda { |attr|
|
217
218
|
unless attribute_synced?(attr)
|
218
219
|
@data[:unknown?] = false
|
219
220
|
unsync :unknown?
|
@@ -248,18 +249,19 @@ module Cinch
|
|
248
249
|
# future version.
|
249
250
|
def refresh
|
250
251
|
return if @in_whois
|
252
|
+
|
251
253
|
@data.keys.each do |attr|
|
252
254
|
unsync attr
|
253
255
|
end
|
254
256
|
|
255
257
|
@in_whois = true
|
256
258
|
if @bot.irc.network.whois_only_one_argument?
|
257
|
-
@bot.irc.send "WHOIS
|
259
|
+
@bot.irc.send "WHOIS #{@name}"
|
258
260
|
else
|
259
|
-
@bot.irc.send "WHOIS
|
261
|
+
@bot.irc.send "WHOIS #{@name} #{@name}"
|
260
262
|
end
|
261
263
|
end
|
262
|
-
|
264
|
+
alias whois refresh # deprecated
|
263
265
|
undef_method(:whois) # yardoc hack
|
264
266
|
|
265
267
|
# @deprecated
|
@@ -303,16 +305,16 @@ module Cinch
|
|
303
305
|
end
|
304
306
|
|
305
307
|
if values[:registered]
|
306
|
-
values[:authname] ||=
|
308
|
+
values[:authname] ||= nick
|
307
309
|
values.delete(:registered)
|
308
310
|
end
|
309
311
|
{
|
310
|
-
:
|
311
|
-
:
|
312
|
-
|
313
|
-
|
314
|
-
:
|
315
|
-
:
|
312
|
+
authname: nil,
|
313
|
+
idle: 0,
|
314
|
+
secure?: false,
|
315
|
+
oper?: false,
|
316
|
+
away: nil,
|
317
|
+
channels: [],
|
316
318
|
}.merge(values).each do |attr, value|
|
317
319
|
sync(attr, value, true)
|
318
320
|
end
|
@@ -351,20 +353,20 @@ module Cinch
|
|
351
353
|
#
|
352
354
|
# @return [Mask]
|
353
355
|
def mask(s = "%n!%u@%h")
|
354
|
-
s = s.gsub(/%(.)/)
|
355
|
-
case
|
356
|
+
s = s.gsub(/%(.)/) do
|
357
|
+
case Regexp.last_match(1)
|
356
358
|
when "n"
|
357
359
|
@name
|
358
360
|
when "u"
|
359
|
-
|
361
|
+
user
|
360
362
|
when "h"
|
361
|
-
|
363
|
+
host
|
362
364
|
when "r"
|
363
|
-
|
365
|
+
realname
|
364
366
|
when "a"
|
365
|
-
|
367
|
+
authname
|
366
368
|
end
|
367
|
-
|
369
|
+
end
|
368
370
|
|
369
371
|
Mask.new(s)
|
370
372
|
end
|
@@ -376,7 +378,7 @@ module Cinch
|
|
376
378
|
def match(other)
|
377
379
|
Mask.from(other) =~ Mask.from(self)
|
378
380
|
end
|
379
|
-
|
381
|
+
alias =~ match
|
380
382
|
|
381
383
|
# Starts monitoring a user's online state by either using MONITOR
|
382
384
|
# or periodically running WHOIS.
|
@@ -386,12 +388,12 @@ module Cinch
|
|
386
388
|
# @see #unmonitor
|
387
389
|
def monitor
|
388
390
|
if @bot.irc.isupport["MONITOR"] > 0
|
389
|
-
@bot.irc.send "MONITOR +
|
391
|
+
@bot.irc.send "MONITOR + #{@name}"
|
390
392
|
else
|
391
393
|
refresh
|
392
|
-
@monitored_timer = Timer.new(@bot, interval: 30)
|
394
|
+
@monitored_timer = Timer.new(@bot, interval: 30) do
|
393
395
|
refresh
|
394
|
-
|
396
|
+
end
|
395
397
|
@monitored_timer.start
|
396
398
|
end
|
397
399
|
|
@@ -405,9 +407,9 @@ module Cinch
|
|
405
407
|
# @see #monitor
|
406
408
|
def unmonitor
|
407
409
|
if @bot.irc.isupport["MONITOR"] > 0
|
408
|
-
@bot.irc.send "MONITOR -
|
410
|
+
@bot.irc.send "MONITOR - #{@name}"
|
409
411
|
else
|
410
|
-
@monitored_timer
|
412
|
+
@monitored_timer&.stop
|
411
413
|
end
|
412
414
|
|
413
415
|
@monitored = false
|
@@ -425,8 +427,7 @@ module Cinch
|
|
425
427
|
dcc = DCC::Outgoing::Send.new(receiver: self,
|
426
428
|
filename: filename,
|
427
429
|
io: io,
|
428
|
-
own_ip: own_ip
|
429
|
-
)
|
430
|
+
own_ip: own_ip)
|
430
431
|
|
431
432
|
dcc.start_server
|
432
433
|
|
@@ -435,6 +436,7 @@ module Cinch
|
|
435
436
|
/\001DCC RESUME #{filename} #{dcc.port} (\d+)\001/,
|
436
437
|
/$/)) do |m, position|
|
437
438
|
next unless m.user == self
|
439
|
+
|
438
440
|
dcc.seek(position.to_i)
|
439
441
|
m.user.send "\001DCC ACCEPT #{filename} #{dcc.port} #{position}\001"
|
440
442
|
|
@@ -460,10 +462,11 @@ module Cinch
|
|
460
462
|
# @return [void]
|
461
463
|
# @api private
|
462
464
|
def online=(bool)
|
463
|
-
notify =
|
465
|
+
notify = __send__("online?_unsynced") != bool && @monitored
|
464
466
|
sync(:online?, bool, true)
|
465
467
|
|
466
468
|
return unless notify
|
469
|
+
|
467
470
|
if bool
|
468
471
|
@bot.handlers.dispatch(:online, nil, self)
|
469
472
|
else
|
@@ -477,7 +480,8 @@ module Cinch
|
|
477
480
|
# @api private
|
478
481
|
# @return [void]
|
479
482
|
def update_nick(new_nick)
|
480
|
-
@last_nick
|
483
|
+
@last_nick = @name
|
484
|
+
@name = new_nick
|
481
485
|
# Unsync authname because some networks tie authentication to
|
482
486
|
# the nick, so the user might not be authenticated anymore after
|
483
487
|
# changing their nick
|
data/lib/cinch/user_list.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "cinch/cached_list"
|
2
4
|
|
3
5
|
module Cinch
|
@@ -22,7 +24,8 @@ module Cinch
|
|
22
24
|
# @return [User]
|
23
25
|
# @see Bot#User
|
24
26
|
def find_ensured(*args)
|
25
|
-
user
|
27
|
+
user = nil
|
28
|
+
host = nil
|
26
29
|
case args.size
|
27
30
|
when 1
|
28
31
|
nick = args.first
|
@@ -35,15 +38,11 @@ module Cinch
|
|
35
38
|
raise ArgumentError
|
36
39
|
end
|
37
40
|
|
38
|
-
if nick == @bot.nick
|
39
|
-
user_obj = @bot
|
40
|
-
end
|
41
|
+
user_obj = @bot if nick == @bot.nick
|
41
42
|
|
42
43
|
downcased_nick = nick.irc_downcase(@bot.irc.isupport["CASEMAPPING"])
|
43
44
|
@mutex.synchronize do
|
44
|
-
if user_obj.nil?
|
45
|
-
user_obj = @cache[downcased_nick] ||= User.new(*bargs, @bot)
|
46
|
-
end
|
45
|
+
user_obj = @cache[downcased_nick] ||= User.new(*bargs, @bot) if user_obj.nil?
|
47
46
|
if user && host
|
48
47
|
# Explicitly set user and host whenever we request a User
|
49
48
|
# object to update them on e.g. JOIN.
|
@@ -59,9 +58,7 @@ module Cinch
|
|
59
58
|
# @param [String] nick nick of a user
|
60
59
|
# @return [User, nil]
|
61
60
|
def find(nick)
|
62
|
-
if nick == @bot.nick
|
63
|
-
return @bot
|
64
|
-
end
|
61
|
+
return @bot if nick == @bot.nick
|
65
62
|
|
66
63
|
downcased_nick = nick.irc_downcase(@bot.irc.isupport["CASEMAPPING"])
|
67
64
|
@mutex.synchronize do
|
@@ -81,7 +78,7 @@ module Cinch
|
|
81
78
|
# @api private
|
82
79
|
# @return [void]
|
83
80
|
def delete(user)
|
84
|
-
@cache.delete_if {|
|
81
|
+
@cache.delete_if { |_n, u| u == user }
|
85
82
|
end
|
86
83
|
end
|
87
84
|
end
|