From ce4d8ae87d738e47058b97e288848a66d282da03 Mon Sep 17 00:00:00 2001 From: Zoffix Znet Date: Fri, 29 Jul 2016 14:17:03 -0400 Subject: Blarg --- docs/03-method-reference.md | 26 +++++++----- lib/IRC/Client.pm6 | 99 ++++++++++++++++++++++++++++----------------- lib/IRC/Client/Message.pm6 | 12 +++--- 3 files changed, 87 insertions(+), 50 deletions(-) diff --git a/docs/03-method-reference.md b/docs/03-method-reference.md index 01f25b6..85e86e4 100644 --- a/docs/03-method-reference.md +++ b/docs/03-method-reference.md @@ -5,7 +5,7 @@ This document describes events available on various objects in use when working with `IRC::Client`. -## Message Objects +## Message Objects (`IRC::Client::Message` and subclasses) All event handlers (except for special `irc-started`) receive one positional argument that does `IRC::Client::Message` role and is refered to as @@ -66,6 +66,9 @@ with a safe-method-call operator (`.?`): #### `IRC::Client::Message` +Object is never sent to event handlers and merely provides commonality to +its subclasses. + ##### `.irc` Contains the `IRC::Client` object. @@ -379,32 +382,37 @@ The "real name" of our client. Affects stringification of the object and makes it stringify to the value of `.label` attribute. -#### `.current-nick` +#### Writable Non-Writable Attributes + +The following attributes are writable, however, they are written to by +the internals and the behaviour when writing to them directly is undefined. + +##### `.current-nick` Writable attribute. Our currently-used nick. Will be one of the nicks returned -by `.nicks`. **Warning: this attribute is not meant to be used directly.** +by `.nicks`. -#### `.is-connected` +##### `.is-connected` Writable `Bool` attribute. Indicates whether we're currently in a state where the server considers us connected. This defaults to `False`, then is set to `True` when the server sends us `001` IRC command and set back to `False` when the socket connection breaks. -**Warning: this attribute is not meant to be used directly.** -#### `.has-quit` +##### `.has-quit` Writable `Bool` attribute. Set to `True` when `.quit` method is called on the Client Object and is used by the socket herder to determine whether or not the socket connection was cut intentionally. -**Warning: this attribute is not meant to be used directly.** -#### `.has-quit` +##### `.has-quit` Writable `IO::Socket::Async` attribute. Contains an object representing the socket connected to the server, although it may already be closed. -**Warning: this attribute is not meant to be used directly.** +--- + +## Client Object (`IRC::Client`) ## Up Next Read [the method reference](03-method-reference.md) next. diff --git a/lib/IRC/Client.pm6 b/lib/IRC/Client.pm6 index 419a0f0..66f1cd1 100644 --- a/lib/IRC/Client.pm6 +++ b/lib/IRC/Client.pm6 @@ -1,9 +1,16 @@ unit class IRC::Client; +use IRC::Client::Message; use IRC::Client::Grammar; use IRC::Client::Server; use IRC::Client::Grammar::Actions; +trusts IRC::Client::Message::Ping; +trusts IRC::Client::Message::Privmsg::Channel; +trusts IRC::Client::Message::Privmsg::Me; +trusts IRC::Client::Message::Notice::Channel; +trusts IRC::Client::Message::Notice::Me; + my class IRC_FLAG_NEXT {}; role IRC::Client::Plugin is export { @@ -65,7 +72,7 @@ submethod BUILD ( } method join (*@channels, :$server) { - self.send-cmd: 'JOIN', $_, :$server for @channels; + self!send-cmd: 'JOIN', $_, :$server for @channels; self; } @@ -73,19 +80,19 @@ method nick (*@nicks, :$server = '*') { @nicks = @nicks.map: { $_ ~ '_' x $++ } if @nicks == 1; self!set-server-attr($server, 'nick', @nicks); self!set-server-attr($server, 'current-nick', @nicks[0]); - self.send-cmd: 'NICK', @nicks[0], :$server; + self!send-cmd: 'NICK', @nicks[0], :$server; self; } method part (*@channels, :$server) { - self.send-cmd: 'PART', $_, :$server for @channels; + self!send-cmd: 'PART', $_, :$server for @channels; self; } method quit (:$server = '*') { if $server eq '*' { .has-quit = True for %!servers.values; } else { self!get-server($server).has-quit = True; } - self.send-cmd: 'QUIT', :$server; + self!send-cmd: 'QUIT', :$server; self; } @@ -121,7 +128,7 @@ method run { method send (:$where!, :$text!, :$server, :$notice) { for $server || |%!servers.keys.sort { if self!get-server($server).is-connected { - self.send-cmd: $notice ?? 'NOTICE' !! 'PRIVMSG', $where, $text, + self!send-cmd: $notice ?? 'NOTICE' !! 'PRIVMSG', $where, $text, :server($_); } else { @@ -134,36 +141,6 @@ method send (:$where!, :$text!, :$server, :$notice) { self; } -method send-cmd ($cmd, *@args is copy, :$prefix = '', :$server) { - if $cmd eq 'NOTICE'|'PRIVMSG' { - my ($where, $text) = @args; - if @!filters - and my @f = @!filters.grep({ - .signature.ACCEPTS: \($text) - or .signature.ACCEPTS: \($text, :$where) - }) - { - start { - CATCH { default { warn $_; warn .backtrace } } - for @f -> $f { - given $f.signature.params.elems { - when 1 { $text = $f($text); } - when 2 { ($text, $where) = $f($text, :$where) } - } - } - self!ssay: :$server, join ' ', $cmd, $where, ":$prefix$text"; - } - } - else { - self!ssay: :$server, join ' ', $cmd, $where, ":$prefix$text"; - } - } - else { - @args[*-1] = ':' ~ @args[*-1] if @args; - self!ssay: :$server, join ' ', $cmd, @args; - } -} - ############################################################################### ############################################################################### ############################################################################### @@ -171,6 +148,25 @@ method send-cmd ($cmd, *@args is copy, :$prefix = '', :$server) { ############################################################################### ############################################################################### +method !change-nick ($server) { + my $idx = 0; + for $server.nick.kv -> $i, $n { + next unless $n eq $server.current-nick; + $idx = $i + 1; + $idx = 0 if $idx == $server.nick.elems; + }; + if $idx == 0 { + Promise.in(10).then: { + $server.current-nick = $server.nick[$idx]; + self!send-cmd: "NICK $server.current-nick()", :$server; + } + } + else { + $server.current-nick = $server.nick[$idx]; + self!send-cmd: "NICK $server.current-nick()", :$server; + } +} + method !connect-socket ($server) { $!debug and debug-print 'Attempting to connect to server', :out, :$server; IO::Socket::Async.connect($server.host, $server.port).then: sub ($prom) { @@ -223,7 +219,8 @@ method !handle-event ($e) { $s.current-nick = $e.args[0]; self!ssay: "JOIN $_", :server($s) for |$s.channels; } - when 'PING' { return $e.reply; } + when 'PING' { return $e.reply; } + when '433'|'432' { self!change-nick($s); } } my $event-name = 'irc-' ~ $e.^name.subst('IRC::Client::Message::', '') @@ -310,6 +307,36 @@ method !get-server ($server is copy) { return %!servers{$server}; } +method !send-cmd ($cmd, *@args is copy, :$prefix = '', :$server) { + if $cmd eq 'NOTICE'|'PRIVMSG' { + my ($where, $text) = @args; + if @!filters + and my @f = @!filters.grep({ + .signature.ACCEPTS: \($text) + or .signature.ACCEPTS: \($text, :$where) + }) + { + start { + CATCH { default { warn $_; warn .backtrace } } + for @f -> $f { + given $f.signature.params.elems { + when 1 { $text = $f($text); } + when 2 { ($text, $where) = $f($text, :$where) } + } + } + self!ssay: :$server, join ' ', $cmd, $where, ":$prefix$text"; + } + } + else { + self!ssay: :$server, join ' ', $cmd, $where, ":$prefix$text"; + } + } + else { + @args[*-1] = ':' ~ @args[*-1] if @args; + self!ssay: :$server, join ' ', $cmd, @args; + } +} + method !set-server-attr ($server, $method, $what) { if $server ne '*' { %!servers{$server}."$method"() = $what; diff --git a/lib/IRC/Client/Message.pm6 b/lib/IRC/Client/Message.pm6 index 89295e3..a62972d 100644 --- a/lib/IRC/Client/Message.pm6 +++ b/lib/IRC/Client/Message.pm6 @@ -28,7 +28,7 @@ role Unknown does M { } role Ping does M { - method reply { $.irc.send-cmd: 'PONG', $.args, :$.server; } + method reply { $.irc!IRC::Client::send-cmd: 'PONG', $.args, :$.server; } } role Privmsg does M { @@ -39,13 +39,14 @@ role Privmsg does M { role Privmsg::Channel does Privmsg { has $.channel; method reply ($text, :$where) { - $.irc.send-cmd: 'PRIVMSG', $where // $.channel, $text, + $.irc!IRC::Client::send-cmd: 'PRIVMSG', $where // $.channel, $text, :$.server, :prefix("$.nick, "); } } role Privmsg::Me does Privmsg { method reply ($text, :$where) { - $.irc.send-cmd: 'PRIVMSG', $where // $.nick, $text, :$.server; + $.irc!IRC::Client::send-cmd: 'PRIVMSG', $where // $.nick, $text, + :$.server; } } @@ -57,14 +58,15 @@ role Notice does M { role Notice::Channel does Notice { has $.channel; method reply ($text, :$where) { - $.irc.send-cmd: 'NOTICE', $where // $.channel, $text, + $.irc!IRC::Client::send-cmd: 'NOTICE', $where // $.channel, $text, :$.server, :prefix("$.nick, "); $.replied = True; } } role Notice::Me does Notice { method reply ($text, :$where) { - $.irc.send-cmd: 'NOTICE', $where // $.nick, $text, :$.server; + $.irc!IRC::Client::send-cmd: 'NOTICE', $where // $.nick, $text, + :$.server; $.replied = True; } } -- cgit v1.1