From b6da79a0bc1289f2a6064a6b3ffcd0c2333f2c97 Mon Sep 17 00:00:00 2001 From: Patrick Spek Date: Wed, 5 May 2021 11:03:32 +0200 Subject: Initial commit --- lib/IRC/Client/Core.rakumod | 155 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 lib/IRC/Client/Core.rakumod (limited to 'lib/IRC/Client/Core.rakumod') diff --git a/lib/IRC/Client/Core.rakumod b/lib/IRC/Client/Core.rakumod new file mode 100644 index 0000000..8cba445 --- /dev/null +++ b/lib/IRC/Client/Core.rakumod @@ -0,0 +1,155 @@ +#! /usr/bin/env false + +use v6.d; + +use IRC::Client::Handler; +use IRC::Client::Plugin; +use Log; + +#| A plugin for IRC::Client, encapsulating all the core functionality required +#| of a functional IRC client. +unit class IRC::Client::Core is IRC::Client::Plugin; + +#| Special cased method to setup the initial connection with IRC. +multi method irc-setup ($irc) { + $irc.connected = True; + $irc.send-raw("USER {$irc.user} 8 * :{$irc.real-name}"); + $irc.set-nick($irc.nicks[0]); +} + +#| Special cased method to perform actions once the client is ready to go to +#| work. +multi method irc-ready ($irc) { + for $irc.channels -> $channel { + $irc.join($channel); + } +} + +#| Handle RPL_WELCOME. This message indicates that the connection setup has +#| been succesful. +multi method irc-n001 ($message) { + my $nick = $message.params[0]; + + .debug("Logged in as $nick") with $Log::instance; + + $.irc.prefix = $message[*-1].words.tail; + $.irc.nick = $nick; +} + +#| Handle ERR_ERRONEUSNICKNAME. This message indicates that the nickname which +#| is being used is not allowed, and the client should try an alternative +#| instead. +multi method irc-n432 ($message where { $_.params[0] eq '*' }) { + .error($message.params[*-1]) with $Log::instance; + + my @nicks = $.irc.nicks; + my $index = @nicks.first($.irc.nick, :k) + 1 // 0; + + if (@nicks.elems ≤ $index) { + .warning("No more nicks to try ({@nicks.join(' ')})") with $Log::instance; + $.irc.stop; + exit(3); + } + + $.irc.set-nick(@nicks[$index]); +} + +#| Handle ERR_NICKNAMEINUSE. This message indicates the nickname which is being +#| used is already in use by another client. Another nickname should be tried +#| instead. +multi method irc-n433 ($message where { $_.params[0] eq '*' }) { + self.irc-n432($message); +} + +multi method irc-n433 ($message where { $_.params[0] ne '*'}) { + $.irc.nick = $_.params[1]; +} + +#| Handle ERR_CHANNELISFULL. This message indicates a channel could not be +#| joined due to a user count limitation (+l). +multi method irc-n471 ($message) { + self!unregister-channel($.irc, $message.params[1]); +} + +#| Handle ERR_INVITEONLYCHAN. This message indicates a channel could not be +#| joined because you must be invited (+i). +multi method irc-n473 ($message) { + self!unregister-channel($message.params[1]); +} + +#| Handle ERR_BANNEDFROMCHAN. This message indicates a channel could not be +#| joined due to an active ban (+b). +multi method irc-n474 ($message) { + self!unregister-channel($message.params[1]); +} + +#| Handle ERR_BADCHANNELKEY. This message indicates a channel could not be +#| joined because it requires a key, or the given key was incorrect. +multi method irc-n475 ($message) { + self!unregister-channel($message.params[1]); +} + +#| Handle JOIN, but only if it pertains to ourselves. This method will keep the +#| IRC::Client.channels list synced to the channels the bot is actually in. +multi method irc-join ($message where { $_.nickname eq $message.irc.nick }) { + self!register-channel($message.params[0]); +} + +#| Handle PART, but only if it pertains to ourselves. This method will keep the +#| IRC::Client.channels list synced to the channels the bot is actually in. +multi method irc-part ($message where { $_.nickname eq $message.irc.nick }) { + self!unregister-channel($message.params[0]); +} + +#| Handle a CTCP PING request. +multi method irc-privmsg ($message where { $_.ctcp && $_.params[*-1].words[0] eq 'PING'}) { + $.irc.notice($message.nickname, "PING {$message.params[*-1].words[1..*]}", :ctcp); +} + +#| Handle a CTCP VERSION request. +multi method irc-privmsg ($message where { $_.ctcp && $_.params[*-1].words[0] eq 'VERSION'}) { + $.irc.notice($message.nickname, 'VERSION raku/IRC::Client v0.1.0', :ctcp); +} + +#| Handle a PING command. This message should be responded to with a PONG +#| reply, to indicate the client is still alive. +multi method irc-ping ($message) { + $.irc.send-raw("PONG :{$message.params[*-1]}"); +} + +#| Convenience method for adding a channel to the IRC::Client.channels list. +method !register-channel ($channel) { + my @channels = $.irc.channels; + + return if @channels ∋ $channel; + + .debug("Adding $channel to the IRC::Client.channels") with $Log::instance; + + $.irc.channels.append($channel); +} + +#| Convenience method for removing a channel from the IRC::Client.channels +#| list. +method !unregister-channel ($channel) { + .debug("Removing $channel from IRC::Client.channels") with $Log::instance; + + $.irc.channels = $.irc.channels.grep(* ne $channel); +} + +=begin pod + +=NAME IRC::Client::Core +=AUTHOR Patrick Spek <~tyil/raku-devel@lists.sr.ht> +=VERSION 0.0.0 + +=head1 Synopsis + +=head1 Description + +=head1 Examples + +=head1 See also + +=end pod + +# vim: ft=perl6 noet -- cgit v1.1