1 8f7f2f4a 2021-12-17 jrmu ================================================================================
3 8f7f2f4a 2021-12-17 jrmu AutoGreet Explained
5 8f7f2f4a 2021-12-17 jrmu The first 6 lines of autogreet.pl are similar to dicebot.pl from the
6 8f7f2f4a 2021-12-17 jrmu previous lesson:
8 8f7f2f4a 2021-12-17 jrmu #!/usr/bin/perl
10 8f7f2f4a 2021-12-17 jrmu use warnings;
12 8f7f2f4a 2021-12-17 jrmu package GreetBot;
13 8f7f2f4a 2021-12-17 jrmu use base qw(Bot::BasicBot);
15 8f7f2f4a 2021-12-17 jrmu The only difference is we changed the package to GreetBot instead of
18 8f7f2f4a 2021-12-17 jrmu Next, we have our first subroutine chanjoin, which greets new users
19 8f7f2f4a 2021-12-17 jrmu whenever one joins a channel.
21 8f7f2f4a 2021-12-17 jrmu sub chanjoin {
22 8f7f2f4a 2021-12-17 jrmu my $self = shift;
23 8f7f2f4a 2021-12-17 jrmu my $arguments = shift;
24 8f7f2f4a 2021-12-17 jrmu my $nick = $arguments->{who};
25 8f7f2f4a 2021-12-17 jrmu if ($nick eq $self->pocoirc->nick_name()) {
29 8f7f2f4a 2021-12-17 jrmu channel => $arguments->{channel},
30 8f7f2f4a 2021-12-17 jrmu body => "Welcome, $nick!",
34 8f7f2f4a 2021-12-17 jrmu We store the user's nick in $nick:
36 8f7f2f4a 2021-12-17 jrmu my $nick = $arguments->{who};
38 8f7f2f4a 2021-12-17 jrmu Afterwards, we check if the new user's nick, $nick, is the same as our
39 8f7f2f4a 2021-12-17 jrmu bot's nick, $self->pocoirc->nick_name(). When the bot itself first joins
40 8f7f2f4a 2021-12-17 jrmu a channel, chanjoin is called. We don't want the bot to greet itself, so
41 8f7f2f4a 2021-12-17 jrmu we skip it with return.
43 8f7f2f4a 2021-12-17 jrmu if ($nick eq $self->pocoirc->nick_name()) {
47 8f7f2f4a 2021-12-17 jrmu The return statement exits a subroutine without executing any
48 8f7f2f4a 2021-12-17 jrmu of the code that comes after it:
50 8f7f2f4a 2021-12-17 jrmu Next, we tell the bot to send a message to the channel to greet the new
54 8f7f2f4a 2021-12-17 jrmu channel => $arguments->{channel},
55 8f7f2f4a 2021-12-17 jrmu body => "Welcome, $nick!",
58 8f7f2f4a 2021-12-17 jrmu Up next is the subroutine chanpart. It is called whenever a user parts from
59 8f7f2f4a 2021-12-17 jrmu a channel. It tells the bot to send a message whenever a user leaves:
61 8f7f2f4a 2021-12-17 jrmu sub chanpart {
62 8f7f2f4a 2021-12-17 jrmu my $self = shift;
63 8f7f2f4a 2021-12-17 jrmu my $arguments = shift;
65 8f7f2f4a 2021-12-17 jrmu channel => $arguments->{channel},
66 8f7f2f4a 2021-12-17 jrmu body => "I'm sad to see $arguments->{who} go.",
70 8f7f2f4a 2021-12-17 jrmu Take a closer look at the value of body:
72 8f7f2f4a 2021-12-17 jrmu body => "I'm sad to see $arguments->{who} go.",
74 8f7f2f4a 2021-12-17 jrmu Notice that $arguments->{who} is put right inside the quotation marks, but
75 8f7f2f4a 2021-12-17 jrmu the message does not literally have the string "$arguments->{who}". Instead,
76 8f7f2f4a 2021-12-17 jrmu perl evalutes $arguments->{who} to get the user's nick, then puts that value
77 8f7f2f4a 2021-12-17 jrmu into the string.
79 8f7f2f4a 2021-12-17 jrmu We do something different for the subroutine emoted. Instead of merely
80 8f7f2f4a 2021-12-17 jrmu sending a message, we will emote it (send an action message):
82 8f7f2f4a 2021-12-17 jrmu sub emoted {
83 8f7f2f4a 2021-12-17 jrmu my $self = shift;
84 8f7f2f4a 2021-12-17 jrmu my $arguments = shift;
86 8f7f2f4a 2021-12-17 jrmu $self->emote(
87 8f7f2f4a 2021-12-17 jrmu channel => $arguments->{channel},
88 8f7f2f4a 2021-12-17 jrmu body => "$arguments->{body} too",
92 8f7f2f4a 2021-12-17 jrmu On many irc clients, you can type /me <your-text-here> to emote.
93 8f7f2f4a 2021-12-17 jrmu Watch the bot emote back!
95 8f7f2f4a 2021-12-17 jrmu In the subroutine noticed, we use an array for @notices:
97 8f7f2f4a 2021-12-17 jrmu sub noticed {
98 8f7f2f4a 2021-12-17 jrmu my $self = shift;
99 8f7f2f4a 2021-12-17 jrmu my $arguments = shift;
101 8f7f2f4a 2021-12-17 jrmu my $nick = $arguments->{who};
103 8f7f2f4a 2021-12-17 jrmu my @notices = (
104 8f7f2f4a 2021-12-17 jrmu "$nick, please resend this in a normal message",
105 8f7f2f4a 2021-12-17 jrmu "I'm having a hard time reading your notice.",
106 8f7f2f4a 2021-12-17 jrmu "Good point, $nick.",
107 8f7f2f4a 2021-12-17 jrmu "Can you message on the public channel instead?",
110 8f7f2f4a 2021-12-17 jrmu $self->notice(
111 8f7f2f4a 2021-12-17 jrmu who => $nick,
112 8f7f2f4a 2021-12-17 jrmu channel => $arguments->{channel},
113 8f7f2f4a 2021-12-17 jrmu body => $notices[int(rand(4))],
117 8f7f2f4a 2021-12-17 jrmu When you send a notice to the bot or to a channel the bot is in, it will
118 8f7f2f4a 2021-12-17 jrmu reply with one of four different notices:
120 8f7f2f4a 2021-12-17 jrmu my @notices = (
121 8f7f2f4a 2021-12-17 jrmu "$nick, please resend this in a normal message",
122 8f7f2f4a 2021-12-17 jrmu "I'm having a hard time reading your notice.",
123 8f7f2f4a 2021-12-17 jrmu "Good point, $nick.",
124 8f7f2f4a 2021-12-17 jrmu "Can you message on the public channel instead?",
127 8f7f2f4a 2021-12-17 jrmu The sigil (the symbol before a variable) for an array is @. An array
128 8f7f2f4a 2021-12-17 jrmu can begin with an open and close parenthesis ( ) and the items inside are
129 8f7f2f4a 2021-12-17 jrmu separated with commas ,.
131 8f7f2f4a 2021-12-17 jrmu @notices has four strings. Those strings use double quotes so
132 8f7f2f4a 2021-12-17 jrmu that the variables inside will get interpolated.
134 8f7f2f4a 2021-12-17 jrmu An array stores many items, each one with a unique index. The first
135 8f7f2f4a 2021-12-17 jrmu element of the array @notices is $notices[0]. The second element is
136 8f7f2f4a 2021-12-17 jrmu $notices[1], and the third is $notices[2].
138 8f7f2f4a 2021-12-17 jrmu Arrays in Perl (like in most programming languages) begin with 0 as
139 8f7f2f4a 2021-12-17 jrmu the first index.
141 8f7f2f4a 2021-12-17 jrmu body => $notices[int(rand(4))],
143 8f7f2f4a 2021-12-17 jrmu rand(n) will return a random float between 0 and n. int() *truncates*
144 8f7f2f4a 2021-12-17 jrmu the float, meaning it drops everything after the decimal point. For
145 8f7f2f4a 2021-12-17 jrmu example, int(3.1415) gets *truncated* to 3: everything after the
146 8f7f2f4a 2021-12-17 jrmu decimal point gets ignored.
148 8f7f2f4a 2021-12-17 jrmu int(rand(4)) gives a random integer from 0 to 3, which we use as the
149 8f7f2f4a 2021-12-17 jrmu index for $notices. In other words, the body is a random notice chosen
150 8f7f2f4a 2021-12-17 jrmu from an array of four notices.
152 8f7f2f4a 2021-12-17 jrmu In the subroutine topic, anytime the topic is changed, the bot will
153 8f7f2f4a 2021-12-17 jrmu add a short warning to the end of it:
155 8f7f2f4a 2021-12-17 jrmu sub topic {
156 8f7f2f4a 2021-12-17 jrmu my $self = shift;
157 8f7f2f4a 2021-12-17 jrmu my $arguments = shift;
159 8f7f2f4a 2021-12-17 jrmu if ($arguments->{who} eq $self->pocoirc->nick_name()) {
162 8f7f2f4a 2021-12-17 jrmu $self->pocoirc->yield('topic' => $arguments->{channel} => "$arguments->{topic} || Don't change the topic!");
165 8f7f2f4a 2021-12-17 jrmu If the new nick $arguments->{who} is the same as the bot's current nick
166 8f7f2f4a 2021-12-17 jrmu $self->pocoirc->nick_name(), then we return and do nothing. This line
167 8f7f2f4a 2021-12-17 jrmu is necessary to prevent an infinite loop. Without this line, if the bot
168 8f7f2f4a 2021-12-17 jrmu changes the topic, the subroutine topic will get called again, causing
169 8f7f2f4a 2021-12-17 jrmu the bot to again change the topic.
171 8f7f2f4a 2021-12-17 jrmu if ($arguments->{who} eq $self->pocoirc->nick_name()) {
175 8f7f2f4a 2021-12-17 jrmu The bot will change the topic in the current channel to a new topic.
176 8f7f2f4a 2021-12-17 jrmu This topic contains the original topic plus "|| Don't change the topic!":
178 8f7f2f4a 2021-12-17 jrmu $self->pocoirc->yield('topic' => $arguments->{channel} => "$arguments->{topic} || Don't change the topic!");
180 8f7f2f4a 2021-12-17 jrmu The last subroutine is nick_change:
182 8f7f2f4a 2021-12-17 jrmu sub nick_change {
183 8f7f2f4a 2021-12-17 jrmu my $self = shift;
184 8f7f2f4a 2021-12-17 jrmu my $oldnick = shift;
185 8f7f2f4a 2021-12-17 jrmu my $newnick = shift;
187 8f7f2f4a 2021-12-17 jrmu if ($newnick eq $self->pocoirc->nick_name()) {
191 8f7f2f4a 2021-12-17 jrmu $self->pocoirc->yield('nick' => "$oldnick");
192 8f7f2f4a 2021-12-17 jrmu $self->say(
193 8f7f2f4a 2021-12-17 jrmu who => "$newnick",
194 8f7f2f4a 2021-12-17 jrmu body => "If you don't mind, I'd like to use your old nick.",
198 8f7f2f4a 2021-12-17 jrmu Again, if the new nick is the same as the bot's current nick, we return
199 8f7f2f4a 2021-12-17 jrmu to prevent an infinite loop:
201 8f7f2f4a 2021-12-17 jrmu if ($newnick eq $self->pocoirc->nick_name()) {
205 8f7f2f4a 2021-12-17 jrmu We change the bot's nick to $oldnick:
207 8f7f2f4a 2021-12-17 jrmu $self->pocoirc->yield('nick' => "$oldnick");
209 8f7f2f4a 2021-12-17 jrmu Then have the bot send a message to the user who changed his nick:
211 8f7f2f4a 2021-12-17 jrmu $self->say(
212 8f7f2f4a 2021-12-17 jrmu who => "$newnick",
213 8f7f2f4a 2021-12-17 jrmu body => "If you don't mind, I'd like to use your old nick.",
216 8f7f2f4a 2021-12-17 jrmu The last bit of code is similar to DiceBot. We create a GreetBot then run it:
218 8f7f2f4a 2021-12-17 jrmu package main;
220 8f7f2f4a 2021-12-17 jrmu my $bot = GreetBot->new(
221 8f7f2f4a 2021-12-17 jrmu server => 'irc.example.com',
222 8f7f2f4a 2021-12-17 jrmu port => '6667',
223 8f7f2f4a 2021-12-17 jrmu channels => ['#perl102'],
224 8f7f2f4a 2021-12-17 jrmu nick => 'nickname',
225 8f7f2f4a 2021-12-17 jrmu name => 'username',
227 8f7f2f4a 2021-12-17 jrmu $bot->run();
229 8f7f2f4a 2021-12-17 jrmu ================================================================================
231 8f7f2f4a 2021-12-17 jrmu To learn more about the Bot::BasicBot framework, visit:
233 8f7f2f4a 2021-12-17 jrmu https://metacpan.org/pod/Bot::BasicBot
235 8f7f2f4a 2021-12-17 jrmu View the file ~/challenge to finish the lesson.
237 8f7f2f4a 2021-12-17 jrmu ================================================================================