From 35ba2bab2c192a52a05cfc3ada4c577efe6e042c Mon Sep 17 00:00:00 2001 From: Jason Dove Date: Wed, 1 Dec 2021 13:43:09 -0600 Subject: [PATCH] fix unicode song metadata on windows (#523) * test setting utf8 encoding with ffprobe * use utf8 encoding for console (logging) output * use proper sink package * reset song metadata on windows * fix nfo processing with missing year * update changelog --- CHANGELOG.md | 3 + .../Metadata/LocalMetadataProvider.cs | 8 +- .../Metadata/LocalStatisticsProvider.cs | 5 +- ErsatzTV.Core/Metadata/Nfo/TvShowNfo.cs | 9 +- ...45_Reset_SongMetadataOnWindows.Designer.cs | 3843 +++++++++++++++++ ...11201191945_Reset_SongMetadataOnWindows.cs | 34 + ErsatzTV/Startup.cs | 3 + lib/Serilog.Sinks.SQLite.6.0.0.nupkg | Bin 0 -> 31539 bytes 8 files changed, 3899 insertions(+), 6 deletions(-) create mode 100644 ErsatzTV.Infrastructure/Migrations/20211201191945_Reset_SongMetadataOnWindows.Designer.cs create mode 100644 ErsatzTV.Infrastructure/Migrations/20211201191945_Reset_SongMetadataOnWindows.cs create mode 100644 lib/Serilog.Sinks.SQLite.6.0.0.nupkg diff --git a/CHANGELOG.md b/CHANGELOG.md index d85de6688..3f4c9d6b1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] ### Fixed - Fix artwork upload on Windows +- Fix unicode song metadata on Windows +- Fix unicode console output on Windows +- Fix TV Show NFO metadata processing when `year` is missing ### Changed - Use custom log database backend which should be more portable (i.e. work in osx-arm64) diff --git a/ErsatzTV.Core/Metadata/LocalMetadataProvider.cs b/ErsatzTV.Core/Metadata/LocalMetadataProvider.cs index 6b51b0847..8a4e55958 100644 --- a/ErsatzTV.Core/Metadata/LocalMetadataProvider.cs +++ b/ErsatzTV.Core/Metadata/LocalMetadataProvider.cs @@ -969,9 +969,9 @@ namespace ErsatzTV.Core.Metadata } } - private static int? GetYear(int year, string premiered) + private static int? GetYear(int? year, string premiered) { - if (year > 1000) + if (year is > 1000) { return year; } @@ -989,9 +989,9 @@ namespace ErsatzTV.Core.Metadata return null; } - private static DateTime? GetAired(int year, string aired) + private static DateTime? GetAired(int? year, string aired) { - DateTime? fallback = year > 1000 ? new DateTime(year, 1, 1) : null; + DateTime? fallback = year is > 1000 ? new DateTime(year.Value, 1, 1) : null; if (string.IsNullOrWhiteSpace(aired)) { diff --git a/ErsatzTV.Core/Metadata/LocalStatisticsProvider.cs b/ErsatzTV.Core/Metadata/LocalStatisticsProvider.cs index a6aa8098e..5cb9084fd 100644 --- a/ErsatzTV.Core/Metadata/LocalStatisticsProvider.cs +++ b/ErsatzTV.Core/Metadata/LocalStatisticsProvider.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; +using System.Text; using System.Threading.Tasks; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Extensions; @@ -141,7 +142,9 @@ namespace ErsatzTV.Core.Metadata FileName = ffprobePath, RedirectStandardOutput = true, RedirectStandardError = true, - UseShellExecute = false + UseShellExecute = false, + StandardOutputEncoding = Encoding.UTF8, + StandardErrorEncoding = Encoding.UTF8 }; startInfo.ArgumentList.Add("-v"); diff --git a/ErsatzTV.Core/Metadata/Nfo/TvShowNfo.cs b/ErsatzTV.Core/Metadata/Nfo/TvShowNfo.cs index 8224232c4..835338a55 100644 --- a/ErsatzTV.Core/Metadata/Nfo/TvShowNfo.cs +++ b/ErsatzTV.Core/Metadata/Nfo/TvShowNfo.cs @@ -9,8 +9,15 @@ namespace ErsatzTV.Core.Metadata.Nfo [XmlElement("title")] public string Title { get; set; } + [XmlIgnore] + public int? Year { get; set; } + [XmlElement("year")] - public int Year { get; set; } + public string YearAsText + { + get => Year.HasValue ? Year.ToString() : null; + set => Year = !string.IsNullOrWhiteSpace(value) ? int.Parse(value) : default(int?); + } [XmlElement("plot")] public string Plot { get; set; } diff --git a/ErsatzTV.Infrastructure/Migrations/20211201191945_Reset_SongMetadataOnWindows.Designer.cs b/ErsatzTV.Infrastructure/Migrations/20211201191945_Reset_SongMetadataOnWindows.Designer.cs new file mode 100644 index 000000000..7dc22725b --- /dev/null +++ b/ErsatzTV.Infrastructure/Migrations/20211201191945_Reset_SongMetadataOnWindows.Designer.cs @@ -0,0 +1,3843 @@ +// +using System; +using ErsatzTV.Infrastructure.Data; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace ErsatzTV.Infrastructure.Migrations +{ + [DbContext(typeof(TvContext))] + [Migration("20211201191945_Reset_SongMetadataOnWindows")] + partial class Reset_SongMetadataOnWindows + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder.HasAnnotation("ProductVersion", "6.0.0"); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Actor", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistMetadataId") + .HasColumnType("INTEGER"); + + b.Property("ArtworkId") + .HasColumnType("INTEGER"); + + b.Property("EpisodeMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MovieMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Order") + .HasColumnType("INTEGER"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Role") + .HasColumnType("TEXT"); + + b.Property("SeasonMetadataId") + .HasColumnType("INTEGER"); + + b.Property("ShowMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SongMetadataId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.HasIndex("ArtworkId") + .IsUnique(); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("MusicVideoMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.HasIndex("SeasonMetadataId"); + + b.HasIndex("ShowMetadataId"); + + b.HasIndex("SongMetadataId"); + + b.ToTable("Actor", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ArtistMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistId") + .HasColumnType("INTEGER"); + + b.Property("Biography") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("Disambiguation") + .HasColumnType("TEXT"); + + b.Property("Formed") + .HasColumnType("TEXT"); + + b.Property("MetadataKind") + .HasColumnType("INTEGER"); + + b.Property("OriginalTitle") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("SortTitle") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ArtistId"); + + b.ToTable("ArtistMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Artwork", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistMetadataId") + .HasColumnType("INTEGER"); + + b.Property("ArtworkKind") + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("EpisodeMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MovieMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Path") + .HasColumnType("TEXT"); + + b.Property("SeasonMetadataId") + .HasColumnType("INTEGER"); + + b.Property("ShowMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SongMetadataId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.HasIndex("ChannelId"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("MusicVideoMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.HasIndex("SeasonMetadataId"); + + b.HasIndex("ShowMetadataId"); + + b.HasIndex("SongMetadataId"); + + b.ToTable("Artwork", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Channel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("FFmpegProfileId") + .HasColumnType("INTEGER"); + + b.Property("FallbackFillerId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Number") + .HasColumnType("TEXT"); + + b.Property("PreferredLanguageCode") + .HasColumnType("TEXT"); + + b.Property("StreamingMode") + .HasColumnType("INTEGER"); + + b.Property("UniqueId") + .HasColumnType("TEXT"); + + b.Property("WatermarkId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("FFmpegProfileId"); + + b.HasIndex("FallbackFillerId"); + + b.HasIndex("Number") + .IsUnique(); + + b.HasIndex("WatermarkId"); + + b.ToTable("Channel", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ChannelWatermark", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DurationSeconds") + .HasColumnType("INTEGER"); + + b.Property("FrequencyMinutes") + .HasColumnType("INTEGER"); + + b.Property("HorizontalMarginPercent") + .HasColumnType("INTEGER"); + + b.Property("Image") + .HasColumnType("TEXT"); + + b.Property("ImageSource") + .HasColumnType("INTEGER"); + + b.Property("Location") + .HasColumnType("INTEGER"); + + b.Property("Mode") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Opacity") + .HasColumnType("INTEGER"); + + b.Property("Size") + .HasColumnType("INTEGER"); + + b.Property("VerticalMarginPercent") + .HasColumnType("INTEGER"); + + b.Property("WidthPercent") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("ChannelWatermark", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Collection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("UseCustomPlaybackOrder") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Collection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.CollectionItem", b => + { + b.Property("CollectionId") + .HasColumnType("INTEGER"); + + b.Property("MediaItemId") + .HasColumnType("INTEGER"); + + b.Property("CustomIndex") + .HasColumnType("INTEGER"); + + b.HasKey("CollectionId", "MediaItemId"); + + b.HasIndex("MediaItemId"); + + b.ToTable("CollectionItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ConfigElement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("Value") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("Key") + .IsUnique(); + + b.ToTable("ConfigElement", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Director", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MovieMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.ToTable("Director", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyConnection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Address") + .HasColumnType("TEXT"); + + b.Property("EmbyMediaSourceId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("EmbyMediaSourceId"); + + b.ToTable("EmbyConnection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyPathReplacement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EmbyMediaSourceId") + .HasColumnType("INTEGER"); + + b.Property("EmbyPath") + .HasColumnType("TEXT"); + + b.Property("LocalPath") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EmbyMediaSourceId"); + + b.ToTable("EmbyPathReplacement", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EpisodeMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("EpisodeId") + .HasColumnType("INTEGER"); + + b.Property("EpisodeNumber") + .HasColumnType("INTEGER"); + + b.Property("MetadataKind") + .HasColumnType("INTEGER"); + + b.Property("OriginalTitle") + .HasColumnType("TEXT"); + + b.Property("Outline") + .HasColumnType("TEXT"); + + b.Property("Plot") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("SortTitle") + .HasColumnType("TEXT"); + + b.Property("Tagline") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("EpisodeId"); + + b.ToTable("EpisodeMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.FFmpegProfile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AudioBitrate") + .HasColumnType("INTEGER"); + + b.Property("AudioBufferSize") + .HasColumnType("INTEGER"); + + b.Property("AudioChannels") + .HasColumnType("INTEGER"); + + b.Property("AudioCodec") + .HasColumnType("TEXT"); + + b.Property("AudioSampleRate") + .HasColumnType("INTEGER"); + + b.Property("HardwareAcceleration") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("NormalizeAudio") + .HasColumnType("INTEGER"); + + b.Property("NormalizeLoudness") + .HasColumnType("INTEGER"); + + b.Property("NormalizeVideo") + .HasColumnType("INTEGER"); + + b.Property("ResolutionId") + .HasColumnType("INTEGER"); + + b.Property("ThreadCount") + .HasColumnType("INTEGER"); + + b.Property("Transcode") + .HasColumnType("INTEGER"); + + b.Property("VaapiDevice") + .HasColumnType("TEXT"); + + b.Property("VaapiDriver") + .HasColumnType("INTEGER"); + + b.Property("VideoBitrate") + .HasColumnType("INTEGER"); + + b.Property("VideoBufferSize") + .HasColumnType("INTEGER"); + + b.Property("VideoCodec") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ResolutionId"); + + b.ToTable("FFmpegProfile", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Filler.FillerPreset", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CollectionId") + .HasColumnType("INTEGER"); + + b.Property("CollectionType") + .HasColumnType("INTEGER"); + + b.Property("Count") + .HasColumnType("INTEGER"); + + b.Property("Duration") + .HasColumnType("TEXT"); + + b.Property("FillerKind") + .HasColumnType("INTEGER"); + + b.Property("FillerMode") + .HasColumnType("INTEGER"); + + b.Property("MediaItemId") + .HasColumnType("INTEGER"); + + b.Property("MultiCollectionId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("PadToNearestMinute") + .HasColumnType("INTEGER"); + + b.Property("SmartCollectionId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("CollectionId"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("MultiCollectionId"); + + b.HasIndex("SmartCollectionId"); + + b.ToTable("FillerPreset", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Genre", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistMetadataId") + .HasColumnType("INTEGER"); + + b.Property("EpisodeMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MovieMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SeasonMetadataId") + .HasColumnType("INTEGER"); + + b.Property("ShowMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SongMetadataId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("MusicVideoMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.HasIndex("SeasonMetadataId"); + + b.HasIndex("ShowMetadataId"); + + b.HasIndex("SongMetadataId"); + + b.ToTable("Genre"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinConnection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Address") + .HasColumnType("TEXT"); + + b.Property("JellyfinMediaSourceId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("JellyfinMediaSourceId"); + + b.ToTable("JellyfinConnection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinPathReplacement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("JellyfinMediaSourceId") + .HasColumnType("INTEGER"); + + b.Property("JellyfinPath") + .HasColumnType("TEXT"); + + b.Property("LocalPath") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("JellyfinMediaSourceId"); + + b.ToTable("JellyfinPathReplacement", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LanguageCode", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EnglishName") + .HasColumnType("TEXT"); + + b.Property("FrenchName") + .HasColumnType("TEXT"); + + b.Property("ThreeCode1") + .HasColumnType("TEXT"); + + b.Property("ThreeCode2") + .HasColumnType("TEXT"); + + b.Property("TwoCode") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("LanguageCode", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Library", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("LastScan") + .HasColumnType("TEXT"); + + b.Property("MediaKind") + .HasColumnType("INTEGER"); + + b.Property("MediaSourceId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("MediaSourceId"); + + b.ToTable("Library", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LibraryFolder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("LibraryPathId") + .HasColumnType("INTEGER"); + + b.Property("Path") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("LibraryPathId"); + + b.ToTable("LibraryFolder", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LibraryPath", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("LastScan") + .HasColumnType("TEXT"); + + b.Property("LibraryId") + .HasColumnType("INTEGER"); + + b.Property("Path") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("LibraryId"); + + b.ToTable("LibraryPath", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaChapter", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChapterId") + .HasColumnType("INTEGER"); + + b.Property("EndTime") + .HasColumnType("TEXT"); + + b.Property("MediaVersionId") + .HasColumnType("INTEGER"); + + b.Property("StartTime") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("MediaVersionId"); + + b.ToTable("MediaChapter", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaFile", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("MediaVersionId") + .HasColumnType("INTEGER"); + + b.Property("Path") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("MediaVersionId"); + + b.HasIndex("Path") + .IsUnique(); + + b.ToTable("MediaFile", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("LibraryPathId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("LibraryPathId"); + + b.ToTable("MediaItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaSource", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("MediaSource", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaStream", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("AttachedPic") + .HasColumnType("INTEGER"); + + b.Property("BitsPerRawSample") + .HasColumnType("INTEGER"); + + b.Property("Channels") + .HasColumnType("INTEGER"); + + b.Property("Codec") + .HasColumnType("TEXT"); + + b.Property("Default") + .HasColumnType("INTEGER"); + + b.Property("Forced") + .HasColumnType("INTEGER"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("Language") + .HasColumnType("TEXT"); + + b.Property("MediaStreamKind") + .HasColumnType("INTEGER"); + + b.Property("MediaVersionId") + .HasColumnType("INTEGER"); + + b.Property("PixelFormat") + .HasColumnType("TEXT"); + + b.Property("Profile") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("MediaVersionId"); + + b.ToTable("MediaStream", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaVersion", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("DisplayAspectRatio") + .HasColumnType("TEXT"); + + b.Property("Duration") + .HasColumnType("TEXT"); + + b.Property("EpisodeId") + .HasColumnType("INTEGER"); + + b.Property("Height") + .HasColumnType("INTEGER"); + + b.Property("MovieId") + .HasColumnType("INTEGER"); + + b.Property("MusicVideoId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("OtherVideoId") + .HasColumnType("INTEGER"); + + b.Property("RFrameRate") + .HasColumnType("TEXT"); + + b.Property("SampleAspectRatio") + .HasColumnType("TEXT"); + + b.Property("SongId") + .HasColumnType("INTEGER"); + + b.Property("VideoScanKind") + .HasColumnType("INTEGER"); + + b.Property("Width") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("EpisodeId"); + + b.HasIndex("MovieId"); + + b.HasIndex("MusicVideoId"); + + b.HasIndex("OtherVideoId"); + + b.HasIndex("SongId"); + + b.ToTable("MediaVersion", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MetadataGuid", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistMetadataId") + .HasColumnType("INTEGER"); + + b.Property("EpisodeMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Guid") + .HasColumnType("TEXT"); + + b.Property("MovieMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SeasonMetadataId") + .HasColumnType("INTEGER"); + + b.Property("ShowMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SongMetadataId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("MusicVideoMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.HasIndex("SeasonMetadataId"); + + b.HasIndex("ShowMetadataId"); + + b.HasIndex("SongMetadataId"); + + b.ToTable("MetadataGuid", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Mood", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.ToTable("Mood"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MovieMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ContentRating") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("MetadataKind") + .HasColumnType("INTEGER"); + + b.Property("MovieId") + .HasColumnType("INTEGER"); + + b.Property("OriginalTitle") + .HasColumnType("TEXT"); + + b.Property("Outline") + .HasColumnType("TEXT"); + + b.Property("Plot") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("SortTitle") + .HasColumnType("TEXT"); + + b.Property("Tagline") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("MovieId"); + + b.ToTable("MovieMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MultiCollection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("MultiCollection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MultiCollectionItem", b => + { + b.Property("MultiCollectionId") + .HasColumnType("INTEGER"); + + b.Property("CollectionId") + .HasColumnType("INTEGER"); + + b.Property("PlaybackOrder") + .HasColumnType("INTEGER"); + + b.Property("ScheduleAsGroup") + .HasColumnType("INTEGER"); + + b.HasKey("MultiCollectionId", "CollectionId"); + + b.HasIndex("CollectionId"); + + b.ToTable("MultiCollectionItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MultiCollectionSmartItem", b => + { + b.Property("MultiCollectionId") + .HasColumnType("INTEGER"); + + b.Property("SmartCollectionId") + .HasColumnType("INTEGER"); + + b.Property("PlaybackOrder") + .HasColumnType("INTEGER"); + + b.Property("ScheduleAsGroup") + .HasColumnType("INTEGER"); + + b.HasKey("MultiCollectionId", "SmartCollectionId"); + + b.HasIndex("SmartCollectionId"); + + b.ToTable("MultiCollectionSmartItem"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideoMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Album") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("MetadataKind") + .HasColumnType("INTEGER"); + + b.Property("MusicVideoId") + .HasColumnType("INTEGER"); + + b.Property("OriginalTitle") + .HasColumnType("TEXT"); + + b.Property("Plot") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("SortTitle") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("MusicVideoId"); + + b.ToTable("MusicVideoMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.OtherVideoMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("MetadataKind") + .HasColumnType("INTEGER"); + + b.Property("OriginalTitle") + .HasColumnType("TEXT"); + + b.Property("OtherVideoId") + .HasColumnType("INTEGER"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("SortTitle") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("OtherVideoId"); + + b.ToTable("OtherVideoMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Playout", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChannelId") + .HasColumnType("INTEGER"); + + b.Property("DailyRebuildTime") + .HasColumnType("TEXT"); + + b.Property("ProgramScheduleId") + .HasColumnType("INTEGER"); + + b.Property("ProgramSchedulePlayoutType") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ChannelId"); + + b.HasIndex("ProgramScheduleId"); + + b.ToTable("Playout", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ChapterTitle") + .HasColumnType("TEXT"); + + b.Property("CustomTitle") + .HasColumnType("TEXT"); + + b.Property("FillerKind") + .HasColumnType("INTEGER"); + + b.Property("Finish") + .HasColumnType("TEXT"); + + b.Property("GuideFinish") + .HasColumnType("TEXT"); + + b.Property("GuideGroup") + .HasColumnType("INTEGER"); + + b.Property("InPoint") + .HasColumnType("TEXT"); + + b.Property("MediaItemId") + .HasColumnType("INTEGER"); + + b.Property("OutPoint") + .HasColumnType("TEXT"); + + b.Property("PlayoutId") + .HasColumnType("INTEGER"); + + b.Property("Start") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("PlayoutId"); + + b.ToTable("PlayoutItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutProgramScheduleAnchor", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CollectionId") + .HasColumnType("INTEGER"); + + b.Property("CollectionType") + .HasColumnType("INTEGER"); + + b.Property("MediaItemId") + .HasColumnType("INTEGER"); + + b.Property("MultiCollectionId") + .HasColumnType("INTEGER"); + + b.Property("PlayoutId") + .HasColumnType("INTEGER"); + + b.Property("ProgramScheduleId") + .HasColumnType("INTEGER"); + + b.Property("SmartCollectionId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("CollectionId"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("MultiCollectionId"); + + b.HasIndex("PlayoutId"); + + b.HasIndex("ProgramScheduleId"); + + b.HasIndex("SmartCollectionId"); + + b.ToTable("PlayoutProgramScheduleAnchor", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexConnection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("IsActive") + .HasColumnType("INTEGER"); + + b.Property("PlexMediaSourceId") + .HasColumnType("INTEGER"); + + b.Property("Uri") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("PlexMediaSourceId"); + + b.ToTable("PlexConnection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexPathReplacement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("LocalPath") + .HasColumnType("TEXT"); + + b.Property("PlexMediaSourceId") + .HasColumnType("INTEGER"); + + b.Property("PlexPath") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("PlexMediaSourceId"); + + b.ToTable("PlexPathReplacement", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramSchedule", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("KeepMultiPartEpisodesTogether") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("TreatCollectionsAsShows") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("Name") + .IsUnique(); + + b.ToTable("ProgramSchedule", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("CollectionId") + .HasColumnType("INTEGER"); + + b.Property("CollectionType") + .HasColumnType("INTEGER"); + + b.Property("CustomTitle") + .HasColumnType("TEXT"); + + b.Property("FallbackFillerId") + .HasColumnType("INTEGER"); + + b.Property("GuideMode") + .HasColumnType("INTEGER"); + + b.Property("Index") + .HasColumnType("INTEGER"); + + b.Property("MediaItemId") + .HasColumnType("INTEGER"); + + b.Property("MidRollFillerId") + .HasColumnType("INTEGER"); + + b.Property("MultiCollectionId") + .HasColumnType("INTEGER"); + + b.Property("PlaybackOrder") + .HasColumnType("INTEGER"); + + b.Property("PostRollFillerId") + .HasColumnType("INTEGER"); + + b.Property("PreRollFillerId") + .HasColumnType("INTEGER"); + + b.Property("ProgramScheduleId") + .HasColumnType("INTEGER"); + + b.Property("SmartCollectionId") + .HasColumnType("INTEGER"); + + b.Property("StartTime") + .HasColumnType("TEXT"); + + b.Property("TailFillerId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("CollectionId"); + + b.HasIndex("FallbackFillerId"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("MidRollFillerId"); + + b.HasIndex("MultiCollectionId"); + + b.HasIndex("PostRollFillerId"); + + b.HasIndex("PreRollFillerId"); + + b.HasIndex("ProgramScheduleId"); + + b.HasIndex("SmartCollectionId"); + + b.HasIndex("TailFillerId"); + + b.ToTable("ProgramScheduleItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Resolution", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Height") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Width") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.ToTable("Resolution", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SeasonMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("MetadataKind") + .HasColumnType("INTEGER"); + + b.Property("OriginalTitle") + .HasColumnType("TEXT"); + + b.Property("Outline") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("SeasonId") + .HasColumnType("INTEGER"); + + b.Property("SortTitle") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("SeasonId"); + + b.ToTable("SeasonMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ShowMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ContentRating") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("MetadataKind") + .HasColumnType("INTEGER"); + + b.Property("OriginalTitle") + .HasColumnType("TEXT"); + + b.Property("Outline") + .HasColumnType("TEXT"); + + b.Property("Plot") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("ShowId") + .HasColumnType("INTEGER"); + + b.Property("SortTitle") + .HasColumnType("TEXT"); + + b.Property("Tagline") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ShowId"); + + b.ToTable("ShowMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SmartCollection", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("Query") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("SmartCollection", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SongMetadata", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Album") + .HasColumnType("TEXT"); + + b.Property("Artist") + .HasColumnType("TEXT"); + + b.Property("Date") + .HasColumnType("TEXT"); + + b.Property("DateAdded") + .HasColumnType("TEXT"); + + b.Property("DateUpdated") + .HasColumnType("TEXT"); + + b.Property("MetadataKind") + .HasColumnType("INTEGER"); + + b.Property("OriginalTitle") + .HasColumnType("TEXT"); + + b.Property("ReleaseDate") + .HasColumnType("TEXT"); + + b.Property("SongId") + .HasColumnType("INTEGER"); + + b.Property("SortTitle") + .HasColumnType("TEXT"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("Track") + .HasColumnType("TEXT"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("SongId"); + + b.ToTable("SongMetadata", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Studio", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistMetadataId") + .HasColumnType("INTEGER"); + + b.Property("EpisodeMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MovieMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SeasonMetadataId") + .HasColumnType("INTEGER"); + + b.Property("ShowMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SongMetadataId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("MusicVideoMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.HasIndex("SeasonMetadataId"); + + b.HasIndex("ShowMetadataId"); + + b.HasIndex("SongMetadataId"); + + b.ToTable("Studio", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Style", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.ToTable("Style"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Tag", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("ArtistMetadataId") + .HasColumnType("INTEGER"); + + b.Property("EpisodeMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MovieMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MusicVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("OtherVideoMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SeasonMetadataId") + .HasColumnType("INTEGER"); + + b.Property("ShowMetadataId") + .HasColumnType("INTEGER"); + + b.Property("SongMetadataId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("ArtistMetadataId"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.HasIndex("MusicVideoMetadataId"); + + b.HasIndex("OtherVideoMetadataId"); + + b.HasIndex("SeasonMetadataId"); + + b.HasIndex("ShowMetadataId"); + + b.HasIndex("SongMetadataId"); + + b.ToTable("Tag"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktList", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Description") + .HasColumnType("TEXT"); + + b.Property("ItemCount") + .HasColumnType("INTEGER"); + + b.Property("List") + .HasColumnType("TEXT"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.Property("TraktId") + .HasColumnType("INTEGER"); + + b.Property("User") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.ToTable("TraktList", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktListItem", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Episode") + .HasColumnType("INTEGER"); + + b.Property("Kind") + .HasColumnType("INTEGER"); + + b.Property("MediaItemId") + .HasColumnType("INTEGER"); + + b.Property("Rank") + .HasColumnType("INTEGER"); + + b.Property("Season") + .HasColumnType("INTEGER"); + + b.Property("Title") + .HasColumnType("TEXT"); + + b.Property("TraktId") + .HasColumnType("INTEGER"); + + b.Property("TraktListId") + .HasColumnType("INTEGER"); + + b.Property("Year") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("MediaItemId"); + + b.HasIndex("TraktListId"); + + b.ToTable("TraktListItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktListItemGuid", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("Guid") + .HasColumnType("TEXT"); + + b.Property("TraktListItemId") + .HasColumnType("INTEGER"); + + b.HasKey("Id"); + + b.HasIndex("TraktListItemId"); + + b.ToTable("TraktListItemGuid", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Writer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("INTEGER"); + + b.Property("EpisodeMetadataId") + .HasColumnType("INTEGER"); + + b.Property("MovieMetadataId") + .HasColumnType("INTEGER"); + + b.Property("Name") + .HasColumnType("TEXT"); + + b.HasKey("Id"); + + b.HasIndex("EpisodeMetadataId"); + + b.HasIndex("MovieMetadataId"); + + b.ToTable("Writer", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Artist", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.ToTable("Artist", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyLibrary", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Library"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.Property("ShouldSyncItems") + .HasColumnType("INTEGER"); + + b.ToTable("EmbyLibrary", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyMediaSource", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaSource"); + + b.Property("OperatingSystem") + .HasColumnType("TEXT"); + + b.Property("ServerName") + .HasColumnType("TEXT"); + + b.ToTable("EmbyMediaSource", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Episode", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.Property("SeasonId") + .HasColumnType("INTEGER"); + + b.HasIndex("SeasonId"); + + b.ToTable("Episode", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinLibrary", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Library"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.Property("ShouldSyncItems") + .HasColumnType("INTEGER"); + + b.ToTable("JellyfinLibrary", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinMediaSource", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaSource"); + + b.Property("OperatingSystem") + .HasColumnType("TEXT"); + + b.Property("ServerName") + .HasColumnType("TEXT"); + + b.ToTable("JellyfinMediaSource", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LocalLibrary", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Library"); + + b.ToTable("LocalLibrary", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LocalMediaSource", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaSource"); + + b.ToTable("LocalMediaSource", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Movie", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.ToTable("Movie", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideo", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.Property("ArtistId") + .HasColumnType("INTEGER"); + + b.HasIndex("ArtistId"); + + b.ToTable("MusicVideo", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.OtherVideo", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.ToTable("OtherVideo", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexLibrary", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Library"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("ShouldSyncItems") + .HasColumnType("INTEGER"); + + b.ToTable("PlexLibrary", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMediaFile", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaFile"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.Property("PlexId") + .HasColumnType("INTEGER"); + + b.ToTable("PlexMediaFile", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMediaSource", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaSource"); + + b.Property("ClientIdentifier") + .HasColumnType("TEXT"); + + b.Property("Platform") + .HasColumnType("TEXT"); + + b.Property("PlatformVersion") + .HasColumnType("TEXT"); + + b.Property("ProductVersion") + .HasColumnType("TEXT"); + + b.Property("ServerName") + .HasColumnType("TEXT"); + + b.ToTable("PlexMediaSource", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemDuration", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.ProgramScheduleItem"); + + b.Property("PlayoutDuration") + .HasColumnType("TEXT"); + + b.Property("TailMode") + .HasColumnType("INTEGER"); + + b.ToTable("ProgramScheduleDurationItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemFlood", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.ProgramScheduleItem"); + + b.ToTable("ProgramScheduleFloodItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemMultiple", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.ProgramScheduleItem"); + + b.Property("Count") + .HasColumnType("INTEGER"); + + b.ToTable("ProgramScheduleMultipleItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemOne", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.ProgramScheduleItem"); + + b.ToTable("ProgramScheduleOneItem", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Season", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.Property("SeasonNumber") + .HasColumnType("INTEGER"); + + b.Property("ShowId") + .HasColumnType("INTEGER"); + + b.HasIndex("ShowId"); + + b.ToTable("Season", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Show", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.ToTable("Show", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Song", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.MediaItem"); + + b.ToTable("Song", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyEpisode", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Episode"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.ToTable("EmbyEpisode", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyMovie", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Movie"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.ToTable("EmbyMovie", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbySeason", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Season"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.ToTable("EmbySeason", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyShow", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Show"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.ToTable("EmbyShow", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinEpisode", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Episode"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.ToTable("JellyfinEpisode", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinMovie", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Movie"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.ToTable("JellyfinMovie", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinSeason", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Season"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.ToTable("JellyfinSeason", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinShow", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Show"); + + b.Property("Etag") + .HasColumnType("TEXT"); + + b.Property("ItemId") + .HasColumnType("TEXT"); + + b.ToTable("JellyfinShow", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexEpisode", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Episode"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.ToTable("PlexEpisode", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMovie", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Movie"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.ToTable("PlexMovie", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexSeason", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Season"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.ToTable("PlexSeason", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexShow", b => + { + b.HasBaseType("ErsatzTV.Core.Domain.Show"); + + b.Property("Key") + .HasColumnType("TEXT"); + + b.ToTable("PlexShow", (string)null); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Actor", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Actors") + .HasForeignKey("ArtistMetadataId"); + + b.HasOne("ErsatzTV.Core.Domain.Artwork", "Artwork") + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Actor", "ArtworkId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Actors") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Actors") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Actors") + .HasForeignKey("MusicVideoMetadataId"); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Actors") + .HasForeignKey("OtherVideoMetadataId"); + + b.HasOne("ErsatzTV.Core.Domain.SeasonMetadata", null) + .WithMany("Actors") + .HasForeignKey("SeasonMetadataId"); + + b.HasOne("ErsatzTV.Core.Domain.ShowMetadata", null) + .WithMany("Actors") + .HasForeignKey("ShowMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SongMetadata", null) + .WithMany("Actors") + .HasForeignKey("SongMetadataId"); + + b.Navigation("Artwork"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ArtistMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.Artist", "Artist") + .WithMany("ArtistMetadata") + .HasForeignKey("ArtistId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Artist"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Artwork", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Artwork") + .HasForeignKey("ArtistMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Channel", null) + .WithMany("Artwork") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Artwork") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Artwork") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Artwork") + .HasForeignKey("MusicVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Artwork") + .HasForeignKey("OtherVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SeasonMetadata", null) + .WithMany("Artwork") + .HasForeignKey("SeasonMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ShowMetadata", null) + .WithMany("Artwork") + .HasForeignKey("ShowMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SongMetadata", null) + .WithMany("Artwork") + .HasForeignKey("SongMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Channel", b => + { + b.HasOne("ErsatzTV.Core.Domain.FFmpegProfile", "FFmpegProfile") + .WithMany() + .HasForeignKey("FFmpegProfileId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Filler.FillerPreset", "FallbackFiller") + .WithMany() + .HasForeignKey("FallbackFillerId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.ChannelWatermark", "Watermark") + .WithMany() + .HasForeignKey("WatermarkId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("FFmpegProfile"); + + b.Navigation("FallbackFiller"); + + b.Navigation("Watermark"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.CollectionItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany("CollectionItems") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany("CollectionItems") + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Collection"); + + b.Navigation("MediaItem"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Director", b => + { + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Directors") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Directors") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyConnection", b => + { + b.HasOne("ErsatzTV.Core.Domain.EmbyMediaSource", "EmbyMediaSource") + .WithMany("Connections") + .HasForeignKey("EmbyMediaSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("EmbyMediaSource"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyPathReplacement", b => + { + b.HasOne("ErsatzTV.Core.Domain.EmbyMediaSource", "EmbyMediaSource") + .WithMany("PathReplacements") + .HasForeignKey("EmbyMediaSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("EmbyMediaSource"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EpisodeMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.Episode", "Episode") + .WithMany("EpisodeMetadata") + .HasForeignKey("EpisodeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Episode"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.FFmpegProfile", b => + { + b.HasOne("ErsatzTV.Core.Domain.Resolution", "Resolution") + .WithMany() + .HasForeignKey("ResolutionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Resolution"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Filler.FillerPreset", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany() + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany() + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "SmartCollection") + .WithMany() + .HasForeignKey("SmartCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.Navigation("Collection"); + + b.Navigation("MediaItem"); + + b.Navigation("MultiCollection"); + + b.Navigation("SmartCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Genre", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Genres") + .HasForeignKey("ArtistMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Genres") + .HasForeignKey("EpisodeMetadataId"); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Genres") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Genres") + .HasForeignKey("MusicVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Genres") + .HasForeignKey("OtherVideoMetadataId"); + + b.HasOne("ErsatzTV.Core.Domain.SeasonMetadata", null) + .WithMany("Genres") + .HasForeignKey("SeasonMetadataId"); + + b.HasOne("ErsatzTV.Core.Domain.ShowMetadata", null) + .WithMany("Genres") + .HasForeignKey("ShowMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SongMetadata", null) + .WithMany("Genres") + .HasForeignKey("SongMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinConnection", b => + { + b.HasOne("ErsatzTV.Core.Domain.JellyfinMediaSource", "JellyfinMediaSource") + .WithMany("Connections") + .HasForeignKey("JellyfinMediaSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("JellyfinMediaSource"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinPathReplacement", b => + { + b.HasOne("ErsatzTV.Core.Domain.JellyfinMediaSource", "JellyfinMediaSource") + .WithMany("PathReplacements") + .HasForeignKey("JellyfinMediaSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("JellyfinMediaSource"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Library", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaSource", "MediaSource") + .WithMany("Libraries") + .HasForeignKey("MediaSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaSource"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LibraryFolder", b => + { + b.HasOne("ErsatzTV.Core.Domain.LibraryPath", "LibraryPath") + .WithMany("LibraryFolders") + .HasForeignKey("LibraryPathId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LibraryPath"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LibraryPath", b => + { + b.HasOne("ErsatzTV.Core.Domain.Library", "Library") + .WithMany("Paths") + .HasForeignKey("LibraryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Library"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaChapter", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaVersion", "MediaVersion") + .WithMany("Chapters") + .HasForeignKey("MediaVersionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaVersion"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaFile", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaVersion", "MediaVersion") + .WithMany("MediaFiles") + .HasForeignKey("MediaVersionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaVersion"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.LibraryPath", "LibraryPath") + .WithMany("MediaItems") + .HasForeignKey("LibraryPathId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("LibraryPath"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaStream", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaVersion", "MediaVersion") + .WithMany("Streams") + .HasForeignKey("MediaVersionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaVersion"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaVersion", b => + { + b.HasOne("ErsatzTV.Core.Domain.Episode", null) + .WithMany("MediaVersions") + .HasForeignKey("EpisodeId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Movie", null) + .WithMany("MediaVersions") + .HasForeignKey("MovieId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideo", null) + .WithMany("MediaVersions") + .HasForeignKey("MusicVideoId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideo", null) + .WithMany("MediaVersions") + .HasForeignKey("OtherVideoId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Song", null) + .WithMany("MediaVersions") + .HasForeignKey("SongId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MetadataGuid", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Guids") + .HasForeignKey("ArtistMetadataId"); + + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Guids") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Guids") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Guids") + .HasForeignKey("MusicVideoMetadataId"); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Guids") + .HasForeignKey("OtherVideoMetadataId"); + + b.HasOne("ErsatzTV.Core.Domain.SeasonMetadata", null) + .WithMany("Guids") + .HasForeignKey("SeasonMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.ShowMetadata", null) + .WithMany("Guids") + .HasForeignKey("ShowMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SongMetadata", null) + .WithMany("Guids") + .HasForeignKey("SongMetadataId"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Mood", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Moods") + .HasForeignKey("ArtistMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MovieMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.Movie", "Movie") + .WithMany("MovieMetadata") + .HasForeignKey("MovieId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Movie"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MultiCollectionItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany("MultiCollectionItems") + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany("MultiCollectionItems") + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Collection"); + + b.Navigation("MultiCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MultiCollectionSmartItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany("MultiCollectionSmartItems") + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "SmartCollection") + .WithMany("MultiCollectionSmartItems") + .HasForeignKey("SmartCollectionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MultiCollection"); + + b.Navigation("SmartCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideoMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.MusicVideo", "MusicVideo") + .WithMany("MusicVideoMetadata") + .HasForeignKey("MusicVideoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MusicVideo"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.OtherVideoMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.OtherVideo", "OtherVideo") + .WithMany("OtherVideoMetadata") + .HasForeignKey("OtherVideoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OtherVideo"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Playout", b => + { + b.HasOne("ErsatzTV.Core.Domain.Channel", "Channel") + .WithMany("Playouts") + .HasForeignKey("ChannelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.ProgramSchedule", "ProgramSchedule") + .WithMany("Playouts") + .HasForeignKey("ProgramScheduleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.OwnsOne("ErsatzTV.Core.Domain.PlayoutAnchor", "Anchor", b1 => + { + b1.Property("PlayoutId") + .HasColumnType("INTEGER"); + + b1.Property("DurationFinish") + .HasColumnType("TEXT"); + + b1.Property("InDurationFiller") + .HasColumnType("INTEGER"); + + b1.Property("InFlood") + .HasColumnType("INTEGER"); + + b1.Property("MultipleRemaining") + .HasColumnType("INTEGER"); + + b1.Property("NextGuideGroup") + .HasColumnType("INTEGER"); + + b1.Property("NextScheduleItemId") + .HasColumnType("INTEGER"); + + b1.Property("NextStart") + .HasColumnType("TEXT"); + + b1.HasKey("PlayoutId"); + + b1.HasIndex("NextScheduleItemId"); + + b1.ToTable("PlayoutAnchor", (string)null); + + b1.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", "NextScheduleItem") + .WithMany() + .HasForeignKey("NextScheduleItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b1.WithOwner() + .HasForeignKey("PlayoutId"); + + b1.Navigation("NextScheduleItem"); + }); + + b.Navigation("Anchor"); + + b.Navigation("Channel"); + + b.Navigation("ProgramSchedule"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany() + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Playout", "Playout") + .WithMany("Items") + .HasForeignKey("PlayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaItem"); + + b.Navigation("Playout"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlayoutProgramScheduleAnchor", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany() + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany() + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Playout", "Playout") + .WithMany("ProgramScheduleAnchors") + .HasForeignKey("PlayoutId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.ProgramSchedule", "ProgramSchedule") + .WithMany() + .HasForeignKey("ProgramScheduleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "SmartCollection") + .WithMany() + .HasForeignKey("SmartCollectionId"); + + b.OwnsOne("ErsatzTV.Core.Domain.CollectionEnumeratorState", "EnumeratorState", b1 => + { + b1.Property("PlayoutProgramScheduleAnchorId") + .HasColumnType("INTEGER"); + + b1.Property("Index") + .HasColumnType("INTEGER"); + + b1.Property("Seed") + .HasColumnType("INTEGER"); + + b1.HasKey("PlayoutProgramScheduleAnchorId"); + + b1.ToTable("CollectionEnumeratorState", (string)null); + + b1.WithOwner() + .HasForeignKey("PlayoutProgramScheduleAnchorId"); + }); + + b.Navigation("Collection"); + + b.Navigation("EnumeratorState"); + + b.Navigation("MediaItem"); + + b.Navigation("MultiCollection"); + + b.Navigation("Playout"); + + b.Navigation("ProgramSchedule"); + + b.Navigation("SmartCollection"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexConnection", b => + { + b.HasOne("ErsatzTV.Core.Domain.PlexMediaSource", "PlexMediaSource") + .WithMany("Connections") + .HasForeignKey("PlexMediaSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PlexMediaSource"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexPathReplacement", b => + { + b.HasOne("ErsatzTV.Core.Domain.PlexMediaSource", "PlexMediaSource") + .WithMany("PathReplacements") + .HasForeignKey("PlexMediaSourceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PlexMediaSource"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.Collection", "Collection") + .WithMany() + .HasForeignKey("CollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Filler.FillerPreset", "FallbackFiller") + .WithMany() + .HasForeignKey("FallbackFillerId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany() + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Filler.FillerPreset", "MidRollFiller") + .WithMany() + .HasForeignKey("MidRollFillerId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.MultiCollection", "MultiCollection") + .WithMany() + .HasForeignKey("MultiCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Filler.FillerPreset", "PostRollFiller") + .WithMany() + .HasForeignKey("PostRollFillerId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.Filler.FillerPreset", "PreRollFiller") + .WithMany() + .HasForeignKey("PreRollFillerId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.ProgramSchedule", "ProgramSchedule") + .WithMany("Items") + .HasForeignKey("ProgramScheduleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.SmartCollection", "SmartCollection") + .WithMany() + .HasForeignKey("SmartCollectionId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.Filler.FillerPreset", "TailFiller") + .WithMany() + .HasForeignKey("TailFillerId") + .OnDelete(DeleteBehavior.SetNull); + + b.Navigation("Collection"); + + b.Navigation("FallbackFiller"); + + b.Navigation("MediaItem"); + + b.Navigation("MidRollFiller"); + + b.Navigation("MultiCollection"); + + b.Navigation("PostRollFiller"); + + b.Navigation("PreRollFiller"); + + b.Navigation("ProgramSchedule"); + + b.Navigation("SmartCollection"); + + b.Navigation("TailFiller"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SeasonMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.Season", "Season") + .WithMany("SeasonMetadata") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ShowMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.Show", "Show") + .WithMany("ShowMetadata") + .HasForeignKey("ShowId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Show"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SongMetadata", b => + { + b.HasOne("ErsatzTV.Core.Domain.Song", "Song") + .WithMany("SongMetadata") + .HasForeignKey("SongId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Song"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Studio", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Studios") + .HasForeignKey("ArtistMetadataId"); + + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Studios") + .HasForeignKey("EpisodeMetadataId"); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Studios") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Studios") + .HasForeignKey("MusicVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Studios") + .HasForeignKey("OtherVideoMetadataId"); + + b.HasOne("ErsatzTV.Core.Domain.SeasonMetadata", null) + .WithMany("Studios") + .HasForeignKey("SeasonMetadataId"); + + b.HasOne("ErsatzTV.Core.Domain.ShowMetadata", null) + .WithMany("Studios") + .HasForeignKey("ShowMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SongMetadata", null) + .WithMany("Studios") + .HasForeignKey("SongMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Style", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Styles") + .HasForeignKey("ArtistMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Tag", b => + { + b.HasOne("ErsatzTV.Core.Domain.ArtistMetadata", null) + .WithMany("Tags") + .HasForeignKey("ArtistMetadataId"); + + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Tags") + .HasForeignKey("EpisodeMetadataId"); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Tags") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MusicVideoMetadata", null) + .WithMany("Tags") + .HasForeignKey("MusicVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.OtherVideoMetadata", null) + .WithMany("Tags") + .HasForeignKey("OtherVideoMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SeasonMetadata", null) + .WithMany("Tags") + .HasForeignKey("SeasonMetadataId"); + + b.HasOne("ErsatzTV.Core.Domain.ShowMetadata", null) + .WithMany("Tags") + .HasForeignKey("ShowMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.SongMetadata", null) + .WithMany("Tags") + .HasForeignKey("SongMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktListItem", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", "MediaItem") + .WithMany("TraktListItems") + .HasForeignKey("MediaItemId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("ErsatzTV.Core.Domain.TraktList", "TraktList") + .WithMany("Items") + .HasForeignKey("TraktListId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("MediaItem"); + + b.Navigation("TraktList"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktListItemGuid", b => + { + b.HasOne("ErsatzTV.Core.Domain.TraktListItem", "TraktListItem") + .WithMany("Guids") + .HasForeignKey("TraktListItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("TraktListItem"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Writer", b => + { + b.HasOne("ErsatzTV.Core.Domain.EpisodeMetadata", null) + .WithMany("Writers") + .HasForeignKey("EpisodeMetadataId") + .OnDelete(DeleteBehavior.Cascade); + + b.HasOne("ErsatzTV.Core.Domain.MovieMetadata", null) + .WithMany("Writers") + .HasForeignKey("MovieMetadataId") + .OnDelete(DeleteBehavior.Cascade); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Artist", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Artist", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyLibrary", b => + { + b.HasOne("ErsatzTV.Core.Domain.Library", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.EmbyLibrary", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyMediaSource", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaSource", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.EmbyMediaSource", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Episode", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Episode", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Season", "Season") + .WithMany("Episodes") + .HasForeignKey("SeasonId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Season"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinLibrary", b => + { + b.HasOne("ErsatzTV.Core.Domain.Library", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.JellyfinLibrary", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinMediaSource", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaSource", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.JellyfinMediaSource", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LocalLibrary", b => + { + b.HasOne("ErsatzTV.Core.Domain.Library", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.LocalLibrary", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LocalMediaSource", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaSource", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.LocalMediaSource", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Movie", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Movie", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideo", b => + { + b.HasOne("ErsatzTV.Core.Domain.Artist", "Artist") + .WithMany("MusicVideos") + .HasForeignKey("ArtistId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.MusicVideo", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Artist"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.OtherVideo", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.OtherVideo", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexLibrary", b => + { + b.HasOne("ErsatzTV.Core.Domain.Library", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexLibrary", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMediaFile", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaFile", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexMediaFile", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMediaSource", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaSource", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexMediaSource", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemDuration", b => + { + b.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.ProgramScheduleItemDuration", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemFlood", b => + { + b.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.ProgramScheduleItemFlood", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemMultiple", b => + { + b.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.ProgramScheduleItemMultiple", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramScheduleItemOne", b => + { + b.HasOne("ErsatzTV.Core.Domain.ProgramScheduleItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.ProgramScheduleItemOne", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Season", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Season", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("ErsatzTV.Core.Domain.Show", "Show") + .WithMany("Seasons") + .HasForeignKey("ShowId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Show"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Show", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Show", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Song", b => + { + b.HasOne("ErsatzTV.Core.Domain.MediaItem", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.Song", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyEpisode", b => + { + b.HasOne("ErsatzTV.Core.Domain.Episode", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.EmbyEpisode", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyMovie", b => + { + b.HasOne("ErsatzTV.Core.Domain.Movie", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.EmbyMovie", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbySeason", b => + { + b.HasOne("ErsatzTV.Core.Domain.Season", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.EmbySeason", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyShow", b => + { + b.HasOne("ErsatzTV.Core.Domain.Show", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.EmbyShow", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinEpisode", b => + { + b.HasOne("ErsatzTV.Core.Domain.Episode", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.JellyfinEpisode", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinMovie", b => + { + b.HasOne("ErsatzTV.Core.Domain.Movie", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.JellyfinMovie", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinSeason", b => + { + b.HasOne("ErsatzTV.Core.Domain.Season", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.JellyfinSeason", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinShow", b => + { + b.HasOne("ErsatzTV.Core.Domain.Show", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.JellyfinShow", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexEpisode", b => + { + b.HasOne("ErsatzTV.Core.Domain.Episode", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexEpisode", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMovie", b => + { + b.HasOne("ErsatzTV.Core.Domain.Movie", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexMovie", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexSeason", b => + { + b.HasOne("ErsatzTV.Core.Domain.Season", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexSeason", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexShow", b => + { + b.HasOne("ErsatzTV.Core.Domain.Show", null) + .WithOne() + .HasForeignKey("ErsatzTV.Core.Domain.PlexShow", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ArtistMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Moods"); + + b.Navigation("Studios"); + + b.Navigation("Styles"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Channel", b => + { + b.Navigation("Artwork"); + + b.Navigation("Playouts"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Collection", b => + { + b.Navigation("CollectionItems"); + + b.Navigation("MultiCollectionItems"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EpisodeMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Directors"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Tags"); + + b.Navigation("Writers"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Library", b => + { + b.Navigation("Paths"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.LibraryPath", b => + { + b.Navigation("LibraryFolders"); + + b.Navigation("MediaItems"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaItem", b => + { + b.Navigation("CollectionItems"); + + b.Navigation("TraktListItems"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaSource", b => + { + b.Navigation("Libraries"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MediaVersion", b => + { + b.Navigation("Chapters"); + + b.Navigation("MediaFiles"); + + b.Navigation("Streams"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MovieMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Directors"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Tags"); + + b.Navigation("Writers"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MultiCollection", b => + { + b.Navigation("MultiCollectionItems"); + + b.Navigation("MultiCollectionSmartItems"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideoMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.OtherVideoMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Playout", b => + { + b.Navigation("Items"); + + b.Navigation("ProgramScheduleAnchors"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ProgramSchedule", b => + { + b.Navigation("Items"); + + b.Navigation("Playouts"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SeasonMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.ShowMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SmartCollection", b => + { + b.Navigation("MultiCollectionSmartItems"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.SongMetadata", b => + { + b.Navigation("Actors"); + + b.Navigation("Artwork"); + + b.Navigation("Genres"); + + b.Navigation("Guids"); + + b.Navigation("Studios"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktList", b => + { + b.Navigation("Items"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.TraktListItem", b => + { + b.Navigation("Guids"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Artist", b => + { + b.Navigation("ArtistMetadata"); + + b.Navigation("MusicVideos"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.EmbyMediaSource", b => + { + b.Navigation("Connections"); + + b.Navigation("PathReplacements"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Episode", b => + { + b.Navigation("EpisodeMetadata"); + + b.Navigation("MediaVersions"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.JellyfinMediaSource", b => + { + b.Navigation("Connections"); + + b.Navigation("PathReplacements"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Movie", b => + { + b.Navigation("MediaVersions"); + + b.Navigation("MovieMetadata"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.MusicVideo", b => + { + b.Navigation("MediaVersions"); + + b.Navigation("MusicVideoMetadata"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.OtherVideo", b => + { + b.Navigation("MediaVersions"); + + b.Navigation("OtherVideoMetadata"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.PlexMediaSource", b => + { + b.Navigation("Connections"); + + b.Navigation("PathReplacements"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Season", b => + { + b.Navigation("Episodes"); + + b.Navigation("SeasonMetadata"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Show", b => + { + b.Navigation("Seasons"); + + b.Navigation("ShowMetadata"); + }); + + modelBuilder.Entity("ErsatzTV.Core.Domain.Song", b => + { + b.Navigation("MediaVersions"); + + b.Navigation("SongMetadata"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/ErsatzTV.Infrastructure/Migrations/20211201191945_Reset_SongMetadataOnWindows.cs b/ErsatzTV.Infrastructure/Migrations/20211201191945_Reset_SongMetadataOnWindows.cs new file mode 100644 index 000000000..327027428 --- /dev/null +++ b/ErsatzTV.Infrastructure/Migrations/20211201191945_Reset_SongMetadataOnWindows.cs @@ -0,0 +1,34 @@ +using System.Runtime.InteropServices; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace ErsatzTV.Infrastructure.Migrations +{ + public partial class Reset_SongMetadataOnWindows : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + migrationBuilder.Sql( + @"UPDATE LibraryPath SET LastScan = '0001-01-01 00:00:00' WHERE Id IN + (SELECT LP.Id FROM LibraryPath LP INNER JOIN Library L on L.Id = LP.LibraryId WHERE MediaKind = 5)"); + + migrationBuilder.Sql( + @"UPDATE Library SET LastScan = '0001-01-01 00:00:00' WHERE MediaKind = 5"); + + migrationBuilder.Sql( + @"UPDATE SongMetadata SET DateUpdated = '0001-01-01 00:00:00'"); + + migrationBuilder.Sql( + @"UPDATE LibraryFolder SET Etag = NULL WHERE Id IN + (SELECT LF.Id FROM LibraryFolder LF INNER JOIN LibraryPath LP on LF.LibraryPathId = LP.Id INNER JOIN Library L on LP.LibraryId = L.Id WHERE MediaKind = 5)"); + } + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + } + } +} diff --git a/ErsatzTV/Startup.cs b/ErsatzTV/Startup.cs index db838a0c3..00e5e3a8b 100644 --- a/ErsatzTV/Startup.cs +++ b/ErsatzTV/Startup.cs @@ -2,6 +2,7 @@ using System; using System.Data; using System.IO; using System.Reflection; +using System.Text; using System.Threading.Channels; using Blazored.LocalStorage; using Dapper; @@ -120,6 +121,8 @@ namespace ErsatzTV services.AddCourier(Assembly.GetAssembly(typeof(LibraryScanProgress))); services.AddBlazoredLocalStorage(); + Console.OutputEncoding = Encoding.UTF8; + Log.Logger.Information( "ErsatzTV version {Version}", Assembly.GetEntryAssembly()?.GetCustomAttribute() diff --git a/lib/Serilog.Sinks.SQLite.6.0.0.nupkg b/lib/Serilog.Sinks.SQLite.6.0.0.nupkg new file mode 100644 index 0000000000000000000000000000000000000000..92c88ed8fb7f91ae5b9d91b6f933b2fc3eb391a3 GIT binary patch literal 31539 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 literal 0 HcmV?d00001