diff --git a/src/Ombi.Settings/Ombi.Settings.csproj b/src/Ombi.Settings/Ombi.Settings.csproj
index 4849417bc..9ba67d272 100644
--- a/src/Ombi.Settings/Ombi.Settings.csproj
+++ b/src/Ombi.Settings/Ombi.Settings.csproj
@@ -11,7 +11,7 @@
-
+
diff --git a/src/Ombi.Store/Context/Postgres/ExternalPostgresContext.cs b/src/Ombi.Store/Context/Postgres/ExternalPostgresContext.cs
new file mode 100644
index 000000000..1b106604b
--- /dev/null
+++ b/src/Ombi.Store/Context/Postgres/ExternalPostgresContext.cs
@@ -0,0 +1,16 @@
+using Microsoft.EntityFrameworkCore;
+
+namespace Ombi.Store.Context.Postgres
+{
+ public sealed class ExternalPostgresContext : ExternalContext
+ {
+ private static bool _created;
+ public ExternalPostgresContext(DbContextOptions options) : base(options)
+ {
+ if (_created) return;
+
+ _created = true;
+ Database.Migrate();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Ombi.Store/Context/Postgres/OmbiPostgresContext.cs b/src/Ombi.Store/Context/Postgres/OmbiPostgresContext.cs
new file mode 100644
index 000000000..a2b44180f
--- /dev/null
+++ b/src/Ombi.Store/Context/Postgres/OmbiPostgresContext.cs
@@ -0,0 +1,22 @@
+using Microsoft.EntityFrameworkCore;
+
+namespace Ombi.Store.Context.Postgres
+{
+ public sealed class OmbiPostgresContext : OmbiContext
+ {
+ private static bool _created;
+
+ public OmbiPostgresContext(DbContextOptions options) : base(options)
+ {
+ if (_created) return;
+ _created = true;
+
+ Database.Migrate();
+ }
+
+ public override void Dispose()
+ {
+ base.Dispose();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Ombi.Store/Context/Postgres/SettingsPostgresContext.cs b/src/Ombi.Store/Context/Postgres/SettingsPostgresContext.cs
new file mode 100644
index 000000000..d8f343e46
--- /dev/null
+++ b/src/Ombi.Store/Context/Postgres/SettingsPostgresContext.cs
@@ -0,0 +1,16 @@
+using Microsoft.EntityFrameworkCore;
+
+namespace Ombi.Store.Context.Postgres
+{
+ public sealed class SettingsPostgresContext : SettingsContext
+ {
+ private static bool _created;
+ public SettingsPostgresContext(DbContextOptions options) : base(options)
+ {
+ if (_created) return;
+
+ _created = true;
+ Database.Migrate();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Ombi.Store/MigrationHelper.cs b/src/Ombi.Store/MigrationHelper.cs
index 58b6d6b68..88136d4c1 100644
--- a/src/Ombi.Store/MigrationHelper.cs
+++ b/src/Ombi.Store/MigrationHelper.cs
@@ -20,5 +20,13 @@ INSERT INTO AspNetRoles(Id, ConcurrencyStamp, Name, NormalizedName)
SELECT '{Guid.NewGuid()}','{Guid.NewGuid()}','{role}', '{role.ToUpper()}'
WHERE NOT EXISTS(SELECT 1 FROM AspNetRoles WHERE Name = '{role}');");
}
+
+ public static void InsertRolePostgres(this MigrationBuilder mb, string role)
+ {
+ mb.Sql($@"
+INSERT INTO public.""AspNetRoles""(""Id"", ""ConcurrencyStamp"", ""Name"", ""NormalizedName"")
+SELECT '{Guid.NewGuid()}','{Guid.NewGuid()}','{role}', '{role.ToUpper()}'
+WHERE NOT EXISTS(SELECT 1 FROM public.""AspNetRoles"" WHERE ""Name"" = '{role}');");
+ }
}
}
diff --git a/src/Ombi.Store/Migrations/ExternalPostgres/20231212135426_Initial.Designer.cs b/src/Ombi.Store/Migrations/ExternalPostgres/20231212135426_Initial.Designer.cs
new file mode 100644
index 000000000..5ca9b77b9
--- /dev/null
+++ b/src/Ombi.Store/Migrations/ExternalPostgres/20231212135426_Initial.Designer.cs
@@ -0,0 +1,628 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+using Ombi.Store.Context.Postgres;
+
+#nullable disable
+
+namespace Ombi.Store.Migrations.ExternalPostgres
+{
+ [DbContext(typeof(ExternalPostgresContext))]
+ [Migration("20231212135426_Initial")]
+ partial class Initial
+ {
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "6.0.22")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("Ombi.Store.Entities.CouchPotatoCache", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("TheMovieDbId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.ToTable("CouchPotatoCache");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("AddedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("EmbyId")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Has4K")
+ .HasColumnType("boolean");
+
+ b.Property("ImdbId")
+ .HasColumnType("text");
+
+ b.Property("ProviderId")
+ .HasColumnType("text");
+
+ b.Property("Quality")
+ .HasColumnType("text");
+
+ b.Property("TheMovieDbId")
+ .HasColumnType("text");
+
+ b.Property("Title")
+ .HasColumnType("text");
+
+ b.Property("TvDbId")
+ .HasColumnType("text");
+
+ b.Property("Type")
+ .HasColumnType("integer");
+
+ b.Property("Url")
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("EmbyContent");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("AddedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("EmbyId")
+ .HasColumnType("text");
+
+ b.Property("EpisodeNumber")
+ .HasColumnType("integer");
+
+ b.Property("ImdbId")
+ .HasColumnType("text");
+
+ b.Property("ParentId")
+ .HasColumnType("text");
+
+ b.Property("ProviderId")
+ .HasColumnType("text");
+
+ b.Property("SeasonNumber")
+ .HasColumnType("integer");
+
+ b.Property("TheMovieDbId")
+ .HasColumnType("text");
+
+ b.Property("Title")
+ .HasColumnType("text");
+
+ b.Property("TvDbId")
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ParentId");
+
+ b.ToTable("EmbyEpisode");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("AddedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Has4K")
+ .HasColumnType("boolean");
+
+ b.Property("ImdbId")
+ .HasColumnType("text");
+
+ b.Property("JellyfinId")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("ProviderId")
+ .HasColumnType("text");
+
+ b.Property("Quality")
+ .HasColumnType("text");
+
+ b.Property("TheMovieDbId")
+ .HasColumnType("text");
+
+ b.Property("Title")
+ .HasColumnType("text");
+
+ b.Property("TvDbId")
+ .HasColumnType("text");
+
+ b.Property("Type")
+ .HasColumnType("integer");
+
+ b.Property("Url")
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("JellyfinContent");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("AddedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("EpisodeNumber")
+ .HasColumnType("integer");
+
+ b.Property("ImdbId")
+ .HasColumnType("text");
+
+ b.Property("JellyfinId")
+ .HasColumnType("text");
+
+ b.Property("ParentId")
+ .HasColumnType("text");
+
+ b.Property("ProviderId")
+ .HasColumnType("text");
+
+ b.Property("SeasonNumber")
+ .HasColumnType("integer");
+
+ b.Property("TheMovieDbId")
+ .HasColumnType("text");
+
+ b.Property("Title")
+ .HasColumnType("text");
+
+ b.Property("TvDbId")
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ParentId");
+
+ b.ToTable("JellyfinEpisode");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.LidarrAlbumCache", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("AddedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("ArtistId")
+ .HasColumnType("integer");
+
+ b.Property("ForeignAlbumId")
+ .HasColumnType("text");
+
+ b.Property("Monitored")
+ .HasColumnType("boolean");
+
+ b.Property("PercentOfTracks")
+ .HasColumnType("numeric");
+
+ b.Property("ReleaseDate")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Title")
+ .HasColumnType("text");
+
+ b.Property("TrackCount")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.ToTable("LidarrAlbumCache");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.LidarrArtistCache", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("ArtistId")
+ .HasColumnType("integer");
+
+ b.Property("ArtistName")
+ .HasColumnType("text");
+
+ b.Property("ForeignArtistId")
+ .HasColumnType("text");
+
+ b.Property("Monitored")
+ .HasColumnType("boolean");
+
+ b.HasKey("Id");
+
+ b.ToTable("LidarrArtistCache");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("EpisodeNumber")
+ .HasColumnType("integer");
+
+ b.Property("GrandparentKey")
+ .HasColumnType("text");
+
+ b.Property("Key")
+ .HasColumnType("text");
+
+ b.Property("ParentKey")
+ .HasColumnType("text");
+
+ b.Property("SeasonNumber")
+ .HasColumnType("integer");
+
+ b.Property("Title")
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("GrandparentKey");
+
+ b.ToTable("PlexEpisode");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("ParentKey")
+ .HasColumnType("text");
+
+ b.Property("PlexContentId")
+ .HasColumnType("text");
+
+ b.Property("PlexServerContentId")
+ .HasColumnType("integer");
+
+ b.Property("SeasonKey")
+ .HasColumnType("text");
+
+ b.Property("SeasonNumber")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("PlexServerContentId");
+
+ b.ToTable("PlexSeasonsContent");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("AddedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Has4K")
+ .HasColumnType("boolean");
+
+ b.Property("ImdbId")
+ .HasColumnType("text");
+
+ b.Property("Key")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Quality")
+ .HasColumnType("text");
+
+ b.Property("ReleaseYear")
+ .HasColumnType("text");
+
+ b.Property("RequestId")
+ .HasColumnType("integer");
+
+ b.Property("TheMovieDbId")
+ .HasColumnType("text");
+
+ b.Property("Title")
+ .HasColumnType("text");
+
+ b.Property("TvDbId")
+ .HasColumnType("text");
+
+ b.Property("Type")
+ .HasColumnType("integer");
+
+ b.Property("Url")
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("PlexServerContent");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.PlexWatchlistHistory", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("TmdbId")
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("PlexWatchlistHistory");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.RadarrCache", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Has4K")
+ .HasColumnType("boolean");
+
+ b.Property("HasFile")
+ .HasColumnType("boolean");
+
+ b.Property("HasRegular")
+ .HasColumnType("boolean");
+
+ b.Property("TheMovieDbId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.ToTable("RadarrCache");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.SickRageCache", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("TvDbId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.ToTable("SickRageCache");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.SickRageEpisodeCache", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("EpisodeNumber")
+ .HasColumnType("integer");
+
+ b.Property("SeasonNumber")
+ .HasColumnType("integer");
+
+ b.Property("TvDbId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.ToTable("SickRageEpisodeCache");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.SonarrCache", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("TheMovieDbId")
+ .HasColumnType("integer");
+
+ b.Property("TvDbId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.ToTable("SonarrCache");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.SonarrEpisodeCache", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("EpisodeNumber")
+ .HasColumnType("integer");
+
+ b.Property("HasFile")
+ .HasColumnType("boolean");
+
+ b.Property("MovieDbId")
+ .HasColumnType("integer");
+
+ b.Property("SeasonNumber")
+ .HasColumnType("integer");
+
+ b.Property("TvDbId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.ToTable("SonarrEpisodeCache");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.UserPlayedEpisode", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("EpisodeNumber")
+ .HasColumnType("integer");
+
+ b.Property("SeasonNumber")
+ .HasColumnType("integer");
+
+ b.Property("TheMovieDbId")
+ .HasColumnType("integer");
+
+ b.Property("UserId")
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("UserPlayedEpisode");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.UserPlayedMovie", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("TheMovieDbId")
+ .HasColumnType("integer");
+
+ b.Property("UserId")
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("UserPlayedMovie");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.EmbyEpisode", b =>
+ {
+ b.HasOne("Ombi.Store.Entities.EmbyContent", "Series")
+ .WithMany("Episodes")
+ .HasForeignKey("ParentId")
+ .HasPrincipalKey("EmbyId");
+
+ b.Navigation("Series");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.JellyfinEpisode", b =>
+ {
+ b.HasOne("Ombi.Store.Entities.JellyfinContent", "Series")
+ .WithMany("Episodes")
+ .HasForeignKey("ParentId")
+ .HasPrincipalKey("JellyfinId");
+
+ b.Navigation("Series");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.PlexEpisode", b =>
+ {
+ b.HasOne("Ombi.Store.Entities.PlexServerContent", "Series")
+ .WithMany("Episodes")
+ .HasForeignKey("GrandparentKey")
+ .HasPrincipalKey("Key");
+
+ b.Navigation("Series");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.PlexSeasonsContent", b =>
+ {
+ b.HasOne("Ombi.Store.Entities.PlexServerContent", null)
+ .WithMany("Seasons")
+ .HasForeignKey("PlexServerContentId");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.EmbyContent", b =>
+ {
+ b.Navigation("Episodes");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.JellyfinContent", b =>
+ {
+ b.Navigation("Episodes");
+ });
+
+ modelBuilder.Entity("Ombi.Store.Entities.PlexServerContent", b =>
+ {
+ b.Navigation("Episodes");
+
+ b.Navigation("Seasons");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/src/Ombi.Store/Migrations/ExternalPostgres/20231212135426_Initial.cs b/src/Ombi.Store/Migrations/ExternalPostgres/20231212135426_Initial.cs
new file mode 100644
index 000000000..9ba6ab96c
--- /dev/null
+++ b/src/Ombi.Store/Migrations/ExternalPostgres/20231212135426_Initial.cs
@@ -0,0 +1,430 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace Ombi.Store.Migrations.ExternalPostgres
+{
+ public partial class Initial : Migration
+ {
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "CouchPotatoCache",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ TheMovieDbId = table.Column(type: "integer", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_CouchPotatoCache", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "EmbyContent",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ ProviderId = table.Column(type: "text", nullable: true),
+ EmbyId = table.Column(type: "text", nullable: false),
+ Title = table.Column(type: "text", nullable: true),
+ ImdbId = table.Column(type: "text", nullable: true),
+ TvDbId = table.Column(type: "text", nullable: true),
+ TheMovieDbId = table.Column(type: "text", nullable: true),
+ Type = table.Column(type: "integer", nullable: false),
+ Quality = table.Column(type: "text", nullable: true),
+ Has4K = table.Column(type: "boolean", nullable: false),
+ Url = table.Column(type: "text", nullable: true),
+ AddedAt = table.Column(type: "timestamp with time zone", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_EmbyContent", x => x.Id);
+ table.UniqueConstraint("AK_EmbyContent_EmbyId", x => x.EmbyId);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "JellyfinContent",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ ProviderId = table.Column(type: "text", nullable: true),
+ JellyfinId = table.Column(type: "text", nullable: false),
+ Title = table.Column(type: "text", nullable: true),
+ ImdbId = table.Column(type: "text", nullable: true),
+ TvDbId = table.Column(type: "text", nullable: true),
+ TheMovieDbId = table.Column(type: "text", nullable: true),
+ Type = table.Column(type: "integer", nullable: false),
+ Quality = table.Column(type: "text", nullable: true),
+ Has4K = table.Column(type: "boolean", nullable: false),
+ Url = table.Column(type: "text", nullable: true),
+ AddedAt = table.Column(type: "timestamp with time zone", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_JellyfinContent", x => x.Id);
+ table.UniqueConstraint("AK_JellyfinContent_JellyfinId", x => x.JellyfinId);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "LidarrAlbumCache",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ ArtistId = table.Column(type: "integer", nullable: false),
+ ForeignAlbumId = table.Column(type: "text", nullable: true),
+ TrackCount = table.Column(type: "integer", nullable: false),
+ ReleaseDate = table.Column(type: "timestamp with time zone", nullable: false),
+ Monitored = table.Column(type: "boolean", nullable: false),
+ Title = table.Column(type: "text", nullable: true),
+ PercentOfTracks = table.Column(type: "numeric", nullable: false),
+ AddedAt = table.Column(type: "timestamp with time zone", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_LidarrAlbumCache", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "LidarrArtistCache",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ ArtistId = table.Column(type: "integer", nullable: false),
+ ArtistName = table.Column(type: "text", nullable: true),
+ ForeignArtistId = table.Column(type: "text", nullable: true),
+ Monitored = table.Column(type: "boolean", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_LidarrArtistCache", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "PlexServerContent",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ ReleaseYear = table.Column(type: "text", nullable: true),
+ Key = table.Column(type: "text", nullable: false),
+ RequestId = table.Column(type: "integer", nullable: true),
+ Title = table.Column(type: "text", nullable: true),
+ ImdbId = table.Column(type: "text", nullable: true),
+ TvDbId = table.Column(type: "text", nullable: true),
+ TheMovieDbId = table.Column(type: "text", nullable: true),
+ Type = table.Column(type: "integer", nullable: false),
+ Quality = table.Column(type: "text", nullable: true),
+ Has4K = table.Column(type: "boolean", nullable: false),
+ Url = table.Column(type: "text", nullable: true),
+ AddedAt = table.Column(type: "timestamp with time zone", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_PlexServerContent", x => x.Id);
+ table.UniqueConstraint("AK_PlexServerContent_Key", x => x.Key);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "PlexWatchlistHistory",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ TmdbId = table.Column(type: "text", nullable: true)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_PlexWatchlistHistory", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "RadarrCache",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ TheMovieDbId = table.Column(type: "integer", nullable: false),
+ HasFile = table.Column(type: "boolean", nullable: false),
+ Has4K = table.Column(type: "boolean", nullable: false),
+ HasRegular = table.Column(type: "boolean", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_RadarrCache", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "SickRageCache",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ TvDbId = table.Column(type: "integer", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_SickRageCache", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "SickRageEpisodeCache",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ SeasonNumber = table.Column(type: "integer", nullable: false),
+ EpisodeNumber = table.Column(type: "integer", nullable: false),
+ TvDbId = table.Column(type: "integer", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_SickRageEpisodeCache", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "SonarrCache",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ TvDbId = table.Column(type: "integer", nullable: false),
+ TheMovieDbId = table.Column(type: "integer", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_SonarrCache", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "SonarrEpisodeCache",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ SeasonNumber = table.Column(type: "integer", nullable: false),
+ EpisodeNumber = table.Column(type: "integer", nullable: false),
+ TvDbId = table.Column(type: "integer", nullable: false),
+ MovieDbId = table.Column(type: "integer", nullable: false),
+ HasFile = table.Column(type: "boolean", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_SonarrEpisodeCache", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "UserPlayedEpisode",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ TheMovieDbId = table.Column(type: "integer", nullable: false),
+ SeasonNumber = table.Column(type: "integer", nullable: false),
+ EpisodeNumber = table.Column(type: "integer", nullable: false),
+ UserId = table.Column(type: "text", nullable: true)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_UserPlayedEpisode", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "UserPlayedMovie",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ TheMovieDbId = table.Column(type: "integer", nullable: false),
+ UserId = table.Column(type: "text", nullable: true)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_UserPlayedMovie", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "EmbyEpisode",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ EmbyId = table.Column(type: "text", nullable: true),
+ ParentId = table.Column(type: "text", nullable: true),
+ ProviderId = table.Column(type: "text", nullable: true),
+ AddedAt = table.Column(type: "timestamp with time zone", nullable: false),
+ TvDbId = table.Column(type: "text", nullable: true),
+ ImdbId = table.Column(type: "text", nullable: true),
+ TheMovieDbId = table.Column(type: "text", nullable: true),
+ EpisodeNumber = table.Column(type: "integer", nullable: false),
+ SeasonNumber = table.Column(type: "integer", nullable: false),
+ Title = table.Column(type: "text", nullable: true)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_EmbyEpisode", x => x.Id);
+ table.ForeignKey(
+ name: "FK_EmbyEpisode_EmbyContent_ParentId",
+ column: x => x.ParentId,
+ principalTable: "EmbyContent",
+ principalColumn: "EmbyId");
+ });
+
+ migrationBuilder.CreateTable(
+ name: "JellyfinEpisode",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ JellyfinId = table.Column(type: "text", nullable: true),
+ ParentId = table.Column(type: "text", nullable: true),
+ ProviderId = table.Column(type: "text", nullable: true),
+ AddedAt = table.Column(type: "timestamp with time zone", nullable: false),
+ TvDbId = table.Column(type: "text", nullable: true),
+ ImdbId = table.Column(type: "text", nullable: true),
+ TheMovieDbId = table.Column(type: "text", nullable: true),
+ EpisodeNumber = table.Column(type: "integer", nullable: false),
+ SeasonNumber = table.Column(type: "integer", nullable: false),
+ Title = table.Column(type: "text", nullable: true)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_JellyfinEpisode", x => x.Id);
+ table.ForeignKey(
+ name: "FK_JellyfinEpisode_JellyfinContent_ParentId",
+ column: x => x.ParentId,
+ principalTable: "JellyfinContent",
+ principalColumn: "JellyfinId");
+ });
+
+ migrationBuilder.CreateTable(
+ name: "PlexEpisode",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ Key = table.Column(type: "text", nullable: true),
+ ParentKey = table.Column(type: "text", nullable: true),
+ GrandparentKey = table.Column(type: "text", nullable: true),
+ EpisodeNumber = table.Column(type: "integer", nullable: false),
+ SeasonNumber = table.Column(type: "integer", nullable: false),
+ Title = table.Column(type: "text", nullable: true)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_PlexEpisode", x => x.Id);
+ table.ForeignKey(
+ name: "FK_PlexEpisode_PlexServerContent_GrandparentKey",
+ column: x => x.GrandparentKey,
+ principalTable: "PlexServerContent",
+ principalColumn: "Key");
+ });
+
+ migrationBuilder.CreateTable(
+ name: "PlexSeasonsContent",
+ columns: table => new
+ {
+ Id = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ PlexContentId = table.Column(type: "text", nullable: true),
+ SeasonNumber = table.Column(type: "integer", nullable: false),
+ SeasonKey = table.Column