using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using PluralKit.Core; namespace PluralKit.Bot { public static class ContextArgumentsExt { public static string PopArgument(this Context ctx) => ctx.Parameters.Pop(); public static string PeekArgument(this Context ctx) => ctx.Parameters.Peek(); public static string RemainderOrNull(this Context ctx, bool skipFlags = true) => ctx.Parameters.Remainder(skipFlags).Length == 0 ? null : ctx.Parameters.Remainder(skipFlags); public static bool HasNext(this Context ctx, bool skipFlags = true) => ctx.RemainderOrNull(skipFlags) != null; public static string FullCommand(this Context ctx) => ctx.Parameters.FullCommand; /// /// Checks if the next parameter is equal to one of the given keywords. Case-insensitive. /// public static bool Match(this Context ctx, ref string used, params string[] potentialMatches) { var arg = ctx.PeekArgument(); foreach (var match in potentialMatches) { if (arg.Equals(match, StringComparison.InvariantCultureIgnoreCase)) { used = ctx.PopArgument(); return true; } } return false; } /// /// Checks if the next parameter is equal to one of the given keywords. Case-insensitive. /// public static bool Match(this Context ctx, params string[] potentialMatches) { string used = null; // Unused and unreturned, we just yeet it return ctx.Match(ref used, potentialMatches); } public static bool MatchFlag(this Context ctx, params string[] potentialMatches) { // Flags are *ALWAYS PARSED LOWERCASE*. This means we skip out on a "ToLower" call here. // Can assume the caller array only contains lowercase *and* the set below only contains lowercase var flags = ctx.Parameters.Flags(); return potentialMatches.Any(potentialMatch => flags.Contains(potentialMatch)); } public static bool MatchClear(this Context ctx) => ctx.Match("clear", "reset") || ctx.MatchFlag("c", "clear"); public static async Task> ParseMemberList(this Context ctx, SystemId? restrictToSystem) { var members = new List(); // Loop through all the given arguments while (ctx.HasNext()) { // and attempt to match a member var member = await ctx.MatchMember(); if (member == null) // if we can't, big error. Every member name must be valid. throw new PKError(ctx.CreateMemberNotFoundError(ctx.PopArgument())); if (restrictToSystem != null && member.System != restrictToSystem) throw Errors.NotOwnMemberError; // TODO: name *which* member? members.Add(member); // Then add to the final output list } return members; } } }