-
Notifications
You must be signed in to change notification settings - Fork 51
Plugins
Writing plugins for CloudBot is simple! This page seeks to detail all you need to know to write your own plugins.
(We'd also love it if you helped give back to CloudBot! Send us your custom plugins for inclusion!)
from util import hook
@hook.command
def echo(inp):
msg = inp + inp
return msg<Luke> .echo dance
<MyNewCloudBot> (Luke) dancedance
This defines a command that replies with twice its input. It can be invoked by saying phrases in a channel the bot is in, notably ".echo", "MyNewCloudBot: echo", "MyNewCloudBot; echo", and "MyNewCloudBot, echo" (assuming the bot's nick is "MyNewCloudBot").
It is important to note that any output a command returns will be reply()ed back to the user who triggered the command.
CloudBot continually scans the plugins directory for new or changed .py files. When it finds one, it runs it and examines each function to see whether it is a plugin.
The decorators found in util/hook.py mark functions as plugins of various types.
There are four types of pluginsh: commands, regexes, events, and sieves.
Commands and regexes activate on normal lines of chat (PRIVMSGs).
Events activate on IRC commands (PRIVMSG, KICK, INVITE, ...).
Sieves can prevent commands, regexes, and events from running. Commands could be tagged as admin-only, and then a sieve would verify that the user invoking the command has the necessary privileges.
All plugins need to 'from util import hook' if they want to be callable.
There is also a secondary hook decorator: @hook.singlethread. It indicates that the function should run in its own thread. Note that, in that case, you can't use the existing database connection object.
(plugins are located in plugins/)
@hook.command
@hook.command(mycommand)
Commands run when the beginning of a normal chat line matches one of .command, botnick: command, botnick; command, or botnick, command, where command is the command name, and botnick is the bot's nick on the server.
Commands respond to abbreviated forms: a command named "dictionary" will be invoked on both ".dictionary" and ".dict". If an abbreviated command is ambiguous, the bot will return with a list of possibilities: given commands "dictionary" and "dice", attempting to run command ".di" will make the bot say "did you mean dictionary or dice?".
When @hook.command is used without arguments, the command name is set to the function name. When given an argument, it is used as the command name. This allows one function to respond to multiple commands:
The first argument, inp, will be the text that occurs after the command. (e.g., "bar" in ".foo bar"). You can split this with inp.split(" ").
from util import hook
@hook.command('hi')
@hook.command
def hello(inp):
return "Hey there!"Users can invoke this function with either ".hello" or ".hi".
If a plugin does not take arguments, or arguments are optional, add autohelp=False to avoid the automatic help message. ie:
@hook.command('hi', autohelp=False)@hook.regex
@hook.regex(myregex)
Takes an argument corresponding to the regex string (not the compiled regex), followed by optional flags. It will attempt to match the regex on all inputs (PRIVMSG, NICK changes, NOTICES, etc); if so, the hooked function will be called with the match object.
@hook.event
@hook.event(myevent)
Event hooks are called whenever a specific IRC command is issued. For example, to run some code whenever a user talks, you can use 'PRIVMSG' as the argument. Using '*' ad the argument will hook all IRC activity.
Some useful events to hook onto are:
- PRIVMSG - called when a user speaks
- KICK - called when a user is kicked
- NICK - called when a user changes nick
The first argument returned for 'PRIVMSG' be a two-element list of the form ["#channel", "text"]; I don't know what it's like for NICK or other 'commands'.
In addition to the standard argument, plugins can take other arguments; db is the database object; input corresponds to the triggering line of text, and bot is the bot itself.
If a hook should only work for admins, add adminonly=True to restrict it. ie:
@hook.command('hi', adminonly=True)These arguments are shared by functions of all hook types:
- nick -- string, the nickname of whoever sent the message.
- channel -- string, the channel the message was sent on. Equal to nick if it's a private message.
- msg -- string, the line that was sent.
- raw -- string, the raw full line that was sent.
- re -- the result of doing re.match(hook, msg).
- bot -- the running bot object.
- db -- the database connection object.
- input -- the triggering line of text
- say(msg): obvious (Luke! Want to dance?)
- me(action): makes the bot act something out (* MyNewCloudBot dances with Luke!)
- reply(msg): say("("input.nick + ") " + msg) ((Luke) That was fun!)
- msg(target, msg): sends msg to target (MyNewCloudBot => Luke: Psst, let's do it again!)
- (other irc commands, like mode, topic, etc)
In order to use these, you must pass them as a Nonetype argument to your command, like so:
from util import hook
@hook.command
def say_something(inp, say=None, me=None)
me("is going to say something")
say(inp)If you need help with anything on this page, head on over to #CloudBot!