Design for an IRC bot

This was a series of notes for what became saxo.

The language: Python 3

The architecture: modular

Ah, IRC bots. They're harder than they look to design. (If Twitter clients are a UI design playground, IRC bots may well be a good example of a program-architecture playground. —dpk)

Science bit

The network I/O can be done with select, but commands ideally need to be run in pre-forked separate processes, which means doing resource restriction.

Ideally you also have a monitor process that runs "this can be slow" commands such as storing most recently noted links and so on.

You also need a scheduler and a database. You want these to rock.

Configuration file

Best choice: INI style?

Used Python files for phenny, and JSON files for duxlot.

Writeback of configuration values is not necessarily a good idea.

23:07:44 <sbp> it'll be funny if we both, once a year, give up on maintaining bots and the other one steps in to cover
23:08:25 <sbp> "as far as I remember, it was quite easy!" (a year passes) "FETCH ME MY CROWBAR"

Rough ideas

Create a ./saxo main controller. daemonise.py module, which needs to be checked in Windows, perhaps using a ReactOS VM, or TravisCI (or both). ./saxo-database for SQLite integration, which runs as a server using a file socket and may need to be threaded. Bot is invoked using ./saxo (start|stop|restart) [ directory ] only, where directory defaults to ~/.saxo. The configuration file is INI-style, and uses Python's standard configfile module. It only contains things necessary for setting up the bot. Oh, ./saxo create or ./saxo setup should create a default setup in ~/.saxo/config for you, or ~/.saxo/config.txt. ./saxo-scheduler uses the database script to get its values. Everything is persisted on disc. There could be an options.py to provide default option parsing, and also extensions. There should be a few kinds of extension:

There would be a ./saxo-command which runs under very strict rlimits, and is invoked once per command. In fact it could even be invoked once per line, unless a separate ./saxo-monitor process would be better. There ought to be a process pool of them so that they don't get behind. Not sure how large the process pool would have to be. Anyway, it's not really a pool—just a prefork architecture. And they're not really forks. Every component should have really good tests, and be well documented.

There should be modules for extensions to use, such as web.py or request.py, and commandparse.py for handling certain kinds of input such as :flags and [interpolated quotes]. These should be collected together and usable from a central saxo.py module which can be imported. That module should also give some kind of access to the ./saxo script. Possibly the ./saxo script should be a small wrapper around another module that both it and saxo.py can interface.

Since the main ./saxo script has to be a server, the network part needs to be outsourced to another process, ./saxo-network. This would need to write to the ./saxo server, which doesn't need to be threaded, to give input. It could take input from stdin, though.