iirc 0.3.0 → 0.4.2

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: 4c856c393db0b7645fa204d003750816cda3ce860b2be538e523f7d8bcf56b4e
4
- data.tar.gz: 74252990a51523295d3dc788579b1f7ea456a995939e35d8c6004556742b7117
3
+ metadata.gz: 393add51d4c945dfa67c0459aee623d0cd0611ebd891a67dba43179fdfc71010
4
+ data.tar.gz: 9cc245c08ecb2aa1dd3ba29992620fa611d6fb021a300fae7476f26a02cfcc2a
5
5
  SHA512:
6
- metadata.gz: 1c02d3b4eac6f4bebb0d2cb46e9241594021f07cb4fa2464508203bab3f1402f98901dd138efa1676d2de7fa678ac3117b08256ae819658c02819ff7dc2adeed
7
- data.tar.gz: bb1fbf17c4f574f099a1b0c47d4e6aa087658c51137c8019facc151ccfd93591125c45b5bd327af6e75a85ae0d3f8ccea434da78b424c5f1c563c8f281413c2e
6
+ metadata.gz: 61bc31ca365d0ad70a84d7ad32352c5feb9ba656f594011c1693d6a43c4e0a54ac31524e8ea8826a1ce19a2e18c079b7edc58c3e083216413cccf268fb2d98ad
7
+ data.tar.gz: a772002465744f4325b5d2dd3c2f8d412b6d09f35743ea93da6e2490396c4f1d90f8d9a1924dcd6eb14030ab0bce76a937524bd4dc5b94b5ec97b6e19b9bf024
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --markup=markdown --private --protected
data/CHANGELOG.md CHANGED
@@ -1,9 +1,37 @@
1
+ ## [0.4.2] - 2022-03-29
2
+
3
+ - Fix example in README
4
+
5
+ ## [0.4.1] - 2022-03-29
6
+
7
+ - [ISupport] Add module to process RPL_ISUPPORT
8
+ - [ISupport] Add Inquiry helpers + docs
9
+
10
+ ## [0.4.0] - 2022-03-27
11
+
12
+ - [Numerics] Add module with constants imported from ircdocs.horse
13
+ - Run `rake numerics` to re-import.
14
+
15
+ - [IIRC.run,IIRC.dial] Support passing a symbol as ssl_context
16
+ - e.g. ssl_context: :no_verify instead of ssl_context: IIRC::SSL.no_verify
17
+
18
+ - The AmbientEvents modules have been reorganised
19
+ - AmbientVerbs is now Ambient::Verbs
20
+ - AmbientEvents => Ambient::Events
21
+ - AmbientEvents::{LabeledRequests,ReplyTarget} => Ambient::{LabeledRequests,ReplyTarget}
22
+
23
+ - #ambient_reply_target() has been replaced with #reply_target(evt=ambient_event)
24
+
25
+ - [Bot.run] Set nick to class name if no param is given
26
+ - `MyBot.run('irc.libera.chat')` is enough to connect to Libera as 'MyBot'
27
+
1
28
  ## [0.3.0] - 2022-03-26
2
29
 
3
30
  - [Bot] Include ReplyTarget
4
31
  - [Hooks] Refactor
5
32
  - Add AcceptInvites module
6
33
  - Improve Greeter example
34
+ - [IIRC.run,IIRC.dial] now accept local_host, local_port keyword arguments
7
35
 
8
36
  ## [0.2.9] - 2022-03-24
9
37
 
data/Gemfile CHANGED
@@ -8,3 +8,6 @@ gemspec
8
8
  gem "rake", "~> 13.0"
9
9
 
10
10
  gem "minitest", "~> 5.0"
11
+
12
+ gem "redcarpet", "= 3.5.1" # for Markdown docs (README.md)
13
+ gem "yard"
data/README.md CHANGED
@@ -1,8 +1,26 @@
1
1
  # Lean, mean IRC processing machine
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/iirc`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ ```ruby
4
+ require 'iirc'
5
+
6
+ class CoolBot < IIRC::IRCv3Bot
7
+ include Verbs
8
+
9
+ def configure_coolness
10
+ on /^!poke/, :poke_back
11
+ end
4
12
 
5
- TODO: Delete this and the text above, and describe your gem
13
+ def poke_back(evt)
14
+ act reply_target(evt), "pokes #{evt.sender.nick} back!!!"
15
+ end
16
+
17
+ def autojoin_channels
18
+ ['##coolness']
19
+ end
20
+ end
21
+
22
+ CoolBot.run 'irc.libera.chat' if __FILE__ == $0
23
+ ```
6
24
 
7
25
  ## Installation
8
26
 
@@ -22,7 +40,7 @@ Or install it yourself as:
22
40
 
23
41
  ## Usage
24
42
 
25
- TODO: Write usage instructions here
43
+ TODO: Flesh out usage instructions here
26
44
 
27
45
  ## Development
28
46
 
data/Rakefile CHANGED
@@ -15,4 +15,63 @@ RDoc::Task.new do |rd|
15
15
  rd.options = ["--all"]
16
16
  end
17
17
 
18
+ task :numerics do
19
+ require 'yaml'
20
+ require 'open-uri'
21
+
22
+ data = YAML.load URI.open('https://raw.githubusercontent.com/ircdocs/irc-defs/gh-pages/_data/numerics.yaml')
23
+ revision = data['file']['revision']
24
+
25
+ puts "Loaded numerics.yaml revision #{revision}"
26
+
27
+ open(File.join(__dir__, 'lib/iirc/numerics.rb'), 'w+') do |out|
28
+ out << <<~HEADER
29
+ module IIRC
30
+ # Definitions imported from ircdocs.horse
31
+ # @version #{revision}
32
+ # @see https://raw.githubusercontent.com/ircdocs/irc-defs/gh-pages/_data/numerics.yaml
33
+ # @see https://defs.ircdocs.horse/defs/numerics.html
34
+ module Numerics
35
+ HEADER
36
+
37
+ values = data['values'].reject { |v| v['obsolete'] }
38
+ counts = values.map { |v| v['name'] }.tally
39
+
40
+ constants = {}
41
+
42
+ for row in values
43
+ out << " # #{row['comment'].squeeze(' ').tr("\r", '').gsub("\n", ' ').strip}\n" if row['comment']
44
+ out << " # @format #{row['numeric']} #{row['format'].strip}\n" if row['format']
45
+
46
+ name = row['name']
47
+ if counts[name] > 1 and row['origin']
48
+ name += '_' + row['origin'].gsub(/[^[:alnum:]]/, '_').gsub(/_{2,}/, '_').sub(/_$/, '').upcase
49
+ end
50
+ if constants[name]
51
+ name += '_ALT'
52
+ if constants[name]
53
+ fail <<~MSG
54
+ Couldn't derive a unique name for #{name}.
55
+ Previous source: #{constants[name].inspect}
56
+ MSG
57
+ end
58
+ end
59
+
60
+ constants[name] = row
61
+
62
+ out << " #{name} = #{row['numeric'].to_sym.inspect}"
63
+ out << "\n"
64
+ end
65
+
66
+ out << <<~FOOTER
67
+ end
68
+ end
69
+ FOOTER
70
+ end
71
+
72
+ puts "%d numerics." % data['values'].count
73
+ system('wc', File.join(__dir__, 'lib/iirc/numerics.rb'))
74
+ end
75
+
18
76
  task default: :test
77
+
@@ -1,60 +1,61 @@
1
1
  require_relative "reply_target"
2
2
 
3
3
  module IIRC
4
- module Bot::AmbientEvents
5
- private
6
- def configure_ambient_events
7
- hook :set_ambient_event
8
- end
4
+ module Bot::Ambient
5
+ module Events
6
+ private
7
+ def configure_ambient_events
8
+ hook :set_ambient_event
9
+ end
9
10
 
10
- def ambient_event
11
- Thread.current[:ambient_event]
12
- end
11
+ def ambient_event
12
+ Thread.current[:ambient_event]
13
+ end
13
14
 
14
- def ambient_target; ambient_event&.target; end
15
- def ambient_sender; ambient_event&.sender; end
15
+ def ambient_target; ambient_event&.target; end
16
+ def ambient_sender; ambient_event&.sender; end
16
17
 
17
- def set_ambient_event(evt)
18
- Thread.current[:ambient_event] = evt
19
- end
18
+ def set_ambient_event(evt)
19
+ Thread.current[:ambient_event] = evt
20
+ end
20
21
 
21
- def with_ambient_event(evt)
22
- initial_event = ambient_event
23
- set_ambient_event(evt)
24
- begin
25
- yield evt
26
- ensure
27
- set_ambient_event(initial_event)
22
+ def with_ambient_event(evt)
23
+ initial_event = ambient_event
24
+ set_ambient_event(evt)
25
+ begin
26
+ yield evt
27
+ ensure
28
+ set_ambient_event(initial_event)
29
+ end
28
30
  end
29
- end
30
- end
31
+ end
31
32
 
32
- module Bot::AmbientEvents::LabeledRequests
33
- def labeled_request(*)
34
- initial_evt = ambient_event
35
- super do |reply|
36
- with_ambient_event(initial_evt) { yield reply }
33
+ module LabeledRequests
34
+ def labeled_request(*)
35
+ initial_evt = ambient_event
36
+ super do |reply|
37
+ with_ambient_event(initial_evt) { yield reply }
38
+ end
37
39
  end
38
40
  end
39
- end
40
41
 
41
- module Bot::AmbientEvents::ReplyTarget
42
- include Bot::ReplyTarget
43
- def ambient_reply_target
44
- reply_target(ambient_event)
42
+ module ReplyTarget
43
+ def reply_target(evt=ambient_event) super end
44
+ end
45
+
46
+ module Verbs
47
+ include Events
48
+ include ReplyTarget
49
+
50
+ def join(channel=reply_target) super end
51
+ def part(channel=reply_target, reason='') super end
52
+ def msg(target=reply_target, msg) super end
53
+ def act(target=reply_target, msg) super end
54
+ def cycle(channel=reply_target, reason='') super end
55
+ def mode(target=reply_target, mode) super end
56
+ alias :say :msg
45
57
  end
46
- end
47
58
 
48
- module Bot::AmbientVerbs
49
- include Bot::AmbientEvents
50
- include Bot::AmbientEvents::ReplyTarget
51
-
52
- def join(channel=ambient_reply_target) super end
53
- def part(channel=ambient_reply_target, reason='') super end
54
- def msg(channel=ambient_reply_target, msg) super end
55
- def act(channel=ambient_reply_target, msg) super end
56
- def cycle(channel=ambient_reply_target, reason='') super end
57
- def mode(channel=ambient_reply_target, mode) super end
58
- alias :say :msg
59
+ include Verbs
59
60
  end
60
- end
61
+ end
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IIRC
4
+ # Parses RPL_ISUPPORT (005) events into a Hash.
5
+ #
6
+ # These are sent by servers after registration to provide info about the network,
7
+ # what the server supports, and how it behaves.
8
+ #
9
+ # Provides a Hash of the raw values, extended with helper methods which process them.
10
+ #
11
+ # @see https://defs.ircdocs.horse/defs/isupport.html List of tokens and their values (defs.ircdocs.horse)
12
+ # @see https://datatracker.ietf.org/doc/html/draft-hardy-irc-isupport-00
13
+ # @see https://datatracker.ietf.org/doc/html/draft-brocklesby-irc-isupport-00
14
+ module Bot::ISupport
15
+ # Hash of tokens sent by the server after registration indicating feature support and limits.
16
+ # @return [Hash#extend(Inquiry)] the raw isupport key=>value pairs. keys with no value are assigned +true+.
17
+ def isupport
18
+ @isupport ||= {}.extend(Inquiry)
19
+ end
20
+
21
+ private
22
+ def configure_isupport
23
+ on :'005', :store_isupport
24
+ end
25
+
26
+ def store_isupport(evt)
27
+ tokens = evt.args[1..-2]
28
+
29
+ for token in tokens
30
+ name, value = token.split('=', 2)
31
+ isupport[name] = value.freeze || true
32
+ end
33
+ end
34
+ end
35
+
36
+ # Methods for inquiry into a Hash of raw ISUPPORT key=>value pairs.
37
+ # These are mixed in to the Hash returned by {ISupport#isupport}.
38
+ #
39
+ # The key=>value format returned by #isupport won't change.
40
+ # Rather, methods which process the values can be added here.
41
+ module Bot::ISupport::Inquiry
42
+ # Whether or not the server supports a user mode which lets clients mark themselves as bots.
43
+ def bot_mode?
44
+ !!bot_mode
45
+ end
46
+
47
+ # User mode which can be used to mark clients as bots.
48
+ # @return [String] mode char (usually 'B')
49
+ # @return [nil] if mode is not supported
50
+ def bot_mode
51
+ self['BOT']
52
+ end
53
+
54
+ # A string indicating the case mapping used by the server to determine case-insensitive equality
55
+ # of channel names and nick names.
56
+ #
57
+ # @note IIRC does not currently perform case-insensitive comparisons. This may change in future.
58
+ # @return [String] the name of the casemapping. e.g. 'ascii', 'rfc1459', 'rfc3454'
59
+ def case_mapping
60
+ self['CASEMAPPING']
61
+ end
62
+
63
+ # Characters used as channel prefixes by this server.
64
+ # @see https://defs.ircdocs.horse/defs/chantypes.html
65
+ # @return [Array] prefixes, e.g. ['#', '&']
66
+ def channel_prefixes
67
+ (@channel_prefixes ||= self['CHANTYPES']&.chars.freeze) || ['#'].freeze
68
+ end
69
+ end
70
+ end
@@ -1,15 +1,11 @@
1
1
  module IIRC
2
2
  module Bot::Members
3
- def self.configure_actions
4
- [:listen_for_names]
5
- end
6
-
7
3
  def members
8
4
  @members ||= {}
9
5
  end
10
6
 
11
7
  private
12
- def listen_for_names
8
+ def configure_members_tracking
13
9
  on :'353', :receive_names
14
10
  on :'366', :receive_names_end
15
11
  end
data/lib/iirc/bot.rb CHANGED
@@ -30,7 +30,7 @@ module IIRC
30
30
  end
31
31
 
32
32
  private def ensure_registration_info!
33
- me.username ||= me.nick.downcase
33
+ me.username ||= me.nick&.downcase
34
34
  me.realname ||= me.nick
35
35
  raise ArgumentError.new('no nick given') unless me.nick && !me.nick.empty?
36
36
  end