From 2e688db927604b8ffe409dd93161a0b536877a0f Mon Sep 17 00:00:00 2001 From: sabihoshi Date: Tue, 2 Aug 2022 08:43:37 +0800 Subject: [PATCH] feat: Add Message Attachments Logging --- HuTao.Bot/Modules/Logging/LoggingModule.cs | 16 + ...19_AddLoggingUploadAttachments.Designer.cs | 3021 +++++++++++++++++ ...20802004219_AddLoggingUploadAttachments.cs | 26 + .../Migrations/HuTaoContextModelSnapshot.cs | 3 + HuTao.Data/Models/Logging/LoggingRules.cs | 2 + HuTao.Services/Logging/LoggingService.cs | 83 +- .../Utilities/EmbedBuilderExtensions.cs | 15 +- 7 files changed, 3123 insertions(+), 43 deletions(-) create mode 100644 HuTao.Data/Migrations/20220802004219_AddLoggingUploadAttachments.Designer.cs create mode 100644 HuTao.Data/Migrations/20220802004219_AddLoggingUploadAttachments.cs diff --git a/HuTao.Bot/Modules/Logging/LoggingModule.cs b/HuTao.Bot/Modules/Logging/LoggingModule.cs index 470e9e1..cb8145f 100644 --- a/HuTao.Bot/Modules/Logging/LoggingModule.cs +++ b/HuTao.Bot/Modules/Logging/LoggingModule.cs @@ -125,6 +125,22 @@ [Remainder] [Summary("Leave empty to disable the appeal message.")] await ReplyAsync(embed: embed.Build()); } + [Command("attachments")] + [Alias("attachment")] + [Summary("Re-upload attachments when messages are deleted.")] + public async Task ConfigureAttachmentsAsync( + [Summary("Set to 'true' or 'false'. Leave blank to toggle.")] + bool? reUpload = null) + { + var guild = await _db.Guilds.TrackGuildAsync(Context.Guild); + guild.LoggingRules ??= new LoggingRules(); + + guild.LoggingRules.UploadAttachments = reUpload ?? !guild.LoggingRules.UploadAttachments; + await _db.SaveChangesAsync(); + + await ReplyAsync($"Current value: {guild.LoggingRules.UploadAttachments}"); + } + [Command("channel")] [Summary("Set the channel to output the reprimand.")] public async Task ConfigureChannelAsync( diff --git a/HuTao.Data/Migrations/20220802004219_AddLoggingUploadAttachments.Designer.cs b/HuTao.Data/Migrations/20220802004219_AddLoggingUploadAttachments.Designer.cs new file mode 100644 index 0000000..a88da6a --- /dev/null +++ b/HuTao.Data/Migrations/20220802004219_AddLoggingUploadAttachments.Designer.cs @@ -0,0 +1,3021 @@ +// +using System; +using HuTao.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace HuTao.Data.Migrations +{ + [DbContext(typeof(HuTaoContext))] + [Migration("20220802004219_AddLoggingUploadAttachments")] + partial class AddLoggingUploadAttachments + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.5") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("HardMuteRoleEntity", b => + { + b.Property("MutesId") + .HasColumnType("uuid"); + + b.Property("RolesRoleId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("MutesId", "RolesRoleId"); + + b.HasIndex("RolesRoleId"); + + b.ToTable("HardMuteRoleEntity"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Authorization.AuthorizationGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Access") + .HasColumnType("integer"); + + b.Property("ActionId") + .HasColumnType("uuid"); + + b.Property("GuildEntityId") + .HasColumnType("numeric(20,0)"); + + b.Property("JudgeType") + .HasColumnType("integer"); + + b.Property("LinkedCommandId") + .HasColumnType("uuid"); + + b.Property("ModerationCategoryId") + .HasColumnType("uuid"); + + b.Property("Scope") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ActionId"); + + b.HasIndex("GuildEntityId"); + + b.HasIndex("LinkedCommandId"); + + b.HasIndex("ModerationCategoryId"); + + b.ToTable("AuthorizationGroup"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Criteria.Criterion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuthorizationGroupId") + .HasColumnType("uuid"); + + b.Property("CensorId") + .HasColumnType("uuid"); + + b.Property("Discriminator") + .IsRequired() + .HasColumnType("text"); + + b.Property("LoggingRulesId") + .HasColumnType("uuid"); + + b.Property("ModerationCategoryId") + .HasColumnType("uuid"); + + b.Property("ModerationRulesId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AuthorizationGroupId"); + + b.HasIndex("CensorId"); + + b.HasIndex("LoggingRulesId"); + + b.HasIndex("ModerationCategoryId"); + + b.HasIndex("ModerationRulesId"); + + b.ToTable("Criterion"); + + b.HasDiscriminator("Discriminator").HasValue("Criterion"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.EnumChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("Discriminator") + .IsRequired() + .HasColumnType("text"); + + b.Property("IntType") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("EnumChannels"); + + b.HasDiscriminator("Discriminator").HasValue("EnumChannel"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.GuildEntity", b => + { + b.Property("Id") + .HasColumnType("numeric(20,0)"); + + b.Property("GenshinRulesId") + .HasColumnType("uuid"); + + b.Property("ModerationRulesId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("GenshinRulesId"); + + b.HasIndex("ModerationRulesId"); + + b.ToTable("Guilds"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.GuildUserEntity", b => + { + b.Property("Id") + .HasColumnType("numeric(20,0)"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("JoinedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id", "GuildId"); + + b.HasIndex("GuildId"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Attachment", b => + { + b.Property("AttachmentId") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ContentType") + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Ephemeral") + .HasColumnType("boolean"); + + b.Property("Filename") + .IsRequired() + .HasColumnType("text"); + + b.Property("Height") + .HasColumnType("integer"); + + b.Property("Id") + .HasColumnType("numeric(20,0)"); + + b.Property("MessageLogId") + .HasColumnType("uuid"); + + b.Property("MessageTemplateId") + .HasColumnType("uuid"); + + b.Property("ProxyUrl") + .IsRequired() + .HasColumnType("text"); + + b.Property("Size") + .HasColumnType("integer"); + + b.Property("Url") + .IsRequired() + .HasColumnType("text"); + + b.Property("Width") + .HasColumnType("integer"); + + b.HasKey("AttachmentId"); + + b.HasIndex("MessageLogId"); + + b.HasIndex("MessageTemplateId"); + + b.ToTable("Attachment"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Components.ActionRow", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("MessageLogId") + .HasColumnType("uuid"); + + b.Property("MessageTemplateId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("MessageLogId"); + + b.HasIndex("MessageTemplateId"); + + b.ToTable("ActionRow"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Components.Component", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ActionRowId") + .HasColumnType("uuid"); + + b.Property("CustomId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Discriminator") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsDisabled") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("ActionRowId"); + + b.ToTable("Component"); + + b.HasDiscriminator("Discriminator").HasValue("Component"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Components.MenuOption", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Description") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("Emote") + .HasColumnType("text"); + + b.Property("IsDefault") + .HasColumnType("boolean"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SelectMenuId") + .HasColumnType("uuid"); + + b.Property("Value") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.HasIndex("SelectMenuId"); + + b.ToTable("MenuOption"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Embeds.Author", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("IconUrl") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("ProxyIconUrl") + .HasColumnType("text"); + + b.Property("Url") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Author"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Embeds.Embed", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AuthorId") + .HasColumnType("uuid"); + + b.Property("Color") + .HasColumnType("bigint"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("FooterId") + .HasColumnType("uuid"); + + b.Property("ImageId") + .HasColumnType("uuid"); + + b.Property("MessageLogId") + .HasColumnType("uuid"); + + b.Property("MessageTemplateId") + .HasColumnType("uuid"); + + b.Property("ThumbnailId") + .HasColumnType("uuid"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone"); + + b.Property("Title") + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("Url") + .HasColumnType("text"); + + b.Property("VideoId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AuthorId"); + + b.HasIndex("FooterId"); + + b.HasIndex("ImageId"); + + b.HasIndex("MessageLogId"); + + b.HasIndex("MessageTemplateId"); + + b.HasIndex("ThumbnailId"); + + b.HasIndex("VideoId"); + + b.ToTable("Embed"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Embeds.Field", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("EmbedId") + .HasColumnType("uuid"); + + b.Property("Inline") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("EmbedId"); + + b.ToTable("Field"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Embeds.Footer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("IconUrl") + .HasColumnType("text"); + + b.Property("ProxyUrl") + .HasColumnType("text"); + + b.Property("Text") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Footer"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Embeds.Image", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Height") + .HasColumnType("integer"); + + b.Property("ProxyUrl") + .IsRequired() + .HasColumnType("text"); + + b.Property("Url") + .IsRequired() + .HasColumnType("text"); + + b.Property("Width") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Image"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Embeds.Thumbnail", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Height") + .HasColumnType("integer"); + + b.Property("ProxyUrl") + .IsRequired() + .HasColumnType("text"); + + b.Property("Url") + .IsRequired() + .HasColumnType("text"); + + b.Property("Width") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Thumbnail"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Embeds.Video", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Height") + .HasColumnType("integer"); + + b.Property("Url") + .IsRequired() + .HasColumnType("text"); + + b.Property("Width") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Video"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Linking.LinkedButton", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ButtonId") + .HasColumnType("uuid"); + + b.Property("DmUser") + .HasColumnType("boolean"); + + b.Property("Ephemeral") + .HasColumnType("boolean"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("MessageId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ButtonId") + .IsUnique(); + + b.HasIndex("GuildId"); + + b.HasIndex("MessageId"); + + b.ToTable("LinkedButton"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Linking.LinkedCommand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Cooldown") + .HasColumnType("interval"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Ephemeral") + .HasColumnType("boolean"); + + b.Property("GuildEntityId") + .HasColumnType("numeric(20,0)"); + + b.Property("MessageId") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Silent") + .HasColumnType("boolean"); + + b.Property("UserOptions") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("GuildEntityId"); + + b.HasIndex("MessageId"); + + b.ToTable("LinkedCommand"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Linking.MessageTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AllowMentions") + .HasColumnType("boolean"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("IsLive") + .HasColumnType("boolean"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)"); + + b.Property("ReplaceTimestamps") + .HasColumnType("boolean"); + + b.Property("SuppressEmbeds") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.ToTable("MessageTemplate"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Linking.RoleTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Behavior") + .HasColumnType("integer"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("LinkedButtonId") + .HasColumnType("uuid"); + + b.Property("LinkedCommandId") + .HasColumnType("uuid"); + + b.Property("RoleActionId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)"); + + b.Property("RoleReprimandId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("LinkedButtonId"); + + b.HasIndex("LinkedCommandId"); + + b.HasIndex("RoleActionId"); + + b.HasIndex("RoleReprimandId"); + + b.ToTable("RoleTemplate"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Linking.StickyMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("CountDelay") + .HasColumnType("bigint"); + + b.Property("GuildEntityId") + .HasColumnType("numeric(20,0)"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("TemplateId") + .HasColumnType("uuid"); + + b.Property("TimeDelay") + .HasColumnType("interval"); + + b.HasKey("Id"); + + b.HasIndex("GuildEntityId"); + + b.HasIndex("TemplateId"); + + b.ToTable("StickyMessage"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Reaction.ReactionEntity", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Discriminator") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("ReactionEntity"); + + b.HasDiscriminator("Discriminator").HasValue("ReactionEntity"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.RoleEntity", b => + { + b.Property("RoleId") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("RoleId"); + + b.ToTable("Roles"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.TemporaryRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ActionId") + .HasColumnType("uuid"); + + b.Property("EndedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpireAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GuildEntityId") + .HasColumnType("numeric(20,0)"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("Length") + .HasColumnType("interval"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)"); + + b.Property("StartedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ActionId"); + + b.HasIndex("GuildEntityId"); + + b.ToTable("TemporaryRole"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.TemporaryRoleMember", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ActionId") + .HasColumnType("uuid"); + + b.Property("EndedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpireAt") + .HasColumnType("timestamp with time zone"); + + b.Property("GuildEntityId") + .HasColumnType("numeric(20,0)"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("Length") + .HasColumnType("interval"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)"); + + b.Property("StartedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("ActionId"); + + b.HasIndex("GuildEntityId"); + + b.HasIndex("UserId", "GuildId"); + + b.ToTable("TemporaryRoleMember"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Logging.DeleteLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ActionId") + .HasColumnType("uuid"); + + b.Property("Discriminator") + .IsRequired() + .HasColumnType("text"); + + b.Property("GuildEntityId") + .HasColumnType("numeric(20,0)"); + + b.Property("LogDate") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ActionId"); + + b.HasIndex("GuildEntityId"); + + b.ToTable("DeleteLog"); + + b.HasDiscriminator("Discriminator").HasValue("DeleteLog"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Logging.LoggingRules", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("UploadAttachments") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("LoggingRules"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Logging.MessageLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("Content") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("EditedTimestamp") + .HasColumnType("timestamp with time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("LogDate") + .HasColumnType("timestamp with time zone"); + + b.Property("MentionedEveryone") + .HasColumnType("boolean"); + + b.Property("MentionedRolesCount") + .HasColumnType("integer"); + + b.Property("MentionedUsersCount") + .HasColumnType("integer"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)"); + + b.Property("ReferencedMessageId") + .HasColumnType("numeric(20,0)"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone"); + + b.Property("UpdatedLogId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.HasIndex("UpdatedLogId"); + + b.HasIndex("UserId", "GuildId"); + + b.ToTable("MessageLog"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Logging.ReactionLog", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("EmoteId") + .HasColumnType("uuid"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("LogDate") + .HasColumnType("timestamp with time zone"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("EmoteId"); + + b.HasIndex("GuildId"); + + b.HasIndex("UserId", "GuildId"); + + b.ToTable("ReactionLog"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Configurations.Link", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("OriginalString") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Link"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Exclusions.ModerationExclusion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConfigurationId") + .HasColumnType("uuid"); + + b.Property("Discriminator") + .IsRequired() + .HasColumnType("text"); + + b.Property("ModerationRulesId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ConfigurationId"); + + b.HasIndex("ModerationRulesId"); + + b.ToTable("ModerationExclusion"); + + b.HasDiscriminator("Discriminator").HasValue("ModerationExclusion"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Actions.ModerationTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ActionId") + .HasColumnType("uuid"); + + b.Property("CategoryId") + .HasColumnType("uuid"); + + b.Property("GuildEntityId") + .HasColumnType("numeric(20,0)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Reason") + .HasColumnType("text"); + + b.Property("Scope") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("ActionId"); + + b.HasIndex("CategoryId"); + + b.HasIndex("GuildEntityId"); + + b.ToTable("ModerationTemplate"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Actions.ReprimandAction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Discriminator") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("ReprimandAction"); + + b.HasDiscriminator("Discriminator").HasValue("ReprimandAction"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.ModerationAction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Date") + .HasColumnType("timestamp with time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("Reason") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.HasIndex("UserId", "GuildId"); + + b.ToTable("ModerationAction"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Reprimands.Reprimand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ActionId") + .HasColumnType("uuid"); + + b.Property("CategoryId") + .HasColumnType("uuid"); + + b.Property("Discriminator") + .IsRequired() + .HasColumnType("text"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("ModifiedActionId") + .HasColumnType("uuid"); + + b.Property("Status") + .HasColumnType("integer"); + + b.Property("TriggerId") + .HasColumnType("uuid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("ActionId"); + + b.HasIndex("CategoryId"); + + b.HasIndex("GuildId"); + + b.HasIndex("ModifiedActionId"); + + b.HasIndex("TriggerId"); + + b.HasIndex("UserId", "GuildId"); + + b.ToTable("Reprimand"); + + b.HasDiscriminator("Discriminator").HasValue("Reprimand"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Triggers.Trigger", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ActionId") + .HasColumnType("uuid"); + + b.Property("Amount") + .HasColumnType("bigint"); + + b.Property("CategoryId") + .HasColumnType("uuid"); + + b.Property("Discriminator") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("Mode") + .HasColumnType("integer"); + + b.Property("ModerationRulesId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("ActionId"); + + b.HasIndex("CategoryId"); + + b.HasIndex("ModerationRulesId"); + + b.ToTable("Trigger"); + + b.HasDiscriminator("Discriminator").HasValue("Trigger"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Logging.ModerationLogConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AppealMessage") + .HasColumnType("text"); + + b.Property("Discriminator") + .IsRequired() + .HasColumnType("text"); + + b.Property("LogReprimandStatus") + .HasColumnType("integer"); + + b.Property("LogReprimands") + .HasColumnType("integer"); + + b.Property("Options") + .HasColumnType("integer"); + + b.Property("ShowAppealOnReprimands") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("ModerationLogConfig"); + + b.HasDiscriminator("Discriminator").HasValue("ModerationLogConfig"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Logging.ModerationLoggingRules", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CommandLogId") + .HasColumnType("uuid"); + + b.Property("HistoryReprimands") + .HasColumnType("integer"); + + b.Property("IgnoreDuplicates") + .HasColumnType("boolean"); + + b.Property("ModeratorLogId") + .HasColumnType("uuid"); + + b.Property("PublicLogId") + .HasColumnType("uuid"); + + b.Property("SilentReprimands") + .HasColumnType("integer"); + + b.Property("SummaryReprimands") + .HasColumnType("integer"); + + b.Property("UserLogId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("CommandLogId"); + + b.HasIndex("ModeratorLogId"); + + b.HasIndex("PublicLogId"); + + b.HasIndex("UserLogId"); + + b.ToTable("ModerationLoggingRules"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.ModerationCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AutoReprimandCooldown") + .HasColumnType("interval"); + + b.Property("CensorNicknames") + .HasColumnType("boolean"); + + b.Property("CensorUsernames") + .HasColumnType("boolean"); + + b.Property("CensoredExpiryLength") + .HasColumnType("interval"); + + b.Property("FilteredExpiryLength") + .HasColumnType("interval"); + + b.Property("GuildEntityId") + .HasColumnType("numeric(20,0)"); + + b.Property("HardMuteRoleId") + .HasColumnType("numeric(20,0)"); + + b.Property("LoggingId") + .HasColumnType("uuid"); + + b.Property("MuteRoleId") + .HasColumnType("numeric(20,0)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("NameReplacement") + .HasColumnType("text"); + + b.Property("NoticeExpiryLength") + .HasColumnType("interval"); + + b.Property("ReplaceMutes") + .HasColumnType("boolean"); + + b.Property("WarningExpiryLength") + .HasColumnType("interval"); + + b.HasKey("Id"); + + b.HasIndex("GuildEntityId"); + + b.HasIndex("LoggingId"); + + b.ToTable("ModerationCategory"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.ModerationRules", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AutoReprimandCooldown") + .HasColumnType("interval"); + + b.Property("CensorNicknames") + .HasColumnType("boolean"); + + b.Property("CensorUsernames") + .HasColumnType("boolean"); + + b.Property("CensoredExpiryLength") + .HasColumnType("interval"); + + b.Property("FilteredExpiryLength") + .HasColumnType("interval"); + + b.Property("HardMuteRoleId") + .HasColumnType("numeric(20,0)"); + + b.Property("LoggingId") + .HasColumnType("uuid"); + + b.Property("MuteRoleId") + .HasColumnType("numeric(20,0)"); + + b.Property("NameReplacement") + .HasColumnType("text"); + + b.Property("NoticeExpiryLength") + .HasColumnType("interval"); + + b.Property("ReplaceMutes") + .HasColumnType("boolean"); + + b.Property("WarningExpiryLength") + .HasColumnType("interval"); + + b.HasKey("Id"); + + b.HasIndex("LoggingId"); + + b.ToTable("ModerationRules"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.ModerationVariable", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ModerationRulesId") + .HasColumnType("uuid"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("ModerationRulesId"); + + b.ToTable("ModerationVariable"); + }); + + modelBuilder.Entity("HuTao.Data.Models.TimeTracking.GenshinTimeTrackingRules", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AmericaChannelId") + .HasColumnType("uuid"); + + b.Property("AsiaChannelId") + .HasColumnType("uuid"); + + b.Property("EuropeChannelId") + .HasColumnType("uuid"); + + b.Property("SARChannelId") + .HasColumnType("uuid"); + + b.Property("ServerStatusId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AmericaChannelId"); + + b.HasIndex("AsiaChannelId"); + + b.HasIndex("EuropeChannelId"); + + b.HasIndex("SARChannelId"); + + b.HasIndex("ServerStatusId"); + + b.ToTable("GenshinTimeTrackingRules"); + }); + + modelBuilder.Entity("HuTao.Data.Models.TimeTracking.TimeTracking", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Discriminator") + .IsRequired() + .HasColumnType("text"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("TimeTrackingRules"); + + b.HasDiscriminator("Discriminator").HasValue("TimeTracking"); + }); + + modelBuilder.Entity("HuTao.Data.Models.VoiceChat.VoiceChatLink", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("TextChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.Property("VoiceChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("VoiceChatRulesId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.HasIndex("VoiceChatRulesId"); + + b.HasIndex("UserId", "GuildId"); + + b.ToTable("VoiceChatLink"); + }); + + modelBuilder.Entity("HuTao.Data.Models.VoiceChat.VoiceChatRules", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("DeletionDelay") + .HasColumnType("interval"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("HubVoiceChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("PurgeEmpty") + .HasColumnType("boolean"); + + b.Property("ShowJoinLeave") + .HasColumnType("boolean"); + + b.Property("VoiceChannelCategoryId") + .HasColumnType("numeric(20,0)"); + + b.Property("VoiceChatCategoryId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("VoiceChatRules"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Criteria.ChannelCriterion", b => + { + b.HasBaseType("HuTao.Data.Models.Criteria.Criterion"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("IsCategory") + .HasColumnType("boolean"); + + b.HasDiscriminator().HasValue("ChannelCriterion"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Criteria.PermissionCriterion", b => + { + b.HasBaseType("HuTao.Data.Models.Criteria.Criterion"); + + b.Property("Permission") + .HasColumnType("integer"); + + b.HasDiscriminator().HasValue("PermissionCriterion"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Criteria.RoleCriterion", b => + { + b.HasBaseType("HuTao.Data.Models.Criteria.Criterion"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)"); + + b.HasDiscriminator().HasValue("RoleCriterion"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Criteria.UserCriterion", b => + { + b.HasBaseType("HuTao.Data.Models.Criteria.Criterion"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasDiscriminator().HasValue("UserCriterion"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.EnumChannel", b => + { + b.HasBaseType("HuTao.Data.Models.Discord.EnumChannel"); + + b.Property("LoggingRulesId") + .HasColumnType("uuid"); + + b.HasIndex("LoggingRulesId"); + + b.HasDiscriminator().HasValue("EnumChannel"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Components.Button", b => + { + b.HasBaseType("HuTao.Data.Models.Discord.Message.Components.Component"); + + b.Property("Emote") + .HasColumnType("text"); + + b.Property("Label") + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("Style") + .HasColumnType("integer"); + + b.Property("Url") + .HasColumnType("text"); + + b.HasDiscriminator().HasValue("Button"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Components.SelectMenu", b => + { + b.HasBaseType("HuTao.Data.Models.Discord.Message.Components.Component"); + + b.Property("MaxValues") + .HasColumnType("integer"); + + b.Property("MinValues") + .HasColumnType("integer"); + + b.Property("Placeholder") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasDiscriminator().HasValue("SelectMenu"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Reaction.EmojiEntity", b => + { + b.HasBaseType("HuTao.Data.Models.Discord.Reaction.ReactionEntity"); + + b.HasDiscriminator().HasValue("EmojiEntity"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Reaction.EmoteEntity", b => + { + b.HasBaseType("HuTao.Data.Models.Discord.Reaction.ReactionEntity"); + + b.Property("EmoteId") + .HasColumnType("numeric(20,0)"); + + b.Property("IsAnimated") + .HasColumnType("boolean"); + + b.HasIndex("EmoteId") + .IsUnique(); + + b.HasDiscriminator().HasValue("EmoteEntity"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Logging.MessageDeleteLog", b => + { + b.HasBaseType("HuTao.Data.Models.Logging.DeleteLog"); + + b.Property("ChannelId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("numeric(20,0)") + .HasColumnName("ChannelId"); + + b.Property("FilteredId") + .HasColumnType("uuid"); + + b.Property("GuildId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("numeric(20,0)") + .HasColumnName("GuildId"); + + b.Property("MessageId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("numeric(20,0)") + .HasColumnName("MessageId"); + + b.Property("MessagesDeleteLogId") + .HasColumnType("uuid"); + + b.Property("UserId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("numeric(20,0)") + .HasColumnName("UserId"); + + b.HasIndex("FilteredId"); + + b.HasIndex("MessagesDeleteLogId"); + + b.HasDiscriminator().HasValue("MessageDeleteLog"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Logging.MessagesDeleteLog", b => + { + b.HasBaseType("HuTao.Data.Models.Logging.DeleteLog"); + + b.Property("ChannelId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("numeric(20,0)") + .HasColumnName("ChannelId"); + + b.Property("GuildId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("numeric(20,0)") + .HasColumnName("GuildId"); + + b.HasDiscriminator().HasValue("MessagesDeleteLog"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Logging.ReactionDeleteLog", b => + { + b.HasBaseType("HuTao.Data.Models.Logging.DeleteLog"); + + b.Property("ChannelId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("numeric(20,0)") + .HasColumnName("ChannelId"); + + b.Property("EmoteId") + .HasColumnType("uuid"); + + b.Property("GuildId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("numeric(20,0)") + .HasColumnName("GuildId"); + + b.Property("MessageId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("numeric(20,0)") + .HasColumnName("MessageId"); + + b.Property("UserId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("numeric(20,0)") + .HasColumnName("UserId"); + + b.HasIndex("EmoteId"); + + b.HasDiscriminator().HasValue("ReactionDeleteLog"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Configurations.AutoConfiguration", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Infractions.Triggers.Trigger"); + + b.Property("Cooldown") + .HasColumnType("interval"); + + b.Property("DeleteMessages") + .HasColumnType("boolean"); + + b.Property("Global") + .HasColumnType("boolean"); + + b.Property("Length") + .HasColumnType("interval"); + + b.Property("MinimumLength") + .HasColumnType("integer"); + + b.Property("Reason") + .HasColumnType("text"); + + b.Property("ReprimandId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("ReprimandId"); + + b.HasIndex("ReprimandId"); + + b.HasDiscriminator().HasValue("AutoConfiguration"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Exclusions.CriterionExclusion", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Auto.Exclusions.ModerationExclusion"); + + b.Property("CriterionId") + .HasColumnType("uuid"); + + b.HasIndex("CriterionId"); + + b.HasDiscriminator().HasValue("CriterionExclusion"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Exclusions.EmojiExclusion", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Auto.Exclusions.ModerationExclusion"); + + b.Property("EmojiId") + .HasColumnType("uuid"); + + b.HasIndex("EmojiId"); + + b.HasDiscriminator().HasValue("EmojiExclusion"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Exclusions.InviteExclusion", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Auto.Exclusions.ModerationExclusion"); + + b.Property("GuildId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("numeric(20,0)") + .HasColumnName("GuildId"); + + b.HasIndex("GuildId"); + + b.HasDiscriminator().HasValue("InviteExclusion"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Exclusions.LinkExclusion", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Auto.Exclusions.ModerationExclusion"); + + b.Property("LinkId") + .HasColumnType("uuid"); + + b.HasIndex("LinkId"); + + b.HasDiscriminator().HasValue("LinkExclusion"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Exclusions.RoleMentionExclusion", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Auto.Exclusions.ModerationExclusion"); + + b.Property("GuildId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("numeric(20,0)") + .HasColumnName("GuildId"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)"); + + b.HasIndex("RoleId"); + + b.HasDiscriminator().HasValue("RoleMentionExclusion"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Exclusions.UserMentionExclusion", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Auto.Exclusions.ModerationExclusion"); + + b.Property("GuildId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("numeric(20,0)") + .HasColumnName("GuildId"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasIndex("UserId", "GuildId"); + + b.HasDiscriminator().HasValue("UserMentionExclusion"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Actions.BanAction", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Infractions.Actions.ReprimandAction"); + + b.Property("DeleteDays") + .HasColumnType("bigint"); + + b.Property("Length") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("interval") + .HasColumnName("Length"); + + b.HasDiscriminator().HasValue("BanAction"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Actions.KickAction", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Infractions.Actions.ReprimandAction"); + + b.HasDiscriminator().HasValue("KickAction"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Actions.MuteAction", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Infractions.Actions.ReprimandAction"); + + b.Property("Length") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("interval") + .HasColumnName("Length"); + + b.HasDiscriminator().HasValue("MuteAction"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Actions.NoteAction", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Infractions.Actions.ReprimandAction"); + + b.HasDiscriminator().HasValue("NoteAction"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Actions.NoticeAction", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Infractions.Actions.ReprimandAction"); + + b.HasDiscriminator().HasValue("NoticeAction"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Actions.RoleAction", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Infractions.Actions.ReprimandAction"); + + b.Property("Length") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("interval") + .HasColumnName("Length"); + + b.HasDiscriminator().HasValue("RoleAction"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Actions.WarningAction", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Infractions.Actions.ReprimandAction"); + + b.Property("Count") + .HasColumnType("bigint"); + + b.HasDiscriminator().HasValue("WarningAction"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Censors.Censor", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Infractions.Triggers.Trigger"); + + b.Property("Options") + .HasColumnType("integer"); + + b.Property("Pattern") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReprimandId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("ReprimandId"); + + b.Property("Silent") + .HasColumnType("boolean"); + + b.HasIndex("ReprimandId"); + + b.HasDiscriminator().HasValue("Censor"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Reprimands.ExpirableReprimand", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Infractions.Reprimands.Reprimand"); + + b.Property("EndedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ExpireAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Length") + .HasColumnType("interval"); + + b.Property("StartedAt") + .HasColumnType("timestamp with time zone"); + + b.HasDiscriminator().HasValue("ExpirableReprimand"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Reprimands.Kick", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Infractions.Reprimands.Reprimand"); + + b.HasDiscriminator().HasValue("Kick"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Reprimands.Note", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Infractions.Reprimands.Reprimand"); + + b.HasDiscriminator().HasValue("Note"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Triggers.ReprimandTrigger", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Infractions.Triggers.Trigger"); + + b.Property("ReprimandId") + .ValueGeneratedOnUpdateSometimes() + .HasColumnType("uuid") + .HasColumnName("ReprimandId"); + + b.Property("Source") + .HasColumnType("integer"); + + b.HasIndex("ReprimandId"); + + b.HasDiscriminator().HasValue("ReprimandTrigger"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Logging.ModerationLogChannelConfig", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Logging.ModerationLogConfig"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.HasDiscriminator().HasValue("ModerationLogChannelConfig"); + }); + + modelBuilder.Entity("HuTao.Data.Models.TimeTracking.ChannelTimeTracking", b => + { + b.HasBaseType("HuTao.Data.Models.TimeTracking.TimeTracking"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("ChannelTimeTracking_ChannelId"); + + b.HasDiscriminator().HasValue("ChannelTimeTracking"); + }); + + modelBuilder.Entity("HuTao.Data.Models.TimeTracking.MessageTimeTracking", b => + { + b.HasBaseType("HuTao.Data.Models.TimeTracking.TimeTracking"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)"); + + b.HasDiscriminator().HasValue("MessageTimeTracking"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Configurations.AttachmentConfiguration", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Auto.Configurations.AutoConfiguration"); + + b.HasDiscriminator().HasValue("AttachmentConfiguration"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Configurations.DuplicateConfiguration", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Auto.Configurations.AutoConfiguration"); + + b.Property("Percentage") + .HasColumnType("double precision"); + + b.Property("Tolerance") + .HasColumnType("integer"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasDiscriminator().HasValue("DuplicateConfiguration"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Configurations.EmojiConfiguration", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Auto.Configurations.AutoConfiguration"); + + b.HasDiscriminator().HasValue("EmojiConfiguration"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Configurations.InviteConfiguration", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Auto.Configurations.AutoConfiguration"); + + b.HasDiscriminator().HasValue("InviteConfiguration"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Configurations.LinkConfiguration", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Auto.Configurations.AutoConfiguration"); + + b.HasDiscriminator().HasValue("LinkConfiguration"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Configurations.MentionConfiguration", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Auto.Configurations.AutoConfiguration"); + + b.Property("CountDuplicate") + .HasColumnType("boolean"); + + b.Property("CountInvalid") + .HasColumnType("boolean"); + + b.Property("CountRoleMembers") + .HasColumnType("boolean"); + + b.HasDiscriminator().HasValue("MentionConfiguration"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Configurations.MessageConfiguration", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Auto.Configurations.AutoConfiguration"); + + b.HasDiscriminator().HasValue("MessageConfiguration"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Configurations.NewLineConfiguration", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Auto.Configurations.AutoConfiguration"); + + b.Property("BlankOnly") + .HasColumnType("boolean"); + + b.HasDiscriminator().HasValue("NewLineConfiguration"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Configurations.ReplyConfiguration", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Auto.Configurations.AutoConfiguration"); + + b.HasDiscriminator().HasValue("ReplyConfiguration"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Reprimands.Ban", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Infractions.Reprimands.ExpirableReprimand"); + + b.Property("DeleteDays") + .HasColumnType("bigint"); + + b.HasDiscriminator().HasValue("Ban"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Reprimands.Censored", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Infractions.Reprimands.ExpirableReprimand"); + + b.Property("Content") + .IsRequired() + .HasColumnType("text"); + + b.HasDiscriminator().HasValue("Censored"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Reprimands.Filtered", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Infractions.Reprimands.ExpirableReprimand"); + + b.HasDiscriminator().HasValue("Filtered"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Reprimands.Mute", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Infractions.Reprimands.ExpirableReprimand"); + + b.HasDiscriminator().HasValue("Mute"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Reprimands.Notice", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Infractions.Reprimands.ExpirableReprimand"); + + b.HasDiscriminator().HasValue("Notice"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Reprimands.RoleReprimand", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Infractions.Reprimands.ExpirableReprimand"); + + b.HasDiscriminator().HasValue("RoleReprimand"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Reprimands.Warning", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Infractions.Reprimands.ExpirableReprimand"); + + b.Property("Count") + .HasColumnType("bigint"); + + b.HasDiscriminator().HasValue("Warning"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Reprimands.HardMute", b => + { + b.HasBaseType("HuTao.Data.Models.Moderation.Infractions.Reprimands.Mute"); + + b.HasDiscriminator().HasValue("HardMute"); + }); + + modelBuilder.Entity("HardMuteRoleEntity", b => + { + b.HasOne("HuTao.Data.Models.Moderation.Infractions.Reprimands.HardMute", null) + .WithMany() + .HasForeignKey("MutesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("HuTao.Data.Models.Discord.RoleEntity", null) + .WithMany() + .HasForeignKey("RolesRoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("HuTao.Data.Models.Authorization.AuthorizationGroup", b => + { + b.HasOne("HuTao.Data.Models.Moderation.Infractions.ModerationAction", "Action") + .WithMany() + .HasForeignKey("ActionId"); + + b.HasOne("HuTao.Data.Models.Discord.GuildEntity", null) + .WithMany("AuthorizationGroups") + .HasForeignKey("GuildEntityId"); + + b.HasOne("HuTao.Data.Models.Discord.Message.Linking.LinkedCommand", null) + .WithMany("Authorization") + .HasForeignKey("LinkedCommandId"); + + b.HasOne("HuTao.Data.Models.Moderation.ModerationCategory", null) + .WithMany("Authorization") + .HasForeignKey("ModerationCategoryId"); + + b.Navigation("Action"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Criteria.Criterion", b => + { + b.HasOne("HuTao.Data.Models.Authorization.AuthorizationGroup", null) + .WithMany("Collection") + .HasForeignKey("AuthorizationGroupId"); + + b.HasOne("HuTao.Data.Models.Moderation.Infractions.Censors.Censor", null) + .WithMany("Exclusions") + .HasForeignKey("CensorId"); + + b.HasOne("HuTao.Data.Models.Logging.LoggingRules", null) + .WithMany("LoggingExclusions") + .HasForeignKey("LoggingRulesId"); + + b.HasOne("HuTao.Data.Models.Moderation.ModerationCategory", null) + .WithMany("CensorExclusions") + .HasForeignKey("ModerationCategoryId"); + + b.HasOne("HuTao.Data.Models.Moderation.ModerationRules", null) + .WithMany("CensorExclusions") + .HasForeignKey("ModerationRulesId"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.GuildEntity", b => + { + b.HasOne("HuTao.Data.Models.TimeTracking.GenshinTimeTrackingRules", "GenshinRules") + .WithMany() + .HasForeignKey("GenshinRulesId"); + + b.HasOne("HuTao.Data.Models.Moderation.ModerationRules", "ModerationRules") + .WithMany() + .HasForeignKey("ModerationRulesId"); + + b.Navigation("GenshinRules"); + + b.Navigation("ModerationRules"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.GuildUserEntity", b => + { + b.HasOne("HuTao.Data.Models.Discord.GuildEntity", "Guild") + .WithMany() + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Guild"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Attachment", b => + { + b.HasOne("HuTao.Data.Models.Logging.MessageLog", null) + .WithMany("Attachments") + .HasForeignKey("MessageLogId"); + + b.HasOne("HuTao.Data.Models.Discord.Message.Linking.MessageTemplate", null) + .WithMany("Attachments") + .HasForeignKey("MessageTemplateId"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Components.ActionRow", b => + { + b.HasOne("HuTao.Data.Models.Logging.MessageLog", null) + .WithMany("Components") + .HasForeignKey("MessageLogId"); + + b.HasOne("HuTao.Data.Models.Discord.Message.Linking.MessageTemplate", null) + .WithMany("Components") + .HasForeignKey("MessageTemplateId"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Components.Component", b => + { + b.HasOne("HuTao.Data.Models.Discord.Message.Components.ActionRow", null) + .WithMany("Components") + .HasForeignKey("ActionRowId"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Components.MenuOption", b => + { + b.HasOne("HuTao.Data.Models.Discord.Message.Components.SelectMenu", null) + .WithMany("Options") + .HasForeignKey("SelectMenuId"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Embeds.Embed", b => + { + b.HasOne("HuTao.Data.Models.Discord.Message.Embeds.Author", "Author") + .WithMany() + .HasForeignKey("AuthorId"); + + b.HasOne("HuTao.Data.Models.Discord.Message.Embeds.Footer", "Footer") + .WithMany() + .HasForeignKey("FooterId"); + + b.HasOne("HuTao.Data.Models.Discord.Message.Embeds.Image", "Image") + .WithMany() + .HasForeignKey("ImageId"); + + b.HasOne("HuTao.Data.Models.Logging.MessageLog", null) + .WithMany("Embeds") + .HasForeignKey("MessageLogId"); + + b.HasOne("HuTao.Data.Models.Discord.Message.Linking.MessageTemplate", null) + .WithMany("Embeds") + .HasForeignKey("MessageTemplateId"); + + b.HasOne("HuTao.Data.Models.Discord.Message.Embeds.Thumbnail", "Thumbnail") + .WithMany() + .HasForeignKey("ThumbnailId"); + + b.HasOne("HuTao.Data.Models.Discord.Message.Embeds.Video", "Video") + .WithMany() + .HasForeignKey("VideoId"); + + b.Navigation("Author"); + + b.Navigation("Footer"); + + b.Navigation("Image"); + + b.Navigation("Thumbnail"); + + b.Navigation("Video"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Embeds.Field", b => + { + b.HasOne("HuTao.Data.Models.Discord.Message.Embeds.Embed", null) + .WithMany("Fields") + .HasForeignKey("EmbedId"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Linking.LinkedButton", b => + { + b.HasOne("HuTao.Data.Models.Discord.Message.Components.Button", "Button") + .WithOne("Link") + .HasForeignKey("HuTao.Data.Models.Discord.Message.Linking.LinkedButton", "ButtonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("HuTao.Data.Models.Discord.GuildEntity", "Guild") + .WithMany("LinkedButtons") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("HuTao.Data.Models.Discord.Message.Linking.MessageTemplate", "Message") + .WithMany() + .HasForeignKey("MessageId"); + + b.Navigation("Button"); + + b.Navigation("Guild"); + + b.Navigation("Message"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Linking.LinkedCommand", b => + { + b.HasOne("HuTao.Data.Models.Discord.GuildEntity", null) + .WithMany("LinkedCommands") + .HasForeignKey("GuildEntityId"); + + b.HasOne("HuTao.Data.Models.Discord.Message.Linking.MessageTemplate", "Message") + .WithMany() + .HasForeignKey("MessageId"); + + b.Navigation("Message"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Linking.RoleTemplate", b => + { + b.HasOne("HuTao.Data.Models.Discord.Message.Linking.LinkedButton", null) + .WithMany("Roles") + .HasForeignKey("LinkedButtonId"); + + b.HasOne("HuTao.Data.Models.Discord.Message.Linking.LinkedCommand", null) + .WithMany("Roles") + .HasForeignKey("LinkedCommandId"); + + b.HasOne("HuTao.Data.Models.Moderation.Infractions.Actions.RoleAction", null) + .WithMany("Roles") + .HasForeignKey("RoleActionId"); + + b.HasOne("HuTao.Data.Models.Moderation.Infractions.Reprimands.RoleReprimand", null) + .WithMany("Roles") + .HasForeignKey("RoleReprimandId"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Linking.StickyMessage", b => + { + b.HasOne("HuTao.Data.Models.Discord.GuildEntity", null) + .WithMany("StickyMessages") + .HasForeignKey("GuildEntityId"); + + b.HasOne("HuTao.Data.Models.Discord.Message.Linking.MessageTemplate", "Template") + .WithMany() + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.TemporaryRole", b => + { + b.HasOne("HuTao.Data.Models.Moderation.Infractions.ModerationAction", "Action") + .WithMany() + .HasForeignKey("ActionId"); + + b.HasOne("HuTao.Data.Models.Discord.GuildEntity", null) + .WithMany("TemporaryRoles") + .HasForeignKey("GuildEntityId"); + + b.Navigation("Action"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.TemporaryRoleMember", b => + { + b.HasOne("HuTao.Data.Models.Moderation.Infractions.ModerationAction", "Action") + .WithMany() + .HasForeignKey("ActionId"); + + b.HasOne("HuTao.Data.Models.Discord.GuildEntity", null) + .WithMany("TemporaryRoleMembers") + .HasForeignKey("GuildEntityId"); + + b.HasOne("HuTao.Data.Models.Discord.GuildUserEntity", "User") + .WithMany() + .HasForeignKey("UserId", "GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Action"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Logging.DeleteLog", b => + { + b.HasOne("HuTao.Data.Models.Moderation.Infractions.ModerationAction", "Action") + .WithMany() + .HasForeignKey("ActionId"); + + b.HasOne("HuTao.Data.Models.Discord.GuildEntity", null) + .WithMany("DeleteLogs") + .HasForeignKey("GuildEntityId"); + + b.Navigation("Action"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Logging.LoggingRules", b => + { + b.HasOne("HuTao.Data.Models.Discord.GuildEntity", "Guild") + .WithOne("LoggingRules") + .HasForeignKey("HuTao.Data.Models.Logging.LoggingRules", "GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Guild"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Logging.MessageLog", b => + { + b.HasOne("HuTao.Data.Models.Discord.GuildEntity", "Guild") + .WithMany("MessageLogs") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("HuTao.Data.Models.Logging.MessageLog", "UpdatedLog") + .WithMany() + .HasForeignKey("UpdatedLogId"); + + b.HasOne("HuTao.Data.Models.Discord.GuildUserEntity", "User") + .WithMany() + .HasForeignKey("UserId", "GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Guild"); + + b.Navigation("UpdatedLog"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Logging.ReactionLog", b => + { + b.HasOne("HuTao.Data.Models.Discord.Reaction.ReactionEntity", "Emote") + .WithMany() + .HasForeignKey("EmoteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("HuTao.Data.Models.Discord.GuildEntity", "Guild") + .WithMany("ReactionLogs") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("HuTao.Data.Models.Discord.GuildUserEntity", "User") + .WithMany() + .HasForeignKey("UserId", "GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Emote"); + + b.Navigation("Guild"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Exclusions.ModerationExclusion", b => + { + b.HasOne("HuTao.Data.Models.Moderation.Auto.Configurations.AutoConfiguration", "Configuration") + .WithMany("Exclusions") + .HasForeignKey("ConfigurationId"); + + b.HasOne("HuTao.Data.Models.Moderation.ModerationRules", null) + .WithMany("Exclusions") + .HasForeignKey("ModerationRulesId"); + + b.Navigation("Configuration"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Actions.ModerationTemplate", b => + { + b.HasOne("HuTao.Data.Models.Moderation.Infractions.Actions.ReprimandAction", "Action") + .WithMany() + .HasForeignKey("ActionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("HuTao.Data.Models.Moderation.ModerationCategory", "Category") + .WithMany() + .HasForeignKey("CategoryId"); + + b.HasOne("HuTao.Data.Models.Discord.GuildEntity", null) + .WithMany("ModerationTemplates") + .HasForeignKey("GuildEntityId"); + + b.Navigation("Action"); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.ModerationAction", b => + { + b.HasOne("HuTao.Data.Models.Discord.GuildEntity", "Guild") + .WithMany() + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("HuTao.Data.Models.Discord.GuildUserEntity", "Moderator") + .WithMany() + .HasForeignKey("UserId", "GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Guild"); + + b.Navigation("Moderator"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Reprimands.Reprimand", b => + { + b.HasOne("HuTao.Data.Models.Moderation.Infractions.ModerationAction", "Action") + .WithMany() + .HasForeignKey("ActionId"); + + b.HasOne("HuTao.Data.Models.Moderation.ModerationCategory", "Category") + .WithMany() + .HasForeignKey("CategoryId"); + + b.HasOne("HuTao.Data.Models.Discord.GuildEntity", "Guild") + .WithMany("ReprimandHistory") + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("HuTao.Data.Models.Moderation.Infractions.ModerationAction", "ModifiedAction") + .WithMany() + .HasForeignKey("ModifiedActionId"); + + b.HasOne("HuTao.Data.Models.Moderation.Infractions.Triggers.Trigger", "Trigger") + .WithMany() + .HasForeignKey("TriggerId"); + + b.HasOne("HuTao.Data.Models.Discord.GuildUserEntity", "User") + .WithMany() + .HasForeignKey("UserId", "GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Action"); + + b.Navigation("Category"); + + b.Navigation("Guild"); + + b.Navigation("ModifiedAction"); + + b.Navigation("Trigger"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Triggers.Trigger", b => + { + b.HasOne("HuTao.Data.Models.Moderation.Infractions.ModerationAction", "Action") + .WithMany() + .HasForeignKey("ActionId"); + + b.HasOne("HuTao.Data.Models.Moderation.ModerationCategory", "Category") + .WithMany() + .HasForeignKey("CategoryId"); + + b.HasOne("HuTao.Data.Models.Moderation.ModerationRules", null) + .WithMany("Triggers") + .HasForeignKey("ModerationRulesId"); + + b.Navigation("Action"); + + b.Navigation("Category"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Logging.ModerationLoggingRules", b => + { + b.HasOne("HuTao.Data.Models.Moderation.Logging.ModerationLogConfig", "CommandLog") + .WithMany() + .HasForeignKey("CommandLogId"); + + b.HasOne("HuTao.Data.Models.Moderation.Logging.ModerationLogChannelConfig", "ModeratorLog") + .WithMany() + .HasForeignKey("ModeratorLogId"); + + b.HasOne("HuTao.Data.Models.Moderation.Logging.ModerationLogChannelConfig", "PublicLog") + .WithMany() + .HasForeignKey("PublicLogId"); + + b.HasOne("HuTao.Data.Models.Moderation.Logging.ModerationLogConfig", "UserLog") + .WithMany() + .HasForeignKey("UserLogId"); + + b.Navigation("CommandLog"); + + b.Navigation("ModeratorLog"); + + b.Navigation("PublicLog"); + + b.Navigation("UserLog"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.ModerationCategory", b => + { + b.HasOne("HuTao.Data.Models.Discord.GuildEntity", null) + .WithMany("ModerationCategories") + .HasForeignKey("GuildEntityId"); + + b.HasOne("HuTao.Data.Models.Moderation.Logging.ModerationLoggingRules", "Logging") + .WithMany() + .HasForeignKey("LoggingId"); + + b.Navigation("Logging"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.ModerationRules", b => + { + b.HasOne("HuTao.Data.Models.Moderation.Logging.ModerationLoggingRules", "Logging") + .WithMany() + .HasForeignKey("LoggingId"); + + b.Navigation("Logging"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.ModerationVariable", b => + { + b.HasOne("HuTao.Data.Models.Moderation.ModerationRules", null) + .WithMany("Variables") + .HasForeignKey("ModerationRulesId"); + }); + + modelBuilder.Entity("HuTao.Data.Models.TimeTracking.GenshinTimeTrackingRules", b => + { + b.HasOne("HuTao.Data.Models.TimeTracking.ChannelTimeTracking", "AmericaChannel") + .WithMany() + .HasForeignKey("AmericaChannelId"); + + b.HasOne("HuTao.Data.Models.TimeTracking.ChannelTimeTracking", "AsiaChannel") + .WithMany() + .HasForeignKey("AsiaChannelId"); + + b.HasOne("HuTao.Data.Models.TimeTracking.ChannelTimeTracking", "EuropeChannel") + .WithMany() + .HasForeignKey("EuropeChannelId"); + + b.HasOne("HuTao.Data.Models.TimeTracking.ChannelTimeTracking", "SARChannel") + .WithMany() + .HasForeignKey("SARChannelId"); + + b.HasOne("HuTao.Data.Models.TimeTracking.MessageTimeTracking", "ServerStatus") + .WithMany() + .HasForeignKey("ServerStatusId"); + + b.Navigation("AmericaChannel"); + + b.Navigation("AsiaChannel"); + + b.Navigation("EuropeChannel"); + + b.Navigation("SARChannel"); + + b.Navigation("ServerStatus"); + }); + + modelBuilder.Entity("HuTao.Data.Models.VoiceChat.VoiceChatLink", b => + { + b.HasOne("HuTao.Data.Models.Discord.GuildEntity", "Guild") + .WithMany() + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("HuTao.Data.Models.VoiceChat.VoiceChatRules", null) + .WithMany("VoiceChats") + .HasForeignKey("VoiceChatRulesId"); + + b.HasOne("HuTao.Data.Models.Discord.GuildUserEntity", "Owner") + .WithMany() + .HasForeignKey("UserId", "GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Guild"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("HuTao.Data.Models.VoiceChat.VoiceChatRules", b => + { + b.HasOne("HuTao.Data.Models.Discord.GuildEntity", "Guild") + .WithOne("VoiceChatRules") + .HasForeignKey("HuTao.Data.Models.VoiceChat.VoiceChatRules", "GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Guild"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.EnumChannel", b => + { + b.HasOne("HuTao.Data.Models.Logging.LoggingRules", null) + .WithMany("LoggingChannels") + .HasForeignKey("LoggingRulesId"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Logging.MessageDeleteLog", b => + { + b.HasOne("HuTao.Data.Models.Moderation.Infractions.Reprimands.Filtered", null) + .WithMany("Messages") + .HasForeignKey("FilteredId"); + + b.HasOne("HuTao.Data.Models.Logging.MessagesDeleteLog", null) + .WithMany("Messages") + .HasForeignKey("MessagesDeleteLogId"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Logging.ReactionDeleteLog", b => + { + b.HasOne("HuTao.Data.Models.Discord.Reaction.ReactionEntity", "Emote") + .WithMany() + .HasForeignKey("EmoteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Emote"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Configurations.AutoConfiguration", b => + { + b.HasOne("HuTao.Data.Models.Moderation.Infractions.Actions.ReprimandAction", "Reprimand") + .WithMany() + .HasForeignKey("ReprimandId"); + + b.Navigation("Reprimand"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Exclusions.CriterionExclusion", b => + { + b.HasOne("HuTao.Data.Models.Criteria.Criterion", "Criterion") + .WithMany() + .HasForeignKey("CriterionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Criterion"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Exclusions.EmojiExclusion", b => + { + b.HasOne("HuTao.Data.Models.Discord.Reaction.ReactionEntity", "Emoji") + .WithMany() + .HasForeignKey("EmojiId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Emoji"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Exclusions.InviteExclusion", b => + { + b.HasOne("HuTao.Data.Models.Discord.GuildEntity", "Guild") + .WithMany() + .HasForeignKey("GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Guild"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Exclusions.LinkExclusion", b => + { + b.HasOne("HuTao.Data.Models.Moderation.Auto.Configurations.Link", "Link") + .WithMany() + .HasForeignKey("LinkId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Link"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Exclusions.RoleMentionExclusion", b => + { + b.HasOne("HuTao.Data.Models.Discord.RoleEntity", "Role") + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Role"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Exclusions.UserMentionExclusion", b => + { + b.HasOne("HuTao.Data.Models.Discord.GuildUserEntity", "User") + .WithMany() + .HasForeignKey("UserId", "GuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Censors.Censor", b => + { + b.HasOne("HuTao.Data.Models.Moderation.Infractions.Actions.ReprimandAction", "Reprimand") + .WithMany() + .HasForeignKey("ReprimandId"); + + b.Navigation("Reprimand"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Triggers.ReprimandTrigger", b => + { + b.HasOne("HuTao.Data.Models.Moderation.Infractions.Actions.ReprimandAction", "Reprimand") + .WithMany() + .HasForeignKey("ReprimandId"); + + b.Navigation("Reprimand"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Authorization.AuthorizationGroup", b => + { + b.Navigation("Collection"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.GuildEntity", b => + { + b.Navigation("AuthorizationGroups"); + + b.Navigation("DeleteLogs"); + + b.Navigation("LinkedButtons"); + + b.Navigation("LinkedCommands"); + + b.Navigation("LoggingRules"); + + b.Navigation("MessageLogs"); + + b.Navigation("ModerationCategories"); + + b.Navigation("ModerationTemplates"); + + b.Navigation("ReactionLogs"); + + b.Navigation("ReprimandHistory"); + + b.Navigation("StickyMessages"); + + b.Navigation("TemporaryRoleMembers"); + + b.Navigation("TemporaryRoles"); + + b.Navigation("VoiceChatRules"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Components.ActionRow", b => + { + b.Navigation("Components"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Embeds.Embed", b => + { + b.Navigation("Fields"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Linking.LinkedButton", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Linking.LinkedCommand", b => + { + b.Navigation("Authorization"); + + b.Navigation("Roles"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Linking.MessageTemplate", b => + { + b.Navigation("Attachments"); + + b.Navigation("Components"); + + b.Navigation("Embeds"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Logging.LoggingRules", b => + { + b.Navigation("LoggingChannels"); + + b.Navigation("LoggingExclusions"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Logging.MessageLog", b => + { + b.Navigation("Attachments"); + + b.Navigation("Components"); + + b.Navigation("Embeds"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.ModerationCategory", b => + { + b.Navigation("Authorization"); + + b.Navigation("CensorExclusions"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.ModerationRules", b => + { + b.Navigation("CensorExclusions"); + + b.Navigation("Exclusions"); + + b.Navigation("Triggers"); + + b.Navigation("Variables"); + }); + + modelBuilder.Entity("HuTao.Data.Models.VoiceChat.VoiceChatRules", b => + { + b.Navigation("VoiceChats"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Components.Button", b => + { + b.Navigation("Link"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Discord.Message.Components.SelectMenu", b => + { + b.Navigation("Options"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Logging.MessagesDeleteLog", b => + { + b.Navigation("Messages"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Auto.Configurations.AutoConfiguration", b => + { + b.Navigation("Exclusions"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Actions.RoleAction", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Censors.Censor", b => + { + b.Navigation("Exclusions"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Reprimands.Filtered", b => + { + b.Navigation("Messages"); + }); + + modelBuilder.Entity("HuTao.Data.Models.Moderation.Infractions.Reprimands.RoleReprimand", b => + { + b.Navigation("Roles"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/HuTao.Data/Migrations/20220802004219_AddLoggingUploadAttachments.cs b/HuTao.Data/Migrations/20220802004219_AddLoggingUploadAttachments.cs new file mode 100644 index 0000000..18f6aef --- /dev/null +++ b/HuTao.Data/Migrations/20220802004219_AddLoggingUploadAttachments.cs @@ -0,0 +1,26 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace HuTao.Data.Migrations +{ + public partial class AddLoggingUploadAttachments : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "UploadAttachments", + table: "LoggingRules", + type: "boolean", + nullable: false, + defaultValue: false); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "UploadAttachments", + table: "LoggingRules"); + } + } +} diff --git a/HuTao.Data/Migrations/HuTaoContextModelSnapshot.cs b/HuTao.Data/Migrations/HuTaoContextModelSnapshot.cs index 2761bc3..2bd5d34 100644 --- a/HuTao.Data/Migrations/HuTaoContextModelSnapshot.cs +++ b/HuTao.Data/Migrations/HuTaoContextModelSnapshot.cs @@ -862,6 +862,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("GuildId") .HasColumnType("numeric(20,0)"); + b.Property("UploadAttachments") + .HasColumnType("boolean"); + b.HasKey("Id"); b.HasIndex("GuildId") diff --git a/HuTao.Data/Models/Logging/LoggingRules.cs b/HuTao.Data/Models/Logging/LoggingRules.cs index 7cb2edb..7e62cce 100644 --- a/HuTao.Data/Models/Logging/LoggingRules.cs +++ b/HuTao.Data/Models/Logging/LoggingRules.cs @@ -9,6 +9,8 @@ public class LoggingRules { public Guid Id { get; set; } + public bool UploadAttachments { get; set; } + public virtual GuildEntity Guild { get; set; } = null!; public virtual ICollection LoggingExclusions { get; set; } diff --git a/HuTao.Services/Logging/LoggingService.cs b/HuTao.Services/Logging/LoggingService.cs index 52c1116..91ed321 100644 --- a/HuTao.Services/Logging/LoggingService.cs +++ b/HuTao.Services/Logging/LoggingService.cs @@ -3,6 +3,7 @@ using System.IO; using System.Linq; using System.Linq.Expressions; +using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -24,26 +25,25 @@ using HuTao.Services.Utilities; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; +using static HuTao.Services.Utilities.EmbedBuilderOptions; using Attachment = HuTao.Data.Models.Discord.Message.Attachment; namespace HuTao.Services.Logging; public class LoggingService { - private const EmbedBuilderOptions LogEmbedOptions = - EmbedBuilderOptions.UseProxy | - EmbedBuilderOptions.EnlargeThumbnails | - EmbedBuilderOptions.ReplaceAnimations; - + private const EmbedBuilderOptions LogEmbedOptions = UseProxy | EnlargeThumbnails | ReplaceAnimations; private readonly DiscordSocketClient _client; + private readonly HttpClient _http; private readonly HuTaoContext _db; private readonly IMemoryCache _cache; - public LoggingService(DiscordSocketClient client, IMemoryCache cache, HuTaoContext db) + public LoggingService(DiscordSocketClient client, HttpClient http, HuTaoContext db, IMemoryCache cache) { _client = client; - _cache = cache; + _http = http; _db = db; + _cache = cache; } public async Task LogAsync(MessageReceivedNotification notification, CancellationToken cancellationToken) @@ -167,13 +167,14 @@ private IEnumerable GetLatestMessages(IGuildChannel channel, IEnumer .Where(m => messageIds.Contains(m.MessageId)) .OrderByDescending(m => m.LogDate); - private static MemoryStream GenerateStreamFromString(string value) - => new(Encoding.UTF8.GetBytes(value)); - - private async Task PublishLogAsync(DeleteDetails details, - CancellationToken cancellationToken) + private async Task PublishLogAsync(DeleteDetails details, CancellationToken cancellationToken) { - var embed = await BuildLogAsync(details); + var guildEntity = await _db.Guilds.TrackGuildAsync(details.Guild, cancellationToken); + var options = guildEntity.LoggingRules?.UploadAttachments is true + ? LogEmbedOptions | UploadAttachments + : LogEmbedOptions; + + var embed = await BuildLogAsync(details, options); var channel = await GetLoggingChannelAsync(details switch { MessageDeleteDetails => LogType.MessageDeleted, @@ -189,7 +190,7 @@ private async Task PublishLogAsync(ILog? log, LogType type, IGuild guild, Cancel { if (log is null) return; - var embed = await BuildLogAsync(log); + var embed = await BuildLogAsync(log, LogEmbedOptions); var channel = await GetLoggingChannelAsync(type, guild, cancellationToken); await PublishLogAsync(embed, channel); @@ -198,12 +199,7 @@ private async Task PublishLogAsync(ILog? log, LogType type, IGuild guild, Cancel private static async Task PublishLogAsync(EmbedLog? log, IMessageChannel? channel) { if (log is null || channel is null) return; - var (embeds, attachment) = log; - - if (attachment is null) - await channel.SendMessageAsync(embeds: embeds); - else - await channel.SendFileAsync(GenerateStreamFromString(attachment), "Messages.md", embeds: embeds); + await channel.SendFilesAsync(log.Attachments, embeds: log.Embeds.ToArray()); } private static async Task TryGetAuditLogDetails(IMessage? message, IGuild guild) @@ -266,10 +262,11 @@ private async Task AddDetailsAsync(EmbedBuilder embed, ILog log, IRead .AppendLine($"- Created: {log.LogDate} {log.LogDate.Humanize()}") .AppendLine($"- Message Count: {logs.Count}") .Append(await logs.GetDetailsAsync(_client)); - return new EmbedLog(embed, content.ToString()); + + return new EmbedLog(embed, content: content.ToString()); } - private async Task AddDetailsAsync(EmbedBuilder embed, MessageLog log) + private async Task AddDetailsAsync(EmbedBuilder embed, MessageLog log, EmbedBuilderOptions options) { var user = await GetUserAsync(log); @@ -298,14 +295,16 @@ private async Task AddDetailsAsync(EmbedBuilder embed, MessageLog log) embed.WithMessageReference(log, reply, replyUser); } - var attachments = log.Attachments.Chunk(4) - .SelectMany(attachments => attachments.ToEmbedBuilders(LogEmbedOptions)); - - var embeds = log.Embeds - .Where(e => e.IsViewable()) - .Select(e => e.ToBuilder(LogEmbedOptions)); + var attachments = log.Attachments.Chunk(4).SelectMany(attachments => attachments.ToEmbedBuilders(options)); + var embeds = log.Embeds.Where(e => e.IsViewable()).Select(e => e.ToBuilder(options)); + var files = options.HasFlag(UploadAttachments) + ? await log.Attachments.ToAsyncEnumerable() + .Select(a => (Url: options.HasFlag(UseProxy) ? a.ProxyUrl : a.Url, Name: a.Filename)) + .SelectAwait(async a => new FileAttachment(await _http.GetStreamAsync(a.Url), a.Name)) + .ToListAsync() + : Enumerable.Empty(); - return new EmbedLog(embed, attachments.Concat(embeds)); + return new EmbedLog(embed, attachments.Concat(embeds), attachments: files); } private async Task AddDetailsAsync(EmbedBuilder embed, T log) where T : ILog, IReactionEntity @@ -326,7 +325,7 @@ private async Task AddDetailsAsync(EmbedBuilder embed, T log) where return new EmbedLog(embed); } - private async Task BuildLogAsync(DeleteDetails details) + private async Task BuildLogAsync(DeleteDetails details, EmbedBuilderOptions options) { var log = details.Deleted; var embed = new EmbedBuilder() @@ -345,13 +344,13 @@ private async Task BuildLogAsync(DeleteDetails details) return details switch { MessagesDeleteDetails messages => await AddDetailsAsync(embed, messages.Log, messages.Messages), - MessageDeleteDetails message => await AddDetailsAsync(embed, message.Message), + MessageDeleteDetails message => await AddDetailsAsync(embed, message.Message, options), ReactionDeleteDetails reaction => await AddDetailsAsync(embed, reaction.Log), _ => throw new ArgumentOutOfRangeException(nameof(log), log, "Invalid log type.") }; } - private async Task BuildLogAsync(ILog log) + private async Task BuildLogAsync(ILog log, EmbedBuilderOptions options) { var embed = new EmbedBuilder() .WithTitle(log.GetTitle()) @@ -360,7 +359,7 @@ private async Task BuildLogAsync(ILog log) return log switch { - MessageLog message => await AddDetailsAsync(embed, message), + MessageLog message => await AddDetailsAsync(embed, message, options), ReactionLog reaction => await AddDetailsAsync(embed, reaction), _ => throw new ArgumentOutOfRangeException( nameof(log), log, "Invalid log type.") @@ -518,12 +517,20 @@ private record MessageDeleteDetails(MessageLog Message, DeleteLog Deleted, IGuil private record MessagesDeleteDetails(IReadOnlyCollection Messages, MessagesDeleteLog Log, IGuild Guild) : DeleteDetails(Log, Guild); - private record EmbedLog(Embed[] Embeds, string? Attachment = null) + private record EmbedLog(IEnumerable Embeds, IEnumerable Attachments) { - public EmbedLog(EmbedBuilder embed, string? attachment = null) - : this(new[] { embed.Build() }, attachment) { } + public EmbedLog( + EmbedBuilder embed, IEnumerable? embeds = null, string? content = null, + IEnumerable? attachments = null) : this( + (embeds?.Select(e => e.Build()) ?? Enumerable.Empty()).Prepend(embed.Build()), + attachments ?? Enumerable.Empty()) + { + if (!string.IsNullOrEmpty(content)) + Attachments = Attachments.Prepend(Attachment(content)).Take(10); + } + + private static FileAttachment Attachment(string content) => new(Stream(content), "messages.md"); - public EmbedLog(EmbedBuilder embed, IEnumerable embeds) - : this(new[] { embed.Build() }.Concat(embeds.Select(e => e.Build())).ToArray()) { } + private static MemoryStream Stream(string value) => new(Encoding.UTF8.GetBytes(value)); } } \ No newline at end of file diff --git a/HuTao.Services/Utilities/EmbedBuilderExtensions.cs b/HuTao.Services/Utilities/EmbedBuilderExtensions.cs index e588305..08cfcb2 100644 --- a/HuTao.Services/Utilities/EmbedBuilderExtensions.cs +++ b/HuTao.Services/Utilities/EmbedBuilderExtensions.cs @@ -30,15 +30,16 @@ public enum EmbedBuilderOptions UseProxy = 1 << 0, ReplaceTimestamps = 1 << 1, ReplaceAnimations = 1 << 2, - EnlargeThumbnails = 1 << 3 + EnlargeThumbnails = 1 << 3, + UploadAttachments = 1 << 4 } public static class EmbedBuilderExtensions { - private static readonly Regex Tenor = new(@"tenor\.com/(?\w+?)A+(\w+)/(?[\w-]+)", + private static readonly Regex Giphy = new(@"giphy\.com/media/(?\w+)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture); - private static readonly Regex Giphy = new(@"giphy\.com/media/(?\w+)", + private static readonly Regex Tenor = new(@"tenor\.com/(?\w+?)A+(\w+)/(?[\w-]+)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture); public static bool IsViewable(this Embed embed) @@ -122,12 +123,16 @@ public static IEnumerable ToEmbedBuilders( var description = string.Join(Environment.NewLine, attachments.Select(GetDetails)); var footer = string.Join(Environment.NewLine, attachments.Select(Footer)); - var url = attachments.First().ProxyUrl; + var url = options.HasFlag(UseProxy) ? attachments.First().ProxyUrl : attachments.First().Url; return attachments.Select(a => new EmbedBuilder() .WithUrl(url).WithDescription(description) .WithFooter(footer.Truncate(EmbedBuilder.MaxDescriptionLength)) - .WithImageUrl(options.HasFlag(UseProxy) ? a.ProxyUrl : a.Url)); + .WithImageUrl(options.HasFlag(UploadAttachments) + ? $"attachment://{a.Filename}" + : options.HasFlag(UseProxy) + ? a.ProxyUrl + : a.Url)); static string Footer(IAttachment i) => $"{i.Filename.Truncate(EmbedBuilder.MaxTitleLength)} {i.Width}x{i.Height}px {i.Size.Bytes().Humanize()}";