Included hooks

Access

Path: immp.hook.access.ChannelAccessHook

Channel join control, extended by other hooks.

Config:
hooks ((str, str list) dict):
Mapping of controlling hooks to a list of channels they manage.
exclude ((str, str list) dict):
Mapping of plugs to user IDs who should be ignored during checks.
joins (bool):
True to check each join as it happens.
startup (bool):
True to run a full check of all named channels on load.
passive (bool):
True to log violations without actually following through with removals.

This hook implements its own protocol for test purposes, by rejecting all joins and members of a channel. To make full use of it, other hooks with support for channel access can determine if a user satisfies membership of an external group or application.

Alerts

Path: immp.hook.alerts.MentionsHook (mentions), immp.hook.alerts.SubscriptionsHook (highlights)

Fallback mention and word highlight support for plugs via private channels.

Mentions

Config:
plugs (str list):
List of plug names to enable mention alerts for.
usernames (bool):
Whether to match network usernames (True by default).
real-names (bool):
Whether to match user’s display names (False by default).
ambiguous (bool):
Whether to notify multiple potential users of an ambiguous mention (False by default).

For networks that don’t provide native user mentions, this plug can send users a private message when mentioned by their username or real name.

A mention is matched from each @ sign until whitespace is encountered. For real names, spaces and special characters are ignored, so that e.g. @fredbloggs will match Fred Bloggs.

Partial mentions are supported, failing any exact matches, by basic prefix search on real names. For example, @fred will match Frederick, and @fredb will match Fred Bloggs.

Subscriptions

Config:
plugs (str list):
List of plug names to enable subscription alerts for.
Commands:
sub-add <text>:
Add a subscription to your trigger list.
sub-remove <text>:
Remove a subscription from your trigger list.
sub-exclude <text>:
Don’t trigger a specific subscription in the current public channel.
sub-list:
Show all active subscriptions.

Allows users to opt in to private message notifications when chosen highlight words are used in a group conversation.

Note

This hook requires an active DatabaseHook to store data.

Auto-responder

Path: immp.hook.autorespond.AutoRespondHook

Basic text request/response handler.

Config:
channels (str list):
List of channels to process responses in.
responses ((str, str) dict):
Mapping from match regex to response text.
Commands:
ar-add <match> <response>:
Add a new trigger / response pair.
ar-remove <match>:
Remove an existing trigger.

This hook will listen for messages in all given channels, for text content that matches any of the defined regular expressions. On a match, it will answer with the corresponding response. You can include capture groups in the expression, which are available using positional formatting syntax ({0} for a specific group, or {} for each one in turn).

Because all responses are defined in the config, you’ll need to ensure it’s saved when making changes via the add/remove commands.

Commands

Path: immp.hook.command.CommandHook

Backbone for other hooks to process commands contained in channel messages.

Config:
prefix (str):
Characters at the start of a message to denote commands. Use a single character to make commands top-level (e.g. "?" would allow commands like ?help), or a string followed by a space for subcommands (e.g. "!bot " for !bot help).
return-errors (bool):
True to send unhandled exceptions raised by commands back to the source channel (False by default).
sets ((str, str list) dict):
Subsets of hook commands by name, to restrict certain features.
mapping (str, dict) dict):

Named config groups to enable commands in selected channels.

groups (str list):
List of groups (plugs and channels) to process public commands in.
hooks (str list):
List of hooks to enable commands for.
sets (str list):
List of command sets to enable.
admins ((str, str list) dict):
Users authorised to execute administrative commands, a mapping of network identifiers to lists of user identifiers.

The binding works by making commands exposed by all listed hooks available to all listed channels, and to the private channels of all listed plugs. Note that the channels need not belong to any hook-specific config – you can, for example, bind some commands to an admin-only channel elsewhere. Multiple groups can be used for fine-grained control.

Database

Path: immp.hook.database.DatabaseHook

Provider of database access to other hooks.

Config:
url (str):
Database connection string, as defined by Peewee’s Database URL.

This hook provides persistent storage via a database. Any database types supported by Peewee can be used, though the usual caveats apply: if a hook requires fields specific to a single database type, the app is effectively locked-in to that type.

Hooks should subclass BaseModel for their data structures. At startup, they can obtain the database connection via host.resources[DatabaseHook].db, and use it to create their database tables via peewee.Database.create_tables().

Note

This hook requires the Peewee Python module, along with any database-specific libraries (e.g. Psycopg2 for PostgreSQL).

Discord roles

Path: immp.hook.discordrole.DiscordRoleHook

Self-serve Discord roles for users.

Config:
roles ((str, int) dict):
Mapping from user-facing role names to Discord role IDs.
Commands:
role <name>:
Claim a role of this name.
unrole <name>:
Drop the role of this name.

Hangouts locks

Path: immp.hook.hangoutslock.HangoutsLockHook

History and link-join setting locks for Hangouts.

Config:
history ((str, bool) dict):
Mapping from channel names to desired conversation history settings – True to keep history enabled, False to keep it disabled.
linkjoin ((str, bool) dict):
Mapping from channel names to desired link join settings – True to enable joining the hangout via link, False to disable it.

Identity lookup

Path: immp.hook.identity.WhoIsHook

Identity protocol backbone, and a generic user lookup command.

Config:
identities (str list):
List of identity provider names from which to allow lookups.
public (bool):
True to allow anyone with access to the who command to do a lookup, without necessarily being identified themselves (defaults to False).
Commands:
who <name>:
Recall a known identity and all of its links.

This module defines a subclass for all hooks providing identity services – no hook is needed from here if using an identity hook elsewhere. The WhoIsHook provides a command for users to query basic identity information.

Local identity

Path: immp.hook.identitylocal.LocalIdentityHook

Basic identity management for users in different networks.

Config:
instance (int):
Unique instance code.
plugs (str list):
List of plug names to accept identities for.
multiple (bool):
True (default) to allow linking multiple accounts from the same network.
Commands:
id-add <name> <pwd>:
Create a new identity, or link to an existing one from a second user.
id-rename <name>:
Rename the current identity.
id-password <pwd>:
Update the password for the current identity.
id-reset:
Delete the current identity and all linked users.
id-role <name> [role]:
List roles assigned to an identity, or add/remove a given role.

This is a local implementation of the identity protocol, providing self-serve identity linking to users where a user management backend doesn’t otherwise exist.

In order to support multiple copies of this hook with overlapping plugs (e.g. including a private network in some groups), each hook has an instance code. If a code isn’t defined in the config, a new one will be assigned at startup. If multiple hooks are in use, it’s important to define these yourself, so that identities remained assigned to the correct instance.

Note

This hook requires an active DatabaseHook to store data.

Notes

Path: immp.hook.notes.NotesHook

Recallable per-channel lists of text items.

Commands:
note-add <text>:
Add a new note for this channel.
note-edit <num> <text>:
Update an existing note from this channel with new text.
note-remove <num>:
Delete an existing note from this channel by its position.
note-show <num>:
Recall a single note in this channel.
note-list:
Recall all notes for this channel.

Note

This hook requires an active DatabaseHook to store data.

Shell

Path: immp.hook.shell.ShellHook (synchronous), immp.hook.shell.AsyncShellHook (asynchronous)

Interact with and debug a running app in the console.

Synchronous

Config:
all (bool):
True to process any message, False (default) to restrict to defined channels.
console (str):
Use a different embedded console. By default, code.interact() is used, but set this to ptpython (requires the ptpython Python module) for a more functional shell.

When a new message is received, a console will launch in the terminal where your app is running. The variables channel and msg are defined in the local scope, whilst self refers to the shell hook itself.

Warning

The console will block all other running tasks; notably, all plugs will be unable to make any progress whilst the console is open.

Asynchronous

Config:
port (int):
Port to bind the console on. Once running, one can connect using e.g. netcat. See aioconsole’s docs for more info.
buffer (int):
Number of received messages to keep cached for later inspection. If unset (default), no buffer will be available. Otherwise, when a new message comes in and the queue is full, the oldest message will be discarded. Set to 0 for an unlimited buffer, not recommended on production deployments.

At startup, a console will be launched on the given port. You can connect to it from a separate terminal, for example:

$ rlwrap nc localhost $PORT

Use of rlwrap provides you with readline-style keybinds, such as ↑ and ↓ to navigate through previous commands. The variables shell and host are defined, refering to the shell hook and the running Host respectively. This hook also maintains a cache of messages as they’re received, accessible via AsyncShellHook.buffer.

Note

This hook requires the aioconsole Python module.

Warning

The console will be accessible on a locally bound port without authentication. Do not use on shared or untrusted systems, as the host and all connected plugs are exposed.

Sync

Path: immp.hook.sync.SyncHook

Bridge multiple channels into a single unified conversation, or relay messages from one channel to one or more others.

Sync

Config:
channels ((str, str list) dict):
Mapping from virtual channel names to lists of channel names to bridge.
plug (str):
Name of a virtual plug to register for this sync.
joins (bool):
Whether to sync join and part messages across the bridge.
renames (bool):
Whether to sync channel title changes across the bridge.
identities (str):

Name of a registered IdentityProvider to provide unified names across networks.

If enabled, this will rewrite mentions for users identified in both the source and any sync target channels, to use their platform-native identity.

reset-author (bool):
True to create and attach a new user with just a name, False (default) to clone and modify the existing user (thus keeping username, avatar etc.).
name-format (str):

Template to use for replacing real names on synced messages, parsed by jinja2. If not set but the user is identified, it defaults to <real name> (<identity name>).

Context variables:
user (.User):
Message author, may be None for system messages or when reset-author is set.
identity (.IdentityGroup):
Connected identity, or None if no link or identities isn’t set.
title (str):
Channel title.
strip-name-emoji (bool):
True to remove emoji characters from message authors’ real names.
Commands:
sync-members:
List all members of the current conversation, across all channels.
sync-list:
List all channels connected to this conversation.

When a message is received from any of the listed channels, a copy is pushed to all other channels participating in the bridge.

If plug is specified, a virtual plug is registered under that name, with a channel for each defined bridge. Other hooks may reference these channels, to work with all channels in that sync as one. This allows them to listen to a unified stream of messages, or push new messages to all synced channels.

Forward

Config:
channels ((str, str list) dict):
Mapping from source channel names to lists of channel names to forward to.
users (str list):
Whitelist of user IDs to accept source messages from. If set, messages from anyone else in the source channel will be ignored.
joins (bool):
Whether to forward join and part messages.
renames (bool):
Whether to forward channel title changes.
identities (str):

Name of a registered IdentityProvider to provide unified names across networks.

If enabled, this will rewrite mentions for users identified in both the source and any sync target channels, to use their platform-native identity.

reset-author (bool):
True to create and attach a new user with just a name, False (default) to clone and modify the existing user (thus keeping username, avatar etc.).
name-format (str):

Template to use for replacing real names on synced messages, parsed by jinja2. If not set but the user is identified, it defaults to <real name> (<identity name>).

Context variables:
user (.User):
Message author, may be None for system messages or when reset-author is set.
identity (.IdentityGroup):
Connected identity, or None if no link or identities isn’t set.
title (str):
Channel title.
strip-name-emoji (bool):
True to remove emoji characters from message authors’ real names.

When a message is received in a configured source channel, a copy is pushed to all downstream channels. Unlike a sync, this is a one-direction copy, useful for announcements or alerts.

Note

Use of name-format requires the Jinja2 Python module. Use of strip-name-emoji requires the emoji Python module.

Text commands

Path: immp.hook.textcommand.TextCommandHook

Simple custom commands to send preconfigured text messages to channels.

Config:
commands ((str, str) dict):
Mapping from command name to rich response text.

Web

Path: immp.hook.web.WebHook

Run a webserver for other plugs or hooks to accept incoming HTTP requests.

Config:
host (str):
Hostname or IP address to bind to.
port (int):
Port number to bind to.

As the server is unauthenticated, you will typically want to bind it to localhost, and proxy it behind a full webserver like nginx to separate out routes, lock down access and so on.

Note

For templating via Jinja2, both jinja2 and aiohttp_jinja2 must be installed.

Web UI

Path: immp.hook.webui.WebUIHook

Web-based management UI for a host instance.

Config:
route (str):
Path to expose the UI pages under.

This is a simple control panel to add or update plugs and hooks in a running system.

Warning

The UI provides no authentication, and exposes all internals of the system (including any secret keys, as well as remote code execution via loading new plugs/hooks). You should only run this hook on a trusted system, and bind it to localhost to avoid external access.

If remotely accessible configuration is desired, use SSH with port forwarding to securely connect to your server. Failing that, you could proxy via a webserver like nginx and enable HTTP authentication, or use a service layer like oauth2_proxy.

When-Do

Note

Not yet released.

Path: immp.hook.whendo.WhenDoHook

Configurable when-this-do-these task runner.

Config:
tasks (task list):
Triggers and actions to perform.

Each task should have the following structure (example in YAML):

when:
    type: join-message
    channels: [test-channel]
do:
  - type: message
    channels: [admin-channel]
    text: "{{ user.real_name }} joined the test channel."
Triggers (when):
raw-message:

Any new message received.

Provides:
msg (Message):
Raw message object.
text-message:

Any new message containing plain text, excluding joins and parts.

Provides:
sender (User):
User who sent the message.
text (str):
Message text.
msg (Message):
Raw message object.
join-message:

A user has joined the channel. In the case of multiple joins, this trigger is called for each joining user.

Provides:
sender (User):
User who requested the join. For self-joins, this will be the same as user.
user (User):
User who joined the channel.
msg (Message):
Raw message object.
leave-message:

A user has left the channel. In the case of multiple leaves, this trigger is called for each leaving user.

Provides:
sender (User):
User who requested the leave. For self-leaves, this will be the same as user.
user (User):
User who left the channel.
msg (Message):
Raw message object.
rename-message:

The channel title has been changed.

Provides:
sender (User):
User who renamed the channel.
title (str):
New channel title.
msg (Message):
Raw message object.
Actions (do):
message:

Send a new message.

Args:
channels (str list):
Target channel names.
text (str):
Template message text, parsed using jinja2.
rename:

Update a channel’s title.

Args:
channels (str list):
Target channel names.
text (str):
Template replacement title, parsed using jinja2.