IRC Bots, Redis bindings and Formlets
Published on September 27, 2010 under the tag haskell
It’s been a bit quiet on this blog – my last post dates from the 9th of August. But it’s still September, which means I still haven’t broken my goal of writing at least one blogpost every month.
The new academic term has now started at Ghent University, and I thought it’d be a good idea to write a bit on the side projects I’ve done after my Google Summer of Code project ended.
I’ve tried to abstract the gore IRC protocol away as much as possible. The result is that writing handlers (plugins responding to IRC messages) can now happen in an easy yet quite flexible way.
All handlers run in the
Irc monad, which gives them access to many useful
variables such as the IRC command used in the incoming message, the sender, the
text… Number Six will also run your handlers in separate thread, so a crashing
plugin will have no effect on the rest of the bot.
This is a sample plugin that will reconnect the bot when it’s kicked:
handler :: Handler String = makeHandler "kick" $ return $ onCommand "KICK" $ do handler : nick' : _) <- getParameters (channel <- getNick myNick == myNick) $ do when (nick' 3 sleep "JOIN" [channel] writeMessage
String – it simply specifies the string type
ByteString are supported). I’m using an irrefutable pattern
match, because I know that a crashing plugin won’t matter much.
Of course, the code contains a large number of utility functions to quickly create simpler handlers. Here is the code of a handler that does some basic base conversions.
Storing data in a database is also very simple. There is a Redis util module which will automagically generate keys that don’t clash between handlers and bots. Here is an example.
That leads us to the next subject. I’ve written a small wrapper around the Haskell Redis bindings which provide a somewhat simpler interface. It only supports a small subset of the bindings (coincidentally, this subset equals the subset of functions I needed).
<- connect localhost defaultPort redis "commander" ("Adama" :: String) itemSet redis Just commander <- itemGet redis "commander" putStrLn $ commander
My package can be found here. As you can see, I’ve made the bindings as simple as I could. However, if you need full redis functionality, I still recommend the original package.
A week or so ago, I read this discussion on the state of Haskell web frameworks.
So, I’ve ported formlets to blaze-html. The results should appear on Hackage when the maintainers find time to look over my patches. In the meanwhile, you can find my fork here.