Jeremy Shaw | 11 Oct 00:02 2011

ANN: ircbot 0.1.1

Hello,

I have just released a new library on hackage called ircbot. (Because  
that is what Haskell really needs -- another irc bot library).

http://hackage.haskell.org/package/ircbot

A demo app is here:

http://patch-tag.com/r/stepcut/ircbot/snapshot/current/content/pretty/demo.hs

The demo is pretty non-thrilling. 98% of it is parsing command-line  
arguments, and then it calls a simple bot with two parts:

  pingPart - part that handles server PING/PONG requests
  dicePart - a simple part that lets you roll dice

Here is an example session:

<stepcut> synthea: dice 3d4+12
<synthea> You rolled 3 4-sided dice with a +12 modifier: [1,3,4] => 20

The primary reason this library exists is that a long time ago, I  
needed a way to log the #happs channel. So I coded up a little logging  
bot using the irc library from hackage.

Then later I decided to fork the irc logging out of the happstack.com  
server itself and into a resuable irc bot library.

The library has the following features:

  1. a reconnect loop that tries really hard to make sure the bot  
notices if it is disconnected and tries to reconnect.

  2. a channel logging facility that automatically rolls over to a new  
log file every day.

  3. a BotMonad class and BotPartT monad which make it easy to create  
handlers for incoming messages:

http://patch-tag.com/r/stepcut/ircbot/snapshot/current/content/pretty/Network/IRC/Bot/BotMonad.hs

Each bot part is run in its own thread. Incoming messages are  
delivered to all the parts. That is useful because some parts, like  
the seen command, need to see every incoming message, even if they do  
not actively respond to them. Because the parts are handled by  
different threads, they do not block each other.

By default, each part is single-threaded. That is because some parts  
may need to see multiple messages and see them in the order they  
originally arrived. However, a part can easily call forkIO to handle  
each incoming Message and avoid blocking when appropriate.

  4. a wrapper that let's you use Parsec to parse an incoming message.  
It is used by the dicePart:

http://patch-tag.com/r/stepcut/ircbot/snapshot/current/content/pretty/Network/IRC/Bot/Part/Dice.hs

Using parsec gives you an easy way to specify syntax errors:

<stepcut>  synthea: dice
<synthea> unexpected end of input; expecting dice <num-dice>d<num- 
sides>[+<modifier>]

Future work:

1. The library is based around the old String based irc library. Would  
be nice to upgrade to something that used ByteStrings+Text+Builder.  
Practically speaking.. it's IRC. The maximum line length is 510  
characters, and the bot typically needs to handle, at most, a few  
messages per second. So, space and time issues would only be a  
practical concern if your bot is joining hundreds of channels. But,  
that is no excused not to use Text :) Perhaps the fastirc library?

2. The channel logging feature needs some minor changes so that more  
than one channel at a time can be logged

3. the bot needs to do something sane if the nick it wants is already  
in use. It should also support nick registration.

4. needs automatic help text generation

5. documentation

6. It should be possible to support dynamically reloadable plugins.  
Most of the technology exists in happstack-plugins + plugins. We just  
need to finish splitting happstack-plugins into two packages.

7. clustering support. ircbot does not have any built-in persistent  
storage. It should work fine with acid-state, SQL, etc. When acid- 
state gets multimaster replication support, it would be nice if there  
was an automatic failover system. Basically, you could have two or  
more bots in the channel using acid-state replication. Queries would  
normally be answered by the primary bot, but if the primary bot goes  
offline, the secondary bot could answer the queries instead.

8. windows support - the channel logging feature uses the unix  
package, which is not supported on Windows. The rest of the code is  
already portable.

Anyway. Enjoy!

- Jeremy

Gmane