Esempio n. 1
0
        public async Task <Embed> CreateMessageInfoEmbed(FullMessage msg)
        {
            var channel = await _cache.GetOrFetchChannel(_rest, msg.Message.Channel);

            var ctx = LookupContext.ByNonOwner;

            Message serverMsg = null;

            try
            {
                serverMsg = await _rest.GetMessage(msg.Message.Channel, msg.Message.Mid);
            }
            catch (ForbiddenException)
            {
                // no permission, couldn't fetch, oh well
            }

            // Need this whole dance to handle cases where:
            // - the user is deleted (userInfo == null)
            // - the bot's no longer in the server we're querying (channel == null)
            // - the member is no longer in the server we're querying (memberInfo == null)
            // TODO: optimize ordering here a bit with new cache impl; and figure what happens if bot leaves server -> channel still cached -> hits this bit and 401s?
            GuildMemberPartial memberInfo = null;
            User userInfo = null;

            if (channel != null)
            {
                GuildMember member = null;
                try
                {
                    member = await _rest.GetGuildMember(channel.GuildId !.Value, msg.Message.Sender);
                }
                catch (ForbiddenException)
                {
                    // no permission, couldn't fetch, oh well
                }

                if (member != null)
                {
                    // Don't do an extra request if we already have this info from the member lookup
                    userInfo = member.User;
                }
                memberInfo = member;
            }

            if (userInfo == null)
            {
                userInfo = await _cache.GetOrFetchUser(_rest, msg.Message.Sender);
            }

            // Calculate string displayed under "Sent by"
            string userStr;

            if (memberInfo != null && memberInfo.Nick != null)
            {
                userStr = $"**Username:** {userInfo.NameAndMention()}\n**Nickname:** {memberInfo.Nick}";
            }
            else if (userInfo != null)
            {
                userStr = userInfo.NameAndMention();
            }
            else
            {
                userStr = $"*(deleted user {msg.Message.Sender})*";
            }

            // Put it all together
            var eb = new EmbedBuilder()
                     .Author(new(msg.Member.NameFor(ctx), IconUrl: DiscordUtils.WorkaroundForUrlBug(msg.Member.AvatarFor(ctx))))
                     .Description(serverMsg?.Content?.NormalizeLineEndSpacing() ?? "*(message contents deleted or inaccessible)*")
                     .Image(new(serverMsg?.Attachments?.FirstOrDefault()?.Url))
                     .Field(new("System",
                                msg.System.Name != null ? $"{msg.System.Name} (`{msg.System.Hid}`)" : $"`{msg.System.Hid}`", true))
                     .Field(new("Member", $"{msg.Member.NameFor(ctx)} (`{msg.Member.Hid}`)", true))
                     .Field(new("Sent by", userStr, true))
                     .Timestamp(DiscordUtils.SnowflakeToInstant(msg.Message.Mid).ToDateTimeOffset().ToString("O"));

            var roles = memberInfo?.Roles?.ToList();

            if (roles != null && roles.Count > 0)
            {
                // TODO: what if role isn't in cache? figure out a fallback
                var rolesString = string.Join(", ", roles.Select(id => _cache.GetRole(id))
                                              .OrderByDescending(role => role.Position)
                                              .Select(role => role.Name));
                eb.Field(new($"Account roles ({roles.Count})", rolesString.Truncate(1024)));
            }

            return(eb.Build());
        }