Plugin quick start guide

tjgillies edited this page Feb 17, 2012 · 5 revisions

Get started writing for lazybot

Lazybot is based on a plugin system, so you can write a plugin without having to touch any existing code. Here's how it works:

Fork off

If you are reading this page at're doing it wrong! See the Fork button in the upper right, right above the Wiki button you pushed? Go press it, and get your very own copy of lazybot. Then start reading your version of this guide.

Configuring lazybot

info.clj is just one big Clojure map that lazybot reads before it does anything else. There's a lot of stuff in there, most of which is completely uninteresting. The keys you're likely to want to change are:

  • prepends - any message starting with a character that's in this list will be treated as a command. If you're going to take your bot into any public channels (not recommended until you've done some solid testing, and turned off any plugins that would upset the channel), you should pick something that won't conflict with other bots. The default setting is @, which is as good as anything else; if you're used to using the "live" lazybot you can add in $ to avoid relearning anything.

  • eval-prefixes - like prepends, but for evaluating clojure code. The big hairy ones looking like #"..." are regular expressions - turn them off if you're going into a room with another lazybot, but otherwise they're designed not to get in anyone's way.

  • - lazybot will run on any IRC server you like, and will log into more than one at a time if you say so. Each string key in this map is a server for him to connect to, followed by another map of server-specific information. So change the key, or copy the whole key-value pair, if you want to use different servers.

  • channels, bot-name, bot-password, and users are all pretty self-explanatory. If one of them really baffles you, come see us in #lazybot. You should probably send him to some channel where he won't bother anyone if you make a mistake.

  • plugins - there's a copy of this key both in the global configuration settings, and in the per-server map. Most of the time, especially if you're running on only one server, these should be the same. At any rate, this is a list of strings naming all the plugins lazybot should load, and which ones should be turned on in each server.

Running lazybot

There are some good tips on "installing" lazybot in the README at the root of your repository; the executive summary is that you need to install and run MongoDB, copy the example.policy file to ~/.java.policy, and adjust .lazybot/info.clj (lazybot's main configuration file). Then, ./lazybot should get you going. But, definitely read the more detailed version in the README, especially if you have problems. If you've done all of the above, and lazybot joins a channel you specified, you can see if he's working by sending the message @kill (replacing @ with the prefix you configured earlier). This is a useful command for testing, because all it does is send the message "KILL IT WITH FIRE!" to the channel you're in. If that works, lazybot is probably in good shape; otherwise go back over these steps and see what you missed.

Writing a plugin

So, now that you've got lazybot running in a channel of your choice, how do you actually run some code? The answer is, create a .clj file in the lazybot.plugins.whatever namespace. Let's say you want to write a simple hello-world plugin: when you send @sayhi, you want lazybot to respond with : Hello! So your new source file should start like

(ns lazybot.plugins.hello
  (:use lazybot.registry))

lazybot.registry (the plugin registry) contains the functions that every plugin will need. Next you'll have to define a plugin, with the convenient defplugin macro: every plugin should include exactly one call to this macro. Because we're defining a command plugin, it should start like this:

    "Say hello!"
    ; actual code to be added later))

"Say hello!" is what will be displayed when someone asks for help with your command. It should provide a brief description of what it does and how to use it. Next up is #{"sayhi"}: this is a Clojure set of all the strings your command will respond to. For example, if you used #{"sayhi" "hello"} instead, your plugin function would be called after @hello messages as well as @sayhi messages.

The fun part

All that's left is the actual code: the last element of the :cmd structure is a function to be called from lazybot's internals. If you like, you can define that function before the defplugin section, and simply supply its name here; but most lazybot plugins provide their function inline. Of course, they're also more complicated, and have some helper functions higher up in the file - nobody's suggesting you write your whole program inside the defplugin!

This function will be called with a single argument, usually referred to as com-m, for "communication map". There is a wealth of information in this map about lazybot's current state, and you need it in order to do just about anything with lazybot. For the moment, however, all you care about is its :nick key, which maps to the name of the user running the command.

Now, you only need to know one more thing about lazybot in order to finish writing this function: there is a (send-message com-m msg-string) function that takes a com-m map and a string, and sends a message back over the same route the message was received from. At this point, you have enough pieces of the puzzle to finish writing this function yourself if you're familiar with Clojure and you've been paying attention. To that end, I won't write it here. If you get stuck, or would rather just see the code, it's here.

My code isn't running!

Remember info.clj and the list of plugins? You'll need to add "hello" to that list (both lists, really), because your plugin's namespace is lazybot.plugins.hello. That way lazybot knows to look in that file for a defplugin form.

Improve productivity by logging in

If you've done any plugin development beyond our little Hello World example, you're probably already tired of restarting lazybot every time you change some code. Well, you don't have to: just add your IRC nick to :users in info.clj, with a password and admin privileges. Then, you can @login to be recognized as an administrator; administrators can ask lazybot to reload all plugins with @reload, and have access to a bunch of other useful commands, like @log, @shell, and @debug. Most of these commands are still not as useful as they could be; instead of complaining, improve them and send a pull request!

Okay, I'm done. Now what?

Your brilliant new save-the-world plugin is finished and tested, and you want it included in the real-live lazybot. All you have to do is send a pull request from your repository on github. Include a description of what it does and why we should be interested; someone will look it over, try it out, and maybe pull from you. More likely, we'll discuss it with you for a while first:

  • You did something weird on line 37; what's that for?
  • Hey, could you make it do X too?
  • Do you mind if we change it to do Y a little differently?

But eventually, it will probably get pulled and included. Congratulations, you're now a contributor to lazybot!