Writing hooks#

A Hook class accepts messages from all configured channels, and processes them however it likes. A common scenario is to forward or sync messages from one channel to another.

The following methods are recognised:

The following events can be implemented to collect, replace, or drop messages:

Note that channel filtering is not provided out-of-the-box – each hook will receive messages from all connected channels. Most likely you’ll want to add a channels config entry which should take a list of channel names, and resolve them at initialisation.

Host interaction#

You can work with plugs, channels, groups, and other hooks by accessing them via the Host instance at Hook.host. Typically you should accept a list of objects in your config, then add config properties like Plug.Property to access them via an attribute.

Plug & channel identifiers#

When working with plugs and channels, only refer to them by name when reading from user-provided config (e.g. to initially retrieve them). These names are liable to change if the user edits their setup, so if you were to store information about a channel or plug then it would become decoupled.

Instead, use Plug.network_id to identify plugs, and Channel.source for channels, which should be based on constants from the underlying network (see Persistent identifiers).

Resource hooks#

In some cases, you may design a hook that acts as a single resource for other hooks, where only one such hook may be active, and other hooks retrieve it via the host. Rather than needing a setting to specify the hook name, as well as logic to ensure only one can be registered, you can subclass ResourceHook instead of Hook.

Resources can be accessed via Host.resources, keyed by the hook’s class rather than its name, but is defined and added to a host in the same way as a regular hook.