#nullable disable using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; using Microsoft.Extensions.Logging; using NadekoBot.Db.Models; using NadekoBot.Services.Database.Models; // ReSharper disable UnusedAutoPropertyAccessor.Global namespace NadekoBot.Services.Database; public abstract class NadekoContext : DbContext { public DbSet GuildConfigs { get; set; } 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; } public DbSet WaifuUpdates { get; set; } public DbSet WaifuItem { get; set; } public DbSet Warnings { get; set; } public DbSet UserXpStats { get; set; } public DbSet Clubs { get; set; } public DbSet ClubBans { get; set; } public DbSet ClubApplicants { get; set; } //logging public DbSet LogSettings { get; set; } public DbSet IgnoredVoicePresenceCHannels { get; set; } public DbSet IgnoredLogChannels { get; set; } public DbSet RotatingStatus { get; set; } public DbSet Blacklist { get; set; } public DbSet AutoCommands { get; set; } public DbSet RewardedUsers { get; set; } public DbSet PlantedCurrency { get; set; } public DbSet BanTemplates { get; set; } public DbSet DiscordPermOverrides { get; set; } public DbSet DiscordUser { get; set; } public DbSet MusicPlayerSettings { get; set; } public DbSet Repeaters { get; set; } public DbSet Poll { get; set; } public DbSet WaifuInfo { get; set; } public DbSet ImageOnlyChannels { get; set; } public DbSet NsfwBlacklistedTags { get; set; } public DbSet AutoTranslateChannels { get; set; } public DbSet AutoTranslateUsers { get; set; } public DbSet Permissions { get; set; } #region Mandatory Provider-Specific Values protected abstract string CurrencyTransactionOtherIdDefaultValue { get; } protected abstract string DiscordUserLastXpGainDefaultValue { get; } protected abstract string LastLevelUpDefaultValue { get; } #endregion protected override void OnModelCreating(ModelBuilder modelBuilder) { #region QUOTES var quoteEntity = modelBuilder.Entity(); quoteEntity.HasIndex(x => x.GuildId); quoteEntity.HasIndex(x => x.Keyword); #endregion #region GuildConfig var configEntity = modelBuilder.Entity(); configEntity.HasIndex(c => c.GuildId).IsUnique(); modelBuilder.Entity().HasOne(x => x.GuildConfig).WithOne(x => x.AntiSpamSetting); modelBuilder.Entity().HasOne(x => x.GuildConfig).WithOne(x => x.AntiRaidSetting); modelBuilder.Entity() .HasOne(x => x.AntiAltSetting) .WithOne() .HasForeignKey(x => x.GuildConfigId) .OnDelete(DeleteBehavior.Cascade); modelBuilder.Entity() .HasAlternateKey(x => new { x.GuildConfigId, x.Url }); modelBuilder.Entity().HasIndex(x => x.MessageId).IsUnique(); modelBuilder.Entity().HasIndex(x => x.ChannelId); configEntity.HasIndex(x => x.WarnExpireHours).IsUnique(false); #endregion #region streamrole modelBuilder.Entity().HasOne(x => x.GuildConfig).WithOne(x => x.StreamRole); #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(); musicPlaylistEntity.HasMany(p => p.Songs).WithOne().OnDelete(DeleteBehavior.Cascade); #endregion #region Waifus var wi = modelBuilder.Entity(); wi.HasOne(x => x.Waifu).WithOne(); wi.HasIndex(x => x.Price); wi.HasIndex(x => x.ClaimerId); // wi.HasMany(x => x.Items) // .WithOne() // .OnDelete(DeleteBehavior.Cascade); #endregion #region DiscordUser modelBuilder.Entity(du => { du.Property(x => x.IsClubAdmin) .HasDefaultValue(false); du.Property(x => x.NotifyOnLevelUp) .HasDefaultValue(XpNotificationLocation.None); du.Property(x => x.LastXpGain) .HasDefaultValueSql(DiscordUserLastXpGainDefaultValue); du.Property(x => x.LastLevelUp) .HasDefaultValueSql(LastLevelUpDefaultValue); du.Property(x => x.TotalXp) .HasDefaultValue(0); du.Property(x => x.CurrencyAmount) .HasDefaultValue(0); du.HasAlternateKey(w => w.UserId); du.HasOne(x => x.Club) .WithMany(x => x.Members) .IsRequired(false) .OnDelete(DeleteBehavior.NoAction); du.HasIndex(x => x.TotalXp); du.HasIndex(x => x.CurrencyAmount); du.HasIndex(x => x.UserId); }); #endregion #region Warnings modelBuilder.Entity(warn => { warn.HasIndex(x => x.GuildId); warn.HasIndex(x => x.UserId); warn.HasIndex(x => x.DateAdded); warn.Property(x => x.Weight).HasDefaultValue(1); }); #endregion #region PatreonRewards var pr = modelBuilder.Entity(); pr.HasIndex(x => x.PatreonUserId).IsUnique(); #endregion #region XpStats var xps = modelBuilder.Entity(); xps.HasIndex(x => new { x.UserId, x.GuildId }) .IsUnique(); xps.Property(x => x.LastLevelUp) .HasDefaultValueSql(LastLevelUpDefaultValue); xps.HasIndex(x => x.UserId); xps.HasIndex(x => x.GuildId); xps.HasIndex(x => x.Xp); xps.HasIndex(x => x.AwardedXp); #endregion #region XpSettings modelBuilder.Entity().HasOne(x => x.GuildConfig).WithOne(x => x.XpSettings); #endregion #region XpRoleReward modelBuilder.Entity() .HasIndex(x => new { x.XpSettingsId, x.Level }) .IsUnique(); #endregion #region Club var ci = modelBuilder.Entity(); ci.HasOne(x => x.Owner) .WithOne() .HasForeignKey(x => x.OwnerId) .OnDelete(DeleteBehavior.SetNull); ci.HasAlternateKey(x => new { x.Name }); #endregion #region ClubManytoMany modelBuilder.Entity() .HasKey(t => new { t.ClubId, t.UserId }); modelBuilder.Entity() .HasOne(pt => pt.User) .WithMany(); modelBuilder.Entity() .HasOne(pt => pt.Club) .WithMany(x => x.Applicants); modelBuilder.Entity() .HasKey(t => new { t.ClubId, t.UserId }); modelBuilder.Entity() .HasOne(pt => pt.User) .WithMany(); modelBuilder.Entity() .HasOne(pt => pt.Club) .WithMany(x => x.Bans); #endregion #region Polls modelBuilder.Entity().HasIndex(x => x.GuildId).IsUnique(); #endregion #region CurrencyTransactions modelBuilder.Entity(e => { e.HasIndex(x => x.UserId) .IsUnique(false); e.Property(x => x.OtherId) .HasDefaultValueSql(CurrencyTransactionOtherIdDefaultValue); e.Property(x => x.Type) .IsRequired(); e.Property(x => x.Extra) .IsRequired(); }); #endregion #region Reminders modelBuilder.Entity().HasIndex(x => x.When); #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(); #endregion #region Perm Override modelBuilder.Entity() .HasIndex(x => new { x.GuildId, x.Command }) .IsUnique(); #endregion #region Music modelBuilder.Entity().HasIndex(x => x.GuildId).IsUnique(); modelBuilder.Entity().Property(x => x.Volume).HasDefaultValue(100); #endregion #region Reaction roles modelBuilder.Entity(rrm => rrm .HasMany(x => x.ReactionRoles) .WithOne() .OnDelete(DeleteBehavior.Cascade)); #endregion #region LogSettings modelBuilder.Entity(ls => ls.HasIndex(x => x.GuildId).IsUnique()); modelBuilder.Entity(ls => ls .HasMany(x => x.LogIgnores) .WithOne(x => x.LogSetting) .OnDelete(DeleteBehavior.Cascade)); modelBuilder.Entity(ili => ili .HasIndex(x => new { x.LogSettingId, x.LogItemId, x.ItemType }) .IsUnique()); #endregion modelBuilder.Entity(ioc => ioc.HasIndex(x => x.ChannelId).IsUnique()); modelBuilder.Entity(nbt => nbt.HasIndex(x => x.GuildId).IsUnique(false)); var atch = modelBuilder.Entity(); atch.HasIndex(x => x.GuildId).IsUnique(false); atch.HasIndex(x => x.ChannelId).IsUnique(); atch.HasMany(x => x.Users).WithOne(x => x.Channel).OnDelete(DeleteBehavior.Cascade); modelBuilder.Entity(atu => atu.HasAlternateKey(x => new { x.ChannelId, x.UserId })); } #if DEBUG private static readonly ILoggerFactory _debugLoggerFactory = LoggerFactory.Create(x => x.AddConsole()); protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder.UseLoggerFactory(_debugLoggerFactory); #endif }