Add command prefix configuration
This commit is contained in:
		| @@ -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; } | ||||
|     } | ||||
| } | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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).  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user