using DysonNetwork.Common.Models; using DysonNetwork.Sphere.Permission; using DysonNetwork.Sphere.Realm; using DysonNetwork.Sphere.Sticker; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Query; namespace DysonNetwork.Sphere; public class AppDatabase( DbContextOptions options, IConfiguration configuration ) : DbContext(options) { public DbSet Files { get; set; } public DbSet FileReferences { get; set; } public DbSet Publishers { get; set; } public DbSet PublisherFeatures { get; set; } public DbSet Posts { get; set; } public DbSet PostReactions { get; set; } public DbSet PostTags { get; set; } public DbSet PostCategories { get; set; } public DbSet PostCollections { get; set; } public DbSet Realms { get; set; } public DbSet RealmMembers { get; set; } public DbSet Tags { get; set; } public DbSet RealmTags { get; set; } public DbSet ChatRooms { get; set; } public DbSet ChatMembers { get; set; } public DbSet ChatMessages { get; set; } public DbSet ChatRealtimeCall { get; set; } public DbSet ChatReactions { get; set; } public DbSet Stickers { get; set; } public DbSet StickerPacks { get; set; } public DbSet Wallets { get; set; } public DbSet WalletPockets { get; set; } public DbSet PaymentOrders { get; set; } public DbSet PaymentTransactions { get; set; } public DbSet CustomApps { get; set; } public DbSet CustomAppSecrets { get; set; } public DbSet WalletSubscriptions { get; set; } public DbSet WalletCoupons { get; set; } public DbSet WebArticles { get; set; } public DbSet WebFeeds { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseNpgsql( configuration.GetConnectionString("App"), opt => opt .ConfigureDataSource(optSource => optSource.EnableDynamicJson()) .UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery) .UseNetTopologySuite() .UseNodaTime() ).UseSnakeCaseNamingConvention(); base.OnConfiguring(optionsBuilder); } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity() .HasKey(pm => new { pm.PublisherId, pm.AccountId }); modelBuilder.Entity() .HasOne(pm => pm.Publisher) .WithMany(p => p.Members) .HasForeignKey(pm => pm.PublisherId) .OnDelete(DeleteBehavior.Cascade); modelBuilder.Entity() .HasGeneratedTsVectorColumn(p => p.SearchVector, "simple", p => new { p.Title, p.Description, p.Content }) .HasIndex(p => p.SearchVector) .HasMethod("GIN"); modelBuilder.Entity() .HasIndex(s => s.Secret) .IsUnique(); modelBuilder.Entity() .HasMany(c => c.Secrets) .WithOne(s => s.App) .HasForeignKey(s => s.AppId) .OnDelete(DeleteBehavior.Cascade); modelBuilder.Entity() .HasOne(p => p.RepliedPost) .WithMany() .HasForeignKey(p => p.RepliedPostId) .OnDelete(DeleteBehavior.Restrict); modelBuilder.Entity() .HasOne(p => p.ForwardedPost) .WithMany() .HasForeignKey(p => p.ForwardedPostId) .OnDelete(DeleteBehavior.Restrict); modelBuilder.Entity() .HasMany(p => p.Tags) .WithMany(t => t.Posts) .UsingEntity(j => j.ToTable("post_tag_links")); modelBuilder.Entity() .HasMany(p => p.Categories) .WithMany(c => c.Posts) .UsingEntity(j => j.ToTable("post_category_links")); modelBuilder.Entity() .HasMany(p => p.Collections) .WithMany(c => c.Posts) .UsingEntity(j => j.ToTable("post_collection_links")); modelBuilder.Entity() .HasKey(pm => new { pm.Id }); modelBuilder.Entity() .HasAlternateKey(pm => new { pm.ChatRoomId, pm.AccountId }); modelBuilder.Entity() .HasOne(m => m.ForwardedMessage) .WithMany() .HasForeignKey(m => m.ForwardedMessageId) .OnDelete(DeleteBehavior.Restrict); modelBuilder.Entity() .HasOne(m => m.RepliedMessage) .WithMany() .HasForeignKey(m => m.RepliedMessageId) .OnDelete(DeleteBehavior.Restrict); modelBuilder.Entity() .HasIndex(f => f.Url) .IsUnique(); modelBuilder.Entity() .HasIndex(a => a.Url) .IsUnique(); public static class OptionalQueryExtensions { public static IQueryable If( this IQueryable source, bool condition, Func, IQueryable> transform ) { return condition ? transform(source) : source; } public static IQueryable If( this IIncludableQueryable source, bool condition, Func, IQueryable> transform ) where T : class { return condition ? transform(source) : source; } public static IQueryable If( this IIncludableQueryable> source, bool condition, Func>, IQueryable> transform ) where T : class { return condition ? transform(source) : source; } }