grinch 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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/network.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
# Like Ruby's Queue class, but allowing both pushing and unshifting
|
4
4
|
# objects.
|
@@ -9,17 +9,17 @@ class OpenEndedQueue < Queue
|
|
9
9
|
# @return [void]
|
10
10
|
def unshift(obj)
|
11
11
|
t = nil
|
12
|
-
@mutex.synchronize
|
12
|
+
@mutex.synchronize do
|
13
13
|
@que.unshift obj
|
14
14
|
begin
|
15
15
|
t = @waiting.shift
|
16
|
-
t
|
16
|
+
t&.wakeup
|
17
17
|
rescue ThreadError
|
18
18
|
retry
|
19
19
|
end
|
20
|
-
|
20
|
+
end
|
21
21
|
begin
|
22
|
-
t
|
22
|
+
t&.run
|
23
23
|
rescue ThreadError
|
24
24
|
end
|
25
25
|
end
|
data/lib/cinch/pattern.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Cinch
|
3
4
|
# @api private
|
4
5
|
# @since 1.1.0
|
@@ -9,25 +10,25 @@ module Cinch
|
|
9
10
|
def self.obj_to_r(obj, anchor = nil)
|
10
11
|
case obj
|
11
12
|
when Regexp, NilClass
|
12
|
-
|
13
|
+
obj
|
13
14
|
else
|
14
15
|
escaped = Regexp.escape(obj.to_s)
|
15
16
|
case anchor
|
16
17
|
when :start
|
17
|
-
|
18
|
+
Regexp.new("^" + escaped)
|
18
19
|
when :end
|
19
|
-
|
20
|
+
Regexp.new(escaped + "$")
|
20
21
|
when nil
|
21
|
-
|
22
|
+
Regexp.new(Regexp.escape(obj.to_s))
|
22
23
|
end
|
23
24
|
end
|
24
25
|
end
|
25
26
|
|
26
27
|
def self.resolve_proc(obj, msg = nil)
|
27
28
|
if obj.is_a?(Proc)
|
28
|
-
|
29
|
+
resolve_proc(obj.call(msg), msg)
|
29
30
|
else
|
30
|
-
|
31
|
+
obj
|
31
32
|
end
|
32
33
|
end
|
33
34
|
|
@@ -44,7 +45,9 @@ module Cinch
|
|
44
45
|
attr_reader :suffix
|
45
46
|
attr_reader :pattern
|
46
47
|
def initialize(prefix, pattern, suffix)
|
47
|
-
@prefix
|
48
|
+
@prefix = prefix
|
49
|
+
@pattern = pattern
|
50
|
+
@suffix = suffix
|
48
51
|
end
|
49
52
|
|
50
53
|
def to_r(msg = nil)
|
data/lib/cinch/plugin.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "cinch/helpers"
|
2
4
|
|
3
5
|
module Cinch
|
@@ -42,11 +44,11 @@ module Cinch
|
|
42
44
|
|
43
45
|
# @return [String]
|
44
46
|
def plugin_name=(new_name)
|
45
|
-
if new_name.nil? &&
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
47
|
+
@plugin_name = if new_name.nil? && name
|
48
|
+
name.split("::").last.downcase
|
49
|
+
else
|
50
|
+
new_name
|
51
|
+
end
|
50
52
|
end
|
51
53
|
|
52
54
|
# @return [Array<Matcher>] All matchers
|
@@ -124,7 +126,7 @@ module Cinch
|
|
124
126
|
@listeners = []
|
125
127
|
@timers = []
|
126
128
|
@help = nil
|
127
|
-
@hooks = Hash.new{|h, k| h[k] = []}
|
129
|
+
@hooks = Hash.new { |h, k| h[k] = [] }
|
128
130
|
@prefix = nil
|
129
131
|
@suffix = nil
|
130
132
|
@react_on = :message
|
@@ -161,13 +163,13 @@ module Cinch
|
|
161
163
|
when 1
|
162
164
|
# {:key => value, ...}
|
163
165
|
args.first.each do |key, value|
|
164
|
-
|
166
|
+
send("#{key}=", value)
|
165
167
|
end
|
166
168
|
when 2
|
167
169
|
# key, value
|
168
|
-
|
170
|
+
send("#{args.first}=", args.last)
|
169
171
|
else
|
170
|
-
raise ArgumentError # TODO proper error message
|
172
|
+
raise ArgumentError # TODO: proper error message
|
171
173
|
end
|
172
174
|
end
|
173
175
|
|
@@ -194,18 +196,16 @@ module Cinch
|
|
194
196
|
# @todo Document match/listener grouping
|
195
197
|
def match(pattern, options = {})
|
196
198
|
options = {
|
197
|
-
:
|
198
|
-
:
|
199
|
-
:
|
200
|
-
:
|
201
|
-
:
|
202
|
-
:
|
203
|
-
:
|
204
|
-
:
|
199
|
+
use_prefix: true,
|
200
|
+
use_suffix: true,
|
201
|
+
method: :execute,
|
202
|
+
group: nil,
|
203
|
+
prefix: nil,
|
204
|
+
suffix: nil,
|
205
|
+
react_on: nil,
|
206
|
+
strip_colors: false,
|
205
207
|
}.merge(options)
|
206
|
-
if options[:react_on]
|
207
|
-
options[:react_on] = options[:react_on].to_s.to_sym
|
208
|
-
end
|
208
|
+
options[:react_on] = options[:react_on].to_s.to_sym if options[:react_on]
|
209
209
|
matcher = Matcher.new(pattern, *options.values_at(:use_prefix,
|
210
210
|
:use_suffix,
|
211
211
|
:method,
|
@@ -229,12 +229,10 @@ module Cinch
|
|
229
229
|
# execute
|
230
230
|
# @return [Array<Listener>]
|
231
231
|
def listen_to(*types)
|
232
|
-
options = {:
|
233
|
-
if types.last.is_a?(Hash)
|
234
|
-
options.merge!(types.pop)
|
235
|
-
end
|
232
|
+
options = { method: :listen }
|
233
|
+
options.merge!(types.pop) if types.last.is_a?(Hash)
|
236
234
|
|
237
|
-
listeners = types.map {|type| Listener.new(type.to_s.to_sym, options[:method])}
|
235
|
+
listeners = types.map { |type| Listener.new(type.to_s.to_sym, options[:method]) }
|
238
236
|
@listeners.concat listeners
|
239
237
|
|
240
238
|
listeners
|
@@ -266,7 +264,7 @@ module Cinch
|
|
266
264
|
# @return [Timer]
|
267
265
|
# @since 1.1.0
|
268
266
|
def timer(interval, options = {})
|
269
|
-
options = {:
|
267
|
+
options = { method: :timer, threaded: true }.merge(options)
|
270
268
|
timer = Timer.new(interval, options, false)
|
271
269
|
@timers << timer
|
272
270
|
|
@@ -287,7 +285,7 @@ module Cinch
|
|
287
285
|
# @return [Hook]
|
288
286
|
# @since 1.1.0
|
289
287
|
def hook(type, options = {})
|
290
|
-
options = {:
|
288
|
+
options = { for: %i[match listen_to ctcp], method: :hook, group: nil }.merge(options)
|
291
289
|
hook = Hook.new(type, options[:for], options[:method], options[:group])
|
292
290
|
__hooks(type) << hook
|
293
291
|
|
@@ -297,36 +295,34 @@ module Cinch
|
|
297
295
|
# @return [Hash]
|
298
296
|
# @api private
|
299
297
|
def __hooks(type = nil, events = nil, group = nil)
|
300
|
-
if type.nil?
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
298
|
+
hooks = if type.nil?
|
299
|
+
@hooks
|
300
|
+
else
|
301
|
+
@hooks[type]
|
302
|
+
end
|
305
303
|
|
306
304
|
if events.nil?
|
307
305
|
return hooks
|
308
306
|
else
|
309
307
|
events = [*events]
|
310
|
-
if hooks.is_a?(Hash)
|
311
|
-
|
312
|
-
end
|
313
|
-
hooks = hooks.select { |hook| (events & hook.for).size > 0 }
|
308
|
+
hooks = hooks.map { |_k, v| v } if hooks.is_a?(Hash)
|
309
|
+
hooks = hooks.reject { |hook| (events & hook.for).empty? }
|
314
310
|
end
|
315
311
|
|
316
|
-
|
312
|
+
hooks.select { |hook| hook.group.nil? || hook.group == group }
|
317
313
|
end
|
318
314
|
|
319
315
|
# @return [Boolean] True if processing should continue
|
320
316
|
# @api private
|
321
317
|
def call_hooks(type, event, group, instance, args)
|
322
|
-
stop = __hooks(type, event, group).find
|
318
|
+
stop = __hooks(type, event, group).find do |hook|
|
323
319
|
# stop after the first hook that returns false
|
324
320
|
if hook.method.respond_to?(:call)
|
325
321
|
instance.instance_exec(*args, &hook.method) == false
|
326
322
|
else
|
327
323
|
instance.__send__(hook.method, *args) == false
|
328
324
|
end
|
329
|
-
|
325
|
+
end
|
330
326
|
|
331
327
|
!stop
|
332
328
|
end
|
@@ -336,9 +332,9 @@ module Cinch
|
|
336
332
|
# @since 2.0.0
|
337
333
|
# @api private
|
338
334
|
def check_for_missing_options(bot)
|
339
|
-
@required_options.
|
340
|
-
|
341
|
-
|
335
|
+
@required_options.reject do |option|
|
336
|
+
bot.config.plugins.options[self].key?(option)
|
337
|
+
end
|
342
338
|
end
|
343
339
|
end
|
344
340
|
|
@@ -379,13 +375,13 @@ module Cinch
|
|
379
375
|
private :__register_ctcps
|
380
376
|
|
381
377
|
def __register_timers
|
382
|
-
@timers = self.class.timers.map
|
378
|
+
@timers = self.class.timers.map do |timer_struct|
|
383
379
|
@bot.loggers.debug "[plugin] #{self.class.plugin_name}: Registering timer with interval `#{timer_struct.interval}` for method `#{timer_struct.options[:method]}`"
|
384
380
|
|
385
|
-
block =
|
381
|
+
block = method(timer_struct.options[:method])
|
386
382
|
options = timer_struct.options.merge(interval: timer_struct.interval)
|
387
383
|
Cinch::Timer.new(@bot, options, &block)
|
388
|
-
|
384
|
+
end
|
389
385
|
end
|
390
386
|
private :__register_timers
|
391
387
|
|
@@ -479,9 +475,7 @@ module Cinch
|
|
479
475
|
# @since 2.0.0
|
480
476
|
def unregister
|
481
477
|
@bot.loggers.debug "[plugin] #{self.class.plugin_name}: Unloading plugin"
|
482
|
-
@timers.each
|
483
|
-
timer.stop
|
484
|
-
end
|
478
|
+
@timers.each(&:stop)
|
485
479
|
|
486
480
|
handlers.each do |handler|
|
487
481
|
handler.stop
|
@@ -512,4 +506,4 @@ module Cinch
|
|
512
506
|
end
|
513
507
|
end
|
514
508
|
|
515
|
-
# TODO more details in "message dropped" debug output
|
509
|
+
# TODO: more details in "message dropped" debug output
|
data/lib/cinch/plugin_list.rb
CHANGED
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Cinch
|
2
4
|
# @since 2.0.0
|
3
5
|
class PluginList < Array
|
4
6
|
def initialize(bot)
|
5
|
-
@bot
|
7
|
+
@bot = bot
|
6
8
|
super()
|
7
9
|
end
|
8
10
|
|
@@ -24,9 +26,7 @@ module Cinch
|
|
24
26
|
|
25
27
|
# @since 2.0.0
|
26
28
|
def unregister_plugins(plugins)
|
27
|
-
if plugins == self
|
28
|
-
plugins = self.dup
|
29
|
-
end
|
29
|
+
plugins = dup if plugins == self
|
30
30
|
plugins.each { |plugin| unregister_plugin(plugin) }
|
31
31
|
end
|
32
32
|
|
data/lib/cinch/rubyext/float.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Float::INFINITY = 1.0 / 0.0 unless Float.const_defined?(:INFINITY)
|
data/lib/cinch/rubyext/module.rb
CHANGED
data/lib/cinch/rubyext/string.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Extensions to Ruby's String class.
|
2
4
|
class String
|
3
5
|
# Like `String#downcase`, but respecting different IRC casemaps.
|
@@ -7,12 +9,12 @@ class String
|
|
7
9
|
def irc_downcase(mapping)
|
8
10
|
case mapping
|
9
11
|
when :rfc1459
|
10
|
-
|
12
|
+
tr("A-Z[]\\\\^", "a-z{}|~")
|
11
13
|
when :"strict-rfc1459"
|
12
|
-
|
14
|
+
tr("A-Z[]\\\\", "a-z{}|")
|
13
15
|
else
|
14
16
|
# when :ascii or unknown/nil
|
15
|
-
|
17
|
+
tr("A-Z", "a-z")
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
@@ -23,11 +25,11 @@ class String
|
|
23
25
|
def irc_upcase(mapping)
|
24
26
|
case mapping
|
25
27
|
when :ascii
|
26
|
-
|
28
|
+
tr("a-z", "A-Z")
|
27
29
|
when :rfc1459
|
28
|
-
|
30
|
+
tr("a-z{}|~", "A-Z[]\\\\^")
|
29
31
|
when :"strict-rfc1459"
|
30
|
-
|
32
|
+
tr("a-z{}|", "A-Z[]\\\\")
|
31
33
|
end
|
32
34
|
end
|
33
35
|
end
|
data/lib/cinch/sasl.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "openssl"
|
2
4
|
require "base64"
|
3
5
|
require "cinch/sasl/mechanism"
|
@@ -21,13 +23,13 @@ module Cinch
|
|
21
23
|
payload = payload.dup
|
22
24
|
|
23
25
|
3.times do
|
24
|
-
size = payload.
|
26
|
+
size = payload.unpack1("n")
|
25
27
|
payload.slice!(0, 2)
|
26
|
-
pgy << payload.
|
28
|
+
pgy << payload.unpack1("a#{size}")
|
27
29
|
payload.slice!(0, size)
|
28
30
|
end
|
29
31
|
|
30
|
-
pgy.map {|i| OpenSSL::BN.new(i, 2).to_i}
|
32
|
+
pgy.map { |i| OpenSSL::BN.new(i, 2).to_i }
|
31
33
|
end
|
32
34
|
|
33
35
|
# @param [String] user
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Cinch
|
2
4
|
module SASL
|
3
5
|
class DiffieHellman
|
@@ -24,13 +26,14 @@ module Cinch
|
|
24
26
|
end
|
25
27
|
|
26
28
|
private
|
29
|
+
|
27
30
|
# validate a public key
|
28
31
|
def valid?
|
29
|
-
@e
|
32
|
+
@e&.between?(2, @p - 2) && bits_set(@e) > 1
|
30
33
|
end
|
31
34
|
|
32
35
|
def bits_set(e)
|
33
|
-
("%b" % e).count(
|
36
|
+
("%b" % e).count("1")
|
34
37
|
end
|
35
38
|
|
36
39
|
def mod_exp(b, e, m)
|
@@ -40,7 +43,7 @@ module Cinch
|
|
40
43
|
e = e >> 1
|
41
44
|
b = (b * b) % m
|
42
45
|
end
|
43
|
-
|
46
|
+
result
|
44
47
|
end
|
45
48
|
end
|
46
49
|
end
|
data/lib/cinch/sasl/mechanism.rb
CHANGED
data/lib/cinch/sasl/plain.rb
CHANGED
data/lib/cinch/syncable.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Cinch
|
2
4
|
# Provide blocking access to user/channel information.
|
3
5
|
module Syncable
|
@@ -8,17 +10,18 @@ module Cinch
|
|
8
10
|
def wait_until_synced(attr)
|
9
11
|
attr = attr.to_sym
|
10
12
|
waited = 0
|
11
|
-
|
13
|
+
loop do
|
12
14
|
return if attribute_synced?(attr)
|
15
|
+
|
13
16
|
waited += 1
|
14
17
|
|
15
18
|
if waited % 100 == 0
|
16
|
-
bot.loggers.warn "A synced attribute ('%s' for %s) has not been available for %d seconds, still waiting" % [attr,
|
17
|
-
bot.loggers.warn caller.map {|s| " #{s}"}
|
19
|
+
bot.loggers.warn "A synced attribute ('%s' for %s) has not been available for %d seconds, still waiting" % [attr, inspect, waited / 10]
|
20
|
+
bot.loggers.warn caller.map { |s| " #{s}" }
|
18
21
|
|
19
22
|
if waited / 10 >= 30
|
20
23
|
bot.loggers.warn " Giving up..."
|
21
|
-
raise Exceptions::SyncedAttributeNotAvailable, "'%s' for %s" % [attr,
|
24
|
+
raise Exceptions::SyncedAttributeNotAvailable, "'%s' for %s" % [attr, inspect]
|
22
25
|
end
|
23
26
|
end
|
24
27
|
sleep 0.1
|
@@ -61,16 +64,14 @@ module Cinch
|
|
61
64
|
# @api private
|
62
65
|
def attr(attribute, data = false, unsync = false)
|
63
66
|
unless unsync
|
64
|
-
|
65
|
-
@when_requesting_synced_attribute.call(attribute)
|
66
|
-
end
|
67
|
+
@when_requesting_synced_attribute&.call(attribute)
|
67
68
|
wait_until_synced(attribute)
|
68
69
|
end
|
69
70
|
|
70
71
|
if data
|
71
|
-
|
72
|
+
@data[attribute]
|
72
73
|
else
|
73
|
-
|
74
|
+
instance_variable_get("@#{attribute}")
|
74
75
|
end
|
75
76
|
end
|
76
77
|
|