Skip to content

Plugin Authoring (2.3.4 and below)

endofline edited this page Aug 9, 2015 · 3 revisions

Patterns

Pattern: /bot command

def simple_command(bot, event, *args):
    print("something happened!")

This pattern simply implements a new /bot command that can be called with /bot simple_command

Pattern: /bot command and custom handler

import asyncio

def _initialise(Handlers, bot=None):
    """
    first, you can setup stuff, initialise variables and whatever else!
    """
    Handlers.register_handler(_custom_handler)
    Handlers.register_user_command(["custom_command"]) 
    # above command is available to all users
    # Handlers.register_admin_command() if command(s) only available to admins
    return [] # always a blank list


@asyncio.coroutine
def _custom_handler(bot, event, command):
    if "somethinghappened" in event.text
        yield from command.run(bot, event, *["custom_command"])


def custom_command(bot, event, *args):
    print("something happened!")

In the above pattern, custom_command will be available as a /bot command: /bot custom_command. It will also be executed every time somebody says "somethinghappened" in the chat.

Plugin filename

  • If the bot's plugin key in config.json is null, it will attempt to load all valid plugins inside the plugins/ directory.
  • A valid plugin should have a file name with the following specifications:
    • must end with extension .py
    • does NOT start with an underscore (_)
    • does NOT start with a dot (.)
    • file name (excluding extension) must only contain standard ASCII alphabets, numbers, and underscores (_)

Defining custom commands

  • Just a standard Python function with parameters (bot, event, *args)
  • Simply defining a function custom_command will implement new command /bot custom_command regardless of anything else in the plugin file.
  • Can be directly called from events and custom triggers using syntax: yield from command.run(bot, event, *["custom_command"])
  • If more than one plugin defines the same command, the publicly available /bot <command> will be overwritten based on the order of plugins initialisation. This is not recommended, as it may confuse other developers - try and make your custom commands unique.
  • Function names starting with an underscore will not be added as a /bot command - this is by design, and allows "hidden" internal-only functions inside the plugin.

Plugin initialisation (optional)

  • _initialise / _initialize is called automatically when the plugin is loaded
  • developers can use this specialised function to register commands and handlers
  • when defined, this function should return something
    • legacy plugins return a list of <command>s that will be available as /bot <command> e.g. return ["command_a", "command_b", "command_c"] (NOT RECOMMENDED FOR NEW PLUGINS)
    • newer plugins which use the preferred method of registering commands (register_user_command and register_admin_command) should always return []
    • returning None (or not return-ing at all) will make all defined functions available as a /bot command to all users EXCEPT:
      • the reserved function names: _initialise and _initialize; and
      • function names beginning with an underscore.

Registering user and admin-only commands

  • Handlers.register_user_command([LIST of command names]) publishes commands that can be accessed by all users e.g. Handlers.register_user_command(["public_command_a", "public_command_b"])
  • Use Handlers.register_admin_command([LIST of command names]) to add commands that can be only be used by bot admins e.g. Handlers.register_user_command(["dangerous_command_x", "dangerous_command_y"])
  • You do not need to register the same command with both functions - if you do so, the duplicated command will only be available to bot admins.
  • When using any of these two functions, ensure that your _initialise function returns a blank list with return []
    • older plugins used to return a list of commands that can be accessed by all users - this is no longer necessary but supported for backward-compatibility.

Registering custom handlers

  • register_handler(function, type="message") called during plugin initialisation to register custom handlers for specific bot events:
    • message - fires on message received
      • default handler if type not specified
      • handler prototype: def on_receive(bot, event, command)
      • decorate with @asyncio.coroutine
    • rename - fires on chat rename event
      • handler prototype: def on_rename(bot, event, command)
      • decorate with @asyncio.coroutine
    • membership - fires when users join or leave the chat
      • handler prototype: def on_membership(bot, event, command)
      • decorate with @asyncio.coroutine
    • sending - low-level modification of bot messages
      • handler prototype: def on_send(bot, broadcast_list, context)
      • standard function i.e. not decorated with @asyncio.coroutine
      • broadcast_list is a tuple consisting of (conversation_id, chat_segments)
  • Call register_handler last just before return-ing so that any exceptions in preceding code will ensure a handler won't be erroneously registered
  • _custom_handler (or whatever function name you desire) is only required when implementing something that does not use the syntax /bot <command> e.g. responding to a specific keyword, or custom trigger /xyz, etc.
  • To implement custom triggers e.g. /abc, /xyz <command> <parameters>, etc with custom handlers, you must manually parse and split event.text then yield.from appropriately to your desired function (as demonstrated in the "somethinghappened" implementation in the pattern above). Helpful Python(3) references: split, startswith
    • Pass extra arguments in the yield.from syntax with the following: yield from command.run(bot, event, *["custom_command", arg1, arg2, arg3, ... ])

Sharing plugin functionality

Available bot Functions

Please see: available bot functions

Debugging

  • Only basic exception information output to console. The information amounts to a single line starting with "EXCEPTION", with some basic information on the exception - either a line number or the name of the exception.
  • To get the full stack trace for the exception, you need to [see the bot log] (https://github.com/nylonee/hangupsbot#developers-debugging)

# ## ###

Clone this wiki locally