iirc 0.2.8 → 0.4.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/CHANGELOG.md +34 -0
- data/Rakefile +65 -0
- data/examples/greeter.rb +2 -1
- data/lib/iirc/bot/accept_invites.rb +22 -0
- data/lib/iirc/bot/ambient.rb +49 -38
- data/lib/iirc/bot/hooks.rb +22 -23
- data/lib/iirc/bot/ircv3/parsing.rb +1 -1
- data/lib/iirc/bot/reply_target.rb +14 -0
- data/lib/iirc/bot.rb +1 -1
- data/lib/iirc/event.rb +1 -2
- data/lib/iirc/numerics.rb +1252 -0
- data/lib/iirc/sender.rb +43 -3
- data/lib/iirc/version.rb +1 -1
- data/lib/iirc.rb +17 -6
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 89d3e4727f759400cf52bf6a8cb23b365d62259ef32fd977c6fcaab0d542fa53
|
4
|
+
data.tar.gz: fc476e509a2ca6e620d6b93bbde705113136926e574860b05bc5508c332f8e51
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9cbf42882b4aeb2ae080266750d540d5f834a6c55be22d8b75541c7ca4b521492eacae055c21a3bdb716ca691e3db8a685c79d918c353df324ed8f42b9f168d
|
7
|
+
data.tar.gz: 98d82cf28be02e06e32dd8c6978eb0470ca486c6b9f898fb0642e244e2edbaa99f2c0df9aa9fc4491610968d72736cfae05aba8dfddd1fe04fcdf72681389503
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,37 @@
|
|
1
|
+
## [0.4.0] - 2022-03-27
|
2
|
+
|
3
|
+
- [Numerics] Add module with constants imported from ircdocs.horse
|
4
|
+
- Run `rake numerics` to re-import.
|
5
|
+
|
6
|
+
- [IIRC.run,IIRC.dial] Support passing a symbol as ssl_context
|
7
|
+
- e.g. ssl_context: :no_verify instead of ssl_context: IIRC::SSL.no_verify
|
8
|
+
|
9
|
+
- The AmbientEvents modules have been reorganised
|
10
|
+
- AmbientVerbs is now Ambient::Verbs
|
11
|
+
- AmbientEvents => Ambient::Events
|
12
|
+
- AmbientEvents::{LabeledRequests,ReplyTarget} => Ambient::{LabeledRequests,ReplyTarget}
|
13
|
+
|
14
|
+
- #ambient_reply_target() has been replaced with #reply_target(evt=ambient_event)
|
15
|
+
|
16
|
+
- [Bot.run] Set nick to class name if no param is given
|
17
|
+
- `MyBot.run('irc.libera.chat')` is enough to connect to Libera as 'MyBot'
|
18
|
+
|
19
|
+
## [0.3.0] - 2022-03-26
|
20
|
+
|
21
|
+
- [Bot] Include ReplyTarget
|
22
|
+
- [Hooks] Refactor
|
23
|
+
- Add AcceptInvites module
|
24
|
+
- Improve Greeter example
|
25
|
+
- [IIRC.run,IIRC.dial] now accept local_host, local_port keyword arguments
|
26
|
+
|
27
|
+
## [0.2.9] - 2022-03-24
|
28
|
+
|
29
|
+
- Add reply target concept (Bot::ReplyTarget)
|
30
|
+
- The reply target of an event is the sender's nick when we are its target,
|
31
|
+
and equal to the regular target otherwise.
|
32
|
+
- The ambient verb methods now target the reply target of the ambient event by default.
|
33
|
+
- Should make writing actions more convenient.
|
34
|
+
|
1
35
|
## [0.2.8] - 2022-03-22
|
2
36
|
|
3
37
|
- Add MIT license
|
data/Rakefile
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require "bundler/gem_tasks"
|
4
4
|
require "rake/testtask"
|
5
|
+
require "rdoc/task"
|
5
6
|
|
6
7
|
Rake::TestTask.new(:test) do |t|
|
7
8
|
t.libs << "test"
|
@@ -9,4 +10,68 @@ Rake::TestTask.new(:test) do |t|
|
|
9
10
|
t.test_files = FileList["test/**/*_test.rb"]
|
10
11
|
end
|
11
12
|
|
13
|
+
RDoc::Task.new do |rd|
|
14
|
+
rd.rdoc_files.include("lib/**/*.rb")
|
15
|
+
rd.options = ["--all"]
|
16
|
+
end
|
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
|
+
|
12
76
|
task default: :test
|
77
|
+
|
data/examples/greeter.rb
CHANGED
@@ -3,9 +3,10 @@ require "iirc"
|
|
3
3
|
class Greeter < IIRC::Bot
|
4
4
|
include AutoJoin
|
5
5
|
include Verbs
|
6
|
+
include PrintIO
|
6
7
|
|
7
8
|
def on_join(evt)
|
8
|
-
say evt.target, "Hello #{evt.sender.nick}!"
|
9
|
+
say evt.target, "Hello #{evt.sender.nick}!" unless me === evt.sender
|
9
10
|
end
|
10
11
|
|
11
12
|
def autojoin_channels
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module IIRC
|
2
|
+
module Bot::AcceptInvites
|
3
|
+
# Override this to decide whether we should accept a given invite.
|
4
|
+
# By default, all invites are accepted.
|
5
|
+
# @param [Event]
|
6
|
+
# @return [true] if we should join the channel
|
7
|
+
def accept_invite?(evt)
|
8
|
+
true
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
def configure_accept_invites
|
13
|
+
on :invite, :accept_invites
|
14
|
+
end
|
15
|
+
|
16
|
+
def accept_invites(evt)
|
17
|
+
if me === evt.target and accept_invite?(evt)
|
18
|
+
join evt.args[1]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/iirc/bot/ambient.rb
CHANGED
@@ -1,50 +1,61 @@
|
|
1
|
+
require_relative "reply_target"
|
2
|
+
|
1
3
|
module IIRC
|
2
|
-
module Bot::
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
module Bot::Ambient
|
5
|
+
module Events
|
6
|
+
private
|
7
|
+
def configure_ambient_events
|
8
|
+
hook :set_ambient_event
|
9
|
+
end
|
7
10
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
+
def ambient_event
|
12
|
+
Thread.current[:ambient_event]
|
13
|
+
end
|
11
14
|
|
12
|
-
|
13
|
-
|
15
|
+
def ambient_target; ambient_event&.target; end
|
16
|
+
def ambient_sender; ambient_event&.sender; end
|
14
17
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
+
def set_ambient_event(evt)
|
19
|
+
Thread.current[:ambient_event] = evt
|
20
|
+
end
|
21
|
+
|
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
|
30
|
+
end
|
31
|
+
end
|
18
32
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
yield
|
24
|
-
ensure
|
25
|
-
set_ambient_event(initial_event)
|
33
|
+
module LabeledRequests
|
34
|
+
def labeled_request(*)
|
35
|
+
initial_evt = ambient_event
|
36
|
+
super do |reply|
|
37
|
+
with_ambient_event(initial_evt) { yield reply }
|
26
38
|
end
|
27
39
|
end
|
28
|
-
|
40
|
+
end
|
29
41
|
|
30
|
-
|
31
|
-
|
42
|
+
module ReplyTarget
|
43
|
+
def reply_target(evt=ambient_event) super end
|
44
|
+
end
|
32
45
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
def act(channel=ambient_target, msg) super end
|
37
|
-
def cycle(channel=ambient_target, reason='') super end
|
38
|
-
def mode(channel=ambient_target, mode) super end
|
39
|
-
alias :say :msg
|
40
|
-
end
|
46
|
+
module Verbs
|
47
|
+
include Events
|
48
|
+
include ReplyTarget
|
41
49
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
super
|
46
|
-
|
47
|
-
end
|
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
|
48
57
|
end
|
58
|
+
|
59
|
+
include Verbs
|
49
60
|
end
|
50
|
-
end
|
61
|
+
end
|
data/lib/iirc/bot/hooks.rb
CHANGED
@@ -4,6 +4,18 @@ module IIRC
|
|
4
4
|
@hooks ||= Hash.new { |h,v| h[v] = Set.new }
|
5
5
|
end
|
6
6
|
|
7
|
+
def run
|
8
|
+
lines { |line|
|
9
|
+
begin
|
10
|
+
evt = parse(line)
|
11
|
+
fire! evt.verb, evt
|
12
|
+
rescue Exception => ex
|
13
|
+
puts ex.message
|
14
|
+
puts ex.backtrace
|
15
|
+
end
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
7
19
|
def on verb=nil, action=nil, &blk
|
8
20
|
if action and blk
|
9
21
|
define_singleton_method(action, blk)
|
@@ -17,10 +29,6 @@ module IIRC
|
|
17
29
|
end
|
18
30
|
end
|
19
31
|
|
20
|
-
def hook action=nil, &blk
|
21
|
-
on nil, action, &blk
|
22
|
-
end
|
23
|
-
|
24
32
|
def off verb, action=nil, &blk
|
25
33
|
action ||= blk
|
26
34
|
if action
|
@@ -30,14 +38,12 @@ module IIRC
|
|
30
38
|
end
|
31
39
|
end
|
32
40
|
|
41
|
+
def hook action=nil, &blk
|
42
|
+
on nil, action, &blk
|
43
|
+
end
|
44
|
+
|
33
45
|
def fire! verb, *args, **kwargs
|
34
|
-
for action in
|
35
|
-
call action, *args, **kwargs
|
36
|
-
end
|
37
|
-
if respond_to? :"on_#{verb}"
|
38
|
-
send(:"on_#{verb}", *args, **kwargs)
|
39
|
-
end
|
40
|
-
for action in hooks[verb]
|
46
|
+
for action in hook_seq(verb)
|
41
47
|
call action, *args, **kwargs
|
42
48
|
end
|
43
49
|
rescue StopIteration
|
@@ -54,16 +60,9 @@ module IIRC
|
|
54
60
|
end
|
55
61
|
end
|
56
62
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
fire! evt.verb, evt
|
62
|
-
rescue Exception => ex
|
63
|
-
puts ex.message
|
64
|
-
puts ex.backtrace
|
65
|
-
end
|
66
|
-
}
|
67
|
-
end
|
63
|
+
protected
|
64
|
+
def hook_seq(verb)
|
65
|
+
[*hooks[nil], (:"on_#{verb}" if respond_to?(:"on_#{verb}")), *hooks[verb]].compact
|
66
|
+
end
|
68
67
|
end
|
69
|
-
end
|
68
|
+
end
|
@@ -4,7 +4,7 @@ module IIRC
|
|
4
4
|
autoload :IRCParser, 'ircparser'
|
5
5
|
|
6
6
|
def parse(line)
|
7
|
-
msg = IRCParser::Message.parse(line.chomp)
|
7
|
+
msg = IRCParser::Message.parse(line.tr("\r", '').chomp)
|
8
8
|
|
9
9
|
Event.new.tap { |evt|
|
10
10
|
evt.sender = IRCParser::RFCWireFormat.__stringify_prefix(msg.prefix) if msg.prefix
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module IIRC
|
2
|
+
module Bot::ReplyTarget
|
3
|
+
# The +reply_target+ of an event is the sender's nickname when _we_ are the
|
4
|
+
# +target+. Otherwise, it returns the regular +target+.
|
5
|
+
#
|
6
|
+
# It lets us reply to events without having to repeat the `(me ===
|
7
|
+
# target) ? sender.nick : target` logic used to make sure we don't message
|
8
|
+
# ourselves when we receive a direct PRIVMSG, NOTICE, etc.
|
9
|
+
|
10
|
+
def reply_target(evt)
|
11
|
+
(me === evt.target) ? evt.sender.nick : evt.target
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/iirc/bot.rb
CHANGED