Skip to content
This repository was archived by the owner on Aug 31, 2021. It is now read-only.

Plugin Writing

Jason Fried edited this page Feb 21, 2014 · 7 revisions

There are two types of pyaib plugins, class based or just functions. They both use the same decorators but the class based plugins get a irc_context and config passed to their constructor.

Pyaib objects

Context Object

Every method called by pyaib will receive an irc context object. The context is a dictionary subclass (pyaib.util.data.Object)

The context contains information about the running bot and has methods for interacting with IRC. The following methods are present in the context object, they are all UPPERCASE. In the future these might move to a sub dictionary called 'cmd'

  • context.RAW(string) send raw strings to the irc server
  • context.NICK(string) Set the bot nickname
  • context.PRIVMSG(target, message) Send message to target via PRIVMSG. Messages longer than 510 characters will be split into multiple messages
  • context.JOIN(channels) Join a single channel or a sequence of channels. Will split long sequences of channels into multiple JOINs of a max of 510 characters long.
  • context.PART(channels, message=None) Leave a channel and provide an optional message. Channels can be a list remember context.JOIN('0') is the fastest way to leave all your channels.

The context has the following bits of information

  • context.botnick is the bot's current nickname
  • context.botsender is the bot's Sender Object
  • context.server is the current IRC Server Sender Object
  • context.config the global bot config

The following components are available via the context

  • context.channels (Good for checking membership in a channel) '#channel' in context.channels
  • context.events (Fire events or register new ones)
  • context.timers (Periodic events)
  • context.triggers (keyword triggers)
  • context.db (DB component access, if configured)

Config Object

The config object located at both context.config and passed to plugin_class constructors is a case insensitive pyaib.util.data.Object. It contains the contents of the bots config file.

Message Object

This is an IRC message. It contains the raw and parsed irc message that caused the event or trigger

  • msg.raw - RAW irc message
  • msg.kind - IRC Message Name of Numeric
  • msg.sender - Sender Object for the Message
  • msg.args - Message Arguments
  • msg.nick - If the Sender is a person this will be their nickname

Messages Types can have their own parsers, so the members of the message object depend on the message type. For directed messages like PRIVMSG, NOTICE, INVITE the also have these members

  • msg.target = Who the message was targeted at, the bot or a channel name
  • msg.message = The message body
  • msg.channel = Normalized Channel name (.lower()) if this message was directed to a channel
  • msg.raw_channel = raw channel name, could have mixed case
  • msg.channel_prefix = msg.PREFIX_OP / msg.PREFIX_HALFOP / msg.PREFIX_VOICE - if the message was sent by somebody with a channel mode

Also Directed Messages come with a nifty reply() method, so that messages directed to the bot are replied back to the sender, and messages directed at a channel are replied to the channel.

  • msg.reply(text) This wraps irc_c.PRIVMSG so wrapping of long lines is automatic

Custom Message Parsers.

Any plugin or Component can define a message parser that gets a copy of the message before it triggers any events or triggers. @msg_parser(kind, [kind]*, chain=False) from pyaib.plugins The Message object will pass a copy of the message to these methods followed by the irc_context object. When the message is of the same kind.

Normally parsers replace any existing parser, but you can set chain to True / 'after' or 'before'. This setting will chain the existing parser so that this new parser executes before or after.

Sender Object

Sender Object is a unicode subclass, so it can be used like a string. When sender is a person the sender object equals their nickname, if its a sever it equals the server address

The following properties exist on the Sender Object *sender.raw - A Raw copy of the sender info, nick!user@host or server.fqdn *sender.hostname - The hostname of the user or server

For servers these return None, but for people they return data *sender.nick - The nick *sender.user - The username with '~' stripped *sender.usermask - user@host for the user.

Plugin Hooks (Decorators)

from pyaib.plugins import observe, keyword, every, plugin_class There are various aliases for each of these.

@plugin_class

This decorator designates a class as a plugin and it will be initialized when the module is loaded. The decorator can take an optional string argument that tells pyaib to save the instance of the plugin in the irc_context object with the given name.

All plugin classes must have an init method that takes two arguments the first is the irc context the second is a config object.

The config object just contains the plugin config section from the bot global config.

@plugin_class.requires(name, [name]*)

This tells the bot to makes sure the named component is loaded before this plugin loads. If you want to wait for a plugin to load first use 'plugin.[name]'

This is useful for making sure the 'db' component is loaded before your plugin init is called.

If the required component or plugin never loads, neither will your plugin.

@observe(event, [event]*)

This decorator designates a method or function to be a handler for an 'event'. Multiple handlers can exist for a single event

Event handlers take 2 arguments: irc context object, Message Object

Common Events

These events receive Message Objects

  • IRC_MSG_[kind] The event fired for various message types after they are parsed
  • IRC_MSG - Fired for every Message type, after the more specific event.

Raw Events

  • IRC_RAW_SEND - gets fired every time a message is passed to the server, it gets a copy of the context and string sent
  • IRC_RAW_MSG - gets fired every time a line is received from the server, it gets a copy of the context and raw string received.

Misc Events

  • IRC_ONCONNECT - fired when the bot finishes registering and is fully connected to the irc server. Channel AutoJOIN triggers on this event. Only gets the irc_context
  • IRC_NICK_INUSE - fired when we get a Nick Conflict, we could ghost the nick on this event if we wanted. gets the irc_context and the nick we attempted to use.
  • IRC_NICK_CHANGE - fired when bot nick changes, gets: irc_context, oldnick, newnick

@keyword('word', ['word']*)

This decorator designates this method or function as a command word trigger handler. 'triggers.prefix' (default: '!') can be set in the config file as a single character that these words must be prefixed by so the bot knows to react to them.

You can also address the bot: 'botnick: word' would be the same as '!word'

Keyword Handlers take 5 arguments: irc context, Message Object, trigger word, args, keyword args)

The trigger word is useful if the same method listens to multiple words and you want to know which one.

args will be all positional arguments after the command word.

keyword args will be any arguments after the command word that prefixed with -- ex: '--help' or '--value=4'

If you don't like working with args or keywords you can always parse the message from the Message Object

keyword sub decorators

These are helper decorators that prevent lots of boiler plate code from having to be written

  • keyword.channel - Only trigger inside channels
  • keyword.channel('#channel1', '#channel2' ...) - Only trigger in specified channels
  • keyword.channel('instance_var_name', runtime=True) - Pull allowed channels from given varname from the plugin instance
  • keyword.private - Only trigger in private messages (Those not directed to the bot and not a channel)
  • keyword.private_or_channel('#channel1', '#channel2' ...) - Trigger both in private and in listed channels
  • keyword.private_or_channel('instance_var_name', runtime=True) - Same as above but pull channel list from a named instance var
  • keyword.helponly - print the doc string and return.
  • keyword.autohelp - print the doc string if either 'help' or '--help' is given as an argument to the trigger word
  • keyword.autohelp_noargs - Same as the above but also if no arguments are passed to the trigger word.
  • keyword.sub(word, [word]*) - Trigger this method when the first argument is one of the words given. Allows easy sub commands
  • keyword.nosub - Only trigger when no arguments are present
  • keyword.nosub(word, [word]*) - Only trigger when the first argument is not one of the given words

@every(seconds, optional name)

This method will be called every 'seconds' and will be passed two arguments: irc context, timer name.

More complex timers are supported, but required working directly with the timers api in the context object. Timers can be fired at an exact time in the future, repeats a set number of times, etc.

Clone this wiki locally