Skip to content
John Maguire edited this page Feb 11, 2021 · 16 revisions

Writing plugins is designed to be simple and quick with Cardinal, while still providing a ton of power. To get started, simply create a sub-directory within plugins/, add an empty __init__.py file, and create a plugin.py file containing your plugin.

The plugin.py file must contain a module attribute entrypoint which points to your plugin's entrypoint: either a plugin class or a factory method that returns an instance of your plugin class.

The entrypoint may optionally accept two kwargs: cardinal and config. If cardinal is specified, the plugin will be passed the instance of CardinalBot - the main method of interacting with the bot. If config is specified, the plugin will receive its config loaded from disk (config.json in the plugin directory.)

Additionally, a close() function may optionally be defined on the returned object. If it is, it will be called whenever the plugin is unloaded (including during reloads) and can optionally be passed the instance of CardinalBot.

class HelloWorldPlugin(object):
    def __init__(self, cardinal, config):
        pass

    def close(self, cardinal):
        pass

entrypoint = HelloWorldPlugin

Adding commands to a plugin

Note: Cardinal responds to commands prefixed with .. There is currently no way to configure this.

Commands are just methods on the plugin object which Cardinal will route messages to when it detects a command has been invoked. They should accept four arguments: cardinal, user, channel, message

The first argument passed in will be the instance of CardinalBot.

The second is a carinal.bot.user_info named tuple. It contains (nick, user, hostname).

The third argument will be the default channel at which to respond (i.e. the channel name if the message was received in a channel, or the sender's name if it was received in PM).

Finally, the fourth argument will be the full message received.

An example of a function definition for a command is as follows:

def hello(self, cardinal, user, channel, msg):

To let Cardinal know that you want to respond to a given command, simply use the @command decorator. Additionally, you can use the @help decorator to specify a response that should be given to .help <command name> (this feature is provided by the built-in help plugin).

from cardinal.decorators import command, help

# ...

@command(['hello', 'hi'])
@help("Responds to the user with a greeting.")
@help("Syntax: .hello [user to greet]")

It's recommended that you provide two help lines: The first, a brief description of what the command does. Second, an example of the syntax.

You can use [] to denote optional arguments, <> to denote required arguments, and [var [var [..]]] to denote lists. These rules are not enforced though, so you're free to come up with your own notation.

Responding to regular expressions

You can use the @regex decorator on your command method to set an expression that will trigger it. For example, to respond to a message containing only "hello":

@regex(r'^hello$')

Putting it all together

from cardinal.decorators import command, help

class HelloWorldPlugin(object):
    @command(['hello', 'hi'])
    @help("Responds to the user with a greeting.")
    @help("Syntax: .hello [user to greet]")
    def hello(self, cardinal, user, channel, msg):
        nick, ident, vhost = user.group(1), user.group(2), user.group(3)
        cardinal.sendMsg(channel, "Hello %s!" % nick)

entrypoint = HelloWorldPlugin

Built-in functionality

cardinal.sendMsg() is one of a few built-in Cardinal methods.

Event-based Plugins

Cardinal also supports events as of version 2.0. Built-in are the core IRC events:

  • irc.raw - 2 arguments (command, message) -- Available since v2.2.0
  • irc.invite - 2 arguments (inviter, channel)
  • irc.privmsg - 3 arguments (sender, channel, message)
  • irc.notice - 3 arguments (sender, channel, message)
  • irc.nick - 2 arguments (changer, new nick)
  • irc.mode - 3 arguments(setter, channel, mode)
  • irc.join - 2 arguments (joiner, channel)
  • irc.part - 3 arguments (leaver, channel, message)
  • irc.kick - 4 arguments (kicker, channel, kicked nick, message)
  • irc.quit - 2 arguments (quitter, message)

You can read about how to register events and event callbacks here.