DigitalPulseSoftware/NotaBot

[spec] One-word commands

Closed this issue · 1 comments

What

The goal is to have a way to bind single-word commands to text blocks.

As an example, the !ask s-w command would make the bot print the following
text block.

"To maximise your chances at getting an answer, you should..."

Why

On help-oriented servers and channels, there are a lot of cases where the
"helpers" may need to regularly repeat the same messages, e.g. "give some info".

On a more "general" case, this can be used as a rule reminder, info. block, etc.

How

P1: A simple key-based message posting

The basics

Existing NaB modules are triggered based on a word.

In this case, the module may have a lot of words, and the same behaviour on
each trigger.

To avoid loading a lot of redundant instances of the same module, we should
develop a module that'd be triggered on every message, and post the right
message if needed.

Message storing and loading

A message is associated to its trigger word, its "key".

The most primitive implementation of such a feature would be to have a folder,
each file being named after the key.

The simplest way to name the file would be to only put the key.
Making extensions optional could simplify integration, but slow
down the module for "not in cache" keys.

On trigger, the bot would then load the message found inside the file, before
posting it on Discord.

Simple optimizations to do to avoid high disk IO/latency would be:

  • On startup, make the bot scan the folder supposedly containing messages, and
    keep the list of found files in a "key" cache.
  • On file read (command trigger with an existing associated message), keep the
    message content in cache along the key.

The base naïve algorithm then becomes:

On incoming message
// Taking the first item, removing the trigger character
key := split(message, " ", 2)[0][1:]
if key in loaded_messages then
	send(channel, loaded_messages[key])
// startup analysis, and FS check
else if key in found_keys or exists(key)
	loaded_messages[key] = load(key)
	send(channel, loaded_messages[key])
else pass

P2: Let the users remove bot-posted messages

Allowing the users to remove the messages the bot posted after being triggered
may help with self-moderation, spam avoidance (letting the users react to
a trigger spammer), or just to let them clear the chat once the message
have been read.

This could be done by allowing the user react on the message by adding a given
emoji reaction, which would remove the bot message.

Still, a naïve implementation of this feature may make the bot remove other
messages it posted, that aren't in the scope of this module.

For that, either the message should contain a flag to recognize it without
any bot-side cache (e.g. starting the message with a known keyword),
or the bot should keep a list of every answer it posted (message ID).

To avoid growing memory consumption, expiration would be required on the time
users have to remove the message.

The cache could be either in the NaB code (with a garbage-collector running
to reap every expired message watch) or in some specialized cache servers, like
Redis, which natively supports expiration on keys.

This is implemented