Writing IRC bots with Perl's BasicBot
Chat Bot
Writing an IRC chat bot does not have to be difficult. We'll show you how to create your own custom IRC bot using the Perl BasicBot module.
Internet Relay Chat (IRC) is a popular protocol for sustaining group conversations online. The user connects to an IRC server, which is usually part of an IRC network, and joins chat rooms, known as channels, in IRC terminology. Channels are carried by every server that is part of the same IRC network, so users all across the network can join the same channels and talk to each other in real time.
An IRC bot is a program that connects to a chat service as if it were a user and performs automated tasks. Bots are used for running games, conveying messages across different networks, managing user authentication, and much more.
Building a custom bot might seem like a high-end task limited to an enterprise web portal or other commercial service, but in fact, homegrown bots serve a number of roles on smaller networks and are often deployed by local organizations and community groups. For instance, the #bitcoin-otc
channel in the Freenode IRC network makes use of a bot for maintaining the reputation score of the buyers and sellers that trade in the chat. On the other hand, the I2P project keeps a bot that passes messages from users in Freenode to users in Irc2p, the official I2P IRC network.
Several frameworks exist for making your own bot, and you can also start with a pre-designed bot and tweak it to your own liking. In this article, I will focus on the BasicBot
Perl module, which allows you to create bots very quickly. This module takes care of the hard parts of writing a bot and lets you focus on what you want your bot to do.
The goal of this article is to explain how to build useful bots with BasicBot
. I'll use a simple relay bot as an example. This text assumes you have familiarity with Perl and Object Oriented Programming (see the box entitled "New to Object Oriented Programming?"), but even if you're new to Perl, the discussion should give you some insights into Perl programming and the nature of IRC bots.
New to Object Oriented Programming?
In the Object Oriented Programming (OOP) model, objects are data structures that contain attributes and methods. Attributes are characteristics of the object, and methods are things the object can do. Objects also belong to classes, which define which attributes and methods the object possesses. For example, objects from the class Horse
all have the weight
attribute and the neigh
and eat
methods. Therefore, if I create object sophie
as a Horse
, sophie
will have a weight
and will be able to eat
and neigh
.
Objects are organized in hierarchical trees. For example, Horse
is a subclass of Animal
. A Horse
can do anything an Animal
can do, which is to say, if an Animal
can procreate
, a Horse
also has such a method – because a Horse
is actually an Animal
. However, not every animal procreates the same way.
Following the example, an Animal
object will have a generic procreate
method that creates other Animals
. A Dove
object will have a specific procreate
method that creates other Doves
by laying eggs, overriding the default procreate
method from the Animal
class. A Horse
will have yet another specific method for giving birth to other Horse
objects, replacing Animal
's generic procreate
via override.
The BasicBot
class has many stub methods that do nothing. The idea is for you to create your own bot subclasses, overriding the stub methods with ones that do what you want them to do.
Preparing the Environment
Before you start coding, you must install the software. On a Devuan system, the following command will get all the components required for this tutorial. (libpoe-component-sslify-perl
is needed in case the bot needs to make TLS connections.)
# apt-get install libpoe-component-sslify-perllibbot-basicbot-perl
Alternatively, you can install these components from the CPAN online Perl archive if you have a CPAN client such as cpanm
:
# apt-get install cpanminus make
Using cpanm
[1] allows you to install Perl modules as a regular user. You can configure your environment for installing the modules in your $HOME
instead of the whole system as follows:
$ cpanm --local-lib=~/perl5 local::lib && eval $(perl -I ~/perl5/lib/perl5/ -Mlocal::lib)
Then, you can use cpanm
to install the modules you need:
$ cpanm -i POE::Component::SSLify Bot::BasicBot
BasicBot Concepts
BasicBot
provides a Bot::BasicBot baseclass. It is intended to be subclassed, overriding BasicBot
's methods as needed. (See the box entitled "BasicBot's Methods.")
Listing 1 shows a proof-of-concept bot that joins a channel, says "Hello, World!"
, and disconnects from the chat. The use string
and use warnings
flags instruct Perl to enforce proper programming practices and to display warnings. These flags should be included in any serious program. Lines 7 to 18 are used to define a custom bot subclass, HelloBot
. HelloBot
overrides BasicBot
's connected
method. The connected
method is executed when BasicBot
, or any bot subclassed from it, connects to a server. In the example, connected
sends the message "Hello, World!"
to the first channel of the server the HelloBot
connects to and then shuts the bot down (see Figure 1).
Listing 1
hellobot.pl
01 #!/usr/bin/perl 02 03 use strict; 04 use warnings; 05 06 # Create a HelloBot class using Bot::BasicBot as parent. 07 package HelloBot; 08 use base qw(Bot::BasicBot); 09 10 # Override BasicBot's connected method. 11 sub connected { 12 my $self = shift; 13 $self->say( 14 channel => ($self->channels)[0], 15 body => "Hello, World!", 16 ); 17 $self->shutdown; 18 } 19 20 # Main program begins. 21 package main; 22 23 # Create a HelloBot instance 24 my $bot = HelloBot->new( 25 server => 'irc.colosolutions.net', 26 port => '6667', 27 channels => ['#funwithbots'], 28 nick => 'HelloBot', 29 name => 'Hello Bot', 30 flood => '1', 31 ); 32 33 # Run the instance we just created. 34 $bot->run();
BasicBot's Methods
BasicBot
provides many stub methods that are intended to be overridden by the developer. Every method is passed from the bot object itself as first parameter. The most interesting methods are said
and tick
.
said
is invoked every time the bot hears something in the channel. When that happens, the said
method is passed a hash, which contains who
, body
, and address
elements, among others. who
identifies the user who posted the message. body
contains the message itself, and address
informs if and how somebody was addressed (for example, if somebody wrote Tux: Hello!
, the address field would contain Tux
and the body field would contain Hello!
) You'll find an example of this method in action in Listing 2.
tick
is an event that is called regularly. The tick
event might be used for scheduling tasks that must be carried out repeatedly. If you want the bot to retrieve an RSS feed periodically, use tick
. The tick
event must return a numeric value equal to the number of seconds you want to wait before it is invoked again.
Listing 2
relaybot.pl
01 #!/usr/bin/perl 02 03 use strict; 04 use warnings; 05 06 # Configure the bots. 07 my $botnick_1 = "Sophie"; 08 my $server_1 = "irc.colosolutions.net"; 09 my $port_1 = "6667"; 10 my $channel_1 = "#funwithbots"; 11 # Turn ssl support off. 12 my $ssl_1 = "0"; 13 14 my $botnick_2 = "Diana"; 15 my $server_2 = "irc.canternet.org"; 16 my $port_2 = "6697"; 17 my $channel_2 = "#funwithlinux"; 18 # Turn ssl support on. POE::Component::SSLify required. 19 my $ssl_2 = "1"; 20 21 # Create a RelayBot class using Bot::BasicBot as parent. 22 package RelayBot; 23 use base qw(Bot::BasicBot); 24 25 # Override BasicBot's said method. 26 sub said { 27 my ($self, $message) = @_; 28 # This "if" is necessary for forwarding addressed messages in full. 29 $message->{body} = "$message->{address}: ". 30 "$message->{body}" if $message->{address}; 31 $self->altbot->relay($message); 32 } 33 34 # Custom methods we create just for RelayBot. 35 sub altbot { 36 my $self = shift(); 37 return ${$self->{alt_bot}}; 38 } 39 40 sub relay { 41 my ($self, $message) = @_; 42 # This "if" prevents the bot from relaying private messages. 43 if ( $message->{channel} eq ($self->altbot->channels)[0] ) { 44 $message->{channel} = ($self->channels)[0]; 45 $message->{body} = $message->{who}. 46 " said: ".$message->{body}; 47 $self->say( 48 channel => ($self->channels)[0], 49 body => $message->{body} 50 ); 51 } 52 } 53 54 # Main program begins 55 package main; 56 use POE; 57 58 # Create RelayBot objects. 59 my ($bot_1, $bot_2); 60 61 $bot_1 = RelayBot->new( 62 server => "$server_1", 63 port => "$port_1", 64 channels => ["$channel_1"], 65 nick => "$botnick_1", 66 username => "$botnick_1", 67 name => "$botnick_1", 68 alt_bot => \$bot_2, 69 ssl => "$ssl_1", 70 no_run => 1, 71 ); 72 73 $bot_2 = RelayBot->new( 74 server => "$server_2", 75 port => "$port_2", 76 channels => ["$channel_2"], 77 nick => "$botnick_2", 78 username => "$botnick_2", 79 name => "$botnick_2", 80 alt_bot => \$bot_1, 81 ssl => "$ssl_2", 82 no_run => 1, 83 ); 84 85 # Launch RelayBot objects and connect. 86 $bot_1->run(); 87 $bot_2->run(); 88 $poe_kernel?run();
The main part of the program starts at line 21. Lines 24 to 31 create a HelloBot
object called bot
, configured to join channel #funwithbots
at server irc.colosolutions.net
. Afterwards, line 34 runs the bot.
You can launch the bot using the following command:
$ /usr/bin/perl hellobot.pl
Writing a Relay Bot
HelloBot
is handy for showing how BasicBot
works, but at some point, you will want to write something that is actually useful, such as a relay bot.
A relay bot is a program that reads messages from one channel and posts them in another channel. This is convenient if you want people to talk with users who are located on different IRC networks (as shown in Figure 2). Listing 2 shows a relay bot. This bot connects to #funwithbots
at the irc.colosolutions.net server and #funwithlinux
at the Canternet IRC network (irc.canternet.org) and relays messages between the two channels.
Internally, the program is running two RelayBot
objects, one for each server. Lines 7 to 19 set the variables that will configure both RelayBots
. A RelayBot
will join irc.colosolutions.net
as user Sophie
. The other RelayBot
will join irc.canternet.org
as user Diana
. Line 19 configures the Canternet end to use TLS encryption.
Lines 22 to 52 define the RelayBot
subclass. RelayBot
overrides BasicBot
's said
method on line 26. Lines 29 and 30 are a workaround to ensure that a message gets relayed in full when a user is addressing another user or the bot.
Line 31 tells the RelayBot
that didn't hear the message to post it on its own side. The line uses the altbot
method of the RelayBot
that heard the message to retrieve the other RelayBot
and then invokes the relay
method from this object. It is not beautiful, but it does work.
The main program begins at line 55. Note that the program invokes the Perl Object Environment (POE) with use POE
. The reason is that the RelayBot
objects created between lines 59 and 83 are created with the no_run
flag, which prevents them from connecting upon creation. The last line, $poe_kernel->run()
, launches both bots at the same time.
Launch the bot using the following command:
$ /usr/bin/perl relaybot.pl
To stop the program, press Ctrl+C in the terminal that runs the process.
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
New Linux Kernel Patch Allows Forcing a CPU Mitigation
Even when CPU mitigations can consume precious CPU cycles, it might not be a bad idea to allow users to enable them, even if your machine isn't vulnerable.
-
Red Hat Enterprise Linux 9.5 Released
Notify your friends, loved ones, and colleagues that the latest version of RHEL is available with plenty of enhancements.
-
Linux Sees Massive Performance Increase from a Single Line of Code
With one line of code, Intel was able to increase the performance of the Linux kernel by 4,000 percent.
-
Fedora KDE Approved as an Official Spin
If you prefer the Plasma desktop environment and the Fedora distribution, you're in luck because there's now an official spin that is listed on the same level as the Fedora Workstation edition.
-
New Steam Client Ups the Ante for Linux
The latest release from Steam has some pretty cool tricks up its sleeve.
-
Gnome OS Transitioning Toward a General-Purpose Distro
If you're looking for the perfectly vanilla take on the Gnome desktop, Gnome OS might be for you.
-
Fedora 41 Released with New Features
If you're a Fedora fan or just looking for a Linux distribution to help you migrate from Windows, Fedora 41 might be just the ticket.
-
AlmaLinux OS Kitten 10 Gives Power Users a Sneak Preview
If you're looking to kick the tires of AlmaLinux's upstream version, the developers have a purrfect solution.
-
Gnome 47.1 Released with a Few Fixes
The latest release of the Gnome desktop is all about fixing a few nagging issues and not about bringing new features into the mix.
-
System76 Unveils an Ampere-Powered Thelio Desktop
If you're looking for a new desktop system for developing autonomous driving and software-defined vehicle solutions. System76 has you covered.