InternBot - The modular IRC intern
Internbot is a python irc bot that offers the ability to easily and quickly write plugins for adding functionality specific to your situation. It is written as a set of modular python packages which are imported into the base bot to add functionality. Plugins can be loaded beforehand and also swapped in/out at runtime according to the users' need.
Internbot is well-equipped for situational text generation; it comes bundled with a Markov chain pseudo-random text generator. Internbot can both gather and generate phrases based on the context of the chat, or can be provided with a textfile from which to pull and generate phrases.
This bot was borne out of a joke at my work that an intern's function can be automated away with a simple script - thus the name! After a few weeks running in the background of gathering messages, autogenerated responses started seeming like plausible technical solutions...
Some sample internbots live at my website, and can be reached by pointing your IRC client of
irc.brack.xyz, and joining
#bot, or by visiting my demo page.
Currently loaded modules include intern, lmgtfy, broadcast, and pick. Try them out! Fair warning: drakebot can use some choice language when he gets excited!
Issuing commands is simple -- simply include the botname in a message to a channel it is
currently in, and the the command desired, eg.
internbot get coffee. It follows the general
<botnick> <command> <args>. Of course, some modules can circumvent this,
intern module does, by simply looking for keywords in any text regardless of
whether or not the botnick is mentioned.
If you are joined to the
<botnick> channel, you do not need to preface commands with the
bot's nickname. It will read commands directly as if all messages were prefaced with the
As its name implies, it comes bundled with plugins to mock-up some intern-like behaviour (dig into the 'intern' plugin for more details). Included in the base package are:
intern : The quintessential intern plugin. Namesake of internbot, most of the original bot functionality is encapsulated entirely in this plugin. If loaded, it should be loaded as the last module, to allow proper responses to unknown/unhandled commands.
Any unhandled commands are passed to a Markov chain text generator, which can build reasonable-sounding responses based on the phrase given to internbot. Responses are generated from a file containing sample text [default: botlog.txt].
In the intern plugin config file, if
logchat=True, then internbot will record to file all chatter in a channel. This is a great setting to leave true if you wish to improve text prediction with time. The longer it runs, the more hilarious (and accurate) the responses. Commands:
<botnick> get coffee: when get coffee is found in a message, internbot will part/rejoin with "coffee"
<botnick> say <msg>: repeat a phrase to the channel
coffee: any time the word coffee is mentioned in the chat, internbot mentions something about coffee.
<botnick> <phrase>: uses the last few words of the phrase for predictive text generation. If no textfile containing those words is found, it will default to a few predefined phrases.
lmgtfy : Goes out to google and returns the first "I'm Feeling Lucky" result. Commands:
<botnick> search <phrase>: Gets the first "I'm Feeling Lucky" page matching the search
broadcast : Broadcast messages to all channels internbot has joined. Commands:
<botnick> broadcast <msg>: Send message to all channels
ignore : Ban people from giving internbot commands. Commands:
<botnick> ignore <nick>: add user to blacklist
<botnick> unignore <nick>: remove user from blacklist
loadmod : This module provides the on-the-fly loading/unloading of other modules. If this module is not loaded in the config, you will NOT be able to swap in/out modules at runtime! Be aware that it IS possible for users to get the module to unload itself, forcing internbot to be unable to further load new modules on-the-fly. Commands:
<botnick> loadmod <pluginname>: load the requested plugin into internbot
<botnick> unloadmod <pluginname>: if loaded, unload the requested plugin from internbot.
roku : Connects out to ROKU internet radio boxes to display marquee text on their displays. Text is displayed until changed or this module is unloaded. Tested and works with ROKU models M1000 and M1001. Commands:
<botnick> update roku <message>: Display a rotating marquee message on ROKU
<botnick> show roku: Print the current message being displayed on ROKU
pick : This module helps you decide things! Edit the config file to add your own selections, some choices (that my coworkers are fond of) for lunch are included. Commands:
<botnick> pick <topic>: Randomly pick a choice out of the
<topic>list defined in config
Some commands are important enough they deserved to be built-in to internbot. These include:
<botnick> join <chan>: Join a new channel
<botnick> leave: Leave the current channel
<botnick> replay [first|last] <lines>: Print the least/most recent logged chat lines. If is not set, defaults to printing 5.
Installation and Configuration
Simply download / clone into your directory of choice, and run the bot from its root
python internbot.py. Tested with python2.7 - there might be
super() when running with python3 - use python2.7 for best results.
Installing as a daemon: Copy the install files to the install dir (default: /opt/internbot/). The pid file is stored in /var/internbot/ by default - make sure this is owned by the interbot user. Make sure to add a user as which internbot deamon will run, for security (default: internbot). All these defaults can be edited in the init.d/internbotd script. Install the internbotd startup script to either /etc/init.d/internbotd or /etc/rc.d/internbotd to enable start at boot.
Do not run internbot as root. I make no promises of secure code!
The config file is located at
core/config.py, with the following options:
- server : the address / IP of the IRC server
- port : port on which the IRC server responds. By default, it's port 6667
- botnick : your bot's nickname. By default, it's "internbot"
- channels : channels which your bot will join on start. By default, it will only join #. Channels can be either added here, or joined by issuing command
- memorysize : determines how many lines of chat will be recorded/logged per channel. Set to '0' to disable chat logging.
- plugins : list of plugins to be loaded on start. Plugins are loaded IN ORDER, which CAN
affect the proper operation of some plugins. If the
loadmodmodule is loaded, then plugins can also be loaded on-the-fly once internbot is started.
In addition, each plugin will have its own
config.py file located in its folder in the
Internbot allows customization through quick and easy module building. From within modules and plugins, the user has the ability to modify and access all of the parent classes and their attributes for maximum flexibility. Plugins can range from simple, stand-alones that return dialogue to complex ones which run background tasks as daemons.
A good example for a beginner plugin can be found in the
plugins/broadcast/ directory. A
more complex example, which requires spawning a thread + having background tasks can be
seen in the roku plugin, in
Mandatory components: In your plugin's folder:
__init__.py: this will tell internbot that this is a plugin package. In it, you import your plugin, like so:
from yourpluginname import *
yourmodulename.py: the actual code for your plugin/module. This file should contain a set of mandatory classes, methods and function definitions (outlined below) as well as any additional code to make the plugin function.
config.py(optional) : your plugin's config file
- class Load() : this class is the instance of your plugin. It must contain the following:
def __init__(self, channel): All the setup code for the plugin.
channelis a a reference to the parent Channel() object which is always passed in.
def __del__(self): when the module is unloaded or internbot quits, this code will be executed for cleanup. Complex modules with background tasks or plugins which modify channel methods will want to add cleanup code here.
def run(self, ircmsg): this method is called every time a new message is inter- cepted by internbot.
ircmsgis the raw textline that was recieved from the IRC server. If your module does not require interaction at runtime, simply define this with
def stop(): this is called when unloading the module or when internbot quits. If there are background tasks running, this method can be used to stop them. If no cleanup is needed on halt or unload, then simply define this with
In addition, the
Load() class must include the attribute
self.name, which should be
identical to the the file name of yourmodulename.py
A lot! A refactor is long overdue.