iirc 0.5.1 → 0.6.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 +4 -4
- data/CHANGELOG.md +24 -0
- data/README.md +7 -7
- data/examples/facts.rb +2 -2
- data/examples/greeter.rb +5 -5
- data/examples/sed.rb +83 -0
- data/examples/wolfram.rb +2 -2
- data/lib/iirc/bot.rb +5 -1
- data/lib/iirc/event.rb +34 -0
- data/lib/iirc/{bot → modules}/accept_invites.rb +6 -3
- data/lib/iirc/{bot → modules}/ambient.rb +22 -1
- data/lib/iirc/modules/autojoin.rb +25 -0
- data/lib/iirc/{bot → modules}/channels.rb +7 -3
- data/lib/iirc/{bot → modules}/configure.rb +1 -1
- data/lib/iirc/{bot → modules}/formatting.rb +1 -1
- data/lib/iirc/{bot → modules}/hooks.rb +7 -3
- data/lib/iirc/{bot → modules}/ircv3/batches.rb +1 -1
- data/lib/iirc/{bot → modules}/ircv3/caps.rb +1 -1
- data/lib/iirc/{bot → modules}/ircv3/labeled_requests.rb +1 -1
- data/lib/iirc/{bot → modules}/ircv3/parsing.rb +1 -1
- data/lib/iirc/{bot → modules}/isupport.rb +22 -2
- data/lib/iirc/modules/members.rb +39 -0
- data/lib/iirc/{bot → modules}/oper_up.rb +1 -1
- data/lib/iirc/{bot → modules}/parsing.rb +1 -1
- data/lib/iirc/{bot → modules}/pong.rb +1 -1
- data/lib/iirc/modules/print_io.rb +17 -0
- data/lib/iirc/modules/reading.rb +12 -0
- data/lib/iirc/{bot → modules}/redis.rb +1 -1
- data/lib/iirc/{bot → modules}/regex_hooks.rb +3 -3
- data/lib/iirc/{bot → modules}/reply_target.rb +1 -1
- data/lib/iirc/{bot → modules}/track_own_nick.rb +1 -1
- data/lib/iirc/{bot → modules}/verbs.rb +1 -1
- data/lib/iirc/sender.rb +6 -5
- data/lib/iirc/version.rb +1 -1
- data/lib/iirc.rb +34 -36
- metadata +26 -25
- data/lib/iirc/bot/autojoin.rb +0 -18
- data/lib/iirc/bot/members.rb +0 -28
- data/lib/iirc/bot/print_io.rb +0 -12
- data/lib/iirc/bot/reading.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 49f724afe62aa2f76c2d5effda29ce98c9f9b5ae8d83f175ac0de51385e9c431
|
4
|
+
data.tar.gz: e61a5053975303f7e45dc4be44f3cebddc63a3171a984c1785fcae666be27d07
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fc76b8e4d7455058a20dff37d6d29cb0082d69b65681a0e36b7eeccb7abdb25cf58b52bbb23bb652c34747756e0352e2969bb99a669349cada61041cfcdd0dec
|
7
|
+
data.tar.gz: 3c4a85314c46eb87752f1a85e2235d1744a0e2f3b9a024af7c5bc5e8b7a604d505edf9905022393bacb973b7bfd7e94da815321cba5d651cea21776d1dc07486
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,27 @@
|
|
1
|
+
## [0.6.2] - 2022-04-28
|
2
|
+
|
3
|
+
- [Event] Add CTCP parsing methods
|
4
|
+
- [Sender] Nick is the server name when sender is a server
|
5
|
+
|
6
|
+
## [0.6.1] - 2022-04-01
|
7
|
+
|
8
|
+
- Add SedBot example
|
9
|
+
- [RegexHooks] Passes matches as args
|
10
|
+
- e.g. (evt, match_one, match_two, ..)
|
11
|
+
- [RegexHooks] Add some tests
|
12
|
+
|
13
|
+
## [0.6.0] - 2022-03-30
|
14
|
+
|
15
|
+
- Move modules from IIRC::Bot to IIRC namespace
|
16
|
+
|
17
|
+
- Document AcceptInvites
|
18
|
+
- Document Ambient
|
19
|
+
- Document AutoJoin
|
20
|
+
- Document Channels
|
21
|
+
- Document Members
|
22
|
+
- Document PrintIO
|
23
|
+
- Document Reading
|
24
|
+
|
1
25
|
## [0.5.1] - 2022-03-29
|
2
26
|
|
3
27
|
- [Batteries] Include ISupport
|
data/README.md
CHANGED
@@ -10,10 +10,10 @@ It's based on composition, with code reload, extensibility and predictability in
|
|
10
10
|
require 'iirc'
|
11
11
|
|
12
12
|
class CoolBot < IIRC::IRCv3Bot
|
13
|
-
include Verbs
|
14
|
-
include AutoJoin
|
15
|
-
include RegexHooks
|
16
|
-
include PrintIO
|
13
|
+
include IIRC::Verbs
|
14
|
+
include IIRC::AutoJoin
|
15
|
+
include IIRC::RegexHooks
|
16
|
+
include IIRC::PrintIO
|
17
17
|
|
18
18
|
def configure_coolness
|
19
19
|
on /^!poke/, :poke_back
|
@@ -35,8 +35,8 @@ CoolBot.run 'irc.libera.chat' if __FILE__ == $0
|
|
35
35
|
require 'iirc'
|
36
36
|
|
37
37
|
class SillyBot < IIRC::IRCv3Bot
|
38
|
-
include AcceptInvites
|
39
|
-
include Batteries # Verbs, Ambient, RegexHooks used here
|
38
|
+
include IIRC::AcceptInvites
|
39
|
+
include IIRC::Batteries # Verbs, Ambient, RegexHooks used here
|
40
40
|
|
41
41
|
def configure_silliness
|
42
42
|
on /^!uptime/, :say_uptime
|
@@ -110,7 +110,7 @@ For example:
|
|
110
110
|
|
111
111
|
```ruby
|
112
112
|
class CoolBot < IIRC::IRCv3Bot
|
113
|
-
include RegexHooks
|
113
|
+
include IIRC::RegexHooks
|
114
114
|
|
115
115
|
def configure_reload
|
116
116
|
on /^=reload/, :reload!
|
data/examples/facts.rb
CHANGED
data/examples/greeter.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
require "iirc"
|
2
2
|
|
3
3
|
class Greeter < IIRC::Bot
|
4
|
-
include AutoJoin
|
5
|
-
include Verbs
|
6
|
-
include PrintIO
|
4
|
+
include IIRC::AutoJoin
|
5
|
+
include IIRC::Verbs
|
6
|
+
include IIRC::PrintIO
|
7
7
|
|
8
8
|
def on_join(evt)
|
9
|
-
say evt.target, "Hello #{evt.
|
9
|
+
say evt.target, "Hello #{evt.nick}!" unless me === evt.sender
|
10
10
|
end
|
11
11
|
|
12
12
|
def autojoin_channels
|
@@ -14,4 +14,4 @@ class Greeter < IIRC::Bot
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
Greeter.run 'irc.libera.chat', nick: 'GreeterBot' if __FILE__ == $0
|
17
|
+
Greeter.run 'irc.libera.chat', nick: 'GreeterBot' if __FILE__ == $0
|
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/examples/wolfram.rb
CHANGED
data/lib/iirc/bot.rb
CHANGED
@@ -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
|
@@ -1,8 +1,11 @@
|
|
1
1
|
module IIRC
|
2
|
-
|
3
|
-
|
2
|
+
# Accept INVITEs to join a channel.
|
3
|
+
# By default, all invites are accepted.
|
4
|
+
# To choose which ones to accept, define {#accept_invite?} on your object / class.
|
5
|
+
module AcceptInvites
|
6
|
+
# Decides whether to accept a given INVITE.
|
4
7
|
# By default, all invites are accepted.
|
5
|
-
# @param [Event]
|
8
|
+
# @param evt [Event] the invite
|
6
9
|
# @return [true] if we should join the channel
|
7
10
|
def accept_invite?(evt)
|
8
11
|
true
|
@@ -1,7 +1,28 @@
|
|
1
1
|
require_relative "reply_target"
|
2
2
|
|
3
3
|
module IIRC
|
4
|
-
|
4
|
+
# Ambient lets you access the current event without having to pass it around.
|
5
|
+
#
|
6
|
+
# A thread-local variable is set by {Events} when an event comes in.
|
7
|
+
#
|
8
|
+
# Overloads of {#say}, {#act}, {#mode}, {#join} etc. make their
|
9
|
+
# first argument optional.
|
10
|
+
#
|
11
|
+
# This module pulls in both {Events} and {Verbs}.
|
12
|
+
#
|
13
|
+
# @example say (with Ambient)
|
14
|
+
# def on_privmsg
|
15
|
+
# say "Hello!"
|
16
|
+
# end
|
17
|
+
# @example say (without)
|
18
|
+
# def on_privmsg(evt)
|
19
|
+
# say reply_target(evt), "Hello!"
|
20
|
+
# end
|
21
|
+
# @example mode (with Ambient)
|
22
|
+
# def on_join(evt)
|
23
|
+
# mode "+v #{evt.nick}"
|
24
|
+
# end
|
25
|
+
module Ambient
|
5
26
|
module Events
|
6
27
|
private
|
7
28
|
def configure_ambient_events
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module IIRC
|
2
|
+
# Automatically joins channels on RPL_WELCOME (001).
|
3
|
+
#
|
4
|
+
# Override {#autojoin_channels} to choose which channels to join.
|
5
|
+
# {#autojoin!} may be called at any time to resend.
|
6
|
+
module AutoJoin
|
7
|
+
private def configure_autojoin
|
8
|
+
on :'001', :autojoin!
|
9
|
+
end
|
10
|
+
|
11
|
+
# Send JOIN for each in {#autojoin_channels}
|
12
|
+
# @return [Array<String>] channels joined
|
13
|
+
def autojoin!
|
14
|
+
for channel in autojoin_channels
|
15
|
+
self << "JOIN #{channel}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# The channels to join. By default, returns an empty array.
|
20
|
+
# @return [Array<String>] channel names
|
21
|
+
def autojoin_channels
|
22
|
+
[]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,15 +1,19 @@
|
|
1
1
|
module IIRC
|
2
|
-
|
2
|
+
# Keeps track of the channels we are currently in.
|
3
|
+
# The list can be retrieved with {#channels}.
|
4
|
+
# Based on JOIN, PART and KICK messages received for our nick.
|
5
|
+
module Channels
|
6
|
+
# @return [Set<String>]
|
3
7
|
def channels
|
4
8
|
@channels ||= Set.new
|
5
9
|
end
|
6
10
|
|
7
11
|
private
|
8
12
|
def configure_channel_tracking
|
9
|
-
hook :
|
13
|
+
hook :track_own_channels
|
10
14
|
end
|
11
15
|
|
12
|
-
def
|
16
|
+
def track_own_channels(evt)
|
13
17
|
case evt.verb
|
14
18
|
when :'001'
|
15
19
|
channels.clear
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module IIRC
|
2
|
-
module
|
2
|
+
module Hooks
|
3
3
|
def hooks
|
4
4
|
@hooks ||= Hash.new { |h,v| h[v] = Set.new }
|
5
5
|
end
|
@@ -7,8 +7,7 @@ module IIRC
|
|
7
7
|
def run
|
8
8
|
lines { |line|
|
9
9
|
begin
|
10
|
-
|
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)
|
@@ -11,7 +11,7 @@ module IIRC
|
|
11
11
|
# @see https://defs.ircdocs.horse/defs/isupport.html List of tokens and their values (defs.ircdocs.horse)
|
12
12
|
# @see https://datatracker.ietf.org/doc/html/draft-hardy-irc-isupport-00
|
13
13
|
# @see https://datatracker.ietf.org/doc/html/draft-brocklesby-irc-isupport-00
|
14
|
-
module
|
14
|
+
module ISupport
|
15
15
|
# Hash of tokens sent by the server after registration indicating feature support and limits.
|
16
16
|
# @return [Hash#extend(Inquiry)] the raw isupport key=>value pairs. keys with no value are assigned +true+.
|
17
17
|
def isupport
|
@@ -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
|
|
@@ -38,7 +43,7 @@ module IIRC
|
|
38
43
|
#
|
39
44
|
# The key=>value format returned by #isupport won't change.
|
40
45
|
# Rather, methods which process the values can be added here.
|
41
|
-
module
|
46
|
+
module ISupport::Inquiry
|
42
47
|
# Whether or not the server supports a user mode which lets clients mark themselves as bots.
|
43
48
|
def bot_mode?
|
44
49
|
!!bot_mode
|
@@ -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
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module IIRC
|
2
|
+
# Processes lists of channel participants sent by the server into {#members}.
|
3
|
+
# Namely, it processes NAMES replies, such as the ones sent automatically when we
|
4
|
+
# join a channel.
|
5
|
+
# @note IIRC doesn't send NAMES by itself, but will process any replies received, such
|
6
|
+
# as to JOIN, or any requests you have made yourself.
|
7
|
+
# @see IIRC::Verbs#names send a NAMES request
|
8
|
+
module Members
|
9
|
+
# Nicknames present in channels, by channel.
|
10
|
+
# Updated from NAMES replies.
|
11
|
+
# @return [Hash<String,[String]>]
|
12
|
+
def members
|
13
|
+
@members ||= {}
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
# @note In a future release, this may also track using JOIN/KICK/PART, etc.
|
18
|
+
def configure_members_tracking
|
19
|
+
on :'353', :receive_names
|
20
|
+
on :'366', :receive_names_end
|
21
|
+
end
|
22
|
+
|
23
|
+
def receive_names evt
|
24
|
+
names = evt.args[3]
|
25
|
+
channel = evt.args[2]
|
26
|
+
members_receiving[channel].concat names.tr('&+@%~', '').split(' ')
|
27
|
+
end
|
28
|
+
|
29
|
+
def receive_names_end evt
|
30
|
+
channel = evt.args[1]
|
31
|
+
members[channel] = members_receiving.delete(channel)
|
32
|
+
end
|
33
|
+
|
34
|
+
# @return [Hash]
|
35
|
+
def members_receiving
|
36
|
+
@members_receiving ||= Hash.new { |h,k| h[k] = [] }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module IIRC
|
2
|
+
# Wraps {Reading#lines} and {Bot#<<} to print lines received and sent to stdout.
|
3
|
+
# Useful for debugging.
|
4
|
+
module PrintIO
|
5
|
+
# Prints `>> #{line}` to stdout, then yields, for each line from super.
|
6
|
+
def lines
|
7
|
+
super { |line| puts ">> #{line}"; yield line }
|
8
|
+
end
|
9
|
+
|
10
|
+
# Prints `<< #{line}` to stdout, then calls super
|
11
|
+
# @return [self]
|
12
|
+
def <<(line)
|
13
|
+
puts "<< #{line}"
|
14
|
+
super
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module IIRC
|
2
|
+
module Reading
|
3
|
+
# Read lines from {#socket} in a blocking loop until EOF or an error is raised.
|
4
|
+
# @return nil
|
5
|
+
# @yield [String] line encoded as UTF-8.
|
6
|
+
def lines
|
7
|
+
loop {
|
8
|
+
yield socket.readline.force_encoding('utf-8').encode
|
9
|
+
}
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module IIRC
|
2
|
-
module
|
2
|
+
module RegexHooks
|
3
3
|
def regex_hooks
|
4
4
|
hooks.filter { |k,v| Regexp === k }.freeze
|
5
5
|
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
|
34
|
+
def nick; user ? user.nick : without_leading_colon end
|
35
35
|
def username; user&.username end
|
36
|
-
def host;
|
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
|
-
#
|
52
|
-
#
|
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
data/lib/iirc.rb
CHANGED
@@ -4,33 +4,33 @@ require_relative "iirc/event"
|
|
4
4
|
require_relative "iirc/sender"
|
5
5
|
require_relative "iirc/user"
|
6
6
|
|
7
|
+
require_relative "iirc/bot"
|
7
8
|
require_relative "iirc/numerics"
|
8
9
|
|
9
|
-
require_relative "iirc/
|
10
|
-
require_relative "iirc/
|
11
|
-
require_relative "iirc/
|
12
|
-
require_relative "iirc/
|
13
|
-
require_relative "iirc/
|
14
|
-
require_relative "iirc/
|
15
|
-
require_relative "iirc/
|
16
|
-
require_relative "iirc/
|
17
|
-
require_relative "iirc/
|
18
|
-
require_relative "iirc/
|
19
|
-
require_relative "iirc/
|
20
|
-
require_relative "iirc/
|
21
|
-
require_relative "iirc/
|
22
|
-
require_relative "iirc/
|
23
|
-
require_relative "iirc/
|
24
|
-
require_relative "iirc/
|
25
|
-
require_relative "iirc/
|
26
|
-
require_relative "iirc/
|
27
|
-
require_relative "iirc/
|
28
|
-
|
29
|
-
|
30
|
-
require_relative "iirc/
|
31
|
-
require_relative "iirc/
|
32
|
-
require_relative "iirc/
|
33
|
-
require_relative "iirc/bot/ircv3/labeled_requests"
|
10
|
+
require_relative "iirc/modules/accept_invites"
|
11
|
+
require_relative "iirc/modules/ambient"
|
12
|
+
require_relative "iirc/modules/autojoin"
|
13
|
+
require_relative "iirc/modules/channels"
|
14
|
+
require_relative "iirc/modules/configure"
|
15
|
+
require_relative "iirc/modules/formatting"
|
16
|
+
require_relative "iirc/modules/hooks"
|
17
|
+
require_relative "iirc/modules/isupport"
|
18
|
+
require_relative "iirc/modules/members"
|
19
|
+
require_relative "iirc/modules/oper_up"
|
20
|
+
require_relative "iirc/modules/parsing"
|
21
|
+
require_relative "iirc/modules/pong"
|
22
|
+
require_relative "iirc/modules/print_io"
|
23
|
+
require_relative "iirc/modules/reading"
|
24
|
+
require_relative "iirc/modules/redis"
|
25
|
+
require_relative "iirc/modules/regex_hooks"
|
26
|
+
require_relative "iirc/modules/reply_target"
|
27
|
+
require_relative "iirc/modules/track_own_nick"
|
28
|
+
require_relative "iirc/modules/verbs"
|
29
|
+
|
30
|
+
require_relative "iirc/modules/ircv3/caps"
|
31
|
+
require_relative "iirc/modules/ircv3/parsing"
|
32
|
+
require_relative "iirc/modules/ircv3/batches"
|
33
|
+
require_relative "iirc/modules/ircv3/labeled_requests"
|
34
34
|
|
35
35
|
module IIRC
|
36
36
|
class Error < StandardError; end
|
@@ -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
|
@@ -67,15 +65,15 @@ module IIRC
|
|
67
65
|
end
|
68
66
|
|
69
67
|
# Batteries is a recommended set of modules for writing interactive bots.
|
70
|
-
module
|
71
|
-
include
|
72
|
-
include
|
73
|
-
include
|
74
|
-
include
|
75
|
-
include
|
76
|
-
include
|
77
|
-
include
|
78
|
-
include
|
68
|
+
module Batteries
|
69
|
+
include Channels
|
70
|
+
include Members
|
71
|
+
include Formatting
|
72
|
+
include AutoJoin
|
73
|
+
include Verbs
|
74
|
+
include Ambient
|
75
|
+
include RegexHooks
|
76
|
+
include ISupport
|
79
77
|
end
|
80
78
|
|
81
79
|
module SSL
|
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.
|
4
|
+
version: 0.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- mooff
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-04-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ircparser
|
@@ -43,34 +43,35 @@ 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
|
49
50
|
- lib/iirc/bot.rb
|
50
|
-
- lib/iirc/bot/accept_invites.rb
|
51
|
-
- lib/iirc/bot/ambient.rb
|
52
|
-
- lib/iirc/bot/autojoin.rb
|
53
|
-
- lib/iirc/bot/channels.rb
|
54
|
-
- lib/iirc/bot/configure.rb
|
55
|
-
- lib/iirc/bot/formatting.rb
|
56
|
-
- lib/iirc/bot/hooks.rb
|
57
|
-
- lib/iirc/bot/ircv3/batches.rb
|
58
|
-
- lib/iirc/bot/ircv3/caps.rb
|
59
|
-
- lib/iirc/bot/ircv3/labeled_requests.rb
|
60
|
-
- lib/iirc/bot/ircv3/parsing.rb
|
61
|
-
- lib/iirc/bot/isupport.rb
|
62
|
-
- lib/iirc/bot/members.rb
|
63
|
-
- lib/iirc/bot/oper_up.rb
|
64
|
-
- lib/iirc/bot/parsing.rb
|
65
|
-
- lib/iirc/bot/pong.rb
|
66
|
-
- lib/iirc/bot/print_io.rb
|
67
|
-
- lib/iirc/bot/reading.rb
|
68
|
-
- lib/iirc/bot/redis.rb
|
69
|
-
- lib/iirc/bot/regex_hooks.rb
|
70
|
-
- lib/iirc/bot/reply_target.rb
|
71
|
-
- lib/iirc/bot/track_own_nick.rb
|
72
|
-
- lib/iirc/bot/verbs.rb
|
73
51
|
- lib/iirc/event.rb
|
52
|
+
- lib/iirc/modules/accept_invites.rb
|
53
|
+
- lib/iirc/modules/ambient.rb
|
54
|
+
- lib/iirc/modules/autojoin.rb
|
55
|
+
- lib/iirc/modules/channels.rb
|
56
|
+
- lib/iirc/modules/configure.rb
|
57
|
+
- lib/iirc/modules/formatting.rb
|
58
|
+
- lib/iirc/modules/hooks.rb
|
59
|
+
- lib/iirc/modules/ircv3/batches.rb
|
60
|
+
- lib/iirc/modules/ircv3/caps.rb
|
61
|
+
- lib/iirc/modules/ircv3/labeled_requests.rb
|
62
|
+
- lib/iirc/modules/ircv3/parsing.rb
|
63
|
+
- lib/iirc/modules/isupport.rb
|
64
|
+
- lib/iirc/modules/members.rb
|
65
|
+
- lib/iirc/modules/oper_up.rb
|
66
|
+
- lib/iirc/modules/parsing.rb
|
67
|
+
- lib/iirc/modules/pong.rb
|
68
|
+
- lib/iirc/modules/print_io.rb
|
69
|
+
- lib/iirc/modules/reading.rb
|
70
|
+
- lib/iirc/modules/redis.rb
|
71
|
+
- lib/iirc/modules/regex_hooks.rb
|
72
|
+
- lib/iirc/modules/reply_target.rb
|
73
|
+
- lib/iirc/modules/track_own_nick.rb
|
74
|
+
- lib/iirc/modules/verbs.rb
|
74
75
|
- lib/iirc/numerics.rb
|
75
76
|
- lib/iirc/sender.rb
|
76
77
|
- lib/iirc/user.rb
|
data/lib/iirc/bot/autojoin.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
module IIRC
|
2
|
-
module Bot::AutoJoin
|
3
|
-
private def configure_autojoin_hook
|
4
|
-
on :'001', :autojoin!
|
5
|
-
end
|
6
|
-
|
7
|
-
def autojoin!
|
8
|
-
for channel in autojoin_channels
|
9
|
-
self << "JOIN #{channel}"
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
# override this to read from e.g. redis, config
|
14
|
-
def autojoin_channels
|
15
|
-
[]
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
data/lib/iirc/bot/members.rb
DELETED
@@ -1,28 +0,0 @@
|
|
1
|
-
module IIRC
|
2
|
-
module Bot::Members
|
3
|
-
def members
|
4
|
-
@members ||= {}
|
5
|
-
end
|
6
|
-
|
7
|
-
private
|
8
|
-
def configure_members_tracking
|
9
|
-
on :'353', :receive_names
|
10
|
-
on :'366', :receive_names_end
|
11
|
-
end
|
12
|
-
|
13
|
-
def receive_names evt
|
14
|
-
names = evt.args[3]
|
15
|
-
channel = evt.args[2]
|
16
|
-
members_receiving[channel].concat names.tr('&+@%~', '').split(' ')
|
17
|
-
end
|
18
|
-
|
19
|
-
def receive_names_end evt
|
20
|
-
channel = evt.args[1]
|
21
|
-
members[channel] = members_receiving.delete(channel)
|
22
|
-
end
|
23
|
-
|
24
|
-
def members_receiving
|
25
|
-
@members_receiving ||= Hash.new { |h,k| h[k] = [] }
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
data/lib/iirc/bot/print_io.rb
DELETED