Creating a simple IRC Bot in Python
IRC, Internet Relay Chat, is a text chat program created in 1988. Although this technology is outdated, many IRC servers still continue to exist with thousands of users discussing different topics and sharing information. Mostly, IRC is used among developers. There are many open source projects IRC channels on the internet; even on private servers, developers from huge companies still prefer to communicate using IRC channels.
An IRC Bot is basically a program that is going to parse and interpret what the users from IRC channels are sending directly or indirectly to this bot. This could be an open message on the channel or a message directly to the bot, that is going to be parsed and interpreted to execute commands, log the chat in a file or even reply to some questions the users might send.
For this IRC Bot we are going to use Python 3 and mainly its socket library to handle the low-level networking communication.
Connecting to an IRC channel
First, you need to choose a server and a channel to connect. It is recommended to use a channel name that does not exist. By creating a new channel you will be the only user on that channel, which will allow you to not affect other users with the tests. If you do not have a preference for IRC servers, try Freenode IRC Server.
At the top, we are going to define some constant variables that will store the connection information. After, we will define a function initializeBot()
that is going to connect the bot to the server and channel you defined previously.
Here, we are going to define the IRC
object. It is going to be a socket to connect and communicate with the IRC server. Sockets serve for many purposes. In this case, we are going to use it to establish a continuous connection with the IRC server while the bot is sending and receiving information.
After connecting we need to send the IRC server some information about the bot with the send()
command, such as the nickname, ident, realname. Make sure that before sending the information you add a sleep()
command of 5 seconds, In some servers the bot might take a while to connect, so you need to make sure it is already connected to the server to send the command to join a channel.
1 | SERVER = 'chat.freenode.net' |
More info: Python Sockets
Event Loop
The event loop, also known as the main loop, will be used to check if some message has been sent to the channel that our IRC bot is connected to and handle the message properly later on. In order to achieve that we first need to create a loop that is going to be checking for messages. We do not want this loop to be checking non-stop, which is why we are putting a sleep()
command for this loop to run each half a second. This way we will not require as much processing power and as much delay to reply.
Each half a second, we will get what our socket received using the recv()
command. It is recommended to use a relatively small power of 2 number, such as 4096
to be the buffer size. Decode it from bytes object to human readable text and save it on a variable called readBuffer
, splitting each line we received into a string list to be passed to the function that is going to handle each line of text individually.
1 | if __name__ == '__main__': |
More info: Event Loop, Encoding/Decoding
Handling the message
For each message we receive, we are going to handle it using the function below. First we use rstrip()
and split()
string handling functions to trim default trailing characters from the end of our message and then break down this message into smaller chunks (strings), which we will use inside of an array received by the split()
function.
1 | def handleLine(line): |
More info: Common String Operations
Ping Pong
IRC servers send out PING
message from time to time to check if the users are still connected. One must respond to that message with PONG
, and that’s what we are doing in the code below, we send a PONG
right away. This is defined by the IRC Client Protocol.
1 | if line[0] == 'PING': |
More info: IRC Client Protocol
Identifying the message
For the other messages, first, we must identify who’s the sender and get the complete message before going to the next step. As the protocol implies, the format for messages from users to channels and to another users is source PRIVMSG :Message
. We are using two auxiliar functions in order to identify these parts, getSenderName()
and getMessage()
based on the format.
1 | def getSenderName(line): |
Now we are making usage of these functions to identify the sender
and the message
, and logging messages sent and received to the standard output.
1 | if line[1] == 'PRIVMSG': |
More info: Common String Operations, Standard Streams
Parsing the message
In the next step we are going to interpret the message from the user to our bot and reply. In this case, we are replying if someone asks the bot who's your master
or a similar phrase containing the keyword master
in it. We are going to reply with the name we set in the MASTER
variable. Otherwise we will reply with a default message.
Note that I am using lower()
string handling function since we want to compare the strings in case insensitive.
1 | def parseMessage(message): |
Now we are making usage of this function to send the user a message only if the message sent to the channel begins with $(YOUR_BOT_NICKNAME)
. You could reply to any message, but normally IRC Bots are requested to answer something only when called. Otherwise it would be annoying for the users on that channel.
1 | if message.startswith(NICK): |
More info: Parsing, Case Sensitivity
Ready!
This concludes our simple IRC bot in Python, if you are interested in this topic you can search for popular IRC Bots on Github. There are plenty of open source IRC Bot projects in different languages. You can find the complete code for this bot on my Github Repository