diff --git a/src/Mewdeko/Database/Extensions/DiscordUserExtensions.cs b/src/Mewdeko/Database/Extensions/DiscordUserExtensions.cs index d698dee30..5ebe476dc 100644 --- a/src/Mewdeko/Database/Extensions/DiscordUserExtensions.cs +++ b/src/Mewdeko/Database/Extensions/DiscordUserExtensions.cs @@ -21,19 +21,17 @@ public static async Task EnsureUserCreated( this MewdekoContext ctx, ulong userId, string username, - string discrim, string avatarId) { await ctx.DiscordUser.ToLinqToDBTable().InsertOrUpdateAsync(() => new DiscordUser { UserId = userId, Username = username, - Discriminator = discrim, AvatarId = avatarId, TotalXp = 0 }, old => new DiscordUser { - Username = username, Discriminator = discrim, AvatarId = avatarId + Username = username, AvatarId = avatarId }, () => new DiscordUser { UserId = userId @@ -53,10 +51,9 @@ public static async Task GetOrCreateUser( this MewdekoContext ctx, ulong userId, string username, - string discrim, string avatarId) { - await ctx.EnsureUserCreated(userId, username, discrim, avatarId); + await ctx.EnsureUserCreated(userId, username, avatarId); return await ctx.DiscordUser.FirstOrDefaultAsyncEF(u => u.UserId == userId) .ConfigureAwait(false); } @@ -69,7 +66,7 @@ public static async Task GetOrCreateUser( /// The Discord user entity. public static async Task GetOrCreateUser(this MewdekoContext ctx, IUser original) { - return await ctx.GetOrCreateUser(original.Id, original.Username, original.Discriminator, original.AvatarId); + return await ctx.GetOrCreateUser(original.Id, original.Username, original.AvatarId); } /// diff --git a/src/Mewdeko/Database/Migrations/PostgreSql/20241014004959_GreetDmOptout.Designer.cs b/src/Mewdeko/Database/Migrations/PostgreSql/20241014004959_GreetDmOptout.Designer.cs new file mode 100644 index 000000000..6332139ec --- /dev/null +++ b/src/Mewdeko/Database/Migrations/PostgreSql/20241014004959_GreetDmOptout.Designer.cs @@ -0,0 +1,4681 @@ +// +using System; +using Mewdeko.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace Mewdeko.Database.Migrations.PostgreSql +{ + [DbContext(typeof(MewdekoPostgresContext))] + [Migration("20241014004959_GreetDmOptout")] + partial class GreetDmOptout + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("Mewdeko.Database.Models.Afk", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.Property("WasTimed") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + b.HasKey("Id"); + + b.ToTable("AFK"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.AntiAltSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("integer"); + + b.Property("ActionDurationMinutes") + .HasColumnType("integer"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("MinAge") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("AntiAltSetting"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.AntiMassMentionSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("integer"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("IgnoreBots") + .HasColumnType("boolean"); + + b.Property("MaxMentionsInTimeWindow") + .HasColumnType("integer"); + + b.Property("MentionThreshold") + .HasColumnType("integer"); + + b.Property("MuteTime") + .HasColumnType("integer"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)"); + + b.Property("TimeWindowSeconds") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("AntiMassMentionSetting"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.AntiRaidSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("integer"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("PunishDuration") + .HasColumnType("integer"); + + b.Property("Seconds") + .HasColumnType("integer"); + + b.Property("UserThreshold") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("AntiRaidSetting"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.AntiSpamIgnore", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AntiMassMentionSettingId") + .HasColumnType("integer"); + + b.Property("AntiSpamSettingId") + .HasColumnType("integer"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.HasKey("Id"); + + b.HasIndex("AntiMassMentionSettingId"); + + b.HasIndex("AntiSpamSettingId"); + + b.ToTable("AntiSpamIgnore"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.AntiSpamSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("integer"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("MessageThreshold") + .HasColumnType("integer"); + + b.Property("MuteTime") + .HasColumnType("integer"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("AntiSpamSetting"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.AutoBanEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("Word") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("AutoBanWords"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.AutoBanRoles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("AutoBanRoles"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.AutoCommand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("ChannelName") + .HasColumnType("text"); + + b.Property("CommandText") + .HasColumnType("text"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("GuildName") + .HasColumnType("text"); + + b.Property("Interval") + .HasColumnType("integer"); + + b.Property("VoiceChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("VoiceChannelName") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("AutoCommands"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.AutoPublish", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BlacklistedUsers") + .HasColumnType("numeric(20,0)"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("AutoPublish"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("Text") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("BanTemplates"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.BlacklistEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("ItemId") + .HasColumnType("numeric(20,0)"); + + b.Property("Reason") + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Blacklist"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.BlacklistedPermission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("Permission") + .HasColumnType("numeric(20,0)"); + + b.Property("PunishmentAction") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("BlacklistedPermissions"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.BlacklistedRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("PunishmentAction") + .HasColumnType("integer"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("BlacklistedRoles"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.BotReviews", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AvatarUrl") + .IsRequired() + .HasColumnType("text"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("Review") + .IsRequired() + .HasColumnType("text"); + + b.Property("Stars") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.Property("Username") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("BotReviews"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.ChatTriggers", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AllowTarget") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("ApplicationCommandDescription") + .HasColumnType("text"); + + b.Property("ApplicationCommandId") + .HasColumnType("numeric(20,0)"); + + b.Property("ApplicationCommandName") + .HasColumnType("text"); + + b.Property("ApplicationCommandType") + .HasColumnType("integer"); + + b.Property("AutoDeleteTrigger") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("ContainsAnywhere") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("CrosspostingChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("CrosspostingWebhookUrl") + .HasColumnType("text"); + + b.Property("CustomPrefix") + .HasColumnType("text"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("DmResponse") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("EphemeralResponse") + .HasColumnType("boolean"); + + b.Property("GrantedRoles") + .HasColumnType("text"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("IsRegex") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("NoRespond") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("OwnerOnly") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("PrefixType") + .HasColumnType("integer"); + + b.Property("ReactToTrigger") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Reactions") + .HasColumnType("text"); + + b.Property("RemovedRoles") + .HasColumnType("text"); + + b.Property("Response") + .HasColumnType("text"); + + b.Property("RoleGrantType") + .HasColumnType("integer"); + + b.Property("Trigger") + .HasColumnType("text"); + + b.Property("UseCount") + .HasColumnType("numeric(20,0)"); + + b.Property("ValidTriggerTypes") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("ChatTriggers"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.CommandAlias", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("Mapping") + .HasColumnType("text"); + + b.Property("Trigger") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("CommandAlias"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.CommandCooldown", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CommandName") + .HasColumnType("text"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("Seconds") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("CommandCooldown"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.CommandStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("IsSlash") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Module") + .ValueGeneratedOnAdd() + .HasColumnType("text") + .HasDefaultValue(""); + + b.Property("NameOrId") + .HasColumnType("text"); + + b.Property("Trigger") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("CommandStats"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.Confessions", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("ConfessNumber") + .HasColumnType("numeric(20,0)"); + + b.Property("Confession") + .HasColumnType("text"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("Confessions"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.DelMsgOnCmdChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("State") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("DelMsgOnCmdChannel"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.DiscordPermOverride", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Command") + .HasColumnType("text"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("Perm") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "Command") + .IsUnique(); + + b.ToTable("DiscordPermOverrides"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.DiscordUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AvatarId") + .HasColumnType("text"); + + b.Property("Bio") + .HasColumnType("text"); + + b.Property("Birthday") + .HasColumnType("timestamp without time zone"); + + b.Property("BirthdayDisplayMode") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("Discriminator") + .HasColumnType("text"); + + b.Property("GreetDmsOptOut") + .HasColumnType("boolean"); + + b.Property("IsClubAdmin") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("IsDragon") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("LastLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp without time zone") + .HasDefaultValue(new DateTime(2017, 9, 21, 20, 53, 13, 305, DateTimeKind.Local)); + + b.Property("NotifyOnLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("ProfileColor") + .HasColumnType("bigint"); + + b.Property("ProfileImageUrl") + .HasColumnType("text"); + + b.Property("ProfilePrivacy") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("Pronouns") + .HasColumnType("text"); + + b.Property("PronounsClearedReason") + .HasColumnType("text"); + + b.Property("PronounsDisabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("StatsOptOut") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("SwitchFriendCode") + .HasColumnType("text"); + + b.Property("TotalXp") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.Property("Username") + .HasColumnType("text"); + + b.Property("ZodiacSign") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasAlternateKey("UserId"); + + b.HasIndex("TotalXp"); + + b.HasIndex("UserId"); + + b.ToTable("DiscordUser"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.ExcludedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("ItemId") + .HasColumnType("numeric(20,0)"); + + b.Property("ItemType") + .HasColumnType("integer"); + + b.Property("XpSettingsId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId"); + + b.ToTable("ExcludedItem"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.FeedSub", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("Url") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasAlternateKey("GuildConfigId", "Url"); + + b.ToTable("FeedSub"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.FilterInvitesChannelIds", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilterInvitesChannelIds"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.FilterLinksChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilterLinksChannelId"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.FilterWordsChannelIds", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilterWordsChannelIds"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.FilteredWord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("Word") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilteredWord"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.FollowedStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("integer"); + + b.Property("Username") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FollowedStream"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.GiveawayUsers", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GiveawayId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("GiveawayUsers"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.Giveaways", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BlacklistRoles") + .HasColumnType("text"); + + b.Property("BlacklistUsers") + .HasColumnType("text"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("Emote") + .HasColumnType("text"); + + b.Property("Ended") + .HasColumnType("integer"); + + b.Property("Item") + .HasColumnType("text"); + + b.Property("MessageCountReq") + .HasColumnType("numeric(20,0)"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)"); + + b.Property("RestrictTo") + .HasColumnType("text"); + + b.Property("ServerId") + .HasColumnType("numeric(20,0)"); + + b.Property("UseButton") + .HasColumnType("boolean"); + + b.Property("UseCaptcha") + .HasColumnType("boolean"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + b.Property("Winners") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Giveaways"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.GlobalUserBalance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Balance") + .HasColumnType("bigint"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("GlobalUserBalance"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.GroupName", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Number") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId", "Number") + .IsUnique(); + + b.ToTable("GroupName"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.GuildConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AcceptChannel") + .HasColumnType("numeric(20,0)"); + + b.Property("AcceptMessage") + .HasColumnType("text"); + + b.Property("AfkDel") + .HasColumnType("text"); + + b.Property("AfkDisabledChannels") + .HasColumnType("text"); + + b.Property("AfkLength") + .HasColumnType("integer"); + + b.Property("AfkMessage") + .HasColumnType("text"); + + b.Property("AfkTimeout") + .HasColumnType("integer"); + + b.Property("AfkType") + .HasColumnType("integer"); + + b.Property("ArchiveOnAccept") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("ArchiveOnConsider") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("ArchiveOnDeny") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("ArchiveOnImplement") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("AutoAssignRoleId") + .HasColumnType("text"); + + b.Property("AutoBotRoleIds") + .HasColumnType("text"); + + b.Property("AutoDeleteByeMessages") + .HasColumnType("boolean"); + + b.Property("AutoDeleteByeMessagesTimer") + .HasColumnType("integer"); + + b.Property("AutoDeleteGreetMessages") + .HasColumnType("boolean"); + + b.Property("AutoDeleteGreetMessagesTimer") + .HasColumnType("integer"); + + b.Property("AutoDeleteSelfAssignedRoleMessages") + .HasColumnType("boolean"); + + b.Property("BoostMessage") + .HasColumnType("text"); + + b.Property("BoostMessageChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("BoostMessageDeleteAfter") + .HasColumnType("integer"); + + b.Property("ButtonRepostThreshold") + .HasColumnType("integer"); + + b.Property("ByeMessageChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("ChannelByeMessageText") + .HasColumnType("text"); + + b.Property("ChannelGreetMessageText") + .HasColumnType("text"); + + b.Property("CleverbotChannel") + .HasColumnType("numeric(20,0)"); + + b.Property("CommandLogChannel") + .HasColumnType("numeric(20,0)"); + + b.Property("ConfessionBlacklist") + .HasColumnType("text"); + + b.Property("ConfessionChannel") + .HasColumnType("numeric(20,0)"); + + b.Property("ConfessionLogChannel") + .HasColumnType("numeric(20,0)"); + + b.Property("ConsiderChannel") + .HasColumnType("numeric(20,0)"); + + b.Property("ConsiderMessage") + .HasColumnType("text"); + + b.Property("CurrencyEmoji") + .HasColumnType("text"); + + b.Property("CurrencyName") + .HasColumnType("text"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("DeleteMessageOnCommand") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("DenyChannel") + .HasColumnType("numeric(20,0)"); + + b.Property("DenyMessage") + .HasColumnType("text"); + + b.Property("DmGreetMessageText") + .HasColumnType("text"); + + b.Property("DmOnGiveawayWin") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("Emote1Style") + .HasColumnType("integer"); + + b.Property("Emote2Style") + .HasColumnType("integer"); + + b.Property("Emote3Style") + .HasColumnType("integer"); + + b.Property("Emote4Style") + .HasColumnType("integer"); + + b.Property("Emote5Style") + .HasColumnType("integer"); + + b.Property("EmoteMode") + .HasColumnType("integer"); + + b.Property("ExclusiveSelfAssignedRoles") + .HasColumnType("boolean"); + + b.Property("FilterInvites") + .HasColumnType("boolean"); + + b.Property("FilterLinks") + .HasColumnType("boolean"); + + b.Property("FilterWords") + .HasColumnType("boolean"); + + b.Property("GBAction") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("GBEnabled") + .HasColumnType("integer"); + + b.Property("GEndMessage") + .HasColumnType("text"); + + b.Property("GRolesBlacklist") + .HasColumnType("text"); + + b.Property("GStartMessage") + .HasColumnType("text"); + + b.Property("GUsersBlacklist") + .HasColumnType("text"); + + b.Property("GWinMessage") + .HasColumnType("text"); + + b.Property("GameMasterRole") + .HasColumnType("numeric(20,0)"); + + b.Property("GameVoiceChannel") + .HasColumnType("numeric(20,0)"); + + b.Property("GiveawayBanner") + .HasColumnType("text"); + + b.Property("GiveawayEmbedColor") + .HasColumnType("text"); + + b.Property("GiveawayEmote") + .HasColumnType("text"); + + b.Property("GiveawayEndMessage") + .HasColumnType("text"); + + b.Property("GiveawayPingRole") + .HasColumnType("numeric(20,0)"); + + b.Property("GiveawayWinEmbedColor") + .HasColumnType("text"); + + b.Property("GreetHook") + .HasColumnType("text"); + + b.Property("GreetMessageChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("ImplementChannel") + .HasColumnType("numeric(20,0)"); + + b.Property("ImplementMessage") + .HasColumnType("text"); + + b.Property("JoinGraphColor") + .HasColumnType("bigint"); + + b.Property("Joins") + .HasColumnType("numeric(20,0)"); + + b.Property("LeaveGraphColor") + .HasColumnType("bigint"); + + b.Property("LeaveHook") + .HasColumnType("text"); + + b.Property("Leaves") + .HasColumnType("numeric(20,0)"); + + b.Property("Locale") + .HasColumnType("text"); + + b.Property("LogSettingId") + .HasColumnType("integer"); + + b.Property("MaxSuggestLength") + .HasColumnType("integer"); + + b.Property("MemberRole") + .HasColumnType("numeric(20,0)"); + + b.Property("MinMessageLength") + .HasColumnType("integer"); + + b.Property("MinSuggestLength") + .HasColumnType("integer"); + + b.Property("MiniWarnlogChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("MultiGreetType") + .HasColumnType("integer"); + + b.Property("MuteRoleName") + .HasColumnType("text"); + + b.Property("NotifyStreamOffline") + .HasColumnType("boolean"); + + b.Property("PermissionRole") + .HasColumnType("text"); + + b.Property("Prefix") + .HasColumnType("text"); + + b.Property("PreviewLinks") + .HasColumnType("integer"); + + b.Property("ReactChannel") + .HasColumnType("numeric(20,0)"); + + b.Property("RepostThreshold") + .HasColumnType("integer"); + + b.Property("RewardAmount") + .HasColumnType("integer"); + + b.Property("RewardTimeoutSeconds") + .HasColumnType("integer"); + + b.Property("SendBoostMessage") + .HasColumnType("boolean"); + + b.Property("SendChannelByeMessage") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("SendChannelGreetMessage") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("SendDmGreetMessage") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("StaffRole") + .HasColumnType("numeric(20,0)"); + + b.Property("Star2") + .HasColumnType("text"); + + b.Property("StarboardAllowBots") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("StarboardChannel") + .HasColumnType("numeric(20,0)"); + + b.Property("StarboardCheckChannels") + .HasColumnType("text"); + + b.Property("StarboardRemoveOnBelowThreshold") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("StarboardRemoveOnDelete") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("StarboardRemoveOnReactionsClear") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("Stars") + .HasColumnType("integer"); + + b.Property("StatsOptOut") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("SuggestButtonChannel") + .HasColumnType("numeric(20,0)"); + + b.Property("SuggestButtonColor") + .HasColumnType("integer"); + + b.Property("SuggestButtonEmote") + .HasColumnType("text"); + + b.Property("SuggestButtonMessage") + .HasColumnType("text"); + + b.Property("SuggestButtonMessageId") + .HasColumnType("numeric(20,0)"); + + b.Property("SuggestButtonName") + .HasColumnType("text"); + + b.Property("SuggestButtonRepostThreshold") + .HasColumnType("integer"); + + b.Property("SuggestCommandsType") + .HasColumnType("integer"); + + b.Property("SuggestEmotes") + .HasColumnType("text"); + + b.Property("SuggestMessage") + .HasColumnType("text"); + + b.Property("SuggestionThreadType") + .HasColumnType("integer"); + + b.Property("TOpenMessage") + .HasColumnType("text"); + + b.Property("TicketCategory") + .HasColumnType("numeric(20,0)"); + + b.Property("TicketChannel") + .HasColumnType("numeric(20,0)"); + + b.Property("TimeZoneId") + .HasColumnType("text"); + + b.Property("UseMessageCount") + .HasColumnType("boolean"); + + b.Property("UseStarboardBlacklist") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true); + + b.Property("VerboseErrors") + .HasColumnType("boolean"); + + b.Property("VerbosePermissions") + .HasColumnType("boolean"); + + b.Property("VoteEmbed") + .HasColumnType("text"); + + b.Property("VotesChannel") + .HasColumnType("numeric(20,0)"); + + b.Property("VotesPassword") + .HasColumnType("text"); + + b.Property("WarnExpireAction") + .HasColumnType("integer"); + + b.Property("WarnExpireHours") + .HasColumnType("integer"); + + b.Property("WarnMessage") + .HasColumnType("text"); + + b.Property("WarningsInitialized") + .HasColumnType("boolean"); + + b.Property("WarnlogChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("XpImgUrl") + .HasColumnType("text"); + + b.Property("XpTxtRate") + .HasColumnType("integer"); + + b.Property("XpTxtTimeout") + .HasColumnType("integer"); + + b.Property("XpVoiceRate") + .HasColumnType("integer"); + + b.Property("XpVoiceTimeout") + .HasColumnType("integer"); + + b.Property("fwarn") + .HasColumnType("integer"); + + b.Property("invwarn") + .HasColumnType("integer"); + + b.Property("removeroles") + .HasColumnType("integer"); + + b.Property("snipeset") + .HasColumnType("boolean"); + + b.Property("sugchan") + .HasColumnType("numeric(20,0)"); + + b.Property("sugnum") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.HasIndex("LogSettingId"); + + b.HasIndex("WarnExpireHours"); + + b.ToTable("GuildConfigs"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.GuildUserBalance", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Balance") + .HasColumnType("bigint"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("GuildUserBalance"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.HighlightSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("HighlightsOn") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("IgnoredChannels") + .HasColumnType("text"); + + b.Property("IgnoredUsers") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("HighlightSettings"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.Highlights", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.Property("Word") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Highlights"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.IgnoredLogChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("LogSettingId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("LogSettingId"); + + b.ToTable("IgnoredLogChannels"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.InviteCount", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Count") + .HasColumnType("integer"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("InviteCounts"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.InviteCountSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("MinAccountAge") + .HasColumnType("interval"); + + b.Property("RemoveInviteOnLeave") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.ToTable("InviteCountSettings"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.InvitedBy", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("InviterId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("InvitedBy"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.JoinLeaveLogs", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("IsJoin") + .HasColumnType("boolean"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("JoinLeaveLogs"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.LocalBotInstances", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BotUrl") + .IsRequired() + .HasColumnType("text"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.HasKey("Id"); + + b.ToTable("BotInstances"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.LockdownChannelPermissions", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AllowPermissions") + .HasColumnType("numeric(20,0)"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("DenyPermissions") + .HasColumnType("numeric(20,0)"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("TargetId") + .HasColumnType("numeric(20,0)"); + + b.Property("TargetType") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("LockdownChannelPermissions"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.LogSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AvatarUpdatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("ChannelCreated") + .HasColumnType("bigint"); + + b.Property("ChannelCreatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("ChannelDestroyed") + .HasColumnType("bigint"); + + b.Property("ChannelDestroyedId") + .HasColumnType("numeric(20,0)"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("ChannelUpdated") + .HasColumnType("bigint"); + + b.Property("ChannelUpdatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("EventCreatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("IsLogging") + .HasColumnType("bigint"); + + b.Property("LogOtherId") + .HasColumnType("numeric(20,0)"); + + b.Property("LogUserPresence") + .HasColumnType("bigint"); + + b.Property("LogUserPresenceId") + .HasColumnType("numeric(20,0)"); + + b.Property("LogVoicePresence") + .HasColumnType("bigint"); + + b.Property("LogVoicePresenceId") + .HasColumnType("numeric(20,0)"); + + b.Property("LogVoicePresenceTTSId") + .HasColumnType("numeric(20,0)"); + + b.Property("MessageDeleted") + .HasColumnType("bigint"); + + b.Property("MessageDeletedId") + .HasColumnType("numeric(20,0)"); + + b.Property("MessageUpdated") + .HasColumnType("bigint"); + + b.Property("MessageUpdatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("NicknameUpdatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("RoleCreatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("RoleDeletedId") + .HasColumnType("numeric(20,0)"); + + b.Property("RoleUpdatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("ServerUpdatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("ThreadCreatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("ThreadDeletedId") + .HasColumnType("numeric(20,0)"); + + b.Property("ThreadUpdatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserBanned") + .HasColumnType("bigint"); + + b.Property("UserBannedId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserJoined") + .HasColumnType("bigint"); + + b.Property("UserJoinedId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserLeft") + .HasColumnType("bigint"); + + b.Property("UserLeftId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserMutedId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserPresenceChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserRoleAddedId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserRoleRemovedId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserUnbanned") + .HasColumnType("bigint"); + + b.Property("UserUnbannedId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserUpdated") + .HasColumnType("bigint"); + + b.Property("UserUpdatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("UsernameUpdatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("VoicePresenceChannelId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("LogSettings"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.LoggingV2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AvatarUpdatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("ChannelCreatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("ChannelDestroyedId") + .HasColumnType("numeric(20,0)"); + + b.Property("ChannelUpdatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("EventCreatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("LogOtherId") + .HasColumnType("numeric(20,0)"); + + b.Property("LogUserPresenceId") + .HasColumnType("numeric(20,0)"); + + b.Property("LogVoicePresenceId") + .HasColumnType("numeric(20,0)"); + + b.Property("LogVoicePresenceTTSId") + .HasColumnType("numeric(20,0)"); + + b.Property("MessageDeletedId") + .HasColumnType("numeric(20,0)"); + + b.Property("MessageUpdatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("NicknameUpdatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("RoleCreatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("RoleDeletedId") + .HasColumnType("numeric(20,0)"); + + b.Property("RoleUpdatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("ServerUpdatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("ThreadCreatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("ThreadDeletedId") + .HasColumnType("numeric(20,0)"); + + b.Property("ThreadUpdatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserBannedId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserJoinedId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserLeftId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserMutedId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserRoleAddedId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserRoleRemovedId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserUnbannedId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserUpdatedId") + .HasColumnType("numeric(20,0)"); + + b.Property("UsernameUpdatedId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("LoggingV2"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.MessageCount", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("Count") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("RecentTimestamps") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("MessageCounts"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.MultiGreet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("DeleteTime") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(1); + + b.Property("Disabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("GreetBots") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("WebhookUrl") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("MultiGreets"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.MusicPlayerSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoDisconnect") + .HasColumnType("integer"); + + b.Property("AutoPlay") + .HasColumnType("integer"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("MusicChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("PlayerRepeat") + .HasColumnType("integer"); + + b.Property("Volume") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(100); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("MusicPlayerSettings"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.MusicPlaylist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Author") + .HasColumnType("text"); + + b.Property("AuthorId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("IsDefault") + .HasColumnType("boolean"); + + b.Property("Name") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("MusicPlaylists"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.MutedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.Property("roles") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("MutedUserId"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.NsfwBlacklitedTag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("Tag") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("NsfwBlacklitedTag"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.OwnerOnly", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CurrencyEmote") + .HasColumnType("text"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GptTokensUsed") + .HasColumnType("integer"); + + b.Property("Owners") + .HasColumnType("text"); + + b.Property("RewardAmount") + .HasColumnType("integer"); + + b.Property("RewardTimeoutSeconds") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("OwnerOnly"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.Permission", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("NextId") + .HasColumnType("integer"); + + b.Property("PrimaryTarget") + .HasColumnType("integer"); + + b.Property("PrimaryTargetId") + .HasColumnType("numeric(20,0)"); + + b.Property("SecondaryTarget") + .HasColumnType("integer"); + + b.Property("SecondaryTargetName") + .HasColumnType("text"); + + b.Property("State") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("NextId") + .IsUnique(); + + b.ToTable("Permission"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.Permissionv2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("Index") + .HasColumnType("integer"); + + b.Property("IsCustomCommand") + .HasColumnType("boolean"); + + b.Property("PrimaryTarget") + .HasColumnType("integer"); + + b.Property("PrimaryTargetId") + .HasColumnType("numeric(20,0)"); + + b.Property("SecondaryTarget") + .HasColumnType("integer"); + + b.Property("SecondaryTargetName") + .HasColumnType("text"); + + b.Property("State") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("Permissionv2"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.PlaylistSong", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("MusicPlaylistId") + .HasColumnType("integer"); + + b.Property("Provider") + .HasColumnType("text"); + + b.Property("ProviderType") + .HasColumnType("integer"); + + b.Property("Query") + .HasColumnType("text"); + + b.Property("Title") + .HasColumnType("text"); + + b.Property("Uri") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("MusicPlaylistId"); + + b.ToTable("PlaylistSong"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.PollAnswers", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("Index") + .HasColumnType("integer"); + + b.Property("PollsId") + .HasColumnType("integer"); + + b.Property("Text") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("PollsId"); + + b.ToTable("PollAnswer"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.PollVote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("PollId") + .HasColumnType("integer"); + + b.Property("PollsId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.Property("VoteIndex") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("PollsId"); + + b.ToTable("PollVote"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.Polls", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("PollType") + .HasColumnType("integer"); + + b.Property("Question") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("Poll"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.PublishUserBlacklist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("User") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("PublishUserBlacklist"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.PublishWordBlacklist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("Word") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("PublishWordBlacklist"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.Quote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .HasColumnType("numeric(20,0)"); + + b.Property("AuthorName") + .IsRequired() + .HasColumnType("text"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("Keyword") + .IsRequired() + .HasColumnType("text"); + + b.Property("Text") + .IsRequired() + .HasColumnType("text"); + + b.Property("UseCount") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.HasIndex("Keyword"); + + b.ToTable("Quotes"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.ReactionRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("EmoteName") + .HasColumnType("text"); + + b.Property("ReactionRoleMessageId") + .HasColumnType("integer"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("ReactionRoleMessageId"); + + b.ToTable("ReactionRole"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.ReactionRoleMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("Exclusive") + .HasColumnType("boolean"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("Index") + .HasColumnType("integer"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("ReactionRoleMessage"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.Reminder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("IsPrivate") + .HasColumnType("boolean"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("ServerId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.Property("When") + .HasColumnType("timestamp without time zone"); + + b.HasKey("Id"); + + b.HasIndex("When"); + + b.ToTable("Reminders"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.Repeater", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("Interval") + .HasColumnType("text"); + + b.Property("LastMessageId") + .HasColumnType("numeric(20,0)"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("NoRedundant") + .HasColumnType("boolean"); + + b.Property("StartTimeOfDay") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("GuildRepeater"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.RoleConnectionAuthStorage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("ExpiresAt") + .HasColumnType("timestamp without time zone"); + + b.Property("RefreshToken") + .HasColumnType("text"); + + b.Property("Scopes") + .HasColumnType("text"); + + b.Property("Token") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("AuthCodes"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.RoleGreet", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("DeleteTime") + .HasColumnType("integer"); + + b.Property("Disabled") + .HasColumnType("boolean"); + + b.Property("GreetBots") + .HasColumnType("boolean"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("Message") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)"); + + b.Property("WebhookUrl") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("RoleGreets"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.RoleMonitoringSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("DefaultPunishmentAction") + .HasColumnType("integer"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("RoleMonitoringSettings"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.RoleStateSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClearOnBan") + .HasColumnType("boolean"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("DeniedRoles") + .HasColumnType("text"); + + b.Property("DeniedUsers") + .HasColumnType("text"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("IgnoreBots") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.ToTable("RoleStateSettings"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.RotatingPlayingStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("Type") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("RotatingStatus"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.SelfAssignedRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("Group") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("LevelRequirement") + .HasColumnType("integer"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "RoleId") + .IsUnique(); + + b.ToTable("SelfAssignableRoles"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.ServerRecoveryStore", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("RecoveryKey") + .HasColumnType("text"); + + b.Property("TwoFactorKey") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("ServerRecoveryStore"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.StarboardPosts", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)"); + + b.Property("PostId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("Starboard"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.StatusRolesTable", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("ReaddRemoved") + .HasColumnType("boolean"); + + b.Property("RemoveAdded") + .HasColumnType("boolean"); + + b.Property("Status") + .HasColumnType("text"); + + b.Property("StatusChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("StatusEmbed") + .HasColumnType("text"); + + b.Property("ToAdd") + .HasColumnType("text"); + + b.Property("ToRemove") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("StatusRoles"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.StreamRoleBlacklistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.Property("Username") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("StreamRoleSettingsId"); + + b.ToTable("StreamRoleBlacklistedUser"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.StreamRoleSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AddRoleId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("Enabled") + .HasColumnType("boolean"); + + b.Property("FromRoleId") + .HasColumnType("numeric(20,0)"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("Keyword") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("StreamRoleSettings"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.StreamRoleWhitelistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.Property("Username") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("StreamRoleSettingsId"); + + b.ToTable("StreamRoleWhitelistedUser"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.SuggestThreads", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)"); + + b.Property("ThreadChannelId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("SuggestThreads"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.SuggestVotes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("EmotePicked") + .HasColumnType("integer"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("SuggestVotes"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.SuggestionsModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CurrentState") + .HasColumnType("integer"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("EmoteCount1") + .HasColumnType("integer"); + + b.Property("EmoteCount2") + .HasColumnType("integer"); + + b.Property("EmoteCount3") + .HasColumnType("integer"); + + b.Property("EmoteCount4") + .HasColumnType("integer"); + + b.Property("EmoteCount5") + .HasColumnType("integer"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)"); + + b.Property("StateChangeCount") + .HasColumnType("numeric(20,0)"); + + b.Property("StateChangeMessageId") + .HasColumnType("numeric(20,0)"); + + b.Property("StateChangeUser") + .HasColumnType("numeric(20,0)"); + + b.Property("Suggestion") + .HasColumnType("text"); + + b.Property("SuggestionId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("Suggestions"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.Template", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AwardedColor") + .HasColumnType("text"); + + b.Property("AwardedFontSize") + .HasColumnType("integer"); + + b.Property("AwardedX") + .HasColumnType("integer"); + + b.Property("AwardedY") + .HasColumnType("integer"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("OutputSizeX") + .HasColumnType("integer"); + + b.Property("OutputSizeY") + .HasColumnType("integer"); + + b.Property("ShowAwarded") + .HasColumnType("boolean"); + + b.Property("ShowTimeOnLevel") + .HasColumnType("boolean"); + + b.Property("TemplateBarId") + .HasColumnType("integer"); + + b.Property("TemplateClubId") + .HasColumnType("integer"); + + b.Property("TemplateGuildId") + .HasColumnType("integer"); + + b.Property("TemplateUserId") + .HasColumnType("integer"); + + b.Property("TimeOnLevelColor") + .HasColumnType("text"); + + b.Property("TimeOnLevelFontSize") + .HasColumnType("integer"); + + b.Property("TimeOnLevelFormat") + .HasColumnType("text"); + + b.Property("TimeOnLevelX") + .HasColumnType("integer"); + + b.Property("TimeOnLevelY") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("TemplateBarId"); + + b.HasIndex("TemplateClubId"); + + b.HasIndex("TemplateGuildId"); + + b.HasIndex("TemplateUserId"); + + b.ToTable("Template"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.TemplateBar", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BarColor") + .HasColumnType("text"); + + b.Property("BarDirection") + .HasColumnType("integer"); + + b.Property("BarLength") + .HasColumnType("integer"); + + b.Property("BarPointAx") + .HasColumnType("integer"); + + b.Property("BarPointAy") + .HasColumnType("integer"); + + b.Property("BarPointBx") + .HasColumnType("integer"); + + b.Property("BarPointBy") + .HasColumnType("integer"); + + b.Property("BarTransparency") + .HasColumnType("smallint"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("ShowBar") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.ToTable("TemplateBar"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.TemplateClub", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClubIconSizeX") + .HasColumnType("integer"); + + b.Property("ClubIconSizeY") + .HasColumnType("integer"); + + b.Property("ClubIconX") + .HasColumnType("integer"); + + b.Property("ClubIconY") + .HasColumnType("integer"); + + b.Property("ClubNameColor") + .HasColumnType("text"); + + b.Property("ClubNameFontSize") + .HasColumnType("integer"); + + b.Property("ClubNameX") + .HasColumnType("integer"); + + b.Property("ClubNameY") + .HasColumnType("integer"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("ShowClubIcon") + .HasColumnType("boolean"); + + b.Property("ShowClubName") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.ToTable("TemplateClub"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.TemplateGuild", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildLevelColor") + .HasColumnType("text"); + + b.Property("GuildLevelFontSize") + .HasColumnType("integer"); + + b.Property("GuildLevelX") + .HasColumnType("integer"); + + b.Property("GuildLevelY") + .HasColumnType("integer"); + + b.Property("GuildRankColor") + .HasColumnType("text"); + + b.Property("GuildRankFontSize") + .HasColumnType("integer"); + + b.Property("GuildRankX") + .HasColumnType("integer"); + + b.Property("GuildRankY") + .HasColumnType("integer"); + + b.Property("ShowGuildLevel") + .HasColumnType("boolean"); + + b.Property("ShowGuildRank") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.ToTable("TemplateGuild"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.TemplateUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("FontSize") + .HasColumnType("integer"); + + b.Property("IconSizeX") + .HasColumnType("integer"); + + b.Property("IconSizeY") + .HasColumnType("integer"); + + b.Property("IconX") + .HasColumnType("integer"); + + b.Property("IconY") + .HasColumnType("integer"); + + b.Property("ShowIcon") + .HasColumnType("boolean"); + + b.Property("ShowText") + .HasColumnType("boolean"); + + b.Property("TextColor") + .HasColumnType("text"); + + b.Property("TextX") + .HasColumnType("integer"); + + b.Property("TextY") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("TemplateUser"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.TransactionHistory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Amount") + .HasColumnType("bigint"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("TransactionHistory"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.UnbanTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("UnbanAt") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("UnbanTimer"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.UnmuteTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("UnmuteAt") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("UnmuteTimer"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.UnroleTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)"); + + b.Property("UnbanAt") + .HasColumnType("timestamp without time zone"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("UnroleTimer"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.UserRoleStates", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("SavedRoles") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserName") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("UserRoleStates"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.UserXpStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AwardedXp") + .HasColumnType("integer"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("LastLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("timestamp without time zone") + .HasDefaultValue(new DateTime(2017, 9, 21, 20, 53, 13, 307, DateTimeKind.Local)); + + b.Property("NotifyOnLevelUp") + .HasColumnType("integer"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.Property("Xp") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("AwardedXp"); + + b.HasIndex("GuildId"); + + b.HasIndex("UserId"); + + b.HasIndex("Xp"); + + b.HasIndex("UserId", "GuildId") + .IsUnique(); + + b.ToTable("UserXpStats"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.VcRoleInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)"); + + b.Property("VoiceChannelId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("VcRoleInfo"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.VoteRoles", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)"); + + b.Property("Timer") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("VoteRoles"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.Votes", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("BotId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("Votes"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.Warning", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("Forgiven") + .HasColumnType("boolean"); + + b.Property("ForgivenBy") + .HasColumnType("text"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("Moderator") + .HasColumnType("text"); + + b.Property("Reason") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.HasIndex("DateAdded"); + + b.HasIndex("GuildId"); + + b.HasIndex("UserId"); + + b.ToTable("Warnings"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.Warning2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("Forgiven") + .HasColumnType("boolean"); + + b.Property("ForgivenBy") + .HasColumnType("text"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("Moderator") + .HasColumnType("text"); + + b.Property("Reason") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("Warnings2"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.WarningPunishment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Count") + .HasColumnType("integer"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("Punishment") + .HasColumnType("integer"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)"); + + b.Property("Time") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("WarningPunishment"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.WarningPunishment2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Count") + .HasColumnType("integer"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("Punishment") + .HasColumnType("integer"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)"); + + b.Property("Time") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("WarningPunishment2"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.WhitelistedRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("WhitelistedRoles"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.WhitelistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)"); + + b.HasKey("Id"); + + b.ToTable("WhitelistedUsers"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.XpCurrencyReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Amount") + .HasColumnType("integer"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("XpSettingsId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId"); + + b.ToTable("XpCurrencyReward"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.XpRoleReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("Level") + .HasColumnType("integer"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)"); + + b.Property("XpSettingsId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId", "Level") + .IsUnique(); + + b.ToTable("XpRoleReward"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.XpSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildConfigId") + .HasColumnType("integer"); + + b.Property("NotifyMessage") + .HasColumnType("text"); + + b.Property("ServerExcluded") + .HasColumnType("boolean"); + + b.Property("XpRoleRewardExclusive") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("XpSettings"); + }); + + modelBuilder.Entity("TicketButton", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("Emoji") + .IsRequired() + .HasColumnType("text"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text"); + + b.Property("OpenMessage") + .IsRequired() + .HasColumnType("text"); + + b.Property("TicketPanelId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("TicketPanelId"); + + b.ToTable("TicketButtons"); + }); + + modelBuilder.Entity("TicketPanel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)"); + + b.Property("MessageJson") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("TicketPanels"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.AntiAltSetting", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithOne("AntiAltSetting") + .HasForeignKey("Mewdeko.Database.Models.AntiAltSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.AntiMassMentionSetting", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithOne("AntiMassMentionSetting") + .HasForeignKey("Mewdeko.Database.Models.AntiMassMentionSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.AntiRaidSetting", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithOne("AntiRaidSetting") + .HasForeignKey("Mewdeko.Database.Models.AntiRaidSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.AntiSpamIgnore", b => + { + b.HasOne("Mewdeko.Database.Models.AntiMassMentionSetting", null) + .WithMany("IgnoredChannels") + .HasForeignKey("AntiMassMentionSettingId"); + + b.HasOne("Mewdeko.Database.Models.AntiSpamSetting", null) + .WithMany("IgnoredChannels") + .HasForeignKey("AntiSpamSettingId"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.AntiSpamSetting", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithOne("AntiSpamSetting") + .HasForeignKey("Mewdeko.Database.Models.AntiSpamSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.CommandAlias", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithMany("CommandAliases") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.CommandCooldown", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithMany("CommandCooldowns") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.DelMsgOnCmdChannel", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithMany("DelMsgOnCmdChannels") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.ExcludedItem", b => + { + b.HasOne("Mewdeko.Database.Models.XpSettings", null) + .WithMany("ExclusionList") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.FeedSub", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithMany("FeedSubs") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.FilterInvitesChannelIds", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithMany("FilterInvitesChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.FilterLinksChannelId", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithMany("FilterLinksChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.FilterWordsChannelIds", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithMany("FilterWordsChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.FilteredWord", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithMany("FilteredWords") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.FollowedStream", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithMany("FollowedStreams") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.GroupName", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithMany("SelfAssignableRoleGroupNames") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.GuildConfig", b => + { + b.HasOne("Mewdeko.Database.Models.LogSetting", "LogSetting") + .WithMany() + .HasForeignKey("LogSettingId"); + + b.Navigation("LogSetting"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.IgnoredLogChannel", b => + { + b.HasOne("Mewdeko.Database.Models.LogSetting", null) + .WithMany("IgnoredChannels") + .HasForeignKey("LogSettingId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.MutedUserId", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithMany("MutedUsers") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.NsfwBlacklitedTag", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithMany("NsfwBlacklistedTags") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.Permission", b => + { + b.HasOne("Mewdeko.Database.Models.Permission", "Next") + .WithOne("Previous") + .HasForeignKey("Mewdeko.Database.Models.Permission", "NextId"); + + b.Navigation("Next"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.Permissionv2", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithMany("Permissions") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.PlaylistSong", b => + { + b.HasOne("Mewdeko.Database.Models.MusicPlaylist", null) + .WithMany("Songs") + .HasForeignKey("MusicPlaylistId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.PollAnswers", b => + { + b.HasOne("Mewdeko.Database.Models.Polls", null) + .WithMany("Answers") + .HasForeignKey("PollsId"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.PollVote", b => + { + b.HasOne("Mewdeko.Database.Models.Polls", null) + .WithMany("Votes") + .HasForeignKey("PollsId"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.ReactionRole", b => + { + b.HasOne("Mewdeko.Database.Models.ReactionRoleMessage", null) + .WithMany("ReactionRoles") + .HasForeignKey("ReactionRoleMessageId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.ReactionRoleMessage", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithMany("ReactionRoleMessages") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.Repeater", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithMany("GuildRepeaters") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.StreamRoleBlacklistedUser", b => + { + b.HasOne("Mewdeko.Database.Models.StreamRoleSettings", null) + .WithMany("Blacklist") + .HasForeignKey("StreamRoleSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.StreamRoleSettings", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithOne("StreamRole") + .HasForeignKey("Mewdeko.Database.Models.StreamRoleSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.StreamRoleWhitelistedUser", b => + { + b.HasOne("Mewdeko.Database.Models.StreamRoleSettings", null) + .WithMany("Whitelist") + .HasForeignKey("StreamRoleSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.Template", b => + { + b.HasOne("Mewdeko.Database.Models.TemplateBar", "TemplateBar") + .WithMany() + .HasForeignKey("TemplateBarId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Mewdeko.Database.Models.TemplateClub", "TemplateClub") + .WithMany() + .HasForeignKey("TemplateClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Mewdeko.Database.Models.TemplateGuild", "TemplateGuild") + .WithMany() + .HasForeignKey("TemplateGuildId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Mewdeko.Database.Models.TemplateUser", "TemplateUser") + .WithMany() + .HasForeignKey("TemplateUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TemplateBar"); + + b.Navigation("TemplateClub"); + + b.Navigation("TemplateGuild"); + + b.Navigation("TemplateUser"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.UnbanTimer", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithMany("UnbanTimer") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.UnmuteTimer", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithMany("UnmuteTimers") + .HasForeignKey("GuildConfigId"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.UnroleTimer", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithMany("UnroleTimer") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.VcRoleInfo", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithMany("VcRoleInfos") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.WarningPunishment", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithMany("WarnPunishments") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.WarningPunishment2", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithMany("WarnPunishments2") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.XpCurrencyReward", b => + { + b.HasOne("Mewdeko.Database.Models.XpSettings", "XpSettings") + .WithMany("CurrencyRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.XpRoleReward", b => + { + b.HasOne("Mewdeko.Database.Models.XpSettings", "XpSettings") + .WithMany("RoleRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.XpSettings", b => + { + b.HasOne("Mewdeko.Database.Models.GuildConfig", null) + .WithOne("XpSettings") + .HasForeignKey("Mewdeko.Database.Models.XpSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("TicketButton", b => + { + b.HasOne("TicketPanel", null) + .WithMany("Buttons") + .HasForeignKey("TicketPanelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.AntiMassMentionSetting", b => + { + b.Navigation("IgnoredChannels"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.AntiSpamSetting", b => + { + b.Navigation("IgnoredChannels"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.GuildConfig", b => + { + b.Navigation("AntiAltSetting") + .IsRequired(); + + b.Navigation("AntiMassMentionSetting") + .IsRequired(); + + b.Navigation("AntiRaidSetting") + .IsRequired(); + + b.Navigation("AntiSpamSetting") + .IsRequired(); + + b.Navigation("CommandAliases"); + + b.Navigation("CommandCooldowns"); + + b.Navigation("DelMsgOnCmdChannels"); + + b.Navigation("FeedSubs"); + + b.Navigation("FilterInvitesChannelIds"); + + b.Navigation("FilterLinksChannelIds"); + + b.Navigation("FilterWordsChannelIds"); + + b.Navigation("FilteredWords"); + + b.Navigation("FollowedStreams"); + + b.Navigation("GuildRepeaters"); + + b.Navigation("MutedUsers"); + + b.Navigation("NsfwBlacklistedTags"); + + b.Navigation("Permissions"); + + b.Navigation("ReactionRoleMessages"); + + b.Navigation("SelfAssignableRoleGroupNames"); + + b.Navigation("StreamRole"); + + b.Navigation("UnbanTimer"); + + b.Navigation("UnmuteTimers"); + + b.Navigation("UnroleTimer"); + + b.Navigation("VcRoleInfos"); + + b.Navigation("WarnPunishments"); + + b.Navigation("WarnPunishments2"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.LogSetting", b => + { + b.Navigation("IgnoredChannels"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.MusicPlaylist", b => + { + b.Navigation("Songs"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.Permission", b => + { + b.Navigation("Previous") + .IsRequired(); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.Polls", b => + { + b.Navigation("Answers"); + + b.Navigation("Votes"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.ReactionRoleMessage", b => + { + b.Navigation("ReactionRoles"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.StreamRoleSettings", b => + { + b.Navigation("Blacklist"); + + b.Navigation("Whitelist"); + }); + + modelBuilder.Entity("Mewdeko.Database.Models.XpSettings", b => + { + b.Navigation("CurrencyRewards"); + + b.Navigation("ExclusionList"); + + b.Navigation("RoleRewards"); + }); + + modelBuilder.Entity("TicketPanel", b => + { + b.Navigation("Buttons"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/Mewdeko/Database/Migrations/PostgreSql/20241014004959_GreetDmOptout.cs b/src/Mewdeko/Database/Migrations/PostgreSql/20241014004959_GreetDmOptout.cs new file mode 100644 index 000000000..2cd555e43 --- /dev/null +++ b/src/Mewdeko/Database/Migrations/PostgreSql/20241014004959_GreetDmOptout.cs @@ -0,0 +1,29 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Mewdeko.Database.Migrations.PostgreSql +{ + /// + public partial class GreetDmOptout : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "GreetDmsOptOut", + table: "DiscordUser", + type: "boolean", + nullable: false, + defaultValue: false); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "GreetDmsOptOut", + table: "DiscordUser"); + } + } +} diff --git a/src/Mewdeko/Database/Migrations/PostgreSql/MewdekoPostgresContextModelSnapshot.cs b/src/Mewdeko/Database/Migrations/PostgreSql/MewdekoPostgresContextModelSnapshot.cs index 93dcb3055..f26dde4d3 100644 --- a/src/Mewdeko/Database/Migrations/PostgreSql/MewdekoPostgresContextModelSnapshot.cs +++ b/src/Mewdeko/Database/Migrations/PostgreSql/MewdekoPostgresContextModelSnapshot.cs @@ -795,6 +795,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("Discriminator") .HasColumnType("text"); + b.Property("GreetDmsOptOut") + .HasColumnType("boolean"); + b.Property("IsClubAdmin") .ValueGeneratedOnAdd() .HasColumnType("boolean") diff --git a/src/Mewdeko/Database/Models/DiscordUser.cs b/src/Mewdeko/Database/Models/DiscordUser.cs index d71708c57..d69897d0b 100644 --- a/src/Mewdeko/Database/Models/DiscordUser.cs +++ b/src/Mewdeko/Database/Models/DiscordUser.cs @@ -68,6 +68,12 @@ public enum ProfilePrivacyEnum /// public string? Discriminator { get; set; } + /// + /// Sets whether the user has opted out of greet dms. + /// + [NewProperty] + public bool GreetDmsOptOut { get; set; } = false; + /// /// Gets or sets the avatar ID. /// diff --git a/src/Mewdeko/Mewdeko.cs b/src/Mewdeko/Mewdeko.cs index 106dff1ca..c8ae5af52 100644 --- a/src/Mewdeko/Mewdeko.cs +++ b/src/Mewdeko/Mewdeko.cs @@ -260,8 +260,7 @@ public async Task RunAsync() var dbProvider = Services.GetRequiredService(); await using var dbContext = await dbProvider.GetContextAsync(); - await dbContext.EnsureUserCreated(Client.CurrentUser.Id, Client.CurrentUser.Username, - Client.CurrentUser.Discriminator, Client.CurrentUser.AvatarId); + await dbContext.EnsureUserCreated(Client.CurrentUser.Id, Client.CurrentUser.Username, Client.CurrentUser.AvatarId); } catch (Exception ex) { diff --git a/src/Mewdeko/Modules/Administration/ServerGreetCommands.cs b/src/Mewdeko/Modules/Administration/ServerGreetCommands.cs index b3fbbb562..d4f3a60f3 100644 --- a/src/Mewdeko/Modules/Administration/ServerGreetCommands.cs +++ b/src/Mewdeko/Modules/Administration/ServerGreetCommands.cs @@ -15,31 +15,6 @@ public partial class Administration public class ServerGreetCommands(IHttpClientFactory fact, GuildSettingsService guildSettings) : MewdekoSubmodule { - /// - /// Sets the timer for deleting greeting messages. - /// - /// - /// This command allows users to set the timer for deleting greeting messages. - /// - /// The timer in seconds. Must be between 0 and 600. - /// A task representing the asynchronous operation. - [Cmd] - [Aliases] - [RequireContext(ContextType.Guild)] - [UserPerm(GuildPermission.ManageGuild)] - public async Task GreetDel(int timer = 30) - { - if (timer is < 0 or > 600) - return; - - await Service.SetGreetDel(ctx.Guild.Id, timer).ConfigureAwait(false); - - if (timer > 0) - await ReplyConfirmLocalizedAsync("greetdel_on", timer).ConfigureAwait(false); - else - await ReplyConfirmLocalizedAsync("greetdel_off").ConfigureAwait(false); - } - /// /// Displays the current boost message. /// @@ -135,73 +110,6 @@ await ReplyConfirmLocalizedAsync("boostmsg_enable", $"{await guildSettings.GetPr .ConfigureAwait(false); } - /// - /// Toggles greeting messages for the server. - /// - /// - /// This command allows users to toggle greeting messages for the server. - /// - /// A task representing the asynchronous operation. - [Cmd] - [Aliases] - [RequireContext(ContextType.Guild)] - [UserPerm(GuildPermission.ManageGuild)] - public async Task Greet() - { - var enabled = await Service.SetGreet(ctx.Guild.Id, ctx.Channel.Id).ConfigureAwait(false); - - if (enabled) - await ReplyConfirmLocalizedAsync("greet_on").ConfigureAwait(false); - else - await ReplyConfirmLocalizedAsync("greet_off").ConfigureAwait(false); - } - - - /// - /// Sets up a webhook for greeting messages with an optional image. - /// - /// - /// This command allows users to set up a webhook for greeting messages with an optional image. - /// - /// The text channel to set up the webhook in. - /// The name of the webhook. - /// The URL of the image to include in the webhook message. - /// The text to include in the webhook message. - /// A task representing the asynchronous operation. - [Cmd] - [Aliases] - [RequireContext(ContextType.Guild)] - [UserPerm(GuildPermission.ManageGuild)] - public async Task GreetHook(ITextChannel? chan, string? name, string? image = null, string? text = null) - { - if (text?.ToLower() == "disable") - { - await Service.SetWebGreetUrl(ctx.Guild, "").ConfigureAwait(false); - await ctx.Channel.SendConfirmAsync(GetText("greethookdisabled")).ConfigureAwait(false); - return; - } - - if (image != null || ctx.Message.Attachments.Count > 0) - { - var imageUrl = image ?? ctx.Message.Attachments.FirstOrDefault()?.Url; - var webhook = await CreateWebhook(chan, name, imageUrl).ConfigureAwait(false); - var txt = $"https://discord.com/api/webhooks/{webhook.Id}/{webhook.Token}"; - await Service.SetWebGreetUrl(ctx.Guild, txt).ConfigureAwait(false); - } - else if (image == null && text == null) - { - var webhook = await chan.CreateWebhookAsync(name).ConfigureAwait(false); - var txt = $"https://discord.com/api/webhooks/{webhook.Id}/{webhook.Token}"; - await Service.SetWebGreetUrl(ctx.Guild, txt).ConfigureAwait(false); - } - - var enabled = await Service.SetGreet(ctx.Guild.Id, ctx.Channel.Id).ConfigureAwait(false); - var message = enabled ? "greethookset" : "greethookset2"; - await ctx.Channel.SendConfirmAsync(GetText(message, await guildSettings.GetPrefix(Context.Guild))) - .ConfigureAwait(false); - } - - private async Task CreateWebhook(ITextChannel? chan, string? name, string imageUrl) { using var http = fact.CreateClient(); @@ -257,23 +165,6 @@ await ctx.Channel.SendConfirmAsync(GetText(message, await guildSettings.GetPrefi .ConfigureAwait(false); } - /// - /// Sets up a greeting message using the specified text. - /// - /// - /// This command allows users to set up a greeting message using the specified text. - /// - /// The text to include in the greeting message. - /// A task representing the asynchronous operation. - [Cmd] - [Aliases] - [RequireContext(ContextType.Guild)] - [UserPerm(GuildPermission.ManageGuild)] - public Task GreetHook(string text) - { - return GreetHook(null, null, null, text); - } - /// /// Sets up a leave message using the specified text. /// @@ -291,52 +182,6 @@ public Task LeaveHook(string text) return LeaveHook(null, null, null, text); } - /// - /// Displays the current greeting message. - /// - /// - /// This command displays the current greeting message set for the guild. - /// - /// A task representing the asynchronous operation. - [Cmd] - [Aliases] - [RequireContext(ContextType.Guild)] - [UserPerm(GuildPermission.ManageGuild)] - public async Task GreetMsg() - { - var greetMsg = await Service.GetGreetMsg(ctx.Guild.Id); - await ReplyConfirmLocalizedAsync("greetmsg_cur", greetMsg.SanitizeMentions()); - } - - /// - /// Sets the greeting message to the specified text. - /// - /// - /// This command allows users to set the greeting message to the specified text. - /// - /// The text to set as the greeting message. - /// A task representing the asynchronous operation. - [Cmd] - [Aliases] - [RequireContext(ContextType.Guild)] - [UserPerm(GuildPermission.ManageGuild)] - public async Task GreetMsg([Remainder] string? text) - { - if (string.IsNullOrWhiteSpace(text)) - { - await GreetMsg().ConfigureAwait(false); - return; - } - - var sendGreetEnabled = await Service.SetGreetMessage(ctx.Guild.Id, text); - - await ReplyConfirmLocalizedAsync("greetmsg_new").ConfigureAwait(false); - if (!sendGreetEnabled) - await ReplyConfirmLocalizedAsync("greetmsg_enable", - $"`{await guildSettings.GetPrefix(ctx.Guild)}greet`") - .ConfigureAwait(false); - } - /// /// Toggles the sending of greeting messages via direct message. /// @@ -546,30 +391,6 @@ await ReplyConfirmLocalizedAsync("boostmsg_enable", $"`{await guildSettings.GetPrefix(ctx.Guild)}greet`").ConfigureAwait(false); } - /// - /// Sends a test greet message. - /// - /// - /// This command allows users to send a test greet message. - /// - /// The user to send the test greet message to. - /// A task representing the asynchronous operation. - [Cmd] - [Aliases] - [RequireContext(ContextType.Guild)] - [UserPerm(GuildPermission.ManageGuild)] - [Ratelimit(5)] - public async Task GreetTest([Remainder] IGuildUser? user = null) - { - user ??= (IGuildUser)Context.User; - - await Service.GreetTest((ITextChannel)Context.Channel, user).ConfigureAwait(false); - var enabled = await Service.GetGreetEnabled(Context.Guild.Id); - if (!enabled) - await ReplyConfirmLocalizedAsync("greetmsg_enable", - $"`{await guildSettings.GetPrefix(ctx.Guild)}greet`").ConfigureAwait(false); - } - /// /// Sends a test direct message greet. /// diff --git a/src/Mewdeko/Modules/Help/HelpSlashCommand.cs b/src/Mewdeko/Modules/Help/HelpSlashCommand.cs index 87987972b..058a8f0e4 100644 --- a/src/Mewdeko/Modules/Help/HelpSlashCommand.cs +++ b/src/Mewdeko/Modules/Help/HelpSlashCommand.cs @@ -2,9 +2,7 @@ using Discord.Interactions; using Fergun.Interactive; using Fergun.Interactive.Pagination; -using LinqToDB.Tools; using Mewdeko.Common.Attributes.InteractionCommands; -using Mewdeko.Common.Attributes.TextCommands; using Mewdeko.Common.Autocompleters; using Mewdeko.Common.DiscordImplementations; using Mewdeko.Common.Modals; diff --git a/src/Mewdeko/Modules/MultiGreets/Services/MultiGreetService.cs b/src/Mewdeko/Modules/MultiGreets/Services/MultiGreetService.cs index ea0d797ad..729e8d95d 100644 --- a/src/Mewdeko/Modules/MultiGreets/Services/MultiGreetService.cs +++ b/src/Mewdeko/Modules/MultiGreets/Services/MultiGreetService.cs @@ -1,390 +1,290 @@ using Discord.Net; using Mewdeko.Database.DbContextStuff; +using Mewdeko.Modules.Utility.Services; +using Microsoft.EntityFrameworkCore; using Serilog; namespace Mewdeko.Modules.MultiGreets.Services; /// -/// Service for handling multi greets. +/// Service for handling multiple greeting messages for users joining a guild. /// public class MultiGreetService : INService { private readonly DiscordShardedClient client; private readonly DbContextProvider dbProvider; private readonly GuildSettingsService guildSettingsService; - + private readonly InviteCountService inviteCountService; /// - /// Service for handling multi greets. + /// Initializes a new instance of the class. /// - /// The database provider - /// The discord client - /// The guild settings service - /// The event handler that i had to make because dnet has never heard of multithreading events + /// The database context provider. + /// The Discord client. + /// The guild settings service. + /// The event handler for user join events. + /// The invite count service. public MultiGreetService(DbContextProvider dbProvider, DiscordShardedClient client, - GuildSettingsService guildSettingsService, EventHandler eventHandler) + GuildSettingsService guildSettingsService, EventHandler eventHandler, InviteCountService inviteCountService) { this.client = client; this.guildSettingsService = guildSettingsService; + this.inviteCountService = inviteCountService; this.dbProvider = dbProvider; eventHandler.UserJoined += DoMultiGreet; } /// - /// Gets all greets for a guild. + /// Gets all greet messages for a specific guild. /// - /// The guild id - /// An array of - public async Task GetGreets(ulong guildId) - { - await using var dbContext = await dbProvider.GetContextAsync(); - - return dbContext.MultiGreets.GetAllGreets(guildId); - } + /// The ID of the guild. + /// An array of MultiGreet objects for the specified guild. + public async Task GetGreets(ulong guildId) => + await WithMewdekoContext(db => Task.FromResult(db.MultiGreets.GetAllGreets(guildId))); - private async Task GetForChannel(ulong channelId) - { - await using var dbContext = await dbProvider.GetContextAsync(); - - return dbContext.MultiGreets.GetForChannel(channelId); - } + private async Task GetForChannel(ulong channelId) => + await WithMewdekoContext(db => Task.FromResult(db.MultiGreets.GetForChannel(channelId))); private async Task DoMultiGreet(IGuildUser user) { var greets = await GetGreets(user.Guild.Id); if (greets.Length == 0) return; - if (await GetMultiGreetType(user.Guild.Id) == 3) - return; - if (await GetMultiGreetType(user.Guild.Id) == 1) - { - var random = new Random(); - var index = random.Next(greets.Length); - await HandleRandomGreet(greets[index], user).ConfigureAwait(false); - return; - } - var webhooks = greets.Where(x => x.WebhookUrl is not null).Select(x => new DiscordWebhookClient(x.WebhookUrl)); - if (greets.Any()) - await HandleChannelGreets(greets, user).ConfigureAwait(false); - if (webhooks.Any()) - await HandleWebhookGreets(greets, user).ConfigureAwait(false); - } + var greetType = await GetMultiGreetType(user.Guild.Id); + if (greetType == 3) return; - /// - /// Handles randomly selected greet. - /// - /// The greet to handle - /// The user to greet - private async Task HandleRandomGreet(MultiGreet greet, IGuildUser user) - { var replacer = new ReplacementBuilder().WithUser(user).WithClient(client) - .WithServer(client, user.Guild as SocketGuild).Build(); - if (greet.WebhookUrl is not null) - { - if (user.IsBot && !greet.GreetBots) - return; - var webhook = new DiscordWebhookClient(greet.WebhookUrl); - var content = replacer.Replace(greet.Message); - try - { - if (SmartEmbed.TryParse(content, user.Guild.Id, out var embedData, out var plainText, - out var components2)) - { - var msg = await webhook - .SendMessageAsync(plainText, embeds: embedData, components: components2.Build()) - .ConfigureAwait(false); - if (greet.DeleteTime > 0) - (await (await user.Guild.GetTextChannelAsync(greet.ChannelId)).GetMessageAsync(msg) - .ConfigureAwait(false)).DeleteAfter( - int.Parse(greet.DeleteTime.ToString())); - } - else - { - var msg = await webhook.SendMessageAsync(content).ConfigureAwait(false); - if (greet.DeleteTime > 0) - (await (await user.Guild.GetTextChannelAsync(greet.ChannelId)).GetMessageAsync(msg) - .ConfigureAwait(false)).DeleteAfter( - int.Parse(greet.DeleteTime.ToString())); - } - } - catch (HttpException ex) - { - if (ex.DiscordCode is DiscordErrorCode.UnknownWebhook or DiscordErrorCode.InvalidWebhookToken) - { - await MultiGreetDisable(greet, true); - Log.Information($"MultiGreet disabled in {user.Guild} due to missing permissions."); - } - } - } - else - { - if (user.IsBot && !greet.GreetBots) - return; - var channel = await user.Guild.GetTextChannelAsync(greet.ChannelId); - var content = replacer.Replace(greet.Message); - if (channel is null) - { - await RemoveMultiGreetInternal(greet); - return; - } - - try - { - if (SmartEmbed.TryParse(content, user.Guild.Id, out var embedData, out var plainText, - out var components2)) - { - if (embedData is not null && plainText is not "") - { - var msg = await channel.SendMessageAsync(plainText, embeds: embedData, - components: components2?.Build(), options: new RequestOptions - { - RetryMode = RetryMode.RetryRatelimit - }).ConfigureAwait(false); - if (greet.DeleteTime > 0) - msg.DeleteAfter(greet.DeleteTime); - } - } - else - { - var msg = await channel.SendMessageAsync(content, options: new RequestOptions - { - RetryMode = RetryMode.RetryRatelimit - }).ConfigureAwait(false); - if (greet.DeleteTime > 0) - msg.DeleteAfter(greet.DeleteTime); - } - } - catch (HttpException ex) - { - if (ex.DiscordCode == DiscordErrorCode.MissingPermissions) - { - await MultiGreetDisable(greet, true); - Log.Information($"MultiGreet disabled in {user.Guild} due to missing permissions."); - } - } - } - } + .WithServer(client, user.Guild as SocketGuild); - /// - /// Handles channel greets. - /// - /// The greets to handle - /// The user to greet - private async Task HandleChannelGreets(IEnumerable multiGreets, IGuildUser user) - { - var replacer = new ReplacementBuilder().WithUser(user).WithClient(client) - .WithServer(client, user.Guild as SocketGuild).Build(); - foreach (var i in multiGreets.Where(x => x.WebhookUrl == null)) + if (greetType == 1) { - if (i.Disabled) - continue; - if (user.IsBot && !i.GreetBots) - continue; - if (i.WebhookUrl is not null) continue; - var channel = await user.Guild.GetTextChannelAsync(i.ChannelId); - if (channel is null) - { - await RemoveMultiGreetInternal(i).ConfigureAwait(false); - continue; - } - - var content = replacer.Replace(i.Message); - if (SmartEmbed.TryParse(content, user.Guild.Id, out var embedData, out var plainText, out var components2)) - { - var msg = await channel.SendMessageAsync(plainText, embeds: embedData, components: components2?.Build()) - .ConfigureAwait(false); - if (i.DeleteTime > 0) - msg.DeleteAfter(i.DeleteTime); - } - else - { - var msg = await channel.SendMessageAsync(content).ConfigureAwait(false); - if (i.DeleteTime > 0) - msg.DeleteAfter(i.DeleteTime); - } + var random = new Random(); + var index = random.Next(greets.Length); + await HandleGreet(greets[index], user, replacer); } - } - - /// - /// Handles webhook greets. - /// - /// The greets to handle - /// The user to greet - private async Task HandleWebhookGreets(IEnumerable multiGreets, IGuildUser user) - { - var replacer = new ReplacementBuilder().WithUser(user).WithClient(client) - .WithServer(client, user.Guild as SocketGuild).Build(); - foreach (var i in multiGreets) + else { - if (i.Disabled) - continue; - if (user.IsBot && !i.GreetBots) - continue; - if (i.WebhookUrl is null) continue; - var webhook = new DiscordWebhookClient(i.WebhookUrl); - var content = replacer.Replace(i.Message); - var channel = await user.Guild.GetTextChannelAsync(i.ChannelId); - if (channel is null) - { - await RemoveMultiGreetInternal(i).ConfigureAwait(false); - continue; - } - - if (SmartEmbed.TryParse(content, user.Guild.Id, out var embedData, out var plainText, out var components2)) + foreach (var greet in greets) { - var msg = await webhook.SendMessageAsync(plainText, embeds: embedData, components: components2?.Build()) - .ConfigureAwait(false); - if (i.DeleteTime > 0) - (await (await user.Guild.GetTextChannelAsync(i.ChannelId)).GetMessageAsync(msg) - .ConfigureAwait(false)).DeleteAfter(int.Parse(i.DeleteTime.ToString())); - } - else - { - var msg = await webhook.SendMessageAsync(content).ConfigureAwait(false); - if (i.DeleteTime > 0) - (await (await user.Guild.GetTextChannelAsync(i.ChannelId)).GetMessageAsync(msg) - .ConfigureAwait(false)).DeleteAfter(int.Parse(i.DeleteTime.ToString())); + await HandleGreet(greet, user, replacer); } } } /// - /// Sets the multi greet type for a guild. + /// Sets the multi-greet type for a guild. /// - /// The guild - /// The type to set + /// The guild to set the multi-greet type for. + /// The type of multi-greet to set. public async Task SetMultiGreetType(IGuild guild, int type) { - await using var db = await dbProvider.GetContextAsync(); - var gc = await db.ForGuildId(guild.Id, set => set); - gc.MultiGreetType = type; - await guildSettingsService.UpdateGuildConfig(guild.Id, gc); + await WithMewdekoContextNoReturn(async db => + { + var gc = await db.ForGuildId(guild.Id, set => set); + gc.MultiGreetType = type; + await guildSettingsService.UpdateGuildConfig(guild.Id, gc); + }); } /// - /// Gets the multi greet type for a guild. + /// Gets the multi-greet type for a guild. /// - /// The guild id - /// - public async Task GetMultiGreetType(ulong id) - { - return (await guildSettingsService.GetGuildConfig(id)).MultiGreetType; - } + /// The ID of the guild. + /// The multi-greet type for the specified guild. + public async Task GetMultiGreetType(ulong id) => + (await guildSettingsService.GetGuildConfig(id)).MultiGreetType; /// - /// Adds a multi greet to a guild. + /// Adds a new multi-greet for a guild and channel. /// - /// The guild id - /// The channel id - /// Whether the greet was added + /// The ID of the guild. + /// The ID of the channel. + /// True if the multi-greet was added successfully, false otherwise. public async Task AddMultiGreet(ulong guildId, ulong channelId) { - if ((await GetForChannel(channelId)).Length == 5) - return false; - if ((await GetGreets(guildId)).Length == 30) + if ((await GetForChannel(channelId)).Length == 5 || (await GetGreets(guildId)).Length == 30) return false; - var toadd = new MultiGreet - { - ChannelId = channelId, GuildId = guildId - }; - await using var dbContext = await dbProvider.GetContextAsync(); - dbContext.MultiGreets.Add(toadd); - await dbContext.SaveChangesAsync(); + await WithMewdekoContextNoReturn(db => + { + db.MultiGreets.Add(new MultiGreet { ChannelId = channelId, GuildId = guildId }); + return db.SaveChangesAsync(); + }); return true; } /// - /// Sets the message for a multi greet. + /// Changes the message for a specific multi-greet. /// - /// The greet to change - /// The new message - public async Task ChangeMgMessage(MultiGreet greet, string code) - { - await using var dbContext = await dbProvider.GetContextAsync(); + /// The multi-greet to update. + /// The new message code. + public async Task ChangeMgMessage(MultiGreet greet, string code) => + await UpdateMultiGreet(greet, mg => mg.Message = code); - greet.Message = code; - dbContext.MultiGreets.Update(greet); - await dbContext.SaveChangesAsync().ConfigureAwait(false); - } + /// + /// Changes the delete time for a specific multi-greet. + /// + /// The multi-greet to update. + /// The new delete time in seconds. + public async Task ChangeMgDelete(MultiGreet greet, int howlong) => + await UpdateMultiGreet(greet, mg => mg.DeleteTime = howlong); /// - /// Sets the delete time for a multi greet message. + /// Changes whether a specific multi-greet should greet bots. /// - /// The greet to change - /// The new delete time - public async Task ChangeMgDelete(MultiGreet greet, int howlong) - { - await using var dbContext = await dbProvider.GetContextAsync(); + /// The multi-greet to update. + /// True to greet bots, false otherwise. + public async Task ChangeMgGb(MultiGreet greet, bool enabled) => + await UpdateMultiGreet(greet, mg => mg.GreetBots = enabled); - greet.DeleteTime = howlong; - dbContext.MultiGreets.Update(greet); - await dbContext.SaveChangesAsync().ConfigureAwait(false); - } + /// + /// Changes the webhook URL for a specific multi-greet. + /// + /// The multi-greet to update. + /// The new webhook URL. + public async Task ChangeMgWebhook(MultiGreet greet, string webhookurl) => + await UpdateMultiGreet(greet, mg => mg.WebhookUrl = webhookurl); /// - /// Changes whether a multi greet greets bots. + /// Removes a specific multi-greet. /// - /// The greet to change - /// Whether to greet bots - public async Task ChangeMgGb(MultiGreet greet, bool enabled) - { - await using var dbContext = await dbProvider.GetContextAsync(); + /// The multi-greet to remove. + public async Task RemoveMultiGreetInternal(MultiGreet greet) => + await WithMewdekoContextNoReturn(db => + { + db.MultiGreets.Remove(greet); + return db.SaveChangesAsync(); + }); - greet.GreetBots = enabled; - dbContext.MultiGreets.Update(greet); - await dbContext.SaveChangesAsync().ConfigureAwait(false); - } + /// + /// Removes multiple multi-greets. + /// + /// An array of multi-greets to remove. + public async Task MultiRemoveMultiGreetInternal(MultiGreet[] greets) => + await WithMewdekoContextNoReturn(db => + { + db.MultiGreets.RemoveRange(greets); + return db.SaveChangesAsync(); + }); /// - /// Changes the webhook url for a multi greet. + /// Enables or disables a specific multi-greet. /// - /// The greet to change - /// The new webhook url - public async Task ChangeMgWebhook(MultiGreet greet, string webhookurl) - { - await using var dbContext = await dbProvider.GetContextAsync(); + /// The multi-greet to update. + /// True to disable the multi-greet, false to enable it. + public async Task MultiGreetDisable(MultiGreet greet, bool disabled) => + await UpdateMultiGreet(greet, mg => mg.Disabled = disabled); + + private async Task UpdateMultiGreet(MultiGreet greet, Action updateAction) => + await WithMewdekoContextNoReturn(db => + { + updateAction(greet); + db.MultiGreets.Update(greet); + return db.SaveChangesAsync(); + }); - greet.WebhookUrl = webhookurl; - dbContext.MultiGreets.Update(greet); - await dbContext.SaveChangesAsync().ConfigureAwait(false); + private static async Task SendSmartEmbedMessage(IMessageChannel channel, string content, ulong guildId, int deleteTime = 0) + { + if (SmartEmbed.TryParse(content, guildId, out var embedData, out var plainText, out var components)) + { + var msg = await channel.SendMessageAsync(plainText, embeds: embedData, components: components?.Build()); + if (deleteTime > 0) + msg.DeleteAfter(deleteTime); + } + else + { + var msg = await channel.SendMessageAsync(content); + if (deleteTime > 0) + msg.DeleteAfter(deleteTime); + } } - /// - /// Removes a multi greet. - /// - /// The greet to remove - public async Task RemoveMultiGreetInternal(MultiGreet greet) + private async Task SendSmartEmbedWebhookMessage(DiscordWebhookClient webhook, string content, ulong guildId) { - await using var dbContext = await dbProvider.GetContextAsync(); - dbContext.MultiGreets.Remove(greet); - await dbContext.SaveChangesAsync().ConfigureAwait(false); + if (SmartEmbed.TryParse(content, guildId, out var embedData, out var plainText, out var components)) + { + return await webhook.SendMessageAsync(plainText, embeds: embedData, components: components?.Build()); + } + else + { + return await webhook.SendMessageAsync(content); + } } - /// - /// Removes multiple multi greets. - /// - /// The greets to remove - public async Task MultiRemoveMultiGreetInternal(MultiGreet[] greet) + private async Task HandleGreet(MultiGreet greet, IGuildUser user, ReplacementBuilder replacer) { - await using var dbContext = await dbProvider.GetContextAsync(); + if (user.IsBot && !greet.GreetBots) + return; + + var inviteSettings = await inviteCountService.GetInviteCountSettingsAsync(user.Guild.Id); + if (inviteSettings.IsEnabled) + { + await Task.Delay(500); + var inviter = await inviteCountService.GetInviter(user.Id, user.Guild); + if (inviter == null) + { + replacer.WithOverride("%inviter.username%", () => "Unknown"); + replacer.WithOverride("%inviter.avatar%", () => "Unknown"); + replacer.WithOverride("%inviter.id%", () => "Unknown"); + replacer.WithOverride("%inviter.mention%", () => "Unknown"); + } + else + { + var invCount = await inviteCountService.GetInviteCount(inviter.Id, user.Guild.Id); + replacer.WithOverride("%inviter.username%", () => inviter.Username); + replacer.WithOverride("%inviter.avatar%", () => inviter.GetAvatarUrl()); + replacer.WithOverride("%inviter.id%", () => user.Id.ToString()); + replacer.WithOverride("%inviter.mention%", () => user.Mention); + replacer.WithOverride("%inviter.count%", () => invCount.ToString()); + } + } + + var rep = replacer.Build(); + var content = rep.Replace(greet.Message); + var channel = await user.Guild.GetTextChannelAsync(greet.ChannelId); + + if (channel == null) + { + await RemoveMultiGreetInternal(greet); + return; + } - await using var _ = dbContext.ConfigureAwait(false); - dbContext.MultiGreets.RemoveRange(greet); - await dbContext.SaveChangesAsync().ConfigureAwait(false); + try + { + if (greet.WebhookUrl != null) + { + var webhook = new DiscordWebhookClient(greet.WebhookUrl); + var msgId = await SendSmartEmbedWebhookMessage(webhook, content, user.Guild.Id); + if (greet.DeleteTime > 0) + { + var msg = await channel.GetMessageAsync(msgId); + msg?.DeleteAfter(greet.DeleteTime); + } + } + else + { + await SendSmartEmbedMessage(channel, content, user.Guild.Id, greet.DeleteTime); + } + } + catch (HttpException ex) + { + if (ex.DiscordCode is DiscordErrorCode.UnknownWebhook or DiscordErrorCode.InvalidWebhookToken or DiscordErrorCode.MissingPermissions) + { + await MultiGreetDisable(greet, true); + Log.Information($"MultiGreet disabled in {user.Guild} due to {ex.DiscordCode}."); + } + } } - /// - /// Disables or enables a multi greet. - /// - /// The greet to disable - /// Whether to disable the greet - public async Task MultiGreetDisable(MultiGreet greet, bool disabled) + private async Task WithMewdekoContext(Func> action) { await using var dbContext = await dbProvider.GetContextAsync(); + return await action(dbContext); + } - greet.Disabled = disabled; - dbContext.MultiGreets.Update(greet); - await dbContext.SaveChangesAsync().ConfigureAwait(false); + private async Task WithMewdekoContextNoReturn(Func action) + { + await using var dbContext = await dbProvider.GetContextAsync(); + await action(dbContext); } } \ No newline at end of file diff --git a/src/Mewdeko/Modules/RoleGreets/Services/RoleGreetService.cs b/src/Mewdeko/Modules/RoleGreets/Services/RoleGreetService.cs index d0cd03022..818cbf472 100644 --- a/src/Mewdeko/Modules/RoleGreets/Services/RoleGreetService.cs +++ b/src/Mewdeko/Modules/RoleGreets/Services/RoleGreetService.cs @@ -1,59 +1,137 @@ using Discord.Net; +using LinqToDB; using Mewdeko.Database.DbContextStuff; +using Mewdeko.Modules.Utility.Services; using Serilog; namespace Mewdeko.Modules.RoleGreets.Services; /// -/// Provides functionalities related to greeting users with specific roles in a guild. +/// Provides functionalities related to greeting users with specific roles in a guild. /// public class RoleGreetService : INService { private readonly DiscordShardedClient client; private readonly DbContextProvider dbProvider; + private readonly InviteCountService inviteCountService; /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The database service for accessing role greet configurations. - /// The Discord socket client to interact with the Discord API. - /// The event handler to subscribe to guild member update events. - public RoleGreetService(DbContextProvider dbProvider, DiscordShardedClient client, EventHandler eventHandler) + /// The database context provider. + /// The Discord client. + /// The event handler for guild member update events. + /// The invite count service + public RoleGreetService(DbContextProvider dbProvider, DiscordShardedClient client, EventHandler eventHandler, InviteCountService inviteCountService) { this.client = client; + this.inviteCountService = inviteCountService; this.dbProvider = dbProvider; eventHandler.GuildMemberUpdated += DoRoleGreet; } /// - /// Retrieves an array of configurations for a specific role. + /// Retrieves an array of configurations for a specific role. /// /// The unique identifier of the role. - /// An array of objects. - public async Task GetGreets(ulong roleId) - { - await using var dbContext = await dbProvider.GetContextAsync(); + /// An array of objects. + public async Task GetGreets(ulong roleId) => + await WithMewdekoContext(db => db.RoleGreets.ForRoleId(roleId)); - return await dbContext.RoleGreets.ForRoleId(roleId) ?? []; - } + /// + /// Retrieves a list of configurations for a specific guild. + /// + /// The unique identifier of the guild. + /// An array of objects if any are found; otherwise, an empty array. + public async Task GetListGreets(ulong guildId) => + await WithMewdekoContext(db => db.RoleGreets.Where(x => x.GuildId == guildId).ToArrayAsync()); /// - /// Retrieves a list of configurations for a specific guild. + /// Adds a new role greet configuration. /// /// The unique identifier of the guild. - /// An array of objects if any are found; otherwise, null. - public async Task GetListGreets(ulong guildId) + /// The unique identifier of the channel. + /// The unique identifier of the role. + /// True if the configuration was added successfully; otherwise, false. + public async Task AddRoleGreet(ulong guildId, ulong channelId, ulong roleId) { - await using var dbContext = await dbProvider.GetContextAsync(); + if ((await GetGreets(roleId)).Length == 10) + return false; - return dbContext.RoleGreets.Where(x => x.GuildId == guildId).ToArray(); + return await WithMewdekoContextNoReturn(db => + { + db.RoleGreets.Add(new RoleGreet + { + ChannelId = channelId, + GuildId = guildId, + RoleId = roleId + }); + return db.SaveChangesAsync(); + }); } /// - /// Handles the role greet functionality when a guild member's roles are updated. + /// Updates the message content of a role greet configuration. + /// + /// The role greet configuration to update. + /// The new message content. + public async Task ChangeMgMessage(RoleGreet greet, string code) => + await UpdateRoleGreet(greet, rg => rg.Message = code); + + /// + /// Enables or disables a role greet configuration. + /// + /// The role greet configuration to update. + /// Specifies whether the greet should be disabled. + public async Task RoleGreetDisable(RoleGreet greet, bool disabled) => + await UpdateRoleGreet(greet, rg => rg.Disabled = disabled); + + /// + /// Updates the deletion time for messages sent by a role greet configuration. + /// + /// The role greet configuration to update. + /// The time in seconds after which the greet message should be deleted. + public async Task ChangeRgDelete(RoleGreet greet, int howlong) => + await UpdateRoleGreet(greet, rg => rg.DeleteTime = howlong); + + /// + /// Updates the webhook URL of a role greet configuration. /// - /// A cacheable representation of the updated guild member. - /// The updated guild member. + /// The role greet configuration to update. + /// The new webhook URL. + public async Task ChangeMgWebhook(RoleGreet greet, string webhookurl) => + await UpdateRoleGreet(greet, rg => rg.WebhookUrl = webhookurl); + + /// + /// Enables or disables greeting bots for a role greet configuration. + /// + /// The role greet configuration to update. + /// Specifies whether bots should be greeted. + public async Task ChangeRgGb(RoleGreet greet, bool enabled) => + await UpdateRoleGreet(greet, rg => rg.GreetBots = enabled); + + /// + /// Removes a specific role greet configuration. + /// + /// The role greet configuration to remove. + public async Task RemoveRoleGreetInternal(RoleGreet greet) => + await WithMewdekoContextNoReturn(db => + { + db.RoleGreets.Remove(greet); + return db.SaveChangesAsync(); + }); + + /// + /// Removes multiple role greet configurations. + /// + /// An array of role greet configurations to remove. + public async Task MultiRemoveRoleGreetInternal(RoleGreet[] greets) => + await WithMewdekoContextNoReturn(db => + { + db.RoleGreets.RemoveRange(greets); + return db.SaveChangesAsync(); + }); + private async Task DoRoleGreet(Cacheable cacheable, SocketGuildUser socketGuildUser) { var user = await cacheable.GetOrDownloadAsync().ConfigureAwait(false); @@ -64,308 +142,131 @@ private async Task DoRoleGreet(Cacheable cacheable, Sock } var diffRoles = socketGuildUser.Roles.Where(r => !user.Roles.Contains(r)).ToArray(); - foreach (var i in diffRoles) + foreach (var role in diffRoles) { - var greets = await GetGreets(i.Id); - if (greets.Length == 0) return; - var webhooks = greets.Where(x => x.WebhookUrl is not null) - .Select(x => new DiscordWebhookClient(x.WebhookUrl)); - if (greets.Length > 0) - { - async void Exec(SocketRole x) - { - await HandleChannelGreets(greets, x, user).ConfigureAwait(false); - } + var greets = await GetGreets(role.Id); + if (greets.Length == 0) continue; - diffRoles.ForEach(Exec); - } + var replacer = new ReplacementBuilder().WithUser(socketGuildUser).WithClient(client) + .WithServer(client, socketGuildUser.Guild); - if (!webhooks.Any()) continue; + foreach (var greet in greets) { - async void Exec(SocketRole x) - { - await HandleWebhookGreets(greets, x, user).ConfigureAwait(false); - } - - diffRoles.ForEach(Exec); + await HandleGreet(greet, socketGuildUser, replacer); } } } - /// - /// Handles the sending of greet messages through channel for roles added to a user. - /// - /// An enumerable of configurations. - /// The role that was added to the user. - /// The user who received the role. - private async Task HandleChannelGreets(IEnumerable multiGreets, SocketRole role, SocketGuildUser user) + private async Task HandleGreet(RoleGreet greet, SocketGuildUser user, ReplacementBuilder replacer) { - var checkGreets = multiGreets.Where(x => x.RoleId == role.Id); - if (!checkGreets.Any()) + if (user.IsBot && !greet.GreetBots) return; - var replacer = new ReplacementBuilder().WithUser(user).WithClient(client).WithServer(client, user.Guild) - .Build(); - foreach (var i in checkGreets) + + var inviteSettings = await inviteCountService.GetInviteCountSettingsAsync(user.Guild.Id); + if (inviteSettings.IsEnabled) { - if (i.Disabled) - continue; - if (!i.GreetBots && user.IsBot) - continue; - if (i.WebhookUrl != null) - continue; - var channel = user.Guild.GetTextChannel(i.ChannelId); - if (channel is null) + await Task.Delay(500); + var inviter = await inviteCountService.GetInviter(user.Id, user.Guild); + if (inviter == null) { - await RemoveRoleGreetInternal(i).ConfigureAwait(false); - continue; + replacer.WithOverride("%inviter.username%", () => "Unknown"); + replacer.WithOverride("%inviter.avatar%", () => "Unknown"); + replacer.WithOverride("%inviter.id%", () => "Unknown"); + replacer.WithOverride("%inviter.mention%", () => "Unknown"); } - - var content = replacer.Replace(i.Message); - try + else { - if (SmartEmbed.TryParse(content, user.Guild?.Id, out var embedData, out var plainText, - out var components)) - { - if (embedData is not null && plainText is not "") - { - var msg = await channel - .SendMessageAsync(plainText, embeds: embedData, components: components?.Build()) - .ConfigureAwait(false); - if (i.DeleteTime > 0) - msg.DeleteAfter(i.DeleteTime); - } - - if (embedData is null && plainText is not null) - { - var msg = await channel.SendMessageAsync(plainText, components: components?.Build()) - .ConfigureAwait(false); - if (i.DeleteTime > 0) - msg.DeleteAfter(i.DeleteTime); - } - - if (embedData is not null && plainText is "") - { - var msg = await channel.SendMessageAsync(embeds: embedData, components: components?.Build()) - .ConfigureAwait(false); - if (i.DeleteTime > 0) - msg.DeleteAfter(i.DeleteTime); - } - } - else - { - var msg = await channel.SendMessageAsync(content).ConfigureAwait(false); - if (i.DeleteTime > 0) - msg.DeleteAfter(i.DeleteTime); - } - } - catch (HttpException ex) - { - if (ex.DiscordCode == DiscordErrorCode.MissingPermissions) - { - await RoleGreetDisable(i, true); - Log.Information($"RoleGreet disabled in {user.Guild} due to missing permissions."); - } + var invCount = await inviteCountService.GetInviteCount(inviter.Id, user.Guild.Id); + replacer.WithOverride("%inviter.username%", () => inviter.Username); + replacer.WithOverride("%inviter.avatar%", () => inviter.GetAvatarUrl()); + replacer.WithOverride("%inviter.id%", () => user.Id.ToString()); + replacer.WithOverride("%inviter.mention%", () => user.Mention); + replacer.WithOverride("%inviter.count%", () => invCount.ToString()); } } - } - /// - /// Handles the sending of greet messages through webhooks for roles added to a user. - /// - /// An enumerable of configurations. - /// The role that was added to the user. - /// The user who received the role. - private async Task HandleWebhookGreets(IEnumerable multiGreets, SocketRole role, SocketGuildUser user) - { - var checkGreets = multiGreets.Where(x => x.RoleId == role.Id); - if (!checkGreets.Any()) - return; - var replacer = new ReplacementBuilder().WithUser(user).WithClient(client).WithServer(client, user.Guild) - .Build(); - foreach (var i in checkGreets) - { - if (i.WebhookUrl == null) - continue; - if (i.Disabled) - continue; - if (!i.GreetBots && user.IsBot) - continue; + var content = replacer.Build().Replace(greet.Message); + var channel = user.Guild.GetTextChannel(greet.ChannelId); - if (string.IsNullOrEmpty(i.WebhookUrl)) continue; - var webhook = new DiscordWebhookClient(i.WebhookUrl); - var channel = user.Guild.GetTextChannel(i.ChannelId); - if (channel is null) - { - await RemoveRoleGreetInternal(i).ConfigureAwait(false); - continue; - } + if (channel == null) + { + await RemoveRoleGreetInternal(greet); + return; + } - var content = replacer.Replace(i.Message); - try + try + { + if (greet.WebhookUrl != null) { - if (SmartEmbed.TryParse(content, channel.Guild?.Id, out var embedData, out var plainText, - out var components)) - { - if (embedData is not null && plainText is not "") - { - var msg = await webhook - .SendMessageAsync(plainText, embeds: embedData, components: components?.Build()) - .ConfigureAwait(false); - if (i.DeleteTime > 0) - (await user.Guild.GetTextChannel(i.ChannelId).GetMessageAsync(msg).ConfigureAwait(false)) - .DeleteAfter(i.DeleteTime); - } - - if (embedData is null && plainText is not null) - { - var msg = await webhook.SendMessageAsync(plainText, components: components?.Build()) - .ConfigureAwait(false); - if (i.DeleteTime > 0) - (await user.Guild.GetTextChannel(i.ChannelId).GetMessageAsync(msg).ConfigureAwait(false)) - .DeleteAfter(i.DeleteTime); - } - - if (embedData is not null && plainText is "") - { - var msg = await webhook.SendMessageAsync(embeds: embedData, components: components?.Build()) - .ConfigureAwait(false); - if (i.DeleteTime > 0) - (await user.Guild.GetTextChannel(i.ChannelId).GetMessageAsync(msg).ConfigureAwait(false)) - .DeleteAfter(i.DeleteTime); - } - } - else + var webhook = new DiscordWebhookClient(greet.WebhookUrl); + var msgId = await SendSmartEmbedWebhookMessage(webhook, content, user.Guild.Id); + if (greet.DeleteTime > 0) { - var msg = await webhook.SendMessageAsync(content).ConfigureAwait(false); - if (i.DeleteTime > 0) - (await user.Guild.GetTextChannel(i.ChannelId).GetMessageAsync(msg).ConfigureAwait(false)) - .DeleteAfter(i.DeleteTime); + var msg = await channel.GetMessageAsync(msgId); + msg?.DeleteAfter(greet.DeleteTime); } } - catch (HttpException ex) + else { - if (ex.DiscordCode == DiscordErrorCode.MissingPermissions) - { - await RoleGreetDisable(i, true); - Log.Information($"RoleGreet disabled in {user.Guild} due to missing permissions."); - } + await SendSmartEmbedMessage(channel, content, user.Guild.Id, greet.DeleteTime); } } - } - - /// - /// Adds a new role greet configuration. - /// - /// The unique identifier of the guild. - /// The unique identifier of the channel. - /// The unique identifier of the role. - /// True if the configuration was added successfully; otherwise, false. - public async Task AddRoleGreet(ulong guildId, ulong channelId, ulong roleId) - { - if ((await GetGreets(guildId)).Length == 10) - return false; - var toadd = new RoleGreet + catch (HttpException ex) { - ChannelId = channelId, GuildId = guildId, RoleId = roleId - }; - await using var dbContext = await dbProvider.GetContextAsync(); - - dbContext.RoleGreets.Add(toadd); - await dbContext.SaveChangesAsync().ConfigureAwait(false); - return true; - } - - /// - /// Updates the message content of a role greet configuration. - /// - /// The role greet configuration to update. - /// The new message content. - public async Task ChangeMgMessage(RoleGreet greet, string code) - { - await using var dbContext = await dbProvider.GetContextAsync(); - - greet.Message = code; - dbContext.RoleGreets.Update(greet); - await dbContext.SaveChangesAsync().ConfigureAwait(false); - } - - /// - /// Enables or disables a role greet configuration. - /// - /// The role greet configuration to update. - /// Specifies whether the greet should be disabled. - public async Task RoleGreetDisable(RoleGreet greet, bool disabled) - { - await using var dbContext = await dbProvider.GetContextAsync(); - - greet.Disabled = disabled; - dbContext.RoleGreets.Update(greet); - await dbContext.SaveChangesAsync().ConfigureAwait(false); + if (ex.DiscordCode is DiscordErrorCode.UnknownWebhook or DiscordErrorCode.InvalidWebhookToken or DiscordErrorCode.MissingPermissions) + { + await RoleGreetDisable(greet, true); + Log.Information($"RoleGreet disabled in {user.Guild} due to {ex.DiscordCode}."); + } + } } - /// - /// Updates the deletion time for messages sent by a role greet configuration. - /// - /// The role greet configuration to update. - /// The time in seconds after which the greet message should be deleted. - public async Task ChangeRgDelete(RoleGreet greet, int howlong) + private static async Task SendSmartEmbedMessage(IMessageChannel channel, string content, ulong guildId, int deleteTime = 0) { - await using var dbContext = await dbProvider.GetContextAsync(); - - greet.DeleteTime = howlong; - dbContext.RoleGreets.Update(greet); - await dbContext.SaveChangesAsync().ConfigureAwait(false); + if (SmartEmbed.TryParse(content, guildId, out var embedData, out var plainText, out var components)) + { + var msg = await channel.SendMessageAsync(plainText, embeds: embedData, components: components?.Build()); + if (deleteTime > 0) + msg.DeleteAfter(deleteTime); + } + else + { + var msg = await channel.SendMessageAsync(content); + if (deleteTime > 0) + msg.DeleteAfter(deleteTime); + } } - /// - /// Updates the webhook URL of a role greet configuration. - /// - /// The role greet configuration to update. - /// The new webhook URL. - public async Task ChangeMgWebhook(RoleGreet greet, string webhookurl) + private async Task SendSmartEmbedWebhookMessage(DiscordWebhookClient webhook, string content, ulong guildId) { - await using var dbContext = await dbProvider.GetContextAsync(); - - greet.WebhookUrl = webhookurl; - dbContext.Update(greet); - await dbContext.SaveChangesAsync().ConfigureAwait(false); + if (SmartEmbed.TryParse(content, guildId, out var embedData, out var plainText, out var components)) + { + return await webhook.SendMessageAsync(plainText, embeds: embedData, components: components?.Build()); + } + else + { + return await webhook.SendMessageAsync(content); + } } - /// - /// Enables or disables greeting bots for a role greet configuration. - /// - /// The role greet configuration to update. - /// Specifies whether bots should be greeted. - public async Task ChangeRgGb(RoleGreet greet, bool enabled) + private async Task WithMewdekoContext(Func> action) { - await using var dbContext = await dbProvider.GetContextAsync(); - - greet.GreetBots = enabled; - dbContext.Update(greet); - await dbContext.SaveChangesAsync().ConfigureAwait(false); + await using var mewdekoContext = await dbProvider.GetContextAsync(); + return await action(mewdekoContext); } - /// - /// Removes a specific role greet configuration. - /// - /// The role greet configuration to remove. - public async Task RemoveRoleGreetInternal(RoleGreet greet) + private async Task WithMewdekoContextNoReturn(Func action) { - await using var dbContext = await dbProvider.GetContextAsync(); - - dbContext.RoleGreets.Remove(greet); - await dbContext.SaveChangesAsync().ConfigureAwait(false); + await using var mewdekoContext = await dbProvider.GetContextAsync(); + await action(mewdekoContext); + return true; } - /// - /// Removes multiple role greet configurations. - /// - /// An array of role greet configurations to remove. - public async Task MultiRemoveRoleGreetInternal(RoleGreet[] greet) - { - await using var dbContext = await dbProvider.GetContextAsync(); - - dbContext.RoleGreets.RemoveRange(greet); - await dbContext.SaveChangesAsync().ConfigureAwait(false); - } + private async Task UpdateRoleGreet(RoleGreet greet, Action updateAction) => + await WithMewdekoContextNoReturn(db => + { + updateAction(greet); + db.RoleGreets.Update(greet); + return db.SaveChangesAsync(); + }); } \ No newline at end of file diff --git a/src/Mewdeko/Modules/UserProfile/Services/UserProfileService.cs b/src/Mewdeko/Modules/UserProfile/Services/UserProfileService.cs index 6a2fd5ff2..5c4e4a621 100644 --- a/src/Mewdeko/Modules/UserProfile/Services/UserProfileService.cs +++ b/src/Mewdeko/Modules/UserProfile/Services/UserProfileService.cs @@ -48,6 +48,21 @@ public UserProfileService(DbContextProvider dbProvider, HttpClient http) ]; } + /// + /// Toggles a users ability to receive greet dms. Only viable if the server they are joining uses mewdeko for greet dms. + /// + /// The user who whishes to toggle the setting + /// The opposite of the current state. + public async Task ToggleDmGreetOptOutAsync(IUser user) + { + await using var db = await dbProvider.GetContextAsync(); + var dUser = await db.GetOrCreateUser(user); + dUser.GreetDmsOptOut = !dUser.GreetDmsOptOut; + db.DiscordUser.Update(dUser); + await db.SaveChangesAsync(); + return dUser.GreetDmsOptOut; + } + /// /// Asynchronously retrieves the pronouns for a given Discord user ID, either from the local database or PronounDB if /// unspecified. diff --git a/src/Mewdeko/Modules/UserProfile/UserProfile.cs b/src/Mewdeko/Modules/UserProfile/UserProfile.cs index 4bead44f0..6b623b9b2 100644 --- a/src/Mewdeko/Modules/UserProfile/UserProfile.cs +++ b/src/Mewdeko/Modules/UserProfile/UserProfile.cs @@ -28,6 +28,21 @@ public async Task Profile(IUser user = null) await ctx.Channel.SendMessageAsync(embed: embed); } + /// + /// Allows a user to toggle opting out of greet dms. Only works if the server they are joining uses mewdeko for dm greets. + /// + [Cmd] + [Aliases] + public async Task GreetDmOptOut() + { + var optOut = await Service.ToggleDmGreetOptOutAsync(ctx.User); + + if (optOut) + await ReplyConfirmLocalizedAsync("greetdm_opt_out"); + else + await ReplyConfirmLocalizedAsync("greetdm_opt_in"); + } + /// /// Sets or updates the biography in the user's profile. /// diff --git a/src/Mewdeko/Services/GreetSettingsService.cs b/src/Mewdeko/Services/GreetSettingsService.cs index 9ebbe4a51..d4eac9c5a 100644 --- a/src/Mewdeko/Services/GreetSettingsService.cs +++ b/src/Mewdeko/Services/GreetSettingsService.cs @@ -1,5 +1,5 @@ using Mewdeko.Database.DbContextStuff; -using Mewdeko.Services.Settings; +using Microsoft.EntityFrameworkCore; using Serilog; namespace Mewdeko.Services; @@ -9,41 +9,35 @@ namespace Mewdeko.Services; /// public class GreetSettingsService : INService { - private readonly BotConfigService bss; private readonly DiscordShardedClient client; private readonly DbContextProvider dbProvider; + private readonly GuildSettingsService gss; + private readonly Channel<(GreetSettings, IGuildUser, TaskCompletionSource)> greetDmQueue = Channel.CreateBounded<(GreetSettings, IGuildUser, TaskCompletionSource)>(new BoundedChannelOptions(60) { - // The limit of 60 users should be only hit when there's a raid. In that case - // probably the best thing to do is to drop newest (raiding) users FullMode = BoundedChannelFullMode.DropNewest }); - private readonly GuildSettingsService gss; - /// /// Initializes a new instance of the class, setting up event handlers for user /// join and leave events, and guild join and leave events. /// /// The Discord client instance to interact with the Discord API. /// The service managing guild settings. - /// The service for database interactions. - /// The service managing bot configurations. + /// The db provider /// The handler managing Discord events. - /// The main bot instance. /// /// Event handlers are set up to listen for specific Discord events, allowing the service to respond to user and guild /// activities such as joining, leaving, or boosting. /// public GreetSettingsService(DiscordShardedClient client, GuildSettingsService gss, DbContextProvider dbProvider, - BotConfigService bss, EventHandler eventHandler) + EventHandler eventHandler) { this.dbProvider = dbProvider; this.client = client; this.gss = gss; - this.bss = bss; eventHandler.UserJoined += UserJoined; eventHandler.UserLeft += UserLeft; @@ -51,7 +45,6 @@ public GreetSettingsService(DiscordShardedClient client, GuildSettingsService gs _ = RunGreetLoop(); } - private async Task RunGreetLoop() { while (true) @@ -69,18 +62,17 @@ private async Task RunGreetLoop() } } - private async Task GetGreetSettings(ulong guildId) - { - var guildConfig = await gss.GetGuildConfig(guildId); - return GreetSettings.Create(guildConfig); - } - private async Task GreetDmUser(GreetSettings conf, IGuildUser user) { var completionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); await greetDmQueue.Writer.WriteAsync((conf, user, completionSource)); return await completionSource.Task; } + private async Task GetGreetSettings(ulong guildId) + { + var guildConfig = await gss.GetGuildConfig(guildId); + return GreetSettings.Create(guildConfig); + } private async Task TriggerBoostMessage(GreetSettings conf, SocketGuildUser user) { @@ -248,22 +240,6 @@ public async Task SetBoost(ulong guildId, ulong channelId) return !conf.SendBoostMessage; } - /// - /// Sets the webhook URL for greeting messages in a guild. - /// - /// The guild object. - /// The URL of the webhook to send greeting messages. - /// - /// This setting allows the guild to customize the destination of greeting messages. - /// - public async Task SetWebGreetUrl(IGuild guild, string url) - { - await using var db = await dbProvider.GetContextAsync(); - var gc = await db.ForGuildId(guild.Id, set => set); - gc.GreetHook = url; - await gss.UpdateGuildConfig(guild.Id, gc); - } - /// /// Sets the webhook URL for leave messages in a guild. /// @@ -280,46 +256,12 @@ public async Task SetWebLeaveUrl(IGuild guild, string url) await gss.UpdateGuildConfig(guild.Id, gc); } - /// - /// Retrieves the direct message (DM) greeting message text for a guild. - /// - /// The guild's unique identifier. - /// The DM greeting message text. - public async Task GetDmGreetMsg(ulong id) - { - await using var dbContext = await dbProvider.GetContextAsync(); - - return (await dbContext.ForGuildId(id, set => set)).DmGreetMessageText; - } - - /// - /// Retrieves the channel greeting message text for a guild. - /// - /// The guild's unique identifier. - /// The channel greeting message text. - public async Task GetGreetMsg(ulong gid) - { - await using var dbContext = await dbProvider.GetContextAsync(); - - return (await dbContext.ForGuildId(gid, set => set)).ChannelGreetMessageText; - } - - /// - /// Retrieves the webhook URL configured for greeting messages in a guild. - /// - /// The guild's unique identifier. - /// The webhook URL for greeting messages. - public async Task GetGreetHook(ulong? gid) - { - return (await gss.GetGuildConfig(gid.Value)).GreetHook; - } - /// /// Retrieves the webhook URL configured for leave messages in a guild. /// /// The guild's unique identifier. /// The webhook URL for leave messages. - public async Task GetLeaveHook(ulong? gid) + private async Task GetLeaveHook(ulong? gid) { return (await gss.GetGuildConfig(gid.Value)).LeaveHook; } @@ -404,87 +346,28 @@ private async Task ByeUsers(GreetSettings conf, ITextChannel channel, IEnumerabl } } - private Task GreetUsers(GreetSettings conf, ITextChannel channel, IGuildUser user) + /// + /// Retrieves the direct message (DM) greeting message text for a guild. + /// + /// The guild's unique identifier. + /// The DM greeting message text. + public async Task GetDmGreetMsg(ulong id) { - return GreetUsers(conf, channel, - [ - user - ]); + await using var dbContext = await dbProvider.GetContextAsync(); + + return (await dbContext.ForGuildId(id, set => set)).DmGreetMessageText; } - private async Task GreetUsers(GreetSettings conf, ITextChannel channel, IEnumerable users) + /// + /// Retrieves the channel greeting message text for a guild. + /// + /// The guild's unique identifier. + /// The channel greeting message text. + public async Task GetGreetMsg(ulong gid) { - if (!users.Any()) - return; + await using var dbContext = await dbProvider.GetContextAsync(); - var rep = new ReplacementBuilder() - .WithChannel(channel) - .WithClient(client) - .WithServer(client, (SocketGuild)channel.Guild) - .WithManyUsers(users) - .Build(); - var gh = await GetGreetHook(channel.GuildId); - if (SmartEmbed.TryParse(rep.Replace(conf.ChannelGreetMessageText), channel.GuildId, out var embed, - out var plainText, out var components)) - { - try - { - if (string.IsNullOrEmpty(gh) || gh == 0.ToString()) - { - var toDelete = await channel - .SendMessageAsync(plainText, embeds: embed, - components: components?.Build()).ConfigureAwait(false); - if (conf.AutoDeleteGreetMessagesTimer > 0) - toDelete.DeleteAfter(conf.AutoDeleteGreetMessagesTimer); - } - else - { - var webhook = new DiscordWebhookClient(await GetGreetHook(channel.GuildId)); - var toDelete = await webhook - .SendMessageAsync(plainText, embeds: embed, components: components?.Build()) - .ConfigureAwait(false); - if (conf.AutoDeleteGreetMessagesTimer > 0) - { - var msg = await channel.GetMessageAsync(toDelete).ConfigureAwait(false) as IUserMessage; - msg.DeleteAfter(conf.AutoDeleteGreetMessagesTimer); - } - } - } - catch (Exception ex) - { - Log.Warning(ex, "Error embedding greet message"); - } - } - else - { - var msg = rep.Replace(conf.ChannelGreetMessageText); - if (!string.IsNullOrWhiteSpace(msg)) - { - try - { - if (string.IsNullOrEmpty(gh) || gh == 0.ToString()) - { - var toDelete = await channel.SendMessageAsync(msg.SanitizeMentions()).ConfigureAwait(false); - if (conf.AutoDeleteGreetMessagesTimer > 0) - toDelete.DeleteAfter(conf.AutoDeleteGreetMessagesTimer); - } - else - { - var webhook = new DiscordWebhookClient(await GetGreetHook(channel.GuildId)); - var toDel = await webhook.SendMessageAsync(msg.SanitizeMentions()).ConfigureAwait(false); - if (conf.AutoDeleteGreetMessagesTimer > 0) - { - var msg2 = await channel.GetMessageAsync(toDel).ConfigureAwait(false) as IUserMessage; - msg2.DeleteAfter(conf.AutoDeleteGreetMessagesTimer); - } - } - } - catch (Exception ex) - { - Log.Warning(ex, "Error sending greet message"); - } - } - } + return (await dbContext.ForGuildId(gid, set => set)).ChannelGreetMessageText; } private async Task GreetDmUserInternal(GreetSettings conf, IGuildUser user) @@ -492,6 +375,12 @@ private async Task GreetDmUserInternal(GreetSettings conf, IGuildUser user if (!conf.SendDmGreetMessage) return false; + await using var db = await dbProvider.GetContextAsync(); + + var dUser = await db.DiscordUser.FirstOrDefaultAsync(x => x.UserId == user.Id).ConfigureAwait(false); + if (dUser.GreetDmsOptOut) + return false; + var channel = await user.CreateDMChannelAsync(); var rep = new ReplacementBuilder() @@ -536,18 +425,6 @@ private Task UserJoined(IGuildUser user) { var conf = await GetGreetSettings(user.GuildId); - if (conf.SendChannelGreetMessage) - { - var channel = await user.Guild.GetTextChannelAsync(conf.GreetMessageChannelId) - .ConfigureAwait(false); - if (channel != null) - { - await GreetUsers(conf, channel, [ - user - ]).ConfigureAwait(false); - } - } - if (conf.SendDmGreetMessage) { var channel = await user.CreateDMChannelAsync().ConfigureAwait(false); @@ -575,50 +452,6 @@ public async Task GetByeMessage(ulong gid) return (await dbContext.ForGuildId(gid, set => set)).ChannelByeMessageText; } - /// - /// Enables or disables the channel greeting feature for a guild and sets the channel for greetings. - /// - /// The unique identifier of the guild. - /// The channel ID where greetings should be sent. - /// - /// Optional. A boolean value indicating whether the feature should be enabled. If null, the setting - /// will be toggled. - /// - /// A boolean indicating whether the greeting feature is enabled after the operation. - public async Task SetGreet(ulong guildId, ulong channelId, bool? value = null) - { - await using var dbContext = await dbProvider.GetContextAsync(); - - var conf = await dbContext.ForGuildId(guildId, set => set); - conf.SendChannelGreetMessage = !conf.SendChannelGreetMessage; - conf.GreetMessageChannelId = channelId; - await dbContext.SaveChangesAsync().ConfigureAwait(false); - return conf.SendChannelGreetMessage; - } - - /// - /// Sets the greeting message for a guild. - /// - /// The unique identifier of the guild. - /// The greeting message to be set. Mentions will be sanitized. - /// A boolean indicating whether the greeting message feature is enabled. - /// Thrown if the message is null or whitespace. - public async Task SetGreetMessage(ulong guildId, string? message) - { - message = message?.SanitizeMentions(); - - if (string.IsNullOrWhiteSpace(message)) - throw new ArgumentNullException(nameof(message)); - - await using var dbContext = await dbProvider.GetContextAsync(); - - var conf = await dbContext.ForGuildId(guildId, set => set); - conf.ChannelGreetMessageText = message; - await gss.UpdateGuildConfig(guildId, conf); - - return conf.SendChannelGreetMessage; - } - /// /// Enables or disables the direct message greeting feature for a guild. /// @@ -726,27 +559,6 @@ public async Task SetByeDel(ulong guildId, int timer) await gss.UpdateGuildConfig(guildId, conf); } - /// - /// Sets the timer for auto-deleting greeting messages in a guild. - /// - /// The unique identifier of the guild. - /// - /// The time in seconds after which greeting messages should be deleted. Must be between 0 and 600 - /// seconds. - /// - /// Thrown if the timer is outside the allowed range. - public async Task SetGreetDel(ulong id, int timer) - { - if (timer is < 0 or > 600) - return; - - await using var dbContext = await dbProvider.GetContextAsync(); - - var conf = await dbContext.ForGuildId(id, set => set); - conf.AutoDeleteGreetMessagesTimer = timer; - await gss.UpdateGuildConfig(id, conf); - } - #region Get Enabled Status /// @@ -762,19 +574,6 @@ public async Task GetGreetDmEnabled(ulong guildId) return conf.SendDmGreetMessage; } - /// - /// Determines if the channel greeting feature is enabled for a specified guild. - /// - /// The unique identifier of the guild. - /// A boolean indicating if the channel greeting feature is enabled. - public async Task GetGreetEnabled(ulong guildId) - { - await using var dbContext = await dbProvider.GetContextAsync(); - - var conf = await dbContext.ForGuildId(guildId, set => set); - return conf.SendChannelGreetMessage; - } - /// /// Determines if the boost message feature is enabled for a specified guild. /// @@ -816,17 +615,6 @@ public async Task ByeTest(ITextChannel channel, IGuildUser user) await ByeUsers(conf, channel, user); } - /// - /// Sends a test greeting message in the specified channel for a given user. - /// - /// The text channel where the message should be sent. - /// The user for whom the greeting message is targeted. - public async Task GreetTest(ITextChannel channel, IGuildUser user) - { - var conf = await GetGreetSettings(user.GuildId); - await GreetUsers(conf, channel, user); - } - /// /// Sends a test boost message in the specified channel for a given user. /// @@ -881,20 +669,11 @@ public class GreetSettings /// public ulong BoostMessageChannelId { get; set; } - /// - /// Gets or sets the time in seconds after which greeting messages should be automatically deleted. - /// - public int AutoDeleteGreetMessagesTimer { get; set; } - /// /// Gets or sets the time in seconds after which farewell messages should be automatically deleted. /// public int AutoDeleteByeMessagesTimer { get; set; } - /// - /// Gets or sets the channel ID where greeting messages should be sent. - /// - public ulong GreetMessageChannelId { get; set; } /// /// Gets or sets the channel ID where farewell messages should be sent. @@ -910,17 +689,6 @@ public class GreetSettings /// Gets or sets the direct message greeting text. /// public string? DmGreetMessageText { get; set; } - - /// - /// Gets or sets a value indicating whether channel greeting messages are enabled for the guild. - /// - public bool SendChannelGreetMessage { get; set; } - - /// - /// Gets or sets the channel greeting message text. - /// - public string? ChannelGreetMessageText { get; set; } - /// /// Gets or sets a value indicating whether channel farewell messages are enabled for the guild. /// @@ -944,13 +712,9 @@ public static GreetSettings Create(GuildConfig g) return new GreetSettings { AutoDeleteByeMessagesTimer = g.AutoDeleteByeMessagesTimer, - AutoDeleteGreetMessagesTimer = g.AutoDeleteGreetMessagesTimer, - GreetMessageChannelId = g.GreetMessageChannelId, ByeMessageChannelId = g.ByeMessageChannelId, SendDmGreetMessage = g.SendDmGreetMessage, DmGreetMessageText = g.DmGreetMessageText, - SendChannelGreetMessage = g.SendChannelGreetMessage, - ChannelGreetMessageText = g.ChannelGreetMessageText, SendChannelByeMessage = g.SendChannelByeMessage, ChannelByeMessageText = g.ChannelByeMessageText, BoostMessage = g.BoostMessage, diff --git a/src/Mewdeko/data/aliases.yml b/src/Mewdeko/data/aliases.yml index 59783a8f3..de43b68a6 100644 --- a/src/Mewdeko/data/aliases.yml +++ b/src/Mewdeko/data/aliases.yml @@ -38,6 +38,9 @@ whoinvited: invitedusers: - invitedusers - userinvites +greetdmoptout: + - greetdmoptout + - gdmoptout purgeuser: - purgeuser - pruneuser diff --git a/src/Mewdeko/data/strings/commands/commands.en-US.yml b/src/Mewdeko/data/strings/commands/commands.en-US.yml index bd2ff1353..f08e5a1b4 100644 --- a/src/Mewdeko/data/strings/commands/commands.en-US.yml +++ b/src/Mewdeko/data/strings/commands/commands.en-US.yml @@ -17,17 +17,29 @@ invites: args: - "@user" desc: "Displays the number of invites for you or the specified user." +greetdmoptout: + args: + - "" + desc: "Allows a user to optout of greet dms from mewdeko. Only works if mewdeko is the bot used for greet dms." invitesettings: + args: + - "" desc: "Shows the current invite tracking settings for the server." toggleinvitetracking: + args: + - "" desc: "Enables or disables invite tracking for the server." toggleremoveinviteonleave: + args: + - "" desc: "Toggles whether invites should be removed when a user leaves the server." setminaccountage: args: - "days" desc: "Sets the minimum account age required for an invite to be counted." inviteleaderboard: + args: + - "" desc: "Displays a leaderboard of users with the most invites." whoinvited: args: diff --git a/src/Mewdeko/data/strings/responses/responses.en-US.json b/src/Mewdeko/data/strings/responses/responses.en-US.json index 886d8e39c..4e3ada0ec 100644 --- a/src/Mewdeko/data/strings/responses/responses.en-US.json +++ b/src/Mewdeko/data/strings/responses/responses.en-US.json @@ -19,6 +19,8 @@ "instance_added": "Instance Added", "instance_version": "Instance Version: {0}", "instance_command_count": "Commands Count: {0}", + "greetdm_opt_out": "You have been opted out of greet dms. Keep in mind this only works where mewdeko is used for greet dms.", + "greetdm_opt_in": "You have been opted in to greet dms.", "instance_modules_count": "Modules Count: {0}", "instance_user_count": "User Count {0}", "lockdown_in_progress": "{0} Lockdown is in progress...",