Ejemplo n.º 1
0
        /// <inheritdoc/>
        public override async ValueTask <TypeParserResult <IMember> > ParseAsync(Parameter parameter, string value, DiscordGuildCommandContext context)
        {
            if (!context.Bot.CacheProvider.TryGetMembers(context.GuildId, out var memberCache))
            {
                throw new InvalidOperationException($"The {GetType().Name} requires the member cache.");
            }

            IMember member;

            if (Snowflake.TryParse(value, out var id) || Mention.TryParseUser(value, out id))
            {
                // The value is a mention or an ID.
                // We look up the cache first.
                if (!memberCache.TryGetValue(id, out var cachedMember))
                {
                    // This means it's either an invalid ID or the member isn't cached.
                    // We don't know which one it is, so we have to query the guild.
                    await using (context.BeginYield())
                    {
                        // Check if the gateway is/will be rate-limited.
                        if (context.Bot.GetShard(context.GuildId).RateLimiter.GetRemainingRequests() < 3)
                        {
                            // Use a REST call instead.
                            member = await context.Bot.FetchMemberAsync(context.GuildId, id).ConfigureAwait(false);
                        }
                        else
                        {
                            // Otherwise use gateway member chunking.
                            var members = await context.Bot.Chunker.QueryAsync(context.GuildId, new[] { id }).ConfigureAwait(false);

                            member = members.GetValueOrDefault(id);
                        }
                    }
                }
                else
                {
                    // Have to assign the `out var cachedMember` like this.
                    member = cachedMember;
                }
            }
            else
            {
                // The value is possibly a tag, name, or nick.
                // So let's check for a '#', indicating a tag.
                string name;
                string discriminator;
                var    hashIndex = value.LastIndexOf('#');
                if (hashIndex != -1 && hashIndex + 5 == value.Length)
                {
                    // The value is a tag (Name#0000);
                    name          = value.Substring(0, value.Length - 5);
                    discriminator = value.Substring(hashIndex + 1);
                }
                else
                {
                    // The value is possibly a name or a nick.
                    name          = value;
                    discriminator = null;
                }
Ejemplo n.º 2
0
        /// <inheritdoc/>
        public override async ValueTask <TypeParserResult <IMember> > ParseAsync(Parameter parameter, string value, DiscordGuildCommandContext context)
        {
            IMember member;

            if (Snowflake.TryParse(value, out var id) || Mention.TryParseUser(value, out id))
            {
                // The value is a mention or an ID.
                // We look up the cache first.
                if (!context.Guild.Members.TryGetValue(id, out member))
                {
                    // This means it's either an invalid ID or the member isn't cached.
                    // We don't know which one it is, so we have to query the guild.
                    await using (context.BeginYield())
                    {
                        // Check if the gateway is/will be rate-limited.
                        if (context.Bot.GetShard(context.GuildId).RateLimiter.GetRemainingRequests() < 3)
                        {
                            // Use a REST call instead.
                            member = await context.Bot.FetchMemberAsync(context.GuildId, id).ConfigureAwait(false);
                        }
                        else
                        {
                            // Otherwise use gateway member chunking.
                            var members = await context.Bot.Chunker.QueryAsync(context.GuildId, new[] { id }).ConfigureAwait(false);

                            member = members.GetValueOrDefault(id);
                        }
                    }
                }
            }
            else
            {
                // The value is possibly a tag, name, or nick.
                // So let's check for a '#', indicating a tag.
                string name, discriminator;
                var    hashIndex = value.LastIndexOf('#');
                if (hashIndex != -1 && hashIndex + 5 == value.Length)
                {
                    // The value is a tag (Name#0000);
                    name          = value.Substring(0, value.Length - 5);
                    discriminator = value.Substring(hashIndex + 1);
                }
                else
                {
                    // The value is possibly a name or a nick.
                    name          = value;
                    discriminator = null;
                }

                // The predicate checks for the given tag or name/nick accordingly.
                Func <IMember, bool> predicate = discriminator != null
                    ? x => x.Name == name && x.Discriminator == discriminator
                    : x => x.Name == name || x.Nick == name;

                // We look up the cache first.
                member = context.Guild.Members.Values.FirstOrDefault(predicate);
                if (member == null)
                {
                    // This means it's either an invalid input or the member isn't cached.
                    await using (context.BeginYield())
                    {
                        // We don't know which one it is, so we have to query the guild.
                        // Check if the gateway is/will be rate-limited.
                        // TODO: swap these two around?
                        IEnumerable <IMember> members;
                        if (context.Bot.GetShard(context.GuildId).RateLimiter.GetRemainingRequests() < 3)
                        {
                            members = await context.Bot.SearchMembersAsync(context.GuildId, name);
                        }
                        else
                        {
                            members = (await context.Bot.Chunker.QueryAsync(context.GuildId, name).ConfigureAwait(false)).Values;
                        }

                        member = members.FirstOrDefault(predicate);
                    }
                }
            }

            if (member != null)
            {
                return(Success(member));
            }

            return(Failure("No member found matching the input."));
        }