# 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 M8
```

### Say

Echoes bot output.

#### Example Usage

```
blissful | .say hi
presage  | hi
```

### Permissions

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").
```
