public bool IsListener(ulong guildId, ulong messageId, DiscordEmoji emoji) { var guild = redis.GetAsync <Guild>(RedisKeyNaming.Guild(guildId)).Result; return(guild.ReactionCategories != null && guild.ReactionCategories.Any(x => x.Id == messageId && x.ReactionRoles.Any(x => x.Emoji == emoji.ToString())) || guild.ReactionMessages != null && guild.ReactionMessages.Any(x => x.Id == messageId && x.ReactionRoles.Any(x => x.Emoji == emoji.ToString()))); }
public async Task ManageModerators(DiscordGuild guild, DiscordChannel channel, DiscordRole role, bool isAdd) { var guildData = await redis.InitGuild(guild.Id); var roleName = role.Name; var modRoleExists = guildData.ModeratorRoleIds.Contains(role.Id); if (isAdd) { if (modRoleExists) { await channel.SendMessageAsync($"Role `{roleName}` already exists in the configuration."); } else { guildData.ModeratorRoleIds.Add(role.Id); await channel.SendMessageAsync($"Added `{roleName}` role to the moderation team of this guild."); } } else { if (!modRoleExists) { await channel.SendMessageAsync($"Role `{roleName}` does not exists in the configuration."); } else { guildData.ModeratorRoleIds.Remove(role.Id); await channel.SendMessageAsync($"Removed `{roleName}` role from the moderation team of this guild."); } } await redis.ReplaceAsync <Guild>(RedisKeyNaming.Guild(guild.Id), guildData); }
public async Task AddReactionListener(ulong guildId, ulong messageId, DiscordEmoji emoji, DiscordRole role, ReactionType type) { var guild = await redis.GetAsync <Guild>(RedisKeyNaming.Guild(guildId)); if (type == ReactionType.Message) { guild.ReactionMessages ??= new List <ReactionMessage>(); if (guild.ReactionMessages.Any(x => x.Id != messageId)) { guild.ReactionMessages.Add(new ReactionMessage() { Id = messageId, ReactionRoles = new List <ReactionRole>() }); } guild.ReactionMessages.Single(x => x.Id == messageId).ReactionRoles.Add(new ReactionRole() { Emoji = emoji.ToString(), RoleId = role.Id }); await redis.ReplaceAsync <Guild>(RedisKeyNaming.Guild(guildId), guild); await Task.CompletedTask; } if (type == ReactionType.Category) { guild.ReactionCategories ??= new List <ReactionCategory>(); if (guild.ReactionCategories.Any(x => x.Id != messageId)) { guild.ReactionCategories.Add(new ReactionCategory() { Id = messageId, RoleId = ulong.MinValue, ReactionRoles = new List <ReactionRole>() }); } guild.ReactionMessages.Single(x => x.Id == messageId).ReactionRoles.Add(new ReactionRole() { Emoji = emoji.ToString(), RoleId = role.Id }); await redis.ReplaceAsync <Guild>(RedisKeyNaming.Guild(guildId), guild); await Task.CompletedTask; } }
public static async Task <Guild> InitGuild(this IRedisDatabase redis, ulong guildId) { var guild = await redis.GetAsync <Guild>(RedisKeyNaming.Guild(guildId)); if (guild != null) { return(guild); } guild = new Guild { Id = guildId, Prefix = ApplicationInformation.DefaultPrefix, ModeratorRoleIds = new List <ulong>(), AllowWarnModerators = false, AllowMuteModerators = false, Logs = new List <Log>(), Settings = new List <Setting>(), ReactionCategories = new List <ReactionCategory>(), ReactionMessages = new List <ReactionMessage>() }; await redis.AddAsync <Guild>(RedisKeyNaming.Guild(guildId), guild); if (string.IsNullOrWhiteSpace(guild.Prefix)) { guild.Prefix = ApplicationInformation.DefaultPrefix; } guild.ModeratorRoleIds ??= new List <ulong>(); if (guild.AllowWarnModerators != true && guild.AllowWarnModerators != false) { guild.AllowWarnModerators = false; } if (guild.AllowMuteModerators != true && guild.AllowMuteModerators != false) { guild.AllowMuteModerators = false; } guild.Logs ??= new List <Log>(); guild.Settings ??= new List <Setting>(); guild.ReactionCategories ??= new List <ReactionCategory>(); guild.ReactionMessages ??= new List <ReactionMessage>(); await redis.ReplaceAsync <Guild>(RedisKeyNaming.Guild(guildId), guild); return(guild); }
public async Task SetPrefix(CommandContext context, [Description("The new command prefix.")] string prefix) { var guild = await redis.GetAsync <Defcon.Data.Guilds.Guild>(RedisKeyNaming.Guild(context.Guild.Id)); var oldPrefix = guild.Prefix; guild.Prefix = prefix; await redis.ReplaceAsync <Defcon.Data.Guilds.Guild>(RedisKeyNaming.Guild(context.Guild.Id), guild); var embed = new Embed { Title = "Command prefix set", Description = $"Set the prefix on the guild from {Formatter.InlineCode(oldPrefix)} to {Formatter.InlineCode(prefix)}." }; this.logger.Information($"[Redis] Changed the prefix on the guild '{context.Guild.Name}' ({context.Guild.Id}) from '{oldPrefix}' to '{prefix}' by '{context.User.Mention}' ({context.User.Id})."); await context.SendEmbedMessageAsync(embed); }
public static async Task <bool> IsModerator(this IRedisDatabase redis, ulong guildId, DiscordMember member) { var guild = await redis.GetAsync <Guild>(RedisKeyNaming.Guild(guildId)); var isModerator = false; foreach (var role in member.Roles) { isModerator = guild.ModeratorRoleIds.Any(x => x == role.Id); if (isModerator) { break; } } return(isModerator); }
public async void ManageRole(DiscordMessage message, DiscordChannel channel, DiscordMember member, DiscordEmoji emoji) { var guild = await redis.GetAsync <Guild>(RedisKeyNaming.Guild(channel.GuildId)); var reactionCategory = guild.ReactionCategories?.FirstOrDefault(x => x.Id == message.Id); var reactionCategoryItem = reactionCategory?.ReactionRoles.Single(x => x.Emoji == emoji.ToString()); var reactionMessageItem = guild.ReactionMessages?.Single(x => x.Id == message.Id)?.ReactionRoles.Single(x => x.Emoji == emoji.ToString()); var roleId = ulong.MinValue; var categoryRoleId = ulong.MinValue; if (reactionCategoryItem != null) { categoryRoleId = reactionCategory.RoleId; roleId = reactionCategoryItem.RoleId; } if (reactionMessageItem != null) { roleId = reactionMessageItem.RoleId; } var role = channel.Guild.GetRole(roleId); var categoryRole = channel.Guild.GetRole(categoryRoleId); if (role != null) { if (member.Roles.Contains(role)) { this.logger.Information($"The role '{role.Name}' was revoked from '{member.GetUsertag()}' on the guild '{channel.Guild.Name}' ({channel.GuildId})."); await member.RevokeRoleAsync(role); await member.SendMessageAsync($"The role {Formatter.InlineCode(role.Name)} has been revoked from you on {Formatter.Bold(channel.Guild.Name)}."); } else { this.logger.Information($"The role '{role.Name}' was granted to '{member.GetUsertag()}' on the guild '{channel.Guild.Name}' ({channel.GuildId})."); await member.GrantRoleAsync(role); await member.SendMessageAsync($"The role {Formatter.InlineCode(role.Name)} has been granted to you on {Formatter.Bold(channel.Guild.Name)}."); } await message.DeleteReactionAsync(emoji, member); } }
private async Task ChannelDelete(BaseDiscordClient client, DiscordGuild guild, IList <Defcon.Data.Guilds.Log> logs, ChannelDeleteEventArgs channelDeleteEventArgs, Guild guildData, Embed embed) { if (logs.Any(x => x.ChannelId == channelDeleteEventArgs.Channel.Id)) { var deletedLogChannel = logs.First(x => x.ChannelId == channelDeleteEventArgs.Channel.Id); guildData.Logs.Remove(deletedLogChannel); await redis.ReplaceAsync(RedisKeyNaming.Guild(guild.Id), guildData); } if (!channelDeleteEventArgs.Channel.IsPrivate) { embed.Title = $"{DiscordEmoji.FromGuildEmote(client, EmojiLibrary.Erase)} {channelDeleteEventArgs.Channel.Type.ToString()} channel deleted"; embed.Description = new StringBuilder().AppendLine($"Name: {Formatter.InlineCode(channelDeleteEventArgs.Channel.Name)}") .AppendLine($"Identity: {Formatter.InlineCode(channelDeleteEventArgs.Channel.Id.ToString())}") .ToString(); embed.Color = DiscordColor.IndianRed; } }
private Task <int> PrefixResolverAsync(DiscordMessage msg) { if (msg.Channel.IsPrivate) { return(Task.FromResult(msg.GetStringPrefixLength(ApplicationInformation.DefaultPrefix))); } var guild = redis.GetAsync <Guild>(RedisKeyNaming.Guild(msg.Channel.GuildId)) .GetAwaiter() .GetResult(); var prefix = guild.Prefix; if (!string.IsNullOrWhiteSpace(prefix)) { return(Task.FromResult(msg.GetStringPrefixLength(prefix))); } guild.Prefix = ApplicationInformation.DefaultPrefix; redis.ReplaceAsync <Guild>(RedisKeyNaming.Guild(msg.Channel.GuildId), guild); return(Task.FromResult(msg.GetStringPrefixLength(ApplicationInformation.DefaultPrefix))); }
public async Task ViewPrefix(CommandContext context) { var guild = await redis.GetAsync <Defcon.Data.Guilds.Guild>(RedisKeyNaming.Guild(context.Guild.Id)); await context.RespondAsync($"The command prefix for this guild is {Formatter.InlineCode(guild.Prefix)}."); }
public async Task CreateInfraction(DiscordGuild guild, DiscordChannel channel, DiscordClient client, DiscordMember moderator, DiscordMember suspect, string reason, InfractionType infractionType) { var suspectLeft = guild.GetMemberAsync(suspect.Id).Result == null; var embed = new Embed(); var owners = client.CurrentApplication.Owners; var verb = infractionType.ToInfractionString().ToLowerInvariant(); var action = infractionType.ToActionString().ToLowerInvariant(); var isSuspectAdministrator = false; var isModerator = await redis.IsModerator(guild.Id, moderator); var isAdministrator = moderator.Roles.Any(role => role.Permissions.HasPermission(Permissions.Administrator)); if (!isModerator && isAdministrator) { isModerator = true; } if (isModerator) { if (!suspectLeft) { if (suspect.Roles.Any(role => role.Permissions.HasPermission(Permissions.Administrator))) { isSuspectAdministrator = true; } if (moderator == suspect) { await channel.SendMessageAsync($"You can not {verb} yourself!"); } else if (owners.Any(x => x.Id == suspect.Id)) { await channel.SendMessageAsync($"You can not {verb} {suspect.Username}!"); } else if (suspect.IsOwner) { await channel.SendMessageAsync($"You can not {verb} the owner!"); } else if (isSuspectAdministrator) { await channel.SendMessageAsync($"You can not {verb} a administrator!"); } else if (await redis.IsModerator(guild.Id, suspect)) { var guildData = await redis.GetAsync <Guild>(RedisKeyNaming.Guild(guild.Id)); switch (infractionType) { case InfractionType.Ban: case InfractionType.Kick: await channel.SendMessageAsync($"You can not {verb} a moderator!"); break; case InfractionType.Warning: { if (!guildData.AllowWarnModerators) { await channel.SendMessageAsync($"You can not {verb} a moderator! [Disabled]"); } break; } case InfractionType.Mute: { if (!guildData.AllowMuteModerators) { await channel.SendMessageAsync($"You can not {verb} a moderator! [Disabled]"); } break; } } } else { var userData = await redis.InitUser(suspect.Id); userData.Infractions.Add(new Infraction() { Id = ++userData.InfractionId, ModeratorId = moderator.Id, ModeratorUsername = moderator.GetUsertag(), GuildId = guild.Id, InfractionType = infractionType, Reason = reason, Date = DateTimeOffset.UtcNow }); await redis.ReplaceAsync <User>(RedisKeyNaming.User(suspect.Id), userData); var description = new StringBuilder().AppendLine($"Moderator: {moderator.GetUsertag()} {Formatter.InlineCode($"{moderator.Id}")}") .AppendLine($"Reason: {reason}"); description.AppendLine("User left the server already!"); embed = new Embed() { Title = $"{suspect.Username} has been {action}!", Description = description.ToString(), Footer = new EmbedFooter() { Text = $"Infractions: {userData.Infractions.Count}" } }; await channel.SendEmbedMessageAsync(embed); embed.Title = $"You have been {action} on {guild.Name}"; await suspect.SendEmbedMessageAsync(embed); switch (infractionType) { case InfractionType.Kick: await suspect.RemoveAsync(reason); break; case InfractionType.Ban: await guild.BanMemberAsync(suspect.Id, 7, reason); break; } } } else { var suspectedUser = await client.GetUserAsync(suspect.Id); var userData = await redis.InitUser(suspectedUser.Id); userData.Infractions.Add(new Infraction() { Id = ++userData.InfractionId, ModeratorId = moderator.Id, ModeratorUsername = moderator.GetUsertag(), GuildId = guild.Id, InfractionType = infractionType, Reason = reason, Date = DateTimeOffset.UtcNow }); await redis.ReplaceAsync <User>(RedisKeyNaming.User(suspectedUser.Id), userData); var description = new StringBuilder().AppendLine($"Moderator: {moderator.GetUsertag()} {Formatter.InlineCode($"{moderator.Id}")}") .AppendLine($"Reason: {reason}") .AppendLine("User left the server already!"); embed = new Embed() { Title = $"{suspect.Username} has been {action}!", Description = description.ToString(), Footer = new EmbedFooter() { Text = $"Infractions: {userData.Infractions.Count}" } }; await channel.SendEmbedMessageAsync(embed); switch (infractionType) { case InfractionType.Kick: await channel.SendMessageAsync("Suspect already left"); break; case InfractionType.Ban: await guild.BanMemberAsync(suspectedUser.Id); break; } } } else { await channel.SendMessageAsync("You are not a moderator of this server."); } }
public async Task LogInit(CommandContext context, string status, LogType logType) { var guild = context.Guild; var channel = context.Channel; var logLabel = await SetLogTypeGetLogLabel(logType); var guildData = await redis.GetAsync <Guild>(RedisKeyNaming.Guild(guild.Id)); var log = guildData.Logs.FirstOrDefault(x => x.LogType == logType); var passInformation = true; DiscordChannel loggedChannel = null; DiscordMessage respond = null; if (log != null) { loggedChannel = guild.GetChannel(log.ChannelId); } if (string.IsNullOrWhiteSpace(status)) { if (loggedChannel != null) { respond = await context.RespondAsync($"The {logLabel} log has been set to {loggedChannel.Mention}"); } else { respond = await context.RespondAsync($"The {logLabel} log has not been set to any channel."); } } else { if (status.ToLower().Equals("enable")) { if (loggedChannel != null) { if (loggedChannel.Id == channel.Id) { respond = await context.RespondAsync($"The {logLabel} log is already set to this channel."); } else { respond = await context.RespondAsync($"The {logLabel} log is already set to {loggedChannel.Mention}."); } } else { guildData.Logs.Add(new Defcon.Data.Guilds.Log { ChannelId = channel.Id, LogType = logType }); await redis.AddAsync(RedisKeyNaming.Guild(guild.Id), guildData); } respond = await context.RespondAsync($"The {logLabel} log has been set to this channel."); } else if (status.ToLower().Equals("disable")) { if (log != null) { guildData.Logs.Remove(log); await redis.ReplaceAsync(RedisKeyNaming.Guild(guild.Id), guildData); respond = await context.RespondAsync($"The {logLabel} log has been disabled."); } else { respond = await context.RespondAsync("You can't disable something which is not even activated."); } } } if (respond != null) { await Task.Delay(TimeSpan.FromSeconds(5)); respond.DeleteAsync(); } }
public async Task GuildLogger(BaseDiscordClient client, DiscordGuild guild, object eventArgs, LogType logType) { var guildData = await redis.GetAsync <Guild>(RedisKeyNaming.Guild(guild.Id)); var logs = guildData.Logs; var log = logs.FirstOrDefault(x => x.LogType == logType); if (log != null) { var logChannel = guild.GetChannel(log.ChannelId); if (logChannel != null) { var embed = new Embed(); switch (eventArgs) { case ChannelCreateEventArgs channelCreateEventArgs: ChannelCreate(client, embed, channelCreateEventArgs); break; case ChannelUpdateEventArgs channelUpdateEventArgs: ChannelUpdate(client, embed, channelUpdateEventArgs); break; case ChannelDeleteEventArgs channelDeleteEventArgs: ChannelDelete(client, guild, logs, channelDeleteEventArgs, guildData, embed); break; case GuildRoleCreateEventArgs guildRoleCreateEventArgs: GuildRoleCreate(client, embed, guildRoleCreateEventArgs); break; case GuildRoleUpdateEventArgs guildRoleUpdateEventArgs: GuildRoleUpdate(client, embed, guildRoleUpdateEventArgs); break; case GuildRoleDeleteEventArgs guildRoleDeleteEventArgs: GuildRoleDelete(client, embed, guildRoleDeleteEventArgs); break; case GuildMemberAddEventArgs memberAddEventArgs: GuildMemberAdd(client, embed, memberAddEventArgs); break; case GuildMemberUpdateEventArgs guildMemberUpdateEventArgs: GuildMemberUpdate(client, embed, guildMemberUpdateEventArgs); break; case GuildMemberRemoveEventArgs guildMemberRemoveEventArgs: GuildMemberRemove(client, embed, guildMemberRemoveEventArgs, logType); break; case GuildBanAddEventArgs guildBanAddEventArgs: GuildBanAdd(client, embed, guildBanAddEventArgs); break; case GuildBanRemoveEventArgs guildBanRemoveEventArgs: // Todo: With or without command break; case InviteCreateEventArgs inviteCreateEventArgs: InviteCreate(client, embed, inviteCreateEventArgs); break; case InviteDeleteEventArgs inviteDeleteEventArgs: InviteDelete(client, embed, inviteDeleteEventArgs); break; case MessageUpdateEventArgs messageUpdateEventArgs: MessageUpdate(client, embed, messageUpdateEventArgs); break; case MessageDeleteEventArgs messageDeleteEventArgs: MessageDelete(client, embed, messageDeleteEventArgs); break; case MessageBulkDeleteEventArgs messageBulkDeleteEventArgs: MessageBulkDelete(client, embed, messageBulkDeleteEventArgs); break; case MessageReactionAddEventArgs messageReactionAddEventArgs: // Why should this be a feature at all? break; case MessageReactionRemoveEventArgs messageReactionRemoveEventArgs: // Why should this be a feature at all? break; case MessageReactionRemoveEmojiEventArgs messageReactionRemoveEmojiEventArgs: // Why should this be a feature at all? break; case MessageReactionsClearEventArgs messageReactionsClearEventArgs: // Why should this be a feature at all? break; case VoiceStateUpdateEventArgs voiceStateUpdateEventArgs: { var before = voiceStateUpdateEventArgs.Before; var after = voiceStateUpdateEventArgs.After; var beforeChannel = voiceStateUpdateEventArgs.Before?.Channel; var afterChannel = voiceStateUpdateEventArgs.After?.Channel; if (beforeChannel != null) { if (afterChannel != null) { if (beforeChannel != afterChannel) { VoiceStateUpdateMemberSwitched(client, embed, voiceStateUpdateEventArgs, beforeChannel, afterChannel); } else { VoiceStateUpdateMedia(client, embed, voiceStateUpdateEventArgs, before, after); } embed.Color = DiscordColor.CornflowerBlue; } else { VoiceStateUpdateMemberDisconnected(client, embed, voiceStateUpdateEventArgs, beforeChannel); } } else { VoiceStateUpdateMemberConnected(client, embed, voiceStateUpdateEventArgs, afterChannel); } embed.Thumbnail = voiceStateUpdateEventArgs.User.AvatarUrl; embed.Footer = new EmbedFooter() { Text = $"Member: {voiceStateUpdateEventArgs.User.GetUsertag()} | {voiceStateUpdateEventArgs.User.Id}" }; break; } } if (passInformation) { await logChannel.SendEmbedMessageAsync(embed); } await Task.CompletedTask.ConfigureAwait(true); } else { guildData.Logs.Remove(log); await redis.ReplaceAsync(RedisKeyNaming.Guild(guild.Id), guildData); } } }
public async Task Info(CommandContext context) { var guild = context.Guild; var channels = guild.GetChannelsAsync().ConfigureAwait(true).GetAwaiter().GetResult().ToList(); var roles = await guild.GetRoles(); var emojis = guild.GetEmojisAsync().ConfigureAwait(true).GetAwaiter().GetResult().ToList(); var members = guild.GetAllMembersAsync().ConfigureAwait(true).GetAwaiter().GetResult().ToList(); var owner = guild.Owner; var prefix = redis.GetAsync <Defcon.Data.Guilds.Guild>(RedisKeyNaming.Guild(context.Guild.Id)).GetAwaiter().GetResult().Prefix; var guildAuthor = new EmbedAuthor { Name = guild.Name, Icon = guild.IconUrl }; var ownerDetails = new StringBuilder() .AppendLine($"Username: {owner.Mention} {Formatter.InlineCode(owner.GetUsertag())}") .AppendLine($"Identity: {Formatter.InlineCode(owner.Id.ToString())}") .ToString(); var premiumTierCount = guild.PremiumSubscriptionCount; var premiumTierSubsLabel = premiumTierCount == 1 ? "1 subscription" : $"{premiumTierCount} subscriptions"; var premiumTierDetails = new StringBuilder() .AppendLine($"{await guild.GetPremiumTier()}") .AppendLine(premiumTierSubsLabel) .ToString(); var membersTotal = guild.MemberCount; var botsCount = members.Count(x => x.IsBot); var humansCount = membersTotal - botsCount; var membersOnlineCount = await members.Online(); var membersDnDCount = await members.DoNotDisturb(); var membersIdleCount = await members.Idle(); var membersOfflineCount = membersTotal - (membersOnlineCount + membersIdleCount + membersDnDCount); var membersLabel = members.Count == 1 ? "1 Member" : $"{membersTotal} Members"; var memberDetails = new StringBuilder().AppendLineBold(":busts_in_silhouette: Humans", humansCount) .AppendLineBold(":robot: Bots", botsCount) .AppendLineBold(":green_circle: Online", membersOnlineCount) .AppendLineBold(":orange_circle: Idle", membersIdleCount) .AppendLineBold(":red_circle: DnD", membersDnDCount) .AppendLineBold(":white_circle: Offline", membersOfflineCount) .ToString(); var totalChannelsCount = channels.Count; var categoryChannelCount = await channels.Categories(); var textChannelCount = await channels.Texts(); var nsfwChannelCount = await channels.NSFW(); var voiceChannelCount = await channels.Voices(); var channelsLabel = totalChannelsCount == 1 ? "1 Channel" : $"{totalChannelsCount} Channels"; var channelDetails = new StringBuilder().AppendLineBold(":file_folder: Category", categoryChannelCount) .AppendLineBold(":speech_balloon: Text", textChannelCount) .AppendLineBold(":underage: NSFW", nsfwChannelCount) .AppendLineBold(":loud_sound: Voice", voiceChannelCount) .ToString(); var afkChannel = guild.AfkChannel != null ? guild.AfkChannel.Name : "Not set"; var afkTimeout = guild.AfkTimeout / 60; var miscDetails = new StringBuilder().AppendLineBold("AFK Channel", afkChannel) .AppendLineBold("AFK Timeout", $"{afkTimeout}min") .AppendLineBold("Roles", roles.Count) .AppendLineBold("Emojis", emojis.Count) .ToString(); var fields = new List <EmbedField> { new EmbedField { Inline = false, Name = "Owner", Value = ownerDetails }, new EmbedField { Inline = true, Name = "Premium", Value = premiumTierDetails }, new EmbedField { Inline = true, Name = "Verification Level", Value = $"{guild.VerificationLevel}" }, new EmbedField { Inline = true, Name = "Region", Value = $"{guild.VoiceRegion.Name}" }, new EmbedField { Inline = true, Name = membersLabel, Value = memberDetails }, new EmbedField { Inline = true, Name = channelsLabel, Value = channelDetails }, new EmbedField { Inline = true, Name = "Misc", Value = miscDetails } }; var guildDays = await guild.GetDays(); var guildSinceDays = guildDays == 1 ? $"yesterday" : guildDays == 0 ? "today" : $"{Formatter.Bold($"{guildDays}")} days ago"; var embed = new Embed { Description = new StringBuilder() .AppendLine($"Identity: {Formatter.InlineCode($"{guild.Id}")}") .AppendLine($"Created at: {await guild.CreatedAtLongDateTimeString()} ({guildSinceDays})") .AppendLine($"Server Prefix: {Formatter.InlineCode(prefix)}") .ToString(), Thumbnail = guild.IconUrl, Author = guildAuthor, Fields = fields }; await context.SendEmbedMessageAsync(embed); }