public static ParseResult FromSuccess(IReadOnlyList <TypeReaderValue> argValues, IReadOnlyList <TypeReaderValue> paramValues) { var argList = new TypeReaderResult[argValues.Count]; for (int i = 0; i < argValues.Count; i++) { argList[i] = TypeReaderResult.FromSuccess(argValues[i]); } TypeReaderResult[] paramList = null; if (paramValues != null) { paramList = new TypeReaderResult[paramValues.Count]; for (int i = 0; i < paramValues.Count; i++) { paramList[i] = TypeReaderResult.FromSuccess(paramValues[i]); } } return(new ParseResult(argList, paramList, null, null)); }
public static async Task <ParseResult> ParseArgsAsync(CommandInfo command, ICommandContext context, bool ignoreExtraArgs, IServiceProvider services, string input, int startPos) { ParameterInfo curParam = null; StringBuilder argBuilder = new StringBuilder(input.Length); int endPos = input.Length; var curPart = ParserPart.None; int lastArgEndPos = int.MinValue; var argList = ImmutableArray.CreateBuilder <TypeReaderResult>(); var paramList = ImmutableArray.CreateBuilder <TypeReaderResult>(); bool isEscaping = false; char c; for (int curPos = startPos; curPos <= endPos; curPos++) { if (curPos < endPos) { c = input[curPos]; } else { c = '\0'; } //If this character is escaped, skip it if (isEscaping) { if (curPos != endPos) { argBuilder.Append(c); isEscaping = false; continue; } } //Are we escaping the next character? if (c == '\\' && (curParam == null || !curParam.IsRemainder)) { isEscaping = true; continue; } //If we're processing an remainder parameter, ignore all other logic if (curParam != null && curParam.IsRemainder && curPos != endPos) { argBuilder.Append(c); continue; } //If we're not currently processing one, are we starting the next argument yet? if (curPart == ParserPart.None) { if (char.IsWhiteSpace(c) || curPos == endPos) { continue; //Skip whitespace between arguments } else if (curPos == lastArgEndPos) { return(ParseResult.FromError(CommandError.ParseFailed, "Должен быть хотя бы 1 символ и параметры должны быть разделены пробелом!")); } else { if (curParam == null) { curParam = command.Parameters.Count > argList.Count ? command.Parameters[argList.Count] : null; } if (curParam != null && curParam.IsRemainder) { argBuilder.Append(c); continue; } if (c == '\"') { curPart = ParserPart.QuotedParameter; continue; } curPart = ParserPart.Parameter; } } //Has this parameter ended yet? string argString = null; if (curPart == ParserPart.Parameter) { if (curPos == endPos || char.IsWhiteSpace(c)) { argString = argBuilder.ToString(); lastArgEndPos = curPos; } else { argBuilder.Append(c); } } else if (curPart == ParserPart.QuotedParameter) { if (c == '\"') { argString = argBuilder.ToString(); //Remove quotes lastArgEndPos = curPos + 1; } else { argBuilder.Append(c); } } if (argString != null) { if (curParam == null) { if (ignoreExtraArgs) { break; } else { return(ParseResult.FromError(CommandError.BadArgCount, "Слишком много параметров.")); } } var typeReaderResult = await curParam.ParseAsync(context, argString, services).ConfigureAwait(false); if (!typeReaderResult.IsSuccess && typeReaderResult.Error != CommandError.MultipleMatches) { return(ParseResult.FromError(typeReaderResult)); } if (curParam.IsMultiple) { paramList.Add(typeReaderResult); curPart = ParserPart.None; } else { argList.Add(typeReaderResult); curParam = null; curPart = ParserPart.None; } argBuilder.Clear(); } } if (curParam != null && curParam.IsRemainder) { var typeReaderResult = await curParam.ParseAsync(context, argBuilder.ToString(), services).ConfigureAwait(false); if (!typeReaderResult.IsSuccess) { return(ParseResult.FromError(typeReaderResult)); } argList.Add(typeReaderResult); } if (isEscaping) { return(ParseResult.FromError(CommandError.ParseFailed, "Input text may not end on an incomplete escape.")); } if (curPart == ParserPart.QuotedParameter) { return(ParseResult.FromError(CommandError.ParseFailed, "Кавычки не закрыты")); } //Add missing optionals for (int i = argList.Count; i < command.Parameters.Count; i++) { var param = command.Parameters[i]; if (param.IsMultiple) { continue; } if (!param.IsOptional) { return(ParseResult.FromError(CommandError.BadArgCount, "Слишком мало параметров.")); } argList.Add(TypeReaderResult.FromSuccess(param.DefaultValue)); } return(ParseResult.FromSuccess(argList.ToImmutable(), paramList.ToImmutable())); }
public override async Task <TypeReaderResult> ReadAsync(ICommandContext context, string input, IServiceProvider services) { //var results = new Dictionary<string, TypeReaderValue>(); //IAsyncEnumerable<IUser> channelUsers = context.Channel.GetUsersAsync(CacheMode.CacheOnly).Flatten(); // it's better //IReadOnlyCollection<IGuildUser> guildUsers = ImmutableArray.Create<IGuildUser>(); //ulong id; //if (context.Guild != null) // guildUsers = await context.Guild.GetUsersAsync(CacheMode.CacheOnly).ConfigureAwait(false); //By Mention (1.0) //if (MentionUtils.TryParseUser(input, out id)) //{ // if (context.Guild != null) // AddResult(results, await context.Guild.GetUserAsync(id, CacheMode.CacheOnly).ConfigureAwait(false) as T, 1.00f); // else // AddResult(results, await context.Channel.GetUserAsync(id, CacheMode.CacheOnly).ConfigureAwait(false) as T, 1.00f); //} if (input[0] == '@') { var username = input.Substring(1, input.Length - 1); if (TwitchBot.BotEntry.RedstoneDust.ContainsKey(username.ToLower())) { return(TypeReaderResult.FromSuccess(TwitchBot.BotEntry.RedstoneDust[username.ToLower()].User)); } } if (TwitchBot.BotEntry.RedstoneDust.ContainsKey(input.ToLower())) { return(TypeReaderResult.FromSuccess(TwitchBot.BotEntry.RedstoneDust[input.ToLower()].User)); } //By Id (0.9) //if (ulong.TryParse(input, NumberStyles.None, CultureInfo.InvariantCulture, out id)) //{ // if (context.Guild != null) // AddResult(results, await context.Guild.GetUserAsync(id, CacheMode.CacheOnly).ConfigureAwait(false) as T, 0.90f); // else // AddResult(results, await context.Channel.GetUserAsync(id, CacheMode.CacheOnly).ConfigureAwait(false) as T, 0.90f); //} //By Username + Discriminator (0.7-0.85) //int index = input.LastIndexOf('#'); //if (index >= 0) //{ // string username = input.Substring(0, index); // if (ushort.TryParse(input.Substring(index + 1), out ushort discriminator)) // { // var channelUser = await channelUsers.FirstOrDefault(x => x.DiscriminatorValue == discriminator && // string.Equals(username, x.Username, StringComparison.OrdinalIgnoreCase)); // AddResult(results, channelUser as T, channelUser?.Username == username ? 0.85f : 0.75f); // var guildUser = guildUsers.FirstOrDefault(x => x.DiscriminatorValue == discriminator && // string.Equals(username, x.Username, StringComparison.OrdinalIgnoreCase)); // AddResult(results, guildUser as T, guildUser?.Username == username ? 0.80f : 0.70f); // } //} ////By Username (0.5-0.6) //{ // await channelUsers // .Where(x => string.Equals(input, x.Username, StringComparison.OrdinalIgnoreCase)) // .ForEachAsync(channelUser => AddResult(results, channelUser as T, channelUser.Username == input ? 0.65f : 0.55f)); // foreach (var guildUser in guildUsers.Where(x => string.Equals(input, x.Username, StringComparison.OrdinalIgnoreCase))) // AddResult(results, guildUser as T, guildUser.Username == input ? 0.60f : 0.50f); //} ////By Nickname (0.5-0.6) //{ // await channelUsers // .Where(x => string.Equals(input, (x as IGuildUser)?.Nickname, StringComparison.OrdinalIgnoreCase)) // .ForEachAsync(channelUser => AddResult(results, channelUser as T, (channelUser as IGuildUser).Nickname == input ? 0.65f : 0.55f)); // foreach (var guildUser in guildUsers.Where(x => string.Equals(input, (x as IGuildUser).Nickname, StringComparison.OrdinalIgnoreCase))) // AddResult(results, guildUser as T, (guildUser as IGuildUser).Nickname == input ? 0.60f : 0.50f); //} //if (results.Count > 0) // return TypeReaderResult.FromSuccess(results.Values.ToImmutableArray()); return(TypeReaderResult.FromError(CommandError.ObjectNotFound, "User not found.")); }