Add command prefix configuration

This commit is contained in:
Ske 2020-08-25 19:32:19 +02:00
parent 87619a728e
commit 2206185d55
3 changed files with 38 additions and 17 deletions

View File

@ -2,7 +2,14 @@ namespace PluralKit.Bot
{
public class BotConfig
{
public static readonly string[] DefaultPrefixes = {"pk;", "pk!"};
public string Token { get; set; }
public ulong? ClientId { get; set; }
// ASP.NET configuration merges arrays with defaults, so we leave this field nullable
// and fall back to the separate default array at the use site :)
// This does bind [] as null (therefore default) instead of an empty array, but I can live w/ that.
public string[] Prefixes { get; set; }
}
}

View File

@ -23,11 +23,11 @@ namespace PluralKit.Bot
private readonly ProxyService _proxy;
private readonly ILifetimeScope _services;
private readonly IDatabase _db;
private readonly IDataStore _data;
private readonly BotConfig _config;
public MessageCreated(LastMessageCacheService lastMessageCache, LoggerCleanService loggerClean,
IMetrics metrics, ProxyService proxy, DiscordShardedClient client,
CommandTree tree, ILifetimeScope services, IDatabase db, IDataStore data)
CommandTree tree, ILifetimeScope services, IDatabase db, BotConfig config)
{
_lastMessageCache = lastMessageCache;
_loggerClean = loggerClean;
@ -37,7 +37,7 @@ namespace PluralKit.Bot
_tree = tree;
_services = services;
_db = db;
_data = data;
_config = config;
}
public DiscordChannel ErrorChannelFor(MessageCreateEventArgs evt) => evt.Channel;
@ -87,26 +87,19 @@ namespace PluralKit.Bot
var content = evt.Message.Content;
if (content == null) return false;
var argPos = -1;
// Check if message starts with the command prefix
if (content.StartsWith("pk;", StringComparison.InvariantCultureIgnoreCase)) argPos = 3;
else if (content.StartsWith("pk!", StringComparison.InvariantCultureIgnoreCase)) argPos = 3;
else if (DiscordUtils.HasMentionPrefix(content, ref argPos, out var id)) // Set argPos to the proper value
if (id != _client.CurrentUser.Id) // But undo it if it's someone else's ping
argPos = -1;
// Check for command prefix
if (!HasCommandPrefix(content, out var cmdStart))
return false;
// If we didn't find a prefix, give up handling commands
if (argPos == -1) return false;
// Trim leading whitespace from command without actually modifying the wring
// Trim leading whitespace from command without actually modifying the string
// This just moves the argPos pointer by however much whitespace is at the start of the post-argPos string
var trimStartLengthDiff = content.Substring(argPos).Length - content.Substring(argPos).TrimStart().Length;
argPos += trimStartLengthDiff;
var trimStartLengthDiff = content.Substring(cmdStart).Length - content.Substring(cmdStart).TrimStart().Length;
cmdStart += trimStartLengthDiff;
try
{
var system = ctx.SystemId != null ? await _db.Execute(c => c.QuerySystem(ctx.SystemId.Value)) : null;
await _tree.ExecuteCommand(new Context(_services, evt.Client, evt.Message, argPos, system, ctx));
await _tree.ExecuteCommand(new Context(_services, evt.Client, evt.Message, cmdStart, system, ctx));
}
catch (PKError)
{
@ -117,6 +110,26 @@ namespace PluralKit.Bot
return true;
}
private bool HasCommandPrefix(string message, out int argPos)
{
// First, try prefixes defined in the config
var prefixes = _config.Prefixes ?? BotConfig.DefaultPrefixes;
foreach (var prefix in prefixes)
{
if (!message.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase)) continue;
argPos = prefix.Length;
return true;
}
// Then, check mention prefix (must be the bot user, ofc)
argPos = -1;
if (DiscordUtils.HasMentionPrefix(message, ref argPos, out var id))
return id == _client.CurrentUser.Id;
return false;
}
private async ValueTask<bool> TryHandleProxy(MessageCreateEventArgs evt, MessageContext ctx)
{
try

View File

@ -17,6 +17,7 @@ The configuration file needs to be placed in the bot's working directory (usuall
The configuration file is in JSON format (albeit with a `.conf` extension). The following keys are available (using `.` to indicate a nested object level), bolded key names are required:
* **`PluralKit.Bot.Token`**: the Discord bot token to connect with
* **`PluralKit.Database`**: the URI of the database to connect to (in [ADO.NET Npgsql format](https://www.connectionstrings.com/npgsql/))
* `PluralKit.Bot.Prefixes`: an array of command prefixes to use (default `["pk;", "pk!"]`).
* `PluralKit.Bot.ClientId` *(optional)*: the ID of the bot's user account, used when generating invite links through `pk;invite`. It's automatically determined if not present, but overriding it may be useful for private instances that still want a public invite link.
* `PluralKit.SentryUrl` *(optional)*: the [Sentry](https://sentry.io/welcome/) client key/DSN to report runtime errors to. If absent, disables Sentry integration.
* `PluralKit.InfluxUrl` *(optional)*: the URL to an [InfluxDB](https://www.influxdata.com/products/influxdb-overview/) server to report aggregate statistics to. An example of these stats can be seen on [the public stats page](https://stats.pluralkit.me).