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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -2
  3. data/lib/cinch.rb +7 -5
  4. data/lib/cinch/ban.rb +6 -2
  5. data/lib/cinch/bot.rb +21 -31
  6. data/lib/cinch/cached_list.rb +2 -0
  7. data/lib/cinch/callback.rb +2 -0
  8. data/lib/cinch/channel.rb +43 -44
  9. data/lib/cinch/channel_list.rb +2 -0
  10. data/lib/cinch/configuration.rb +8 -6
  11. data/lib/cinch/configuration/bot.rb +35 -33
  12. data/lib/cinch/configuration/dcc.rb +4 -2
  13. data/lib/cinch/configuration/plugins.rb +8 -6
  14. data/lib/cinch/configuration/sasl.rb +6 -4
  15. data/lib/cinch/configuration/ssl.rb +7 -5
  16. data/lib/cinch/configuration/timeouts.rb +4 -2
  17. data/lib/cinch/constants.rb +3 -1
  18. data/lib/cinch/dcc.rb +2 -0
  19. data/lib/cinch/dcc/dccable_object.rb +6 -8
  20. data/lib/cinch/dcc/incoming.rb +2 -0
  21. data/lib/cinch/dcc/incoming/send.rb +10 -8
  22. data/lib/cinch/dcc/outgoing.rb +2 -0
  23. data/lib/cinch/dcc/outgoing/send.rb +13 -14
  24. data/lib/cinch/exceptions.rb +2 -0
  25. data/lib/cinch/formatting.rb +32 -30
  26. data/lib/cinch/handler.rb +15 -13
  27. data/lib/cinch/handler_list.rb +13 -13
  28. data/lib/cinch/helpers.rb +16 -16
  29. data/lib/cinch/irc.rb +118 -142
  30. data/lib/cinch/isupport.rb +22 -20
  31. data/lib/cinch/log_filter.rb +3 -2
  32. data/lib/cinch/logger.rb +7 -2
  33. data/lib/cinch/logger/formatted_logger.rb +17 -13
  34. data/lib/cinch/logger/zcbot_logger.rb +4 -0
  35. data/lib/cinch/logger_list.rb +15 -14
  36. data/lib/cinch/mask.rb +11 -9
  37. data/lib/cinch/message.rb +6 -6
  38. data/lib/cinch/message_queue.rb +5 -4
  39. data/lib/cinch/mode_parser.rb +7 -5
  40. data/lib/cinch/network.rb +2 -0
  41. data/lib/cinch/open_ended_queue.rb +5 -5
  42. data/lib/cinch/pattern.rb +11 -8
  43. data/lib/cinch/plugin.rb +43 -49
  44. data/lib/cinch/plugin_list.rb +4 -4
  45. data/lib/cinch/rubyext/float.rb +3 -3
  46. data/lib/cinch/rubyext/module.rb +2 -0
  47. data/lib/cinch/rubyext/string.rb +8 -6
  48. data/lib/cinch/sasl.rb +2 -0
  49. data/lib/cinch/sasl/dh_blowfish.rb +5 -3
  50. data/lib/cinch/sasl/diffie_hellman.rb +6 -3
  51. data/lib/cinch/sasl/mechanism.rb +2 -0
  52. data/lib/cinch/sasl/plain.rb +2 -0
  53. data/lib/cinch/syncable.rb +10 -9
  54. data/lib/cinch/target.rb +15 -17
  55. data/lib/cinch/timer.rb +9 -7
  56. data/lib/cinch/user.rb +52 -48
  57. data/lib/cinch/user_list.rb +8 -11
  58. data/lib/cinch/utilities/deprecation.rb +5 -5
  59. data/lib/cinch/utilities/encoding.rb +9 -9
  60. data/lib/cinch/utilities/kernel.rb +4 -1
  61. data/lib/cinch/version.rb +3 -1
  62. metadata +4 -4
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Cinch
2
4
  # This class allows querying the IRC network for its name and used
3
5
  # server software as well as certain non-standard behaviour.
@@ -1,4 +1,4 @@
1
- require "thread"
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.wakeup if t
16
+ t&.wakeup
17
17
  rescue ThreadError
18
18
  retry
19
19
  end
20
- }
20
+ end
21
21
  begin
22
- t.run if t
22
+ t&.run
23
23
  rescue ThreadError
24
24
  end
25
25
  end
@@ -1,4 +1,5 @@
1
- # -*- coding: utf-8 -*-
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
- return obj
13
+ obj
13
14
  else
14
15
  escaped = Regexp.escape(obj.to_s)
15
16
  case anchor
16
17
  when :start
17
- return Regexp.new("^" + escaped)
18
+ Regexp.new("^" + escaped)
18
19
  when :end
19
- return Regexp.new(escaped + "$")
20
+ Regexp.new(escaped + "$")
20
21
  when nil
21
- return Regexp.new(Regexp.escape(obj.to_s))
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
- return resolve_proc(obj.call(msg), msg)
29
+ resolve_proc(obj.call(msg), msg)
29
30
  else
30
- return obj
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, @pattern, @suffix = prefix, pattern, suffix
48
+ @prefix = prefix
49
+ @pattern = pattern
50
+ @suffix = suffix
48
51
  end
49
52
 
50
53
  def to_r(msg = nil)
@@ -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? && self.name
46
- @plugin_name = self.name.split("::").last.downcase
47
- else
48
- @plugin_name = new_name
49
- end
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
- self.send("#{key}=", value)
166
+ send("#{key}=", value)
165
167
  end
166
168
  when 2
167
169
  # key, value
168
- self.send("#{args.first}=", args.last)
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
- :use_prefix => true,
198
- :use_suffix => true,
199
- :method => :execute,
200
- :group => nil,
201
- :prefix => nil,
202
- :suffix => nil,
203
- :react_on => nil,
204
- :strip_colors => false,
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 = {:method => :listen}
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 = {:method => :timer, :threaded => true}.merge(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 = {:for => [:match, :listen_to, :ctcp], :method => :hook, :group => nil}.merge(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
- hooks = @hooks
302
- else
303
- hooks = @hooks[type]
304
- end
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
- hooks = hooks.map { |k, v| v }
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
- return hooks.select { |hook| hook.group.nil? || hook.group == group }
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 { |hook|
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.select { |option|
340
- !bot.config.plugins.options[self].has_key?(option)
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 {|timer_struct|
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 = self.method(timer_struct.options[:method])
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 do |timer|
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
@@ -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 = 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
 
@@ -1,3 +1,3 @@
1
- unless Float.const_defined?(:INFINITY)
2
- Float::INFINITY = 1.0/0.0
3
- end
1
+ # frozen_string_literal: true
2
+
3
+ Float::INFINITY = 1.0 / 0.0 unless Float.const_defined?(:INFINITY)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Extensions to Ruby's Module class.
2
4
  class Module
3
5
  # Like `attr_reader`, but for defining a synchronized attribute
@@ -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
- self.tr("A-Z[]\\\\^", "a-z{}|~")
12
+ tr("A-Z[]\\\\^", "a-z{}|~")
11
13
  when :"strict-rfc1459"
12
- self.tr("A-Z[]\\\\", "a-z{}|")
14
+ tr("A-Z[]\\\\", "a-z{}|")
13
15
  else
14
16
  # when :ascii or unknown/nil
15
- self.tr("A-Z", "a-z")
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
- self.tr("a-z", "A-Z")
28
+ tr("a-z", "A-Z")
27
29
  when :rfc1459
28
- self.tr("a-z{}|~", "A-Z[]\\\\^")
30
+ tr("a-z{}|~", "A-Z[]\\\\^")
29
31
  when :"strict-rfc1459"
30
- self.tr("a-z{}|", "A-Z[]\\\\")
32
+ tr("a-z{}|", "A-Z[]\\\\")
31
33
  end
32
34
  end
33
35
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "cinch/sasl/diffie_hellman"
2
4
  require "cinch/sasl/plain"
3
5
  require "cinch/sasl/dh_blowfish"
@@ -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.unpack("n").first
26
+ size = payload.unpack1("n")
25
27
  payload.slice!(0, 2)
26
- pgy << payload.unpack("a#{size}").first
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 && @e.between?(2, @p - 2) && bits_set(@e) > 1
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('1')
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
- return result
46
+ result
44
47
  end
45
48
  end
46
49
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Cinch
2
4
  module SASL
3
5
  class Mechanism
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "base64"
2
4
  require "cinch/sasl/mechanism"
3
5
 
@@ -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
- while true
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, self.inspect, waited / 10]
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, self.inspect]
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
- if @when_requesting_synced_attribute
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
- return @data[attribute]
72
+ @data[attribute]
72
73
  else
73
- return instance_variable_get("@#{attribute}")
74
+ instance_variable_get("@#{attribute}")
74
75
  end
75
76
  end
76
77