Presage
Okay, most of the shit written here is just empty speak so far. But in my opinion, writing this is fairly easy provided I have a clear plan. One weekend I'll sit down and shit something out! And a lot of this shit will move to documentation.
A cute little bot for IRC and Discord.
Features
- A nice assortment of command modules.
- Message relay among a cluster of channels.
- Decently configurable, but I'm not looking to create k8s-for-IRC.
- Detailed documentation for the source code and user interface.
- Thoroughly tested! Most shit works, at least on my machine~
- Highly concurrent!
- Well designed. This bot can be extended with new listeners and new modules cleanly.
Motivation
I want to write one cute little application with OTP. Elixir and OTP are pretty cool, wouldn't you say?
Design Overview
Actors
- Listeners: Listeners on a chat service. They receive and dispatch messages.
- Note: One chat protocol can have multiple listeners (e.g. multiple IRC servers).
- Module: A set of functions that act on chat commands.
- Cluster: A set of connected channels. Messages are relayed between channels.
- Aliaser: Stores aliases for commands and can unalias messages.
- Each cluster has an aliaser.
- Authorizer: Determines the permissions for a user.
- Each listener has an authorizer.
Data Interfaces
User:
id: A unique (per-listener) identifier.listener_id: A globally unique identifier for the listener this user belongs to.mention: A string to use when mentioning the user in a message.nickname: A human-readable method of mentioning the user.-
Uniquely identified by
(id, listener_id).
MessageInfo:
raw_message: The raw message received from the listener.unaliased_message: The unaliased version of the raw message.source_user: The user that sent the message.source_cluster: The cluster that this message came from.source_listener: The listener that this message came from.
Message Flow
- A message is received in a channel by a listener.
- The listener passes the message to the cluster of the channel.
- The cluster relays the received message to the other member channels.
- The cluster compiles the MessageInfo.
- The cluster passes the MessageInfo to all registered modules.
- The modules pattern match against the unaliased command.
- Each module potentially passes a response to the source cluster.
- The cluster forwards the response to all member channels.
Permissions
Modules can define guard commands with permissions.
The authorizer checks a user's active permissions.
The permissions module provides dynamic permission assignment.
Command Parsing
Modules leverage OptionParser to parse command arguments. This provides well-documented interfaces and detailed error messages with little extra work.
Configuration
TBD. Should just be standard elixir shit.
Modules
Alias
Note: Alias is not strictly one of the modules; it is more significant. However, to an end user, it appears like a module, so I include it here.
Modifies the command aliases.
Example Usage
blissful | .alias new yell "say --uppercase"
presage | ".yell" aliased to ".say --uppercase".
blissful | .yell u wot m8
presage | U WOT M8Say
Echoes bot output.
Example Usage
blissful | .say hi
presage | hiPermissions
Configures per-user permissions. Permissions can be granted globally or for a single cluster.
Example Usage
blissful | .permissions add blissful "alias/delete"
presage | Gave blissful the permission "alias/delete".
blissful | .alias delete yell
presage | Deleted the alias ".yell" (was ".say --uppercase").