iirc 0.6.0 → 0.6.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 619cec1c65f965243d45c96b29f02c38d7f6fb576c180587ec468fb8292cfece
4
- data.tar.gz: d3b9ca07dcdb07132b36c35a776f6ea287edf88d51f11bc7c4135eac67ed54e6
3
+ metadata.gz: 35506ead9be0accbdd02186045edf0ff02f5cce1872a430b7f8a73dac493ebae
4
+ data.tar.gz: 0b3e2e0c4bbb74340429601dea13dd13ccbca51f2dec20e8cc6063995092d9d1
5
5
  SHA512:
6
- metadata.gz: e80238e5d75e018b049e2cb1ee545bced58d4745a32243d5480a433774a5dbb29247da204bde26927135411c14102b0dab92dbba460772a1d450d7c8394b283a
7
- data.tar.gz: 7d7a764ee1b744ca006fc6c4fd949d73b7a14ee2765501c11ffb3dd05db13dc8a72272a4cb0bdb00f29da47375494e17ca359cee6fefdd2d22f0f1f7d44cf627
6
+ metadata.gz: 264f63137eb223d2143facc99ef5a8b7970597185223b1c5e64dc14a3197915b2e26059cfeb90ac3b181344e5c2e55196561815c9e1be7a4e9696bdf039451cf
7
+ data.tar.gz: 2c99f6934ebb734ff03882e4833596363843c6f64b43b7720040e61933529be52adaeca64609891f3b9f36953bfe96053233206a434eaf8ecd0968d469d1393e
data/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ ## [0.6.3] - 2022-05-04
2
+
3
+ - [Bot#<<] Strip all CR / LF characters passed to Bot#<<
4
+ - This will help prevent vulns such as:
5
+ https://matrix.org/blog/2022/05/04/0-34-0-security-release-for-matrix-appservice-irc-high-severity
6
+
7
+ ## [0.6.2] - 2022-04-28
8
+
9
+ - [Event] Add CTCP parsing methods
10
+ - [Sender] Nick is the server name when sender is a server
11
+
12
+ ## [0.6.1] - 2022-04-01
13
+
14
+ - Add SedBot example
15
+ - [RegexHooks] Passes matches as args
16
+ - e.g. (evt, match_one, match_two, ..)
17
+ - [RegexHooks] Add some tests
18
+
1
19
  ## [0.6.0] - 2022-03-30
2
20
 
3
21
  - Move modules from IIRC::Bot to IIRC namespace
data/examples/sed.rb ADDED
@@ -0,0 +1,83 @@
1
+ require "iirc"
2
+ require "timeout"
3
+
4
+ SED_REGEX ||= Regexp.new(DATA.read, Regexp::EXTENDED)
5
+
6
+ class SedBot < IIRC::IRCv3Bot
7
+ include IIRC::Batteries
8
+ include IIRC::AcceptInvites
9
+ include IIRC::PrintIO
10
+
11
+ def autojoin_channels
12
+ ['##iirc']
13
+ end
14
+
15
+ def history
16
+ @history ||= Hash.new { |h,k| h[k] = [] }
17
+ end
18
+
19
+ def on_privmsg evt
20
+ case evt.message
21
+ when SED_REGEX
22
+ needle, sub, flags = Regexp.new($1, $3.include?('i')), $2, $3
23
+
24
+ say Timeout.timeout(5) {
25
+ history[reply_target]
26
+ .find { |msg| msg =~ needle }
27
+ .then { |msg|
28
+ if msg and flags[/g/]
29
+ italic msg.gsub(needle, sub)
30
+ elsif msg
31
+ italic msg.sub(needle, sub)
32
+ else
33
+ 'Sorry, no match found'
34
+ end
35
+ }
36
+ }
37
+ else
38
+ history[reply_target].unshift evt.message
39
+ end
40
+ end
41
+ end
42
+
43
+ if __FILE__ == $0
44
+ SedBot.run 'irc.libera.chat', nick: 'Sed[%x]'%rand(256)
45
+ end
46
+
47
+ __END__
48
+
49
+ # Copied from https://www.azabani.com/2014/02/08/writing-irc-sedbot.html
50
+ # This matches the s/(needle)/(replacement)/(flags) parts of a sed pattern
51
+
52
+ ^ # start of the message
53
+ (?: # BEGIN first sed expression
54
+ s/ # sed replacement expression delimiter
55
+ ( # BEGIN needle component
56
+ (?: # BEGIN single needle character
57
+ [^\\/] # anything that isn't a slash or backslash...
58
+ |\\. # ...or any backslash escape
59
+ )* # END single needle character, zero or more
60
+ ) # END needle component
61
+ / # slash between needle and replacement
62
+ ( # BEGIN replacement component
63
+ (?: # BEGIN single replacement character
64
+ [^\\/]|\\. # escape or non-slash-backslash, as above
65
+ )* # END single replacement character, zero or more
66
+ ) # END replacement component
67
+ / # slash between replacement and flags
68
+ ( # BEGIN flags component
69
+ (?: # BEGIN single flag
70
+ g|i|\d+ # "g", "i" or a sequence of digits
71
+ )* # END single flag, zero or more
72
+ ) # END flags component
73
+ ) # END first sed expression
74
+ (?: # BEGIN optional subsequent sed expressions
75
+ ; # semicolon between sed expressions
76
+ s/ # sed replacement expression delimiter, as above
77
+ ((?:[^\\/]|\\.)*) # needle component, as above
78
+ / # slash between needle and replacement, as above
79
+ ((?:[^\\/]|\\.)*) # replacement component, as above
80
+ / # slash between replacement and flags, as above
81
+ ((?:g|i|\d+)*) # flags component, as above
82
+ )* # END optional subsequent sed expressions, zero or more
83
+ $ # end of the message
data/lib/iirc/bot.rb CHANGED
@@ -5,7 +5,7 @@ module IIRC
5
5
  alias :me :user
6
6
 
7
7
  def <<(text)
8
- socket << text + "\r\n"
8
+ socket << text.tr("\r", "").tr("\n", "") + "\r\n"
9
9
  self
10
10
  end
11
11
 
@@ -21,6 +21,10 @@ module IIRC
21
21
  super() if defined? super
22
22
  self.socket = socket
23
23
  self.user = user.is_a?(User) ? user : User.new(**user)
24
+
25
+ if !user.key?(:nick)
26
+ self.user.nick ||= self.class.name&.split('::')&.last
27
+ end
24
28
  end
25
29
 
26
30
  def register!
@@ -35,4 +39,4 @@ module IIRC
35
39
  raise ArgumentError.new('no nick given') unless me.nick && !me.nick.empty?
36
40
  end
37
41
  end
38
- end
42
+ end
data/lib/iirc/event.rb CHANGED
@@ -28,5 +28,39 @@ module IIRC
28
28
  def message
29
29
  args.last
30
30
  end
31
+
32
+ CTCP_REGEX = /^\x01(\w+)(?: ([^\x01]+))?\x01?$/
33
+
34
+ def ctcp?
35
+ message&.match?(CTCP_REGEX)
36
+ end
37
+
38
+ def ctcp_verb
39
+ $1.downcase.to_sym if message =~ CTCP_REGEX
40
+ end
41
+
42
+ def ctcp_message
43
+ $2 if message =~ CTCP_REGEX
44
+ end
45
+
46
+ # Parses CTCP data in message, returning nil or an Array like [:action, "does the Macarena"], [:version], [:version, "SomeClient v0.1"]
47
+ # @example Pattern matching (case)
48
+ # case evt.ctcp
49
+ # in [:action, msg]
50
+ # say "#{evt.nick} did an action: #{italic msg}"
51
+ # in [:version]
52
+ # say "\x01VERSION Ruby IIRC (v#{IIRC::VERSION})\x01"
53
+ # in [:dcc, type, *]
54
+ # say "You want to start a DCC #{type} with me? Are you crazy!?"
55
+ # else
56
+ # end
57
+ # @example Pattern matching (if)
58
+ # on(:privmsg, :be_annoying) { |evt|
59
+ # act "#{thing} also" if [:action, thing] in evt.ctcp
60
+ # }
61
+ # @return [Array<Symbol, String?>, nil] CTCP verb and text content, if any (e.g. [:action, "says hello"], [:clientinfo], [:version, "SomeClient v0.1"])
62
+ def ctcp
63
+ [ctcp_verb, ctcp_message].compact if ctcp?
64
+ end
31
65
  end
32
66
  end
@@ -8,7 +8,7 @@ module IIRC
8
8
  on :'001', :autojoin!
9
9
  end
10
10
 
11
- # Send JOIN for each {#autojoin_channel}
11
+ # Send JOIN for each in {#autojoin_channels}
12
12
  # @return [Array<String>] channels joined
13
13
  def autojoin!
14
14
  for channel in autojoin_channels
@@ -7,8 +7,7 @@ module IIRC
7
7
  def run
8
8
  lines { |line|
9
9
  begin
10
- evt = parse(line)
11
- fire! evt.verb, evt
10
+ self >> line
12
11
  rescue Exception => ex
13
12
  puts ex.message
14
13
  puts ex.backtrace
@@ -16,6 +15,11 @@ module IIRC
16
15
  }
17
16
  end
18
17
 
18
+ def >>(line)
19
+ evt = parse(line)
20
+ fire! evt.verb, evt
21
+ end
22
+
19
23
  def on verb=nil, action=nil, &blk
20
24
  if action and blk
21
25
  define_singleton_method(action, blk)
@@ -20,9 +20,14 @@ module IIRC
20
20
 
21
21
  private
22
22
  def configure_isupport
23
+ on :'001', :clear_isupport
23
24
  on :'005', :store_isupport
24
25
  end
25
26
 
27
+ def clear_isupport
28
+ @isupport = nil
29
+ end
30
+
26
31
  def store_isupport(evt)
27
32
  tokens = evt.args[1..-2]
28
33
 
@@ -66,5 +71,20 @@ module IIRC
66
71
  def channel_prefixes
67
72
  (@channel_prefixes ||= self['CHANTYPES']&.chars.freeze) || ['#'].freeze
68
73
  end
74
+
75
+ # Modes which grant privileges to a user in a channel and their respective
76
+ # prefix characters seen in NAMES, WHO and WHOIS replies.
77
+ # @see https://modern.ircdocs.horse/#channel-membership-prefixes
78
+ # @example qaohv
79
+ # isupport.prefix_modes # => {'q'=>'~', 'a'=>'&', 'o'=>'@', 'h'=>'%', 'v'=>'+'}
80
+ # @return [Hash<String,String>] channel mode => prefix character
81
+ def prefix_modes
82
+ if self['PREFIX'].is_a? String
83
+ modes, symbols = self['PREFIX'][1..].split(')').map!(&:chars)
84
+ Hash[modes.zip(symbols)].freeze
85
+ else
86
+ {}.freeze
87
+ end
88
+ end
69
89
  end
70
90
  end
@@ -13,8 +13,8 @@ module IIRC
13
13
  regex_hooks
14
14
  .filter { |k,v| k === evt.message }
15
15
  .each_value { |actions|
16
- actions.each { |action| call action, evt }
16
+ actions.each { |action| call action, evt, *Regexp.last_match&.values_at(1..) }
17
17
  }
18
18
  end
19
19
  end
20
- end
20
+ end
data/lib/iirc/sender.rb CHANGED
@@ -31,9 +31,9 @@ module IIRC
31
31
  not user.nil?
32
32
  end
33
33
 
34
- def nick; user&.nick end
34
+ def nick; user ? user.nick : without_leading_colon end
35
35
  def username; user&.username end
36
- def host; server? ? without_leading_colon : user.host end
36
+ def host; user ? user.host : without_leading_colon end
37
37
 
38
38
  def to_prefix
39
39
  ":#{self}"
@@ -48,8 +48,9 @@ module IIRC
48
48
  end
49
49
 
50
50
  module_function
51
- # Extends and returns a source string with the IIRC::Sender mixin.
52
- # Duplicates first if the string is frozen. Returns nil if source is nil.
51
+ # Adds the IIRC::Sender mixin to a string.
52
+ # If the string is frozen, a copy is returned.
53
+ # If the source is nil, nil is returned.
53
54
  #
54
55
  # @example :nick!user@host
55
56
  # v = IIRC.Sender(":JimmyWales!jim@wikipedia.org") # => "JimmyWales!jim@wikipedia.org"
@@ -66,4 +67,4 @@ module IIRC
66
67
  (source.frozen? ? source.dup : source).extend(Sender)
67
68
  end
68
69
  end
69
- end
70
+ end
data/lib/iirc/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module IIRC
4
- VERSION = "0.6.0"
4
+ VERSION = "0.6.3"
5
5
  end
data/lib/iirc.rb CHANGED
@@ -49,8 +49,6 @@ module IIRC
49
49
  local_host: local_host, local_port: local_port,
50
50
  ssl_context: ssl_context)
51
51
 
52
- user_params[:nick] = self.name&.split('::').last if !user_params.key?(:nick)
53
-
54
52
  new(socket, **user_params).tap { |bot|
55
53
  bot.register!
56
54
  bot.tap(&blk) if blk
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iirc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - mooff
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-03-30 00:00:00.000000000 Z
11
+ date: 2022-05-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ircparser
@@ -43,6 +43,7 @@ files:
43
43
  - bin/setup
44
44
  - examples/facts.rb
45
45
  - examples/greeter.rb
46
+ - examples/sed.rb
46
47
  - examples/wolfram.rb
47
48
  - iirc.gemspec
48
49
  - lib/iirc.rb