From 3532554a135ba558f00bda9583679a5e2ac9ce97 Mon Sep 17 00:00:00 2001 From: Toastie Date: Wed, 27 Nov 2024 22:38:06 +1300 Subject: [PATCH 1/4] sar rework, improved --- src/EllieBot/Db/EllieContext.cs | 130 +- .../Db/Extensions/UserXpExtensions.cs | 6 +- src/EllieBot/Db/Models/FollowedStream.cs | 3 +- src/EllieBot/Db/Models/GroupName.cs | 19 +- src/EllieBot/Db/Models/GuildConfig.cs | 4 +- .../Db/Models/roles/SelfAssignableRole.cs | 21 +- src/EllieBot/EllieBot.csproj | 2 +- src/EllieBot/Migrations/MigrationQueries.cs | 31 + ...102022956_no-discrim-and-flag-translate.cs | 2 - .../20241127092257_sar-rework.Designer.cs | 3951 +++++++++++++++++ .../PostgreSql/20241127092257_sar-rework.cs | 153 + .../PostgreSqlContextModelSnapshot.cs | 160 +- ...102022949_no-discrim-and-flag-translate.cs | 2 - .../20241127092212_sar-rework.Designer.cs | 3048 +++++++++++++ .../Sqlite/20241127092212_sar-rework.cs | 152 + .../Sqlite/EllieSqliteContextModelSnapshot.cs | 121 +- .../DangerousCommands/CleanupService.cs | 53 +- .../SelfAssignedRolesCommands.cs | 320 +- .../SelfAssignedRolesService.cs | 486 +- .../UserPunish/UserPunishCommands.cs | 21 - .../Gambling/AnimalRacing/AnimalRace.cs | 4 +- src/EllieBot/Modules/Gambling/Gambling.cs | 6 +- .../Modules/Gambling/Loan/LoanCommands.cs | 92 + .../Providers/TwitchHelixProvider.cs | 52 +- .../Abstractions/Extensions/Extensions.cs | 4 +- src/EllieBot/_common/EllieModule.cs | 21 + src/EllieBot/data/aliases.yml | 43 +- src/EllieBot/data/gambling.yml | 2 +- .../data/strings/commands/commands.en-US.yml | 66 +- .../strings/responses/responses.en-US.json | 11 +- 30 files changed, 8417 insertions(+), 569 deletions(-) create mode 100644 src/EllieBot/Migrations/PostgreSql/20241127092257_sar-rework.Designer.cs create mode 100644 src/EllieBot/Migrations/PostgreSql/20241127092257_sar-rework.cs create mode 100644 src/EllieBot/Migrations/Sqlite/20241127092212_sar-rework.Designer.cs create mode 100644 src/EllieBot/Migrations/Sqlite/20241127092212_sar-rework.cs create mode 100644 src/EllieBot/Modules/Gambling/Loan/LoanCommands.cs diff --git a/src/EllieBot/Db/EllieContext.cs b/src/EllieBot/Db/EllieContext.cs index b0bc0a8..f8783ce 100644 --- a/src/EllieBot/Db/EllieContext.cs +++ b/src/EllieBot/Db/EllieContext.cs @@ -2,6 +2,7 @@ using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using EllieBot.Db.Models; +using EllieBot.Modules.Administration.Services; // ReSharper disable UnusedAutoPropertyAccessor.Global @@ -14,7 +15,6 @@ public abstract class EllieContext : DbContext public DbSet Quotes { get; set; } public DbSet Reminders { get; set; } - public DbSet SelfAssignableRoles { get; set; } public DbSet MusicPlaylists { get; set; } public DbSet Expressions { get; set; } public DbSet CurrencyTransactions { get; set; } @@ -74,6 +74,34 @@ public abstract class EllieContext : DbContext protected override void OnModelCreating(ModelBuilder modelBuilder) { + #region New Sar + + modelBuilder.Entity(sg => + { + sg.HasAlternateKey(x => new + { + x.GuildId, + x.GroupNumber + }); + + sg.HasMany(x => x.Roles) + .WithOne() + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity() + .HasAlternateKey(x => new + { + x.GuildId, + x.RoleId + }); + + modelBuilder.Entity() + .HasIndex(x => x.GuildId) + .IsUnique(); + + #endregion + #region Rakeback modelBuilder.Entity() @@ -84,16 +112,23 @@ public abstract class EllieContext : DbContext #region UserBetStats modelBuilder.Entity() - .HasIndex(x => new { x.UserId, x.Game }) + .HasIndex(x => new + { + x.UserId, + x.Game + }) .IsUnique(); - #endregion - #region Flag Translate + #region Flag Translate modelBuilder.Entity() - .HasIndex(x => new { x.GuildId, x.ChannelId }) + .HasIndex(x => new + { + x.GuildId, + x.ChannelId + }) .IsUnique(); #endregion @@ -286,11 +321,6 @@ public abstract class EllieContext : DbContext .HasForeignKey(x => x.GuildConfigId) .OnDelete(DeleteBehavior.Cascade); - modelBuilder.Entity() - .HasMany(x => x.SelfAssignableRoleGroupNames) - .WithOne() - .OnDelete(DeleteBehavior.Cascade); - modelBuilder.Entity() .HasAlternateKey(x => new { @@ -319,21 +349,6 @@ public abstract class EllieContext : DbContext #endregion - #region Self Assignable Roles - - var selfassignableRolesEntity = modelBuilder.Entity(); - - selfassignableRolesEntity.HasIndex(s => new - { - s.GuildId, - s.RoleId - }) - .IsUnique(); - - selfassignableRolesEntity.Property(x => x.Group).HasDefaultValue(0); - - #endregion - #region MusicPlaylists var musicPlaylistEntity = modelBuilder.Entity(); @@ -401,10 +416,10 @@ public abstract class EllieContext : DbContext var xps = modelBuilder.Entity(); xps.HasIndex(x => new - { - x.UserId, - x.GuildId - }) + { + x.UserId, + x.GuildId + }) .IsUnique(); xps.HasIndex(x => x.UserId); @@ -450,9 +465,9 @@ public abstract class EllieContext : DbContext .OnDelete(DeleteBehavior.SetNull); ci.HasIndex(x => new - { - x.Name - }) + { + x.Name + }) .IsUnique(); #endregion @@ -516,23 +531,6 @@ public abstract class EllieContext : DbContext #endregion - #region GroupName - - modelBuilder.Entity() - .HasIndex(x => new - { - x.GuildConfigId, - x.Number - }) - .IsUnique(); - - modelBuilder.Entity() - .HasOne(x => x.GuildConfig) - .WithMany(x => x.SelfAssignableRoleGroupNames) - .IsRequired(); - - #endregion - #region BanTemplate modelBuilder.Entity().HasIndex(x => x.GuildId).IsUnique(); @@ -571,10 +569,10 @@ public abstract class EllieContext : DbContext .IsUnique(false); rr2.HasIndex(x => new - { - x.MessageId, - x.Emote - }) + { + x.MessageId, + x.Emote + }) .IsUnique(); }); @@ -649,11 +647,11 @@ public abstract class EllieContext : DbContext { // user can own only one of each item x.HasIndex(model => new - { - model.UserId, - model.ItemType, - model.ItemKey - }) + { + model.UserId, + model.ItemType, + model.ItemKey + }) .IsUnique(); }); @@ -678,10 +676,10 @@ public abstract class EllieContext : DbContext #region Sticky Roles modelBuilder.Entity(sr => sr.HasIndex(x => new - { - x.GuildId, - x.UserId - }) + { + x.GuildId, + x.UserId + }) .IsUnique()); #endregion @@ -726,10 +724,10 @@ public abstract class EllieContext : DbContext modelBuilder .Entity(gs => gs.HasIndex(x => new - { - x.GuildId, - x.GreetType - }) + { + x.GuildId, + x.GreetType + }) .IsUnique()); modelBuilder.Entity(gs => diff --git a/src/EllieBot/Db/Extensions/UserXpExtensions.cs b/src/EllieBot/Db/Extensions/UserXpExtensions.cs index b06d98b..5241f3f 100644 --- a/src/EllieBot/Db/Extensions/UserXpExtensions.cs +++ b/src/EllieBot/Db/Extensions/UserXpExtensions.cs @@ -1,5 +1,4 @@ -#nullable disable -using LinqToDB; +using LinqToDB; using LinqToDB.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; using EllieBot.Db.Models; @@ -8,6 +7,9 @@ namespace EllieBot.Db; public static class UserXpExtensions { + public static async Task GetGuildUserXp(this ITable table, ulong guildId, ulong userId) + => await table.FirstOrDefaultAsyncLinqToDB(x => x.GuildId == guildId && x.UserId == userId); + public static UserXpStats GetOrCreateUserXpStats(this DbContext ctx, ulong guildId, ulong userId) { var usr = ctx.Set().FirstOrDefault(x => x.UserId == userId && x.GuildId == guildId); diff --git a/src/EllieBot/Db/Models/FollowedStream.cs b/src/EllieBot/Db/Models/FollowedStream.cs index 183e0ab..0ee5949 100644 --- a/src/EllieBot/Db/Models/FollowedStream.cs +++ b/src/EllieBot/Db/Models/FollowedStream.cs @@ -9,7 +9,8 @@ public class FollowedStream : DbEntity Picarto = 3, Youtube = 4, Facebook = 5, - Trovo = 6 + Trovo = 6, + Kick = 7, } public ulong GuildId { get; set; } diff --git a/src/EllieBot/Db/Models/GroupName.cs b/src/EllieBot/Db/Models/GroupName.cs index 3e29b31..56bfa53 100644 --- a/src/EllieBot/Db/Models/GroupName.cs +++ b/src/EllieBot/Db/Models/GroupName.cs @@ -1,11 +1,18 @@ -#nullable disable +using System.ComponentModel.DataAnnotations; + namespace EllieBot.Db.Models; -public class GroupName : DbEntity +public sealed class SarGroup : DbEntity { - public int GuildConfigId { get; set; } - public GuildConfig GuildConfig { get; set; } + [Key] + public int Id { get; set; } - public int Number { get; set; } - public string Name { get; set; } + public int GroupNumber { get; set; } + public ulong GuildId { get; set; } + public ulong? RoleReq { get; set; } + public ICollection Roles { get; set; } = []; + public bool IsExclusive { get; set; } + + [MaxLength(100)] + public string? Name { get; set; } } \ No newline at end of file diff --git a/src/EllieBot/Db/Models/GuildConfig.cs b/src/EllieBot/Db/Models/GuildConfig.cs index c703000..59872e2 100644 --- a/src/EllieBot/Db/Models/GuildConfig.cs +++ b/src/EllieBot/Db/Models/GuildConfig.cs @@ -31,10 +31,11 @@ public class GuildConfig : DbEntity // public bool SendBoostMessage { get; set; } // pulic int BoostMessageDeleteAfter { get; set; } - //self assignable roles + //todo FUTURE: DELETE, UNUSED public bool ExclusiveSelfAssignedRoles { get; set; } public bool AutoDeleteSelfAssignedRoleMessages { get; set; } + //stream notifications public HashSet FollowedStreams { get; set; } = new(); @@ -91,7 +92,6 @@ public class GuildConfig : DbEntity public List FeedSubs { get; set; } = new(); public bool NotifyStreamOffline { get; set; } public bool DeleteStreamOnlineMessage { get; set; } - public List SelfAssignableRoleGroupNames { get; set; } public int WarnExpireHours { get; set; } public WarnExpireAction WarnExpireAction { get; set; } = WarnExpireAction.Clear; diff --git a/src/EllieBot/Db/Models/roles/SelfAssignableRole.cs b/src/EllieBot/Db/Models/roles/SelfAssignableRole.cs index ac147b6..b7d4556 100644 --- a/src/EllieBot/Db/Models/roles/SelfAssignableRole.cs +++ b/src/EllieBot/Db/Models/roles/SelfAssignableRole.cs @@ -1,11 +1,24 @@ -#nullable disable +using System.ComponentModel.DataAnnotations; + namespace EllieBot.Db.Models; -public class SelfAssignedRole : DbEntity +public sealed class Sar { + [Key] + public int Id { get; set; } + public ulong GuildId { get; set; } public ulong RoleId { get; set; } - public int Group { get; set; } - public int LevelRequirement { get; set; } + public int SarGroupId { get; set; } + public int LevelReq { get; set; } +} + +public sealed class SarAutoDelete +{ + [Key] + public int Id { get; set; } + + public ulong GuildId { get; set; } + public bool IsEnabled { get; set; } = false; } \ No newline at end of file diff --git a/src/EllieBot/EllieBot.csproj b/src/EllieBot/EllieBot.csproj index 0dec0f1..19ea312 100644 --- a/src/EllieBot/EllieBot.csproj +++ b/src/EllieBot/EllieBot.csproj @@ -4,7 +4,7 @@ enable true en - 5.1.20 + 5.2.0 $(MSBuildProjectDirectory) diff --git a/src/EllieBot/Migrations/MigrationQueries.cs b/src/EllieBot/Migrations/MigrationQueries.cs index f35dbc8..7139467 100644 --- a/src/EllieBot/Migrations/MigrationQueries.cs +++ b/src/EllieBot/Migrations/MigrationQueries.cs @@ -5,6 +5,37 @@ namespace EllieBot.Migrations; public static class MigrationQueries { + public static void MigrateSar(MigrationBuilder migrationBuilder) + { + migrationBuilder.Sql(""" + INSERT INTO GroupName (Number, GuildConfigId) + SELECT DISTINCT "Group", GC.Id + FROM SelfAssignableRoles as SAR + INNER JOIN GuildConfigs as GC + ON SAR.GuildId = GC.GuildId + WHERE SAR.GuildId not in (SELECT GuildConfigs.GuildId from GroupName LEFT JOIN GuildConfigs ON GroupName.GuildConfigId = GuildConfigs.Id); + + INSERT INTO SarGroup (Id, GroupNumber, Name, IsExclusive, GuildId) + SELECT GN.Id, GN.Number, GN.Name, GC.ExclusiveSelfAssignedRoles, GC.GuildId + FROM GroupName as GN + INNER JOIN GuildConfigs as GC ON GN.GuildConfigId = GC.Id; + + INSERT INTO Sar (GuildId, RoleId, SarGroupId, LevelReq) + SELECT SAR.GuildId, SAR.RoleId, MIN(SG2.Id), MIN(SAR.LevelRequirement) + FROM SelfAssignableRoles as SAR + INNER JOIN (SELECT GuildId FROM GroupName as gn + INNER JOIN GuildConfigs as gc ON gn.GuildConfigId =gc.Id + ) as SG + ON SG.GuildId = SAR.GuildId + INNER JOIN GroupName as SG2 + ON SG2.Number = SAR."Group" + GROUP BY SAR.GuildId, SAR.RoleId; + + INSERT INTO SarAutoDelete (GuildId, IsEnabled) + SELECT GuildId, AutoDeleteSelfAssignedRoleMessages FROM GuildConfigs WHERE AutoDeleteSelfAssignedRoleMessages = TRUE; + """); + } + public static void UpdateUsernames(MigrationBuilder migrationBuilder) { migrationBuilder.Sql("UPDATE DiscordUser SET Username = '??' || Username WHERE Discriminator = '????';"); diff --git a/src/EllieBot/Migrations/PostgreSql/20241102022956_no-discrim-and-flag-translate.cs b/src/EllieBot/Migrations/PostgreSql/20241102022956_no-discrim-and-flag-translate.cs index ca32adb..332f57b 100644 --- a/src/EllieBot/Migrations/PostgreSql/20241102022956_no-discrim-and-flag-translate.cs +++ b/src/EllieBot/Migrations/PostgreSql/20241102022956_no-discrim-and-flag-translate.cs @@ -12,8 +12,6 @@ namespace EllieBot.Migrations.PostgreSql /// protected override void Up(MigrationBuilder migrationBuilder) { - MigrationQueries.UpdateUsernames(migrationBuilder); - migrationBuilder.DropColumn( name: "discriminator", table: "discorduser"); diff --git a/src/EllieBot/Migrations/PostgreSql/20241127092257_sar-rework.Designer.cs b/src/EllieBot/Migrations/PostgreSql/20241127092257_sar-rework.Designer.cs new file mode 100644 index 0000000..6a61fde --- /dev/null +++ b/src/EllieBot/Migrations/PostgreSql/20241127092257_sar-rework.Designer.cs @@ -0,0 +1,3951 @@ +// +using System; +using EllieBot.Db; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace EllieBot.Migrations.PostgreSql +{ + [DbContext(typeof(PostgreSqlContext))] + [Migration("20241127092257_sar-rework")] + partial class sarrework + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.8") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("EllieBot.Db.Models.AntiAltSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("integer") + .HasColumnName("action"); + + b.Property("ActionDurationMinutes") + .HasColumnType("integer") + .HasColumnName("actiondurationminutes"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("MinAge") + .HasColumnType("interval") + .HasColumnName("minage"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_antialtsetting"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_antialtsetting_guildconfigid"); + + b.ToTable("antialtsetting", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiRaidSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("integer") + .HasColumnName("action"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("PunishDuration") + .HasColumnType("integer") + .HasColumnName("punishduration"); + + b.Property("Seconds") + .HasColumnType("integer") + .HasColumnName("seconds"); + + b.Property("UserThreshold") + .HasColumnType("integer") + .HasColumnName("userthreshold"); + + b.HasKey("Id") + .HasName("pk_antiraidsetting"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_antiraidsetting_guildconfigid"); + + b.ToTable("antiraidsetting", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiSpamIgnore", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AntiSpamSettingId") + .HasColumnType("integer") + .HasColumnName("antispamsettingid"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.HasKey("Id") + .HasName("pk_antispamignore"); + + b.HasIndex("AntiSpamSettingId") + .HasDatabaseName("ix_antispamignore_antispamsettingid"); + + b.ToTable("antispamignore", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiSpamSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("integer") + .HasColumnName("action"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("MessageThreshold") + .HasColumnType("integer") + .HasColumnName("messagethreshold"); + + b.Property("MuteTime") + .HasColumnType("integer") + .HasColumnName("mutetime"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_antispamsetting"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_antispamsetting_guildconfigid"); + + b.ToTable("antispamsetting", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ArchivedTodoListModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_todosarchive"); + + b.ToTable("todosarchive", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoCommand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("ChannelName") + .HasColumnType("text") + .HasColumnName("channelname"); + + b.Property("CommandText") + .HasColumnType("text") + .HasColumnName("commandtext"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("GuildName") + .HasColumnType("text") + .HasColumnName("guildname"); + + b.Property("Interval") + .HasColumnType("integer") + .HasColumnName("interval"); + + b.Property("VoiceChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("voicechannelid"); + + b.Property("VoiceChannelName") + .HasColumnType("text") + .HasColumnName("voicechannelname"); + + b.HasKey("Id") + .HasName("pk_autocommands"); + + b.ToTable("autocommands", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoPublishChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.HasKey("Id") + .HasName("pk_autopublishchannel"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_autopublishchannel_guildid"); + + b.ToTable("autopublishchannel", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoTranslateChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoDelete") + .HasColumnType("boolean") + .HasColumnName("autodelete"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.HasKey("Id") + .HasName("pk_autotranslatechannels"); + + b.HasIndex("ChannelId") + .IsUnique() + .HasDatabaseName("ix_autotranslatechannels_channelid"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_autotranslatechannels_guildid"); + + b.ToTable("autotranslatechannels", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoTranslateUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("integer") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Source") + .HasColumnType("text") + .HasColumnName("source"); + + b.Property("Target") + .HasColumnType("text") + .HasColumnName("target"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_autotranslateusers"); + + b.HasAlternateKey("ChannelId", "UserId") + .HasName("ak_autotranslateusers_channelid_userid"); + + b.ToTable("autotranslateusers", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("PruneDays") + .HasColumnType("integer") + .HasColumnName("prunedays"); + + b.Property("Text") + .HasColumnType("text") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_bantemplates"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_bantemplates_guildid"); + + b.ToTable("bantemplates", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.BankUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Balance") + .HasColumnType("bigint") + .HasColumnName("balance"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_bankusers"); + + b.HasIndex("UserId") + .IsUnique() + .HasDatabaseName("ix_bankusers_userid"); + + b.ToTable("bankusers", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.BlacklistEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("ItemId") + .HasColumnType("numeric(20,0)") + .HasColumnName("itemid"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubApplicants", b => + { + b.Property("ClubId") + .HasColumnType("integer") + .HasColumnName("clubid"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("userid"); + + b.HasKey("ClubId", "UserId") + .HasName("pk_clubapplicants"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_clubapplicants_userid"); + + b.ToTable("clubapplicants", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubBans", b => + { + b.Property("ClubId") + .HasColumnType("integer") + .HasColumnName("clubid"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("userid"); + + b.HasKey("ClubId", "UserId") + .HasName("pk_clubbans"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_clubbans_userid"); + + b.ToTable("clubbans", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("ImageUrl") + .HasColumnType("text") + .HasColumnName("imageurl"); + + b.Property("Name") + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasColumnName("name"); + + b.Property("OwnerId") + .HasColumnType("integer") + .HasColumnName("ownerid"); + + b.Property("Xp") + .HasColumnType("integer") + .HasColumnName("xp"); + + b.HasKey("Id") + .HasName("pk_clubs"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("ix_clubs_name"); + + b.HasIndex("OwnerId") + .IsUnique() + .HasDatabaseName("ix_clubs_ownerid"); + + b.ToTable("clubs", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.CommandAlias", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Mapping") + .HasColumnType("text") + .HasColumnName("mapping"); + + b.Property("Trigger") + .HasColumnType("text") + .HasColumnName("trigger"); + + b.HasKey("Id") + .HasName("pk_commandalias"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_commandalias_guildconfigid"); + + b.ToTable("commandalias", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.CommandCooldown", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CommandName") + .HasColumnType("text") + .HasColumnName("commandname"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Seconds") + .HasColumnType("integer") + .HasColumnName("seconds"); + + b.HasKey("Id") + .HasName("pk_commandcooldown"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_commandcooldown_guildconfigid"); + + b.ToTable("commandcooldown", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.CurrencyTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Amount") + .HasColumnType("bigint") + .HasColumnName("amount"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Extra") + .IsRequired() + .HasColumnType("text") + .HasColumnName("extra"); + + b.Property("Note") + .HasColumnType("text") + .HasColumnName("note"); + + b.Property("OtherId") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)") + .HasColumnName("otherid") + .HasDefaultValueSql("NULL"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text") + .HasColumnName("type"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_currencytransactions"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_currencytransactions_userid"); + + b.ToTable("currencytransactions", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.DelMsgOnCmdChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("State") + .HasColumnType("boolean") + .HasColumnName("state"); + + b.HasKey("Id") + .HasName("pk_delmsgoncmdchannel"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_delmsgoncmdchannel_guildconfigid"); + + b.ToTable("delmsgoncmdchannel", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.DiscordPermOverride", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Command") + .HasColumnType("text") + .HasColumnName("command"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Perm") + .HasColumnType("numeric(20,0)") + .HasColumnName("perm"); + + b.HasKey("Id") + .HasName("pk_discordpermoverrides"); + + b.HasIndex("GuildId", "Command") + .IsUnique() + .HasDatabaseName("ix_discordpermoverrides_guildid_command"); + + b.ToTable("discordpermoverrides", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.DiscordUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AvatarId") + .HasColumnType("text") + .HasColumnName("avatarid"); + + b.Property("ClubId") + .HasColumnType("integer") + .HasColumnName("clubid"); + + b.Property("CurrencyAmount") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(0L) + .HasColumnName("currencyamount"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("IsClubAdmin") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("isclubadmin"); + + b.Property("NotifyOnLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("notifyonlevelup"); + + b.Property("TotalXp") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(0L) + .HasColumnName("totalxp"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Username") + .HasColumnType("text") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_discorduser"); + + b.HasAlternateKey("UserId") + .HasName("ak_discorduser_userid"); + + b.HasIndex("ClubId") + .HasDatabaseName("ix_discorduser_clubid"); + + b.HasIndex("CurrencyAmount") + .HasDatabaseName("ix_discorduser_currencyamount"); + + b.HasIndex("TotalXp") + .HasDatabaseName("ix_discorduser_totalxp"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_discorduser_userid"); + + b.HasIndex("Username") + .HasDatabaseName("ix_discorduser_username"); + + b.ToTable("discorduser", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.EllieExpression", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AllowTarget") + .HasColumnType("boolean") + .HasColumnName("allowtarget"); + + b.Property("AutoDeleteTrigger") + .HasColumnType("boolean") + .HasColumnName("autodeletetrigger"); + + b.Property("ContainsAnywhere") + .HasColumnType("boolean") + .HasColumnName("containsanywhere"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("DmResponse") + .HasColumnType("boolean") + .HasColumnName("dmresponse"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Reactions") + .HasColumnType("text") + .HasColumnName("reactions"); + + b.Property("Response") + .HasColumnType("text") + .HasColumnName("response"); + + b.Property("Trigger") + .HasColumnType("text") + .HasColumnName("trigger"); + + b.HasKey("Id") + .HasName("pk_expressions"); + + b.ToTable("expressions", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ExcludedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("ItemId") + .HasColumnType("numeric(20,0)") + .HasColumnName("itemid"); + + b.Property("ItemType") + .HasColumnType("integer") + .HasColumnName("itemtype"); + + b.Property("XpSettingsId") + .HasColumnType("integer") + .HasColumnName("xpsettingsid"); + + b.HasKey("Id") + .HasName("pk_excludeditem"); + + b.HasIndex("XpSettingsId") + .HasDatabaseName("ix_excludeditem_xpsettingsid"); + + b.ToTable("excludeditem", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FeedSub", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("Url") + .IsRequired() + .HasColumnType("text") + .HasColumnName("url"); + + b.HasKey("Id") + .HasName("pk_feedsub"); + + b.HasAlternateKey("GuildConfigId", "Url") + .HasName("ak_feedsub_guildconfigid_url"); + + b.ToTable("feedsub", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilterChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_filterchannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filterchannelid_guildconfigid"); + + b.ToTable("filterchannelid", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilterLinksChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_filterlinkschannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filterlinkschannelid_guildconfigid"); + + b.ToTable("filterlinkschannelid", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilterWordsChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_filterwordschannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filterwordschannelid_guildconfigid"); + + b.ToTable("filterwordschannelid", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilteredWord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Word") + .HasColumnType("text") + .HasColumnName("word"); + + b.HasKey("Id") + .HasName("pk_filteredword"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filteredword_guildconfigid"); + + b.ToTable("filteredword", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FlagTranslateChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.HasKey("Id") + .HasName("pk_flagtranslatechannel"); + + b.HasIndex("GuildId", "ChannelId") + .IsUnique() + .HasDatabaseName("ix_flagtranslatechannel_guildid_channelid"); + + b.ToTable("flagtranslatechannel", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FollowedStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("Username") + .HasColumnType("text") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_followedstream"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_followedstream_guildconfigid"); + + b.ToTable("followedstream", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GCChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_gcchannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_gcchannelid_guildconfigid"); + + b.ToTable("gcchannelid", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GamblingStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Bet") + .HasColumnType("numeric") + .HasColumnName("bet"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Feature") + .HasColumnType("text") + .HasColumnName("feature"); + + b.Property("PaidOut") + .HasColumnType("numeric") + .HasColumnName("paidout"); + + b.HasKey("Id") + .HasName("pk_gamblingstats"); + + b.HasIndex("Feature") + .IsUnique() + .HasDatabaseName("ix_gamblingstats_feature"); + + b.ToTable("gamblingstats", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GiveawayModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("EndsAt") + .HasColumnType("timestamp without time zone") + .HasColumnName("endsat"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageid"); + + b.HasKey("Id") + .HasName("pk_giveawaymodel"); + + b.ToTable("giveawaymodel", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GiveawayUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("GiveawayId") + .HasColumnType("integer") + .HasColumnName("giveawayid"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_giveawayuser"); + + b.HasIndex("GiveawayId", "UserId") + .IsUnique() + .HasDatabaseName("ix_giveawayuser_giveawayid_userid"); + + b.ToTable("giveawayuser", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GuildConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoAssignRoleIds") + .HasColumnType("text") + .HasColumnName("autoassignroleids"); + + b.Property("AutoDeleteSelfAssignedRoleMessages") + .HasColumnType("boolean") + .HasColumnName("autodeleteselfassignedrolemessages"); + + b.Property("CleverbotEnabled") + .HasColumnType("boolean") + .HasColumnName("cleverbotenabled"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("DeleteMessageOnCommand") + .HasColumnType("boolean") + .HasColumnName("deletemessageoncommand"); + + b.Property("DeleteStreamOnlineMessage") + .HasColumnType("boolean") + .HasColumnName("deletestreamonlinemessage"); + + b.Property("DisableGlobalExpressions") + .HasColumnType("boolean") + .HasColumnName("disableglobalexpressions"); + + b.Property("ExclusiveSelfAssignedRoles") + .HasColumnType("boolean") + .HasColumnName("exclusiveselfassignedroles"); + + b.Property("FilterInvites") + .HasColumnType("boolean") + .HasColumnName("filterinvites"); + + b.Property("FilterLinks") + .HasColumnType("boolean") + .HasColumnName("filterlinks"); + + b.Property("FilterWords") + .HasColumnType("boolean") + .HasColumnName("filterwords"); + + b.Property("GameVoiceChannel") + .HasColumnType("numeric(20,0)") + .HasColumnName("gamevoicechannel"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Locale") + .HasColumnType("text") + .HasColumnName("locale"); + + b.Property("MuteRoleName") + .HasColumnType("text") + .HasColumnName("muterolename"); + + b.Property("NotifyStreamOffline") + .HasColumnType("boolean") + .HasColumnName("notifystreamoffline"); + + b.Property("PermissionRole") + .HasColumnType("text") + .HasColumnName("permissionrole"); + + b.Property("Prefix") + .HasColumnType("text") + .HasColumnName("prefix"); + + b.Property("StickyRoles") + .HasColumnType("boolean") + .HasColumnName("stickyroles"); + + b.Property("TimeZoneId") + .HasColumnType("text") + .HasColumnName("timezoneid"); + + b.Property("VerboseErrors") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("verboseerrors"); + + b.Property("VerbosePermissions") + .HasColumnType("boolean") + .HasColumnName("verbosepermissions"); + + b.Property("WarnExpireAction") + .HasColumnType("integer") + .HasColumnName("warnexpireaction"); + + b.Property("WarnExpireHours") + .HasColumnType("integer") + .HasColumnName("warnexpirehours"); + + b.Property("WarningsInitialized") + .HasColumnType("boolean") + .HasColumnName("warningsinitialized"); + + b.HasKey("Id") + .HasName("pk_guildconfigs"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_guildconfigs_guildid"); + + b.HasIndex("WarnExpireHours") + .HasDatabaseName("ix_guildconfigs_warnexpirehours"); + + b.ToTable("guildconfigs", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.HoneypotChannel", b => + { + b.Property("GuildId") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.HasKey("GuildId") + .HasName("pk_honeypotchannels"); + + b.ToTable("honeypotchannels", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.IgnoredLogItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("ItemType") + .HasColumnType("integer") + .HasColumnName("itemtype"); + + b.Property("LogItemId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logitemid"); + + b.Property("LogSettingId") + .HasColumnType("integer") + .HasColumnName("logsettingid"); + + b.HasKey("Id") + .HasName("pk_ignoredlogchannels"); + + b.HasIndex("LogSettingId", "LogItemId", "ItemType") + .IsUnique() + .HasDatabaseName("ix_ignoredlogchannels_logsettingid_logitemid_itemtype"); + + b.ToTable("ignoredlogchannels", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ImageOnlyChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_imageonlychannels"); + + b.HasIndex("ChannelId") + .IsUnique() + .HasDatabaseName("ix_imageonlychannels_channelid"); + + b.ToTable("imageonlychannels", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.LogSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelCreatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelcreatedid"); + + b.Property("ChannelDestroyedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channeldestroyedid"); + + b.Property("ChannelUpdatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelupdatedid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("LogOtherId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logotherid"); + + b.Property("LogUserPresenceId") + .HasColumnType("numeric(20,0)") + .HasColumnName("loguserpresenceid"); + + b.Property("LogVoicePresenceId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logvoicepresenceid"); + + b.Property("LogVoicePresenceTTSId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logvoicepresencettsid"); + + b.Property("LogWarnsId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logwarnsid"); + + b.Property("MessageDeletedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messagedeletedid"); + + b.Property("MessageUpdatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageupdatedid"); + + b.Property("ThreadCreatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("threadcreatedid"); + + b.Property("ThreadDeletedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("threaddeletedid"); + + b.Property("UserBannedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userbannedid"); + + b.Property("UserJoinedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userjoinedid"); + + b.Property("UserLeftId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userleftid"); + + b.Property("UserMutedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("usermutedid"); + + b.Property("UserUnbannedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userunbannedid"); + + b.Property("UserUpdatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userupdatedid"); + + b.HasKey("Id") + .HasName("pk_logsettings"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_logsettings_guildid"); + + b.ToTable("logsettings", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.MusicPlayerSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoDisconnect") + .HasColumnType("boolean") + .HasColumnName("autodisconnect"); + + b.Property("AutoPlay") + .HasColumnType("boolean") + .HasColumnName("autoplay"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("MusicChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("musicchannelid"); + + b.Property("PlayerRepeat") + .HasColumnType("integer") + .HasColumnName("playerrepeat"); + + b.Property("QualityPreset") + .HasColumnType("integer") + .HasColumnName("qualitypreset"); + + b.Property("Volume") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(100) + .HasColumnName("volume"); + + b.HasKey("Id") + .HasName("pk_musicplayersettings"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_musicplayersettings_guildid"); + + b.ToTable("musicplayersettings", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.MusicPlaylist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Author") + .HasColumnType("text") + .HasColumnName("author"); + + b.Property("AuthorId") + .HasColumnType("numeric(20,0)") + .HasColumnName("authorid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("pk_musicplaylists"); + + b.ToTable("musicplaylists", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.MutedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_muteduserid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_muteduserid_guildconfigid"); + + b.ToTable("muteduserid", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.NCPixel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Color") + .HasColumnType("bigint") + .HasColumnName("color"); + + b.Property("OwnerId") + .HasColumnType("numeric(20,0)") + .HasColumnName("ownerid"); + + b.Property("Position") + .HasColumnType("integer") + .HasColumnName("position"); + + b.Property("Price") + .HasColumnType("bigint") + .HasColumnName("price"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_ncpixel"); + + b.HasAlternateKey("Position") + .HasName("ak_ncpixel_position"); + + b.HasIndex("OwnerId") + .HasDatabaseName("ix_ncpixel_ownerid"); + + b.ToTable("ncpixel", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.PatronUser", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("AmountCents") + .HasColumnType("integer") + .HasColumnName("amountcents"); + + b.Property("LastCharge") + .HasColumnType("timestamp without time zone") + .HasColumnName("lastcharge"); + + b.Property("UniquePlatformUserId") + .HasColumnType("text") + .HasColumnName("uniqueplatformuserid"); + + b.Property("ValidThru") + .HasColumnType("timestamp without time zone") + .HasColumnName("validthru"); + + b.HasKey("UserId") + .HasName("pk_patrons"); + + b.HasIndex("UniquePlatformUserId") + .IsUnique() + .HasDatabaseName("ix_patrons_uniqueplatformuserid"); + + b.ToTable("patrons", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Permissionv2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Index") + .HasColumnType("integer") + .HasColumnName("index"); + + b.Property("IsCustomCommand") + .HasColumnType("boolean") + .HasColumnName("iscustomcommand"); + + b.Property("PrimaryTarget") + .HasColumnType("integer") + .HasColumnName("primarytarget"); + + b.Property("PrimaryTargetId") + .HasColumnType("numeric(20,0)") + .HasColumnName("primarytargetid"); + + b.Property("SecondaryTarget") + .HasColumnType("integer") + .HasColumnName("secondarytarget"); + + b.Property("SecondaryTargetName") + .HasColumnType("text") + .HasColumnName("secondarytargetname"); + + b.Property("State") + .HasColumnType("boolean") + .HasColumnName("state"); + + b.HasKey("Id") + .HasName("pk_permissions"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_permissions_guildconfigid"); + + b.ToTable("permissions", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.PlantedCurrency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Amount") + .HasColumnType("bigint") + .HasColumnName("amount"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageid"); + + b.Property("Password") + .HasColumnType("text") + .HasColumnName("password"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_plantedcurrency"); + + b.HasIndex("ChannelId") + .HasDatabaseName("ix_plantedcurrency_channelid"); + + b.HasIndex("MessageId") + .IsUnique() + .HasDatabaseName("ix_plantedcurrency_messageid"); + + b.ToTable("plantedcurrency", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.PlaylistSong", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("MusicPlaylistId") + .HasColumnType("integer") + .HasColumnName("musicplaylistid"); + + b.Property("Provider") + .HasColumnType("text") + .HasColumnName("provider"); + + b.Property("ProviderType") + .HasColumnType("integer") + .HasColumnName("providertype"); + + b.Property("Query") + .HasColumnType("text") + .HasColumnName("query"); + + b.Property("Title") + .HasColumnType("text") + .HasColumnName("title"); + + b.Property("Uri") + .HasColumnType("text") + .HasColumnName("uri"); + + b.HasKey("Id") + .HasName("pk_playlistsong"); + + b.HasIndex("MusicPlaylistId") + .HasDatabaseName("ix_playlistsong_musicplaylistid"); + + b.ToTable("playlistsong", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Quote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .HasColumnType("numeric(20,0)") + .HasColumnName("authorid"); + + b.Property("AuthorName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("authorname"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Keyword") + .IsRequired() + .HasColumnType("text") + .HasColumnName("keyword"); + + b.Property("Text") + .IsRequired() + .HasColumnType("text") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_quotes"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_quotes_guildid"); + + b.HasIndex("Keyword") + .HasDatabaseName("ix_quotes_keyword"); + + b.ToTable("quotes", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ReactionRoleV2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Emote") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("emote"); + + b.Property("Group") + .HasColumnType("integer") + .HasColumnName("group"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("LevelReq") + .HasColumnType("integer") + .HasColumnName("levelreq"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageid"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_reactionroles"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_reactionroles_guildid"); + + b.HasIndex("MessageId", "Emote") + .IsUnique() + .HasDatabaseName("ix_reactionroles_messageid_emote"); + + b.ToTable("reactionroles", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Reminder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("IsPrivate") + .HasColumnType("boolean") + .HasColumnName("isprivate"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("ServerId") + .HasColumnType("numeric(20,0)") + .HasColumnName("serverid"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("When") + .HasColumnType("timestamp without time zone") + .HasColumnName("when"); + + b.HasKey("Id") + .HasName("pk_reminders"); + + b.HasIndex("When") + .HasDatabaseName("ix_reminders_when"); + + b.ToTable("reminders", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Repeater", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Interval") + .HasColumnType("interval") + .HasColumnName("interval"); + + b.Property("LastMessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("lastmessageid"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("NoRedundant") + .HasColumnType("boolean") + .HasColumnName("noredundant"); + + b.Property("StartTimeOfDay") + .HasColumnType("interval") + .HasColumnName("starttimeofday"); + + b.HasKey("Id") + .HasName("pk_repeaters"); + + b.ToTable("repeaters", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.RewardedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AmountRewardedThisMonth") + .HasColumnType("bigint") + .HasColumnName("amountrewardedthismonth"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("LastReward") + .HasColumnType("timestamp without time zone") + .HasColumnName("lastreward"); + + b.Property("PlatformUserId") + .HasColumnType("text") + .HasColumnName("platformuserid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_rewardedusers"); + + b.HasIndex("PlatformUserId") + .IsUnique() + .HasDatabaseName("ix_rewardedusers_platformuserid"); + + b.ToTable("rewardedusers", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.RotatingPlayingStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Status") + .HasColumnType("text") + .HasColumnName("status"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_rotatingstatus"); + + b.ToTable("rotatingstatus", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Sar", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("LevelReq") + .HasColumnType("integer") + .HasColumnName("levelreq"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("SarGroupId") + .HasColumnType("integer") + .HasColumnName("sargroupid"); + + b.HasKey("Id") + .HasName("pk_sar"); + + b.HasAlternateKey("GuildId", "RoleId") + .HasName("ak_sar_guildid_roleid"); + + b.HasIndex("SarGroupId") + .HasDatabaseName("ix_sar_sargroupid"); + + b.ToTable("sar", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SarAutoDelete", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("IsEnabled") + .HasColumnType("boolean") + .HasColumnName("isenabled"); + + b.HasKey("Id") + .HasName("pk_sarautodelete"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_sarautodelete_guildid"); + + b.ToTable("sarautodelete", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SarGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GroupNumber") + .HasColumnType("integer") + .HasColumnName("groupnumber"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("IsExclusive") + .HasColumnType("boolean") + .HasColumnName("isexclusive"); + + b.Property("Name") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("name"); + + b.Property("RoleReq") + .HasColumnType("numeric(20,0)") + .HasColumnName("rolereq"); + + b.HasKey("Id") + .HasName("pk_sargroup"); + + b.HasAlternateKey("GuildId", "GroupNumber") + .HasName("ak_sargroup_guildid_groupnumber"); + + b.ToTable("sargroup", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .HasColumnType("numeric(20,0)") + .HasColumnName("authorid"); + + b.Property("Command") + .HasColumnType("text") + .HasColumnName("command"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Index") + .HasColumnType("integer") + .HasColumnName("index"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Price") + .HasColumnType("integer") + .HasColumnName("price"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("RoleName") + .HasColumnType("text") + .HasColumnName("rolename"); + + b.Property("RoleRequirement") + .HasColumnType("numeric(20,0)") + .HasColumnName("rolerequirement"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_shopentry"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_shopentry_guildconfigid"); + + b.ToTable("shopentry", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ShopEntryItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("ShopEntryId") + .HasColumnType("integer") + .HasColumnName("shopentryid"); + + b.Property("Text") + .HasColumnType("text") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_shopentryitem"); + + b.HasIndex("ShopEntryId") + .HasDatabaseName("ix_shopentryitem_shopentryid"); + + b.ToTable("shopentryitem", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SlowmodeIgnoredRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_slowmodeignoredrole"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_slowmodeignoredrole_guildconfigid"); + + b.ToTable("slowmodeignoredrole", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SlowmodeIgnoredUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_slowmodeignoreduser"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_slowmodeignoreduser_guildconfigid"); + + b.ToTable("slowmodeignoreduser", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StickyRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("RoleIds") + .HasColumnType("text") + .HasColumnName("roleids"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_stickyroles"); + + b.HasIndex("GuildId", "UserId") + .IsUnique() + .HasDatabaseName("ix_stickyroles_guildid_userid"); + + b.ToTable("stickyroles", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamOnlineMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageid"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_streamonlinemessages"); + + b.ToTable("streamonlinemessages", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleBlacklistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("integer") + .HasColumnName("streamrolesettingsid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Username") + .HasColumnType("text") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_streamroleblacklisteduser"); + + b.HasIndex("StreamRoleSettingsId") + .HasDatabaseName("ix_streamroleblacklisteduser_streamrolesettingsid"); + + b.ToTable("streamroleblacklisteduser", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AddRoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("addroleid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Enabled") + .HasColumnType("boolean") + .HasColumnName("enabled"); + + b.Property("FromRoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("fromroleid"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Keyword") + .HasColumnType("text") + .HasColumnName("keyword"); + + b.HasKey("Id") + .HasName("pk_streamrolesettings"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_streamrolesettings_guildconfigid"); + + b.ToTable("streamrolesettings", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleWhitelistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("integer") + .HasColumnName("streamrolesettingsid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Username") + .HasColumnType("text") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_streamrolewhitelisteduser"); + + b.HasIndex("StreamRoleSettingsId") + .HasDatabaseName("ix_streamrolewhitelisteduser_streamrolesettingsid"); + + b.ToTable("streamrolewhitelisteduser", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.TodoModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ArchiveId") + .HasColumnType("integer") + .HasColumnName("archiveid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("IsDone") + .HasColumnType("boolean") + .HasColumnName("isdone"); + + b.Property("Todo") + .HasColumnType("text") + .HasColumnName("todo"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_todos"); + + b.HasIndex("ArchiveId") + .HasDatabaseName("ix_todos_archiveid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_todos_userid"); + + b.ToTable("todos", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnbanTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("UnbanAt") + .HasColumnType("timestamp without time zone") + .HasColumnName("unbanat"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_unbantimer"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_unbantimer_guildconfigid"); + + b.ToTable("unbantimer", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnmuteTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("UnmuteAt") + .HasColumnType("timestamp without time zone") + .HasColumnName("unmuteat"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_unmutetimer"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_unmutetimer_guildconfigid"); + + b.ToTable("unmutetimer", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnroleTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("UnbanAt") + .HasColumnType("timestamp without time zone") + .HasColumnName("unbanat"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_unroletimer"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_unroletimer_guildconfigid"); + + b.ToTable("unroletimer", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UserXpStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AwardedXp") + .HasColumnType("bigint") + .HasColumnName("awardedxp"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("NotifyOnLevelUp") + .HasColumnType("integer") + .HasColumnName("notifyonlevelup"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Xp") + .HasColumnType("bigint") + .HasColumnName("xp"); + + b.HasKey("Id") + .HasName("pk_userxpstats"); + + b.HasIndex("AwardedXp") + .HasDatabaseName("ix_userxpstats_awardedxp"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_userxpstats_guildid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_userxpstats_userid"); + + b.HasIndex("Xp") + .HasDatabaseName("ix_userxpstats_xp"); + + b.HasIndex("UserId", "GuildId") + .IsUnique() + .HasDatabaseName("ix_userxpstats_userid_guildid"); + + b.ToTable("userxpstats", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.VcRoleInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("VoiceChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("voicechannelid"); + + b.HasKey("Id") + .HasName("pk_vcroleinfo"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_vcroleinfo_guildconfigid"); + + b.ToTable("vcroleinfo", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AffinityId") + .HasColumnType("integer") + .HasColumnName("affinityid"); + + b.Property("ClaimerId") + .HasColumnType("integer") + .HasColumnName("claimerid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Price") + .HasColumnType("bigint") + .HasColumnName("price"); + + b.Property("WaifuId") + .HasColumnType("integer") + .HasColumnName("waifuid"); + + b.HasKey("Id") + .HasName("pk_waifuinfo"); + + b.HasIndex("AffinityId") + .HasDatabaseName("ix_waifuinfo_affinityid"); + + b.HasIndex("ClaimerId") + .HasDatabaseName("ix_waifuinfo_claimerid"); + + b.HasIndex("Price") + .HasDatabaseName("ix_waifuinfo_price"); + + b.HasIndex("WaifuId") + .IsUnique() + .HasDatabaseName("ix_waifuinfo_waifuid"); + + b.ToTable("waifuinfo", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("ItemEmoji") + .HasColumnType("text") + .HasColumnName("itememoji"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("WaifuInfoId") + .HasColumnType("integer") + .HasColumnName("waifuinfoid"); + + b.HasKey("Id") + .HasName("pk_waifuitem"); + + b.HasIndex("WaifuInfoId") + .HasDatabaseName("ix_waifuitem_waifuinfoid"); + + b.ToTable("waifuitem", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuUpdate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("NewId") + .HasColumnType("integer") + .HasColumnName("newid"); + + b.Property("OldId") + .HasColumnType("integer") + .HasColumnName("oldid"); + + b.Property("UpdateType") + .HasColumnType("integer") + .HasColumnName("updatetype"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_waifuupdates"); + + b.HasIndex("NewId") + .HasDatabaseName("ix_waifuupdates_newid"); + + b.HasIndex("OldId") + .HasDatabaseName("ix_waifuupdates_oldid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_waifuupdates_userid"); + + b.ToTable("waifuupdates", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Warning", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Forgiven") + .HasColumnType("boolean") + .HasColumnName("forgiven"); + + b.Property("ForgivenBy") + .HasColumnType("text") + .HasColumnName("forgivenby"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Moderator") + .HasColumnType("text") + .HasColumnName("moderator"); + + b.Property("Reason") + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Weight") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(1L) + .HasColumnName("weight"); + + b.HasKey("Id") + .HasName("pk_warnings"); + + b.HasIndex("DateAdded") + .HasDatabaseName("ix_warnings_dateadded"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_warnings_guildid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_warnings_userid"); + + b.ToTable("warnings", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WarningPunishment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Count") + .HasColumnType("integer") + .HasColumnName("count"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Punishment") + .HasColumnType("integer") + .HasColumnName("punishment"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("Time") + .HasColumnType("integer") + .HasColumnName("time"); + + b.HasKey("Id") + .HasName("pk_warningpunishment"); + + b.HasAlternateKey("GuildId", "Count") + .HasName("ak_warningpunishment_guildid_count"); + + b.ToTable("warningpunishment", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpCurrencyReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Amount") + .HasColumnType("integer") + .HasColumnName("amount"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Level") + .HasColumnType("integer") + .HasColumnName("level"); + + b.Property("XpSettingsId") + .HasColumnType("integer") + .HasColumnName("xpsettingsid"); + + b.HasKey("Id") + .HasName("pk_xpcurrencyreward"); + + b.HasIndex("XpSettingsId") + .HasDatabaseName("ix_xpcurrencyreward_xpsettingsid"); + + b.ToTable("xpcurrencyreward", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpRoleReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Level") + .HasColumnType("integer") + .HasColumnName("level"); + + b.Property("Remove") + .HasColumnType("boolean") + .HasColumnName("remove"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("XpSettingsId") + .HasColumnType("integer") + .HasColumnName("xpsettingsid"); + + b.HasKey("Id") + .HasName("pk_xprolereward"); + + b.HasIndex("XpSettingsId", "Level") + .IsUnique() + .HasDatabaseName("ix_xprolereward_xpsettingsid_level"); + + b.ToTable("xprolereward", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("ServerExcluded") + .HasColumnType("boolean") + .HasColumnName("serverexcluded"); + + b.HasKey("Id") + .HasName("pk_xpsettings"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_xpsettings_guildconfigid"); + + b.ToTable("xpsettings", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpShopOwnedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("IsUsing") + .HasColumnType("boolean") + .HasColumnName("isusing"); + + b.Property("ItemKey") + .IsRequired() + .HasColumnType("text") + .HasColumnName("itemkey"); + + b.Property("ItemType") + .HasColumnType("integer") + .HasColumnName("itemtype"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_xpshopowneditem"); + + b.HasIndex("UserId", "ItemType", "ItemKey") + .IsUnique() + .HasDatabaseName("ix_xpshopowneditem_userid_itemtype_itemkey"); + + b.ToTable("xpshopowneditem", (string)null); + }); + + modelBuilder.Entity("EllieBot.Services.GreetSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoDeleteTimer") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("autodeletetimer"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("GreetType") + .HasColumnType("integer") + .HasColumnName("greettype"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("IsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("isenabled"); + + b.Property("MessageText") + .HasColumnType("text") + .HasColumnName("messagetext"); + + b.HasKey("Id") + .HasName("pk_greetsettings"); + + b.HasIndex("GuildId", "GreetType") + .IsUnique() + .HasDatabaseName("ix_greetsettings_guildid_greettype"); + + b.ToTable("greetsettings", (string)null); + }); + + modelBuilder.Entity("EllieBot.Services.Rakeback", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Amount") + .HasColumnType("numeric") + .HasColumnName("amount"); + + b.HasKey("UserId") + .HasName("pk_rakeback"); + + b.ToTable("rakeback", (string)null); + }); + + modelBuilder.Entity("EllieBot.Services.UserBetStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Game") + .HasColumnType("integer") + .HasColumnName("game"); + + b.Property("LoseCount") + .HasColumnType("bigint") + .HasColumnName("losecount"); + + b.Property("MaxBet") + .HasColumnType("bigint") + .HasColumnName("maxbet"); + + b.Property("MaxWin") + .HasColumnType("bigint") + .HasColumnName("maxwin"); + + b.Property("PaidOut") + .HasColumnType("numeric") + .HasColumnName("paidout"); + + b.Property("TotalBet") + .HasColumnType("numeric") + .HasColumnName("totalbet"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("WinCount") + .HasColumnType("bigint") + .HasColumnName("wincount"); + + b.HasKey("Id") + .HasName("pk_userbetstats"); + + b.HasIndex("UserId", "Game") + .IsUnique() + .HasDatabaseName("ix_userbetstats_userid_game"); + + b.ToTable("userbetstats", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiAltSetting", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithOne("AntiAltSetting") + .HasForeignKey("EllieBot.Db.Models.AntiAltSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_antialtsetting_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiRaidSetting", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithOne("AntiRaidSetting") + .HasForeignKey("EllieBot.Db.Models.AntiRaidSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_antiraidsetting_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiSpamIgnore", b => + { + b.HasOne("EllieBot.Db.Models.AntiSpamSetting", null) + .WithMany("IgnoredChannels") + .HasForeignKey("AntiSpamSettingId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_antispamignore_antispamsetting_antispamsettingid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiSpamSetting", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithOne("AntiSpamSetting") + .HasForeignKey("EllieBot.Db.Models.AntiSpamSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_antispamsetting_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoTranslateUser", b => + { + b.HasOne("EllieBot.Db.Models.AutoTranslateChannel", "Channel") + .WithMany("Users") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_autotranslateusers_autotranslatechannels_channelid"); + + b.Navigation("Channel"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubApplicants", b => + { + b.HasOne("EllieBot.Db.Models.ClubInfo", "Club") + .WithMany("Applicants") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubapplicants_clubs_clubid"); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubapplicants_discorduser_userid"); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubBans", b => + { + b.HasOne("EllieBot.Db.Models.ClubInfo", "Club") + .WithMany("Bans") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubbans_clubs_clubid"); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubbans_discorduser_userid"); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubInfo", b => + { + b.HasOne("EllieBot.Db.Models.DiscordUser", "Owner") + .WithOne() + .HasForeignKey("EllieBot.Db.Models.ClubInfo", "OwnerId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("fk_clubs_discorduser_ownerid"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.CommandAlias", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("CommandAliases") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_commandalias_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.CommandCooldown", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("CommandCooldowns") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_commandcooldown_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.DelMsgOnCmdChannel", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("DelMsgOnCmdChannels") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_delmsgoncmdchannel_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.DiscordUser", b => + { + b.HasOne("EllieBot.Db.Models.ClubInfo", "Club") + .WithMany("Members") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.NoAction) + .HasConstraintName("fk_discorduser_clubs_clubid"); + + b.Navigation("Club"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ExcludedItem", b => + { + b.HasOne("EllieBot.Db.Models.XpSettings", "XpSettings") + .WithMany("ExclusionList") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_excludeditem_xpsettings_xpsettingsid"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FeedSub", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", "GuildConfig") + .WithMany("FeedSubs") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_feedsub_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilterChannelId", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("FilterInvitesChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_filterchannelid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilterLinksChannelId", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("FilterLinksChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_filterlinkschannelid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilterWordsChannelId", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("FilterWordsChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_filterwordschannelid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilteredWord", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("FilteredWords") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_filteredword_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FollowedStream", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("FollowedStreams") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_followedstream_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GCChannelId", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", "GuildConfig") + .WithMany("GenerateCurrencyChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_gcchannelid_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GiveawayUser", b => + { + b.HasOne("EllieBot.Db.Models.GiveawayModel", null) + .WithMany("Participants") + .HasForeignKey("GiveawayId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_giveawayuser_giveawaymodel_giveawayid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.IgnoredLogItem", b => + { + b.HasOne("EllieBot.Db.Models.LogSetting", "LogSetting") + .WithMany("LogIgnores") + .HasForeignKey("LogSettingId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_ignoredlogchannels_logsettings_logsettingid"); + + b.Navigation("LogSetting"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.MutedUserId", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("MutedUsers") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_muteduserid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Permissionv2", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("Permissions") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_permissions_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.PlaylistSong", b => + { + b.HasOne("EllieBot.Db.Models.MusicPlaylist", null) + .WithMany("Songs") + .HasForeignKey("MusicPlaylistId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_playlistsong_musicplaylists_musicplaylistid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Sar", b => + { + b.HasOne("EllieBot.Db.Models.SarGroup", null) + .WithMany("Roles") + .HasForeignKey("SarGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_sar_sargroup_sargroupid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("ShopEntries") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_shopentry_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ShopEntryItem", b => + { + b.HasOne("EllieBot.Db.Models.ShopEntry", null) + .WithMany("Items") + .HasForeignKey("ShopEntryId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_shopentryitem_shopentry_shopentryid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SlowmodeIgnoredRole", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredRoles") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_slowmodeignoredrole_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SlowmodeIgnoredUser", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredUsers") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_slowmodeignoreduser_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleBlacklistedUser", b => + { + b.HasOne("EllieBot.Db.Models.StreamRoleSettings", "StreamRoleSettings") + .WithMany("Blacklist") + .HasForeignKey("StreamRoleSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_streamroleblacklisteduser_streamrolesettings_streamrolesett~"); + + b.Navigation("StreamRoleSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleSettings", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", "GuildConfig") + .WithOne("StreamRole") + .HasForeignKey("EllieBot.Db.Models.StreamRoleSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_streamrolesettings_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleWhitelistedUser", b => + { + b.HasOne("EllieBot.Db.Models.StreamRoleSettings", "StreamRoleSettings") + .WithMany("Whitelist") + .HasForeignKey("StreamRoleSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_streamrolewhitelisteduser_streamrolesettings_streamrolesett~"); + + b.Navigation("StreamRoleSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.TodoModel", b => + { + b.HasOne("EllieBot.Db.Models.ArchivedTodoListModel", null) + .WithMany("Items") + .HasForeignKey("ArchiveId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_todos_todosarchive_archiveid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnbanTimer", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("UnbanTimer") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_unbantimer_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnmuteTimer", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("UnmuteTimers") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_unmutetimer_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnroleTimer", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("UnroleTimer") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_unroletimer_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.VcRoleInfo", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("VcRoleInfos") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_vcroleinfo_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuInfo", b => + { + b.HasOne("EllieBot.Db.Models.DiscordUser", "Affinity") + .WithMany() + .HasForeignKey("AffinityId") + .HasConstraintName("fk_waifuinfo_discorduser_affinityid"); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "Claimer") + .WithMany() + .HasForeignKey("ClaimerId") + .HasConstraintName("fk_waifuinfo_discorduser_claimerid"); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "Waifu") + .WithOne() + .HasForeignKey("EllieBot.Db.Models.WaifuInfo", "WaifuId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_waifuinfo_discorduser_waifuid"); + + b.Navigation("Affinity"); + + b.Navigation("Claimer"); + + b.Navigation("Waifu"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuItem", b => + { + b.HasOne("EllieBot.Db.Models.WaifuInfo", "WaifuInfo") + .WithMany("Items") + .HasForeignKey("WaifuInfoId") + .HasConstraintName("fk_waifuitem_waifuinfo_waifuinfoid"); + + b.Navigation("WaifuInfo"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuUpdate", b => + { + b.HasOne("EllieBot.Db.Models.DiscordUser", "New") + .WithMany() + .HasForeignKey("NewId") + .HasConstraintName("fk_waifuupdates_discorduser_newid"); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "Old") + .WithMany() + .HasForeignKey("OldId") + .HasConstraintName("fk_waifuupdates_discorduser_oldid"); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_waifuupdates_discorduser_userid"); + + b.Navigation("New"); + + b.Navigation("Old"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpCurrencyReward", b => + { + b.HasOne("EllieBot.Db.Models.XpSettings", "XpSettings") + .WithMany("CurrencyRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_xpcurrencyreward_xpsettings_xpsettingsid"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpRoleReward", b => + { + b.HasOne("EllieBot.Db.Models.XpSettings", "XpSettings") + .WithMany("RoleRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_xprolereward_xpsettings_xpsettingsid"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpSettings", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", "GuildConfig") + .WithOne("XpSettings") + .HasForeignKey("EllieBot.Db.Models.XpSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_xpsettings_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiSpamSetting", b => + { + b.Navigation("IgnoredChannels"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ArchivedTodoListModel", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoTranslateChannel", b => + { + b.Navigation("Users"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubInfo", b => + { + b.Navigation("Applicants"); + + b.Navigation("Bans"); + + b.Navigation("Members"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GiveawayModel", b => + { + b.Navigation("Participants"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GuildConfig", b => + { + b.Navigation("AntiAltSetting"); + + b.Navigation("AntiRaidSetting"); + + b.Navigation("AntiSpamSetting"); + + 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("GenerateCurrencyChannelIds"); + + b.Navigation("MutedUsers"); + + b.Navigation("Permissions"); + + b.Navigation("ShopEntries"); + + b.Navigation("SlowmodeIgnoredRoles"); + + b.Navigation("SlowmodeIgnoredUsers"); + + b.Navigation("StreamRole"); + + b.Navigation("UnbanTimer"); + + b.Navigation("UnmuteTimers"); + + b.Navigation("UnroleTimer"); + + b.Navigation("VcRoleInfos"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.LogSetting", b => + { + b.Navigation("LogIgnores"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.MusicPlaylist", b => + { + b.Navigation("Songs"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SarGroup", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleSettings", b => + { + b.Navigation("Blacklist"); + + b.Navigation("Whitelist"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuInfo", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpSettings", b => + { + b.Navigation("CurrencyRewards"); + + b.Navigation("ExclusionList"); + + b.Navigation("RoleRewards"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/EllieBot/Migrations/PostgreSql/20241127092257_sar-rework.cs b/src/EllieBot/Migrations/PostgreSql/20241127092257_sar-rework.cs new file mode 100644 index 0000000..0b68bb7 --- /dev/null +++ b/src/EllieBot/Migrations/PostgreSql/20241127092257_sar-rework.cs @@ -0,0 +1,153 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace EllieBot.Migrations.PostgreSql +{ + /// + public partial class sarrework : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "groupname"); + + migrationBuilder.DropTable( + name: "selfassignableroles"); + + migrationBuilder.CreateTable( + name: "sarautodelete", + columns: table => new + { + id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + guildid = table.Column(type: "numeric(20,0)", nullable: false), + isenabled = table.Column(type: "boolean", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_sarautodelete", x => x.id); + }); + + migrationBuilder.CreateTable( + name: "sargroup", + columns: table => new + { + id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + groupnumber = table.Column(type: "integer", nullable: false), + guildid = table.Column(type: "numeric(20,0)", nullable: false), + rolereq = table.Column(type: "numeric(20,0)", nullable: true), + isexclusive = table.Column(type: "boolean", nullable: false), + name = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + dateadded = table.Column(type: "timestamp without time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_sargroup", x => x.id); + table.UniqueConstraint("ak_sargroup_guildid_groupnumber", x => new { x.guildid, x.groupnumber }); + }); + + migrationBuilder.CreateTable( + name: "sar", + columns: table => new + { + id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + guildid = table.Column(type: "numeric(20,0)", nullable: false), + roleid = table.Column(type: "numeric(20,0)", nullable: false), + sargroupid = table.Column(type: "integer", nullable: false), + levelreq = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_sar", x => x.id); + table.UniqueConstraint("ak_sar_guildid_roleid", x => new { x.guildid, x.roleid }); + table.ForeignKey( + name: "fk_sar_sargroup_sargroupid", + column: x => x.sargroupid, + principalTable: "sargroup", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "ix_sar_sargroupid", + table: "sar", + column: "sargroupid"); + + migrationBuilder.CreateIndex( + name: "ix_sarautodelete_guildid", + table: "sarautodelete", + column: "guildid", + unique: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "sar"); + + migrationBuilder.DropTable( + name: "sarautodelete"); + + migrationBuilder.DropTable( + name: "sargroup"); + + migrationBuilder.CreateTable( + name: "groupname", + columns: table => new + { + id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + guildconfigid = table.Column(type: "integer", nullable: false), + dateadded = table.Column(type: "timestamp without time zone", nullable: true), + name = table.Column(type: "text", nullable: true), + number = table.Column(type: "integer", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_groupname", x => x.id); + table.ForeignKey( + name: "fk_groupname_guildconfigs_guildconfigid", + column: x => x.guildconfigid, + principalTable: "guildconfigs", + principalColumn: "id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "selfassignableroles", + columns: table => new + { + id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + dateadded = table.Column(type: "timestamp without time zone", nullable: true), + group = table.Column(type: "integer", nullable: false, defaultValue: 0), + guildid = table.Column(type: "numeric(20,0)", nullable: false), + levelrequirement = table.Column(type: "integer", nullable: false), + roleid = table.Column(type: "numeric(20,0)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_selfassignableroles", x => x.id); + }); + + migrationBuilder.CreateIndex( + name: "ix_groupname_guildconfigid_number", + table: "groupname", + columns: new[] { "guildconfigid", "number" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "ix_selfassignableroles_guildid_roleid", + table: "selfassignableroles", + columns: new[] { "guildid", "roleid" }, + unique: true); + } + } +} diff --git a/src/EllieBot/Migrations/PostgreSql/PostgreSqlContextModelSnapshot.cs b/src/EllieBot/Migrations/PostgreSql/PostgreSqlContextModelSnapshot.cs index d7e5362..4ed2d4b 100644 --- a/src/EllieBot/Migrations/PostgreSql/PostgreSqlContextModelSnapshot.cs +++ b/src/EllieBot/Migrations/PostgreSql/PostgreSqlContextModelSnapshot.cs @@ -1253,41 +1253,6 @@ namespace EllieBot.Migrations.PostgreSql b.ToTable("giveawayuser", (string)null); }); - modelBuilder.Entity("EllieBot.Db.Models.GroupName", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("integer") - .HasColumnName("id"); - - NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); - - b.Property("DateAdded") - .HasColumnType("timestamp without time zone") - .HasColumnName("dateadded"); - - b.Property("GuildConfigId") - .HasColumnType("integer") - .HasColumnName("guildconfigid"); - - b.Property("Name") - .HasColumnType("text") - .HasColumnName("name"); - - b.Property("Number") - .HasColumnType("integer") - .HasColumnName("number"); - - b.HasKey("Id") - .HasName("pk_groupname"); - - b.HasIndex("GuildConfigId", "Number") - .IsUnique() - .HasDatabaseName("ix_groupname_guildconfigid_number"); - - b.ToTable("groupname", (string)null); - }); - modelBuilder.Entity("EllieBot.Db.Models.GuildConfig", b => { b.Property("Id") @@ -2200,7 +2165,71 @@ namespace EllieBot.Migrations.PostgreSql b.ToTable("rotatingstatus", (string)null); }); - modelBuilder.Entity("EllieBot.Db.Models.SelfAssignedRole", b => + modelBuilder.Entity("EllieBot.Db.Models.Sar", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("LevelReq") + .HasColumnType("integer") + .HasColumnName("levelreq"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("SarGroupId") + .HasColumnType("integer") + .HasColumnName("sargroupid"); + + b.HasKey("Id") + .HasName("pk_sar"); + + b.HasAlternateKey("GuildId", "RoleId") + .HasName("ak_sar_guildid_roleid"); + + b.HasIndex("SarGroupId") + .HasDatabaseName("ix_sar_sargroupid"); + + b.ToTable("sar", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SarAutoDelete", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("IsEnabled") + .HasColumnType("boolean") + .HasColumnName("isenabled"); + + b.HasKey("Id") + .HasName("pk_sarautodelete"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_sarautodelete_guildid"); + + b.ToTable("sarautodelete", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SarGroup", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -2213,32 +2242,34 @@ namespace EllieBot.Migrations.PostgreSql .HasColumnType("timestamp without time zone") .HasColumnName("dateadded"); - b.Property("Group") - .ValueGeneratedOnAdd() + b.Property("GroupNumber") .HasColumnType("integer") - .HasDefaultValue(0) - .HasColumnName("group"); + .HasColumnName("groupnumber"); b.Property("GuildId") .HasColumnType("numeric(20,0)") .HasColumnName("guildid"); - b.Property("LevelRequirement") - .HasColumnType("integer") - .HasColumnName("levelrequirement"); + b.Property("IsExclusive") + .HasColumnType("boolean") + .HasColumnName("isexclusive"); - b.Property("RoleId") + b.Property("Name") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("name"); + + b.Property("RoleReq") .HasColumnType("numeric(20,0)") - .HasColumnName("roleid"); + .HasColumnName("rolereq"); b.HasKey("Id") - .HasName("pk_selfassignableroles"); + .HasName("pk_sargroup"); - b.HasIndex("GuildId", "RoleId") - .IsUnique() - .HasDatabaseName("ix_selfassignableroles_guildid_roleid"); + b.HasAlternateKey("GuildId", "GroupNumber") + .HasName("ak_sargroup_guildid_groupnumber"); - b.ToTable("selfassignableroles", (string)null); + b.ToTable("sargroup", (string)null); }); modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b => @@ -3527,18 +3558,6 @@ namespace EllieBot.Migrations.PostgreSql .HasConstraintName("fk_giveawayuser_giveawaymodel_giveawayid"); }); - modelBuilder.Entity("EllieBot.Db.Models.GroupName", b => - { - b.HasOne("EllieBot.Db.Models.GuildConfig", "GuildConfig") - .WithMany("SelfAssignableRoleGroupNames") - .HasForeignKey("GuildConfigId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired() - .HasConstraintName("fk_groupname_guildconfigs_guildconfigid"); - - b.Navigation("GuildConfig"); - }); - modelBuilder.Entity("EllieBot.Db.Models.IgnoredLogItem", b => { b.HasOne("EllieBot.Db.Models.LogSetting", "LogSetting") @@ -3578,6 +3597,16 @@ namespace EllieBot.Migrations.PostgreSql .HasConstraintName("fk_playlistsong_musicplaylists_musicplaylistid"); }); + modelBuilder.Entity("EllieBot.Db.Models.Sar", b => + { + b.HasOne("EllieBot.Db.Models.SarGroup", null) + .WithMany("Roles") + .HasForeignKey("SarGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_sar_sargroup_sargroupid"); + }); + modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b => { b.HasOne("EllieBot.Db.Models.GuildConfig", null) @@ -3854,8 +3883,6 @@ namespace EllieBot.Migrations.PostgreSql b.Navigation("Permissions"); - b.Navigation("SelfAssignableRoleGroupNames"); - b.Navigation("ShopEntries"); b.Navigation("SlowmodeIgnoredRoles"); @@ -3885,6 +3912,11 @@ namespace EllieBot.Migrations.PostgreSql b.Navigation("Songs"); }); + modelBuilder.Entity("EllieBot.Db.Models.SarGroup", b => + { + b.Navigation("Roles"); + }); + modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b => { b.Navigation("Items"); diff --git a/src/EllieBot/Migrations/Sqlite/20241102022949_no-discrim-and-flag-translate.cs b/src/EllieBot/Migrations/Sqlite/20241102022949_no-discrim-and-flag-translate.cs index f9ddda7..0900e63 100644 --- a/src/EllieBot/Migrations/Sqlite/20241102022949_no-discrim-and-flag-translate.cs +++ b/src/EllieBot/Migrations/Sqlite/20241102022949_no-discrim-and-flag-translate.cs @@ -11,8 +11,6 @@ namespace EllieBot.Migrations /// protected override void Up(MigrationBuilder migrationBuilder) { - MigrationQueries.UpdateUsernames(migrationBuilder); - migrationBuilder.DropColumn( name: "Discriminator", table: "DiscordUser"); diff --git a/src/EllieBot/Migrations/Sqlite/20241127092212_sar-rework.Designer.cs b/src/EllieBot/Migrations/Sqlite/20241127092212_sar-rework.Designer.cs new file mode 100644 index 0000000..e60dcab --- /dev/null +++ b/src/EllieBot/Migrations/Sqlite/20241127092212_sar-rework.Designer.cs @@ -0,0 +1,3048 @@ +// +using System; +using EllieBot.Db; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace EllieBot.Migrations +{ + [DbContext(typeof(SqliteContext))] + [Migration("20241127092212_sar-rework")] + partial class sarrework + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.8"); + + modelBuilder.Entity("EllieBot.Db.Models.AntiAltSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .HasColumnType("INTEGER"); + + b.Property("ActionDurationMinutes") + .HasColumnType("INTEGER"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("MinAge") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("AntiAltSetting"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiRaidSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + 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("EllieBot.Db.Models.AntiSpamIgnore", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AntiSpamSettingId") + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("AntiSpamSettingId"); + + b.ToTable("AntiSpamIgnore"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiSpamSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("MessageThreshold") + .HasColumnType("INTEGER"); + + b.Property("MuteTime") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("AntiSpamSetting"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ArchivedTodoListModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("TodosArchive"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoCommand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("ChannelName") + .HasColumnType("TEXT"); + + b.Property("CommandText") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("GuildName") + .HasColumnType("TEXT"); + + b.Property("Interval") + .HasColumnType("INTEGER"); + + b.Property("VoiceChannelId") + .HasColumnType("INTEGER"); + + b.Property("VoiceChannelName") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("AutoCommands"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoPublishChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("AutoPublishChannel"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoTranslateChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoDelete") + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId") + .IsUnique(); + + b.HasIndex("GuildId"); + + b.ToTable("AutoTranslateChannels"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoTranslateUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Source") + .HasColumnType("TEXT"); + + b.Property("Target") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasAlternateKey("ChannelId", "UserId"); + + b.ToTable("AutoTranslateUsers"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("PruneDays") + .HasColumnType("INTEGER"); + + b.Property("Text") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("BanTemplates"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.BankUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Balance") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("BankUsers"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.BlacklistEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Blacklist"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubApplicants", b => + { + b.Property("ClubId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("ClubId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ClubApplicants"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubBans", b => + { + b.Property("ClubId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("ClubId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ClubBans"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("ImageUrl") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("OwnerId") + .HasColumnType("INTEGER"); + + b.Property("Xp") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("OwnerId") + .IsUnique(); + + b.ToTable("Clubs"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.CommandAlias", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + 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("EllieBot.Db.Models.CommandCooldown", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CommandName") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Seconds") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("CommandCooldown"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.CurrencyTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Amount") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Extra") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("OtherId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValueSql("NULL"); + + b.Property("Type") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("CurrencyTransactions"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.DelMsgOnCmdChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("State") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("DelMsgOnCmdChannel"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.DiscordPermOverride", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Command") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Perm") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "Command") + .IsUnique(); + + b.ToTable("DiscordPermOverrides"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.DiscordUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AvatarId") + .HasColumnType("TEXT"); + + b.Property("ClubId") + .HasColumnType("INTEGER"); + + b.Property("CurrencyAmount") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0L); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IsClubAdmin") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(false); + + b.Property("NotifyOnLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0); + + b.Property("TotalXp") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0L); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasAlternateKey("UserId"); + + b.HasIndex("ClubId"); + + b.HasIndex("CurrencyAmount"); + + b.HasIndex("TotalXp"); + + b.HasIndex("UserId"); + + b.HasIndex("Username"); + + b.ToTable("DiscordUser"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.EllieExpression", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AllowTarget") + .HasColumnType("INTEGER"); + + b.Property("AutoDeleteTrigger") + .HasColumnType("INTEGER"); + + b.Property("ContainsAnywhere") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DmResponse") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Reactions") + .HasColumnType("TEXT"); + + b.Property("Response") + .HasColumnType("TEXT"); + + b.Property("Trigger") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Expressions"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ExcludedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("INTEGER"); + + b.Property("ItemType") + .HasColumnType("INTEGER"); + + b.Property("XpSettingsId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId"); + + b.ToTable("ExcludedItem"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FeedSub", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + 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("EllieBot.Db.Models.FilterChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilterChannelId"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilterLinksChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilterLinksChannelId"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilterWordsChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilterWordsChannelId"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilteredWord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Word") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilteredWord"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FlagTranslateChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "ChannelId") + .IsUnique(); + + b.ToTable("FlagTranslateChannel"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FollowedStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + 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("EllieBot.Db.Models.GCChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("GCChannelId"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GamblingStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Bet") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Feature") + .HasColumnType("TEXT"); + + b.Property("PaidOut") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Feature") + .IsUnique(); + + b.ToTable("GamblingStats"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GiveawayModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("EndsAt") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("MessageId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("GiveawayModel"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GiveawayUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("GiveawayId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GiveawayId", "UserId") + .IsUnique(); + + b.ToTable("GiveawayUser"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GuildConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoAssignRoleIds") + .HasColumnType("TEXT"); + + b.Property("AutoDeleteSelfAssignedRoleMessages") + .HasColumnType("INTEGER"); + + b.Property("CleverbotEnabled") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DeleteMessageOnCommand") + .HasColumnType("INTEGER"); + + b.Property("DeleteStreamOnlineMessage") + .HasColumnType("INTEGER"); + + b.Property("DisableGlobalExpressions") + .HasColumnType("INTEGER"); + + b.Property("ExclusiveSelfAssignedRoles") + .HasColumnType("INTEGER"); + + b.Property("FilterInvites") + .HasColumnType("INTEGER"); + + b.Property("FilterLinks") + .HasColumnType("INTEGER"); + + b.Property("FilterWords") + .HasColumnType("INTEGER"); + + b.Property("GameVoiceChannel") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Locale") + .HasColumnType("TEXT"); + + b.Property("MuteRoleName") + .HasColumnType("TEXT"); + + b.Property("NotifyStreamOffline") + .HasColumnType("INTEGER"); + + b.Property("PermissionRole") + .HasColumnType("TEXT"); + + b.Property("Prefix") + .HasColumnType("TEXT"); + + b.Property("StickyRoles") + .HasColumnType("INTEGER"); + + b.Property("TimeZoneId") + .HasColumnType("TEXT"); + + b.Property("VerboseErrors") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(true); + + b.Property("VerbosePermissions") + .HasColumnType("INTEGER"); + + b.Property("WarnExpireAction") + .HasColumnType("INTEGER"); + + b.Property("WarnExpireHours") + .HasColumnType("INTEGER"); + + b.Property("WarningsInitialized") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.HasIndex("WarnExpireHours"); + + b.ToTable("GuildConfigs"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.HoneypotChannel", b => + { + b.Property("GuildId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.HasKey("GuildId"); + + b.ToTable("HoneyPotChannels"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.IgnoredLogItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemType") + .HasColumnType("INTEGER"); + + b.Property("LogItemId") + .HasColumnType("INTEGER"); + + b.Property("LogSettingId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("LogSettingId", "LogItemId", "ItemType") + .IsUnique(); + + b.ToTable("IgnoredLogChannels"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ImageOnlyChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId") + .IsUnique(); + + b.ToTable("ImageOnlyChannels"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.LogSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelCreatedId") + .HasColumnType("INTEGER"); + + b.Property("ChannelDestroyedId") + .HasColumnType("INTEGER"); + + b.Property("ChannelUpdatedId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("LogOtherId") + .HasColumnType("INTEGER"); + + b.Property("LogUserPresenceId") + .HasColumnType("INTEGER"); + + b.Property("LogVoicePresenceId") + .HasColumnType("INTEGER"); + + b.Property("LogVoicePresenceTTSId") + .HasColumnType("INTEGER"); + + b.Property("LogWarnsId") + .HasColumnType("INTEGER"); + + b.Property("MessageDeletedId") + .HasColumnType("INTEGER"); + + b.Property("MessageUpdatedId") + .HasColumnType("INTEGER"); + + b.Property("ThreadCreatedId") + .HasColumnType("INTEGER"); + + b.Property("ThreadDeletedId") + .HasColumnType("INTEGER"); + + b.Property("UserBannedId") + .HasColumnType("INTEGER"); + + b.Property("UserJoinedId") + .HasColumnType("INTEGER"); + + b.Property("UserLeftId") + .HasColumnType("INTEGER"); + + b.Property("UserMutedId") + .HasColumnType("INTEGER"); + + b.Property("UserUnbannedId") + .HasColumnType("INTEGER"); + + b.Property("UserUpdatedId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("LogSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.MusicPlayerSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoDisconnect") + .HasColumnType("INTEGER"); + + b.Property("AutoPlay") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("MusicChannelId") + .HasColumnType("INTEGER"); + + b.Property("PlayerRepeat") + .HasColumnType("INTEGER"); + + b.Property("QualityPreset") + .HasColumnType("INTEGER"); + + b.Property("Volume") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(100); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("MusicPlayerSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.MusicPlaylist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Author") + .HasColumnType("TEXT"); + + b.Property("AuthorId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("MusicPlaylists"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.MutedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("MutedUserId"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.NCPixel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Color") + .HasColumnType("INTEGER"); + + b.Property("OwnerId") + .HasColumnType("INTEGER"); + + b.Property("Position") + .HasColumnType("INTEGER"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasAlternateKey("Position"); + + b.HasIndex("OwnerId"); + + b.ToTable("NCPixel"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.PatronUser", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AmountCents") + .HasColumnType("INTEGER"); + + b.Property("LastCharge") + .HasColumnType("TEXT"); + + b.Property("UniquePlatformUserId") + .HasColumnType("TEXT"); + + b.Property("ValidThru") + .HasColumnType("TEXT"); + + b.HasKey("UserId"); + + b.HasIndex("UniquePlatformUserId") + .IsUnique(); + + b.ToTable("Patrons"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Permissionv2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("IsCustomCommand") + .HasColumnType("INTEGER"); + + b.Property("PrimaryTarget") + .HasColumnType("INTEGER"); + + b.Property("PrimaryTargetId") + .HasColumnType("INTEGER"); + + b.Property("SecondaryTarget") + .HasColumnType("INTEGER"); + + b.Property("SecondaryTargetName") + .HasColumnType("TEXT"); + + b.Property("State") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.PlantedCurrency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Amount") + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("MessageId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId"); + + b.HasIndex("MessageId") + .IsUnique(); + + b.ToTable("PlantedCurrency"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.PlaylistSong", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + 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("EllieBot.Db.Models.Quote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuthorId") + .HasColumnType("INTEGER"); + + b.Property("AuthorName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Keyword") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Text") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.HasIndex("Keyword"); + + b.ToTable("Quotes"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ReactionRoleV2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Emote") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Group") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("LevelReq") + .HasColumnType("INTEGER"); + + b.Property("MessageId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.HasIndex("MessageId", "Emote") + .IsUnique(); + + b.ToTable("ReactionRoles"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Reminder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IsPrivate") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("When"); + + b.ToTable("Reminders"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Repeater", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Interval") + .HasColumnType("TEXT"); + + b.Property("LastMessageId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("NoRedundant") + .HasColumnType("INTEGER"); + + b.Property("StartTimeOfDay") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Repeaters"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.RewardedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AmountRewardedThisMonth") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("LastReward") + .HasColumnType("TEXT"); + + b.Property("PlatformUserId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PlatformUserId") + .IsUnique(); + + b.ToTable("RewardedUsers"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.RotatingPlayingStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RotatingStatus"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Sar", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("LevelReq") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("SarGroupId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasAlternateKey("GuildId", "RoleId"); + + b.HasIndex("SarGroupId"); + + b.ToTable("Sar"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SarAutoDelete", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("IsEnabled") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("SarAutoDelete"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SarGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GroupNumber") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("IsExclusive") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("RoleReq") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasAlternateKey("GuildId", "GroupNumber"); + + b.ToTable("SarGroup"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuthorId") + .HasColumnType("INTEGER"); + + b.Property("Command") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("RoleName") + .HasColumnType("TEXT"); + + b.Property("RoleRequirement") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("ShopEntry"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ShopEntryItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ShopEntryId") + .HasColumnType("INTEGER"); + + b.Property("Text") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ShopEntryId"); + + b.ToTable("ShopEntryItem"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SlowmodeIgnoredRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("SlowmodeIgnoredRole"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SlowmodeIgnoredUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("SlowmodeIgnoredUser"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StickyRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("RoleIds") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "UserId") + .IsUnique(); + + b.ToTable("StickyRoles"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamOnlineMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("MessageId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("StreamOnlineMessages"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleBlacklistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("StreamRoleSettingsId"); + + b.ToTable("StreamRoleBlacklistedUser"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddRoleId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("FromRoleId") + .HasColumnType("INTEGER"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Keyword") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("StreamRoleSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleWhitelistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("StreamRoleSettingsId"); + + b.ToTable("StreamRoleWhitelistedUser"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.TodoModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArchiveId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IsDone") + .HasColumnType("INTEGER"); + + b.Property("Todo") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ArchiveId"); + + b.HasIndex("UserId"); + + b.ToTable("Todos"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnbanTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UnbanAt") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("UnbanTimer"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnmuteTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UnmuteAt") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("UnmuteTimer"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnroleTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("UnbanAt") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("UnroleTimer"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UserXpStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AwardedXp") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("NotifyOnLevelUp") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + 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("EllieBot.Db.Models.VcRoleInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("VoiceChannelId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("VcRoleInfo"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AffinityId") + .HasColumnType("INTEGER"); + + b.Property("ClaimerId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("WaifuId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("AffinityId"); + + b.HasIndex("ClaimerId"); + + b.HasIndex("Price"); + + b.HasIndex("WaifuId") + .IsUnique(); + + b.ToTable("WaifuInfo"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemEmoji") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("WaifuInfoId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("WaifuInfoId"); + + b.ToTable("WaifuItem"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuUpdate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("NewId") + .HasColumnType("INTEGER"); + + b.Property("OldId") + .HasColumnType("INTEGER"); + + b.Property("UpdateType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NewId"); + + b.HasIndex("OldId"); + + b.HasIndex("UserId"); + + b.ToTable("WaifuUpdates"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Warning", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Forgiven") + .HasColumnType("INTEGER"); + + b.Property("ForgivenBy") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Moderator") + .HasColumnType("TEXT"); + + b.Property("Reason") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Weight") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(1L); + + b.HasKey("Id"); + + b.HasIndex("DateAdded"); + + b.HasIndex("GuildId"); + + b.HasIndex("UserId"); + + b.ToTable("Warnings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WarningPunishment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Count") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Punishment") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("Time") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasAlternateKey("GuildId", "Count"); + + b.ToTable("WarningPunishment"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpCurrencyReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Amount") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("XpSettingsId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId"); + + b.ToTable("XpCurrencyReward"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpRoleReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Remove") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("XpSettingsId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId", "Level") + .IsUnique(); + + b.ToTable("XpRoleReward"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("ServerExcluded") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("XpSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpShopOwnedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IsUsing") + .HasColumnType("INTEGER"); + + b.Property("ItemKey") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ItemType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId", "ItemType", "ItemKey") + .IsUnique(); + + b.ToTable("XpShopOwnedItem"); + }); + + modelBuilder.Entity("EllieBot.Services.GreetSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoDeleteTimer") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("GreetType") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("IsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(false); + + b.Property("MessageText") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "GreetType") + .IsUnique(); + + b.ToTable("GreetSettings"); + }); + + modelBuilder.Entity("EllieBot.Services.Rakeback", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Amount") + .HasColumnType("TEXT"); + + b.HasKey("UserId"); + + b.ToTable("Rakeback"); + }); + + modelBuilder.Entity("EllieBot.Services.UserBetStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("LoseCount") + .HasColumnType("INTEGER"); + + b.Property("MaxBet") + .HasColumnType("INTEGER"); + + b.Property("MaxWin") + .HasColumnType("INTEGER"); + + b.Property("PaidOut") + .HasColumnType("TEXT"); + + b.Property("TotalBet") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("WinCount") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId", "Game") + .IsUnique(); + + b.ToTable("UserBetStats"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiAltSetting", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithOne("AntiAltSetting") + .HasForeignKey("EllieBot.Db.Models.AntiAltSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiRaidSetting", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithOne("AntiRaidSetting") + .HasForeignKey("EllieBot.Db.Models.AntiRaidSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiSpamIgnore", b => + { + b.HasOne("EllieBot.Db.Models.AntiSpamSetting", null) + .WithMany("IgnoredChannels") + .HasForeignKey("AntiSpamSettingId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiSpamSetting", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithOne("AntiSpamSetting") + .HasForeignKey("EllieBot.Db.Models.AntiSpamSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoTranslateUser", b => + { + b.HasOne("EllieBot.Db.Models.AutoTranslateChannel", "Channel") + .WithMany("Users") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Channel"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubApplicants", b => + { + b.HasOne("EllieBot.Db.Models.ClubInfo", "Club") + .WithMany("Applicants") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubBans", b => + { + b.HasOne("EllieBot.Db.Models.ClubInfo", "Club") + .WithMany("Bans") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubInfo", b => + { + b.HasOne("EllieBot.Db.Models.DiscordUser", "Owner") + .WithOne() + .HasForeignKey("EllieBot.Db.Models.ClubInfo", "OwnerId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.CommandAlias", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("CommandAliases") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.CommandCooldown", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("CommandCooldowns") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.DelMsgOnCmdChannel", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("DelMsgOnCmdChannels") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("EllieBot.Db.Models.DiscordUser", b => + { + b.HasOne("EllieBot.Db.Models.ClubInfo", "Club") + .WithMany("Members") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.NoAction); + + b.Navigation("Club"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ExcludedItem", b => + { + b.HasOne("EllieBot.Db.Models.XpSettings", "XpSettings") + .WithMany("ExclusionList") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FeedSub", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", "GuildConfig") + .WithMany("FeedSubs") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilterChannelId", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("FilterInvitesChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilterLinksChannelId", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("FilterLinksChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilterWordsChannelId", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("FilterWordsChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilteredWord", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("FilteredWords") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FollowedStream", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("FollowedStreams") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GCChannelId", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", "GuildConfig") + .WithMany("GenerateCurrencyChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GiveawayUser", b => + { + b.HasOne("EllieBot.Db.Models.GiveawayModel", null) + .WithMany("Participants") + .HasForeignKey("GiveawayId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("EllieBot.Db.Models.IgnoredLogItem", b => + { + b.HasOne("EllieBot.Db.Models.LogSetting", "LogSetting") + .WithMany("LogIgnores") + .HasForeignKey("LogSettingId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LogSetting"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.MutedUserId", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("MutedUsers") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Permissionv2", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("Permissions") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.PlaylistSong", b => + { + b.HasOne("EllieBot.Db.Models.MusicPlaylist", null) + .WithMany("Songs") + .HasForeignKey("MusicPlaylistId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Sar", b => + { + b.HasOne("EllieBot.Db.Models.SarGroup", null) + .WithMany("Roles") + .HasForeignKey("SarGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("ShopEntries") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ShopEntryItem", b => + { + b.HasOne("EllieBot.Db.Models.ShopEntry", null) + .WithMany("Items") + .HasForeignKey("ShopEntryId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SlowmodeIgnoredRole", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredRoles") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SlowmodeIgnoredUser", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredUsers") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleBlacklistedUser", b => + { + b.HasOne("EllieBot.Db.Models.StreamRoleSettings", "StreamRoleSettings") + .WithMany("Blacklist") + .HasForeignKey("StreamRoleSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("StreamRoleSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleSettings", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", "GuildConfig") + .WithOne("StreamRole") + .HasForeignKey("EllieBot.Db.Models.StreamRoleSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleWhitelistedUser", b => + { + b.HasOne("EllieBot.Db.Models.StreamRoleSettings", "StreamRoleSettings") + .WithMany("Whitelist") + .HasForeignKey("StreamRoleSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("StreamRoleSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.TodoModel", b => + { + b.HasOne("EllieBot.Db.Models.ArchivedTodoListModel", null) + .WithMany("Items") + .HasForeignKey("ArchiveId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnbanTimer", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("UnbanTimer") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnmuteTimer", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("UnmuteTimers") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnroleTimer", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("UnroleTimer") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.VcRoleInfo", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("VcRoleInfos") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuInfo", b => + { + b.HasOne("EllieBot.Db.Models.DiscordUser", "Affinity") + .WithMany() + .HasForeignKey("AffinityId"); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "Claimer") + .WithMany() + .HasForeignKey("ClaimerId"); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "Waifu") + .WithOne() + .HasForeignKey("EllieBot.Db.Models.WaifuInfo", "WaifuId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Affinity"); + + b.Navigation("Claimer"); + + b.Navigation("Waifu"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuItem", b => + { + b.HasOne("EllieBot.Db.Models.WaifuInfo", "WaifuInfo") + .WithMany("Items") + .HasForeignKey("WaifuInfoId"); + + b.Navigation("WaifuInfo"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuUpdate", b => + { + b.HasOne("EllieBot.Db.Models.DiscordUser", "New") + .WithMany() + .HasForeignKey("NewId"); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "Old") + .WithMany() + .HasForeignKey("OldId"); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("New"); + + b.Navigation("Old"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpCurrencyReward", b => + { + b.HasOne("EllieBot.Db.Models.XpSettings", "XpSettings") + .WithMany("CurrencyRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpRoleReward", b => + { + b.HasOne("EllieBot.Db.Models.XpSettings", "XpSettings") + .WithMany("RoleRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpSettings", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", "GuildConfig") + .WithOne("XpSettings") + .HasForeignKey("EllieBot.Db.Models.XpSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiSpamSetting", b => + { + b.Navigation("IgnoredChannels"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ArchivedTodoListModel", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoTranslateChannel", b => + { + b.Navigation("Users"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubInfo", b => + { + b.Navigation("Applicants"); + + b.Navigation("Bans"); + + b.Navigation("Members"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GiveawayModel", b => + { + b.Navigation("Participants"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GuildConfig", b => + { + b.Navigation("AntiAltSetting"); + + b.Navigation("AntiRaidSetting"); + + b.Navigation("AntiSpamSetting"); + + 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("GenerateCurrencyChannelIds"); + + b.Navigation("MutedUsers"); + + b.Navigation("Permissions"); + + b.Navigation("ShopEntries"); + + b.Navigation("SlowmodeIgnoredRoles"); + + b.Navigation("SlowmodeIgnoredUsers"); + + b.Navigation("StreamRole"); + + b.Navigation("UnbanTimer"); + + b.Navigation("UnmuteTimers"); + + b.Navigation("UnroleTimer"); + + b.Navigation("VcRoleInfos"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.LogSetting", b => + { + b.Navigation("LogIgnores"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.MusicPlaylist", b => + { + b.Navigation("Songs"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SarGroup", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleSettings", b => + { + b.Navigation("Blacklist"); + + b.Navigation("Whitelist"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuInfo", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpSettings", b => + { + b.Navigation("CurrencyRewards"); + + b.Navigation("ExclusionList"); + + b.Navigation("RoleRewards"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/EllieBot/Migrations/Sqlite/20241127092212_sar-rework.cs b/src/EllieBot/Migrations/Sqlite/20241127092212_sar-rework.cs new file mode 100644 index 0000000..66e84e8 --- /dev/null +++ b/src/EllieBot/Migrations/Sqlite/20241127092212_sar-rework.cs @@ -0,0 +1,152 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace EllieBot.Migrations +{ + /// + public partial class sarrework : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "GroupName"); + + migrationBuilder.DropTable( + name: "SelfAssignableRoles"); + + migrationBuilder.CreateTable( + name: "SarAutoDelete", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + GuildId = table.Column(type: "INTEGER", nullable: false), + IsEnabled = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SarAutoDelete", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "SarGroup", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + GroupNumber = table.Column(type: "INTEGER", nullable: false), + GuildId = table.Column(type: "INTEGER", nullable: false), + RoleReq = table.Column(type: "INTEGER", nullable: true), + IsExclusive = table.Column(type: "INTEGER", nullable: false), + Name = table.Column(type: "TEXT", maxLength: 100, nullable: true), + DateAdded = table.Column(type: "TEXT", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_SarGroup", x => x.Id); + table.UniqueConstraint("AK_SarGroup_GuildId_GroupNumber", x => new { x.GuildId, x.GroupNumber }); + }); + + migrationBuilder.CreateTable( + name: "Sar", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + GuildId = table.Column(type: "INTEGER", nullable: false), + RoleId = table.Column(type: "INTEGER", nullable: false), + SarGroupId = table.Column(type: "INTEGER", nullable: false), + LevelReq = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Sar", x => x.Id); + table.UniqueConstraint("AK_Sar_GuildId_RoleId", x => new { x.GuildId, x.RoleId }); + table.ForeignKey( + name: "FK_Sar_SarGroup_SarGroupId", + column: x => x.SarGroupId, + principalTable: "SarGroup", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateIndex( + name: "IX_Sar_SarGroupId", + table: "Sar", + column: "SarGroupId"); + + migrationBuilder.CreateIndex( + name: "IX_SarAutoDelete_GuildId", + table: "SarAutoDelete", + column: "GuildId", + unique: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Sar"); + + migrationBuilder.DropTable( + name: "SarAutoDelete"); + + migrationBuilder.DropTable( + name: "SarGroup"); + + migrationBuilder.CreateTable( + name: "GroupName", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + GuildConfigId = table.Column(type: "INTEGER", nullable: false), + DateAdded = table.Column(type: "TEXT", nullable: true), + Name = table.Column(type: "TEXT", nullable: true), + Number = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_GroupName", x => x.Id); + table.ForeignKey( + name: "FK_GroupName_GuildConfigs_GuildConfigId", + column: x => x.GuildConfigId, + principalTable: "GuildConfigs", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "SelfAssignableRoles", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + DateAdded = table.Column(type: "TEXT", nullable: true), + Group = table.Column(type: "INTEGER", nullable: false, defaultValue: 0), + GuildId = table.Column(type: "INTEGER", nullable: false), + LevelRequirement = table.Column(type: "INTEGER", nullable: false), + RoleId = table.Column(type: "INTEGER", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_SelfAssignableRoles", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_GroupName_GuildConfigId_Number", + table: "GroupName", + columns: new[] { "GuildConfigId", "Number" }, + unique: true); + + migrationBuilder.CreateIndex( + name: "IX_SelfAssignableRoles_GuildId_RoleId", + table: "SelfAssignableRoles", + columns: new[] { "GuildId", "RoleId" }, + unique: true); + } + } +} diff --git a/src/EllieBot/Migrations/Sqlite/EllieSqliteContextModelSnapshot.cs b/src/EllieBot/Migrations/Sqlite/EllieSqliteContextModelSnapshot.cs index 66f5132..8a10c5a 100644 --- a/src/EllieBot/Migrations/Sqlite/EllieSqliteContextModelSnapshot.cs +++ b/src/EllieBot/Migrations/Sqlite/EllieSqliteContextModelSnapshot.cs @@ -932,32 +932,6 @@ namespace EllieBot.Migrations b.ToTable("GiveawayUser"); }); - modelBuilder.Entity("EllieBot.Db.Models.GroupName", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateAdded") - .HasColumnType("TEXT"); - - 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("EllieBot.Db.Models.GuildConfig", b => { b.Property("Id") @@ -1640,7 +1614,54 @@ namespace EllieBot.Migrations b.ToTable("RotatingStatus"); }); - modelBuilder.Entity("EllieBot.Db.Models.SelfAssignedRole", b => + modelBuilder.Entity("EllieBot.Db.Models.Sar", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("LevelReq") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("SarGroupId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasAlternateKey("GuildId", "RoleId"); + + b.HasIndex("SarGroupId"); + + b.ToTable("Sar"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SarAutoDelete", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("IsEnabled") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("SarAutoDelete"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SarGroup", b => { b.Property("Id") .ValueGeneratedOnAdd() @@ -1649,26 +1670,27 @@ namespace EllieBot.Migrations b.Property("DateAdded") .HasColumnType("TEXT"); - b.Property("Group") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER") - .HasDefaultValue(0); + b.Property("GroupNumber") + .HasColumnType("INTEGER"); b.Property("GuildId") .HasColumnType("INTEGER"); - b.Property("LevelRequirement") + b.Property("IsExclusive") .HasColumnType("INTEGER"); - b.Property("RoleId") + b.Property("Name") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("RoleReq") .HasColumnType("INTEGER"); b.HasKey("Id"); - b.HasIndex("GuildId", "RoleId") - .IsUnique(); + b.HasAlternateKey("GuildId", "GroupNumber"); - b.ToTable("SelfAssignableRoles"); + b.ToTable("SarGroup"); }); modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b => @@ -2660,17 +2682,6 @@ namespace EllieBot.Migrations .IsRequired(); }); - modelBuilder.Entity("EllieBot.Db.Models.GroupName", b => - { - b.HasOne("EllieBot.Db.Models.GuildConfig", "GuildConfig") - .WithMany("SelfAssignableRoleGroupNames") - .HasForeignKey("GuildConfigId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("GuildConfig"); - }); - modelBuilder.Entity("EllieBot.Db.Models.IgnoredLogItem", b => { b.HasOne("EllieBot.Db.Models.LogSetting", "LogSetting") @@ -2706,6 +2717,15 @@ namespace EllieBot.Migrations .OnDelete(DeleteBehavior.Cascade); }); + modelBuilder.Entity("EllieBot.Db.Models.Sar", b => + { + b.HasOne("EllieBot.Db.Models.SarGroup", null) + .WithMany("Roles") + .HasForeignKey("SarGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b => { b.HasOne("EllieBot.Db.Models.GuildConfig", null) @@ -2960,8 +2980,6 @@ namespace EllieBot.Migrations b.Navigation("Permissions"); - b.Navigation("SelfAssignableRoleGroupNames"); - b.Navigation("ShopEntries"); b.Navigation("SlowmodeIgnoredRoles"); @@ -2991,6 +3009,11 @@ namespace EllieBot.Migrations b.Navigation("Songs"); }); + modelBuilder.Entity("EllieBot.Db.Models.SarGroup", b => + { + b.Navigation("Roles"); + }); + modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b => { b.Navigation("Items"); diff --git a/src/EllieBot/Modules/Administration/DangerousCommands/CleanupService.cs b/src/EllieBot/Modules/Administration/DangerousCommands/CleanupService.cs index fcf5612..56cb15f 100644 --- a/src/EllieBot/Modules/Administration/DangerousCommands/CleanupService.cs +++ b/src/EllieBot/Modules/Administration/DangerousCommands/CleanupService.cs @@ -75,7 +75,7 @@ public sealed class CleanupService : ICleanupService, IReadyExecutor, IEService Log.Information("Leaving {RemainingCount} guilds, 1 every second. {DontDeleteCount} will remain", allGuildIds.Length - dontDelete.Count, dontDelete.Count); - + foreach (var guildId in allGuildIds) { if (dontDelete.Contains(guildId)) @@ -136,7 +136,7 @@ public sealed class CleanupService : ICleanupService, IReadyExecutor, IEService await using var linqCtx = ctx.CreateLinqToDBContext(); await using var tempTable = linqCtx.CreateTempTable(); - foreach (var chunk in allIds.Chunk(20000)) + foreach (var chunk in allIds.Chunk(10000)) { await tempTable.BulkCopyAsync(chunk.Select(x => new CleanupId() { @@ -187,13 +187,6 @@ public sealed class CleanupService : ICleanupService, IReadyExecutor, IEService .Contains(x.GuildId)) .DeleteAsync(); - // delete ignored users - await ctx.GetTable() - .Where(x => x.GuildId != null - && !tempTable.Select(x => x.GuildId) - .Contains(x.GuildId.Value)) - .DeleteAsync(); - // delete perm overrides await ctx.GetTable() .Where(x => x.GuildId != null @@ -219,6 +212,48 @@ public sealed class CleanupService : ICleanupService, IReadyExecutor, IEService .Contains(x.GuildId)) .DeleteAsync(); + // delete sar + await ctx.GetTable() + .Where(x => !tempTable.Select(x => x.GuildId) + .Contains(x.GuildId)) + .DeleteAsync(); + + // delete warnings + await ctx.GetTable() + .Where(x => !tempTable.Select(x => x.GuildId) + .Contains(x.GuildId)) + .DeleteAsync(); + + // delete warn punishments + await ctx.GetTable() + .Where(x => !tempTable.Select(x => x.GuildId) + .Contains(x.GuildId)) + .DeleteAsync(); + + // delete sticky roles + await ctx.GetTable() + .Where(x => !tempTable.Select(x => x.GuildId) + .Contains(x.GuildId)) + .DeleteAsync(); + + // delete at channels + await ctx.GetTable() + .Where(x => !tempTable.Select(x => x.GuildId) + .Contains(x.GuildId)) + .DeleteAsync(); + + // delete ban templates + await ctx.GetTable() + .Where(x => !tempTable.Select(x => x.GuildId) + .Contains(x.GuildId)) + .DeleteAsync(); + + // delete reminders + await ctx.GetTable() + .Where(x => !tempTable.Select(x => x.GuildId) + .Contains(x.ServerId)) + .DeleteAsync(); + return new() { GuildCount = guildIds.Keys.Count, diff --git a/src/EllieBot/Modules/Administration/SelfAssignableRoles/SelfAssignedRolesCommands.cs b/src/EllieBot/Modules/Administration/SelfAssignableRoles/SelfAssignedRolesCommands.cs index 70581f7..de35ad4 100644 --- a/src/EllieBot/Modules/Administration/SelfAssignableRoles/SelfAssignedRolesCommands.cs +++ b/src/EllieBot/Modules/Administration/SelfAssignableRoles/SelfAssignedRolesCommands.cs @@ -6,16 +6,155 @@ namespace EllieBot.Modules.Administration; public partial class Administration { - [Group] + public partial class SelfAssignedRolesHelpers : EllieModule + { + private readonly SarAssignerService _sas; + + public SelfAssignedRolesHelpers(SarAssignerService sas) + { + _sas = sas; + } + + [Cmd] + [RequireContext(ContextType.Guild)] + public async Task Iam([Leftover] IRole role) + { + var guildUser = (IGuildUser)ctx.User; + + var group = await _service.GetRoleGroup(ctx.User.Id, role.Id); + + IUserMessage msg = null; + try + { + if (group is null) + { + msg = await Response().Error(strs.self_assign_not).SendAsync(); + return; + } + + var tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + await _sas.Add(new() + { + Group = group, + RoleId = role.Id, + User = guildUser, + CompletionTask = tcs + }); + + var res = await tcs.Task; + + if (res.TryPickT0(out _, out var error)) + { + msg = await Response() + .Confirm(strs.self_assign_success(Format.Bold(role.Name))) + .SendAsync(); + } + else + { + var resStr = error.Match( + _ => strs.error_occured, + lvlReq => strs.self_assign_not_level(Format.Bold(lvlReq.Level.ToString())), + roleRq => strs.self_assign_role_req(Format.Bold(ctx.Guild.GetRole(roleRq.RoleId).ToString() + ?? "missing role " + roleRq.RoleId), + group.Name), + _ => strs.self_assign_already(Format.Bold(role.Name)), + _ => strs.self_assign_perms); + + msg = await Response().Error(resStr).SendAsync(); + } + } + finally + { + var ad = _service.GetAutoDelete(ctx.Guild.Id); + + if (ad) + { + msg?.DeleteAfter(3); + ctx.Message.DeleteAfter(3); + } + } + } + + [Cmd] + [RequireContext(ContextType.Guild)] + public async Task Iamnot([Leftover] IRole role) + { + var guildUser = (IGuildUser)ctx.User; + + IUserMessage msg = null; + try + { + if (guildUser.RoleIds.Contains(role.Id)) + { + msg = await Response().Error(strs.self_assign_not_have(Format.Bold(role.Name))).SendAsync(); + return; + } + + var group = await _service.GetRoleGroup(role.Guild.Id, role.Id); + + if (group is null || group.Roles.All(x => x.RoleId != role.Id)) + { + msg = await Response().Error(strs.self_assign_not).SendAsync(); + return; + } + + if (role.Position >= ((SocketGuild)ctx.Guild).CurrentUser.Roles.Max(x => x.Position)) + { + msg = await Response().Error(strs.self_assign_perms).SendAsync(); + return; + } + + await guildUser.RemoveRoleAsync(role); + msg = await Response().Confirm(strs.self_assign_remove(Format.Bold(role.Name))).SendAsync(); + } + finally + { + var ad = _service.GetAutoDelete(ctx.Guild.Id); + if (ad) + { + msg?.DeleteAfter(3); + ctx.Message.DeleteAfter(3); + } + } + } + } + + [Group("sar")] public partial class SelfAssignedRolesCommands : EllieModule { + private readonly SarAssignerService _sas; + + public SelfAssignedRolesCommands(SarAssignerService sas) + { + _sas = sas; + } + + protected async Task CheckRoleHierarchy(IRole role) + { + var botUser = ((SocketGuild)ctx.Guild).CurrentUser; + var ownerId = ctx.Guild.OwnerId; + var modMaxRole = ((IGuildUser)ctx.User).GetRoles().Max(r => r.Position); + var botMaxRole = botUser.GetRoles().Max(r => r.Position); + + // role must be lower than the bot role + // and the mod must have a higher role + if (botMaxRole <= role.Position + || (ctx.User.Id != ownerId && role.Position >= modMaxRole)) + { + await Response().Error(strs.hierarchy).SendAsync(); + return false; + } + + return true; + } + [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] [BotPerm(GuildPerm.ManageMessages)] - public async Task AdSarm() + public async Task SarAutoDelete() { - var newVal = _service.ToggleAdSarm(ctx.Guild.Id); + var newVal = await _service.ToggleAutoDelete(ctx.Guild.Id); if (newVal) await Response().Confirm(strs.adsarm_enable(prefix)).SendAsync(); @@ -28,30 +167,24 @@ public partial class Administration [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] [Priority(1)] - public Task Asar([Leftover] IRole role) - => Asar(0, role); + public Task SarAdd([Leftover] IRole role) + => SarAdd(0, role); [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] [Priority(0)] - public async Task Asar(int group, [Leftover] IRole role) + public async Task SarAdd(int group, [Leftover] IRole role) { - var guser = (IGuildUser)ctx.User; - if (ctx.User.Id != guser.Guild.OwnerId && guser.GetRoles().Max(x => x.Position) <= role.Position) + if (!await CheckRoleHierarchy(role)) return; - var succ = _service.AddNew(ctx.Guild.Id, role, group); + await _service.AddAsync(ctx.Guild.Id, role.Id, group); - if (succ) - { - await Response() - .Confirm(strs.role_added(Format.Bold(role.Name), Format.Bold(group.ToString()))) - .SendAsync(); - } - else - await Response().Error(strs.role_in_list(Format.Bold(role.Name))).SendAsync(); + await Response() + .Confirm(strs.role_added(Format.Bold(role.Name), Format.Bold(group.ToString()))) + .SendAsync(); } [Cmd] @@ -59,9 +192,9 @@ public partial class Administration [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] [Priority(0)] - public async Task Sargn(int group, [Leftover] string name = null) + public async Task SarGroupName(int group, [Leftover] string name = null) { - var set = await _service.SetNameAsync(ctx.Guild.Id, group, name); + var set = await _service.SetGroupNameAsync(ctx.Guild.Id, group, name); if (set) { @@ -70,19 +203,19 @@ public partial class Administration .SendAsync(); } else + { await Response().Confirm(strs.group_name_removed(Format.Bold(group.ToString()))).SendAsync(); + } } [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] - public async Task Rsar([Leftover] IRole role) + public async Task SarRemove([Leftover] IRole role) { var guser = (IGuildUser)ctx.User; - if (ctx.User.Id != guser.Guild.OwnerId && guser.GetRoles().Max(x => x.Position) <= role.Position) - return; - var success = _service.RemoveSar(role.Guild.Id, role.Id); + var success = await _service.RemoveAsync(role.Guild.Id, role.Id); if (!success) await Response().Error(strs.self_assign_not).SendAsync(); else @@ -91,59 +224,81 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] - public async Task Lsar(int page = 1) + public async Task SarList(int page = 1) { if (--page < 0) return; - var (exclusive, roles, groups) = _service.GetRoles(ctx.Guild); + var groups = await _service.GetSarsAsync(ctx.Guild.Id); + + var gDict = groups.ToDictionary(x => x.Id, x => x); await Response() .Paginated() - .Items(roles.OrderBy(x => x.Model.Group).ToList()) + .Items(groups.SelectMany(x => x.Roles).ToList()) .PageSize(20) .CurrentPage(page) - .Page((items, _) => + .Page(async (items, _) => { - var rolesStr = new StringBuilder(); var roleGroups = items - .GroupBy(x => x.Model.Group) + .GroupBy(x => x.SarGroupId) .OrderBy(x => x.Key); + var eb = _sender.CreateEmbed() + .WithOkColor() + .WithTitle(GetText(strs.self_assign_list(groups.Sum(x => x.Roles.Count)))); + foreach (var kvp in roleGroups) { - string groupNameText; - if (!groups.TryGetValue(kvp.Key, out var name)) - groupNameText = Format.Bold(GetText(strs.self_assign_group(kvp.Key))); - else - groupNameText = Format.Bold($"{kvp.Key} - {name.TrimTo(25, true)}"); + var group = gDict[kvp.Key]; - rolesStr.AppendLine("\t\t\t\t ⟪" + groupNameText + "⟫"); - foreach (var (model, role) in kvp.AsEnumerable()) + var groupNameText = ""; + + if (!string.IsNullOrWhiteSpace(group.Name)) + groupNameText += $" **{group.Name}**"; + + groupNameText = $"`{group.GroupNumber}` {groupNameText}"; + + var rolesStr = new StringBuilder(); + + if (group.IsExclusive) { - if (role is null) + rolesStr.AppendLine(Format.Italics(GetText(strs.choose_one))); + } + + if (group.RoleReq is ulong rrId) + { + var rr = ctx.Guild.GetRole(rrId); + + if (rr is null) { + await _service.SetGroupRoleReq(group.GuildId, group.GroupNumber, null); } else { - // first character is invisible space - if (model.LevelRequirement == 0) - rolesStr.AppendLine("‌‌ " + role.Name); - else - rolesStr.AppendLine("‌‌ " + role.Name + $" (lvl {model.LevelRequirement}+)"); + rolesStr.AppendLine( + Format.Italics(GetText(strs.requires_role(Format.Bold(rr.Name))))); } } - rolesStr.AppendLine(); + foreach (var sar in kvp) + { + var roleName = (ctx.Guild.GetRole(sar.RoleId)?.Name ?? (sar.RoleId + " (deleted)")); + rolesStr.Append("- " + Format.Code(roleName)); + + if (sar.LevelReq > 0) + { + rolesStr.Append($" *[lvl {sar.LevelReq}+]*"); + } + + rolesStr.AppendLine(); + } + + + eb.AddField(groupNameText, rolesStr, false); } - return _sender.CreateEmbed() - .WithOkColor() - .WithTitle(Format.Bold(GetText(strs.self_assign_list(roles.Count())))) - .WithDescription(rolesStr.ToString()) - .WithFooter(exclusive - ? GetText(strs.self_assign_are_exclusive) - : GetText(strs.self_assign_are_not_exclusive)); + return eb; }) .SendAsync(); } @@ -152,9 +307,9 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] - public async Task Togglexclsar() + public async Task SarExclusive(int groupNumber) { - var areExclusive = _service.ToggleEsar(ctx.Guild.Id); + var areExclusive = await _service.SetGroupExclusivityAsync(ctx.Guild.Id, groupNumber); if (areExclusive) await Response().Confirm(strs.self_assign_excl).SendAsync(); else @@ -165,12 +320,12 @@ public partial class Administration [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] - public async Task RoleLevelReq(int level, [Leftover] IRole role) + public async Task SarRoleLevelReq(int level, [Leftover] IRole role) { if (level < 0) return; - var succ = _service.SetLevelReq(ctx.Guild.Id, role, level); + var succ = await _service.SetRoleLevelReq(ctx.Guild.Id, role.Id, level); if (!succ) { @@ -186,54 +341,35 @@ public partial class Administration [Cmd] [RequireContext(ContextType.Guild)] - public async Task Iam([Leftover] IRole role) + [UserPerm(GuildPerm.ManageRoles)] + [BotPerm(GuildPerm.ManageRoles)] + public async Task SarGroupRoleReq(int groupNumber, [Leftover] IRole role) { - var guildUser = (IGuildUser)ctx.User; + var succ = await _service.SetGroupRoleReq(ctx.Guild.Id, groupNumber, role.Id); - var (result, autoDelete, extra) = await _service.Assign(guildUser, role); - - IUserMessage msg; - if (result == SelfAssignedRolesService.AssignResult.ErrNotAssignable) - msg = await Response().Error(strs.self_assign_not).SendAsync(); - else if (result == SelfAssignedRolesService.AssignResult.ErrLvlReq) - msg = await Response().Error(strs.self_assign_not_level(Format.Bold(extra.ToString()))).SendAsync(); - else if (result == SelfAssignedRolesService.AssignResult.ErrAlreadyHave) - msg = await Response().Error(strs.self_assign_already(Format.Bold(role.Name))).SendAsync(); - else if (result == SelfAssignedRolesService.AssignResult.ErrNotPerms) - msg = await Response().Error(strs.self_assign_perms).SendAsync(); - else - msg = await Response().Confirm(strs.self_assign_success(Format.Bold(role.Name))).SendAsync(); - - if (autoDelete) + if (!succ) { - msg.DeleteAfter(3); - ctx.Message.DeleteAfter(3); + await Response().Error(strs.sar_group_not_found).SendAsync(); + return; } + + await Response() + .Confirm(strs.self_assign_group_role_req( + Format.Bold(groupNumber.ToString()), + Format.Bold(role.Name))) + .SendAsync(); } [Cmd] [RequireContext(ContextType.Guild)] - public async Task Iamnot([Leftover] IRole role) + [UserPerm(GuildPerm.ManageRoles)] + public async Task SarGroupDelete(int groupNumber) { - var guildUser = (IGuildUser)ctx.User; - - var (result, autoDelete) = await _service.Remove(guildUser, role); - - IUserMessage msg; - if (result == SelfAssignedRolesService.RemoveResult.ErrNotAssignable) - msg = await Response().Error(strs.self_assign_not).SendAsync(); - else if (result == SelfAssignedRolesService.RemoveResult.ErrNotHave) - msg = await Response().Error(strs.self_assign_not_have(Format.Bold(role.Name))).SendAsync(); - else if (result == SelfAssignedRolesService.RemoveResult.ErrNotPerms) - msg = await Response().Error(strs.self_assign_perms).SendAsync(); + var succ = await _service.DeleteRoleGroup(ctx.Guild.Id, groupNumber); + if (succ) + await Response().Confirm(strs.sar_group_deleted(Format.Bold(groupNumber.ToString()))).SendAsync(); else - msg = await Response().Confirm(strs.self_assign_remove(Format.Bold(role.Name))).SendAsync(); - - if (autoDelete) - { - msg.DeleteAfter(3); - ctx.Message.DeleteAfter(3); - } + await Response().Error(strs.sar_group_not_found).SendAsync(); } } } \ No newline at end of file diff --git a/src/EllieBot/Modules/Administration/SelfAssignableRoles/SelfAssignedRolesService.cs b/src/EllieBot/Modules/Administration/SelfAssignableRoles/SelfAssignedRolesService.cs index 505f56c..903f538 100644 --- a/src/EllieBot/Modules/Administration/SelfAssignableRoles/SelfAssignedRolesService.cs +++ b/src/EllieBot/Modules/Administration/SelfAssignableRoles/SelfAssignedRolesService.cs @@ -1,233 +1,327 @@ -#nullable disable +using LinqToDB; +using LinqToDB.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; +using EllieBot.Common.ModuleBehaviors; using EllieBot.Db.Models; +using EllieBot.Modules.Xp.Services; +using OneOf; +using OneOf.Types; +using System.ComponentModel.DataAnnotations; +using System.Threading.Channels; namespace EllieBot.Modules.Administration.Services; -public class SelfAssignedRolesService : IEService +public class SelfAssignedRolesService : IEService, IReadyExecutor { - public enum AssignResult + private readonly DbService _db; + private readonly DiscordSocketClient _client; + private readonly IBotCreds _creds; + + private ConcurrentHashSet _sarAds = new(); + + public SelfAssignedRolesService(DbService db, DiscordSocketClient client, IBotCreds creds) { - Assigned, // successfully removed - ErrNotAssignable, // not assignable (error) - ErrAlreadyHave, // you already have that role (error) - ErrNotPerms, // bot doesn't have perms (error) - ErrLvlReq // you are not required level (error) + _db = db; + _client = client; + _creds = creds; } - public enum RemoveResult + public async Task AddAsync(ulong guildId, ulong roleId, int groupNumber) { - Removed, // successfully removed - ErrNotAssignable, // not assignable (error) - ErrNotHave, // you don't have a role you want to remove (error) - ErrNotPerms // bot doesn't have perms (error) + await using var ctx = _db.GetDbContext(); + + await ctx.GetTable() + .InsertOrUpdateAsync(() => new() + { + GuildId = guildId, + GroupNumber = groupNumber, + IsExclusive = false + }, + _ => new() + { + }, + () => new() + { + GuildId = guildId, + GroupNumber = groupNumber + }); + + await ctx.GetTable() + .InsertOrUpdateAsync(() => new() + { + RoleId = roleId, + LevelReq = 0, + GuildId = guildId, + SarGroupId = ctx.GetTable() + .Where(x => x.GuildId == guildId && x.GroupNumber == groupNumber) + .Select(x => x.Id) + .First() + }, + _ => new() + { + }, + () => new() + { + RoleId = roleId, + }); } + public async Task RemoveAsync(ulong guildId, ulong roleId) + { + await using var ctx = _db.GetDbContext(); + + var deleted = await ctx.GetTable() + .Where(x => x.RoleId == roleId && x.GuildId == guildId) + .DeleteAsync(); + + return deleted > 0; + } + + public async Task SetGroupNameAsync(ulong guildId, int groupNumber, string? name) + { + await using var ctx = _db.GetDbContext(); + + var changes = await ctx.GetTable() + .Where(x => x.GuildId == guildId && x.GroupNumber == groupNumber) + .UpdateAsync(x => new() + { + Name = name + }); + + return changes > 0; + } + + public async Task> GetSarsAsync(ulong guildId) + { + await using var ctx = _db.GetDbContext(); + + var sgs = await ctx.GetTable() + .Where(x => x.GuildId == guildId) + .LoadWith(x => x.Roles) + .ToListAsyncLinqToDB(); + + return sgs; + } + + public async Task SetRoleLevelReq(ulong guildId, ulong roleId, int levelReq) + { + await using var ctx = _db.GetDbContext(); + var changes = await ctx.GetTable() + .Where(x => x.GuildId == guildId && x.RoleId == roleId) + .UpdateAsync(_ => new() + { + LevelReq = levelReq, + }); + + return changes > 0; + } + + public async Task SetGroupRoleReq(ulong guildId, int groupNumber, ulong? roleId) + { + await using var ctx = _db.GetDbContext(); + var changes = await ctx.GetTable() + .Where(x => x.GuildId == guildId && x.GroupNumber == groupNumber) + .UpdateAsync(_ => new() + { + RoleReq = roleId + }); + + return changes > 0; + } + + public async Task SetGroupExclusivityAsync(ulong guildId, int groupNumber) + { + await using var ctx = _db.GetDbContext(); + var changes = await ctx.GetTable() + .Where(x => x.GuildId == guildId && x.GroupNumber == groupNumber) + .UpdateWithOutputAsync(old => new() + { + IsExclusive = !old.IsExclusive + }, + (o, n) => n.IsExclusive); + + if (changes.Length == 0) + { + // todo group not found + return false; + } + + return changes[0]; + } + + public async Task GetRoleGroup(ulong guildId, ulong roleId) + { + await using var ctx = _db.GetDbContext(); + + var group = await ctx.GetTable() + .Where(x => x.Roles.Any(x => x.RoleId == roleId)) + .LoadWith(x => x.Roles) + .FirstOrDefaultAsyncLinqToDB(); + + + return group; + } + + public async Task DeleteRoleGroup(ulong guildId, int groupNumber) + { + await using var ctx = _db.GetDbContext(); + + var deleted = await ctx.GetTable() + .Where(x => x.GuildId == guildId && x.GroupNumber == groupNumber) + .DeleteAsync(); + + return deleted > 0; + } + + public async Task ToggleAutoDelete(ulong guildId) + { + await using var ctx = _db.GetDbContext(); + + var delted = await ctx.GetTable() + .DeleteAsync(x => x.GuildId == guildId); + + if (delted > 0) + { + _sarAds.TryRemove(guildId); + return false; + } + + await ctx.GetTable() + .InsertOrUpdateAsync(() => new() + { + IsEnabled = true, + GuildId = guildId, + }, + (_) => new() + { + IsEnabled = true + }, + () => new() + { + GuildId = guildId + }); + + _sarAds.Add(guildId); + return true; + } + + public bool GetAutoDelete(ulong guildId) + => _sarAds.Contains(guildId); + + public async Task OnReadyAsync() + { + await using var uow = _db.GetDbContext(); + var guilds = await uow.GetTable() + .Where(x => x.IsEnabled && Linq2DbExpressions.GuildOnShard(x.GuildId, _creds.TotalShards, _client.ShardId)) + .Select(x => x.GuildId) + .ToListAsyncLinqToDB(); + + _sarAds = new(guilds); + } +} + +public sealed class SarAssignerService : IEService, IReadyExecutor +{ + private readonly XpService _xp; private readonly DbService _db; - public SelfAssignedRolesService(DbService db) - => _db = db; + private readonly Channel _channel = + Channel.CreateBounded(100); - public bool AddNew(ulong guildId, IRole role, int group) + + public SarAssignerService(XpService xp, DbService db) { - using var uow = _db.GetDbContext(); - var roles = uow.Set().GetFromGuild(guildId); - if (roles.Any(s => s.RoleId == role.Id && s.GuildId == role.Guild.Id)) - return false; - - uow.Set().Add(new() - { - Group = group, - RoleId = role.Id, - GuildId = role.Guild.Id - }); - uow.SaveChanges(); - return true; + _xp = xp; + _db = db; } - public bool ToggleAdSarm(ulong guildId) + public async Task OnReadyAsync() { - bool newval; - using var uow = _db.GetDbContext(); - var config = uow.GuildConfigsForId(guildId, set => set); - newval = config.AutoDeleteSelfAssignedRoleMessages = !config.AutoDeleteSelfAssignedRoleMessages; - uow.SaveChanges(); - return newval; - } - - public async Task<(AssignResult Result, bool AutoDelete, object extra)> Assign(IGuildUser guildUser, IRole role) - { - LevelStats userLevelData; - await using (var uow = _db.GetDbContext()) + var reader = _channel.Reader; + while (true) { - var stats = uow.GetOrCreateUserXpStats(guildUser.Guild.Id, guildUser.Id); - userLevelData = new(stats.Xp + stats.AwardedXp); - } + var item = await reader.ReadAsync(); - var (autoDelete, exclusive, roles) = GetAdAndRoles(guildUser.Guild.Id); - - var theRoleYouWant = roles.FirstOrDefault(r => r.RoleId == role.Id); - if (theRoleYouWant is null) - return (AssignResult.ErrNotAssignable, autoDelete, null); - if (theRoleYouWant.LevelRequirement > userLevelData.Level) - return (AssignResult.ErrLvlReq, autoDelete, theRoleYouWant.LevelRequirement); - if (guildUser.RoleIds.Contains(role.Id)) - return (AssignResult.ErrAlreadyHave, autoDelete, null); - - var roleIds = roles.Where(x => x.Group == theRoleYouWant.Group).Select(x => x.RoleId).ToArray(); - if (exclusive) - { - var sameRoles = guildUser.RoleIds.Where(r => roleIds.Contains(r)); - - foreach (var roleId in sameRoles) + try { - var sameRole = guildUser.Guild.GetRole(roleId); - if (sameRole is not null) + var sar = item.Group.Roles.First(x => x.RoleId == item.RoleId); + + if (item.User.RoleIds.Contains(item.RoleId)) { - try - { - await guildUser.RemoveRoleAsync(sameRole); - await Task.Delay(300); - } - catch - { - // ignored - } + item.CompletionTask.TrySetResult(new SarAlreadyHasRole()); + continue; } + + if (item.Group.RoleReq is { } rid) + { + if (!item.User.RoleIds.Contains(rid)) + { + item.CompletionTask.TrySetResult(new SarRoleRequirement(rid)); + continue; + } + + // passed + } + + // check level requirement + if (sar.LevelReq > 0) + { + await using var ctx = _db.GetDbContext(); + var xpStats = await ctx.GetTable().GetGuildUserXp(sar.GuildId, item.User.Id); + var lvlData = new LevelStats(xpStats?.Xp ?? 0); + + if (lvlData.Level < sar.LevelReq) + { + item.CompletionTask.TrySetResult(new SarLevelRequirement(sar.LevelReq)); + continue; + } + + // passed + } + + if (item.Group.IsExclusive) + { + var rolesToRemove = item.Group.Roles.Select(x => x.RoleId); + await item.User.RemoveRolesAsync(rolesToRemove); + } + + await item.User.AddRoleAsync(item.RoleId); + + item.CompletionTask.TrySetResult(new Success()); + } + catch (Exception ex) + { + Log.Error(ex, "Unknown error ocurred in SAR runner: {Error}", ex.Message); + item.CompletionTask.TrySetResult(new Error()); } } - - try - { - await guildUser.AddRoleAsync(role); - } - catch (Exception ex) - { - return (AssignResult.ErrNotPerms, autoDelete, ex); - } - - return (AssignResult.Assigned, autoDelete, null); } - public async Task SetNameAsync(ulong guildId, int group, string name) + public async Task Add(SarAssignerDataItem item) { - var set = false; - await using var uow = _db.GetDbContext(); - var gc = uow.GuildConfigsForId(guildId, y => y.Include(x => x.SelfAssignableRoleGroupNames)); - var toUpdate = gc.SelfAssignableRoleGroupNames.FirstOrDefault(x => x.Number == group); - - if (string.IsNullOrWhiteSpace(name)) - { - if (toUpdate is not null) - gc.SelfAssignableRoleGroupNames.Remove(toUpdate); - } - else if (toUpdate is null) - { - gc.SelfAssignableRoleGroupNames.Add(new() - { - Name = name, - Number = group - }); - set = true; - } - else - { - toUpdate.Name = name; - set = true; - } - - await uow.SaveChangesAsync(); - - return set; + await _channel.Writer.WriteAsync(item); } - public async Task<(RemoveResult Result, bool AutoDelete)> Remove(IGuildUser guildUser, IRole role) - { - var (autoDelete, _, roles) = GetAdAndRoles(guildUser.Guild.Id); +} - if (roles.FirstOrDefault(r => r.RoleId == role.Id) is null) - return (RemoveResult.ErrNotAssignable, autoDelete); - if (!guildUser.RoleIds.Contains(role.Id)) - return (RemoveResult.ErrNotHave, autoDelete); - try - { - await guildUser.RemoveRoleAsync(role); - } - catch (Exception) - { - return (RemoveResult.ErrNotPerms, autoDelete); - } +public sealed class SarAssignerDataItem +{ + public required SarGroup Group { get; init; } + public required IGuildUser User { get; init; } + public required ulong RoleId { get; init; } + public required TaskCompletionSource CompletionTask { get; init; } +} - return (RemoveResult.Removed, autoDelete); - } +[GenerateOneOf] +public sealed partial class SarAssignResult + : OneOfBase +{ +} - public bool RemoveSar(ulong guildId, ulong roleId) - { - bool success; - using var uow = _db.GetDbContext(); - success = uow.Set().DeleteByGuildAndRoleId(guildId, roleId); - uow.SaveChanges(); - return success; - } +public record class SarLevelRequirement(int Level); - public (bool AutoDelete, bool Exclusive, IReadOnlyCollection) GetAdAndRoles(ulong guildId) - { - using var uow = _db.GetDbContext(); - var gc = uow.GuildConfigsForId(guildId, set => set); - var autoDelete = gc.AutoDeleteSelfAssignedRoleMessages; - var exclusive = gc.ExclusiveSelfAssignedRoles; - var roles = uow.Set().GetFromGuild(guildId); +public record class SarRoleRequirement(ulong RoleId); - return (autoDelete, exclusive, roles); - } +public record class SarAlreadyHasRole(); - public bool SetLevelReq(ulong guildId, IRole role, int level) - { - using var uow = _db.GetDbContext(); - var roles = uow.Set().GetFromGuild(guildId); - var sar = roles.FirstOrDefault(x => x.RoleId == role.Id); - if (sar is not null) - { - sar.LevelRequirement = level; - uow.SaveChanges(); - } - else - return false; - - return true; - } - - public bool ToggleEsar(ulong guildId) - { - bool areExclusive; - using var uow = _db.GetDbContext(); - var config = uow.GuildConfigsForId(guildId, set => set); - - areExclusive = config.ExclusiveSelfAssignedRoles = !config.ExclusiveSelfAssignedRoles; - uow.SaveChanges(); - return areExclusive; - } - - public (bool Exclusive, IReadOnlyCollection<(SelfAssignedRole Model, IRole Role)> Roles, IDictionary - GroupNames - ) GetRoles(IGuild guild) - { - var exclusive = false; - - IReadOnlyCollection<(SelfAssignedRole Model, IRole Role)> roles; - IDictionary groupNames; - using (var uow = _db.GetDbContext()) - { - var gc = uow.GuildConfigsForId(guild.Id, set => set.Include(x => x.SelfAssignableRoleGroupNames)); - exclusive = gc.ExclusiveSelfAssignedRoles; - groupNames = gc.SelfAssignableRoleGroupNames.ToDictionary(x => x.Number, x => x.Name); - var roleModels = uow.Set().GetFromGuild(guild.Id); - roles = roleModels.Select(x => (Model: x, Role: guild.GetRole(x.RoleId))) - .ToList(); - uow.Set().RemoveRange(roles.Where(x => x.Role is null).Select(x => x.Model).ToArray()); - uow.SaveChanges(); - } - - return (exclusive, roles.Where(x => x.Role is not null).ToList(), groupNames); - } -} \ No newline at end of file +public record class SarInsuffPerms(); \ No newline at end of file diff --git a/src/EllieBot/Modules/Administration/UserPunish/UserPunishCommands.cs b/src/EllieBot/Modules/Administration/UserPunish/UserPunishCommands.cs index 85e5026..ea3999b 100644 --- a/src/EllieBot/Modules/Administration/UserPunish/UserPunishCommands.cs +++ b/src/EllieBot/Modules/Administration/UserPunish/UserPunishCommands.cs @@ -23,27 +23,6 @@ public partial class Administration _mute = mute; } - private async Task CheckRoleHierarchy(IGuildUser target) - { - var curUser = ((SocketGuild)ctx.Guild).CurrentUser; - var ownerId = ctx.Guild.OwnerId; - var modMaxRole = ((IGuildUser)ctx.User).GetRoles().Max(r => r.Position); - var targetMaxRole = target.GetRoles().Max(r => r.Position); - var botMaxRole = curUser.GetRoles().Max(r => r.Position); - // bot can't punish a user who is higher in the hierarchy. Discord will return 403 - // moderator can be owner, in which case role hierarchy doesn't matter - // otherwise, moderator has to have a higher role - if (botMaxRole <= targetMaxRole - || (ctx.User.Id != ownerId && targetMaxRole >= modMaxRole) - || target.Id == ownerId) - { - await Response().Error(strs.hierarchy).SendAsync(); - return false; - } - - return true; - } - [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.BanMembers)] diff --git a/src/EllieBot/Modules/Gambling/AnimalRacing/AnimalRace.cs b/src/EllieBot/Modules/Gambling/AnimalRacing/AnimalRace.cs index 65d7ae0..778de60 100644 --- a/src/EllieBot/Modules/Gambling/AnimalRacing/AnimalRace.cs +++ b/src/EllieBot/Modules/Gambling/AnimalRacing/AnimalRace.cs @@ -6,9 +6,9 @@ namespace EllieBot.Modules.Gambling.Common.AnimalRacing; public sealed class AnimalRace : IDisposable { - public const double BASE_MULTIPLIER = 0.82; + public const double BASE_MULTIPLIER = 0.87; public const double MAX_MULTIPLIER = 0.94; - public const double MULTI_PER_USER = 0.01; + public const double MULTI_PER_USER = 0.005; public enum Phase { diff --git a/src/EllieBot/Modules/Gambling/Gambling.cs b/src/EllieBot/Modules/Gambling/Gambling.cs index 95f66a9..3a0188a 100644 --- a/src/EllieBot/Modules/Gambling/Gambling.cs +++ b/src/EllieBot/Modules/Gambling/Gambling.cs @@ -154,16 +154,16 @@ public partial class Gambling : GamblingModule { var password = _service.GeneratePassword(); - var img = new Image(70, 35); + var img = new Image(60, 30); - var font = _fonts.NotoSans.CreateFont(30); + var font = _fonts.NotoSans.CreateFont(25); var outlinePen = new SolidPen(Color.Black, 1f); var strikeoutRun = new RichTextRun { Start = 0, End = password.GetGraphemeCount(), Font = font, - StrikeoutPen = new SolidPen(Color.White, 3), + StrikeoutPen = new SolidPen(Color.White, 4), TextDecorations = TextDecorations.Strikeout }; // draw password on the image diff --git a/src/EllieBot/Modules/Gambling/Loan/LoanCommands.cs b/src/EllieBot/Modules/Gambling/Loan/LoanCommands.cs new file mode 100644 index 0000000..d540c04 --- /dev/null +++ b/src/EllieBot/Modules/Gambling/Loan/LoanCommands.cs @@ -0,0 +1,92 @@ +// namespace EllieBot.Modules.Gambling; +// public sealed class Loan +// { +// public int Id { get; set; } +// public ulong LenderId { get; set; } +// public string LenderName { get; set; } +// public ulong BorrowerId { get; set; } +// public string BorrowerName { get; set; } +// public long Amount { get; set; } +// public decimal Interest { get; set; } +// public DateTime DueDate { get; set; } +// public bool Repaid { get; set; } +// } +// +// public sealed class LoanService : INService +// { +// public async Task> GetLoans(ulong userId) +// { +// } +// +// public async Task RepayAsync(object loandId) +// { +// } +// } +// +// public partial class Gambling +// { +// public partial class LoanCommands : EllieModule +// { +// [Cmd] +// public async Task Loan( +// IUser lender, +// long amount, +// decimal interest = 0, +// TimeSpan dueIn = default) +// { +// var eb = _sender.CreateEmbed() +// .WithOkColor() +// .WithDescription("User 0 Requests a loan from User {1}") +// .AddField("Amount", amount, true) +// .AddField("Interest", (interest * 0.01m).ToString("P2"), true); +// } +// +// public Task Loans() +// => Loans(ctx.User); +// +// public async Task Loans([Leftover] IUser user) +// { +// var loans = await _service.GetLoans(user.Id); +// +// Response() +// .Paginated() +// .PageItems(loans) +// .Page((items, page) => +// { +// var eb = _sender.CreateEmbed() +// .WithOkColor() +// .WithDescription("Current Loans"); +// +// foreach (var item in items) +// { +// eb.AddField(new kwum(item.id).ToString(), +// $""" +// To: {item.LenderName} +// Amount: {} +// """, +// true); +// } +// +// return eb; +// }); +// } +// +// [Cmd] +// public async Task Repay(kwum loanId) +// { +// var res = await _service.RepayAsync(loandId); +// +// if (res.TryPickT0(out var _, out var err)) +// { +// } +// else +// { +// var errStr = err.Match( +// _ => "Not enough funds", +// _ => "Loan not found"); +// +// await Response().Error(errStr).SendAsync(); +// } +// } +// } +// } \ No newline at end of file diff --git a/src/EllieBot/Modules/Searches/_common/StreamNotifications/Providers/TwitchHelixProvider.cs b/src/EllieBot/Modules/Searches/_common/StreamNotifications/Providers/TwitchHelixProvider.cs index a3c92c6..4dd5657 100644 --- a/src/EllieBot/Modules/Searches/_common/StreamNotifications/Providers/TwitchHelixProvider.cs +++ b/src/EllieBot/Modules/Searches/_common/StreamNotifications/Providers/TwitchHelixProvider.cs @@ -5,6 +5,48 @@ using JsonSerializer = System.Text.Json.JsonSerializer; namespace EllieBot.Modules.Searches.Common.StreamNotifications.Providers; +public sealed class YoutubeProvide : Provider +{ + private readonly IGoogleApiService _api; + private readonly IHttpClientFactory _httpFactory; + + public override FollowedStream.FType Platform + => FollowedStream.FType.Youtube; + + public YoutubeProvide(IGoogleApiService api, IHttpClientFactory httpFactory) + { + _api = api; + _httpFactory = httpFactory; + } + + public override async Task IsValidUrl(string url) + { + await Task.Yield(); + // todo implement + return url.Contains("youtube.com"); + } + + public override Task GetStreamDataByUrlAsync(string url) + { + return default; + } + + public override Task GetStreamDataAsync(string login) + { + var client = _httpFactory.CreateClient(); + + client.GetAsync(); + + + return default; + } + + public override Task> GetStreamDataAsync(List usernames) + { + return default; + } +} + public sealed class TwitchHelixProvider : Provider { private readonly IHttpClientFactory _httpClientFactory; @@ -94,9 +136,9 @@ public sealed class TwitchHelixProvider : Provider var loginsSet = logins.Select(x => x.ToLowerInvariant()) .Distinct() .ToHashSet(); - + var dataDict = new Dictionary(); - + foreach (var chunk in logins.Chunk(100)) { try @@ -125,13 +167,13 @@ public sealed class TwitchHelixProvider : Provider return []; } } - + // any item left over loginsSet is an invalid username foreach (var login in loginsSet) { _failingStreams.TryAdd(login, DateTime.UtcNow); } - + // only get streams for users which exist foreach (var chunk in dataDict.Keys.Chunk(100)) { @@ -178,7 +220,7 @@ public sealed class TwitchHelixProvider : Provider StreamType = FollowedStream.FType.Twitch, Preview = user.OfflineImageUrl }; - + private StreamData FillStreamData(StreamData partial, HelixStreamsResponse.StreamData apiData) => partial with { diff --git a/src/EllieBot/_common/Abstractions/Extensions/Extensions.cs b/src/EllieBot/_common/Abstractions/Extensions/Extensions.cs index 8abf5d6..1bfc3f3 100644 --- a/src/EllieBot/_common/Abstractions/Extensions/Extensions.cs +++ b/src/EllieBot/_common/Abstractions/Extensions/Extensions.cs @@ -1,7 +1,9 @@ +using EllieBot.Db.Models; + namespace Ellie.Common; public static class Extensions { public static long ToTimestamp(this in DateTime value) - => (value.Ticks - 621355968000000000) / 10000000; + => (value.Ticks 621355968000000000) / 10000000; } \ No newline at end of file diff --git a/src/EllieBot/_common/EllieModule.cs b/src/EllieBot/_common/EllieModule.cs index d8867c1..6ae5d91 100644 --- a/src/EllieBot/_common/EllieModule.cs +++ b/src/EllieBot/_common/EllieModule.cs @@ -100,6 +100,27 @@ public abstract class EllieModule : ModuleBase return Task.CompletedTask; } } + + protected async Task CheckRoleHierarchy(IGuildUser target) + { + var curUser = ((SocketGuild)ctx.Guild).CurrentUser; + var ownerId = ctx.Guild.OwnerId; + var modMaxRole = ((IGuildUser)ctx.User).GetRoles().Max(r => r.Position); + var targetMaxRole = target.GetRoles().Max(r => r.Position); + var botMaxRole = curUser.GetRoles().Max(r => r.Position); + // bot can't punish a user who is higher in the hierarchy. Discord will return 403 + // moderator can be owner, in which case role hierarchy doesn't matter + // otherwise, moderator has to have a higher role + if (botMaxRole <= targetMaxRole + || (ctx.User.Id != ownerId && targetMaxRole >= modMaxRole) + || target.Id == ownerId) + { + await Response().Error(strs.hierarchy).SendAsync(); + return false; + } + + return true; + } } public abstract class EllieModule : EllieModule diff --git a/src/EllieBot/data/aliases.yml b/src/EllieBot/data/aliases.yml index 8589812..d5e2f3e 100644 --- a/src/EllieBot/data/aliases.yml +++ b/src/EllieBot/data/aliases.yml @@ -81,17 +81,43 @@ vcrole: - vcrole vcrolerm: - vcrolerm -asar: +saradd: + - add + - a - asar -rsar: +sarremove: + - remove + - rm + - rem - rsar -lsar: +sarlist: + - list + - l + - ls - lsar -sargn: +sarautodelete: + - ad + - autodel + - adsarm +sargroupname: + - groupname + - gn - sargn -togglexclsar: - - togglexclsar +sargrouprolereq: + - grouprolereq + - grr +sargroupdelete: + - groupdelete + - gd + - gdel +sarexclusive: + - exclusive + - ex + - excl - tesar +sarrolelevelreq: + - rolelvlreq + - rlr iam: - iam iamnot: @@ -772,8 +798,6 @@ voicemute: muterole: - muterole - setmuterole -adsarm: - - adsarm setstream: - setstream chatunmute: @@ -1184,9 +1208,6 @@ timelyreset: crypto: - crypto - c -rolelevelreq: - - rolelevelreq - - rlr massban: - massban masskill: diff --git a/src/EllieBot/data/gambling.yml b/src/EllieBot/data/gambling.yml index 2444340..44c4310 100644 --- a/src/EllieBot/data/gambling.yml +++ b/src/EllieBot/data/gambling.yml @@ -28,7 +28,7 @@ betRoll: multiplyBy: 10 - whenAbove: 90 multiplyBy: 4 - - whenAbove: 65 + - whenAbove: 64 multiplyBy: 2 # Automatic currency generation settings. generation: diff --git a/src/EllieBot/data/strings/commands/commands.en-US.yml b/src/EllieBot/data/strings/commands/commands.en-US.yml index e22b0bf..e470cda 100644 --- a/src/EllieBot/data/strings/commands/commands.en-US.yml +++ b/src/EllieBot/data/strings/commands/commands.en-US.yml @@ -323,7 +323,7 @@ vcrolerm: params: - vcId: desc: "The voice channel ID to remove the vcrole from." -asar: +saradd: desc: Adds a role to the list of self-assignable roles. You can also specify a group. If 'Exclusive self-assignable roles' feature is enabled (`{0}tesar`), users will be able to pick one role per group. ex: - Gamer @@ -336,7 +336,7 @@ asar: desc: "The ID of a group that the designated role should belong to." role: desc: "The role that can be assigned by the user." -rsar: +sarremove: desc: Removes a specified role from the list of self-assignable roles. ex: - Gamer @@ -345,7 +345,7 @@ rsar: params: - role: desc: "The role to remove from the list of self-assignable roles." -lsar: +sarlist: desc: Lists self-assignable roles. Shows 20 roles per page. ex: - '' @@ -353,22 +353,53 @@ lsar: params: - page: desc: "The page number to show." -sargn: +sarautodelete: + desc: Toggles the automatic deletion of the user's message and Nadeko's confirmations for `{0}iam` and `{0}iamn` commands. + ex: + - '' + params: + - { } +sargroupname: desc: Sets a self assignable role group name. Provide no name to remove. ex: - 1 Faction - 2 params: - group: - desc: "The ID of the group to name." + desc: "The group number" name: desc: "The name to assign." -togglexclsar: +sargroupdelete: + desc: "Deletes a self-assignable role group" + ex: + - 0 + params: + - group: + desc: "The number of the group to delete." +sarexclusive: desc: Toggles whether self-assigned roles are exclusive. While enabled, users can only have one self-assignable role per group. ex: - '' params: - { } +sarrolelevelreq: + desc: Set a level requirement on a self-assignable role. + ex: + - 5 SomeRole + params: + - level: + desc: "The minimum level required for the role." + role: + desc: "The role that must be assigned before the user can assign this one." +sargrouprolereq: + desc: Set a role that users have to have in order to assign a self-assignable role from the specified group. + ex: + - 1 SomeRole + params: + - group: + desc: "The group number." + role: + desc: "The role that is required." iam: desc: Adds a role to you that you choose. Role must be on the list of self-assignable roles. ex: @@ -2464,12 +2495,6 @@ muterole: params: - role: desc: "The role that determines whether users are muted or not." -adsarm: - desc: Toggles the automatic deletion of the user's message and Ellie's confirmations for `{0}iam` and `{0}iamn` commands. - ex: - - '' - params: - - { } setstream: desc: Sets the bots stream. First parameter is the twitch link, second parameter is stream name. ex: @@ -3356,7 +3381,7 @@ globalcommand: globalmodule: desc: Toggles whether a module can be used on any server. ex: - - 'Gambling' + - 'Gambling' params: - module: desc: "The type of module or configuration information being toggled." @@ -3919,15 +3944,6 @@ stock: params: - query: desc: "The ticker symbol or company name used to retrieve the stock's information." -rolelevelreq: - desc: Set a level requirement on a self-assignable role. - ex: - - 5 SomeRole - params: - - level: - desc: "The minimum level required for the role." - role: - desc: "The role that must be assigned before the user can assign this one." massban: desc: Bans multiple users at once. Specify a space separated list of IDs of users who you wish to ban. ex: @@ -4676,7 +4692,7 @@ betstats: - '@someone lula' - 'bd' params: - - {} + - { } - user: desc: 'The user for who to show the betstats for.' - user: @@ -4691,10 +4707,10 @@ rakeback: Rakeback is accumulated by betting (not by winning or losing). Default rakeback is 0.05 * house edge House edge is defined per game - ex: + ex: - '' params: - - {} + - { } snipe: desc: |- Snipe the message you replied to with this command. diff --git a/src/EllieBot/data/strings/responses/responses.en-US.json b/src/EllieBot/data/strings/responses/responses.en-US.json index 130fcbe..567fb25 100644 --- a/src/EllieBot/data/strings/responses/responses.en-US.json +++ b/src/EllieBot/data/strings/responses/responses.en-US.json @@ -896,9 +896,6 @@ "rank": "Rank", "template_reloaded": "Xp template has been reloaded.", "expr_edited": "Expression Edited", - "self_assign_are_exclusive": "You can only choose 1 role from each group.", - "self_assign_are_not_exclusive": "You can choose any number of roles from any group.", - "self_assign_group": "Group {0}", "new_reaction_event": "Add {0} reaction to this message to get {1}\n{2} left to be awarded.", "new_gamestatus_event": "Type the secret code in any channel to receive {1}\n{2} left to be awarded.", "event_duration_footer": "This event is active for up to {0} hours.", @@ -947,6 +944,7 @@ "did_you_mean": "Did you mean {0}?", "self_assign_level_req": "Self assignable role {0} now requires at least server level {1}.", "self_assign_not_level": "That self-assignable role requires at least server level {0}.", + "self_assign_role_req": "You need {0} role in order to assign yourself a role from group {1}", "invalid": "Invalid / Can't be found ({0})", "mass_kill_in_progress": "Mass Banning and Blacklisting of {0} users is in progress...", "mass_ban_in_progress": "Banning {0} users...", @@ -1118,5 +1116,10 @@ "rakeback_claimed": "You've claimed {0} as rakeback!", "rakeback_none": "You don't have any rakeback to claim yet.", "rakeback_available": "You have {0} rakeback available. Click the button to claim.", - "sniped_by": "Sniped by {0}" + "sniped_by": "Sniped by {0}", + "self_assign_group_role_req": "Users can now self-assign a role from group {0} only if they have {1} role.", + "sar_group_not_found": "Group with that number doesn't exist.", + "sar_group_deleted": "Group {0} deleted.", + "choose_one": "Choose one", + "requires_role": "Requires role: {0}" } -- 2.43.0 From 97094dbe5d67341a41bc4110f925b1e7c3fe079b Mon Sep 17 00:00:00 2001 From: Toastie Date: Wed, 27 Nov 2024 22:45:01 +1300 Subject: [PATCH 2/4] fixed .sinfo for guilds on other shards --- ...{GuildColors.cs => GuildColorsCommands.cs} | 0 .../Modules/Utility/Info/InfoCommands.cs | 2 +- .../SelfAssignableRolesExtensions.cs | 23 ------------------- 3 files changed, 1 insertion(+), 24 deletions(-) rename src/EllieBot/Modules/Utility/{GuildColors.cs => GuildColorsCommands.cs} (100%) delete mode 100644 src/EllieBot/_common/Abstractions/Extensions/SelfAssignableRolesExtensions.cs diff --git a/src/EllieBot/Modules/Utility/GuildColors.cs b/src/EllieBot/Modules/Utility/GuildColorsCommands.cs similarity index 100% rename from src/EllieBot/Modules/Utility/GuildColors.cs rename to src/EllieBot/Modules/Utility/GuildColorsCommands.cs diff --git a/src/EllieBot/Modules/Utility/Info/InfoCommands.cs b/src/EllieBot/Modules/Utility/Info/InfoCommands.cs index c9ae861..2640e76 100644 --- a/src/EllieBot/Modules/Utility/Info/InfoCommands.cs +++ b/src/EllieBot/Modules/Utility/Info/InfoCommands.cs @@ -53,7 +53,7 @@ public partial class Utility .WithTitle(guild.Name) .AddField(GetText(strs.id), guild.Id.ToString(), true) .AddField(GetText(strs.owner), ownername.ToString(), true) - .AddField(GetText(strs.members), (guild as SocketGuild)?.MemberCount ?? guild.ApproximateMemberCount, true) + .AddField(GetText(strs.members), (guild as SocketGuild)?.MemberCount.ToString() ?? guild.ApproximateMemberCount?.ToString() ?? "?", true) .AddField(GetText(strs.channels), channels, true) .AddField(GetText(strs.created_at), $"{createdAt:dd.MM.yyyy HH:mm}", true) .AddField(GetText(strs.roles), (guild.Roles.Count - 1).ToString(), true) diff --git a/src/EllieBot/_common/Abstractions/Extensions/SelfAssignableRolesExtensions.cs b/src/EllieBot/_common/Abstractions/Extensions/SelfAssignableRolesExtensions.cs deleted file mode 100644 index f44488f..0000000 --- a/src/EllieBot/_common/Abstractions/Extensions/SelfAssignableRolesExtensions.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Microsoft.EntityFrameworkCore; -using EllieBot.Db.Models; - -namespace EllieBot.Db; - -public static class SelfAssignableRolesExtensions -{ - public static bool DeleteByGuildAndRoleId(this DbSet roles, ulong guildId, ulong roleId) - { - var role = roles.FirstOrDefault(s => s.GuildId == guildId && s.RoleId == roleId); - - if (role is null) - return false; - - roles.Remove(role); - return true; - } - - public static IReadOnlyCollection GetFromGuild( - this DbSet roles, - ulong guildId) - => roles.AsQueryable().Where(s => s.GuildId == guildId).ToArray(); -} \ No newline at end of file -- 2.43.0 From b411e8cb256238cbe109a426f105847d8d7aaa5f Mon Sep 17 00:00:00 2001 From: Toastie Date: Thu, 28 Nov 2024 01:06:01 +1300 Subject: [PATCH 3/4] .btr and .sclr added, cleanup --- CHANGELOG.md | 53 + src/EllieBot/Db/EllieContext.cs | 24 + src/EllieBot/Db/Models/GuildColors.cs | 7 +- src/EllieBot/Db/Models/GuildConfig.cs | 22 - src/EllieBot/Db/Models/btnrole/ButtonRole.cs | 25 + .../20241127120348_guildcolors.Designer.cs | 4048 +++++++++++++++++ .../PostgreSql/20241127120348_guildcolors.cs | 73 + .../PostgreSqlContextModelSnapshot.cs | 97 + .../20241127120303_guildcolors.Designer.cs | 3122 +++++++++++++ .../Sqlite/20241127120303_guildcolors.cs | 72 + .../Sqlite/EllieSqliteContextModelSnapshot.cs | 74 + .../Modules/Administration/Administration.cs | 2 +- .../Administration/AdministrationService.cs | 2 +- .../DangerousCommands/CleanupService.cs | 6 + .../DangerousCommands/DangerousCommands.cs | 8 +- .../Administration/LocalizationCommands.cs | 2 +- .../Administration/Mute/MuteService.cs | 4 +- .../DiscordPermOverrideCommands.cs | 4 +- .../Protection/ProtectionCommands.cs | 2 +- .../Administration/Prune/PruneCommands.cs | 2 +- .../Role/ButtonRolesCommands.cs | 269 ++ .../Administration/Role/ButtonRolesService.cs | 154 + .../Role/ReactionRoleCommands.cs | 2 +- .../Role/ReactionRolesService.cs | 72 +- .../Administration/Role/RoleCommands.cs | 5 +- .../Administration/Self/SelfCommands.cs | 6 +- .../SelfAssignedRolesCommands.cs | 34 +- .../SelfAssignedRolesService.cs | 7 +- .../ServerLog/ServerLogCommands.cs | 2 +- .../Timezone/TimeZoneCommands.cs | 2 +- .../UserPunish/UserPunishCommands.cs | 32 +- .../Administration/VcRole/VcRoleCommands.cs | 2 +- .../Modules/Expressions/EllieExpressions.cs | 12 +- .../AnimalRacing/AnimalRacingCommands.cs | 4 +- .../Modules/Gambling/Bank/BankCommands.cs | 4 +- .../Modules/Gambling/BetStatsCommands.cs | 8 +- .../Gambling/BlackJack/BlackJackCommands.cs | 2 +- .../Gambling/Connect4/Connect4Commands.cs | 4 +- .../Gambling/DiceRoll/DiceRollCommands.cs | 8 +- .../Modules/Gambling/Draw/DrawCommands.cs | 4 +- .../Gambling/Events/CurrencyEventsCommands.cs | 4 +- .../Gambling/FlipCoin/FlipCoinCommands.cs | 4 +- src/EllieBot/Modules/Gambling/Gambling.cs | 134 +- .../Modules/Gambling/Loan/LoanCommands.cs | 4 +- .../PlantPick/PlantAndPickCommands.cs | 4 +- .../Modules/Gambling/Shop/ShopCommands.cs | 10 +- .../Modules/Gambling/Slot/SlotCommands.cs | 2 +- .../Gambling/Waifus/WaifuClaimCommands.cs | 10 +- .../Games/Acrophobia/AcropobiaCommands.cs | 8 +- src/EllieBot/Modules/Games/Games.cs | 2 +- .../Modules/Games/NCanvas/NCanvasCommands.cs | 12 +- .../Games/SpeedTyping/SpeedTypingCommands.cs | 2 +- .../Modules/Games/Trivia/TriviaCommands.cs | 8 +- src/EllieBot/Modules/Help/Help.cs | 8 +- src/EllieBot/Modules/Marmalades/Marmalade.cs | 12 +- src/EllieBot/Modules/Music/Music.cs | 28 +- .../Modules/Music/PlaylistCommands.cs | 6 +- .../Modules/Music/Services/IMusicService.cs | 1 + .../Modules/Music/Services/MusicService.cs | 45 +- .../Modules/Music/_common/IMusicPlayer.cs | 1 + .../Modules/Music/_common/IMusicQueue.cs | 1 + .../Modules/Music/_common/Impl/MusicPlayer.cs | 40 +- .../Modules/Music/_common/Impl/MusicQueue.cs | 32 +- .../Patronage/CurrencyRewardService.cs | 61 +- .../Modules/Patronage/PatronageCommands.cs | 4 +- .../Blacklist/BlacklistCommands.cs | 4 +- .../CommandCooldown/CmdCdsCommands.cs | 2 +- .../Permissions/Filter/FilterCommands.cs | 4 +- .../GlobalPermissionCommands.cs | 2 +- .../Searches/Anime/AnimeSearchCommands.cs | 4 +- .../Modules/Searches/Crypto/CryptoCommands.cs | 10 +- .../Modules/Searches/Feeds/FeedCommands.cs | 4 +- .../Modules/Searches/Osu/OsuCommands.cs | 6 +- .../Modules/Searches/PokemonSearchCommands.cs | 4 +- .../Searches/Religious/ReligiousCommands.cs | 4 +- .../Modules/Searches/Search/SearchCommands.cs | 37 +- src/EllieBot/Modules/Searches/Searches.cs | 22 +- .../StreamNotificationCommands.cs | 4 +- .../StreamNotificationService.cs | 2 +- .../Translate/FlagTranslateService.cs | 2 +- .../Searches/Translate/TranslateService.cs | 2 +- .../Searches/Translate/TranslatorCommands.cs | 4 +- src/EllieBot/Modules/Searches/XkcdCommands.cs | 4 +- .../Providers/TwitchHelixProvider.cs | 82 +- .../Modules/Utility/Ai/AiAssistantService.cs | 15 +- .../Modules/Utility/Ai/AiCommandModel.cs | 2 +- .../Modules/Utility/Alias/AliasCommands.cs | 2 +- .../Modules/Utility/ConfigCommands.cs | 12 +- .../Utility/Giveaway/GiveawayCommands.cs | 4 +- .../Utility/Giveaway/GiveawayService.cs | 129 +- .../Modules/Utility/GuildColorsCommands.cs | 87 +- .../Modules/Utility/Info/InfoCommands.cs | 8 +- .../Modules/Utility/Invite/InviteCommands.cs | 4 +- .../Modules/Utility/Quote/QuoteCommands.cs | 6 +- .../Modules/Utility/Remind/RemindCommands.cs | 2 +- .../Modules/Utility/Remind/RemindService.cs | 2 +- .../Utility/Repeater/RepeatCommands.cs | 6 +- .../Modules/Utility/Todo/TodoCommands.cs | 18 +- .../Modules/Utility/Todo/TodoService.cs | 127 +- .../UnitConversion/UnitConversionCommands.cs | 2 +- src/EllieBot/Modules/Utility/Utility.cs | 18 +- src/EllieBot/Modules/Xp/Club/Club.cs | 10 +- src/EllieBot/Modules/Xp/Xp.cs | 16 +- src/EllieBot/Modules/Xp/XpRewards.cs | 4 +- .../Abstractions/Extensions/Extensions.cs | 2 +- src/EllieBot/_common/CleanupModuleBase.cs | 2 +- src/EllieBot/_common/EllieModule.cs | 22 + src/EllieBot/_common/MessageLink.cs | 7 + .../_common/Sender/IMessageSenderService.cs | 2 +- .../_common/Sender/MessageSenderService.cs | 31 +- .../Services/Impl/CommandsUtilityService.cs | 2 +- .../Services/Impl/GuildColorsService.cs | 130 + .../Services/Impl/IGuildColorsService.cs | 13 + .../_common/TypeReaders/IEmoteTypeReader.cs | 27 + .../TypeReaders/MessageLinkTypeReader.cs | 44 + .../_common/TypeReaders/Rgba32TypeReader.cs | 19 +- src/EllieBot/data/aliases.yml | 38 +- .../data/strings/commands/commands.en-US.yml | 91 +- .../strings/responses/responses.en-US.json | 13 +- 119 files changed, 9181 insertions(+), 664 deletions(-) create mode 100644 src/EllieBot/Db/Models/btnrole/ButtonRole.cs create mode 100644 src/EllieBot/Migrations/PostgreSql/20241127120348_guildcolors.Designer.cs create mode 100644 src/EllieBot/Migrations/PostgreSql/20241127120348_guildcolors.cs create mode 100644 src/EllieBot/Migrations/Sqlite/20241127120303_guildcolors.Designer.cs create mode 100644 src/EllieBot/Migrations/Sqlite/20241127120303_guildcolors.cs create mode 100644 src/EllieBot/Modules/Administration/Role/ButtonRolesCommands.cs create mode 100644 src/EllieBot/Modules/Administration/Role/ButtonRolesService.cs create mode 100644 src/EllieBot/_common/MessageLink.cs create mode 100644 src/EllieBot/_common/Services/Impl/GuildColorsService.cs create mode 100644 src/EllieBot/_common/Services/Impl/IGuildColorsService.cs create mode 100644 src/EllieBot/_common/TypeReaders/IEmoteTypeReader.cs create mode 100644 src/EllieBot/_common/TypeReaders/MessageLinkTypeReader.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index e565936..531e5c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,59 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except date format. a-c-f-r-o +## [5.2.0] - 28.11.2024 + +### Added + +- Added `.todo undone` command to unmark a todo as done +- Added Button Roles! + - `.btr a` to add a button role to the specified message + - `.btr list` to list all button roles on the server + - `.btr rm` to remove a button role from the specified message + - `.btr rma` to remove all button roles on the specified message + - Use `.h` on any of the above for more info +- Added `.wrongsong` which will delete the last queued song. + - Useful in case you made a mistake, or the bot queued a wrong song + - It will reset after a shuffle or fairplay toggle, or similar events. +- Added Server color Commands! + - Every Server can now set their own colors for ok/error/pending embed (the default green/red/yellow color on the left side of the message the bot sends) + - Use `.h .sclr` to see the list of commands + - `.sclr show` will show the current server colors + - `.sclr ok ` to set ok color + - `.sclr warn ` to set warn color + - `.sclr error ` to set error color + +### Changed + +- Self Assigned Roles reworked! Use `.h .sar` for the list of commands + - `.sar autodel` + - Toggles the automatic deletion of the user's message and Nadeko's confirmations for .iam and .iamn commands. + - `.sar ad` + - Adds a role to the list of self-assignable roles. You can also specify a group. + - If 'Exclusive self-assignable roles' feature is enabled (.sar exclusive), users will be able to pick one role per group. + - `.sar groupname` + - Sets a self assignable role group name. Provide no name to remove. + - `.sar remove` + - Removes a specified role from the list of self-assignable roles. + - `.sar list` + - Lists self-assignable roles. Shows 20 roles per page. + - `.sar exclusive` + - Toggles whether self-assigned roles are exclusive. While enabled, users can only have one self-assignable role per group. + - `.sar rolelvlreq` + - Set a level requirement on a self-assignable role. + - `.sar grouprolereq` + - Set a role that users have to have in order to assign a self-assignable role from the specified group. + - `.sar groupdelete` + - Deletes a self-assignable role group + - `.iam` and `.iamn` are unchanged +- Removed patron limits from Reaction Roles. Anyone can have as many reros as they like. +- `.timely` captcha made stronger and cached per user. +- `.bsreset` price reduced by 90% + +### Fixed + +- Fixed `.sinfo` for servers on other shard + ## [5.1.20] - 13.11.2024 ### Added diff --git a/src/EllieBot/Db/EllieContext.cs b/src/EllieBot/Db/EllieContext.cs index f8783ce..92a0699 100644 --- a/src/EllieBot/Db/EllieContext.cs +++ b/src/EllieBot/Db/EllieContext.cs @@ -74,6 +74,30 @@ public abstract class EllieContext : DbContext protected override void OnModelCreating(ModelBuilder modelBuilder) { + #region GuildColors + + modelBuilder.Entity() + .HasIndex(x => x.GuildId) + .IsUnique(true); + + #endregion + + #region Button Roles + + modelBuilder.Entity(br => + { + br.HasIndex(x => x.GuildId) + .IsUnique(false); + + br.HasAlternateKey(x => new + { + x.RoleId, + x.MessageId, + }); + }); + + #endregion + #region New Sar modelBuilder.Entity(sg => diff --git a/src/EllieBot/Db/Models/GuildColors.cs b/src/EllieBot/Db/Models/GuildColors.cs index efd5fc1..6553dff 100644 --- a/src/EllieBot/Db/Models/GuildColors.cs +++ b/src/EllieBot/Db/Models/GuildColors.cs @@ -5,14 +5,15 @@ namespace EllieBot.Db.Models; public class GuildColors { [Key] + public int Id { get; set; } public ulong GuildId { get; set; } - [Length(0, 9)] + [MaxLength(9)] public string? OkColor { get; set; } - [Length(0, 9)] + [MaxLength(9)] public string? ErrorColor { get; set; } - [Length(0, 9)] + [MaxLength(9)] public string? PendingColor { get; set; } } \ No newline at end of file diff --git a/src/EllieBot/Db/Models/GuildConfig.cs b/src/EllieBot/Db/Models/GuildConfig.cs index 59872e2..787cddd 100644 --- a/src/EllieBot/Db/Models/GuildConfig.cs +++ b/src/EllieBot/Db/Models/GuildConfig.cs @@ -13,24 +13,6 @@ public class GuildConfig : DbEntity public string AutoAssignRoleIds { get; set; } - // //greet stuff - // public int AutoDeleteGreetMessagesTimer { get; set; } = 30; - // public int AutoDeleteByeMessagesTimer { get; set; } = 30; - // - // public ulong GreetMessageChannelId { get; set; } - // public ulong ByeMessageChannelId { get; set; } - // - // public bool SendDmGreetMessage { get; set; } - // public string DmGreetMessageText { get; set; } = "Welcome to the %server% server, %user%!"; - // - // public bool SendChannelGreetMessage { get; set; } - // public string ChannelGreetMessageText { get; set; } = "Welcome to the %server% server, %user%!"; - // - // public bool SendChannelByeMessage { get; set; } - // public string ChannelByeMessageText { get; set; } = "%user% has left!"; - // public bool SendBoostMessage { get; set; } - // pulic int BoostMessageDeleteAfter { get; set; } - //todo FUTURE: DELETE, UNUSED public bool ExclusiveSelfAssignedRoles { get; set; } public bool AutoDeleteSelfAssignedRoleMessages { get; set; } @@ -97,9 +79,5 @@ public class GuildConfig : DbEntity public bool DisableGlobalExpressions { get; set; } = false; - #region Boost Message - public bool StickyRoles { get; set; } - - #endregion } \ No newline at end of file diff --git a/src/EllieBot/Db/Models/btnrole/ButtonRole.cs b/src/EllieBot/Db/Models/btnrole/ButtonRole.cs new file mode 100644 index 0000000..64c3ef8 --- /dev/null +++ b/src/EllieBot/Db/Models/btnrole/ButtonRole.cs @@ -0,0 +1,25 @@ +using System.ComponentModel.DataAnnotations; + +namespace EllieBot.Db.Models; + +public sealed class ButtonRole +{ + [Key] + public int Id { get; set; } + + [MaxLength(200)] + public string ButtonId { get; set; } = string.Empty; + + public ulong GuildId { get; set; } + public ulong ChannelId { get; set; } + public ulong MessageId { get; set; } + + public int Position { get; set; } + public ulong RoleId { get; set; } + + [MaxLength(100)] + public string Emote { get; set; } = string.Empty; + + [MaxLength(50)] + public string Label { get; set; } = string.Empty; +} diff --git a/src/EllieBot/Migrations/PostgreSql/20241127120348_guildcolors.Designer.cs b/src/EllieBot/Migrations/PostgreSql/20241127120348_guildcolors.Designer.cs new file mode 100644 index 0000000..478a5a8 --- /dev/null +++ b/src/EllieBot/Migrations/PostgreSql/20241127120348_guildcolors.Designer.cs @@ -0,0 +1,4048 @@ +// +using System; +using EllieBot.Db; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace EllieBot.Migrations.PostgreSql +{ + [DbContext(typeof(PostgreSqlContext))] + [Migration("20241127120348_guildcolors")] + partial class guildcolors + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.8") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("EllieBot.Db.Models.AntiAltSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("integer") + .HasColumnName("action"); + + b.Property("ActionDurationMinutes") + .HasColumnType("integer") + .HasColumnName("actiondurationminutes"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("MinAge") + .HasColumnType("interval") + .HasColumnName("minage"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_antialtsetting"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_antialtsetting_guildconfigid"); + + b.ToTable("antialtsetting", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiRaidSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("integer") + .HasColumnName("action"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("PunishDuration") + .HasColumnType("integer") + .HasColumnName("punishduration"); + + b.Property("Seconds") + .HasColumnType("integer") + .HasColumnName("seconds"); + + b.Property("UserThreshold") + .HasColumnType("integer") + .HasColumnName("userthreshold"); + + b.HasKey("Id") + .HasName("pk_antiraidsetting"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_antiraidsetting_guildconfigid"); + + b.ToTable("antiraidsetting", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiSpamIgnore", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AntiSpamSettingId") + .HasColumnType("integer") + .HasColumnName("antispamsettingid"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.HasKey("Id") + .HasName("pk_antispamignore"); + + b.HasIndex("AntiSpamSettingId") + .HasDatabaseName("ix_antispamignore_antispamsettingid"); + + b.ToTable("antispamignore", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiSpamSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Action") + .HasColumnType("integer") + .HasColumnName("action"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("MessageThreshold") + .HasColumnType("integer") + .HasColumnName("messagethreshold"); + + b.Property("MuteTime") + .HasColumnType("integer") + .HasColumnName("mutetime"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_antispamsetting"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_antispamsetting_guildconfigid"); + + b.ToTable("antispamsetting", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ArchivedTodoListModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_todosarchive"); + + b.ToTable("todosarchive", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoCommand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("ChannelName") + .HasColumnType("text") + .HasColumnName("channelname"); + + b.Property("CommandText") + .HasColumnType("text") + .HasColumnName("commandtext"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("GuildName") + .HasColumnType("text") + .HasColumnName("guildname"); + + b.Property("Interval") + .HasColumnType("integer") + .HasColumnName("interval"); + + b.Property("VoiceChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("voicechannelid"); + + b.Property("VoiceChannelName") + .HasColumnType("text") + .HasColumnName("voicechannelname"); + + b.HasKey("Id") + .HasName("pk_autocommands"); + + b.ToTable("autocommands", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoPublishChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.HasKey("Id") + .HasName("pk_autopublishchannel"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_autopublishchannel_guildid"); + + b.ToTable("autopublishchannel", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoTranslateChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoDelete") + .HasColumnType("boolean") + .HasColumnName("autodelete"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.HasKey("Id") + .HasName("pk_autotranslatechannels"); + + b.HasIndex("ChannelId") + .IsUnique() + .HasDatabaseName("ix_autotranslatechannels_channelid"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_autotranslatechannels_guildid"); + + b.ToTable("autotranslatechannels", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoTranslateUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("integer") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Source") + .HasColumnType("text") + .HasColumnName("source"); + + b.Property("Target") + .HasColumnType("text") + .HasColumnName("target"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_autotranslateusers"); + + b.HasAlternateKey("ChannelId", "UserId") + .HasName("ak_autotranslateusers_channelid_userid"); + + b.ToTable("autotranslateusers", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("PruneDays") + .HasColumnType("integer") + .HasColumnName("prunedays"); + + b.Property("Text") + .HasColumnType("text") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_bantemplates"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_bantemplates_guildid"); + + b.ToTable("bantemplates", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.BankUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Balance") + .HasColumnType("bigint") + .HasColumnName("balance"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_bankusers"); + + b.HasIndex("UserId") + .IsUnique() + .HasDatabaseName("ix_bankusers_userid"); + + b.ToTable("bankusers", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.BlacklistEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("ItemId") + .HasColumnType("numeric(20,0)") + .HasColumnName("itemid"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_blacklist"); + + b.ToTable("blacklist", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ButtonRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ButtonId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("buttonid"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("Emote") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("emote"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("label"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageid"); + + b.Property("Position") + .HasColumnType("integer") + .HasColumnName("position"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_buttonrole"); + + b.HasAlternateKey("RoleId", "MessageId") + .HasName("ak_buttonrole_roleid_messageid"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_buttonrole_guildid"); + + b.ToTable("buttonrole", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubApplicants", b => + { + b.Property("ClubId") + .HasColumnType("integer") + .HasColumnName("clubid"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("userid"); + + b.HasKey("ClubId", "UserId") + .HasName("pk_clubapplicants"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_clubapplicants_userid"); + + b.ToTable("clubapplicants", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubBans", b => + { + b.Property("ClubId") + .HasColumnType("integer") + .HasColumnName("clubid"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("userid"); + + b.HasKey("ClubId", "UserId") + .HasName("pk_clubbans"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_clubbans_userid"); + + b.ToTable("clubbans", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Description") + .HasColumnType("text") + .HasColumnName("description"); + + b.Property("ImageUrl") + .HasColumnType("text") + .HasColumnName("imageurl"); + + b.Property("Name") + .HasMaxLength(20) + .HasColumnType("character varying(20)") + .HasColumnName("name"); + + b.Property("OwnerId") + .HasColumnType("integer") + .HasColumnName("ownerid"); + + b.Property("Xp") + .HasColumnType("integer") + .HasColumnName("xp"); + + b.HasKey("Id") + .HasName("pk_clubs"); + + b.HasIndex("Name") + .IsUnique() + .HasDatabaseName("ix_clubs_name"); + + b.HasIndex("OwnerId") + .IsUnique() + .HasDatabaseName("ix_clubs_ownerid"); + + b.ToTable("clubs", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.CommandAlias", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Mapping") + .HasColumnType("text") + .HasColumnName("mapping"); + + b.Property("Trigger") + .HasColumnType("text") + .HasColumnName("trigger"); + + b.HasKey("Id") + .HasName("pk_commandalias"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_commandalias_guildconfigid"); + + b.ToTable("commandalias", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.CommandCooldown", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CommandName") + .HasColumnType("text") + .HasColumnName("commandname"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Seconds") + .HasColumnType("integer") + .HasColumnName("seconds"); + + b.HasKey("Id") + .HasName("pk_commandcooldown"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_commandcooldown_guildconfigid"); + + b.ToTable("commandcooldown", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.CurrencyTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Amount") + .HasColumnType("bigint") + .HasColumnName("amount"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Extra") + .IsRequired() + .HasColumnType("text") + .HasColumnName("extra"); + + b.Property("Note") + .HasColumnType("text") + .HasColumnName("note"); + + b.Property("OtherId") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)") + .HasColumnName("otherid") + .HasDefaultValueSql("NULL"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text") + .HasColumnName("type"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_currencytransactions"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_currencytransactions_userid"); + + b.ToTable("currencytransactions", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.DelMsgOnCmdChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("State") + .HasColumnType("boolean") + .HasColumnName("state"); + + b.HasKey("Id") + .HasName("pk_delmsgoncmdchannel"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_delmsgoncmdchannel_guildconfigid"); + + b.ToTable("delmsgoncmdchannel", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.DiscordPermOverride", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Command") + .HasColumnType("text") + .HasColumnName("command"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Perm") + .HasColumnType("numeric(20,0)") + .HasColumnName("perm"); + + b.HasKey("Id") + .HasName("pk_discordpermoverrides"); + + b.HasIndex("GuildId", "Command") + .IsUnique() + .HasDatabaseName("ix_discordpermoverrides_guildid_command"); + + b.ToTable("discordpermoverrides", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.DiscordUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AvatarId") + .HasColumnType("text") + .HasColumnName("avatarid"); + + b.Property("ClubId") + .HasColumnType("integer") + .HasColumnName("clubid"); + + b.Property("CurrencyAmount") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(0L) + .HasColumnName("currencyamount"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("IsClubAdmin") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("isclubadmin"); + + b.Property("NotifyOnLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("notifyonlevelup"); + + b.Property("TotalXp") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(0L) + .HasColumnName("totalxp"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Username") + .HasColumnType("text") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_discorduser"); + + b.HasAlternateKey("UserId") + .HasName("ak_discorduser_userid"); + + b.HasIndex("ClubId") + .HasDatabaseName("ix_discorduser_clubid"); + + b.HasIndex("CurrencyAmount") + .HasDatabaseName("ix_discorduser_currencyamount"); + + b.HasIndex("TotalXp") + .HasDatabaseName("ix_discorduser_totalxp"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_discorduser_userid"); + + b.HasIndex("Username") + .HasDatabaseName("ix_discorduser_username"); + + b.ToTable("discorduser", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.EllieExpression", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AllowTarget") + .HasColumnType("boolean") + .HasColumnName("allowtarget"); + + b.Property("AutoDeleteTrigger") + .HasColumnType("boolean") + .HasColumnName("autodeletetrigger"); + + b.Property("ContainsAnywhere") + .HasColumnType("boolean") + .HasColumnName("containsanywhere"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("DmResponse") + .HasColumnType("boolean") + .HasColumnName("dmresponse"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Reactions") + .HasColumnType("text") + .HasColumnName("reactions"); + + b.Property("Response") + .HasColumnType("text") + .HasColumnName("response"); + + b.Property("Trigger") + .HasColumnType("text") + .HasColumnName("trigger"); + + b.HasKey("Id") + .HasName("pk_expressions"); + + b.ToTable("expressions", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ExcludedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("ItemId") + .HasColumnType("numeric(20,0)") + .HasColumnName("itemid"); + + b.Property("ItemType") + .HasColumnType("integer") + .HasColumnName("itemtype"); + + b.Property("XpSettingsId") + .HasColumnType("integer") + .HasColumnName("xpsettingsid"); + + b.HasKey("Id") + .HasName("pk_excludeditem"); + + b.HasIndex("XpSettingsId") + .HasDatabaseName("ix_excludeditem_xpsettingsid"); + + b.ToTable("excludeditem", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FeedSub", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("Url") + .IsRequired() + .HasColumnType("text") + .HasColumnName("url"); + + b.HasKey("Id") + .HasName("pk_feedsub"); + + b.HasAlternateKey("GuildConfigId", "Url") + .HasName("ak_feedsub_guildconfigid_url"); + + b.ToTable("feedsub", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilterChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_filterchannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filterchannelid_guildconfigid"); + + b.ToTable("filterchannelid", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilterLinksChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_filterlinkschannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filterlinkschannelid_guildconfigid"); + + b.ToTable("filterlinkschannelid", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilterWordsChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_filterwordschannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filterwordschannelid_guildconfigid"); + + b.ToTable("filterwordschannelid", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilteredWord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Word") + .HasColumnType("text") + .HasColumnName("word"); + + b.HasKey("Id") + .HasName("pk_filteredword"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_filteredword_guildconfigid"); + + b.ToTable("filteredword", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FlagTranslateChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.HasKey("Id") + .HasName("pk_flagtranslatechannel"); + + b.HasIndex("GuildId", "ChannelId") + .IsUnique() + .HasDatabaseName("ix_flagtranslatechannel_guildid_channelid"); + + b.ToTable("flagtranslatechannel", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FollowedStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("Username") + .HasColumnType("text") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_followedstream"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_followedstream_guildconfigid"); + + b.ToTable("followedstream", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GCChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.HasKey("Id") + .HasName("pk_gcchannelid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_gcchannelid_guildconfigid"); + + b.ToTable("gcchannelid", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GamblingStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Bet") + .HasColumnType("numeric") + .HasColumnName("bet"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Feature") + .HasColumnType("text") + .HasColumnName("feature"); + + b.Property("PaidOut") + .HasColumnType("numeric") + .HasColumnName("paidout"); + + b.HasKey("Id") + .HasName("pk_gamblingstats"); + + b.HasIndex("Feature") + .IsUnique() + .HasDatabaseName("ix_gamblingstats_feature"); + + b.ToTable("gamblingstats", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GiveawayModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("EndsAt") + .HasColumnType("timestamp without time zone") + .HasColumnName("endsat"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageid"); + + b.HasKey("Id") + .HasName("pk_giveawaymodel"); + + b.ToTable("giveawaymodel", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GiveawayUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("GiveawayId") + .HasColumnType("integer") + .HasColumnName("giveawayid"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_giveawayuser"); + + b.HasIndex("GiveawayId", "UserId") + .IsUnique() + .HasDatabaseName("ix_giveawayuser_giveawayid_userid"); + + b.ToTable("giveawayuser", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GuildColors", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ErrorColor") + .HasMaxLength(9) + .HasColumnType("character varying(9)") + .HasColumnName("errorcolor"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("OkColor") + .HasMaxLength(9) + .HasColumnType("character varying(9)") + .HasColumnName("okcolor"); + + b.Property("PendingColor") + .HasMaxLength(9) + .HasColumnType("character varying(9)") + .HasColumnName("pendingcolor"); + + b.HasKey("Id") + .HasName("pk_guildcolors"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_guildcolors_guildid"); + + b.ToTable("guildcolors", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GuildConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoAssignRoleIds") + .HasColumnType("text") + .HasColumnName("autoassignroleids"); + + b.Property("AutoDeleteSelfAssignedRoleMessages") + .HasColumnType("boolean") + .HasColumnName("autodeleteselfassignedrolemessages"); + + b.Property("CleverbotEnabled") + .HasColumnType("boolean") + .HasColumnName("cleverbotenabled"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("DeleteMessageOnCommand") + .HasColumnType("boolean") + .HasColumnName("deletemessageoncommand"); + + b.Property("DeleteStreamOnlineMessage") + .HasColumnType("boolean") + .HasColumnName("deletestreamonlinemessage"); + + b.Property("DisableGlobalExpressions") + .HasColumnType("boolean") + .HasColumnName("disableglobalexpressions"); + + b.Property("ExclusiveSelfAssignedRoles") + .HasColumnType("boolean") + .HasColumnName("exclusiveselfassignedroles"); + + b.Property("FilterInvites") + .HasColumnType("boolean") + .HasColumnName("filterinvites"); + + b.Property("FilterLinks") + .HasColumnType("boolean") + .HasColumnName("filterlinks"); + + b.Property("FilterWords") + .HasColumnType("boolean") + .HasColumnName("filterwords"); + + b.Property("GameVoiceChannel") + .HasColumnType("numeric(20,0)") + .HasColumnName("gamevoicechannel"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Locale") + .HasColumnType("text") + .HasColumnName("locale"); + + b.Property("MuteRoleName") + .HasColumnType("text") + .HasColumnName("muterolename"); + + b.Property("NotifyStreamOffline") + .HasColumnType("boolean") + .HasColumnName("notifystreamoffline"); + + b.Property("PermissionRole") + .HasColumnType("text") + .HasColumnName("permissionrole"); + + b.Property("Prefix") + .HasColumnType("text") + .HasColumnName("prefix"); + + b.Property("StickyRoles") + .HasColumnType("boolean") + .HasColumnName("stickyroles"); + + b.Property("TimeZoneId") + .HasColumnType("text") + .HasColumnName("timezoneid"); + + b.Property("VerboseErrors") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(true) + .HasColumnName("verboseerrors"); + + b.Property("VerbosePermissions") + .HasColumnType("boolean") + .HasColumnName("verbosepermissions"); + + b.Property("WarnExpireAction") + .HasColumnType("integer") + .HasColumnName("warnexpireaction"); + + b.Property("WarnExpireHours") + .HasColumnType("integer") + .HasColumnName("warnexpirehours"); + + b.Property("WarningsInitialized") + .HasColumnType("boolean") + .HasColumnName("warningsinitialized"); + + b.HasKey("Id") + .HasName("pk_guildconfigs"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_guildconfigs_guildid"); + + b.HasIndex("WarnExpireHours") + .HasDatabaseName("ix_guildconfigs_warnexpirehours"); + + b.ToTable("guildconfigs", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.HoneypotChannel", b => + { + b.Property("GuildId") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.HasKey("GuildId") + .HasName("pk_honeypotchannels"); + + b.ToTable("honeypotchannels", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.IgnoredLogItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("ItemType") + .HasColumnType("integer") + .HasColumnName("itemtype"); + + b.Property("LogItemId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logitemid"); + + b.Property("LogSettingId") + .HasColumnType("integer") + .HasColumnName("logsettingid"); + + b.HasKey("Id") + .HasName("pk_ignoredlogchannels"); + + b.HasIndex("LogSettingId", "LogItemId", "ItemType") + .IsUnique() + .HasDatabaseName("ix_ignoredlogchannels_logsettingid_logitemid_itemtype"); + + b.ToTable("ignoredlogchannels", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ImageOnlyChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_imageonlychannels"); + + b.HasIndex("ChannelId") + .IsUnique() + .HasDatabaseName("ix_imageonlychannels_channelid"); + + b.ToTable("imageonlychannels", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.LogSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelCreatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelcreatedid"); + + b.Property("ChannelDestroyedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channeldestroyedid"); + + b.Property("ChannelUpdatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelupdatedid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("LogOtherId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logotherid"); + + b.Property("LogUserPresenceId") + .HasColumnType("numeric(20,0)") + .HasColumnName("loguserpresenceid"); + + b.Property("LogVoicePresenceId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logvoicepresenceid"); + + b.Property("LogVoicePresenceTTSId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logvoicepresencettsid"); + + b.Property("LogWarnsId") + .HasColumnType("numeric(20,0)") + .HasColumnName("logwarnsid"); + + b.Property("MessageDeletedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messagedeletedid"); + + b.Property("MessageUpdatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageupdatedid"); + + b.Property("ThreadCreatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("threadcreatedid"); + + b.Property("ThreadDeletedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("threaddeletedid"); + + b.Property("UserBannedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userbannedid"); + + b.Property("UserJoinedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userjoinedid"); + + b.Property("UserLeftId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userleftid"); + + b.Property("UserMutedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("usermutedid"); + + b.Property("UserUnbannedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userunbannedid"); + + b.Property("UserUpdatedId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userupdatedid"); + + b.HasKey("Id") + .HasName("pk_logsettings"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_logsettings_guildid"); + + b.ToTable("logsettings", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.MusicPlayerSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoDisconnect") + .HasColumnType("boolean") + .HasColumnName("autodisconnect"); + + b.Property("AutoPlay") + .HasColumnType("boolean") + .HasColumnName("autoplay"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("MusicChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("musicchannelid"); + + b.Property("PlayerRepeat") + .HasColumnType("integer") + .HasColumnName("playerrepeat"); + + b.Property("QualityPreset") + .HasColumnType("integer") + .HasColumnName("qualitypreset"); + + b.Property("Volume") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(100) + .HasColumnName("volume"); + + b.HasKey("Id") + .HasName("pk_musicplayersettings"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_musicplayersettings_guildid"); + + b.ToTable("musicplayersettings", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.MusicPlaylist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Author") + .HasColumnType("text") + .HasColumnName("author"); + + b.Property("AuthorId") + .HasColumnType("numeric(20,0)") + .HasColumnName("authorid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("pk_musicplaylists"); + + b.ToTable("musicplaylists", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.MutedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_muteduserid"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_muteduserid_guildconfigid"); + + b.ToTable("muteduserid", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.NCPixel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Color") + .HasColumnType("bigint") + .HasColumnName("color"); + + b.Property("OwnerId") + .HasColumnType("numeric(20,0)") + .HasColumnName("ownerid"); + + b.Property("Position") + .HasColumnType("integer") + .HasColumnName("position"); + + b.Property("Price") + .HasColumnType("bigint") + .HasColumnName("price"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("character varying(256)") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_ncpixel"); + + b.HasAlternateKey("Position") + .HasName("ak_ncpixel_position"); + + b.HasIndex("OwnerId") + .HasDatabaseName("ix_ncpixel_ownerid"); + + b.ToTable("ncpixel", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.PatronUser", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("AmountCents") + .HasColumnType("integer") + .HasColumnName("amountcents"); + + b.Property("LastCharge") + .HasColumnType("timestamp without time zone") + .HasColumnName("lastcharge"); + + b.Property("UniquePlatformUserId") + .HasColumnType("text") + .HasColumnName("uniqueplatformuserid"); + + b.Property("ValidThru") + .HasColumnType("timestamp without time zone") + .HasColumnName("validthru"); + + b.HasKey("UserId") + .HasName("pk_patrons"); + + b.HasIndex("UniquePlatformUserId") + .IsUnique() + .HasDatabaseName("ix_patrons_uniqueplatformuserid"); + + b.ToTable("patrons", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Permissionv2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Index") + .HasColumnType("integer") + .HasColumnName("index"); + + b.Property("IsCustomCommand") + .HasColumnType("boolean") + .HasColumnName("iscustomcommand"); + + b.Property("PrimaryTarget") + .HasColumnType("integer") + .HasColumnName("primarytarget"); + + b.Property("PrimaryTargetId") + .HasColumnType("numeric(20,0)") + .HasColumnName("primarytargetid"); + + b.Property("SecondaryTarget") + .HasColumnType("integer") + .HasColumnName("secondarytarget"); + + b.Property("SecondaryTargetName") + .HasColumnType("text") + .HasColumnName("secondarytargetname"); + + b.Property("State") + .HasColumnType("boolean") + .HasColumnName("state"); + + b.HasKey("Id") + .HasName("pk_permissions"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_permissions_guildconfigid"); + + b.ToTable("permissions", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.PlantedCurrency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Amount") + .HasColumnType("bigint") + .HasColumnName("amount"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageid"); + + b.Property("Password") + .HasColumnType("text") + .HasColumnName("password"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_plantedcurrency"); + + b.HasIndex("ChannelId") + .HasDatabaseName("ix_plantedcurrency_channelid"); + + b.HasIndex("MessageId") + .IsUnique() + .HasDatabaseName("ix_plantedcurrency_messageid"); + + b.ToTable("plantedcurrency", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.PlaylistSong", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("MusicPlaylistId") + .HasColumnType("integer") + .HasColumnName("musicplaylistid"); + + b.Property("Provider") + .HasColumnType("text") + .HasColumnName("provider"); + + b.Property("ProviderType") + .HasColumnType("integer") + .HasColumnName("providertype"); + + b.Property("Query") + .HasColumnType("text") + .HasColumnName("query"); + + b.Property("Title") + .HasColumnType("text") + .HasColumnName("title"); + + b.Property("Uri") + .HasColumnType("text") + .HasColumnName("uri"); + + b.HasKey("Id") + .HasName("pk_playlistsong"); + + b.HasIndex("MusicPlaylistId") + .HasDatabaseName("ix_playlistsong_musicplaylistid"); + + b.ToTable("playlistsong", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Quote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .HasColumnType("numeric(20,0)") + .HasColumnName("authorid"); + + b.Property("AuthorName") + .IsRequired() + .HasColumnType("text") + .HasColumnName("authorname"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Keyword") + .IsRequired() + .HasColumnType("text") + .HasColumnName("keyword"); + + b.Property("Text") + .IsRequired() + .HasColumnType("text") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_quotes"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_quotes_guildid"); + + b.HasIndex("Keyword") + .HasDatabaseName("ix_quotes_keyword"); + + b.ToTable("quotes", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ReactionRoleV2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Emote") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("emote"); + + b.Property("Group") + .HasColumnType("integer") + .HasColumnName("group"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("LevelReq") + .HasColumnType("integer") + .HasColumnName("levelreq"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageid"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_reactionroles"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_reactionroles_guildid"); + + b.HasIndex("MessageId", "Emote") + .IsUnique() + .HasDatabaseName("ix_reactionroles_messageid_emote"); + + b.ToTable("reactionroles", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Reminder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("IsPrivate") + .HasColumnType("boolean") + .HasColumnName("isprivate"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("ServerId") + .HasColumnType("numeric(20,0)") + .HasColumnName("serverid"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("When") + .HasColumnType("timestamp without time zone") + .HasColumnName("when"); + + b.HasKey("Id") + .HasName("pk_reminders"); + + b.HasIndex("When") + .HasDatabaseName("ix_reminders_when"); + + b.ToTable("reminders", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Repeater", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Interval") + .HasColumnType("interval") + .HasColumnName("interval"); + + b.Property("LastMessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("lastmessageid"); + + b.Property("Message") + .HasColumnType("text") + .HasColumnName("message"); + + b.Property("NoRedundant") + .HasColumnType("boolean") + .HasColumnName("noredundant"); + + b.Property("StartTimeOfDay") + .HasColumnType("interval") + .HasColumnName("starttimeofday"); + + b.HasKey("Id") + .HasName("pk_repeaters"); + + b.ToTable("repeaters", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.RewardedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AmountRewardedThisMonth") + .HasColumnType("bigint") + .HasColumnName("amountrewardedthismonth"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("LastReward") + .HasColumnType("timestamp without time zone") + .HasColumnName("lastreward"); + + b.Property("PlatformUserId") + .HasColumnType("text") + .HasColumnName("platformuserid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_rewardedusers"); + + b.HasIndex("PlatformUserId") + .IsUnique() + .HasDatabaseName("ix_rewardedusers_platformuserid"); + + b.ToTable("rewardedusers", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.RotatingPlayingStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Status") + .HasColumnType("text") + .HasColumnName("status"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_rotatingstatus"); + + b.ToTable("rotatingstatus", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Sar", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("LevelReq") + .HasColumnType("integer") + .HasColumnName("levelreq"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("SarGroupId") + .HasColumnType("integer") + .HasColumnName("sargroupid"); + + b.HasKey("Id") + .HasName("pk_sar"); + + b.HasAlternateKey("GuildId", "RoleId") + .HasName("ak_sar_guildid_roleid"); + + b.HasIndex("SarGroupId") + .HasDatabaseName("ix_sar_sargroupid"); + + b.ToTable("sar", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SarAutoDelete", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("IsEnabled") + .HasColumnType("boolean") + .HasColumnName("isenabled"); + + b.HasKey("Id") + .HasName("pk_sarautodelete"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_sarautodelete_guildid"); + + b.ToTable("sarautodelete", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SarGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GroupNumber") + .HasColumnType("integer") + .HasColumnName("groupnumber"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("IsExclusive") + .HasColumnType("boolean") + .HasColumnName("isexclusive"); + + b.Property("Name") + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("name"); + + b.Property("RoleReq") + .HasColumnType("numeric(20,0)") + .HasColumnName("rolereq"); + + b.HasKey("Id") + .HasName("pk_sargroup"); + + b.HasAlternateKey("GuildId", "GroupNumber") + .HasName("ak_sargroup_guildid_groupnumber"); + + b.ToTable("sargroup", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AuthorId") + .HasColumnType("numeric(20,0)") + .HasColumnName("authorid"); + + b.Property("Command") + .HasColumnType("text") + .HasColumnName("command"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Index") + .HasColumnType("integer") + .HasColumnName("index"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Price") + .HasColumnType("integer") + .HasColumnName("price"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("RoleName") + .HasColumnType("text") + .HasColumnName("rolename"); + + b.Property("RoleRequirement") + .HasColumnType("numeric(20,0)") + .HasColumnName("rolerequirement"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_shopentry"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_shopentry_guildconfigid"); + + b.ToTable("shopentry", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ShopEntryItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("ShopEntryId") + .HasColumnType("integer") + .HasColumnName("shopentryid"); + + b.Property("Text") + .HasColumnType("text") + .HasColumnName("text"); + + b.HasKey("Id") + .HasName("pk_shopentryitem"); + + b.HasIndex("ShopEntryId") + .HasDatabaseName("ix_shopentryitem_shopentryid"); + + b.ToTable("shopentryitem", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SlowmodeIgnoredRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_slowmodeignoredrole"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_slowmodeignoredrole_guildconfigid"); + + b.ToTable("slowmodeignoredrole", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SlowmodeIgnoredUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_slowmodeignoreduser"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_slowmodeignoreduser_guildconfigid"); + + b.ToTable("slowmodeignoreduser", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StickyRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("RoleIds") + .HasColumnType("text") + .HasColumnName("roleids"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_stickyroles"); + + b.HasIndex("GuildId", "UserId") + .IsUnique() + .HasDatabaseName("ix_stickyroles_guildid_userid"); + + b.ToTable("stickyroles", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamOnlineMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageid"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Type") + .HasColumnType("integer") + .HasColumnName("type"); + + b.HasKey("Id") + .HasName("pk_streamonlinemessages"); + + b.ToTable("streamonlinemessages", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleBlacklistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("integer") + .HasColumnName("streamrolesettingsid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Username") + .HasColumnType("text") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_streamroleblacklisteduser"); + + b.HasIndex("StreamRoleSettingsId") + .HasDatabaseName("ix_streamroleblacklisteduser_streamrolesettingsid"); + + b.ToTable("streamroleblacklisteduser", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AddRoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("addroleid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Enabled") + .HasColumnType("boolean") + .HasColumnName("enabled"); + + b.Property("FromRoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("fromroleid"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("Keyword") + .HasColumnType("text") + .HasColumnName("keyword"); + + b.HasKey("Id") + .HasName("pk_streamrolesettings"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_streamrolesettings_guildconfigid"); + + b.ToTable("streamrolesettings", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleWhitelistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("integer") + .HasColumnName("streamrolesettingsid"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Username") + .HasColumnType("text") + .HasColumnName("username"); + + b.HasKey("Id") + .HasName("pk_streamrolewhitelisteduser"); + + b.HasIndex("StreamRoleSettingsId") + .HasDatabaseName("ix_streamrolewhitelisteduser_streamrolesettingsid"); + + b.ToTable("streamrolewhitelisteduser", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.TodoModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ArchiveId") + .HasColumnType("integer") + .HasColumnName("archiveid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("IsDone") + .HasColumnType("boolean") + .HasColumnName("isdone"); + + b.Property("Todo") + .HasColumnType("text") + .HasColumnName("todo"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_todos"); + + b.HasIndex("ArchiveId") + .HasDatabaseName("ix_todos_archiveid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_todos_userid"); + + b.ToTable("todos", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnbanTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("UnbanAt") + .HasColumnType("timestamp without time zone") + .HasColumnName("unbanat"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_unbantimer"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_unbantimer_guildconfigid"); + + b.ToTable("unbantimer", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnmuteTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("UnmuteAt") + .HasColumnType("timestamp without time zone") + .HasColumnName("unmuteat"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_unmutetimer"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_unmutetimer_guildconfigid"); + + b.ToTable("unmutetimer", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnroleTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("UnbanAt") + .HasColumnType("timestamp without time zone") + .HasColumnName("unbanat"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_unroletimer"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_unroletimer_guildconfigid"); + + b.ToTable("unroletimer", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UserXpStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AwardedXp") + .HasColumnType("bigint") + .HasColumnName("awardedxp"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("NotifyOnLevelUp") + .HasColumnType("integer") + .HasColumnName("notifyonlevelup"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Xp") + .HasColumnType("bigint") + .HasColumnName("xp"); + + b.HasKey("Id") + .HasName("pk_userxpstats"); + + b.HasIndex("AwardedXp") + .HasDatabaseName("ix_userxpstats_awardedxp"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_userxpstats_guildid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_userxpstats_userid"); + + b.HasIndex("Xp") + .HasDatabaseName("ix_userxpstats_xp"); + + b.HasIndex("UserId", "GuildId") + .IsUnique() + .HasDatabaseName("ix_userxpstats_userid_guildid"); + + b.ToTable("userxpstats", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.VcRoleInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("VoiceChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("voicechannelid"); + + b.HasKey("Id") + .HasName("pk_vcroleinfo"); + + b.HasIndex("GuildConfigId") + .HasDatabaseName("ix_vcroleinfo_guildconfigid"); + + b.ToTable("vcroleinfo", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AffinityId") + .HasColumnType("integer") + .HasColumnName("affinityid"); + + b.Property("ClaimerId") + .HasColumnType("integer") + .HasColumnName("claimerid"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Price") + .HasColumnType("bigint") + .HasColumnName("price"); + + b.Property("WaifuId") + .HasColumnType("integer") + .HasColumnName("waifuid"); + + b.HasKey("Id") + .HasName("pk_waifuinfo"); + + b.HasIndex("AffinityId") + .HasDatabaseName("ix_waifuinfo_affinityid"); + + b.HasIndex("ClaimerId") + .HasDatabaseName("ix_waifuinfo_claimerid"); + + b.HasIndex("Price") + .HasDatabaseName("ix_waifuinfo_price"); + + b.HasIndex("WaifuId") + .IsUnique() + .HasDatabaseName("ix_waifuinfo_waifuid"); + + b.ToTable("waifuinfo", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("ItemEmoji") + .HasColumnType("text") + .HasColumnName("itememoji"); + + b.Property("Name") + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("WaifuInfoId") + .HasColumnType("integer") + .HasColumnName("waifuinfoid"); + + b.HasKey("Id") + .HasName("pk_waifuitem"); + + b.HasIndex("WaifuInfoId") + .HasDatabaseName("ix_waifuitem_waifuinfoid"); + + b.ToTable("waifuitem", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuUpdate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("NewId") + .HasColumnType("integer") + .HasColumnName("newid"); + + b.Property("OldId") + .HasColumnType("integer") + .HasColumnName("oldid"); + + b.Property("UpdateType") + .HasColumnType("integer") + .HasColumnName("updatetype"); + + b.Property("UserId") + .HasColumnType("integer") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_waifuupdates"); + + b.HasIndex("NewId") + .HasDatabaseName("ix_waifuupdates_newid"); + + b.HasIndex("OldId") + .HasDatabaseName("ix_waifuupdates_oldid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_waifuupdates_userid"); + + b.ToTable("waifuupdates", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Warning", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Forgiven") + .HasColumnType("boolean") + .HasColumnName("forgiven"); + + b.Property("ForgivenBy") + .HasColumnType("text") + .HasColumnName("forgivenby"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Moderator") + .HasColumnType("text") + .HasColumnName("moderator"); + + b.Property("Reason") + .HasColumnType("text") + .HasColumnName("reason"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Weight") + .ValueGeneratedOnAdd() + .HasColumnType("bigint") + .HasDefaultValue(1L) + .HasColumnName("weight"); + + b.HasKey("Id") + .HasName("pk_warnings"); + + b.HasIndex("DateAdded") + .HasDatabaseName("ix_warnings_dateadded"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_warnings_guildid"); + + b.HasIndex("UserId") + .HasDatabaseName("ix_warnings_userid"); + + b.ToTable("warnings", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WarningPunishment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Count") + .HasColumnType("integer") + .HasColumnName("count"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Punishment") + .HasColumnType("integer") + .HasColumnName("punishment"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("Time") + .HasColumnType("integer") + .HasColumnName("time"); + + b.HasKey("Id") + .HasName("pk_warningpunishment"); + + b.HasAlternateKey("GuildId", "Count") + .HasName("ak_warningpunishment_guildid_count"); + + b.ToTable("warningpunishment", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpCurrencyReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Amount") + .HasColumnType("integer") + .HasColumnName("amount"); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Level") + .HasColumnType("integer") + .HasColumnName("level"); + + b.Property("XpSettingsId") + .HasColumnType("integer") + .HasColumnName("xpsettingsid"); + + b.HasKey("Id") + .HasName("pk_xpcurrencyreward"); + + b.HasIndex("XpSettingsId") + .HasDatabaseName("ix_xpcurrencyreward_xpsettingsid"); + + b.ToTable("xpcurrencyreward", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpRoleReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("Level") + .HasColumnType("integer") + .HasColumnName("level"); + + b.Property("Remove") + .HasColumnType("boolean") + .HasColumnName("remove"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.Property("XpSettingsId") + .HasColumnType("integer") + .HasColumnName("xpsettingsid"); + + b.HasKey("Id") + .HasName("pk_xprolereward"); + + b.HasIndex("XpSettingsId", "Level") + .IsUnique() + .HasDatabaseName("ix_xprolereward_xpsettingsid_level"); + + b.ToTable("xprolereward", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("GuildConfigId") + .HasColumnType("integer") + .HasColumnName("guildconfigid"); + + b.Property("ServerExcluded") + .HasColumnType("boolean") + .HasColumnName("serverexcluded"); + + b.HasKey("Id") + .HasName("pk_xpsettings"); + + b.HasIndex("GuildConfigId") + .IsUnique() + .HasDatabaseName("ix_xpsettings_guildconfigid"); + + b.ToTable("xpsettings", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpShopOwnedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("DateAdded") + .HasColumnType("timestamp without time zone") + .HasColumnName("dateadded"); + + b.Property("IsUsing") + .HasColumnType("boolean") + .HasColumnName("isusing"); + + b.Property("ItemKey") + .IsRequired() + .HasColumnType("text") + .HasColumnName("itemkey"); + + b.Property("ItemType") + .HasColumnType("integer") + .HasColumnName("itemtype"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.HasKey("Id") + .HasName("pk_xpshopowneditem"); + + b.HasIndex("UserId", "ItemType", "ItemKey") + .IsUnique() + .HasDatabaseName("ix_xpshopowneditem_userid_itemtype_itemkey"); + + b.ToTable("xpshopowneditem", (string)null); + }); + + modelBuilder.Entity("EllieBot.Services.GreetSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("AutoDeleteTimer") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasDefaultValue(0) + .HasColumnName("autodeletetimer"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("GreetType") + .HasColumnType("integer") + .HasColumnName("greettype"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("IsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("boolean") + .HasDefaultValue(false) + .HasColumnName("isenabled"); + + b.Property("MessageText") + .HasColumnType("text") + .HasColumnName("messagetext"); + + b.HasKey("Id") + .HasName("pk_greetsettings"); + + b.HasIndex("GuildId", "GreetType") + .IsUnique() + .HasDatabaseName("ix_greetsettings_guildid_greettype"); + + b.ToTable("greetsettings", (string)null); + }); + + modelBuilder.Entity("EllieBot.Services.Rakeback", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("Amount") + .HasColumnType("numeric") + .HasColumnName("amount"); + + b.HasKey("UserId") + .HasName("pk_rakeback"); + + b.ToTable("rakeback", (string)null); + }); + + modelBuilder.Entity("EllieBot.Services.UserBetStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Game") + .HasColumnType("integer") + .HasColumnName("game"); + + b.Property("LoseCount") + .HasColumnType("bigint") + .HasColumnName("losecount"); + + b.Property("MaxBet") + .HasColumnType("bigint") + .HasColumnName("maxbet"); + + b.Property("MaxWin") + .HasColumnType("bigint") + .HasColumnName("maxwin"); + + b.Property("PaidOut") + .HasColumnType("numeric") + .HasColumnName("paidout"); + + b.Property("TotalBet") + .HasColumnType("numeric") + .HasColumnName("totalbet"); + + b.Property("UserId") + .HasColumnType("numeric(20,0)") + .HasColumnName("userid"); + + b.Property("WinCount") + .HasColumnType("bigint") + .HasColumnName("wincount"); + + b.HasKey("Id") + .HasName("pk_userbetstats"); + + b.HasIndex("UserId", "Game") + .IsUnique() + .HasDatabaseName("ix_userbetstats_userid_game"); + + b.ToTable("userbetstats", (string)null); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiAltSetting", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithOne("AntiAltSetting") + .HasForeignKey("EllieBot.Db.Models.AntiAltSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_antialtsetting_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiRaidSetting", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithOne("AntiRaidSetting") + .HasForeignKey("EllieBot.Db.Models.AntiRaidSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_antiraidsetting_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiSpamIgnore", b => + { + b.HasOne("EllieBot.Db.Models.AntiSpamSetting", null) + .WithMany("IgnoredChannels") + .HasForeignKey("AntiSpamSettingId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_antispamignore_antispamsetting_antispamsettingid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiSpamSetting", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithOne("AntiSpamSetting") + .HasForeignKey("EllieBot.Db.Models.AntiSpamSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_antispamsetting_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoTranslateUser", b => + { + b.HasOne("EllieBot.Db.Models.AutoTranslateChannel", "Channel") + .WithMany("Users") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_autotranslateusers_autotranslatechannels_channelid"); + + b.Navigation("Channel"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubApplicants", b => + { + b.HasOne("EllieBot.Db.Models.ClubInfo", "Club") + .WithMany("Applicants") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubapplicants_clubs_clubid"); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubapplicants_discorduser_userid"); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubBans", b => + { + b.HasOne("EllieBot.Db.Models.ClubInfo", "Club") + .WithMany("Bans") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubbans_clubs_clubid"); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_clubbans_discorduser_userid"); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubInfo", b => + { + b.HasOne("EllieBot.Db.Models.DiscordUser", "Owner") + .WithOne() + .HasForeignKey("EllieBot.Db.Models.ClubInfo", "OwnerId") + .OnDelete(DeleteBehavior.SetNull) + .HasConstraintName("fk_clubs_discorduser_ownerid"); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.CommandAlias", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("CommandAliases") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_commandalias_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.CommandCooldown", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("CommandCooldowns") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_commandcooldown_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.DelMsgOnCmdChannel", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("DelMsgOnCmdChannels") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_delmsgoncmdchannel_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.DiscordUser", b => + { + b.HasOne("EllieBot.Db.Models.ClubInfo", "Club") + .WithMany("Members") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.NoAction) + .HasConstraintName("fk_discorduser_clubs_clubid"); + + b.Navigation("Club"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ExcludedItem", b => + { + b.HasOne("EllieBot.Db.Models.XpSettings", "XpSettings") + .WithMany("ExclusionList") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_excludeditem_xpsettings_xpsettingsid"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FeedSub", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", "GuildConfig") + .WithMany("FeedSubs") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_feedsub_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilterChannelId", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("FilterInvitesChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_filterchannelid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilterLinksChannelId", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("FilterLinksChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_filterlinkschannelid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilterWordsChannelId", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("FilterWordsChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_filterwordschannelid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilteredWord", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("FilteredWords") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_filteredword_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FollowedStream", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("FollowedStreams") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_followedstream_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GCChannelId", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", "GuildConfig") + .WithMany("GenerateCurrencyChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_gcchannelid_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GiveawayUser", b => + { + b.HasOne("EllieBot.Db.Models.GiveawayModel", null) + .WithMany("Participants") + .HasForeignKey("GiveawayId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_giveawayuser_giveawaymodel_giveawayid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.IgnoredLogItem", b => + { + b.HasOne("EllieBot.Db.Models.LogSetting", "LogSetting") + .WithMany("LogIgnores") + .HasForeignKey("LogSettingId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_ignoredlogchannels_logsettings_logsettingid"); + + b.Navigation("LogSetting"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.MutedUserId", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("MutedUsers") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_muteduserid_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Permissionv2", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("Permissions") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_permissions_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.PlaylistSong", b => + { + b.HasOne("EllieBot.Db.Models.MusicPlaylist", null) + .WithMany("Songs") + .HasForeignKey("MusicPlaylistId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_playlistsong_musicplaylists_musicplaylistid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Sar", b => + { + b.HasOne("EllieBot.Db.Models.SarGroup", null) + .WithMany("Roles") + .HasForeignKey("SarGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_sar_sargroup_sargroupid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("ShopEntries") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_shopentry_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ShopEntryItem", b => + { + b.HasOne("EllieBot.Db.Models.ShopEntry", null) + .WithMany("Items") + .HasForeignKey("ShopEntryId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_shopentryitem_shopentry_shopentryid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SlowmodeIgnoredRole", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredRoles") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_slowmodeignoredrole_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SlowmodeIgnoredUser", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredUsers") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_slowmodeignoreduser_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleBlacklistedUser", b => + { + b.HasOne("EllieBot.Db.Models.StreamRoleSettings", "StreamRoleSettings") + .WithMany("Blacklist") + .HasForeignKey("StreamRoleSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_streamroleblacklisteduser_streamrolesettings_streamrolesett~"); + + b.Navigation("StreamRoleSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleSettings", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", "GuildConfig") + .WithOne("StreamRole") + .HasForeignKey("EllieBot.Db.Models.StreamRoleSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_streamrolesettings_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleWhitelistedUser", b => + { + b.HasOne("EllieBot.Db.Models.StreamRoleSettings", "StreamRoleSettings") + .WithMany("Whitelist") + .HasForeignKey("StreamRoleSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_streamrolewhitelisteduser_streamrolesettings_streamrolesett~"); + + b.Navigation("StreamRoleSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.TodoModel", b => + { + b.HasOne("EllieBot.Db.Models.ArchivedTodoListModel", null) + .WithMany("Items") + .HasForeignKey("ArchiveId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_todos_todosarchive_archiveid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnbanTimer", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("UnbanTimer") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_unbantimer_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnmuteTimer", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("UnmuteTimers") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_unmutetimer_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnroleTimer", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("UnroleTimer") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_unroletimer_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.VcRoleInfo", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("VcRoleInfos") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .HasConstraintName("fk_vcroleinfo_guildconfigs_guildconfigid"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuInfo", b => + { + b.HasOne("EllieBot.Db.Models.DiscordUser", "Affinity") + .WithMany() + .HasForeignKey("AffinityId") + .HasConstraintName("fk_waifuinfo_discorduser_affinityid"); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "Claimer") + .WithMany() + .HasForeignKey("ClaimerId") + .HasConstraintName("fk_waifuinfo_discorduser_claimerid"); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "Waifu") + .WithOne() + .HasForeignKey("EllieBot.Db.Models.WaifuInfo", "WaifuId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_waifuinfo_discorduser_waifuid"); + + b.Navigation("Affinity"); + + b.Navigation("Claimer"); + + b.Navigation("Waifu"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuItem", b => + { + b.HasOne("EllieBot.Db.Models.WaifuInfo", "WaifuInfo") + .WithMany("Items") + .HasForeignKey("WaifuInfoId") + .HasConstraintName("fk_waifuitem_waifuinfo_waifuinfoid"); + + b.Navigation("WaifuInfo"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuUpdate", b => + { + b.HasOne("EllieBot.Db.Models.DiscordUser", "New") + .WithMany() + .HasForeignKey("NewId") + .HasConstraintName("fk_waifuupdates_discorduser_newid"); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "Old") + .WithMany() + .HasForeignKey("OldId") + .HasConstraintName("fk_waifuupdates_discorduser_oldid"); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_waifuupdates_discorduser_userid"); + + b.Navigation("New"); + + b.Navigation("Old"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpCurrencyReward", b => + { + b.HasOne("EllieBot.Db.Models.XpSettings", "XpSettings") + .WithMany("CurrencyRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_xpcurrencyreward_xpsettings_xpsettingsid"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpRoleReward", b => + { + b.HasOne("EllieBot.Db.Models.XpSettings", "XpSettings") + .WithMany("RoleRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_xprolereward_xpsettings_xpsettingsid"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpSettings", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", "GuildConfig") + .WithOne("XpSettings") + .HasForeignKey("EllieBot.Db.Models.XpSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired() + .HasConstraintName("fk_xpsettings_guildconfigs_guildconfigid"); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiSpamSetting", b => + { + b.Navigation("IgnoredChannels"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ArchivedTodoListModel", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoTranslateChannel", b => + { + b.Navigation("Users"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubInfo", b => + { + b.Navigation("Applicants"); + + b.Navigation("Bans"); + + b.Navigation("Members"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GiveawayModel", b => + { + b.Navigation("Participants"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GuildConfig", b => + { + b.Navigation("AntiAltSetting"); + + b.Navigation("AntiRaidSetting"); + + b.Navigation("AntiSpamSetting"); + + 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("GenerateCurrencyChannelIds"); + + b.Navigation("MutedUsers"); + + b.Navigation("Permissions"); + + b.Navigation("ShopEntries"); + + b.Navigation("SlowmodeIgnoredRoles"); + + b.Navigation("SlowmodeIgnoredUsers"); + + b.Navigation("StreamRole"); + + b.Navigation("UnbanTimer"); + + b.Navigation("UnmuteTimers"); + + b.Navigation("UnroleTimer"); + + b.Navigation("VcRoleInfos"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.LogSetting", b => + { + b.Navigation("LogIgnores"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.MusicPlaylist", b => + { + b.Navigation("Songs"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SarGroup", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleSettings", b => + { + b.Navigation("Blacklist"); + + b.Navigation("Whitelist"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuInfo", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpSettings", b => + { + b.Navigation("CurrencyRewards"); + + b.Navigation("ExclusionList"); + + b.Navigation("RoleRewards"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/EllieBot/Migrations/PostgreSql/20241127120348_guildcolors.cs b/src/EllieBot/Migrations/PostgreSql/20241127120348_guildcolors.cs new file mode 100644 index 0000000..66c373b --- /dev/null +++ b/src/EllieBot/Migrations/PostgreSql/20241127120348_guildcolors.cs @@ -0,0 +1,73 @@ +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace EllieBot.Migrations.PostgreSql +{ + /// + public partial class guildcolors : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "buttonrole", + columns: table => new + { + id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + buttonid = table.Column(type: "character varying(200)", maxLength: 200, nullable: false), + guildid = table.Column(type: "numeric(20,0)", nullable: false), + channelid = table.Column(type: "numeric(20,0)", nullable: false), + messageid = table.Column(type: "numeric(20,0)", nullable: false), + position = table.Column(type: "integer", nullable: false), + roleid = table.Column(type: "numeric(20,0)", nullable: false), + emote = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + label = table.Column(type: "character varying(50)", maxLength: 50, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("pk_buttonrole", x => x.id); + table.UniqueConstraint("ak_buttonrole_roleid_messageid", x => new { x.roleid, x.messageid }); + }); + + migrationBuilder.CreateTable( + name: "guildcolors", + columns: table => new + { + id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + guildid = table.Column(type: "numeric(20,0)", nullable: false), + okcolor = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), + errorcolor = table.Column(type: "character varying(9)", maxLength: 9, nullable: true), + pendingcolor = table.Column(type: "character varying(9)", maxLength: 9, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("pk_guildcolors", x => x.id); + }); + + migrationBuilder.CreateIndex( + name: "ix_buttonrole_guildid", + table: "buttonrole", + column: "guildid"); + + migrationBuilder.CreateIndex( + name: "ix_guildcolors_guildid", + table: "guildcolors", + column: "guildid", + unique: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "buttonrole"); + + migrationBuilder.DropTable( + name: "guildcolors"); + } + } +} diff --git a/src/EllieBot/Migrations/PostgreSql/PostgreSqlContextModelSnapshot.cs b/src/EllieBot/Migrations/PostgreSql/PostgreSqlContextModelSnapshot.cs index 4ed2d4b..4053ed2 100644 --- a/src/EllieBot/Migrations/PostgreSql/PostgreSqlContextModelSnapshot.cs +++ b/src/EllieBot/Migrations/PostgreSql/PostgreSqlContextModelSnapshot.cs @@ -451,6 +451,65 @@ namespace EllieBot.Migrations.PostgreSql b.ToTable("blacklist", (string)null); }); + modelBuilder.Entity("EllieBot.Db.Models.ButtonRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ButtonId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("character varying(200)") + .HasColumnName("buttonid"); + + b.Property("ChannelId") + .HasColumnType("numeric(20,0)") + .HasColumnName("channelid"); + + b.Property("Emote") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)") + .HasColumnName("emote"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("character varying(50)") + .HasColumnName("label"); + + b.Property("MessageId") + .HasColumnType("numeric(20,0)") + .HasColumnName("messageid"); + + b.Property("Position") + .HasColumnType("integer") + .HasColumnName("position"); + + b.Property("RoleId") + .HasColumnType("numeric(20,0)") + .HasColumnName("roleid"); + + b.HasKey("Id") + .HasName("pk_buttonrole"); + + b.HasAlternateKey("RoleId", "MessageId") + .HasName("ak_buttonrole_roleid_messageid"); + + b.HasIndex("GuildId") + .HasDatabaseName("ix_buttonrole_guildid"); + + b.ToTable("buttonrole", (string)null); + }); + modelBuilder.Entity("EllieBot.Db.Models.ClubApplicants", b => { b.Property("ClubId") @@ -1253,6 +1312,44 @@ namespace EllieBot.Migrations.PostgreSql b.ToTable("giveawayuser", (string)null); }); + modelBuilder.Entity("EllieBot.Db.Models.GuildColors", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer") + .HasColumnName("id"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ErrorColor") + .HasMaxLength(9) + .HasColumnType("character varying(9)") + .HasColumnName("errorcolor"); + + b.Property("GuildId") + .HasColumnType("numeric(20,0)") + .HasColumnName("guildid"); + + b.Property("OkColor") + .HasMaxLength(9) + .HasColumnType("character varying(9)") + .HasColumnName("okcolor"); + + b.Property("PendingColor") + .HasMaxLength(9) + .HasColumnType("character varying(9)") + .HasColumnName("pendingcolor"); + + b.HasKey("Id") + .HasName("pk_guildcolors"); + + b.HasIndex("GuildId") + .IsUnique() + .HasDatabaseName("ix_guildcolors_guildid"); + + b.ToTable("guildcolors", (string)null); + }); + modelBuilder.Entity("EllieBot.Db.Models.GuildConfig", b => { b.Property("Id") diff --git a/src/EllieBot/Migrations/Sqlite/20241127120303_guildcolors.Designer.cs b/src/EllieBot/Migrations/Sqlite/20241127120303_guildcolors.Designer.cs new file mode 100644 index 0000000..d2e42c9 --- /dev/null +++ b/src/EllieBot/Migrations/Sqlite/20241127120303_guildcolors.Designer.cs @@ -0,0 +1,3122 @@ +// +using System; +using EllieBot.Db; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace EllieBot.Migrations +{ + [DbContext(typeof(SqliteContext))] + [Migration("20241127120303_guildcolors")] + partial class guildcolors + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "8.0.8"); + + modelBuilder.Entity("EllieBot.Db.Models.AntiAltSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .HasColumnType("INTEGER"); + + b.Property("ActionDurationMinutes") + .HasColumnType("INTEGER"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("MinAge") + .HasColumnType("TEXT"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("AntiAltSetting"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiRaidSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + 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("EllieBot.Db.Models.AntiSpamIgnore", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AntiSpamSettingId") + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("AntiSpamSettingId"); + + b.ToTable("AntiSpamIgnore"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiSpamSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Action") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("MessageThreshold") + .HasColumnType("INTEGER"); + + b.Property("MuteTime") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("AntiSpamSetting"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ArchivedTodoListModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("TodosArchive"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoCommand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("ChannelName") + .HasColumnType("TEXT"); + + b.Property("CommandText") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("GuildName") + .HasColumnType("TEXT"); + + b.Property("Interval") + .HasColumnType("INTEGER"); + + b.Property("VoiceChannelId") + .HasColumnType("INTEGER"); + + b.Property("VoiceChannelName") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("AutoCommands"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoPublishChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("AutoPublishChannel"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoTranslateChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoDelete") + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId") + .IsUnique(); + + b.HasIndex("GuildId"); + + b.ToTable("AutoTranslateChannels"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoTranslateUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Source") + .HasColumnType("TEXT"); + + b.Property("Target") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasAlternateKey("ChannelId", "UserId"); + + b.ToTable("AutoTranslateUsers"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.BanTemplate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("PruneDays") + .HasColumnType("INTEGER"); + + b.Property("Text") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("BanTemplates"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.BankUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Balance") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId") + .IsUnique(); + + b.ToTable("BankUsers"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.BlacklistEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Blacklist"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ButtonRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ButtonId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("Emote") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("MessageId") + .HasColumnType("INTEGER"); + + b.Property("Position") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasAlternateKey("RoleId", "MessageId"); + + b.HasIndex("GuildId"); + + b.ToTable("ButtonRole"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubApplicants", b => + { + b.Property("ClubId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("ClubId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ClubApplicants"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubBans", b => + { + b.Property("ClubId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("ClubId", "UserId"); + + b.HasIndex("UserId"); + + b.ToTable("ClubBans"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("ImageUrl") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasMaxLength(20) + .HasColumnType("TEXT"); + + b.Property("OwnerId") + .HasColumnType("INTEGER"); + + b.Property("Xp") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.HasIndex("OwnerId") + .IsUnique(); + + b.ToTable("Clubs"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.CommandAlias", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + 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("EllieBot.Db.Models.CommandCooldown", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CommandName") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Seconds") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("CommandCooldown"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.CurrencyTransaction", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Amount") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Extra") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Note") + .HasColumnType("TEXT"); + + b.Property("OtherId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValueSql("NULL"); + + b.Property("Type") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("CurrencyTransactions"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.DelMsgOnCmdChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("State") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("DelMsgOnCmdChannel"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.DiscordPermOverride", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Command") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Perm") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "Command") + .IsUnique(); + + b.ToTable("DiscordPermOverrides"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.DiscordUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AvatarId") + .HasColumnType("TEXT"); + + b.Property("ClubId") + .HasColumnType("INTEGER"); + + b.Property("CurrencyAmount") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0L); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IsClubAdmin") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(false); + + b.Property("NotifyOnLevelUp") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0); + + b.Property("TotalXp") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0L); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasAlternateKey("UserId"); + + b.HasIndex("ClubId"); + + b.HasIndex("CurrencyAmount"); + + b.HasIndex("TotalXp"); + + b.HasIndex("UserId"); + + b.HasIndex("Username"); + + b.ToTable("DiscordUser"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.EllieExpression", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AllowTarget") + .HasColumnType("INTEGER"); + + b.Property("AutoDeleteTrigger") + .HasColumnType("INTEGER"); + + b.Property("ContainsAnywhere") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DmResponse") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Reactions") + .HasColumnType("TEXT"); + + b.Property("Response") + .HasColumnType("TEXT"); + + b.Property("Trigger") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Expressions"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ExcludedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("INTEGER"); + + b.Property("ItemType") + .HasColumnType("INTEGER"); + + b.Property("XpSettingsId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId"); + + b.ToTable("ExcludedItem"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FeedSub", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + 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("EllieBot.Db.Models.FilterChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilterChannelId"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilterLinksChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilterLinksChannelId"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilterWordsChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilterWordsChannelId"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilteredWord", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Word") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("FilteredWord"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FlagTranslateChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "ChannelId") + .IsUnique(); + + b.ToTable("FlagTranslateChannel"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FollowedStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + 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("EllieBot.Db.Models.GCChannelId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("GCChannelId"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GamblingStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Bet") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Feature") + .HasColumnType("TEXT"); + + b.Property("PaidOut") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Feature") + .IsUnique(); + + b.ToTable("GamblingStats"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GiveawayModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("EndsAt") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("MessageId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("GiveawayModel"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GiveawayUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("GiveawayId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GiveawayId", "UserId") + .IsUnique(); + + b.ToTable("GiveawayUser"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GuildColors", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ErrorColor") + .HasMaxLength(9) + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("OkColor") + .HasMaxLength(9) + .HasColumnType("TEXT"); + + b.Property("PendingColor") + .HasMaxLength(9) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("GuildColors"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GuildConfig", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoAssignRoleIds") + .HasColumnType("TEXT"); + + b.Property("AutoDeleteSelfAssignedRoleMessages") + .HasColumnType("INTEGER"); + + b.Property("CleverbotEnabled") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DeleteMessageOnCommand") + .HasColumnType("INTEGER"); + + b.Property("DeleteStreamOnlineMessage") + .HasColumnType("INTEGER"); + + b.Property("DisableGlobalExpressions") + .HasColumnType("INTEGER"); + + b.Property("ExclusiveSelfAssignedRoles") + .HasColumnType("INTEGER"); + + b.Property("FilterInvites") + .HasColumnType("INTEGER"); + + b.Property("FilterLinks") + .HasColumnType("INTEGER"); + + b.Property("FilterWords") + .HasColumnType("INTEGER"); + + b.Property("GameVoiceChannel") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Locale") + .HasColumnType("TEXT"); + + b.Property("MuteRoleName") + .HasColumnType("TEXT"); + + b.Property("NotifyStreamOffline") + .HasColumnType("INTEGER"); + + b.Property("PermissionRole") + .HasColumnType("TEXT"); + + b.Property("Prefix") + .HasColumnType("TEXT"); + + b.Property("StickyRoles") + .HasColumnType("INTEGER"); + + b.Property("TimeZoneId") + .HasColumnType("TEXT"); + + b.Property("VerboseErrors") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(true); + + b.Property("VerbosePermissions") + .HasColumnType("INTEGER"); + + b.Property("WarnExpireAction") + .HasColumnType("INTEGER"); + + b.Property("WarnExpireHours") + .HasColumnType("INTEGER"); + + b.Property("WarningsInitialized") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.HasIndex("WarnExpireHours"); + + b.ToTable("GuildConfigs"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.HoneypotChannel", b => + { + b.Property("GuildId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.HasKey("GuildId"); + + b.ToTable("HoneyPotChannels"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.IgnoredLogItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemType") + .HasColumnType("INTEGER"); + + b.Property("LogItemId") + .HasColumnType("INTEGER"); + + b.Property("LogSettingId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("LogSettingId", "LogItemId", "ItemType") + .IsUnique(); + + b.ToTable("IgnoredLogChannels"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ImageOnlyChannel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId") + .IsUnique(); + + b.ToTable("ImageOnlyChannels"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.LogSetting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelCreatedId") + .HasColumnType("INTEGER"); + + b.Property("ChannelDestroyedId") + .HasColumnType("INTEGER"); + + b.Property("ChannelUpdatedId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("LogOtherId") + .HasColumnType("INTEGER"); + + b.Property("LogUserPresenceId") + .HasColumnType("INTEGER"); + + b.Property("LogVoicePresenceId") + .HasColumnType("INTEGER"); + + b.Property("LogVoicePresenceTTSId") + .HasColumnType("INTEGER"); + + b.Property("LogWarnsId") + .HasColumnType("INTEGER"); + + b.Property("MessageDeletedId") + .HasColumnType("INTEGER"); + + b.Property("MessageUpdatedId") + .HasColumnType("INTEGER"); + + b.Property("ThreadCreatedId") + .HasColumnType("INTEGER"); + + b.Property("ThreadDeletedId") + .HasColumnType("INTEGER"); + + b.Property("UserBannedId") + .HasColumnType("INTEGER"); + + b.Property("UserJoinedId") + .HasColumnType("INTEGER"); + + b.Property("UserLeftId") + .HasColumnType("INTEGER"); + + b.Property("UserMutedId") + .HasColumnType("INTEGER"); + + b.Property("UserUnbannedId") + .HasColumnType("INTEGER"); + + b.Property("UserUpdatedId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("LogSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.MusicPlayerSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoDisconnect") + .HasColumnType("INTEGER"); + + b.Property("AutoPlay") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("MusicChannelId") + .HasColumnType("INTEGER"); + + b.Property("PlayerRepeat") + .HasColumnType("INTEGER"); + + b.Property("QualityPreset") + .HasColumnType("INTEGER"); + + b.Property("Volume") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(100); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("MusicPlayerSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.MusicPlaylist", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Author") + .HasColumnType("TEXT"); + + b.Property("AuthorId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("MusicPlaylists"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.MutedUserId", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("MutedUserId"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.NCPixel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Color") + .HasColumnType("INTEGER"); + + b.Property("OwnerId") + .HasColumnType("INTEGER"); + + b.Property("Position") + .HasColumnType("INTEGER"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("Text") + .IsRequired() + .HasMaxLength(256) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasAlternateKey("Position"); + + b.HasIndex("OwnerId"); + + b.ToTable("NCPixel"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.PatronUser", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AmountCents") + .HasColumnType("INTEGER"); + + b.Property("LastCharge") + .HasColumnType("TEXT"); + + b.Property("UniquePlatformUserId") + .HasColumnType("TEXT"); + + b.Property("ValidThru") + .HasColumnType("TEXT"); + + b.HasKey("UserId"); + + b.HasIndex("UniquePlatformUserId") + .IsUnique(); + + b.ToTable("Patrons"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Permissionv2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("IsCustomCommand") + .HasColumnType("INTEGER"); + + b.Property("PrimaryTarget") + .HasColumnType("INTEGER"); + + b.Property("PrimaryTargetId") + .HasColumnType("INTEGER"); + + b.Property("SecondaryTarget") + .HasColumnType("INTEGER"); + + b.Property("SecondaryTargetName") + .HasColumnType("TEXT"); + + b.Property("State") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("Permissions"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.PlantedCurrency", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Amount") + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("MessageId") + .HasColumnType("INTEGER"); + + b.Property("Password") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId"); + + b.HasIndex("MessageId") + .IsUnique(); + + b.ToTable("PlantedCurrency"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.PlaylistSong", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + 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("EllieBot.Db.Models.Quote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuthorId") + .HasColumnType("INTEGER"); + + b.Property("AuthorName") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Keyword") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("Text") + .IsRequired() + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.HasIndex("Keyword"); + + b.ToTable("Quotes"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ReactionRoleV2", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Emote") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("Group") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("LevelReq") + .HasColumnType("INTEGER"); + + b.Property("MessageId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId"); + + b.HasIndex("MessageId", "Emote") + .IsUnique(); + + b.ToTable("ReactionRoles"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Reminder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IsPrivate") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("ServerId") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("When") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("When"); + + b.ToTable("Reminders"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Repeater", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Interval") + .HasColumnType("TEXT"); + + b.Property("LastMessageId") + .HasColumnType("INTEGER"); + + b.Property("Message") + .HasColumnType("TEXT"); + + b.Property("NoRedundant") + .HasColumnType("INTEGER"); + + b.Property("StartTimeOfDay") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("Repeaters"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.RewardedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AmountRewardedThisMonth") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("LastReward") + .HasColumnType("TEXT"); + + b.Property("PlatformUserId") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("PlatformUserId") + .IsUnique(); + + b.ToTable("RewardedUsers"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.RotatingPlayingStatus", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Status") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("RotatingStatus"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Sar", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("LevelReq") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("SarGroupId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasAlternateKey("GuildId", "RoleId"); + + b.HasIndex("SarGroupId"); + + b.ToTable("Sar"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SarAutoDelete", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("IsEnabled") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("SarAutoDelete"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SarGroup", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GroupNumber") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("IsExclusive") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("RoleReq") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasAlternateKey("GuildId", "GroupNumber"); + + b.ToTable("SarGroup"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AuthorId") + .HasColumnType("INTEGER"); + + b.Property("Command") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("RoleName") + .HasColumnType("TEXT"); + + b.Property("RoleRequirement") + .HasColumnType("INTEGER"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("ShopEntry"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ShopEntryItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ShopEntryId") + .HasColumnType("INTEGER"); + + b.Property("Text") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ShopEntryId"); + + b.ToTable("ShopEntryItem"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SlowmodeIgnoredRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("SlowmodeIgnoredRole"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SlowmodeIgnoredUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("SlowmodeIgnoredUser"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StickyRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("RoleIds") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "UserId") + .IsUnique(); + + b.ToTable("StickyRoles"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamOnlineMessage", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("MessageId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Type") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("StreamOnlineMessages"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleBlacklistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("StreamRoleSettingsId"); + + b.ToTable("StreamRoleBlacklistedUser"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AddRoleId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Enabled") + .HasColumnType("INTEGER"); + + b.Property("FromRoleId") + .HasColumnType("INTEGER"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("Keyword") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("StreamRoleSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleWhitelistedUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("StreamRoleSettingsId") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Username") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("StreamRoleSettingsId"); + + b.ToTable("StreamRoleWhitelistedUser"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.TodoModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArchiveId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IsDone") + .HasColumnType("INTEGER"); + + b.Property("Todo") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ArchiveId"); + + b.HasIndex("UserId"); + + b.ToTable("Todos"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnbanTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UnbanAt") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("UnbanTimer"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnmuteTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("UnmuteAt") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("UnmuteTimer"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnroleTimer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("UnbanAt") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("UnroleTimer"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UserXpStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AwardedXp") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("NotifyOnLevelUp") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + 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("EllieBot.Db.Models.VcRoleInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("VoiceChannelId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId"); + + b.ToTable("VcRoleInfo"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AffinityId") + .HasColumnType("INTEGER"); + + b.Property("ClaimerId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Price") + .HasColumnType("INTEGER"); + + b.Property("WaifuId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("AffinityId"); + + b.HasIndex("ClaimerId"); + + b.HasIndex("Price"); + + b.HasIndex("WaifuId") + .IsUnique(); + + b.ToTable("WaifuInfo"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("ItemEmoji") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("WaifuInfoId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("WaifuInfoId"); + + b.ToTable("WaifuItem"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuUpdate", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("NewId") + .HasColumnType("INTEGER"); + + b.Property("OldId") + .HasColumnType("INTEGER"); + + b.Property("UpdateType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("NewId"); + + b.HasIndex("OldId"); + + b.HasIndex("UserId"); + + b.ToTable("WaifuUpdates"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Warning", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Forgiven") + .HasColumnType("INTEGER"); + + b.Property("ForgivenBy") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Moderator") + .HasColumnType("TEXT"); + + b.Property("Reason") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("Weight") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(1L); + + b.HasKey("Id"); + + b.HasIndex("DateAdded"); + + b.HasIndex("GuildId"); + + b.HasIndex("UserId"); + + b.ToTable("Warnings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WarningPunishment", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Count") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Punishment") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("Time") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasAlternateKey("GuildId", "Count"); + + b.ToTable("WarningPunishment"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpCurrencyReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Amount") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("XpSettingsId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId"); + + b.ToTable("XpCurrencyReward"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpRoleReward", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("Level") + .HasColumnType("INTEGER"); + + b.Property("Remove") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.Property("XpSettingsId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("XpSettingsId", "Level") + .IsUnique(); + + b.ToTable("XpRoleReward"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("GuildConfigId") + .HasColumnType("INTEGER"); + + b.Property("ServerExcluded") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("GuildConfigId") + .IsUnique(); + + b.ToTable("XpSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpShopOwnedItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("IsUsing") + .HasColumnType("INTEGER"); + + b.Property("ItemKey") + .IsRequired() + .HasColumnType("TEXT"); + + b.Property("ItemType") + .HasColumnType("INTEGER"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId", "ItemType", "ItemKey") + .IsUnique(); + + b.ToTable("XpShopOwnedItem"); + }); + + modelBuilder.Entity("EllieBot.Services.GreetSettings", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AutoDeleteTimer") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(0); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("GreetType") + .HasColumnType("INTEGER"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("IsEnabled") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER") + .HasDefaultValue(false); + + b.Property("MessageText") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId", "GreetType") + .IsUnique(); + + b.ToTable("GreetSettings"); + }); + + modelBuilder.Entity("EllieBot.Services.Rakeback", b => + { + b.Property("UserId") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Amount") + .HasColumnType("TEXT"); + + b.HasKey("UserId"); + + b.ToTable("Rakeback"); + }); + + modelBuilder.Entity("EllieBot.Services.UserBetStats", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Game") + .HasColumnType("INTEGER"); + + b.Property("LoseCount") + .HasColumnType("INTEGER"); + + b.Property("MaxBet") + .HasColumnType("INTEGER"); + + b.Property("MaxWin") + .HasColumnType("INTEGER"); + + b.Property("PaidOut") + .HasColumnType("TEXT"); + + b.Property("TotalBet") + .HasColumnType("TEXT"); + + b.Property("UserId") + .HasColumnType("INTEGER"); + + b.Property("WinCount") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("UserId", "Game") + .IsUnique(); + + b.ToTable("UserBetStats"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiAltSetting", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithOne("AntiAltSetting") + .HasForeignKey("EllieBot.Db.Models.AntiAltSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiRaidSetting", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithOne("AntiRaidSetting") + .HasForeignKey("EllieBot.Db.Models.AntiRaidSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiSpamIgnore", b => + { + b.HasOne("EllieBot.Db.Models.AntiSpamSetting", null) + .WithMany("IgnoredChannels") + .HasForeignKey("AntiSpamSettingId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiSpamSetting", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithOne("AntiSpamSetting") + .HasForeignKey("EllieBot.Db.Models.AntiSpamSetting", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoTranslateUser", b => + { + b.HasOne("EllieBot.Db.Models.AutoTranslateChannel", "Channel") + .WithMany("Users") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Channel"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubApplicants", b => + { + b.HasOne("EllieBot.Db.Models.ClubInfo", "Club") + .WithMany("Applicants") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubBans", b => + { + b.HasOne("EllieBot.Db.Models.ClubInfo", "Club") + .WithMany("Bans") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Club"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubInfo", b => + { + b.HasOne("EllieBot.Db.Models.DiscordUser", "Owner") + .WithOne() + .HasForeignKey("EllieBot.Db.Models.ClubInfo", "OwnerId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Owner"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.CommandAlias", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("CommandAliases") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.CommandCooldown", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("CommandCooldowns") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.DelMsgOnCmdChannel", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("DelMsgOnCmdChannels") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("EllieBot.Db.Models.DiscordUser", b => + { + b.HasOne("EllieBot.Db.Models.ClubInfo", "Club") + .WithMany("Members") + .HasForeignKey("ClubId") + .OnDelete(DeleteBehavior.NoAction); + + b.Navigation("Club"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ExcludedItem", b => + { + b.HasOne("EllieBot.Db.Models.XpSettings", "XpSettings") + .WithMany("ExclusionList") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FeedSub", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", "GuildConfig") + .WithMany("FeedSubs") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilterChannelId", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("FilterInvitesChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilterLinksChannelId", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("FilterLinksChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilterWordsChannelId", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("FilterWordsChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FilteredWord", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("FilteredWords") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.FollowedStream", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("FollowedStreams") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GCChannelId", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", "GuildConfig") + .WithMany("GenerateCurrencyChannelIds") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GiveawayUser", b => + { + b.HasOne("EllieBot.Db.Models.GiveawayModel", null) + .WithMany("Participants") + .HasForeignKey("GiveawayId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("EllieBot.Db.Models.IgnoredLogItem", b => + { + b.HasOne("EllieBot.Db.Models.LogSetting", "LogSetting") + .WithMany("LogIgnores") + .HasForeignKey("LogSettingId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LogSetting"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.MutedUserId", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("MutedUsers") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Permissionv2", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("Permissions") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.PlaylistSong", b => + { + b.HasOne("EllieBot.Db.Models.MusicPlaylist", null) + .WithMany("Songs") + .HasForeignKey("MusicPlaylistId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.Sar", b => + { + b.HasOne("EllieBot.Db.Models.SarGroup", null) + .WithMany("Roles") + .HasForeignKey("SarGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("ShopEntries") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ShopEntryItem", b => + { + b.HasOne("EllieBot.Db.Models.ShopEntry", null) + .WithMany("Items") + .HasForeignKey("ShopEntryId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SlowmodeIgnoredRole", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredRoles") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SlowmodeIgnoredUser", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("SlowmodeIgnoredUsers") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleBlacklistedUser", b => + { + b.HasOne("EllieBot.Db.Models.StreamRoleSettings", "StreamRoleSettings") + .WithMany("Blacklist") + .HasForeignKey("StreamRoleSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("StreamRoleSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleSettings", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", "GuildConfig") + .WithOne("StreamRole") + .HasForeignKey("EllieBot.Db.Models.StreamRoleSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleWhitelistedUser", b => + { + b.HasOne("EllieBot.Db.Models.StreamRoleSettings", "StreamRoleSettings") + .WithMany("Whitelist") + .HasForeignKey("StreamRoleSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("StreamRoleSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.TodoModel", b => + { + b.HasOne("EllieBot.Db.Models.ArchivedTodoListModel", null) + .WithMany("Items") + .HasForeignKey("ArchiveId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnbanTimer", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("UnbanTimer") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnmuteTimer", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("UnmuteTimers") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.UnroleTimer", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("UnroleTimer") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.VcRoleInfo", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", null) + .WithMany("VcRoleInfos") + .HasForeignKey("GuildConfigId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuInfo", b => + { + b.HasOne("EllieBot.Db.Models.DiscordUser", "Affinity") + .WithMany() + .HasForeignKey("AffinityId"); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "Claimer") + .WithMany() + .HasForeignKey("ClaimerId"); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "Waifu") + .WithOne() + .HasForeignKey("EllieBot.Db.Models.WaifuInfo", "WaifuId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Affinity"); + + b.Navigation("Claimer"); + + b.Navigation("Waifu"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuItem", b => + { + b.HasOne("EllieBot.Db.Models.WaifuInfo", "WaifuInfo") + .WithMany("Items") + .HasForeignKey("WaifuInfoId"); + + b.Navigation("WaifuInfo"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuUpdate", b => + { + b.HasOne("EllieBot.Db.Models.DiscordUser", "New") + .WithMany() + .HasForeignKey("NewId"); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "Old") + .WithMany() + .HasForeignKey("OldId"); + + b.HasOne("EllieBot.Db.Models.DiscordUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("New"); + + b.Navigation("Old"); + + b.Navigation("User"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpCurrencyReward", b => + { + b.HasOne("EllieBot.Db.Models.XpSettings", "XpSettings") + .WithMany("CurrencyRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpRoleReward", b => + { + b.HasOne("EllieBot.Db.Models.XpSettings", "XpSettings") + .WithMany("RoleRewards") + .HasForeignKey("XpSettingsId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpSettings", b => + { + b.HasOne("EllieBot.Db.Models.GuildConfig", "GuildConfig") + .WithOne("XpSettings") + .HasForeignKey("EllieBot.Db.Models.XpSettings", "GuildConfigId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("GuildConfig"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AntiSpamSetting", b => + { + b.Navigation("IgnoredChannels"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ArchivedTodoListModel", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.AutoTranslateChannel", b => + { + b.Navigation("Users"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ClubInfo", b => + { + b.Navigation("Applicants"); + + b.Navigation("Bans"); + + b.Navigation("Members"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GiveawayModel", b => + { + b.Navigation("Participants"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.GuildConfig", b => + { + b.Navigation("AntiAltSetting"); + + b.Navigation("AntiRaidSetting"); + + b.Navigation("AntiSpamSetting"); + + 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("GenerateCurrencyChannelIds"); + + b.Navigation("MutedUsers"); + + b.Navigation("Permissions"); + + b.Navigation("ShopEntries"); + + b.Navigation("SlowmodeIgnoredRoles"); + + b.Navigation("SlowmodeIgnoredUsers"); + + b.Navigation("StreamRole"); + + b.Navigation("UnbanTimer"); + + b.Navigation("UnmuteTimers"); + + b.Navigation("UnroleTimer"); + + b.Navigation("VcRoleInfos"); + + b.Navigation("XpSettings"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.LogSetting", b => + { + b.Navigation("LogIgnores"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.MusicPlaylist", b => + { + b.Navigation("Songs"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.SarGroup", b => + { + b.Navigation("Roles"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.ShopEntry", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.StreamRoleSettings", b => + { + b.Navigation("Blacklist"); + + b.Navigation("Whitelist"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.WaifuInfo", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("EllieBot.Db.Models.XpSettings", b => + { + b.Navigation("CurrencyRewards"); + + b.Navigation("ExclusionList"); + + b.Navigation("RoleRewards"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/EllieBot/Migrations/Sqlite/20241127120303_guildcolors.cs b/src/EllieBot/Migrations/Sqlite/20241127120303_guildcolors.cs new file mode 100644 index 0000000..9f7ac5d --- /dev/null +++ b/src/EllieBot/Migrations/Sqlite/20241127120303_guildcolors.cs @@ -0,0 +1,72 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace EllieBot.Migrations +{ + /// + public partial class guildcolors : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "ButtonRole", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + ButtonId = table.Column(type: "TEXT", maxLength: 200, nullable: false), + GuildId = table.Column(type: "INTEGER", nullable: false), + ChannelId = table.Column(type: "INTEGER", nullable: false), + MessageId = table.Column(type: "INTEGER", nullable: false), + Position = table.Column(type: "INTEGER", nullable: false), + RoleId = table.Column(type: "INTEGER", nullable: false), + Emote = table.Column(type: "TEXT", maxLength: 100, nullable: false), + Label = table.Column(type: "TEXT", maxLength: 50, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ButtonRole", x => x.Id); + table.UniqueConstraint("AK_ButtonRole_RoleId_MessageId", x => new { x.RoleId, x.MessageId }); + }); + + migrationBuilder.CreateTable( + name: "GuildColors", + columns: table => new + { + Id = table.Column(type: "INTEGER", nullable: false) + .Annotation("Sqlite:Autoincrement", true), + GuildId = table.Column(type: "INTEGER", nullable: false), + OkColor = table.Column(type: "TEXT", maxLength: 9, nullable: true), + ErrorColor = table.Column(type: "TEXT", maxLength: 9, nullable: true), + PendingColor = table.Column(type: "TEXT", maxLength: 9, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_GuildColors", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_ButtonRole_GuildId", + table: "ButtonRole", + column: "GuildId"); + + migrationBuilder.CreateIndex( + name: "IX_GuildColors_GuildId", + table: "GuildColors", + column: "GuildId", + unique: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ButtonRole"); + + migrationBuilder.DropTable( + name: "GuildColors"); + } + } +} diff --git a/src/EllieBot/Migrations/Sqlite/EllieSqliteContextModelSnapshot.cs b/src/EllieBot/Migrations/Sqlite/EllieSqliteContextModelSnapshot.cs index 8a10c5a..981f2b7 100644 --- a/src/EllieBot/Migrations/Sqlite/EllieSqliteContextModelSnapshot.cs +++ b/src/EllieBot/Migrations/Sqlite/EllieSqliteContextModelSnapshot.cs @@ -335,6 +335,51 @@ namespace EllieBot.Migrations b.ToTable("Blacklist"); }); + modelBuilder.Entity("EllieBot.Db.Models.ButtonRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ButtonId") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("TEXT"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("Emote") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("Label") + .IsRequired() + .HasMaxLength(50) + .HasColumnType("TEXT"); + + b.Property("MessageId") + .HasColumnType("INTEGER"); + + b.Property("Position") + .HasColumnType("INTEGER"); + + b.Property("RoleId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasAlternateKey("RoleId", "MessageId"); + + b.HasIndex("GuildId"); + + b.ToTable("ButtonRole"); + }); + modelBuilder.Entity("EllieBot.Db.Models.ClubApplicants", b => { b.Property("ClubId") @@ -932,6 +977,35 @@ namespace EllieBot.Migrations b.ToTable("GiveawayUser"); }); + modelBuilder.Entity("EllieBot.Db.Models.GuildColors", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ErrorColor") + .HasMaxLength(9) + .HasColumnType("TEXT"); + + b.Property("GuildId") + .HasColumnType("INTEGER"); + + b.Property("OkColor") + .HasMaxLength(9) + .HasColumnType("TEXT"); + + b.Property("PendingColor") + .HasMaxLength(9) + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("GuildId") + .IsUnique(); + + b.ToTable("GuildColors"); + }); + modelBuilder.Entity("EllieBot.Db.Models.GuildConfig", b => { b.Property("Id") diff --git a/src/EllieBot/Modules/Administration/Administration.cs b/src/EllieBot/Modules/Administration/Administration.cs index 9e18e8b..6c01605 100644 --- a/src/EllieBot/Modules/Administration/Administration.cs +++ b/src/EllieBot/Modules/Administration/Administration.cs @@ -96,7 +96,7 @@ public partial class Administration : EllieModule var guild = (SocketGuild)ctx.Guild; var (enabled, channels) = _service.GetDelMsgOnCmdData(ctx.Guild.Id); - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.server_delmsgoncmd)) .WithDescription(enabled ? "✅" : "❌"); diff --git a/src/EllieBot/Modules/Administration/AdministrationService.cs b/src/EllieBot/Modules/Administration/AdministrationService.cs index b1bec59..c354181 100644 --- a/src/EllieBot/Modules/Administration/AdministrationService.cs +++ b/src/EllieBot/Modules/Administration/AdministrationService.cs @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore; using EllieBot.Db.Models; using EllieBot.Modules.Administration._common.results; -namespace EllieBot.Modules.Administration.Services; +namespace EllieBot.Modules.Administration; public class AdministrationService : IEService { diff --git a/src/EllieBot/Modules/Administration/DangerousCommands/CleanupService.cs b/src/EllieBot/Modules/Administration/DangerousCommands/CleanupService.cs index 56cb15f..4d14924 100644 --- a/src/EllieBot/Modules/Administration/DangerousCommands/CleanupService.cs +++ b/src/EllieBot/Modules/Administration/DangerousCommands/CleanupService.cs @@ -254,6 +254,12 @@ public sealed class CleanupService : ICleanupService, IReadyExecutor, IEService .Contains(x.ServerId)) .DeleteAsync(); + // delete button roles + await ctx.GetTable() + .Where(x => !tempTable.Select(x => x.GuildId) + .Contains(x.GuildId)) + .DeleteAsync(); + return new() { GuildCount = guildIds.Keys.Count, diff --git a/src/EllieBot/Modules/Administration/DangerousCommands/DangerousCommands.cs b/src/EllieBot/Modules/Administration/DangerousCommands/DangerousCommands.cs index 2e6444f..f0e5c84 100644 --- a/src/EllieBot/Modules/Administration/DangerousCommands/DangerousCommands.cs +++ b/src/EllieBot/Modules/Administration/DangerousCommands/DangerousCommands.cs @@ -42,9 +42,9 @@ public partial class Administration .Page((items, _) => { if (!items.Any()) - return _sender.CreateEmbed().WithErrorColor().WithFooter(sql).WithDescription("-"); + return CreateEmbed().WithErrorColor().WithFooter(sql).WithDescription("-"); - return _sender.CreateEmbed() + return CreateEmbed() .WithOkColor() .WithFooter(sql) .WithTitle(string.Join(" ║ ", result.ColumnNames)) @@ -99,7 +99,7 @@ public partial class Administration { try { - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithTitle(GetText(strs.sql_confirm_exec)) .WithDescription(Format.Code(sql)); @@ -119,7 +119,7 @@ public partial class Administration [OwnerOnly] public async Task PurgeUser(ulong userId) { - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithDescription(GetText(strs.purge_user_confirm(Format.Bold(userId.ToString())))); if (!await PromptUserConfirmAsync(embed)) diff --git a/src/EllieBot/Modules/Administration/LocalizationCommands.cs b/src/EllieBot/Modules/Administration/LocalizationCommands.cs index 9715d0b..76ba107 100644 --- a/src/EllieBot/Modules/Administration/LocalizationCommands.cs +++ b/src/EllieBot/Modules/Administration/LocalizationCommands.cs @@ -123,7 +123,7 @@ public partial class Administration [Cmd] public async Task LanguagesList() - => await Response().Embed(_sender.CreateEmbed() + => await Response().Embed(CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.lang_list)) .WithDescription(string.Join("\n", diff --git a/src/EllieBot/Modules/Administration/Mute/MuteService.cs b/src/EllieBot/Modules/Administration/Mute/MuteService.cs index a67610d..cb74059 100644 --- a/src/EllieBot/Modules/Administration/Mute/MuteService.cs +++ b/src/EllieBot/Modules/Administration/Mute/MuteService.cs @@ -122,7 +122,7 @@ public class MuteService : IEService return; _ = Task.Run(() => _sender.Response(user) - .Embed(_sender.CreateEmbed() + .Embed(_sender.CreateEmbed(user?.GuildId) .WithDescription($"You've been muted in {user.Guild} server") .AddField("Mute Type", type.ToString()) .AddField("Moderator", mod.ToString()) @@ -140,7 +140,7 @@ public class MuteService : IEService return; _ = Task.Run(() => _sender.Response(user) - .Embed(_sender.CreateEmbed() + .Embed(_sender.CreateEmbed(user.GuildId) .WithDescription($"You've been unmuted in {user.Guild} server") .AddField("Unmute Type", type.ToString()) .AddField("Moderator", mod.ToString()) diff --git a/src/EllieBot/Modules/Administration/PermOverrides/DiscordPermOverrideCommands.cs b/src/EllieBot/Modules/Administration/PermOverrides/DiscordPermOverrideCommands.cs index cc43b31..df992f3 100644 --- a/src/EllieBot/Modules/Administration/PermOverrides/DiscordPermOverrideCommands.cs +++ b/src/EllieBot/Modules/Administration/PermOverrides/DiscordPermOverrideCommands.cs @@ -36,7 +36,7 @@ public partial class Administration [UserPerm(GuildPerm.Administrator)] public async Task DiscordPermOverrideReset() { - var result = await PromptUserConfirmAsync(_sender.CreateEmbed() + var result = await PromptUserConfirmAsync(CreateEmbed() .WithOkColor() .WithDescription(GetText(strs.perm_override_all_confirm))); @@ -65,7 +65,7 @@ public partial class Administration .CurrentPage(page) .Page((items, _) => { - var eb = _sender.CreateEmbed().WithTitle(GetText(strs.perm_overrides)).WithOkColor(); + var eb = CreateEmbed().WithTitle(GetText(strs.perm_overrides)).WithOkColor(); if (items.Count == 0) eb.WithDescription(GetText(strs.perm_override_page_none)); diff --git a/src/EllieBot/Modules/Administration/Protection/ProtectionCommands.cs b/src/EllieBot/Modules/Administration/Protection/ProtectionCommands.cs index 64648b8..f1721c1 100644 --- a/src/EllieBot/Modules/Administration/Protection/ProtectionCommands.cs +++ b/src/EllieBot/Modules/Administration/Protection/ProtectionCommands.cs @@ -241,7 +241,7 @@ public partial class Administration return; } - var embed = _sender.CreateEmbed().WithOkColor().WithTitle(GetText(strs.prot_active)); + var embed = CreateEmbed().WithOkColor().WithTitle(GetText(strs.prot_active)); if (spam is not null) embed.AddField("Anti-Spam", GetAntiSpamString(spam).TrimTo(1024), true); diff --git a/src/EllieBot/Modules/Administration/Prune/PruneCommands.cs b/src/EllieBot/Modules/Administration/Prune/PruneCommands.cs index 5ebafab..6167995 100644 --- a/src/EllieBot/Modules/Administration/Prune/PruneCommands.cs +++ b/src/EllieBot/Modules/Administration/Prune/PruneCommands.cs @@ -113,7 +113,7 @@ public partial class Administration { await progressMsg.ModifyAsync(props => { - props.Embed = _sender.CreateEmbed() + props.Embed = CreateEmbed() .WithPendingColor() .WithDescription(GetText(strs.prune_progress(deleted, total))) .Build(); diff --git a/src/EllieBot/Modules/Administration/Role/ButtonRolesCommands.cs b/src/EllieBot/Modules/Administration/Role/ButtonRolesCommands.cs new file mode 100644 index 0000000..626f556 --- /dev/null +++ b/src/EllieBot/Modules/Administration/Role/ButtonRolesCommands.cs @@ -0,0 +1,269 @@ +using EllieBot.Db.Models; +using EllieBot.Modules.Administration.Services; +using System.Text; +using ContextType = Discord.Commands.ContextType; + +namespace EllieBot.Modules.Administration; + +public partial class Administration +{ + public partial class ButtonRoleCommands : EllieModule + { + private List GetActionRows(IReadOnlyList roles) + { + var rows = roles.Select((x, i) => (Index: i, ButtonRole: x)) + .GroupBy(x => x.Index / 5) + .Select(x => x.Select(y => y.ButtonRole)) + .Select(x => + { + var ab = new ActionRowBuilder() + .WithComponents(x.Select(y => + { + var curRole = ctx.Guild.GetRole(y.RoleId); + var label = string.IsNullOrWhiteSpace(y.Label) + ? curRole?.ToString() ?? "?missing " + y.RoleId + : y.Label; + + var btnEmote = EmoteTypeReader.TryParse(y.Emote, out var e) + ? e + : null; + + return new ButtonBuilder() + .WithCustomId(y.ButtonId) + .WithEmote(btnEmote) + .WithLabel(label) + .WithStyle(ButtonStyle.Secondary) + .Build() as IMessageComponent; + }) + .ToList()); + + return ab; + }) + .ToList(); + return rows; + } + + private async Task CreateMessageLinkAsync(ulong messageId) + { + var msg = await ctx.Channel.GetMessageAsync(messageId); + if (msg is null) + return null; + + return new MessageLink(ctx.Guild, ctx.Channel, msg); + } + + [Cmd] + [RequireContext(ContextType.Guild)] + [BotPerm(GuildPerm.ManageRoles)] + [RequireUserPermission(GuildPerm.ManageRoles)] + public async Task BtnRoleAdd(ulong messageId, IEmote emote, [Leftover] IRole role) + { + var link = await CreateMessageLinkAsync(messageId); + + if (link is null) + { + await Response().Error(strs.invalid_message_id).SendAsync(); + return; + } + + await BtnRoleAdd(link, emote, role); + } + + + [Cmd] + [RequireContext(ContextType.Guild)] + [BotPerm(GuildPerm.ManageRoles)] + [RequireUserPermission(GuildPerm.ManageRoles)] + public async Task BtnRoleAdd(MessageLink link, IEmote emote, [Leftover] IRole role) + { + if (link.Message is not IUserMessage msg || !msg.IsAuthor(ctx.Client)) + { + await Response().Error(strs.invalid_message_link).SendAsync(); + return; + } + + if (!await CheckRoleHierarchy(role)) + { + await Response().Error(strs.hierarchy).SendAsync(); + return; + } + + var success = await _service.AddButtonRole(ctx.Guild.Id, link.Channel.Id, role.Id, link.Message.Id, emote); + if (!success) + { + await Response().Error(strs.btnrole_message_max).SendAsync(); + return; + } + + var roles = await _service.GetButtonRoles(ctx.Guild.Id, link.Message.Id); + + var rows = GetActionRows(roles); + + await msg.ModifyAsync(x => x.Components = new(new ComponentBuilder().WithRows(rows).Build())); + await ctx.OkAsync(); + } + + [Cmd] + [RequireContext(ContextType.Guild)] + [BotPerm(GuildPerm.ManageRoles)] + [RequireUserPermission(GuildPerm.ManageRoles)] + public Task BtnRoleRemove(ulong messageId, IRole role) + => BtnRoleRemove(messageId, role.Id); + + [Cmd] + [RequireContext(ContextType.Guild)] + [BotPerm(GuildPerm.ManageRoles)] + [RequireUserPermission(GuildPerm.ManageRoles)] + public Task BtnRoleRemove(MessageLink link, IRole role) + => BtnRoleRemove(link.Message.Id, role.Id); + + [Cmd] + [RequireContext(ContextType.Guild)] + [BotPerm(GuildPerm.ManageRoles)] + [RequireUserPermission(GuildPerm.ManageRoles)] + public Task BtnRoleRemove(MessageLink link, ulong roleId) + => BtnRoleRemove(link.Message.Id, roleId); + + [Cmd] + [RequireContext(ContextType.Guild)] + [BotPerm(GuildPerm.ManageRoles)] + [RequireUserPermission(GuildPerm.ManageRoles)] + public async Task BtnRoleRemove(ulong messageId, ulong roleId) + { + var removed = await _service.RemoveButtonRole(ctx.Guild.Id, messageId, roleId); + if (removed is null) + { + await Response().Error(strs.btnrole_not_found).SendAsync(); + return; + } + + var roles = await _service.GetButtonRoles(ctx.Guild.Id, messageId); + + var ch = await ctx.Guild.GetTextChannelAsync(removed.ChannelId); + + if (ch is null) + { + await Response().Error(strs.btnrole_removeall_not_found).SendAsync(); + return; + } + + var msg = await ch.GetMessageAsync(removed.MessageId) as IUserMessage; + + if (msg is null) + { + await Response().Error(strs.btnrole_removeall_not_found).SendAsync(); + return; + } + + var rows = GetActionRows(roles); + await msg.ModifyAsync(x => x.Components = new(new ComponentBuilder().WithRows(rows).Build())); + await Response().Confirm(strs.btnrole_removed).SendAsync(); + } + + [Cmd] + [RequireContext(ContextType.Guild)] + [BotPerm(GuildPerm.ManageRoles)] + [RequireUserPermission(GuildPerm.ManageRoles)] + public Task BtnRoleRemoveAll(MessageLink link) + => BtnRoleRemoveAll(link.Message.Id); + + [Cmd] + [RequireContext(ContextType.Guild)] + [BotPerm(GuildPerm.ManageRoles)] + [RequireUserPermission(GuildPerm.ManageRoles)] + public async Task BtnRoleRemoveAll(ulong messageId) + { + var succ = await _service.RemoveButtonRoles(ctx.Guild.Id, messageId); + + if (succ.Count == 0) + { + await Response().Error(strs.btnrole_not_found).SendAsync(); + return; + } + + var info = succ[0]; + + var ch = await ctx.Guild.GetTextChannelAsync(info.ChannelId); + if (ch is null) + { + await Response().Pending(strs.btnrole_removeall_not_found).SendAsync(); + return; + } + + var msg = await ch.GetMessageAsync(info.MessageId) as IUserMessage; + if (msg is null) + { + await Response().Pending(strs.btnrole_removeall_not_found).SendAsync(); + return; + } + + await msg.ModifyAsync(x => x.Components = new(new ComponentBuilder().Build())); + await ctx.OkAsync(); + } + + [Cmd] + [RequireContext(ContextType.Guild)] + [BotPerm(GuildPerm.ManageRoles)] + [RequireUserPermission(GuildPerm.ManageRoles)] + public async Task BtnRoleList() + { + var btnRoles = await _service.GetButtonRoles(ctx.Guild.Id, null); + + var groups = btnRoles + .GroupBy(x => (x.ChannelId, x.MessageId)) + .ToList(); + + await Response() + .Paginated() + .Items(groups) + .PageSize(1) + .AddFooter(false) + .Page(async (items, page) => + { + var eb = CreateEmbed() + .WithOkColor(); + + var item = items.FirstOrDefault(); + if (item == default) + { + eb.WithPendingColor() + .WithDescription(GetText(strs.btnrole_none)); + + return eb; + } + + var (cid, msgId) = item.Key; + + var str = new StringBuilder(); + + var ch = await ctx.Client.GetChannelAsync(cid) as IMessageChannel; + + str.AppendLine($"Channel: {ch?.ToString() ?? cid.ToString()}"); + str.AppendLine($"Message: {msgId}"); + + if (ch is not null) + { + var msg = await ch.GetMessageAsync(msgId); + if (msg is not null) + { + str.AppendLine(new MessageLink(ctx.Guild, ch, msg).ToString()); + } + } + + str.AppendLine("---"); + + foreach (var x in item.AsEnumerable()) + { + var role = ctx.Guild.GetRole(x.RoleId); + + str.AppendLine($"{x.Emote} {(role?.ToString() ?? x.RoleId.ToString())}"); + } + + eb.WithDescription(str.ToString()); + + return eb; + }) + .SendAsync(); + } + } +} \ No newline at end of file diff --git a/src/EllieBot/Modules/Administration/Role/ButtonRolesService.cs b/src/EllieBot/Modules/Administration/Role/ButtonRolesService.cs new file mode 100644 index 0000000..6369d72 --- /dev/null +++ b/src/EllieBot/Modules/Administration/Role/ButtonRolesService.cs @@ -0,0 +1,154 @@ +using LinqToDB; +using LinqToDB.EntityFrameworkCore; +using LinqToDB.SqlQuery; +using EllieBot.Common.ModuleBehaviors; +using EllieBot.Db.Models; +using NCalc; + +namespace EllieBot.Modules.Administration.Services; + +public sealed class ButtonRolesService : IEService, IReadyExecutor +{ + private const string BTN_PREFIX = "n:btnrole:"; + + private readonly DbService _db; + private readonly DiscordSocketClient _client; + private readonly IBotCreds _creds; + + public ButtonRolesService(IBotCreds creds, DiscordSocketClient client, DbService db) + { + _creds = creds; + _client = client; + _db = db; + } + + + public Task OnReadyAsync() + { + _client.InteractionCreated += OnInteraction; + + return Task.CompletedTask; + } + + private async Task OnInteraction(SocketInteraction inter) + { + if (inter is not SocketMessageComponent smc) + return; + + if (!smc.Data.CustomId.StartsWith(BTN_PREFIX)) + return; + + await inter.DeferAsync(); + + _ = Task.Run(async () => + { + await using var uow = _db.GetDbContext(); + var buttonRole = await uow.GetTable() + .Where(x => x.ButtonId == smc.Data.CustomId && x.MessageId == smc.Message.Id) + .FirstOrDefaultAsyncLinqToDB(); + + if (buttonRole is null) + return; + + var guild = _client.GetGuild(buttonRole.GuildId); + if (guild is null) + return; + + var role = guild.GetRole(buttonRole.RoleId); + if (role is null) + return; + + if (smc.User is not IGuildUser user) + return; + + if (user.GetRoles().Any(x => x.Id == role.Id)) + { + await user.RemoveRoleAsync(role.Id); + return; + } + + await user.AddRoleAsync(role.Id); + }); + } + + public async Task AddButtonRole( + ulong guildId, + ulong channelId, + ulong roleId, + ulong messageId, + IEmote emote + ) + { + await using var uow = _db.GetDbContext(); + + // up to 25 per message + if (await uow.GetTable() + .Where(x => x.MessageId == messageId) + .CountAsyncLinqToDB() + >= 25) + return false; + + + var emoteStr = emote.ToString()!; + var guid = Guid.NewGuid(); + await uow.GetTable() + .InsertOrUpdateAsync(() => new ButtonRole() + { + GuildId = guildId, + ChannelId = channelId, + RoleId = roleId, + MessageId = messageId, + Position = + uow + .GetTable() + .Any(x => x.MessageId == messageId) + ? uow.GetTable() + .Where(x => x.MessageId == messageId) + .Max(x => x.Position) + : 1, + Emote = emoteStr, + Label = string.Empty, + ButtonId = $"{BTN_PREFIX}:{guildId}:{guid}" + }, + _ => new() + { + Emote = emoteStr, + Label = string.Empty, + ButtonId = $"{BTN_PREFIX}:{guildId}:{guid}" + }, + () => new() + { + RoleId = roleId, + MessageId = messageId, + }); + + return true; + } + + public async Task> RemoveButtonRoles(ulong guildId, ulong messageId) + { + await using var uow = _db.GetDbContext(); + return await uow.GetTable() + .Where(x => x.GuildId == guildId && x.MessageId == messageId) + .DeleteWithOutputAsync(); + } + + public async Task RemoveButtonRole(ulong guildId, ulong messageId, ulong roleId) + { + await using var uow = _db.GetDbContext(); + var deleted = await uow.GetTable() + .Where(x => x.GuildId == guildId && x.MessageId == messageId && x.RoleId == roleId) + .DeleteWithOutputAsync(); + + return deleted.FirstOrDefault(); + } + + public async Task> GetButtonRoles(ulong guildId, ulong? messageId) + { + await using var uow = _db.GetDbContext(); + return await uow.GetTable() + .Where(x => x.GuildId == guildId && (messageId == null || x.MessageId == messageId)) + .OrderBy(x => x.Id) + .ToListAsyncLinqToDB(); + } +} diff --git a/src/EllieBot/Modules/Administration/Role/ReactionRoleCommands.cs b/src/EllieBot/Modules/Administration/Role/ReactionRoleCommands.cs index cfcad28..0d947ac 100644 --- a/src/EllieBot/Modules/Administration/Role/ReactionRoleCommands.cs +++ b/src/EllieBot/Modules/Administration/Role/ReactionRoleCommands.cs @@ -80,7 +80,7 @@ public partial class Administration .CurrentPage(page) .Page((items, _) => { - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor(); var content = string.Empty; diff --git a/src/EllieBot/Modules/Administration/Role/ReactionRolesService.cs b/src/EllieBot/Modules/Administration/Role/ReactionRolesService.cs index f8550ed..87d4568 100644 --- a/src/EllieBot/Modules/Administration/Role/ReactionRolesService.cs +++ b/src/EllieBot/Modules/Administration/Role/ReactionRolesService.cs @@ -1,8 +1,6 @@ -#nullable disable -using LinqToDB; +using LinqToDB; using LinqToDB.EntityFrameworkCore; using EllieBot.Common.ModuleBehaviors; -using EllieBot.Modules.Patronage; using EllieBot.Db.Models; using OneOf.Types; using OneOf; @@ -18,18 +16,15 @@ public sealed class ReactionRolesService : IReadyExecutor, IEService, IReactionR private ConcurrentDictionary> _cache; private readonly object _cacheLock = new(); private readonly SemaphoreSlim _assignementLock = new(1, 1); - private readonly IPatronageService _ps; public ReactionRolesService( DiscordSocketClient client, - IPatronageService ps, DbService db, IBotCreds creds) { _db = db; _client = client; _creds = creds; - _ps = ps; _cache = new(); } @@ -57,7 +52,7 @@ public sealed class ReactionRolesService : IReadyExecutor, IEService, IReactionR var guild = _client.GetGuild(rero.GuildId); var role = guild?.GetRole(rero.RoleId); - if (role is null) + if (guild is null || role is null) return default; var user = guild.GetUser(userId) as IGuildUser @@ -80,8 +75,8 @@ public sealed class ReactionRolesService : IReadyExecutor, IEService, IReactionR _ = Task.Run(async () => { var emote = await GetFixedEmoteAsync(cmsg, r.Emote); - - var rero = reros.FirstOrDefault(x => x.Emote == emote.Name + + var rero = reros.FirstOrDefault(x => x.Emote == emote.Name || x.Emote == emote.ToString()); if (rero is null) return; @@ -96,10 +91,11 @@ public sealed class ReactionRolesService : IReadyExecutor, IEService, IReactionR { if (user.RoleIds.Contains(role.Id)) { - await user.RemoveRoleAsync(role.Id, new RequestOptions() - { - AuditLogReason = $"Reaction role" - }); + await user.RemoveRoleAsync(role.Id, + new RequestOptions() + { + AuditLogReason = $"Reaction role" + }); } } finally @@ -111,7 +107,7 @@ public sealed class ReactionRolesService : IReadyExecutor, IEService, IReactionR return Task.CompletedTask; } - + // had to add this because for some reason, reactionremoved event's reaction doesn't have IsAnimated set, // causing the .ToString() to be wrong on animated custom emotes private async Task GetFixedEmoteAsync( @@ -210,10 +206,11 @@ public sealed class ReactionRolesService : IReadyExecutor, IEService, IReactionR } } - await user.AddRoleAsync(role.Id, new() - { - AuditLogReason = "Reaction role" - }); + await user.AddRoleAsync(role.Id, + new() + { + AuditLogReason = "Reaction role" + }); } } finally @@ -244,36 +241,23 @@ public sealed class ReactionRolesService : IReadyExecutor, IEService, IReactionR int levelReq = 0) { ArgumentOutOfRangeException.ThrowIfNegative(group); - ArgumentOutOfRangeException.ThrowIfNegative(levelReq); await using var ctx = _db.GetDbContext(); - await using var tran = await ctx.Database.BeginTransactionAsync(); - var activeReactionRoles = await ctx.GetTable() - .Where(x => x.GuildId == guild.Id) - .CountAsync(); - - var limit = await _ps.GetUserLimit(LimitedFeatureName.ReactionRole, guild.OwnerId); - - if (!_creds.IsOwner(guild.OwnerId) && (activeReactionRoles >= limit.Quota && limit.Quota >= 0)) - { - return new Error(); - } - await ctx.GetTable() .InsertOrUpdateAsync(() => new() - { - GuildId = guild.Id, - ChannelId = msg.Channel.Id, + { + GuildId = guild.Id, + ChannelId = msg.Channel.Id, - MessageId = msg.Id, - Emote = emote, + MessageId = msg.Id, + Emote = emote, - RoleId = role.Id, - Group = group, - LevelReq = levelReq - }, + RoleId = role.Id, + Group = group, + LevelReq = levelReq + }, (old) => new() { RoleId = role.Id, @@ -286,8 +270,6 @@ public sealed class ReactionRolesService : IReadyExecutor, IEService, IReactionR Emote = emote, }); - await tran.CommitAsync(); - var obj = new ReactionRoleV2() { GuildId = guild.Id, @@ -380,9 +362,9 @@ public sealed class ReactionRolesService : IReadyExecutor, IEService, IReactionR var updated = ctx.GetTable() .Where(x => x.GuildId == guildId && x.MessageId == fromMessageId) .UpdateWithOutput(old => new() - { - MessageId = toMessageId - }, + { + MessageId = toMessageId + }, (old, neu) => neu); lock (_cacheLock) { diff --git a/src/EllieBot/Modules/Administration/Role/RoleCommands.cs b/src/EllieBot/Modules/Administration/Role/RoleCommands.cs index 7f5daea..66c4251 100644 --- a/src/EllieBot/Modules/Administration/Role/RoleCommands.cs +++ b/src/EllieBot/Modules/Administration/Role/RoleCommands.cs @@ -174,12 +174,11 @@ public partial class Administration [UserPerm(GuildPerm.ManageRoles)] [BotPerm(GuildPerm.ManageRoles)] [Priority(0)] - public async Task RoleColor(Color color, [Leftover] IRole role) + public async Task RoleColor(Rgba32 color, [Leftover] IRole role) { try { - var rgba32 = color.ToPixel(); - await role.ModifyAsync(r => r.Color = new Discord.Color(rgba32.R, rgba32.G, rgba32.B)); + await role.ModifyAsync(r => r.Color = new Discord.Color(color.R, color.G, color.B)); await Response().Confirm(strs.rc(Format.Bold(role.Name))).SendAsync(); } catch (Exception) diff --git a/src/EllieBot/Modules/Administration/Self/SelfCommands.cs b/src/EllieBot/Modules/Administration/Self/SelfCommands.cs index 57f5765..e5196d5 100644 --- a/src/EllieBot/Modules/Administration/Self/SelfCommands.cs +++ b/src/EllieBot/Modules/Administration/Self/SelfCommands.cs @@ -62,7 +62,7 @@ public partial class Administration var (added, updated) = await _service.RefreshUsersAsync(users); await message.ModifyAsync(x => - x.Embed = _sender.CreateEmbed() + x.Embed = CreateEmbed() .WithDescription(GetText(strs.cache_users_done(added, updated))) .WithOkColor() .Build() @@ -115,7 +115,7 @@ public partial class Administration _service.AddNewAutoCommand(cmd); await Response() - .Embed(_sender.CreateEmbed() + .Embed(CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.scadd)) .AddField(GetText(strs.server), @@ -343,7 +343,7 @@ public partial class Administration if (string.IsNullOrWhiteSpace(str)) str = GetText(strs.no_shards_on_page); - return _sender.CreateEmbed().WithOkColor().WithDescription($"{status}\n\n{str}"); + return CreateEmbed().WithOkColor().WithDescription($"{status}\n\n{str}"); }) .SendAsync(); } diff --git a/src/EllieBot/Modules/Administration/SelfAssignableRoles/SelfAssignedRolesCommands.cs b/src/EllieBot/Modules/Administration/SelfAssignableRoles/SelfAssignedRolesCommands.cs index de35ad4..18a7871 100644 --- a/src/EllieBot/Modules/Administration/SelfAssignableRoles/SelfAssignedRolesCommands.cs +++ b/src/EllieBot/Modules/Administration/SelfAssignableRoles/SelfAssignedRolesCommands.cs @@ -129,25 +129,6 @@ public partial class Administration _sas = sas; } - protected async Task CheckRoleHierarchy(IRole role) - { - var botUser = ((SocketGuild)ctx.Guild).CurrentUser; - var ownerId = ctx.Guild.OwnerId; - var modMaxRole = ((IGuildUser)ctx.User).GetRoles().Max(r => r.Position); - var botMaxRole = botUser.GetRoles().Max(r => r.Position); - - // role must be lower than the bot role - // and the mod must have a higher role - if (botMaxRole <= role.Position - || (ctx.User.Id != ownerId && role.Position >= modMaxRole)) - { - await Response().Error(strs.hierarchy).SendAsync(); - return false; - } - - return true; - } - [Cmd] [RequireContext(ContextType.Guild)] [UserPerm(GuildPerm.ManageMessages)] @@ -244,7 +225,7 @@ public partial class Administration .GroupBy(x => x.SarGroupId) .OrderBy(x => x.Key); - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.self_assign_list(groups.Sum(x => x.Roles.Count)))); @@ -310,10 +291,21 @@ public partial class Administration public async Task SarExclusive(int groupNumber) { var areExclusive = await _service.SetGroupExclusivityAsync(ctx.Guild.Id, groupNumber); - if (areExclusive) + + if (areExclusive is null) + { + await Response().Error(strs.sar_group_not_found).SendAsync(); + return; + } + + if (areExclusive is true) + { await Response().Confirm(strs.self_assign_excl).SendAsync(); + } else + { await Response().Confirm(strs.self_assign_no_excl).SendAsync(); + } } [Cmd] diff --git a/src/EllieBot/Modules/Administration/SelfAssignableRoles/SelfAssignedRolesService.cs b/src/EllieBot/Modules/Administration/SelfAssignableRoles/SelfAssignedRolesService.cs index 903f538..7a100d4 100644 --- a/src/EllieBot/Modules/Administration/SelfAssignableRoles/SelfAssignedRolesService.cs +++ b/src/EllieBot/Modules/Administration/SelfAssignableRoles/SelfAssignedRolesService.cs @@ -129,7 +129,7 @@ public class SelfAssignedRolesService : IEService, IReadyExecutor return changes > 0; } - public async Task SetGroupExclusivityAsync(ulong guildId, int groupNumber) + public async Task SetGroupExclusivityAsync(ulong guildId, int groupNumber) { await using var ctx = _db.GetDbContext(); var changes = await ctx.GetTable() @@ -142,8 +142,7 @@ public class SelfAssignedRolesService : IEService, IReadyExecutor if (changes.Length == 0) { - // todo group not found - return false; + return null; } return changes[0]; @@ -154,7 +153,7 @@ public class SelfAssignedRolesService : IEService, IReadyExecutor await using var ctx = _db.GetDbContext(); var group = await ctx.GetTable() - .Where(x => x.Roles.Any(x => x.RoleId == roleId)) + .Where(x => x.GuildId == guildId && x.Roles.Any(x => x.RoleId == roleId)) .LoadWith(x => x.Roles) .FirstOrDefaultAsyncLinqToDB(); diff --git a/src/EllieBot/Modules/Administration/ServerLog/ServerLogCommands.cs b/src/EllieBot/Modules/Administration/ServerLog/ServerLogCommands.cs index 1632da5..5a6a3fa 100644 --- a/src/EllieBot/Modules/Administration/ServerLog/ServerLogCommands.cs +++ b/src/EllieBot/Modules/Administration/ServerLog/ServerLogCommands.cs @@ -35,7 +35,7 @@ public partial class Administration var usrs = settings?.LogIgnores.Where(x => x.ItemType == IgnoredItemType.User).ToList() ?? new List(); - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor() .AddField(GetText(strs.log_ignored_channels), chs.Count == 0 diff --git a/src/EllieBot/Modules/Administration/Timezone/TimeZoneCommands.cs b/src/EllieBot/Modules/Administration/Timezone/TimeZoneCommands.cs index a05789d..67bad83 100644 --- a/src/EllieBot/Modules/Administration/Timezone/TimeZoneCommands.cs +++ b/src/EllieBot/Modules/Administration/Timezone/TimeZoneCommands.cs @@ -42,7 +42,7 @@ public partial class Administration .Items(timezoneStrings) .PageSize(timezonesPerPage) .CurrentPage(page) - .Page((items, _) => _sender.CreateEmbed() + .Page((items, _) => CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.timezones_available)) .WithDescription(string.Join("\n", items))) diff --git a/src/EllieBot/Modules/Administration/UserPunish/UserPunishCommands.cs b/src/EllieBot/Modules/Administration/UserPunish/UserPunishCommands.cs index ea3999b..c9507fa 100644 --- a/src/EllieBot/Modules/Administration/UserPunish/UserPunishCommands.cs +++ b/src/EllieBot/Modules/Administration/UserPunish/UserPunishCommands.cs @@ -44,7 +44,7 @@ public partial class Administration try { await _sender.Response(user) - .Embed(_sender.CreateEmbed() + .Embed(CreateEmbed() .WithErrorColor() .WithDescription(GetText(strs.warned_on(ctx.Guild.ToString()))) .AddField(GetText(strs.moderator), ctx.User.ToString()) @@ -64,7 +64,7 @@ public partial class Administration catch (Exception ex) { Log.Warning(ex, "Exception occured while warning a user"); - var errorEmbed = _sender.CreateEmbed() + var errorEmbed = CreateEmbed() .WithErrorColor() .WithDescription(GetText(strs.cant_apply_punishment)); @@ -75,7 +75,7 @@ public partial class Administration return; } - var embed = _sender.CreateEmbed().WithOkColor(); + var embed = CreateEmbed().WithOkColor(); if (punishment is null) embed.WithDescription(GetText(strs.user_warned(Format.Bold(user.ToString())))); else @@ -184,7 +184,7 @@ public partial class Administration .Page((warnings, page) => { var user = (ctx.Guild as SocketGuild)?.GetUser(userId)?.ToString() ?? userId.ToString(); - var embed = _sender.CreateEmbed().WithOkColor().WithTitle(GetText(strs.warnlog_for(user))); + var embed = CreateEmbed().WithOkColor().WithTitle(GetText(strs.warnlog_for(user))); if (!warnings.Any()) embed.WithDescription(GetText(strs.warnings_none)); @@ -245,7 +245,7 @@ public partial class Administration + $" | {total} ({all} - {forgiven})"; }); - return _sender.CreateEmbed() + return CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.warnings_list)) .WithDescription(string.Join("\n", ws)); @@ -457,7 +457,7 @@ public partial class Administration var user = await ctx.Client.GetUserAsync(userId); var banPrune = await _service.GetBanPruneAsync(ctx.Guild.Id) ?? 7; await _mute.TimedBan(ctx.Guild, userId, time.Time, (ctx.User + " | " + msg).TrimTo(512), banPrune); - var toSend = _sender.CreateEmbed() + var toSend = CreateEmbed() .WithOkColor() .WithTitle("⛔️ " + GetText(strs.banned_user)) .AddField(GetText(strs.username), user?.ToString() ?? userId.ToString(), true) @@ -486,7 +486,7 @@ public partial class Administration await ctx.Guild.AddBanAsync(userId, banPrune, (ctx.User + " | " + msg).TrimTo(512)); await Response() - .Embed(_sender.CreateEmbed() + .Embed(CreateEmbed() .WithOkColor() .WithTitle("⛔️ " + GetText(strs.banned_user)) .AddField("ID", userId.ToString(), true)) @@ -523,7 +523,7 @@ public partial class Administration var banPrune = await _service.GetBanPruneAsync(ctx.Guild.Id) ?? 7; await ctx.Guild.AddBanAsync(user, banPrune, (ctx.User + " | " + msg).TrimTo(512)); - var toSend = _sender.CreateEmbed() + var toSend = CreateEmbed() .WithOkColor() .WithTitle("⛔️ " + GetText(strs.banned_user)) .AddField(GetText(strs.username), user.ToString(), true) @@ -719,7 +719,7 @@ public partial class Administration { await ctx.Guild.RemoveBanAsync(user); } catch { await ctx.Guild.RemoveBanAsync(user); } - var toSend = _sender.CreateEmbed() + var toSend = CreateEmbed() .WithOkColor() .WithTitle("☣ " + GetText(strs.sb_user)) .AddField(GetText(strs.username), user.ToString(), true) @@ -774,7 +774,7 @@ public partial class Administration await user.KickAsync((ctx.User + " | " + msg).TrimTo(512)); - var toSend = _sender.CreateEmbed() + var toSend = CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.kicked_user)) .AddField(GetText(strs.username), user.ToString(), true) @@ -807,7 +807,7 @@ public partial class Administration { var dmMessage = GetText(strs.timeoutdm(Format.Bold(ctx.Guild.Name), msg)); await _sender.Response(user) - .Embed(_sender.CreateEmbed() + .Embed(CreateEmbed() .WithPendingColor() .WithDescription(dmMessage)) .SendAsync(); @@ -819,7 +819,7 @@ public partial class Administration await user.SetTimeOutAsync(time.Time); - var toSend = _sender.CreateEmbed() + var toSend = CreateEmbed() .WithOkColor() .WithTitle("⏳ " + GetText(strs.timedout_user)) .AddField(GetText(strs.username), user.ToString(), true) @@ -880,7 +880,7 @@ public partial class Administration if (string.IsNullOrWhiteSpace(missStr)) missStr = "-"; - var toSend = _sender.CreateEmbed() + var toSend = CreateEmbed() .WithDescription(GetText(strs.mass_ban_in_progress(banning.Count))) .AddField(GetText(strs.invalid(missing.Count)), missStr) .WithPendingColor(); @@ -900,7 +900,7 @@ public partial class Administration } } - await banningMessage.ModifyAsync(x => x.Embed = _sender.CreateEmbed() + await banningMessage.ModifyAsync(x => x.Embed = CreateEmbed() .WithDescription( GetText(strs.mass_ban_completed( banning.Count()))) @@ -928,7 +928,7 @@ public partial class Administration //send a message but don't wait for it var banningMessageTask = Response() - .Embed(_sender.CreateEmbed() + .Embed(CreateEmbed() .WithDescription( GetText(strs.mass_kill_in_progress(bans.Count()))) .AddField(GetText(strs.invalid(missing)), missStr) @@ -949,7 +949,7 @@ public partial class Administration //wait for the message and edit it var banningMessage = await banningMessageTask; - await banningMessage.ModifyAsync(x => x.Embed = _sender.CreateEmbed() + await banningMessage.ModifyAsync(x => x.Embed = CreateEmbed() .WithDescription( GetText(strs.mass_kill_completed(bans.Count()))) .AddField(GetText(strs.invalid(missing)), missStr) diff --git a/src/EllieBot/Modules/Administration/VcRole/VcRoleCommands.cs b/src/EllieBot/Modules/Administration/VcRole/VcRoleCommands.cs index a5f547a..4c705d3 100644 --- a/src/EllieBot/Modules/Administration/VcRole/VcRoleCommands.cs +++ b/src/EllieBot/Modules/Administration/VcRole/VcRoleCommands.cs @@ -68,7 +68,7 @@ public partial class Administration else text = GetText(strs.no_vcroles); - await Response().Embed(_sender.CreateEmbed() + await Response().Embed(CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.vc_role_list)) .WithDescription(text)).SendAsync(); diff --git a/src/EllieBot/Modules/Expressions/EllieExpressions.cs b/src/EllieBot/Modules/Expressions/EllieExpressions.cs index a90b52a..49a3a74 100644 --- a/src/EllieBot/Modules/Expressions/EllieExpressions.cs +++ b/src/EllieBot/Modules/Expressions/EllieExpressions.cs @@ -34,7 +34,7 @@ public partial class EllieExpressions : EllieModule var ex = await _service.AddAsync(ctx.Guild?.Id, key, message); await Response() - .Embed(_sender.CreateEmbed() + .Embed(CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.expr_new)) .WithDescription($"#{new kwum(ex.Id)}") @@ -104,7 +104,7 @@ public partial class EllieExpressions : EllieModule if (ex is not null) { await Response() - .Embed(_sender.CreateEmbed() + .Embed(CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.expr_edited)) .WithDescription($"#{id}") @@ -159,7 +159,7 @@ public partial class EllieExpressions : EllieModule : " // " + string.Join(" ", ex.GetReactions()))) .Join('\n'); - return _sender.CreateEmbed().WithOkColor().WithTitle(GetText(strs.expressions)).WithDescription(desc); + return CreateEmbed().WithOkColor().WithTitle(GetText(strs.expressions)).WithDescription(desc); }) .SendAsync(); } @@ -179,7 +179,7 @@ public partial class EllieExpressions : EllieModule await Response() .Interaction(IsValidExprEditor() ? inter : null) - .Embed(_sender.CreateEmbed() + .Embed(CreateEmbed() .WithOkColor() .WithDescription($"#{id}") .AddField(GetText(strs.trigger), found.Trigger.TrimTo(1024)) @@ -224,7 +224,7 @@ public partial class EllieExpressions : EllieModule if (ex is not null) { await Response() - .Embed(_sender.CreateEmbed() + .Embed(CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.expr_deleted)) .WithDescription($"#{id}") @@ -375,7 +375,7 @@ public partial class EllieExpressions : EllieModule [UserPerm(GuildPerm.Administrator)] public async Task ExprClear() { - if (await PromptUserConfirmAsync(_sender.CreateEmbed() + if (await PromptUserConfirmAsync(CreateEmbed() .WithTitle("Expression clear") .WithDescription("This will delete all expressions on this server."))) { diff --git a/src/EllieBot/Modules/Gambling/AnimalRacing/AnimalRacingCommands.cs b/src/EllieBot/Modules/Gambling/AnimalRacing/AnimalRacingCommands.cs index 04356df..5a4be4e 100644 --- a/src/EllieBot/Modules/Gambling/AnimalRacing/AnimalRacingCommands.cs +++ b/src/EllieBot/Modules/Gambling/AnimalRacing/AnimalRacingCommands.cs @@ -74,7 +74,7 @@ public partial class Gambling if (race.FinishedUsers[0].Bet > 0) { return Response() - .Embed(_sender.CreateEmbed() + .Embed(CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.animal_race)) .WithDescription(GetText(strs.animal_race_won_money( @@ -132,7 +132,7 @@ public partial class Gambling raceMessage = await Response().Confirm(text).SendAsync(); else { - await msg.ModifyAsync(x => x.Embed = _sender.CreateEmbed() + await msg.ModifyAsync(x => x.Embed = CreateEmbed() .WithTitle(GetText(strs.animal_race)) .WithDescription(text) .WithOkColor() diff --git a/src/EllieBot/Modules/Gambling/Bank/BankCommands.cs b/src/EllieBot/Modules/Gambling/Bank/BankCommands.cs index 1005763..274f39d 100644 --- a/src/EllieBot/Modules/Gambling/Bank/BankCommands.cs +++ b/src/EllieBot/Modules/Gambling/Bank/BankCommands.cs @@ -59,7 +59,7 @@ public partial class Gambling { var bal = await _bank.GetBalanceAsync(ctx.User.Id); - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor() .WithDescription(GetText(strs.bank_balance(N(bal)))); @@ -80,7 +80,7 @@ public partial class Gambling { var bal = await _bank.GetBalanceAsync(user.Id); - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor() .WithDescription(GetText(strs.bank_balance_other(user.ToString(), N(bal)))); diff --git a/src/EllieBot/Modules/Gambling/BetStatsCommands.cs b/src/EllieBot/Modules/Gambling/BetStatsCommands.cs index 4fe5c11..f9ba829 100644 --- a/src/EllieBot/Modules/Gambling/BetStatsCommands.cs +++ b/src/EllieBot/Modules/Gambling/BetStatsCommands.cs @@ -24,7 +24,7 @@ public partial class Gambling { var price = await _service.GetResetStatsPriceAsync(ctx.User.Id, game); - var result = await PromptUserConfirmAsync(_sender.CreateEmbed() + var result = await PromptUserConfirmAsync(CreateEmbed() .WithDescription( $""" Are you sure you want to reset your bet stats for **{GetGameName(game)}**? @@ -87,7 +87,7 @@ public partial class Gambling } }; - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor() .WithAuthor(user) .AddField("Total Won", N(stats.Sum(x => x.PaidOut)), true) @@ -120,7 +120,7 @@ public partial class Gambling { var stats = await _gamblingTxTracker.GetAllAsync(); - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor(); var str = "` Feature `|` Bet `|`Paid Out`|` RoI `\n"; @@ -156,7 +156,7 @@ public partial class Gambling [OwnerOnly] public async Task GambleStatsReset() { - if (!await PromptUserConfirmAsync(_sender.CreateEmbed() + if (!await PromptUserConfirmAsync(CreateEmbed() .WithDescription( """ Are you sure? diff --git a/src/EllieBot/Modules/Gambling/BlackJack/BlackJackCommands.cs b/src/EllieBot/Modules/Gambling/BlackJack/BlackJackCommands.cs index 14798e9..3cc8824 100644 --- a/src/EllieBot/Modules/Gambling/BlackJack/BlackJackCommands.cs +++ b/src/EllieBot/Modules/Gambling/BlackJack/BlackJackCommands.cs @@ -95,7 +95,7 @@ public partial class Gambling var cStr = string.Concat(c.Select(x => x[..^1] + " ")); cStr += "\n" + string.Concat(c.Select(x => x.Last() + " ")); - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .WithTitle("BlackJack") .AddField($"{dealerIcon} Dealer's Hand | Value: {bj.Dealer.GetHandValue()}", cStr); diff --git a/src/EllieBot/Modules/Gambling/Connect4/Connect4Commands.cs b/src/EllieBot/Modules/Gambling/Connect4/Connect4Commands.cs index ca2900c..1e72c85 100644 --- a/src/EllieBot/Modules/Gambling/Connect4/Connect4Commands.cs +++ b/src/EllieBot/Modules/Gambling/Connect4/Connect4Commands.cs @@ -132,7 +132,7 @@ public partial class Gambling else title = GetText(strs.connect4_draw); - return msg.ModifyAsync(x => x.Embed = _sender.CreateEmbed() + return msg.ModifyAsync(x => x.Embed = CreateEmbed() .WithTitle(title) .WithDescription(GetGameStateText(game)) .WithOkColor() @@ -142,7 +142,7 @@ public partial class Gambling private async Task Game_OnGameStateUpdated(Connect4Game game) { - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithTitle($"{game.CurrentPlayer.Username} vs {game.OtherPlayer.Username}") .WithDescription(GetGameStateText(game)) .WithOkColor(); diff --git a/src/EllieBot/Modules/Gambling/DiceRoll/DiceRollCommands.cs b/src/EllieBot/Modules/Gambling/DiceRoll/DiceRollCommands.cs index 15bf7ff..1b26175 100644 --- a/src/EllieBot/Modules/Gambling/DiceRoll/DiceRollCommands.cs +++ b/src/EllieBot/Modules/Gambling/DiceRoll/DiceRollCommands.cs @@ -38,7 +38,7 @@ public partial class Gambling var fileName = $"dice.{format.FileExtensions.First()}"; - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor() .WithAuthor(ctx.User) .AddField(GetText(strs.roll2), gen) @@ -115,7 +115,7 @@ public partial class Gambling d.Dispose(); var imageName = $"dice.{format.FileExtensions.First()}"; - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor() .WithAuthor(ctx.User) .AddField(GetText(strs.rolls), values.Select(x => Format.Code(x.ToString())).Join(' '), true) @@ -141,7 +141,7 @@ public partial class Gambling for (var i = 0; i < n1; i++) rolls.Add(_fateRolls[rng.Next(0, _fateRolls.Length)]); - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .WithAuthor(ctx.User) .WithDescription(GetText(strs.dice_rolled_num(Format.Bold(n1.ToString())))) @@ -170,7 +170,7 @@ public partial class Gambling arr[i] = rng.Next(1, n2 + 1); var sum = arr.Sum(); - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .WithAuthor(ctx.User) .WithDescription(GetText(strs.dice_rolled_num(n1 + $"`1 - {n2}`"))) diff --git a/src/EllieBot/Modules/Gambling/Draw/DrawCommands.cs b/src/EllieBot/Modules/Gambling/Draw/DrawCommands.cs index 1bf1986..cbb9de2 100644 --- a/src/EllieBot/Modules/Gambling/Draw/DrawCommands.cs +++ b/src/EllieBot/Modules/Gambling/Draw/DrawCommands.cs @@ -56,7 +56,7 @@ public partial class Gambling foreach (var i in images) i.Dispose(); - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor(); var toSend = string.Empty; @@ -171,7 +171,7 @@ public partial class Gambling return; } - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor() .WithAuthor(ctx.User) .WithDescription(result.Card.GetEmoji()) diff --git a/src/EllieBot/Modules/Gambling/Events/CurrencyEventsCommands.cs b/src/EllieBot/Modules/Gambling/Events/CurrencyEventsCommands.cs index 2f959fc..509cf93 100644 --- a/src/EllieBot/Modules/Gambling/Events/CurrencyEventsCommands.cs +++ b/src/EllieBot/Modules/Gambling/Events/CurrencyEventsCommands.cs @@ -30,12 +30,12 @@ public partial class Gambling private EmbedBuilder GetEmbed(CurrencyEvent.Type type, EventOptions opts, long currentPot) => type switch { - CurrencyEvent.Type.Reaction => _sender.CreateEmbed() + CurrencyEvent.Type.Reaction => CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.event_title(type.ToString()))) .WithDescription(GetReactionDescription(opts.Amount, currentPot)) .WithFooter(GetText(strs.event_duration_footer(opts.Hours))), - CurrencyEvent.Type.GameStatus => _sender.CreateEmbed() + CurrencyEvent.Type.GameStatus => CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.event_title(type.ToString()))) .WithDescription(GetGameStatusDescription(opts.Amount, currentPot)) diff --git a/src/EllieBot/Modules/Gambling/FlipCoin/FlipCoinCommands.cs b/src/EllieBot/Modules/Gambling/FlipCoin/FlipCoinCommands.cs index 8f3f589..f297d4f 100644 --- a/src/EllieBot/Modules/Gambling/FlipCoin/FlipCoinCommands.cs +++ b/src/EllieBot/Modules/Gambling/FlipCoin/FlipCoinCommands.cs @@ -84,7 +84,7 @@ public partial class Gambling ? Format.Bold(GetText(strs.heads)) : Format.Bold(GetText(strs.tails)))); - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor() .WithAuthor(ctx.User) .WithDescription(msg) @@ -130,7 +130,7 @@ public partial class Gambling str = Format.Bold(GetText(strs.better_luck)); } - await Response().Embed(_sender.CreateEmbed() + await Response().Embed(CreateEmbed() .WithAuthor(ctx.User) .WithDescription(str) .WithOkColor() diff --git a/src/EllieBot/Modules/Gambling/Gambling.cs b/src/EllieBot/Modules/Gambling/Gambling.cs index 3a0188a..3815137 100644 --- a/src/EllieBot/Modules/Gambling/Gambling.cs +++ b/src/EllieBot/Modules/Gambling/Gambling.cs @@ -39,6 +39,7 @@ public partial class Gambling : GamblingModule private readonly GamblingTxTracker _gamblingTxTracker; private readonly IPatronageService _ps; private readonly RakebackService _rb; + private readonly IBotCache _cache; public Gambling( IGamblingService gs, @@ -52,7 +53,8 @@ public partial class Gambling : GamblingModule IRemindService remind, IPatronageService patronage, GamblingTxTracker gamblingTxTracker, - RakebackService rb) + RakebackService rb, + IBotCache cache) : base(configService) { _gs = gs; @@ -63,6 +65,7 @@ public partial class Gambling : GamblingModule _remind = remind; _gamblingTxTracker = gamblingTxTracker; _rb = rb; + _cache = cache; _ps = patronage; _rng = new EllieRandom(); @@ -152,40 +155,10 @@ public partial class Gambling : GamblingModule } else if (Config.Timely.ProtType == TimelyProt.Captcha) { - var password = _service.GeneratePassword(); - - var img = new Image(60, 30); - - var font = _fonts.NotoSans.CreateFont(25); - var outlinePen = new SolidPen(Color.Black, 1f); - var strikeoutRun = new RichTextRun - { - Start = 0, - End = password.GetGraphemeCount(), - Font = font, - StrikeoutPen = new SolidPen(Color.White, 4), - TextDecorations = TextDecorations.Strikeout - }; - // draw password on the image - img.Mutate(x => - { - x.DrawText(new RichTextOptions(font) - { - HorizontalAlignment = HorizontalAlignment.Center, - VerticalAlignment = VerticalAlignment.Center, - FallbackFontFamilies = _fonts.FallBackFonts, - Origin = new(35, 17), - TextRuns = [strikeoutRun] - }, - password, - Brushes.Solid(Color.White), - outlinePen); - }); + var password = await GetUserTimelyPassword(ctx.User.Id); + var img = GetPasswordImage(password); using var stream = await img.ToStreamAsync(); var captcha = await Response() - // .Embed(_sender.CreateEmbed() - // .WithOkColor() - // .WithImageUrl("attachment://timely.png")) .File(stream, "timely.png") .SendAsync(); try @@ -195,6 +168,8 @@ public partial class Gambling : GamblingModule { return; } + + await ClearUserTimelyPassword(ctx.User.Id); } finally { @@ -205,6 +180,57 @@ public partial class Gambling : GamblingModule await ClaimTimely(); } + private static TypedKey TimelyPasswordKey(ulong userId) + => new($"timely_password:{userId}"); + + private async Task GetUserTimelyPassword(ulong userId) + { + var pw = await _cache.GetOrAddAsync(TimelyPasswordKey(userId), + () => + { + var password = _service.GeneratePassword(); + return Task.FromResult(password); + }); + + return pw; + } + + private ValueTask ClearUserTimelyPassword(ulong userId) + => _cache.RemoveAsync(TimelyPasswordKey(userId)); + + private Image GetPasswordImage(string password) + { + var img = new Image(50, 24); + + var font = _fonts.NotoSans.CreateFont(22); + var outlinePen = new SolidPen(Color.Black, 0.5f); + var strikeoutRun = new RichTextRun + { + Start = 0, + End = password.GetGraphemeCount(), + Font = font, + StrikeoutPen = new SolidPen(Color.White, 4), + TextDecorations = TextDecorations.Strikeout + }; + // draw password on the image + img.Mutate(x => + { + x.DrawText(new RichTextOptions(font) + { + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + FallbackFontFamilies = _fonts.FallBackFonts, + Origin = new(25, 12), + TextRuns = [strikeoutRun] + }, + password, + Brushes.Solid(Color.White), + outlinePen); + }); + + return img; + } + private async Task ClaimTimely() { var period = Config.Timely.Cooldown; @@ -384,11 +410,11 @@ public partial class Gambling : GamblingModule trs = await uow.Set().GetPageFor(userId, page); } - var embed = _sender.CreateEmbed() - .WithTitle(GetText(strs.transactions( - ((SocketGuild)ctx.Guild)?.GetUser(userId)?.ToString() - ?? $"{userId}"))) - .WithOkColor(); + var embed = CreateEmbed() + .WithTitle(GetText(strs.transactions( + ((SocketGuild)ctx.Guild)?.GetUser(userId)?.ToString() + ?? $"{userId}"))) + .WithOkColor(); var sb = new StringBuilder(); foreach (var tr in trs) @@ -435,7 +461,7 @@ public partial class Gambling : GamblingModule return; } - var eb = _sender.CreateEmbed().WithOkColor(); + var eb = CreateEmbed().WithOkColor(); eb.WithAuthor(ctx.User); eb.WithTitle(GetText(strs.transaction)); @@ -699,11 +725,11 @@ public partial class Gambling : GamblingModule str = GetText(strs.better_luck); } - var eb = _sender.CreateEmbed() - .WithAuthor(ctx.User) - .WithDescription(Format.Bold(str)) - .AddField(GetText(strs.roll2), result.Roll.ToString(CultureInfo.InvariantCulture)) - .WithOkColor(); + var eb = CreateEmbed() + .WithAuthor(ctx.User) + .WithDescription(Format.Bold(str)) + .AddField(GetText(strs.roll2), result.Roll.ToString(CultureInfo.InvariantCulture)) + .WithOkColor(); await Response().Embed(eb).SendAsync(); } @@ -766,9 +792,9 @@ public partial class Gambling : GamblingModule .CurrentPage(page) .Page((toSend, curPage) => { - var embed = _sender.CreateEmbed() - .WithOkColor() - .WithTitle(CurrencySign + " " + GetText(strs.leaderboard)); + var embed = CreateEmbed() + .WithOkColor() + .WithTitle(CurrencySign + " " + GetText(strs.leaderboard)); if (!toSend.Any()) { @@ -829,7 +855,7 @@ public partial class Gambling : GamblingModule return; } - var embed = _sender.CreateEmbed(); + var embed = CreateEmbed(); string msg; if (result.Result == RpsResultType.Draw) @@ -893,12 +919,12 @@ public partial class Gambling : GamblingModule sb.AppendLine(); } - var eb = _sender.CreateEmbed() - .WithOkColor() - .WithDescription(sb.ToString()) - .AddField(GetText(strs.multiplier), $"{result.Multiplier:0.##}x", true) - .AddField(GetText(strs.won), $"{(long)result.Won}", true) - .WithAuthor(ctx.User); + var eb = CreateEmbed() + .WithOkColor() + .WithDescription(sb.ToString()) + .AddField(GetText(strs.multiplier), $"{result.Multiplier:0.##}x", true) + .AddField(GetText(strs.won), $"{(long)result.Won}", true) + .WithAuthor(ctx.User); await Response().Embed(eb).SendAsync(); diff --git a/src/EllieBot/Modules/Gambling/Loan/LoanCommands.cs b/src/EllieBot/Modules/Gambling/Loan/LoanCommands.cs index d540c04..6d23486 100644 --- a/src/EllieBot/Modules/Gambling/Loan/LoanCommands.cs +++ b/src/EllieBot/Modules/Gambling/Loan/LoanCommands.cs @@ -34,7 +34,7 @@ // decimal interest = 0, // TimeSpan dueIn = default) // { -// var eb = _sender.CreateEmbed() +// var eb = CreateEmbed() // .WithOkColor() // .WithDescription("User 0 Requests a loan from User {1}") // .AddField("Amount", amount, true) @@ -53,7 +53,7 @@ // .PageItems(loans) // .Page((items, page) => // { -// var eb = _sender.CreateEmbed() +// var eb = CreateEmbed() // .WithOkColor() // .WithDescription("Current Loans"); // diff --git a/src/EllieBot/Modules/Gambling/PlantPick/PlantAndPickCommands.cs b/src/EllieBot/Modules/Gambling/PlantPick/PlantAndPickCommands.cs index 7723a6a..558885b 100644 --- a/src/EllieBot/Modules/Gambling/PlantPick/PlantAndPickCommands.cs +++ b/src/EllieBot/Modules/Gambling/PlantPick/PlantAndPickCommands.cs @@ -103,9 +103,9 @@ public partial class Gambling .Page((items, _) => { if (!items.Any()) - return _sender.CreateEmbed().WithErrorColor().WithDescription("-"); + return CreateEmbed().WithErrorColor().WithDescription("-"); - return items.Aggregate(_sender.CreateEmbed().WithOkColor(), + return items.Aggregate(CreateEmbed().WithOkColor(), (eb, i) => eb.AddField(i.GuildId.ToString(), i.ChannelId)); }) .SendAsync(); diff --git a/src/EllieBot/Modules/Gambling/Shop/ShopCommands.cs b/src/EllieBot/Modules/Gambling/Shop/ShopCommands.cs index 2c2dca6..4935658 100644 --- a/src/EllieBot/Modules/Gambling/Shop/ShopCommands.cs +++ b/src/EllieBot/Modules/Gambling/Shop/ShopCommands.cs @@ -56,8 +56,8 @@ public partial class Gambling .Page((items, curPage) => { if (!items.Any()) - return _sender.CreateEmbed().WithErrorColor().WithDescription(GetText(strs.shop_none)); - var embed = _sender.CreateEmbed().WithOkColor().WithTitle(GetText(strs.shop)); + return CreateEmbed().WithErrorColor().WithDescription(GetText(strs.shop_none)); + var embed = CreateEmbed().WithOkColor().WithTitle(GetText(strs.shop)); for (var i = 0; i < items.Count; i++) { @@ -188,7 +188,7 @@ public partial class Gambling { await Response() .User(ctx.User) - .Embed(_sender.CreateEmbed() + .Embed(CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.shop_purchase(ctx.Guild.Name))) .AddField(GetText(strs.item), item.Text) @@ -254,7 +254,7 @@ public partial class Gambling .Replace("%you.name%", buyer.GlobalName ?? buyer.Username) .Replace("%you.nick%", buyer.DisplayName); - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithPendingColor() .WithTitle("Executing shop command") .WithDescription(cmd); @@ -541,7 +541,7 @@ public partial class Gambling public EmbedBuilder EntryToEmbed(ShopEntry entry) { - var embed = _sender.CreateEmbed().WithOkColor(); + var embed = CreateEmbed().WithOkColor(); if (entry.Type == ShopEntryType.Role) { diff --git a/src/EllieBot/Modules/Gambling/Slot/SlotCommands.cs b/src/EllieBot/Modules/Gambling/Slot/SlotCommands.cs index 239b7bc..6cda98d 100644 --- a/src/EllieBot/Modules/Gambling/Slot/SlotCommands.cs +++ b/src/EllieBot/Modules/Gambling/Slot/SlotCommands.cs @@ -65,7 +65,7 @@ public partial class Gambling await using var imgStream = await image.ToStreamAsync(); - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithAuthor(ctx.User) .WithDescription(Format.Bold(text)) .WithImageUrl($"attachment://result.png") diff --git a/src/EllieBot/Modules/Gambling/Waifus/WaifuClaimCommands.cs b/src/EllieBot/Modules/Gambling/Waifus/WaifuClaimCommands.cs index d52a22b..1420733 100644 --- a/src/EllieBot/Modules/Gambling/Waifus/WaifuClaimCommands.cs +++ b/src/EllieBot/Modules/Gambling/Waifus/WaifuClaimCommands.cs @@ -21,7 +21,7 @@ public partial class Gambling public async Task WaifuReset() { var price = _service.GetResetPrice(ctx.User); - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithTitle(GetText(strs.waifu_reset_confirm)) .WithDescription(GetText(strs.waifu_reset_price(Format.Bold(N(price))))); @@ -46,7 +46,7 @@ public partial class Gambling .PageItems(async (page) => await _service.GetClaimsAsync(ctx.User.Id, page)) .Page((items, page) => { - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor() .WithTitle("Waifus"); @@ -266,7 +266,7 @@ public partial class Gambling return; } - var embed = _sender.CreateEmbed().WithTitle(GetText(strs.waifus_top_waifus)).WithOkColor(); + var embed = CreateEmbed().WithTitle(GetText(strs.waifus_top_waifus)).WithOkColor(); var i = 0; foreach (var w in waifus) @@ -350,7 +350,7 @@ public partial class Gambling if (string.IsNullOrWhiteSpace(fansStr)) fansStr = "-"; - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.waifu) + " " @@ -393,7 +393,7 @@ public partial class Gambling .CurrentPage(page) .Page((items, _) => { - var embed = _sender.CreateEmbed().WithTitle(GetText(strs.waifu_gift_shop)).WithOkColor(); + var embed = CreateEmbed().WithTitle(GetText(strs.waifu_gift_shop)).WithOkColor(); items .ToList() diff --git a/src/EllieBot/Modules/Games/Acrophobia/AcropobiaCommands.cs b/src/EllieBot/Modules/Games/Acrophobia/AcropobiaCommands.cs index 30defba..166aa16 100644 --- a/src/EllieBot/Modules/Games/Acrophobia/AcropobiaCommands.cs +++ b/src/EllieBot/Modules/Games/Acrophobia/AcropobiaCommands.cs @@ -67,7 +67,7 @@ public partial class Games private Task Game_OnStarted(AcrophobiaGame game) { - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.acrophobia)) .WithDescription( @@ -92,7 +92,7 @@ public partial class Games if (submissions.Length == 1) { - await Response().Embed(_sender.CreateEmbed() + await Response().Embed(CreateEmbed() .WithOkColor() .WithDescription(GetText( strs.acro_winner_only( @@ -103,7 +103,7 @@ public partial class Games var i = 0; - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.acrophobia) + " - " + GetText(strs.submissions_closed)) .WithDescription(GetText(strs.acro_nym_was( @@ -127,7 +127,7 @@ public partial class Games var table = votes.OrderByDescending(v => v.Value); var winner = table.First(); - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.acrophobia)) .WithDescription(GetText(strs.acro_winner(Format.Bold(winner.Key.UserName), diff --git a/src/EllieBot/Modules/Games/Games.cs b/src/EllieBot/Modules/Games/Games.cs index c14d6ee..4823756 100644 --- a/src/EllieBot/Modules/Games/Games.cs +++ b/src/EllieBot/Modules/Games/Games.cs @@ -38,7 +38,7 @@ public partial class Games : EllieModule return; var res = _service.GetEightballResponse(ctx.User.Id, question); - await Response().Embed(_sender.CreateEmbed() + await Response().Embed(CreateEmbed() .WithOkColor() .WithDescription(ctx.User.ToString()) .AddField("❓ " + GetText(strs.question), question) diff --git a/src/EllieBot/Modules/Games/NCanvas/NCanvasCommands.cs b/src/EllieBot/Modules/Games/NCanvas/NCanvasCommands.cs index 6d37a5e..ee35fba 100644 --- a/src/EllieBot/Modules/Games/NCanvas/NCanvasCommands.cs +++ b/src/EllieBot/Modules/Games/NCanvas/NCanvasCommands.cs @@ -53,7 +53,7 @@ public partial class Games var hint = GetText(strs.nc_hint(prefix, _service.GetWidth(), _service.GetHeight())); await Response() .File(stream, "ncanvas.png") - .Embed(_sender.CreateEmbed() + .Embed(CreateEmbed() .WithOkColor() #if GLOBAL_ELLIE .WithDescription("This is not available yet.") @@ -164,7 +164,7 @@ public partial class Games Culture, _gcs.Data.Currency.Sign)))); - if (!await PromptUserConfirmAsync(_sender.CreateEmbed() + if (!await PromptUserConfirmAsync(CreateEmbed() .WithPendingColor() .WithDescription(prompt))) { @@ -193,7 +193,7 @@ public partial class Games await using var stream = await img.ToStreamAsync(); await Response() - .Embed(_sender.CreateEmbed() + .Embed(CreateEmbed() .WithOkColor() .WithDescription(GetText(strs.nc_pixel_set(Format.Code(position.ToString())))) .WithImageUrl($"attachment://zoom_{position}.png")) @@ -231,7 +231,7 @@ public partial class Games var pos = new kwum(pixel.Position); await Response() .File(stream, $"{pixel.Position}.png") - .Embed(_sender.CreateEmbed() + .Embed(CreateEmbed() .WithOkColor() .WithDescription(string.IsNullOrWhiteSpace(pixel.Text) ? string.Empty : pixel.Text) .WithTitle(GetText(strs.nc_pixel(pos))) @@ -263,7 +263,7 @@ public partial class Games return; } - if (!await PromptUserConfirmAsync(_sender.CreateEmbed() + if (!await PromptUserConfirmAsync(CreateEmbed() .WithDescription( "This will reset the canvas to the specified image. All prices, text and colors will be reset.\n\n" + "Are you sure you want to continue?"))) @@ -293,7 +293,7 @@ public partial class Games { await _service.ResetAsync(); - if (!await PromptUserConfirmAsync(_sender.CreateEmbed() + if (!await PromptUserConfirmAsync(CreateEmbed() .WithDescription( "This will delete all pixels and reset the canvas.\n\n" + "Are you sure you want to continue?"))) diff --git a/src/EllieBot/Modules/Games/SpeedTyping/SpeedTypingCommands.cs b/src/EllieBot/Modules/Games/SpeedTyping/SpeedTypingCommands.cs index 65b8bbd..265aa7a 100644 --- a/src/EllieBot/Modules/Games/SpeedTyping/SpeedTypingCommands.cs +++ b/src/EllieBot/Modules/Games/SpeedTyping/SpeedTypingCommands.cs @@ -94,7 +94,7 @@ public partial class Games if (removed is null) return; - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithTitle($"Removed typing article #{index + 1}") .WithDescription(removed.Text.TrimTo(50)) .WithOkColor(); diff --git a/src/EllieBot/Modules/Games/Trivia/TriviaCommands.cs b/src/EllieBot/Modules/Games/Trivia/TriviaCommands.cs index 72b4eb4..6403b85 100644 --- a/src/EllieBot/Modules/Games/Trivia/TriviaCommands.cs +++ b/src/EllieBot/Modules/Games/Trivia/TriviaCommands.cs @@ -160,7 +160,7 @@ public partial class Games { try { - questionEmbed = _sender.CreateEmbed() + questionEmbed = CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.trivia_game)) .AddField(GetText(strs.category), question.Category) @@ -189,7 +189,7 @@ public partial class Games { try { - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithErrorColor() .WithTitle(GetText(strs.trivia_game)) .WithDescription(GetText(strs.trivia_times_up(Format.Bold(question.Answer)))); @@ -221,7 +221,7 @@ public partial class Games { try { - await Response().Embed(_sender.CreateEmbed() + await Response().Embed(CreateEmbed() .WithOkColor() .WithAuthor(GetText(strs.trivia_ended)) .WithTitle(GetText(strs.leaderboard)) @@ -247,7 +247,7 @@ public partial class Games { try { - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.trivia_game)) .WithDescription(GetText(strs.trivia_win(user.Name, diff --git a/src/EllieBot/Modules/Help/Help.cs b/src/EllieBot/Modules/Help/Help.cs index 8b7c006..48d9973 100644 --- a/src/EllieBot/Modules/Help/Help.cs +++ b/src/EllieBot/Modules/Help/Help.cs @@ -114,7 +114,7 @@ public sealed partial class Help : EllieModule .AddFooter(false) .Page((items, _) => { - var embed = _sender.CreateEmbed().WithOkColor().WithTitle(GetText(strs.list_of_modules)); + var embed = CreateEmbed().WithOkColor().WithTitle(GetText(strs.list_of_modules)); if (!items.Any()) { @@ -315,7 +315,7 @@ public sealed partial class Help : EllieModule .WithPlaceholder("Select a submodule to see detailed commands"); var groups = cmdsWithGroup.ToArray(); - var embed = _sender.CreateEmbed().WithOkColor(); + var embed = CreateEmbed().WithOkColor(); foreach (var g in groups) { sb.AddOption(g.Key, g.Key); @@ -383,7 +383,7 @@ public sealed partial class Help : EllieModule .Interaction(inter) .Page((items, _) => { - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithTitle(GetText(strs.cmd_group_commands(group.Name))) .WithOkColor(); @@ -520,7 +520,7 @@ public sealed partial class Help : EllieModule [OnlyPublicBot] public async Task Donate() { - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor() .WithTitle("Thank you for considering to donate to the EllieBot project!"); diff --git a/src/EllieBot/Modules/Marmalades/Marmalade.cs b/src/EllieBot/Modules/Marmalades/Marmalade.cs index 530b23f..4a86f57 100644 --- a/src/EllieBot/Modules/Marmalades/Marmalade.cs +++ b/src/EllieBot/Modules/Marmalades/Marmalade.cs @@ -40,7 +40,7 @@ public partial class Marmalade : EllieModule .PageSize(10) .Page((items, _) => { - return _sender.CreateEmbed() + return CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.list_of_unloaded)) .WithDescription(items.Join('\n')); @@ -81,7 +81,7 @@ public partial class Marmalade : EllieModule } await Response() - .Embed(_sender.CreateEmbed() + .Embed(CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.loaded_marmalades)) .WithDescription(loaded.Select(x => x.Name) @@ -136,7 +136,7 @@ public partial class Marmalade : EllieModule .Paginated() .Items(output) .PageSize(10) - .Page((items, _) => _sender.CreateEmbed() + .Page((items, _) => CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.list_of_marmalades)) .WithDescription(items.Join('\n'))) @@ -168,7 +168,7 @@ public partial class Marmalade : EllieModule : $"{x.Prefix} {x.Name}")) .Join("\n"); - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor() .WithAuthor(GetText(strs.marmalade_info)) .WithTitle(found.Name) @@ -201,7 +201,7 @@ public partial class Marmalade : EllieModule .CurrentPage(0) .Page((items, _) => { - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor(); foreach (var marmalade in items) @@ -224,7 +224,7 @@ public partial class Marmalade : EllieModule [OwnerOnly] public async Task MarmaladeSearch() { - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithTitle(GetText(strs.list_of_marmalades)) .WithOkColor(); diff --git a/src/EllieBot/Modules/Music/Music.cs b/src/EllieBot/Modules/Music/Music.cs index 3b1393c..1061ad1 100644 --- a/src/EllieBot/Modules/Music/Music.cs +++ b/src/EllieBot/Modules/Music/Music.cs @@ -109,7 +109,7 @@ public sealed partial class Music : EllieModule try { - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .WithAuthor(GetText(strs.queued_track) + " #" + (index + 1), MUSIC_ICON_URL) .WithDescription($"{trackInfo.PrettyName()}\n{GetText(strs.queue)} ") @@ -314,7 +314,7 @@ public sealed partial class Music : EllieModule if (!string.IsNullOrWhiteSpace(add)) desc = add + "\n" + desc; - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithAuthor( GetText(strs.player_queue(curPage + 1, (tracks.Count / LQ_ITEMS_PER_PAGE) + 1)), MUSIC_ICON_URL) @@ -352,7 +352,7 @@ public sealed partial class Music : EllieModule } - var embeds = videos.Select((x, i) => _sender.CreateEmbed() + var embeds = videos.Select((x, i) => CreateEmbed() .WithOkColor() .WithThumbnailUrl(x.Thumbnail) .WithDescription($"`{i + 1}.` {Format.Bold(x.Title)}\n\t{x.Url}")) @@ -424,7 +424,7 @@ public sealed partial class Music : EllieModule return; } - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithAuthor(GetText(strs.removed_track) + " #" + index, MUSIC_ICON_URL) .WithDescription(track.PrettyName()) .WithFooter(track.PrettyInfo()) @@ -592,7 +592,7 @@ public sealed partial class Music : EllieModule return; } - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithTitle(track.Title.TrimTo(65)) .WithAuthor(GetText(strs.track_moved), MUSIC_ICON_URL) .AddField(GetText(strs.from_position), $"#{from + 1}", true) @@ -651,7 +651,7 @@ public sealed partial class Music : EllieModule if (currentTrack is null) return; - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .WithAuthor(GetText(strs.now_playing), MUSIC_ICON_URL) .WithDescription(currentTrack.PrettyName()) @@ -752,4 +752,20 @@ public sealed partial class Music : EllieModule else await Response().Error(strs.no_player).SendAsync(); } + + [Cmd] + [RequireContext(ContextType.Guild)] + public async Task WrongSong() + { + var removed = await _service.RemoveLastQueuedTrackAsync(ctx.Guild.Id); + + if (removed is null) + { + await Response().Error(strs.no_last_queued_found).SendAsync(); + } + else + { + await Response().Confirm(strs.wrongsong_success(removed.Title.TrimTo(30))).SendAsync(); + } + } } \ No newline at end of file diff --git a/src/EllieBot/Modules/Music/PlaylistCommands.cs b/src/EllieBot/Modules/Music/PlaylistCommands.cs index 68a651d..2eb1d57 100644 --- a/src/EllieBot/Modules/Music/PlaylistCommands.cs +++ b/src/EllieBot/Modules/Music/PlaylistCommands.cs @@ -49,7 +49,7 @@ public sealed partial class Music playlists = uow.Set().GetPlaylistsOnPage(num); } - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithAuthor(GetText(strs.playlists_page(num)), MUSIC_ICON_URL) .WithDescription(string.Join("\n", playlists.Select(r => GetText(strs.playlists(r.Id, r.Name, r.Author, r.Songs.Count))))) @@ -113,7 +113,7 @@ public sealed partial class Music var str = string.Join("\n", items .Select(x => $"`{++i}.` [{x.Title.TrimTo(45)}]({x.Query}) `{x.Provider}`")); - return _sender.CreateEmbed().WithTitle($"\"{mpl.Name}\" by {mpl.Author}") + return CreateEmbed().WithTitle($"\"{mpl.Name}\" by {mpl.Author}") .WithOkColor() .WithDescription(str); }) @@ -155,7 +155,7 @@ public sealed partial class Music } await Response() - .Embed(_sender.CreateEmbed() + .Embed(CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.playlist_saved)) .AddField(GetText(strs.name), name) diff --git a/src/EllieBot/Modules/Music/Services/IMusicService.cs b/src/EllieBot/Modules/Music/Services/IMusicService.cs index 43bad99..6648640 100644 --- a/src/EllieBot/Modules/Music/Services/IMusicService.cs +++ b/src/EllieBot/Modules/Music/Services/IMusicService.cs @@ -33,4 +33,5 @@ public interface IMusicService Task SetMusicQualityAsync(ulong guildId, QualityPreset preset); Task ToggleQueueAutoPlayAsync(ulong guildId); Task FairplayAsync(ulong guildId); + Task RemoveLastQueuedTrackAsync(ulong guildId); } \ No newline at end of file diff --git a/src/EllieBot/Modules/Music/Services/MusicService.cs b/src/EllieBot/Modules/Music/Services/MusicService.cs index 89c848d..6ddcbf4 100644 --- a/src/EllieBot/Modules/Music/Services/MusicService.cs +++ b/src/EllieBot/Modules/Music/Services/MusicService.cs @@ -179,11 +179,11 @@ public sealed class MusicService : IMusicService, IPlaceholderProvider return async (mp, trackInfo) => { _ = lastFinishedMessage?.DeleteAsync(); - var embed = _sender.CreateEmbed() - .WithOkColor() - .WithAuthor(GetText(guildId, strs.finished_track), Music.MUSIC_ICON_URL) - .WithDescription(trackInfo.PrettyName()) - .WithFooter(trackInfo.PrettyTotalTime()); + var embed = _sender.CreateEmbed(guildId) + .WithOkColor() + .WithAuthor(GetText(guildId, strs.finished_track), Music.MUSIC_ICON_URL) + .WithDescription(trackInfo.PrettyName()) + .WithFooter(trackInfo.PrettyTotalTime()); lastFinishedMessage = await SendToOutputAsync(guildId, embed); }; @@ -195,11 +195,11 @@ public sealed class MusicService : IMusicService, IPlaceholderProvider return async (mp, trackInfo, index) => { _ = lastPlayingMessage?.DeleteAsync(); - var embed = _sender.CreateEmbed() - .WithOkColor() - .WithAuthor(GetText(guildId, strs.playing_track(index + 1)), Music.MUSIC_ICON_URL) - .WithDescription(trackInfo.PrettyName()) - .WithFooter($"{mp.PrettyVolume()} | {trackInfo.PrettyInfo()}"); + var embed = _sender.CreateEmbed(guildId) + .WithOkColor() + .WithAuthor(GetText(guildId, strs.playing_track(index + 1)), Music.MUSIC_ICON_URL) + .WithDescription(trackInfo.PrettyName()) + .WithFooter($"{mp.PrettyVolume()} | {trackInfo.PrettyInfo()}"); lastPlayingMessage = await SendToOutputAsync(guildId, embed); }; @@ -213,7 +213,7 @@ public sealed class MusicService : IMusicService, IPlaceholderProvider if (settings.AutoDisconnect) return LeaveVoiceChannelAsync(guildId); } - + return Task.CompletedTask; }; @@ -290,7 +290,8 @@ public sealed class MusicService : IMusicService, IPlaceholderProvider return "-"; return randomPlayingTrack.Title; - }); + } + ); // number of servers currently listening to music yield return ("%music.servers%", () => @@ -298,14 +299,16 @@ public sealed class MusicService : IMusicService, IPlaceholderProvider var count = _players.Select(x => x.Value.GetCurrentTrack(out _)).Count(x => x is not null); return count.ToString(); - }); + } + ); yield return ("%music.queued%", () => { var count = _players.Sum(x => x.Value.GetQueuedTracks().Count); return count.ToString(); - }); + } + ); } #region Settings @@ -434,5 +437,17 @@ public sealed class MusicService : IMusicService, IPlaceholderProvider return Task.FromResult(false); } + public async Task RemoveLastQueuedTrackAsync(ulong guildId) + { + if (TryGetMusicPlayer(guildId, out var mp)) + { + var last = await mp.RemoveLastQueuedTrack(); + + return last; + } + + return null; + } + #endregion -} +} \ No newline at end of file diff --git a/src/EllieBot/Modules/Music/_common/IMusicPlayer.cs b/src/EllieBot/Modules/Music/_common/IMusicPlayer.cs index a593a57..18e1c58 100644 --- a/src/EllieBot/Modules/Music/_common/IMusicPlayer.cs +++ b/src/EllieBot/Modules/Music/_common/IMusicPlayer.cs @@ -38,4 +38,5 @@ public interface IMusicPlayer : IDisposable void SetRepeat(PlayerRepeatType type); void ShuffleQueue(); void SetFairplay(); + Task RemoveLastQueuedTrack(); } \ No newline at end of file diff --git a/src/EllieBot/Modules/Music/_common/IMusicQueue.cs b/src/EllieBot/Modules/Music/_common/IMusicQueue.cs index 5d4d24b..bb1f457 100644 --- a/src/EllieBot/Modules/Music/_common/IMusicQueue.cs +++ b/src/EllieBot/Modules/Music/_common/IMusicQueue.cs @@ -20,4 +20,5 @@ public interface IMusicQueue void Shuffle(Random rng); bool IsLast(); void ReorderFairly(); + int? GetLastQueuedIndex(); } \ No newline at end of file diff --git a/src/EllieBot/Modules/Music/_common/Impl/MusicPlayer.cs b/src/EllieBot/Modules/Music/_common/Impl/MusicPlayer.cs index 02cb4e2..91178d3 100644 --- a/src/EllieBot/Modules/Music/_common/Impl/MusicPlayer.cs +++ b/src/EllieBot/Modules/Music/_common/Impl/MusicPlayer.cs @@ -260,7 +260,6 @@ public sealed class MusicPlayer : IMusicPlayer IsStopped = true; Log.Error("Please install ffmpeg and make sure it's added to your " + "PATH environment variable before trying again"); - } catch (OperationCanceledException) { @@ -313,7 +312,7 @@ public sealed class MusicPlayer : IMusicPlayer { if (track.TrackInfo is SimpleTrackInfo sti) return sti.StreamUrl; - + return await _ytResolverFactory.GetYoutubeResolver().GetStreamUrl(track.TrackInfo.Id); } @@ -420,20 +419,20 @@ public sealed class MusicPlayer : IMusicPlayer break; await chunk.Select(async data => + { + var (query, platform) = data; + try { - var (query, platform) = data; - try - { - await TryEnqueueTrackAsync(query, queuer, false, platform); - errorCount = 0; - } - catch (Exception ex) - { - Log.Warning(ex, "Error resolving {MusicPlatform} Track {TrackQuery}", platform, query); - ++errorCount; - } - }) - .WhenAll(); + await TryEnqueueTrackAsync(query, queuer, false, platform); + errorCount = 0; + } + catch (Exception ex) + { + Log.Warning(ex, "Error resolving {MusicPlatform} Track {TrackQuery}", platform, query); + ++errorCount; + } + }) + .WhenAll(); await Task.Delay(1000); @@ -542,4 +541,15 @@ public sealed class MusicPlayer : IMusicPlayer { _queue.ReorderFairly(); } + + public Task RemoveLastQueuedTrack() + { + var last = _queue.GetLastQueuedIndex(); + if (last is null) + return Task.FromResult(null); + + return TryRemoveTrackAt(last.Value, out var trackInfo) + ? Task.FromResult(trackInfo) + : Task.FromResult(null); + } } \ No newline at end of file diff --git a/src/EllieBot/Modules/Music/_common/Impl/MusicQueue.cs b/src/EllieBot/Modules/Music/_common/Impl/MusicQueue.cs index 9b1c7aa..38f9761 100644 --- a/src/EllieBot/Modules/Music/_common/Impl/MusicQueue.cs +++ b/src/EllieBot/Modules/Music/_common/Impl/MusicQueue.cs @@ -60,6 +60,7 @@ public sealed partial class MusicQueue : IMusicQueue private LinkedList tracks; private int index; + private int? _lastQueued = null; private readonly object _locker = new(); @@ -74,9 +75,9 @@ public sealed partial class MusicQueue : IMusicQueue lock (_locker) { var added = new QueuedTrackInfo(trackInfo, queuer); - enqueuedAt = tracks.Count; + _lastQueued = enqueuedAt = tracks.Count; tracks.AddLast(added); - + return added; } } @@ -99,6 +100,8 @@ public sealed partial class MusicQueue : IMusicQueue tracks.AddAfter(currentNode, added); + _lastQueued = i; + return added; } } @@ -112,6 +115,8 @@ public sealed partial class MusicQueue : IMusicQueue var added = new QueuedTrackInfo(track, queuer); tracks.AddLast(added); } + + _lastQueued = tracks.Count; } } @@ -146,6 +151,7 @@ public sealed partial class MusicQueue : IMusicQueue lock (_locker) { tracks.Clear(); + _lastQueued = null; } } @@ -177,6 +183,18 @@ public sealed partial class MusicQueue : IMusicQueue if (index < 0) index = Count; + if (i < _lastQueued) + { + if (_lastQueued is not null) + { + _lastQueued -= 1; + } + } + else if (i == _lastQueued) + { + _lastQueued = null; + } + // if it was the last song in the queue // // wrap back to start // if (_index == Count) @@ -207,6 +225,11 @@ public sealed partial class MusicQueue : IMusicQueue if (from >= Count || to >= Count) return null; + if (from == _lastQueued) + _lastQueued = to; + else if (to == _lastQueued) + _lastQueued += 1; + // update current track index if (from == index) { @@ -267,6 +290,7 @@ public sealed partial class MusicQueue : IMusicQueue var list = tracks.ToArray(); rng.Shuffle(list); tracks = new(list); + _lastQueued = null; } } @@ -318,6 +342,8 @@ public sealed partial class MusicQueue : IMusicQueue if (queuers.Count == 0) break; } + + _lastQueued = null; } } @@ -339,4 +365,6 @@ public sealed partial class MusicQueue : IMusicQueue return true; } } + + public int? GetLastQueuedIndex() => _lastQueued; } \ No newline at end of file diff --git a/src/EllieBot/Modules/Patronage/CurrencyRewardService.cs b/src/EllieBot/Modules/Patronage/CurrencyRewardService.cs index 391ebb4..a25ee20 100644 --- a/src/EllieBot/Modules/Patronage/CurrencyRewardService.cs +++ b/src/EllieBot/Modules/Patronage/CurrencyRewardService.cs @@ -32,9 +32,8 @@ public sealed class CurrencyRewardService : IEService, IReadyExecutor _sender = sender; _config = config; _client = client; - } - + public Task OnReadyAsync() { _ps.OnNewPatronPayment += OnNewPayment; @@ -55,29 +54,29 @@ public sealed class CurrencyRewardService : IEService, IReadyExecutor await using (var ctx = _db.GetDbContext()) { old = await ctx.GetTable() - .Where(x => x.PlatformUserId == newPatron.UniquePlatformUserId) - .FirstOrDefaultAsync(); - + .Where(x => x.PlatformUserId == newPatron.UniquePlatformUserId) + .FirstOrDefaultAsync(); + if (old is null) { await OnNewPayment(newPatron); return; } - + // no action as the amount is the same or lower if (old.AmountRewardedThisMonth >= newAmount) return; - + var count = await ctx.GetTable() - .Where(x => x.PlatformUserId == newPatron.UniquePlatformUserId) - .UpdateAsync(_ => new() - { - PlatformUserId = newPatron.UniquePlatformUserId, - UserId = newPatron.UserId, - // amount before bonuses - AmountRewardedThisMonth = newAmount, - LastReward = newPatron.PaidAt - }); + .Where(x => x.PlatformUserId == newPatron.UniquePlatformUserId) + .UpdateAsync(_ => new() + { + PlatformUserId = newPatron.UniquePlatformUserId, + UserId = newPatron.UserId, + // amount before bonuses + AmountRewardedThisMonth = newAmount, + LastReward = newPatron.PaidAt + }); // shouldn't ever happen if (count == 0) @@ -90,21 +89,21 @@ public sealed class CurrencyRewardService : IEService, IReadyExecutor (int)(newAmount / conf.PatreonCurrencyPerCent), newAmount, out var percentBonus); - + var realOldAmount = GetRealCurrencyReward( (int)(oldAmount / conf.PatreonCurrencyPerCent), oldAmount, out _); - + var diff = realNewAmount - realOldAmount; if (diff <= 0) return; // no action if new is lower // if the user pledges 5$ or more, they will get X % more flowers where X is amount in dollars, // up to 100% - - await _cs.AddAsync(newPatron.UserId, diff, new TxData("patron","update")); - + + await _cs.AddAsync(newPatron.UserId, diff, new TxData("patron", "update")); + _ = SendMessageToUser(newPatron.UserId, $"You've received an additional **{diff}**{_config.Data.Currency.Sign} as a currency reward (+{percentBonus}%)!"); } @@ -139,12 +138,12 @@ public sealed class CurrencyRewardService : IEService, IReadyExecutor await using var ctx = _db.GetDbContext(); await ctx.GetTable() .InsertOrUpdateAsync(() => new() - { - PlatformUserId = patron.UniquePlatformUserId, - UserId = patron.UserId, - AmountRewardedThisMonth = amount, - LastReward = patron.PaidAt, - }, + { + PlatformUserId = patron.UniquePlatformUserId, + UserId = patron.UserId, + AmountRewardedThisMonth = amount, + LastReward = patron.PaidAt, + }, old => new() { AmountRewardedThisMonth = amount, @@ -155,7 +154,7 @@ public sealed class CurrencyRewardService : IEService, IReadyExecutor { PlatformUserId = patron.UniquePlatformUserId }); - + var realAmount = GetRealCurrencyReward(patron.Amount, amount, out var percentBonus); await _cs.AddAsync(patron.UserId, realAmount, new("patron", "new")); _ = SendMessageToUser(patron.UserId, @@ -171,9 +170,9 @@ public sealed class CurrencyRewardService : IEService, IReadyExecutor return; var eb = _sender.CreateEmbed() - .WithOkColor() - .WithDescription(message); - + .WithOkColor() + .WithDescription(message); + await _sender.Response(user).Embed(eb).SendAsync(); } catch diff --git a/src/EllieBot/Modules/Patronage/PatronageCommands.cs b/src/EllieBot/Modules/Patronage/PatronageCommands.cs index fee2c33..64850f3 100644 --- a/src/EllieBot/Modules/Patronage/PatronageCommands.cs +++ b/src/EllieBot/Modules/Patronage/PatronageCommands.cs @@ -53,7 +53,7 @@ public partial class Help // // var patron = _service.GiftPatronAsync(user, amount); // - // var eb = _sender.CreateEmbed(); + // var eb = CreateEmbed(); // // await Response().Embed(eb.WithDescription($"Added **{days}** days of Patron benefits to {user.Mention}!") // .AddField("Tier", Format.Bold(patron.Tier.ToString()), true) @@ -75,7 +75,7 @@ public partial class Help var quotaStats = await _service.LimitStats(user.Id); - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithAuthor(user) .WithTitle(GetText(strs.patron_info)) .WithOkColor(); diff --git a/src/EllieBot/Modules/Permissions/Blacklist/BlacklistCommands.cs b/src/EllieBot/Modules/Permissions/Blacklist/BlacklistCommands.cs index 5ce851b..70bc2e6 100644 --- a/src/EllieBot/Modules/Permissions/Blacklist/BlacklistCommands.cs +++ b/src/EllieBot/Modules/Permissions/Blacklist/BlacklistCommands.cs @@ -60,12 +60,12 @@ public partial class Permissions .Page((pageItems, _) => { if (pageItems.Count == 0) - return _sender.CreateEmbed() + return CreateEmbed() .WithOkColor() .WithTitle(title) .WithDescription(GetText(strs.empty_page)); - return _sender.CreateEmbed() + return CreateEmbed() .WithTitle(title) .WithDescription(pageItems.Join('\n')) .WithOkColor(); diff --git a/src/EllieBot/Modules/Permissions/CommandCooldown/CmdCdsCommands.cs b/src/EllieBot/Modules/Permissions/CommandCooldown/CmdCdsCommands.cs index a9b7a13..8d7a414 100644 --- a/src/EllieBot/Modules/Permissions/CommandCooldown/CmdCdsCommands.cs +++ b/src/EllieBot/Modules/Permissions/CommandCooldown/CmdCdsCommands.cs @@ -95,7 +95,7 @@ public partial class Permissions var output = items.Select(x => $"{Format.Code(x.CommandName)}: {x.Seconds}s"); - return _sender.CreateEmbed() + return CreateEmbed() .WithOkColor() .WithDescription(output.Join("\n")); }) diff --git a/src/EllieBot/Modules/Permissions/Filter/FilterCommands.cs b/src/EllieBot/Modules/Permissions/Filter/FilterCommands.cs index fab1a11..87de574 100644 --- a/src/EllieBot/Modules/Permissions/Filter/FilterCommands.cs +++ b/src/EllieBot/Modules/Permissions/Filter/FilterCommands.cs @@ -28,7 +28,7 @@ public partial class Permissions [RequireContext(ContextType.Guild)] public async Task FilterList() { - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .WithTitle("Server filter settings"); @@ -316,7 +316,7 @@ public partial class Permissions .Items(fws) .PageSize(10) .CurrentPage(page) - .Page((items, _) => _sender.CreateEmbed() + .Page((items, _) => CreateEmbed() .WithTitle(GetText(strs.filter_word_list)) .WithDescription(string.Join("\n", items)) .WithOkColor()) diff --git a/src/EllieBot/Modules/Permissions/GlobalPermissions/GlobalPermissionCommands.cs b/src/EllieBot/Modules/Permissions/GlobalPermissions/GlobalPermissionCommands.cs index d3abefd..2647cd8 100644 --- a/src/EllieBot/Modules/Permissions/GlobalPermissions/GlobalPermissionCommands.cs +++ b/src/EllieBot/Modules/Permissions/GlobalPermissions/GlobalPermissionCommands.cs @@ -30,7 +30,7 @@ public partial class Permissions return; } - var embed = _sender.CreateEmbed().WithOkColor(); + var embed = CreateEmbed().WithOkColor(); if (blockedModule.Any()) embed.AddField(GetText(strs.blocked_modules), string.Join("\n", _service.BlockedModules)); diff --git a/src/EllieBot/Modules/Searches/Anime/AnimeSearchCommands.cs b/src/EllieBot/Modules/Searches/Anime/AnimeSearchCommands.cs index 4e95d39..a9a8433 100644 --- a/src/EllieBot/Modules/Searches/Anime/AnimeSearchCommands.cs +++ b/src/EllieBot/Modules/Searches/Anime/AnimeSearchCommands.cs @@ -24,7 +24,7 @@ public partial class Searches return; } - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .WithDescription(animeData.Synopsis.Replace("
", Environment.NewLine, @@ -56,7 +56,7 @@ public partial class Searches return; } - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .WithDescription(mangaData.Synopsis.Replace("
", Environment.NewLine, diff --git a/src/EllieBot/Modules/Searches/Crypto/CryptoCommands.cs b/src/EllieBot/Modules/Searches/Crypto/CryptoCommands.cs index b5dabb3..db314a2 100644 --- a/src/EllieBot/Modules/Searches/Crypto/CryptoCommands.cs +++ b/src/EllieBot/Modules/Searches/Crypto/CryptoCommands.cs @@ -35,7 +35,7 @@ public partial class Searches } var symbol = symbols.First(); - var promptEmbed = _sender.CreateEmbed() + var promptEmbed = CreateEmbed() .WithDescription(symbol.Description) .WithTitle(GetText(strs.did_you_mean(symbol.Symbol))); @@ -67,7 +67,7 @@ public partial class Searches var price = stock.Price.ToString("C2", localCulture); - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor() .WithAuthor(stock.Symbol) .WithUrl($"https://www.tradingview.com/chart/?symbol={stock.Symbol}") @@ -112,7 +112,7 @@ public partial class Searches if (nearest is not null) { - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithTitle(GetText(strs.crypto_not_found)) .WithDescription( GetText(strs.did_you_mean(Format.Bold($"{nearest.Name} ({nearest.Symbol})")))); @@ -145,7 +145,7 @@ public partial class Searches await using var sparkline = await _service.GetSparklineAsync(crypto.Id, usd.PercentChange7d >= 0); var fileName = $"{crypto.Slug}_7d.png"; - var toSend = _sender.CreateEmbed() + var toSend = CreateEmbed() .WithOkColor() .WithAuthor($"#{crypto.CmcRank}") .WithTitle($"{crypto.Name} ({crypto.Symbol})") @@ -198,7 +198,7 @@ public partial class Searches .PageSize(10) .Page((items, _) => { - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor(); if (items.Count > 0) diff --git a/src/EllieBot/Modules/Searches/Feeds/FeedCommands.cs b/src/EllieBot/Modules/Searches/Feeds/FeedCommands.cs index 316fc73..95e83aa 100644 --- a/src/EllieBot/Modules/Searches/Feeds/FeedCommands.cs +++ b/src/EllieBot/Modules/Searches/Feeds/FeedCommands.cs @@ -123,7 +123,7 @@ public partial class Searches if (!feeds.Any()) { await Response() - .Embed(_sender.CreateEmbed().WithOkColor().WithDescription(GetText(strs.feed_no_feed))) + .Embed(CreateEmbed().WithOkColor().WithDescription(GetText(strs.feed_no_feed))) .SendAsync(); return; } @@ -135,7 +135,7 @@ public partial class Searches .CurrentPage(page) .Page((items, cur) => { - var embed = _sender.CreateEmbed().WithOkColor(); + var embed = CreateEmbed().WithOkColor(); var i = 0; var fs = string.Join("\n", items.Select(x => $"`{(cur * 10) + ++i}.` <#{x.ChannelId}> {x.Url}")); diff --git a/src/EllieBot/Modules/Searches/Osu/OsuCommands.cs b/src/EllieBot/Modules/Searches/Osu/OsuCommands.cs index 81f354a..83fa334 100644 --- a/src/EllieBot/Modules/Searches/Osu/OsuCommands.cs +++ b/src/EllieBot/Modules/Searches/Osu/OsuCommands.cs @@ -44,7 +44,7 @@ public partial class Searches await Response() - .Embed(_sender.CreateEmbed() + .Embed(CreateEmbed() .WithOkColor() .WithTitle($"osu! {smode} profile for {user}") .WithThumbnailUrl($"https://a.ppy.sh/{userId}") @@ -78,7 +78,7 @@ public partial class Searches return; } - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .WithTitle($"osu!Gatari {modeStr} profile for {user}") .WithThumbnailUrl($"https://a.gatari.pw/{userStats.Id}") @@ -113,7 +113,7 @@ public partial class Searches var plays = await _service.GetOsuPlay(user, mode); - var eb = _sender.CreateEmbed().WithOkColor().WithTitle($"Top 5 plays for {user}"); + var eb = CreateEmbed().WithOkColor().WithTitle($"Top 5 plays for {user}"); foreach(var (title, desc) in plays) eb.AddField(title, desc); diff --git a/src/EllieBot/Modules/Searches/PokemonSearchCommands.cs b/src/EllieBot/Modules/Searches/PokemonSearchCommands.cs index 6250e87..211d78d 100644 --- a/src/EllieBot/Modules/Searches/PokemonSearchCommands.cs +++ b/src/EllieBot/Modules/Searches/PokemonSearchCommands.cs @@ -25,7 +25,7 @@ public partial class Searches if (kvp.Key.ToUpperInvariant() == pokemon.ToUpperInvariant()) { var p = kvp.Value; - await Response().Embed(_sender.CreateEmbed() + await Response().Embed(CreateEmbed() .WithOkColor() .WithTitle(kvp.Key.ToTitleCase()) .WithDescription(p.BaseStats.ToString()) @@ -55,7 +55,7 @@ public partial class Searches { if (kvp.Key.ToUpperInvariant() == ability) { - await Response().Embed(_sender.CreateEmbed() + await Response().Embed(CreateEmbed() .WithOkColor() .WithTitle(kvp.Value.Name) .WithDescription(string.IsNullOrWhiteSpace(kvp.Value.Desc) diff --git a/src/EllieBot/Modules/Searches/Religious/ReligiousCommands.cs b/src/EllieBot/Modules/Searches/Religious/ReligiousCommands.cs index 074cff5..792b54c 100644 --- a/src/EllieBot/Modules/Searches/Religious/ReligiousCommands.cs +++ b/src/EllieBot/Modules/Searches/Religious/ReligiousCommands.cs @@ -22,7 +22,7 @@ public partial class Searches } await Response() - .Embed(_sender.CreateEmbed() + .Embed(CreateEmbed() .WithOkColor() .WithTitle($"{verse.BookName} {verse.Chapter}:{verse.Verse}") .WithDescription(verse.Text)) @@ -48,7 +48,7 @@ public partial class Searches await using var audio = await http.GetStreamAsync(arabic.Audio); await Response() - .Embed(_sender.CreateEmbed() + .Embed(CreateEmbed() .WithOkColor() .AddField("Arabic", arabic.Text) .AddField("English", english.Text) diff --git a/src/EllieBot/Modules/Searches/Search/SearchCommands.cs b/src/EllieBot/Modules/Searches/Search/SearchCommands.cs index 4bd4d2c..88a40e1 100644 --- a/src/EllieBot/Modules/Searches/Search/SearchCommands.cs +++ b/src/EllieBot/Modules/Searches/Search/SearchCommands.cs @@ -59,14 +59,14 @@ public partial class Searches descStr = descStr.TrimTo(4096); - var embed = _sender.CreateEmbed() - .WithOkColor() - .WithAuthor(ctx.User) - .WithTitle(query.TrimTo(64)!) - .WithDescription(descStr) - .WithFooter( - GetText(strs.results_in(data.Info.TotalResults, data.Info.SearchTime)), - "https://i.imgur.com/G46fm8J.png"); + var embed = CreateEmbed() + .WithOkColor() + .WithAuthor(ctx.User) + .WithTitle(query.TrimTo(64)!) + .WithDescription(descStr) + .WithFooter( + GetText(strs.results_in(data.Info.TotalResults, data.Info.SearchTime)), + "https://i.imgur.com/G46fm8J.png"); await Response().Embed(embed).SendAsync(); } @@ -93,13 +93,13 @@ public partial class Searches return; } - EmbedBuilder CreateEmbed(IImageSearchResultEntry entry) + EmbedBuilder CreateImageEmbed(IImageSearchResultEntry entry) { - return _sender.CreateEmbed() - .WithOkColor() - .WithAuthor(ctx.User) - .WithTitle(query) - .WithImageUrl(entry.Link); + return CreateEmbed() + .WithOkColor() + .WithAuthor(ctx.User) + .WithTitle(query) + .WithImageUrl(entry.Link); } await Response() @@ -112,10 +112,11 @@ public partial class Searches var item = items.FirstOrDefault(); if (item is null) - return _sender.CreateEmbed() - .WithDescription(GetText(strs.no_search_results)); + return CreateEmbed() + .WithPendingColor() + .WithDescription(GetText(strs.no_search_results)); - var embed = CreateEmbed(item); + var embed = CreateImageEmbed(item); return embed; }) @@ -184,7 +185,7 @@ public partial class Searches // // var descStr = string.Join("\n\n", desc); // - // var embed = _sender.CreateEmbed() + // var embed = CreateEmbed() // .WithAuthor(ctx.User.ToString(), // "https://upload.wikimedia.org/wikipedia/en/9/90/The_DuckDuckGo_Duck.png") // .WithDescription($"{GetText(strs.search_for)} **{query}**\n\n" + descStr) diff --git a/src/EllieBot/Modules/Searches/Searches.cs b/src/EllieBot/Modules/Searches/Searches.cs index ac7e60a..de40406 100644 --- a/src/EllieBot/Modules/Searches/Searches.cs +++ b/src/EllieBot/Modules/Searches/Searches.cs @@ -39,7 +39,7 @@ public partial class Searches : EllieModule if (!await ValidateQuery(query)) return; - var embed = _sender.CreateEmbed(); + var embed = CreateEmbed(); var data = await _service.GetWeatherDataAsync(query); if (data is null) @@ -102,7 +102,7 @@ public partial class Searches : EllieModule return; } - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.time_new)) .WithDescription(Format.Code(data.Time.ToString(Culture))) @@ -128,7 +128,7 @@ public partial class Searches : EllieModule } await Response() - .Embed(_sender.CreateEmbed() + .Embed(CreateEmbed() .WithOkColor() .WithTitle(movie.Title) .WithUrl($"https://www.imdb.com/title/{movie.ImdbId}/") @@ -161,7 +161,7 @@ public partial class Searches : EllieModule private Task InternalRandomImage(SearchesService.ImageTag tag) { var url = _service.GetRandomImageUrl(tag); - return Response().Embed(_sender.CreateEmbed().WithOkColor().WithImageUrl(url)).SendAsync(); + return Response().Embed(CreateEmbed().WithOkColor().WithImageUrl(url)).SendAsync(); } [Cmd] @@ -190,7 +190,7 @@ public partial class Searches : EllieModule } await Response() - .Embed(_sender.CreateEmbed() + .Embed(CreateEmbed() .WithOkColor() .AddField(GetText(strs.original_url), $"<{query}>") .AddField(GetText(strs.short_url), $"<{shortLink}>")) @@ -213,7 +213,7 @@ public partial class Searches : EllieModule return; } - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .WithTitle(card.Name) .WithDescription(card.Description) @@ -246,7 +246,7 @@ public partial class Searches : EllieModule return; } - var embed = _sender.CreateEmbed().WithOkColor().WithImageUrl(card.Img); + var embed = CreateEmbed().WithOkColor().WithImageUrl(card.Img); if (!string.IsNullOrWhiteSpace(card.Flavor)) embed.WithDescription(card.Flavor); @@ -280,7 +280,7 @@ public partial class Searches : EllieModule .Page((items, _) => { var item = items[0]; - return _sender.CreateEmbed() + return CreateEmbed() .WithOkColor() .WithUrl(item.Permalink) .WithTitle(item.Word) @@ -311,7 +311,7 @@ public partial class Searches : EllieModule .Page((items, _) => { var model = items.First(); - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithDescription(ctx.User.Mention) .AddField(GetText(strs.word), model.Word, true) .AddField(GetText(strs._class), model.WordType, true) @@ -374,7 +374,7 @@ public partial class Searches : EllieModule } [Cmd] - public async Task Color(params Color[] colors) + public async Task Color(params Rgba32[] colors) { if (!colors.Any()) return; @@ -403,7 +403,7 @@ public partial class Searches : EllieModule await Response() .Embed( - _sender.CreateEmbed() + CreateEmbed() .WithOkColor() .AddField("Username", usr.ToString()) .AddField("Avatar Url", avatarUrl) diff --git a/src/EllieBot/Modules/Searches/StreamNotification/StreamNotificationCommands.cs b/src/EllieBot/Modules/Searches/StreamNotification/StreamNotificationCommands.cs index ed260ae..a10c38c 100644 --- a/src/EllieBot/Modules/Searches/StreamNotification/StreamNotificationCommands.cs +++ b/src/EllieBot/Modules/Searches/StreamNotification/StreamNotificationCommands.cs @@ -79,9 +79,9 @@ public partial class Searches .Page((elements, cur) => { if (elements.Count == 0) - return _sender.CreateEmbed().WithDescription(GetText(strs.streams_none)).WithErrorColor(); + return CreateEmbed().WithDescription(GetText(strs.streams_none)).WithErrorColor(); - var eb = _sender.CreateEmbed().WithTitle(GetText(strs.streams_follow_title)).WithOkColor(); + var eb = CreateEmbed().WithTitle(GetText(strs.streams_follow_title)).WithOkColor(); for (var index = 0; index < elements.Count; index++) { var elem = elements[index]; diff --git a/src/EllieBot/Modules/Searches/StreamNotification/StreamNotificationService.cs b/src/EllieBot/Modules/Searches/StreamNotification/StreamNotificationService.cs index 9870c13..24178c0 100644 --- a/src/EllieBot/Modules/Searches/StreamNotification/StreamNotificationService.cs +++ b/src/EllieBot/Modules/Searches/StreamNotification/StreamNotificationService.cs @@ -491,7 +491,7 @@ public sealed class StreamNotificationService : IEService, IReadyExecutor public EmbedBuilder GetEmbed(ulong guildId, StreamData status, bool showViewers = true) { - var embed = _sender.CreateEmbed() + var embed = _sender.CreateEmbed(guildId) .WithTitle(status.Name) .WithUrl(status.StreamUrl) .WithDescription(status.StreamUrl) diff --git a/src/EllieBot/Modules/Searches/Translate/FlagTranslateService.cs b/src/EllieBot/Modules/Searches/Translate/FlagTranslateService.cs index 2b5baa5..ffb7413 100644 --- a/src/EllieBot/Modules/Searches/Translate/FlagTranslateService.cs +++ b/src/EllieBot/Modules/Searches/Translate/FlagTranslateService.cs @@ -135,7 +135,7 @@ public sealed partial class FlagTranslateService : IReadyExecutor, IEService var response = await _ts.Translate("", lang, msg.Content).ConfigureAwait(false); - await msg.ReplyAsync(embed: _sender.CreateEmbed() + await msg.ReplyAsync(embed: _sender.CreateEmbed(tc.Guild?.Id) .WithOkColor() .WithFooter(user.ToString() ?? reaction.UserId.ToString(), user.RealAvatarUrl().ToString()) diff --git a/src/EllieBot/Modules/Searches/Translate/TranslateService.cs b/src/EllieBot/Modules/Searches/Translate/TranslateService.cs index 22e4338..bfc413f 100644 --- a/src/EllieBot/Modules/Searches/Translate/TranslateService.cs +++ b/src/EllieBot/Modules/Searches/Translate/TranslateService.cs @@ -67,7 +67,7 @@ public sealed class TranslateService : ITranslateService, IExecNoCommand, IReady || msg.Content.Equals(output, StringComparison.InvariantCultureIgnoreCase)) return; - var embed = _sender.CreateEmbed().WithOkColor(); + var embed = _sender.CreateEmbed(guild?.Id).WithOkColor(); if (autoDelete) { diff --git a/src/EllieBot/Modules/Searches/Translate/TranslatorCommands.cs b/src/EllieBot/Modules/Searches/Translate/TranslatorCommands.cs index b1cf524..98037a5 100644 --- a/src/EllieBot/Modules/Searches/Translate/TranslatorCommands.cs +++ b/src/EllieBot/Modules/Searches/Translate/TranslatorCommands.cs @@ -28,7 +28,7 @@ public partial class Searches await ctx.Channel.TriggerTypingAsync(); var translation = await _service.Translate(fromLang, toLang, text); - var embed = _sender.CreateEmbed().WithOkColor().AddField(fromLang, text).AddField(toLang, translation); + var embed = CreateEmbed().WithOkColor().AddField(fromLang, text).AddField(toLang, translation); await Response().Embed(embed).SendAsync(); } @@ -88,7 +88,7 @@ public partial class Searches { var langs = _service.GetLanguages().ToList(); - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithTitle(GetText(strs.supported_languages)) .WithOkColor(); diff --git a/src/EllieBot/Modules/Searches/XkcdCommands.cs b/src/EllieBot/Modules/Searches/XkcdCommands.cs index d913a87..8641050 100644 --- a/src/EllieBot/Modules/Searches/XkcdCommands.cs +++ b/src/EllieBot/Modules/Searches/XkcdCommands.cs @@ -25,7 +25,7 @@ public partial class Searches using var http = _httpFactory.CreateClient(); var res = await http.GetStringAsync($"{XKCD_URL}/info.0.json"); var comic = JsonConvert.DeserializeObject(res); - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .WithImageUrl(comic.ImageLink) .WithAuthor(comic.Title, "https://xkcd.com/s/919f27.ico", $"{XKCD_URL}/{comic.Num}") @@ -60,7 +60,7 @@ public partial class Searches var res = await http.GetStringAsync($"{XKCD_URL}/{num}/info.0.json"); var comic = JsonConvert.DeserializeObject(res); - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .WithImageUrl(comic.ImageLink) .WithAuthor(comic.Title, "https://xkcd.com/s/919f27.ico", $"{XKCD_URL}/{num}") diff --git a/src/EllieBot/Modules/Searches/_common/StreamNotifications/Providers/TwitchHelixProvider.cs b/src/EllieBot/Modules/Searches/_common/StreamNotifications/Providers/TwitchHelixProvider.cs index 4dd5657..660cef4 100644 --- a/src/EllieBot/Modules/Searches/_common/StreamNotifications/Providers/TwitchHelixProvider.cs +++ b/src/EllieBot/Modules/Searches/_common/StreamNotifications/Providers/TwitchHelixProvider.cs @@ -5,48 +5,46 @@ using JsonSerializer = System.Text.Json.JsonSerializer; namespace EllieBot.Modules.Searches.Common.StreamNotifications.Providers; -public sealed class YoutubeProvide : Provider -{ - private readonly IGoogleApiService _api; - private readonly IHttpClientFactory _httpFactory; - - public override FollowedStream.FType Platform - => FollowedStream.FType.Youtube; - - public YoutubeProvide(IGoogleApiService api, IHttpClientFactory httpFactory) - { - _api = api; - _httpFactory = httpFactory; - } - - public override async Task IsValidUrl(string url) - { - await Task.Yield(); - // todo implement - return url.Contains("youtube.com"); - } - - public override Task GetStreamDataByUrlAsync(string url) - { - return default; - } - - public override Task GetStreamDataAsync(string login) - { - var client = _httpFactory.CreateClient(); - - client.GetAsync(); - - - return default; - } - - public override Task> GetStreamDataAsync(List usernames) - { - return default; - } -} - +// public sealed class YoutubeProvide : Provider +// { +// private readonly IGoogleApiService _api; +// private readonly IHttpClientFactory _httpFactory; +// +// public override FollowedStream.FType Platform +// => FollowedStream.FType.Youtube; +// +// public YoutubeProvide(IGoogleApiService api, IHttpClientFactory httpFactory) +// { +// _api = api; +// _httpFactory = httpFactory; +// } +// +// public override async Task IsValidUrl(string url) +// { +// await Task.Yield(); +// return url.Contains("youtube.com"); +// } +// +// public override Task GetStreamDataByUrlAsync(string url) +// { +// return default; +// } +// +// public override Task GetStreamDataAsync(string login) +// { +// var client = _httpFactory.CreateClient(); +// +// client.GetAsync() +// +// return default; +// } +// +// public override Task> GetStreamDataAsync(List usernames) +// { +// return default; +// } +// } +// public sealed class TwitchHelixProvider : Provider { private readonly IHttpClientFactory _httpClientFactory; diff --git a/src/EllieBot/Modules/Utility/Ai/AiAssistantService.cs b/src/EllieBot/Modules/Utility/Ai/AiAssistantService.cs index 512c2db..e896ea5 100644 --- a/src/EllieBot/Modules/Utility/Ai/AiAssistantService.cs +++ b/src/EllieBot/Modules/Utility/Ai/AiAssistantService.cs @@ -164,8 +164,8 @@ public sealed class AiAssistantService funcs.Add(new() { Name = cmd, - Desc = commandStrings?.Desc?.Replace("currency", "flowers") ?? string.Empty, - Params = commandStrings?.Params.FirstOrDefault() + Desc = commandStrings.Desc?.Replace("currency", "flowers") ?? string.Empty, + Params = commandStrings.Params.FirstOrDefault() ?.Select(x => new AiCommandParamModel() { Desc = x.Value.Desc, @@ -219,6 +219,9 @@ public sealed class AiAssistantService ITextChannel channel, string query) { + if (guild is not SocketGuild sg) + return false; + // check permissions var pcResult = await _permChecker.CheckPermsAsync( guild, @@ -239,9 +242,6 @@ public sealed class AiAssistantService { if (model.Name == ".ai_chat") { - if (guild is not SocketGuild sg) - return false; - var sess = _cbs.GetOrCreateSession(guild.Id); if (sess is null) return false; @@ -253,7 +253,7 @@ public sealed class AiAssistantService var commandString = GetCommandString(model); var msgTask = _sender.Response(channel) - .Embed(_sender.CreateEmbed() + .Embed(_sender.CreateEmbed(guild?.Id) .WithOkColor() .WithAuthor(msg.Author.GlobalName, msg.Author.RealAvatarUrl().ToString()) @@ -261,8 +261,7 @@ public sealed class AiAssistantService .SendAsync(); - await _cmdHandler.TryRunCommand( - (SocketGuild)guild, + await _cmdHandler.TryRunCommand(sg, (ISocketMessageChannel)channel, new DoAsUserMessage((SocketUserMessage)msg, msg.Author, commandString)); diff --git a/src/EllieBot/Modules/Utility/Ai/AiCommandModel.cs b/src/EllieBot/Modules/Utility/Ai/AiCommandModel.cs index eeaf38b..17a8730 100644 --- a/src/EllieBot/Modules/Utility/Ai/AiCommandModel.cs +++ b/src/EllieBot/Modules/Utility/Ai/AiCommandModel.cs @@ -8,7 +8,7 @@ public sealed class AiCommandModel public required string Name { get; set; } [JsonPropertyName("desc")] - public required string Desc { get; set; } + public required string? Desc { get; set; } [JsonPropertyName("params")] public required IReadOnlyList Params { get; set; } diff --git a/src/EllieBot/Modules/Utility/Alias/AliasCommands.cs b/src/EllieBot/Modules/Utility/Alias/AliasCommands.cs index 7a4641d..23724d1 100644 --- a/src/EllieBot/Modules/Utility/Alias/AliasCommands.cs +++ b/src/EllieBot/Modules/Utility/Alias/AliasCommands.cs @@ -127,7 +127,7 @@ public partial class Utility .CurrentPage(page) .Page((items, _) => { - return _sender.CreateEmbed() + return CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.alias_list)) .WithDescription(string.Join("\n", items.Select(x => $"`{x.Key}` => `{x.Value}`"))); diff --git a/src/EllieBot/Modules/Utility/ConfigCommands.cs b/src/EllieBot/Modules/Utility/ConfigCommands.cs index 57b8f4c..9d8c949 100644 --- a/src/EllieBot/Modules/Utility/ConfigCommands.cs +++ b/src/EllieBot/Modules/Utility/ConfigCommands.cs @@ -20,7 +20,7 @@ public partial class Utility if (setting is null) { var configNames = _settingServices.Select(x => x.Name); - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithErrorColor() .WithDescription(GetText(strs.config_not_found(Format.Code(name)))) .AddField(GetText(strs.config_list), string.Join("\n", configNames)); @@ -43,7 +43,7 @@ public partial class Utility name = name?.ToLowerInvariant(); if (string.IsNullOrWhiteSpace(name)) { - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.config_list)) .WithDescription(string.Join("\n", configNames)); @@ -58,7 +58,7 @@ public partial class Utility // if config name is not found, print error and the list of configs if (setting is null) { - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithErrorColor() .WithDescription(GetText(strs.config_not_found(Format.Code(name)))) .AddField(GetText(strs.config_list), string.Join("\n", configNames)); @@ -75,7 +75,7 @@ public partial class Utility if (string.IsNullOrWhiteSpace(prop)) { var propStrings = GetPropsAndValuesString(setting, propNames); - var embed = _sender.CreateEmbed().WithOkColor().WithTitle($"⚙️ {setting.Name}").WithDescription(propStrings); + var embed = CreateEmbed().WithOkColor().WithTitle($"⚙️ {setting.Name}").WithDescription(propStrings); await Response().Embed(embed).SendAsync(); @@ -88,7 +88,7 @@ public partial class Utility if (!exists) { var propStrings = GetPropsAndValuesString(setting, propNames); - var propErrorEmbed = _sender.CreateEmbed() + var propErrorEmbed = CreateEmbed() .WithErrorColor() .WithDescription(GetText( strs.config_prop_not_found(Format.Code(prop), Format.Code(name)))) @@ -110,7 +110,7 @@ public partial class Utility if (prop != "currency.sign") value = Format.Code(Format.Sanitize(value.TrimTo(1000)), "json"); - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .AddField("Config", Format.Code(setting.Name), true) .AddField("Prop", Format.Code(prop), true) diff --git a/src/EllieBot/Modules/Utility/Giveaway/GiveawayCommands.cs b/src/EllieBot/Modules/Utility/Giveaway/GiveawayCommands.cs index 2109eef..dd847d1 100644 --- a/src/EllieBot/Modules/Utility/Giveaway/GiveawayCommands.cs +++ b/src/EllieBot/Modules/Utility/Giveaway/GiveawayCommands.cs @@ -17,7 +17,7 @@ public partial class Utility return; } - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithPendingColor() .WithTitle(GetText(strs.giveaway_starting)) .WithDescription(message); @@ -103,7 +103,7 @@ public partial class Utility return; } - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithTitle(GetText(strs.giveaway_list)) .WithOkColor(); diff --git a/src/EllieBot/Modules/Utility/Giveaway/GiveawayService.cs b/src/EllieBot/Modules/Utility/Giveaway/GiveawayService.cs index 0a0cf51..0c2f14e 100644 --- a/src/EllieBot/Modules/Utility/Giveaway/GiveawayService.cs +++ b/src/EllieBot/Modules/Utility/Giveaway/GiveawayService.cs @@ -20,8 +20,14 @@ public sealed class GiveawayService : IEService, IReadyExecutor private SortedSet _giveawayCache = new SortedSet(); private readonly EllieRandom _rng; - public GiveawayService(DbService db, IBotCreds creds, DiscordSocketClient client, - IMessageSenderService sender, IBotStrings strings, ILocalization localization, IMemoryCache cache) + public GiveawayService( + DbService db, + IBotCreds creds, + DiscordSocketClient client, + IMessageSenderService sender, + IBotStrings strings, + ILocalization localization, + IMemoryCache cache) { _db = db; _creds = creds; @@ -37,7 +43,8 @@ public sealed class GiveawayService : IEService, IReadyExecutor _client.ReactionRemoved += OnReactionRemoved; } - private async Task OnReactionRemoved(Cacheable msg, + private async Task OnReactionRemoved( + Cacheable msg, Cacheable arg2, SocketReaction r) { @@ -55,7 +62,9 @@ public sealed class GiveawayService : IEService, IReadyExecutor } } - private async Task OnReactionAdded(Cacheable msg, Cacheable ch, + private async Task OnReactionAdded( + Cacheable msg, + Cacheable ch, SocketReaction r) { if (!r.User.IsSpecified) @@ -84,9 +93,9 @@ public sealed class GiveawayService : IEService, IReadyExecutor await using var ctx = _db.GetDbContext(); var gas = await ctx - .GetTable() - .Where(x => Linq2DbExpressions.GuildOnShard(x.GuildId, _creds.TotalShards, _client.ShardId)) - .ToArrayAsync(); + .GetTable() + .Where(x => Linq2DbExpressions.GuildOnShard(x.GuildId, _creds.TotalShards, _client.ShardId)) + .ToArrayAsync(); lock (_giveawayCache) { @@ -101,8 +110,8 @@ public sealed class GiveawayService : IEService, IReadyExecutor lock (_giveawayCache) { toEnd = _giveawayCache.TakeWhile( - x => x.EndsAt <= DateTime.UtcNow.AddSeconds(15)) - .ToArray(); + x => x.EndsAt <= DateTime.UtcNow.AddSeconds(15)) + .ToArray(); } foreach (var ga in toEnd) @@ -119,29 +128,33 @@ public sealed class GiveawayService : IEService, IReadyExecutor } } - public async Task StartGiveawayAsync(ulong guildId, ulong channelId, ulong messageId, TimeSpan duration, + public async Task StartGiveawayAsync( + ulong guildId, + ulong channelId, + ulong messageId, + TimeSpan duration, string message) { await using var ctx = _db.GetDbContext(); // first check if there are more than 5 giveaways var count = await ctx - .GetTable() - .CountAsync(x => x.GuildId == guildId); + .GetTable() + .CountAsync(x => x.GuildId == guildId); if (count >= 5) return null; var endsAt = DateTime.UtcNow + duration; var ga = await ctx.GetTable() - .InsertWithOutputAsync(() => new GiveawayModel - { - GuildId = guildId, - MessageId = messageId, - ChannelId = channelId, - Message = message, - EndsAt = endsAt, - }); + .InsertWithOutputAsync(() => new GiveawayModel + { + GuildId = guildId, + MessageId = messageId, + ChannelId = channelId, + Message = message, + EndsAt = endsAt, + }); lock (_giveawayCache) { @@ -157,18 +170,18 @@ public sealed class GiveawayService : IEService, IReadyExecutor await using var ctx = _db.GetDbContext(); var giveaway = await ctx - .GetTable() - .Where(x => x.GuildId == guildId && x.Id == id) - .LoadWith(x => x.Participants) - .FirstOrDefaultAsyncLinqToDB(); + .GetTable() + .Where(x => x.GuildId == guildId && x.Id == id) + .LoadWith(x => x.Participants) + .FirstOrDefaultAsyncLinqToDB(); if (giveaway is null) return false; await ctx - .GetTable() - .Where(x => x.Id == id) - .DeleteAsync(); + .GetTable() + .Where(x => x.Id == id) + .DeleteAsync(); lock (_giveawayCache) { @@ -222,9 +235,9 @@ public sealed class GiveawayService : IEService, IReadyExecutor await using var ctx = _db.GetDbContext(); var ga = await ctx - .GetTable() - .Where(x => x.GuildId == guildId && x.Id == id) - .DeleteWithOutputAsync(); + .GetTable() + .Where(x => x.GuildId == guildId && x.Id == id) + .DeleteWithOutputAsync(); if (ga is not { Length: > 0 }) return false; @@ -242,9 +255,9 @@ public sealed class GiveawayService : IEService, IReadyExecutor await using var ctx = _db.GetDbContext(); return await ctx - .GetTable() - .Where(x => x.GuildId == guildId) - .ToListAsync(); + .GetTable() + .Where(x => x.GuildId == guildId) + .ToListAsync(); } public async Task JoinGivawayAsync(ulong messageId, ulong userId, string userName) @@ -252,23 +265,23 @@ public sealed class GiveawayService : IEService, IReadyExecutor await using var ctx = _db.GetDbContext(); var giveaway = await ctx - .GetTable() - .Where(x => x.MessageId == messageId) - .FirstOrDefaultAsyncLinqToDB(); + .GetTable() + .Where(x => x.MessageId == messageId) + .FirstOrDefaultAsyncLinqToDB(); if (giveaway is null) return false; // add the user to the database await ctx.GetTable() - .InsertAsync( - () => new GiveawayUser() - { - UserId = userId, - GiveawayId = giveaway.Id, - Name = userName, - } - ); + .InsertAsync( + () => new GiveawayUser() + { + UserId = userId, + GiveawayId = giveaway.Id, + Name = userName, + } + ); return true; } @@ -278,17 +291,17 @@ public sealed class GiveawayService : IEService, IReadyExecutor await using var ctx = _db.GetDbContext(); var giveaway = await ctx - .GetTable() - .Where(x => x.MessageId == messageId) - .FirstOrDefaultAsyncLinqToDB(); + .GetTable() + .Where(x => x.MessageId == messageId) + .FirstOrDefaultAsyncLinqToDB(); if (giveaway is null) return false; await ctx - .GetTable() - .Where(x => x.UserId == userId && x.GiveawayId == giveaway.Id) - .DeleteAsync(); + .GetTable() + .Where(x => x.UserId == userId && x.GiveawayId == giveaway.Id) + .DeleteAsync(); return true; } @@ -316,14 +329,14 @@ public sealed class GiveawayService : IEService, IReadyExecutor {Format.Code(winner.UserId.ToString())} """; - var eb = _sender.CreateEmbed() - .WithOkColor() - .WithTitle(GetText(strs.giveaway_ended)) - .WithDescription(ga.Message) - .WithFooter($"id: {new kwum(ga.Id).ToString()}") - .AddField(GetText(strs.winner), - winnerStr, - true); + var eb = _sender.CreateEmbed(ch.GuildId) + .WithOkColor() + .WithTitle(GetText(strs.giveaway_ended)) + .WithDescription(ga.Message) + .WithFooter($"id: {new kwum(ga.Id).ToString()}") + .AddField(GetText(strs.winner), + winnerStr, + true); try { diff --git a/src/EllieBot/Modules/Utility/GuildColorsCommands.cs b/src/EllieBot/Modules/Utility/GuildColorsCommands.cs index 7f787e6..da17070 100644 --- a/src/EllieBot/Modules/Utility/GuildColorsCommands.cs +++ b/src/EllieBot/Modules/Utility/GuildColorsCommands.cs @@ -1,39 +1,66 @@ -using EllieBot.Db.Models; +using SixLabors.ImageSharp.PixelFormats; namespace EllieBot.Modules.Utility; -public interface IGuildColorsService -{ - -} - -public sealed class GuildColorsService : IGuildColorsService, IEService -{ - private readonly DbService _db; - - public GuildColorsService(DbService db) - { - _db = db; - } - - public async Task GetGuildColors(ulong guildId) - { - // get from database and cache it with linq2db - - await using var ctx = _db.GetDbContext(); - - return null; - // return await ctx - // .GuildColors - // .FirstOrDefaultAsync(x => x.GuildId == guildId); - - } -} - public partial class Utility { + [Group("sclr")] public class GuildColorsCommands : EllieModule { - + [Cmd] + [UserPerm(GuildPerm.ManageGuild)] + [RequireContext(ContextType.Guild)] + public async Task ServerColorsShow() + { + EmbedBuilder[] ebs = + [ + CreateEmbed() + .WithOkColor() + .WithDescription("\\✅"), + CreateEmbed() + .WithPendingColor() + .WithDescription("\\⏳\\⚠️"), + CreateEmbed() + .WithErrorColor() + .WithDescription("\\❌") + ]; + + await Response() + .Embeds(ebs) + .SendAsync(); + } + + [Cmd] + [UserPerm(GuildPerm.ManageGuild)] + [RequireContext(ContextType.Guild)] + public async Task ServerColorOk([Leftover] Rgba32? color = null) + { + await _service.SetOkColor(ctx.Guild.Id, color); + + await Response().Confirm(strs.server_color_set).SendAsync(); + await ServerColorsShow(); + } + + [Cmd] + [UserPerm(GuildPerm.ManageGuild)] + [RequireContext(ContextType.Guild)] + public async Task ServerColorPending([Leftover] Rgba32? color = null) + { + await _service.SetPendingColor(ctx.Guild.Id, color); + + await Response().Confirm(strs.server_color_set).SendAsync(); + await ServerColorsShow(); + } + + [Cmd] + [UserPerm(GuildPerm.ManageGuild)] + [RequireContext(ContextType.Guild)] + public async Task ServerColorError([Leftover] Rgba32? color = null) + { + await _service.SetErrorColor(ctx.Guild.Id, color); + + await Response().Confirm(strs.server_color_set).SendAsync(); + await ServerColorsShow(); + } } } \ No newline at end of file diff --git a/src/EllieBot/Modules/Utility/Info/InfoCommands.cs b/src/EllieBot/Modules/Utility/Info/InfoCommands.cs index 2640e76..c9d4ab2 100644 --- a/src/EllieBot/Modules/Utility/Info/InfoCommands.cs +++ b/src/EllieBot/Modules/Utility/Info/InfoCommands.cs @@ -48,7 +48,7 @@ public partial class Utility if (string.IsNullOrWhiteSpace(features)) features = "-"; - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithAuthor(GetText(strs.server_info)) .WithTitle(guild.Name) .AddField(GetText(strs.id), guild.Id.ToString(), true) @@ -81,7 +81,7 @@ public partial class Utility return; var createdAt = new DateTime(2015, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(ch.Id >> 22); var usercount = (await ch.GetUsersAsync().FlattenAsync()).Count(); - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithTitle(ch.Name) .WithDescription(ch.Topic?.SanitizeMentions(true)) .AddField(GetText(strs.id), ch.Id.ToString(), true) @@ -101,7 +101,7 @@ public partial class Utility var createdAt = new DateTime(2015, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc) .AddMilliseconds(role.Id >> 22); var usercount = role.Members.LongCount(); - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithTitle(role.Name.TrimTo(128)) .WithDescription(role.Permissions.ToList().Join(" | ")) .AddField(GetText(strs.id), role.Id.ToString(), true) @@ -129,7 +129,7 @@ public partial class Utility if (user is null) return; - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .AddField(GetText(strs.name), $"**{user.Username}**#{user.Discriminator}", true); if (!string.IsNullOrWhiteSpace(user.Nickname)) embed.AddField(GetText(strs.nickname), user.Nickname, true); diff --git a/src/EllieBot/Modules/Utility/Invite/InviteCommands.cs b/src/EllieBot/Modules/Utility/Invite/InviteCommands.cs index f9174ae..dd9e796 100644 --- a/src/EllieBot/Modules/Utility/Invite/InviteCommands.cs +++ b/src/EllieBot/Modules/Utility/Invite/InviteCommands.cs @@ -47,9 +47,9 @@ public partial class Utility var i = 1; if (!invs.Any()) - return _sender.CreateEmbed().WithErrorColor().WithDescription(GetText(strs.no_invites)); + return CreateEmbed().WithErrorColor().WithDescription(GetText(strs.no_invites)); - var embed = _sender.CreateEmbed().WithOkColor(); + var embed = CreateEmbed().WithOkColor(); foreach (var inv in invs) { var expiryString = inv.MaxAge is null or 0 || inv.CreatedAt is null diff --git a/src/EllieBot/Modules/Utility/Quote/QuoteCommands.cs b/src/EllieBot/Modules/Utility/Quote/QuoteCommands.cs index a50cd19..afc172d 100644 --- a/src/EllieBot/Modules/Utility/Quote/QuoteCommands.cs +++ b/src/EllieBot/Modules/Utility/Quote/QuoteCommands.cs @@ -147,7 +147,7 @@ public partial class Utility private async Task ShowQuoteData(Quote quote) { var inter = CreateEditInteraction(quote.Id, quote); - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor() .WithTitle($"{GetText(strs.quote_id($"`{new kwum(quote.Id)}"))}`") .WithDescription(Format.Sanitize(quote.Text).Replace("](", "]\\(").TrimTo(4096)) @@ -188,7 +188,7 @@ public partial class Utility var text = quote.Keyword.ToLowerInvariant() + ": " + quote.Text; - return _sender.CreateEmbed() + return CreateEmbed() .WithOkColor() .WithTitle($"{new kwum(quote.Id)} 💬 ") .WithDescription(text); @@ -266,7 +266,7 @@ public partial class Utility if (q is not null) { await Response() - .Embed(_sender.CreateEmbed() + .Embed(CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.quote_edited)) .WithDescription($"#{quoteId}") diff --git a/src/EllieBot/Modules/Utility/Remind/RemindCommands.cs b/src/EllieBot/Modules/Utility/Remind/RemindCommands.cs index b568ada..a575e20 100644 --- a/src/EllieBot/Modules/Utility/Remind/RemindCommands.cs +++ b/src/EllieBot/Modules/Utility/Remind/RemindCommands.cs @@ -97,7 +97,7 @@ public partial class Utility if (--page < 0) return; - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .WithTitle(GetText(guildId is not null ? strs.reminder_server_list diff --git a/src/EllieBot/Modules/Utility/Remind/RemindService.cs b/src/EllieBot/Modules/Utility/Remind/RemindService.cs index 0d91498..3c004c6 100644 --- a/src/EllieBot/Modules/Utility/Remind/RemindService.cs +++ b/src/EllieBot/Modules/Utility/Remind/RemindService.cs @@ -211,7 +211,7 @@ public class RemindService : IEService, IReadyExecutor, IRemindService else { await res - .Embed(_sender.CreateEmbed() + .Embed(_sender.CreateEmbed(r.ServerId) .WithOkColor() .WithTitle("Reminder") .AddField("Created At", diff --git a/src/EllieBot/Modules/Utility/Repeater/RepeatCommands.cs b/src/EllieBot/Modules/Utility/Repeater/RepeatCommands.cs index e2060d4..4517b9b 100644 --- a/src/EllieBot/Modules/Utility/Repeater/RepeatCommands.cs +++ b/src/EllieBot/Modules/Utility/Repeater/RepeatCommands.cs @@ -64,7 +64,7 @@ public partial class Utility } var description = GetRepeaterInfoString(removed); - await Response().Embed(_sender.CreateEmbed() + await Response().Embed(CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.repeater_removed(index + 1))) .WithDescription(description)).SendAsync(); @@ -187,7 +187,7 @@ public partial class Utility } var description = GetRepeaterInfoString(runner); - await Response().Embed(_sender.CreateEmbed() + await Response().Embed(CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.repeater_created)) .WithDescription(description)).SendAsync(); @@ -205,7 +205,7 @@ public partial class Utility return; } - var embed = _sender.CreateEmbed().WithTitle(GetText(strs.list_of_repeaters)).WithOkColor(); + var embed = CreateEmbed().WithTitle(GetText(strs.list_of_repeaters)).WithOkColor(); var i = 0; foreach (var runner in repeaters.OrderBy(r => r.Repeater.Id)) diff --git a/src/EllieBot/Modules/Utility/Todo/TodoCommands.cs b/src/EllieBot/Modules/Utility/Todo/TodoCommands.cs index 874fc87..ed941d6 100644 --- a/src/EllieBot/Modules/Utility/Todo/TodoCommands.cs +++ b/src/EllieBot/Modules/Utility/Todo/TodoCommands.cs @@ -51,7 +51,7 @@ public partial class Utility .AddFooter(false) .Page((items, _) => { - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.todo_list)); @@ -95,6 +95,18 @@ public partial class Utility await ctx.OkAsync(); } + [Cmd] + public async Task TodoUncomplete(kwum todoId) + { + if (!await _service.UncompleteTodoAsync(ctx.User.Id, todoId)) + { + await Response().Error(strs.todo_not_found).SendAsync(); + return; + } + + await ctx.OkAsync(); + } + [Cmd] public async Task TodoDelete(kwum todoId) { @@ -175,7 +187,7 @@ public partial class Utility .CurrentPage(page) .Page((items, _) => { - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithTitle(GetText(strs.todo_archive_list)) .WithOkColor(); @@ -206,7 +218,7 @@ public partial class Utility .AddFooter(false) .Page((items, _) => { - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.todo_archived_list)); diff --git a/src/EllieBot/Modules/Utility/Todo/TodoService.cs b/src/EllieBot/Modules/Utility/Todo/TodoService.cs index 38ea848..ab7f3bf 100644 --- a/src/EllieBot/Modules/Utility/Todo/TodoService.cs +++ b/src/EllieBot/Modules/Utility/Todo/TodoService.cs @@ -21,22 +21,23 @@ public sealed class TodoService : IEService await using var ctx = _db.GetDbContext(); if (await ctx - .GetTable() - .Where(x => x.UserId == userId && x.ArchiveId == null) - .CountAsync() >= TODO_MAX_COUNT) + .GetTable() + .Where(x => x.UserId == userId && x.ArchiveId == null) + .CountAsync() + >= TODO_MAX_COUNT) { return TodoAddResult.MaxLimitReached; } await ctx - .GetTable() - .InsertAsync(() => new TodoModel() - { - UserId = userId, - Todo = todo, - DateAdded = DateTime.UtcNow, - IsDone = false, - }); + .GetTable() + .InsertAsync(() => new TodoModel() + { + UserId = userId, + Todo = todo, + DateAdded = DateTime.UtcNow, + IsDone = false, + }); return TodoAddResult.Success; } @@ -45,10 +46,11 @@ public sealed class TodoService : IEService { await using var ctx = _db.GetDbContext(); return await ctx - .GetTable() - .Where(x => x.UserId == userId && x.Id == todoId) - .Set(x => x.Todo, newMessage) - .UpdateAsync() > 0; + .GetTable() + .Where(x => x.UserId == userId && x.Id == todoId) + .Set(x => x.Todo, newMessage) + .UpdateAsync() + > 0; } public async Task GetAllTodosAsync(ulong userId) @@ -56,9 +58,9 @@ public sealed class TodoService : IEService await using var ctx = _db.GetDbContext(); return await ctx - .GetTable() - .Where(x => x.UserId == userId && x.ArchiveId == null) - .ToArrayAsyncLinqToDB(); + .GetTable() + .Where(x => x.UserId == userId && x.ArchiveId == null) + .ToArrayAsyncLinqToDB(); } public async Task CompleteTodoAsync(ulong userId, int todoId) @@ -66,10 +68,23 @@ public sealed class TodoService : IEService await using var ctx = _db.GetDbContext(); var count = await ctx - .GetTable() - .Where(x => x.UserId == userId && x.Id == todoId) - .Set(x => x.IsDone, true) - .UpdateAsync(); + .GetTable() + .Where(x => x.UserId == userId && x.Id == todoId) + .Set(x => x.IsDone, true) + .UpdateAsync(); + + return count > 0; + } + + public async Task UncompleteTodoAsync(ulong userId, int todoId) + { + await using var ctx = _db.GetDbContext(); + + var count = await ctx + .GetTable() + .Where(x => x.UserId == userId && x.Id == todoId) + .Set(x => x.IsDone, false) + .UpdateAsync(); return count > 0; } @@ -79,9 +94,9 @@ public sealed class TodoService : IEService await using var ctx = _db.GetDbContext(); var count = await ctx - .GetTable() - .Where(x => x.UserId == userId && x.Id == todoId) - .DeleteAsync(); + .GetTable() + .Where(x => x.UserId == userId && x.Id == todoId) + .DeleteAsync(); return count > 0; } @@ -91,9 +106,9 @@ public sealed class TodoService : IEService await using var ctx = _db.GetDbContext(); await ctx - .GetTable() - .Where(x => x.UserId == userId && x.ArchiveId == null) - .DeleteAsync(); + .GetTable() + .Where(x => x.UserId == userId && x.ArchiveId == null) + .DeleteAsync(); } public async Task ArchiveTodosAsync(ulong userId, string name) @@ -106,28 +121,28 @@ public sealed class TodoService : IEService // check if the user reached the limit var count = await ctx - .GetTable() - .Where(x => x.UserId == userId) - .CountAsync(); + .GetTable() + .Where(x => x.UserId == userId) + .CountAsync(); if (count >= ARCHIVE_MAX_COUNT) return ArchiveTodoResult.MaxLimitReached; var inserted = await ctx - .GetTable() - .InsertWithOutputAsync(() => new ArchivedTodoListModel() - { - UserId = userId, - Name = name, - }); + .GetTable() + .InsertWithOutputAsync(() => new ArchivedTodoListModel() + { + UserId = userId, + Name = name, + }); // mark all existing todos as archived var updated = await ctx - .GetTable() - .Where(x => x.UserId == userId && x.ArchiveId == null) - .Set(x => x.ArchiveId, inserted.Id) - .UpdateAsync(); + .GetTable() + .Where(x => x.UserId == userId && x.ArchiveId == null) + .Set(x => x.ArchiveId, inserted.Id) + .UpdateAsync(); if (updated == 0) { @@ -140,7 +155,7 @@ public sealed class TodoService : IEService return ArchiveTodoResult.NoTodos; } - + await tr.CommitAsync(); return ArchiveTodoResult.Success; @@ -152,9 +167,9 @@ public sealed class TodoService : IEService await using var ctx = _db.GetDbContext(); return await ctx - .GetTable() - .Where(x => x.UserId == userId) - .ToArrayAsyncLinqToDB(); + .GetTable() + .Where(x => x.UserId == userId) + .ToArrayAsyncLinqToDB(); } public async Task GetArchivedTodoListAsync(ulong userId, int archiveId) @@ -162,10 +177,10 @@ public sealed class TodoService : IEService await using var ctx = _db.GetDbContext(); return await ctx - .GetTable() - .Where(x => x.UserId == userId && x.Id == archiveId) - .LoadWith(x => x.Items) - .FirstOrDefaultAsyncLinqToDB(); + .GetTable() + .Where(x => x.UserId == userId && x.Id == archiveId) + .LoadWith(x => x.Items) + .FirstOrDefaultAsyncLinqToDB(); } public async Task ArchiveDeleteAsync(ulong userId, int archiveId) @@ -173,9 +188,9 @@ public sealed class TodoService : IEService await using var ctx = _db.GetDbContext(); var count = await ctx - .GetTable() - .Where(x => x.UserId == userId && x.Id == archiveId) - .DeleteAsync(); + .GetTable() + .Where(x => x.UserId == userId && x.Id == archiveId) + .DeleteAsync(); return count > 0; } @@ -183,10 +198,10 @@ public sealed class TodoService : IEService public async Task GetTodoAsync(ulong userId, int todoId) { await using var ctx = _db.GetDbContext(); - + return await ctx - .GetTable() - .Where(x => x.UserId == userId && x.Id == todoId) - .FirstOrDefaultAsyncLinqToDB(); + .GetTable() + .Where(x => x.UserId == userId && x.Id == todoId) + .FirstOrDefaultAsyncLinqToDB(); } } \ No newline at end of file diff --git a/src/EllieBot/Modules/Utility/UnitConversion/UnitConversionCommands.cs b/src/EllieBot/Modules/Utility/UnitConversion/UnitConversionCommands.cs index 61ffc54..50bbc2e 100644 --- a/src/EllieBot/Modules/Utility/UnitConversion/UnitConversionCommands.cs +++ b/src/EllieBot/Modules/Utility/UnitConversion/UnitConversionCommands.cs @@ -13,7 +13,7 @@ public partial class Utility { var units = await _service.GetUnitsAsync(); - var embed = _sender.CreateEmbed().WithTitle(GetText(strs.convertlist)).WithOkColor(); + var embed = CreateEmbed().WithTitle(GetText(strs.convertlist)).WithOkColor(); foreach (var g in units.GroupBy(x => x.UnitType)) diff --git a/src/EllieBot/Modules/Utility/Utility.cs b/src/EllieBot/Modules/Utility/Utility.cs index 146a97c..356604a 100644 --- a/src/EllieBot/Modules/Utility/Utility.cs +++ b/src/EllieBot/Modules/Utility/Utility.cs @@ -131,12 +131,12 @@ public partial class Utility : EllieModule { if (names.Count == 0) { - return _sender.CreateEmbed() + return CreateEmbed() .WithErrorColor() .WithDescription(GetText(strs.nobody_playing_game)); } - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor(); var users = names.Join('\n'); @@ -180,11 +180,11 @@ public partial class Utility : EllieModule .Page((pageUsers, _) => { if (pageUsers.Count == 0) - return _sender.CreateEmbed().WithOkColor().WithDescription(GetText(strs.no_user_on_this_page)); + return CreateEmbed().WithOkColor().WithDescription(GetText(strs.no_user_on_this_page)); var roleName = Format.Bold(role?.Name ?? "No Role"); - return _sender.CreateEmbed() + return CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.inrole_list(roleName, roleUsers.Count))) .WithDescription(string.Join("\n", pageUsers)); @@ -327,7 +327,7 @@ public partial class Utility : EllieModule if (string.IsNullOrWhiteSpace(ownerIds)) ownerIds = "-"; - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor() .WithAuthor($"EllieBot v{StatsService.BotVersion}", "https://cdn.elliebot.net/Ellie.png", @@ -583,12 +583,12 @@ public partial class Utility : EllieModule { if (!guilds.Any()) { - return _sender.CreateEmbed() + return CreateEmbed() .WithDescription(GetText(strs.listservers_none)) .WithErrorColor(); } - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor(); foreach (var guild in guilds) embed.AddField(guild.Name, GetText(strs.listservers(guild.Id, guild.MemberCount, guild.OwnerId))); @@ -770,7 +770,7 @@ public partial class Utility : EllieModule var output = result.ReturnValue?.ToString(); if (!string.IsNullOrWhiteSpace(output)) { - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor() .AddField("Code", scriptText) .AddField("Output", output.TrimTo(512)!); @@ -796,7 +796,7 @@ public partial class Utility : EllieModule return; } - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor() .WithDescription(msg.Content) .WithAuthor(msg.Author) diff --git a/src/EllieBot/Modules/Xp/Club/Club.cs b/src/EllieBot/Modules/Xp/Club/Club.cs index 4ce1c57..6ab0fa4 100644 --- a/src/EllieBot/Modules/Xp/Club/Club.cs +++ b/src/EllieBot/Modules/Xp/Club/Club.cs @@ -130,7 +130,7 @@ public partial class Xp .PageSize(10) .Page((users, _) => { - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .WithTitle($"{club}") .WithDescription(GetText(strs.level_x(lvl.Level + $" ({club.Xp} xp)"))) @@ -216,7 +216,7 @@ public partial class Xp { var toShow = string.Join("\n", items.Select(x => x.ToString())); - return _sender.CreateEmbed() + return CreateEmbed() .WithTitle(GetText(strs.club_bans_for(club.ToString()))) .WithDescription(toShow) .WithOkColor(); @@ -245,7 +245,7 @@ public partial class Xp { var toShow = string.Join("\n", items.Select(x => x.ToString())); - return _sender.CreateEmbed() + return CreateEmbed() .WithTitle(GetText(strs.club_apps_for(club.ToString()))) .WithDescription(toShow) .WithOkColor(); @@ -446,7 +446,7 @@ public partial class Xp var clubs = _service.GetClubLeaderboardPage(page); - var embed = _sender.CreateEmbed().WithTitle(GetText(strs.club_leaderboard(page + 1))).WithOkColor(); + var embed = CreateEmbed().WithTitle(GetText(strs.club_leaderboard(page + 1))).WithOkColor(); var i = page * 9; foreach (var club in clubs) @@ -467,7 +467,7 @@ public partial class Xp return; case ClubRenameResult.Success: { - var embed = _sender.CreateEmbed().WithTitle(GetText(strs.club_renamed(clubName))).WithOkColor(); + var embed = CreateEmbed().WithTitle(GetText(strs.club_renamed(clubName))).WithOkColor(); await Response().Embed(embed).SendAsync(); return; } diff --git a/src/EllieBot/Modules/Xp/Xp.cs b/src/EllieBot/Modules/Xp/Xp.cs index 16e9a2f..75f5a64 100644 --- a/src/EllieBot/Modules/Xp/Xp.cs +++ b/src/EllieBot/Modules/Xp/Xp.cs @@ -58,7 +58,7 @@ public partial class Xp : EllieModule var globalSetting = _service.GetNotificationType(ctx.User); var serverSetting = _service.GetNotificationType(ctx.User.Id, ctx.Guild.Id); - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .AddField(GetText(strs.xpn_setting_global), GetNotifLocationString(globalSetting)) .AddField(GetText(strs.xpn_setting_server), GetNotifLocationString(serverSetting)); @@ -153,7 +153,7 @@ public partial class Xp : EllieModule .CurrentPage(0) .Page((items, _) => { - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithTitle(GetText(strs.exclusion_list)) .WithDescription(string.Join('\n', items)) .WithOkColor(); @@ -207,7 +207,7 @@ public partial class Xp : EllieModule .CurrentPage(page) .Page((users, curPage) => { - var embed = _sender.CreateEmbed().WithTitle(GetText(strs.server_leaderboard)).WithOkColor(); + var embed = CreateEmbed().WithTitle(GetText(strs.server_leaderboard)).WithOkColor(); if (!users.Any()) return embed.WithDescription("-"); @@ -265,7 +265,7 @@ public partial class Xp : EllieModule .PageSize(10) .Page((users, curPage) => { - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithOkColor() .WithTitle(GetText(strs.global_leaderboard)); @@ -350,7 +350,7 @@ public partial class Xp : EllieModule [UserPerm(GuildPerm.Administrator)] public async Task XpReset(ulong userId) { - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithTitle(GetText(strs.reset)) .WithDescription(GetText(strs.reset_user_confirm)); @@ -367,7 +367,7 @@ public partial class Xp : EllieModule [UserPerm(GuildPerm.Administrator)] public async Task XpReset() { - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithTitle(GetText(strs.reset)) .WithDescription(GetText(strs.reset_server_confirm)); @@ -445,13 +445,13 @@ public partial class Xp : EllieModule .Page((items, _) => { if (!items.Any()) - return _sender.CreateEmbed() + return CreateEmbed() .WithDescription(GetText(strs.not_found)) .WithErrorColor(); var (key, item) = items.FirstOrDefault(); - var eb = _sender.CreateEmbed() + var eb = CreateEmbed() .WithOkColor() .WithTitle(item.Name) .AddField(GetText(strs.price), diff --git a/src/EllieBot/Modules/Xp/XpRewards.cs b/src/EllieBot/Modules/Xp/XpRewards.cs index 5adc746..1ec3ae2 100644 --- a/src/EllieBot/Modules/Xp/XpRewards.cs +++ b/src/EllieBot/Modules/Xp/XpRewards.cs @@ -16,7 +16,7 @@ public partial class Xp [UserPerm(GuildPerm.Administrator)] public async Task XpRewsReset() { - var promptEmbed = _sender.CreateEmbed() + var promptEmbed = CreateEmbed() .WithPendingColor() .WithDescription(GetText(strs.xprewsreset_confirm)); @@ -73,7 +73,7 @@ public partial class Xp .CurrentPage(page) .Page((items, _) => { - var embed = _sender.CreateEmbed().WithTitle(GetText(strs.level_up_rewards)).WithOkColor(); + var embed = CreateEmbed().WithTitle(GetText(strs.level_up_rewards)).WithOkColor(); if (!items.Any()) return embed.WithDescription(GetText(strs.no_level_up_rewards)); diff --git a/src/EllieBot/_common/Abstractions/Extensions/Extensions.cs b/src/EllieBot/_common/Abstractions/Extensions/Extensions.cs index 1bfc3f3..fad2b93 100644 --- a/src/EllieBot/_common/Abstractions/Extensions/Extensions.cs +++ b/src/EllieBot/_common/Abstractions/Extensions/Extensions.cs @@ -5,5 +5,5 @@ namespace Ellie.Common; public static class Extensions { public static long ToTimestamp(this in DateTime value) - => (value.Ticks 621355968000000000) / 10000000; + => (value.Ticks - 621355968000000000) / 10000000; } \ No newline at end of file diff --git a/src/EllieBot/_common/CleanupModuleBase.cs b/src/EllieBot/_common/CleanupModuleBase.cs index 1e97a66..4f1962b 100644 --- a/src/EllieBot/_common/CleanupModuleBase.cs +++ b/src/EllieBot/_common/CleanupModuleBase.cs @@ -7,7 +7,7 @@ public abstract class CleanupModuleBase : EllieModule { try { - var embed = _sender.CreateEmbed() + var embed = CreateEmbed() .WithTitle(GetText(strs.sql_confirm_exec)) .WithDescription(name); diff --git a/src/EllieBot/_common/EllieModule.cs b/src/EllieBot/_common/EllieModule.cs index 6ae5d91..4e56663 100644 --- a/src/EllieBot/_common/EllieModule.cs +++ b/src/EllieBot/_common/EllieModule.cs @@ -27,6 +27,9 @@ public abstract class EllieModule : ModuleBase protected ICommandContext ctx => Context; + protected EmbedBuilder CreateEmbed() + => _sender.CreateEmbed(ctx.Guild?.Id); + public ResponseBuilder Response() => new ResponseBuilder(Strings, _bcs, (DiscordSocketClient)ctx.Client) .Context(ctx); @@ -121,6 +124,25 @@ public abstract class EllieModule : ModuleBase return true; } + + protected async Task CheckRoleHierarchy(IRole role) + { + var botUser = ((SocketGuild)ctx.Guild).CurrentUser; + var ownerId = ctx.Guild.OwnerId; + var modMaxRole = ((IGuildUser)ctx.User).GetRoles().Max(r => r.Position); + var botMaxRole = botUser.GetRoles().Max(r => r.Position); + + // role must be lower than the bot role + // and the mod must have a higher role + if (botMaxRole <= role.Position + || (ctx.User.Id != ownerId && role.Position >= modMaxRole)) + { + await Response().Error(strs.hierarchy).SendAsync(); + return false; + } + + return true; + } } public abstract class EllieModule : EllieModule diff --git a/src/EllieBot/_common/MessageLink.cs b/src/EllieBot/_common/MessageLink.cs new file mode 100644 index 0000000..fefdb41 --- /dev/null +++ b/src/EllieBot/_common/MessageLink.cs @@ -0,0 +1,7 @@ +namespace EllieBot.Modules.Administration.Services; + +public sealed record class MessageLink(IGuild? Guild, IChannel Channel, IMessage Message) +{ + public override string ToString() + => $"https://discord.com/channels/{(Guild?.Id.ToString() ?? "@me")}/{Channel.Id}/{Message.Id}"; +} \ No newline at end of file diff --git a/src/EllieBot/_common/Sender/IMessageSenderService.cs b/src/EllieBot/_common/Sender/IMessageSenderService.cs index ccc8c0f..41eac79 100644 --- a/src/EllieBot/_common/Sender/IMessageSenderService.cs +++ b/src/EllieBot/_common/Sender/IMessageSenderService.cs @@ -8,5 +8,5 @@ public interface IMessageSenderService ResponseBuilder Response(SocketMessageComponent smc); - EllieEmbedBuilder CreateEmbed(); + EllieEmbedBuilder CreateEmbed(ulong? guildId = null); } \ No newline at end of file diff --git a/src/EllieBot/_common/Sender/MessageSenderService.cs b/src/EllieBot/_common/Sender/MessageSenderService.cs index 88f1c40..0ab3096 100644 --- a/src/EllieBot/_common/Sender/MessageSenderService.cs +++ b/src/EllieBot/_common/Sender/MessageSenderService.cs @@ -1,5 +1,3 @@ -using EllieBot.Common.Configs; - namespace EllieBot.Extensions; public sealed class MessageSenderService : IMessageSenderService, IEService @@ -7,12 +5,18 @@ public sealed class MessageSenderService : IMessageSenderService, IEService private readonly IBotStrings _bs; private readonly BotConfigService _bcs; private readonly DiscordSocketClient _client; + private readonly IGuildColorsService _gcs; - public MessageSenderService(IBotStrings bs, BotConfigService bcs, DiscordSocketClient client) + public MessageSenderService( + IBotStrings bs, + BotConfigService bcs, + DiscordSocketClient client, + IGuildColorsService gcs) { _bs = bs; _bcs = bcs; _client = client; + _gcs = gcs; } @@ -32,25 +36,30 @@ public sealed class MessageSenderService : IMessageSenderService, IEService => new ResponseBuilder(_bs, _bcs, _client) .Channel(smc.Channel); - public EllieEmbedBuilder CreateEmbed() - => new EllieEmbedBuilder(_bcs); + public EllieEmbedBuilder CreateEmbed(ulong? guildId = null) + => new EllieEmbedBuilder(_bcs, guildId is { } gid ? _gcs.GetColors(gid) : null); } public class EllieEmbedBuilder : EmbedBuilder { - private readonly BotConfig _bc; + private readonly Color _okColor; + private readonly Color _errorColor; + private readonly Color _pendingColor; - public EllieEmbedBuilder(BotConfigService bcs) + public EllieEmbedBuilder(BotConfigService bcsData, Colors? guildColors = null) { - _bc = bcs.Data; + var bcColors = bcsData.Data.Color; + _okColor = guildColors?.Ok ?? bcColors.Ok.ToDiscordColor(); + _errorColor = guildColors?.Error ?? bcColors.Error.ToDiscordColor(); + _pendingColor = guildColors?.Pending ?? bcColors.Pending.ToDiscordColor(); } public EmbedBuilder WithOkColor() - => WithColor(_bc.Color.Ok.ToDiscordColor()); + => WithColor(_okColor); public EmbedBuilder WithErrorColor() - => WithColor(_bc.Color.Error.ToDiscordColor()); + => WithColor(_errorColor); public EmbedBuilder WithPendingColor() - => WithColor(_bc.Color.Pending.ToDiscordColor()); + => WithColor(_pendingColor); } \ No newline at end of file diff --git a/src/EllieBot/_common/Services/Impl/CommandsUtilityService.cs b/src/EllieBot/_common/Services/Impl/CommandsUtilityService.cs index ed57096..c5f8373 100644 --- a/src/EllieBot/_common/Services/Impl/CommandsUtilityService.cs +++ b/src/EllieBot/_common/Services/Impl/CommandsUtilityService.cs @@ -39,7 +39,7 @@ public sealed class CommandsUtilityService : ICommandsUtilityService, IEService var culture = _loc.GetCultureInfo(guild); - var em = _sender.CreateEmbed() + var em = _sender.CreateEmbed(guild?.Id) .AddField(str, $"{com.RealSummary(_strings, _marmalades, culture, prefix)}", true); _dpos.TryGetOverrides(guild?.Id ?? 0, com.Name, out var overrides); diff --git a/src/EllieBot/_common/Services/Impl/GuildColorsService.cs b/src/EllieBot/_common/Services/Impl/GuildColorsService.cs new file mode 100644 index 0000000..d1f7618 --- /dev/null +++ b/src/EllieBot/_common/Services/Impl/GuildColorsService.cs @@ -0,0 +1,130 @@ +using AngleSharp.Common; +using LinqToDB; +using LinqToDB.EntityFrameworkCore; +using EllieBot.Common.ModuleBehaviors; +using EllieBot.Db.Models; +using SixLabors.ImageSharp.PixelFormats; + +namespace EllieBot.Services.Impl; + +public sealed class GuildColorsService : IReadyExecutor, IGuildColorsService, IEService +{ + private readonly DbService _db; + private readonly ConcurrentDictionary _colors = new(); + private readonly DiscordSocketClient _client; + private readonly IBotCreds _creds; + + public GuildColorsService(DbService db, DiscordSocketClient client, IBotCreds creds) + { + _db = db; + _client = client; + _creds = creds; + } + + public Colors? GetColors(ulong guildId) + { + if (_colors.TryGetValue(guildId, out var color)) + return color; + + return null; + } + + public async Task SetOkColor(ulong guildId, Rgba32? color) + { + var toInsert = color?.ToHex(); + await _db.GetDbContext() + .GetTable() + .InsertOrUpdateAsync(() => new() + { + GuildId = guildId, + OkColor = toInsert + }, + old => new() + { + OkColor = toInsert + }, + () => new() + { + GuildId = guildId + }); + + if (!_colors.TryAdd(guildId, new Colors(color?.ToDiscordColor(), null, null))) + { + _colors[guildId] = _colors[guildId] with + { + Ok = color?.ToDiscordColor() + }; + } + } + + public async Task SetErrorColor(ulong guildId, Rgba32? color) + { + var toInsert = color?.ToHex(); + await _db.GetDbContext() + .GetTable() + .InsertOrUpdateAsync(() => new() + { + GuildId = guildId, + ErrorColor = toInsert + }, + old => new() + { + ErrorColor = toInsert + }, + () => new() + { + GuildId = guildId + }); + } + + public async Task SetPendingColor(ulong guildId, Rgba32? color) + { + var toInsert = color?.ToHex(); + await _db.GetDbContext() + .GetTable() + .InsertOrUpdateAsync(() => new() + { + GuildId = guildId, + PendingColor = toInsert + }, + old => new() + { + PendingColor = toInsert + }, + () => new() + { + GuildId = guildId + }); + } + + public async Task OnReadyAsync() + { + await using var ctx = _db.GetDbContext(); + var guildColors = await ctx.GetTable() + .Where(x => Linq2DbExpressions.GuildOnShard(x.GuildId, + _creds.TotalShards, + _client.ShardId)) + .ToListAsync(); + + foreach (var color in guildColors) + { + var colors = new Colors( + ConvertColor(color.OkColor), + ConvertColor(color.ErrorColor), + ConvertColor(color.PendingColor)); + + _colors.TryAdd(color.GuildId, colors); + } + } + + private Color? ConvertColor(string? colorErrorColor) + { + if (string.IsNullOrWhiteSpace(colorErrorColor)) + return null; + + if (!Rgba32.TryParseHex(colorErrorColor, out var clr)) + return null; + + return clr.ToDiscordColor(); + } +} diff --git a/src/EllieBot/_common/Services/Impl/IGuildColorsService.cs b/src/EllieBot/_common/Services/Impl/IGuildColorsService.cs new file mode 100644 index 0000000..6369b38 --- /dev/null +++ b/src/EllieBot/_common/Services/Impl/IGuildColorsService.cs @@ -0,0 +1,13 @@ +using SixLabors.ImageSharp.PixelFormats; + +namespace EllieBot.Services; + +public interface IGuildColorsService +{ + Colors? GetColors(ulong guildId); + Task SetOkColor(ulong guildId, Rgba32? color); + Task SetErrorColor(ulong guildId, Rgba32? color); + Task SetPendingColor(ulong guildId, Rgba32? color); +} + +public record struct Colors(Color? Ok, Color? Pending, Color? Error); diff --git a/src/EllieBot/_common/TypeReaders/IEmoteTypeReader.cs b/src/EllieBot/_common/TypeReaders/IEmoteTypeReader.cs new file mode 100644 index 0000000..fccb9a5 --- /dev/null +++ b/src/EllieBot/_common/TypeReaders/IEmoteTypeReader.cs @@ -0,0 +1,27 @@ +using EllieBot.Common.TypeReaders; +using System.Diagnostics.CodeAnalysis; + +namespace EllieBot.Modules.Administration.Services; + +public sealed class EmoteTypeReader : EllieTypeReader +{ + public static bool TryParse(string input, [NotNullWhen(true)] out IEmote? emote) + { + emote = null; + + if (Emoji.TryParse(input, out var emoji)) + emote = emoji; + else if (Emote.TryParse(input, out var emote2)) + emote = emote2; + + return emote is not null; + } + + public override ValueTask> ReadAsync(ICommandContext ctx, string input) + { + if (TryParse(input, out var emote)) + return ValueTask.FromResult>(Discord.Commands.TypeReaderResult.FromSuccess(emote)); + + return ValueTask.FromResult>(Discord.Commands.TypeReaderResult.FromError(CommandError.ParseFailed, "Invalid emote")); + } +} diff --git a/src/EllieBot/_common/TypeReaders/MessageLinkTypeReader.cs b/src/EllieBot/_common/TypeReaders/MessageLinkTypeReader.cs new file mode 100644 index 0000000..a5a5889 --- /dev/null +++ b/src/EllieBot/_common/TypeReaders/MessageLinkTypeReader.cs @@ -0,0 +1,44 @@ +using EllieBot.Common.TypeReaders; +using System.Text.RegularExpressions; + +namespace EllieBot.Modules.Administration.Services; + +public sealed partial class MessageLinkTypeReader : EllieTypeReader +{ + [GeneratedRegex(@"https://discord.com/channels/(?(?:\d+|@me))/(?\d{16,19})/(?\d{16,19})")] + private partial Regex MessageLinkRegex(); + + public override async ValueTask> ReadAsync(ICommandContext ctx, string input) + { + var match = MessageLinkRegex().Match(input); + + if (!match.Success) + return TypeReaderResult.FromError(CommandError.ParseFailed, "Invalid message link"); + + ulong? guildId = ulong.TryParse(match.Groups["sid"].ToString(), out var sid) + ? sid + : null; + + if (guildId != ctx.Guild?.Id) + return TypeReaderResult.FromError(CommandError.ParseFailed, + "Invalid message link. You may only link message from the same server."); + + var channelId = ulong.Parse(match.Groups["cid"].ToString()); + var messageId = ulong.Parse(match.Groups["mid"].ToString()); + + var channel = await ctx.Client.GetChannelAsync(channelId) as IMessageChannel; + + if (channel is null) + return TypeReaderResult.FromError(CommandError.ParseFailed, "Channel not found"); + + var msg = await channel.GetMessageAsync(messageId); + + if (msg is null) + return TypeReaderResult.FromError(CommandError.ParseFailed, "Message not found"); + + return TypeReaderResult.FromSuccess(new MessageLink(ctx.Guild, + channel, + msg + )); + } +} diff --git a/src/EllieBot/_common/TypeReaders/Rgba32TypeReader.cs b/src/EllieBot/_common/TypeReaders/Rgba32TypeReader.cs index 77e7c6a..d1f3711 100644 --- a/src/EllieBot/_common/TypeReaders/Rgba32TypeReader.cs +++ b/src/EllieBot/_common/TypeReaders/Rgba32TypeReader.cs @@ -1,20 +1,19 @@ -using Color = SixLabors.ImageSharp.Color; +using SixLabors.ImageSharp.PixelFormats; +using Color = SixLabors.ImageSharp.Color; #nullable disable namespace EllieBot.Common.TypeReaders; -public sealed class Rgba32TypeReader : EllieTypeReader +public sealed class Rgba32TypeReader : EllieTypeReader { - public override ValueTask> ReadAsync(ICommandContext context, string input) + public override ValueTask> ReadAsync(ICommandContext context, string input) { - input = input.Replace("#", "", StringComparison.InvariantCulture); - try + if (Rgba32.TryParseHex(input, out var clr)) { - return ValueTask.FromResult(TypeReaderResult.FromSuccess(Color.ParseHex(input))); - } - catch - { - return ValueTask.FromResult(TypeReaderResult.FromError(CommandError.ParseFailed, "Parameter is not a valid color hex.")); + return ValueTask.FromResult(TypeReaderResult.FromSuccess(clr)); } + + return ValueTask.FromResult( + TypeReaderResult.FromError(CommandError.ParseFailed, "Parameter is not a valid color hex.")); } } \ No newline at end of file diff --git a/src/EllieBot/data/aliases.yml b/src/EllieBot/data/aliases.yml index d5e2f3e..f2c4a72 100644 --- a/src/EllieBot/data/aliases.yml +++ b/src/EllieBot/data/aliases.yml @@ -1416,6 +1416,10 @@ todocomplete: - complete - done - finish +todouncomplete: + - uncomplete + - undone + - unfinish todoarchiveadd: - add - create @@ -1493,4 +1497,36 @@ gamblestatsreset: - gsreset snipe: - snipe - - sn \ No newline at end of file + - sn +btnroleadd: + - btnradd + - btnra +btnroleremove: + - btnrrem + - btnrr + - btnrrm +btnroleremoveall: + - btnrremall + - btnrra +btnrolelist: + - btnrlist + - btnrl +wrongsong: + - wrongsong + - wrongtrack +servercolorsshow: + - show + - list + - l +servercolorok: + - ok + - success +servercolorerror: + - error + - fail + - err +servercolorpending: + - pending + - warn + - warning + - pend \ No newline at end of file diff --git a/src/EllieBot/data/strings/commands/commands.en-US.yml b/src/EllieBot/data/strings/commands/commands.en-US.yml index e470cda..8fd6ea9 100644 --- a/src/EllieBot/data/strings/commands/commands.en-US.yml +++ b/src/EllieBot/data/strings/commands/commands.en-US.yml @@ -4484,6 +4484,13 @@ todocomplete: params: - todoId: desc: "The id of the todo item being marked as completed." +todouncomplete: + desc: Marks a todo with the specified ID as not done. + ex: + - 4a + params: + - todoId: + desc: "The id of the todo item being marked as not completed." tododelete: desc: Deletes a todo with the specified ID. ex: @@ -4718,4 +4725,86 @@ snipe: ex: - '' params: - - { } \ No newline at end of file + - { } +btnroleadd: + desc: |- + Adds a button role to the specified message (link or id). + Specify a message followed by an emote, followed by a role. + If the role already exists on that message, the button will be updated instead. + Users clicking on the button will receive the role. + ex: + - ' :thumbsup: Good Guy' + params: + - message: + desc: "A message link or id of the message (if id is specified, it has to be a message in this channel)" + - emote: + desc: "An emoji, custom or unicode" + - role: + desc: "The role to add once a user clicks the button" +btnroleremove: + desc: |- + Removes a button role from the message specified by link or id. + Provide a message followed by a role you wish to remove. + ex: + - ' Good Guy' + params: + - message: + desc: "A message link or id of the message" + - role: + desc: "A role to remove" +btnroleremoveall: + desc: |- + Removes all button roles from the message specified by link or id. + ex: + - '' + - '123123123123' + params: + - message: + desc: "A message link or id of the message" +btnrolelist: + desc: |- + Lists all button roles on this server. + One message per page. + ex: + - '' + params: + - { } +wrongsong: + desc: |- + Removes the last queued song. + If the queue was shuffled or fairly re-ordered the song will not be removed. + ex: + - '' + params: + - { } +servercolorsshow: + desc: |- + Shows current Ok, Error and Pending colors for this server. + ex: + - '' + params: + - { } +servercolorok: + desc: |- + Sets the Ok color for this server. + ex: + - '#00ff00' + params: + - color: + desc: "The hex of the color to set" +servercolorerror: + desc: |- + Sets the Error color for this server. + ex: + - '#ff0000' + params: + - color: + desc: "The hex of the color to set" +servercolorpending: + desc: |- + Sets the Pending/Warning color for this server. + ex: + - '#ffff00' + params: + - color: + desc: "The hex of the color to set" \ No newline at end of file diff --git a/src/EllieBot/data/strings/responses/responses.en-US.json b/src/EllieBot/data/strings/responses/responses.en-US.json index 567fb25..0d99314 100644 --- a/src/EllieBot/data/strings/responses/responses.en-US.json +++ b/src/EllieBot/data/strings/responses/responses.en-US.json @@ -1121,5 +1121,16 @@ "sar_group_not_found": "Group with that number doesn't exist.", "sar_group_deleted": "Group {0} deleted.", "choose_one": "Choose one", - "requires_role": "Requires role: {0}" + "requires_role": "Requires role: {0}", + "invalid_message_id": "Invalid Message Id.", + "invalid_message_link": "The message link must be from this server.", + "btnrole_message_max": "Limit reached. You may have up to 25 button roles per message.", + "btnrole_not_found": "No button role found on that message.", + "btnrole_none": "There are no button roles on this page.", + "btnrole_removeall_not_found": "Button role successfully removed but message wasn't found.", + "btnrole_removed": "Button role removed.", + "no_last_queued_found": "No last queued track found.", + "wrongsong_success": "Oops! Wrong song removed: {0}", + "server_not_found": "Server not found.", + "server_color_set": "Successfully set a new server color." } -- 2.43.0 From 7b2adbf9bfbbc37ce76eae931fc44fab13eba0ca Mon Sep 17 00:00:00 2001 From: Toastie Date: Thu, 28 Nov 2024 01:10:50 +1300 Subject: [PATCH 4/4] new method in rotating service --- .../PlayingRotate/PlayingRotateService.cs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/EllieBot/Modules/Administration/PlayingRotate/PlayingRotateService.cs b/src/EllieBot/Modules/Administration/PlayingRotate/PlayingRotateService.cs index 0c9afff..6a0f2bf 100644 --- a/src/EllieBot/Modules/Administration/PlayingRotate/PlayingRotateService.cs +++ b/src/EllieBot/Modules/Administration/PlayingRotate/PlayingRotateService.cs @@ -9,7 +9,9 @@ public sealed class PlayingRotateService : IEService, IReadyExecutor { private readonly BotConfigService _bss; private readonly SelfService _selfService; + private readonly IReplacementService _repService; + // private readonly Replacer _rep; private readonly DbService _db; private readonly DiscordSocketClient _client; @@ -27,14 +29,13 @@ public sealed class PlayingRotateService : IEService, IReadyExecutor _selfService = selfService; _repService = repService; _client = client; - } public async Task OnReadyAsync() { if (_client.ShardId != 0) return; - + using var timer = new PeriodicTimer(TimeSpan.FromMinutes(1)); var index = 0; while (await timer.WaitForNextTickAsync()) @@ -57,7 +58,7 @@ public sealed class PlayingRotateService : IEService, IReadyExecutor ? rotatingStatuses[index = 0] : rotatingStatuses[index++]; - var statusText = await _repService.ReplaceAsync(playingStatus.Status, new (client: _client)); + var statusText = await _repService.ReplaceAsync(playingStatus.Status, new(client: _client)); await _selfService.SetActivityAsync(statusText, (ActivityType)playingStatus.Type); } catch (Exception ex) @@ -72,7 +73,11 @@ public sealed class PlayingRotateService : IEService, IReadyExecutor ArgumentOutOfRangeException.ThrowIfNegative(index); await using var uow = _db.GetDbContext(); - var toRemove = await uow.Set().AsQueryable().AsNoTracking().Skip(index).FirstOrDefaultAsync(); + var toRemove = await uow.Set() + .AsQueryable() + .AsNoTracking() + .Skip(index) + .FirstOrDefaultAsync(); if (toRemove is null) return null; @@ -94,6 +99,11 @@ public sealed class PlayingRotateService : IEService, IReadyExecutor await uow.SaveChangesAsync(); } + public void DisableRotatePlaying() + { + _bss.ModifyConfig(bs => { bs.RotateStatuses = false; }); + } + public bool ToggleRotatePlaying() { var enabled = false; -- 2.43.0