Creating an IRC Bot: Stephen Dunn

“Join us in the DSM Web Geeks chat room to see Stephen’s bot in action and talk about the article.”

Recently I was asked to automatically change the topic of an irc channel for The requirements were to have an IRC bot dynamically change the topic every night and also have a public trigger to force the update to happen. The topic comes from a RSS feed where we filter for specific sections to update the topic with. The task was simple and I will cover the aspects of choosing the right IRC bot and how the custom bot script works.

For the IRC robot I decided to use an Eggdrop so that I could connect to IRC quickly and only have to write a custom script for the Eggdrop itself to change the topic. Originally the Eggdrop was picked because it is known for it’s stability and custom scripting abilities. In recent versions of Eggdrop (1.8) it also has the ability to connect to IRC over SSL this was helpfull in connecting the bot to freenodes’ SSL servers. Lastly setup time for an eggdrop is very minimal and requires little work.

As mentioned above the Eggdrop accepts TCL scripts to be loaded when the bot starts. This next section will describe the custom code that was written to perform the task.

At the top of the script you will find the two binds for the eggdrop to watch for. The first one is the public trigger and second one is the timer. The timer is being called every day at 16:00 or 4pm. The second bind is for the public trigger and used to force an update of the topic. It is called by saying “!topic” inside of the channel.

bind pub -|- !topic update_topic_wraper
bind time -|- "* 16 * * *" update_topic

There are several binds that the egg drop supports but the above are the best to use for the requirements.

We then set the valid types to look for as a global variable in order to be able add/remove/modify allowed types easily. Later on if our RSS topics change or if we need to add another category to the topic we would simply update the validTypes variable.

set validTypes "DoJo Events"
set topicChan "#dsmwebgeeks"

The bot gets its content from a RSS feed on the user groups website. So inside of the script we require the http package in order to connect to the web page and grab the RSS contents to memory.

package require http
set token [http::geturl ""] set rssData [http::data $token] http::cleanup $token

After we have the RSS data we look the first <item> block and check to see if it has one of our valid sections for the channel topic that we are updating. While the item is not valid, increment the counter to the next item block to check for it. This is just one of the ways that you could do it but I feel it is the most efficient way. You could also do this with a foreach loop and split on the ending item tag but using a while loop was picked since the chances that it will not be one of the allowed items is limited and having the foreach loop with the split items would consume more memory.

#Search for first
set offset 0
set searchNoMore 0
while {!$searchNoMore && $searchNoMore <= [string length $rssData]} {
set newOffset [string first "" $rssData $offset]  
set item [string range $rssData [string first "" $rssData $offset] $newOffset] set cat [string range $item [string first "" $item] [string first "" $item]]  
foreach valid $validTypes {
if {[string match -nocase "*$valid*" $cat]} {
set searchNoMore 1
set offset $newOffset

Once we have a valid item block we parse the author and topic. The parsing is simple we could have broken it off into it’s own proc for ease of use, but we are only using a handful of arguments and felt it would be just as fast to hand type them all in.

set item [string range $rssData [string first "" $rssData $offset] $newOffset] set cat [string range $item [string first "" $item] [string first "" $item]]

Finally we have found the valid type and now going to push the TOPIC command to the ircd in order to update it for everyone in the channel.

set auth [string range $item [expr 12 + [string first "" $item]] [expr [string first "" $item] - 1]]  
set title [string range $item [expr 7 + [string first "
" $item]] [expr [string first "
" $item] - 1]] putserv "TOPIC $topicChan :$title ($auth)";

That takes care of grabbing the topic and setting it. We then put that proc as our main public trigger proc. Then for the clock trigger we just simply make a call to the public trigger proc with irrelevant values.

proc update_topic_wraper { n u h c t } {
update_topic 0 0 0 0 0

The final production product was completed in only 30 mins and really easy to do. I encourage everyone to build their own custom IRC channel scripts that read off RSS feeds. Thanks for reading this article and if you have any questions please post here.