Writing IRC bots with Perl's BasicBot

Chat Bot

Article from Issue 239/2020

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


01 #!/usr/bin/perl
03 use strict;
04 use warnings;
06 # Create a HelloBot class using Bot::BasicBot as parent.
07 package HelloBot;
08 use base qw(Bot::BasicBot);
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 }
20 # Main program begins.
21 package main;
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 );
33 # Run the instance we just created.
34 $bot->run();
Figure 1: hellobot.pl connects to a channel, drops a message, and disconnects.

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


01 #!/usr/bin/perl
03 use strict;
04 use warnings;
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";
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";
21 # Create a RelayBot class using Bot::BasicBot as parent.
22 package RelayBot;
23 use base qw(Bot::BasicBot);
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 }
34 # Custom methods we create just for RelayBot.
35 sub altbot {
36         my $self = shift();
37         return ${$self->{alt_bot}};
38 }
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 }
54 # Main program begins
55 package main;
56 use POE;
58 # Create RelayBot objects.
59 my ($bot_1, $bot_2);
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 );
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 );
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.

Figure 2: relaybot.pl in a test environment that connects to two different IRC servers and relays messages between them. In this case, users slackware and devuan can maintain a conversation despite being connected to different IRC systems.

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

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Perl: Log Chat Sessions

    The IRC (Internet Relay Chat) protocol lets you program bots as automatic helpers. In this month's column, we let a bot log a session and store the results in a database.

  • Building an IRC Bot

    Chat rooms aren't just for people. We'll show you how to access an IRC channel using an automated bot.

  • Perl: Arduino Project

    With a few lines of self-written firmware and a simple Perl script, Perlmeister Mike Schilli trains one of his Linux computers with a plugged in Arduino board to switch electrical equipment on and off using a relay. Enchanting.

  • Revisit IRC

    Drop Discord. Say goodbye to Slack. The real way to communicate online is IRC – here's why it still rocks.

  • WebRTC Protocol

    The WebRTC protocol converts your web browser into a communications center, supporting video chat over a peer-to-peer connection without the need for helper apps or browser plugins.

comments powered by Disqus
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.

Learn More