aboutsummaryrefslogtreecommitdiff
path: root/lib/IRC/Client/Core.rakumod
blob: 8cba445a823fc8fc81f42bb7634557a784f32890 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
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