diff --git a/Directory.Packages.props b/Directory.Packages.props index 9d0a6c7f..fe4b3e30 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -1,6 +1,7 @@ true + $(NoWarn);NU1510 @@ -90,4 +91,4 @@ - \ No newline at end of file + diff --git a/Emby.Server.Implementations/ConfigurationOptions.cs b/Emby.Server.Implementations/ConfigurationOptions.cs index bddbbd67..bd682e6c 100644 --- a/Emby.Server.Implementations/ConfigurationOptions.cs +++ b/Emby.Server.Implementations/ConfigurationOptions.cs @@ -18,7 +18,6 @@ namespace Emby.Server.Implementations { FfmpegProbeSizeKey, "1G" }, { FfmpegAnalyzeDurationKey, "200M" }, { BindToUnixSocketKey, bool.FalseString }, - { SqliteCacheSizeKey, "20000" }, { FfmpegSkipValidationKey, bool.FalseString }, { FfmpegImgExtractPerfTradeoffKey, bool.FalseString }, { DetectNetworkChangeKey, bool.TrueString } diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 7da2c898..99cc2fe9 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -2,7 +2,7 @@ - $(NoWarn);CA1024;CA1031;CA1032;CA1034;CA1054;CA1055;CA1056;CA1062;CA1308;CA1303;CA1305;CA1508;CA1722;CA1724;CA1805;CA1813;CA1815;CA1816;CA1819;CA1821;CA1822;CA1823;CA1824;CA1825;CA1826;CA1830;CA1836;CA1839;CA1840;CA1841;CA1859;CA1861;CA1873;CA1911;CA2000;CA2007;CA2016;CA2025;CA2026;CA2100;CA2101;CA2102;CA2201;CA2202;CA2207;CA2208;CA2219;CA2220;CA2222;CA2225;CA2226;CA2230;CA2231;CA2234;CA2241;CA2242;CA2243;CA2244;CA2245;CA2246;CA2247;CA2248;CA2249;CA2250;CA2253;CA3001;CA3002;CA3003;CA3004;CA3005;CA3006;CA3007;CA3008;CA3009;CA3010;CA3011;CA3012;CA3061;CA3062;CA5359;CA5360;CA5361;CA5362;CA5363;CA5364;CA5365;CA5366;CA5367;CA5368;CA5369;CA5370;CA5371;CA5372;CA5373;CA5374;CA5375;CA5376;CA5377;CA5378;CA5379;CA5380;CA5381;CA5382;CA5383;CA5384;CA5385;CA5386;CA5387;CA5388;CA5389;CA5390;CA5391;CA5392;CA5393;CA5394;CA5395;CA5396;CA5397;CA5398;CA5399;CA5400;CA5401;CA5402;CA5403;NU1903;CA1848;CA1515;CA1812;CA1849;CA1860;CA1867;CA1517 + $(NoWarn);CA1024;CA1031;CA1032;CA1034;CA1054;CA1055;CA1056;CA1062;CA1308;CA1303;CA1305;CA1508;CA1722;CA1724;CA1805;CA1813;CA1815;CA1816;CA1819;CA1821;CA1822;CA1823;CA1824;CA1825;CA1826;CA1830;CA1836;CA1839;CA1840;CA1841;CA1859;CA1861;CA1873;CA1911;CA2000;CA2007;CA2016;CA2025;CA2026;CA2100;CA2101;CA2102;CA2201;CA2202;CA2207;CA2208;CA2219;CA2220;CA2222;CA2225;CA2226;CA2230;CA2231;CA2234;CA2241;CA2242;CA2243;CA2244;CA2245;CA2246;CA2247;CA2248;CA2249;CA2250;CA2253;CA3001;CA3002;CA3003;CA3004;CA3005;CA3006;CA3007;CA3008;CA3009;CA3010;CA3011;CA3012;CA3061;CA3062;CA5359;CA5360;CA5361;CA5362;CA5363;CA5364;CA5365;CA5366;CA5367;CA5368;CA5369;CA5370;CA5371;CA5372;CA5373;CA5374;CA5375;CA5376;CA5377;CA5378;CA5379;CA5380;CA5381;CA5382;CA5383;CA5384;CA5385;CA5386;CA5387;CA5388;CA5389;CA5390;CA5391;CA5392;CA5393;CA5394;CA5395;CA5396;CA5397;CA5398;CA5399;CA5400;CA5401;CA5402;CA5403;NU1903;CA1848;CA1515;CA1812;CA1849;CA1860;CA1867;CA1517;NU1510 {E383961B-9356-4D5D-8233-9A1079D03055} @@ -25,10 +25,9 @@ - + - diff --git a/Emby.Server.Implementations/Library/LibraryManager.cs b/Emby.Server.Implementations/Library/LibraryManager.cs index cfa64d70..420e37ad 100644 --- a/Emby.Server.Implementations/Library/LibraryManager.cs +++ b/Emby.Server.Implementations/Library/LibraryManager.cs @@ -1223,29 +1223,26 @@ namespace Emby.Server.Implementations.Library private async Task RunPostScanTasks(IProgress progress, CancellationToken cancellationToken) { var tasks = PostScanTasks.ToList(); - - var numComplete = 0; var numTasks = tasks.Count; - foreach (var task in tasks) + if (numTasks == 0) { - // Prevent access to modified closure - var currentNumComplete = numComplete; + _itemRepository.UpdateInheritedValues(); + progress.Report(100); + return; + } + var progressValues = new double[numTasks]; + + async Task RunOneTask(ILibraryPostScanTask task, int taskIndex) + { + _logger.LogDebug("Running post-scan task {0}", task.GetType().Name); var innerProgress = new Progress(pct => { - double innerPercent = pct; - innerPercent /= 100; - innerPercent += currentNumComplete; - - innerPercent /= numTasks; - innerPercent *= 100; - - progress.Report(innerPercent); + progressValues[taskIndex] = pct; + progress.Report(progressValues.Average()); }); - _logger.LogDebug("Running post-scan task {0}", task.GetType().Name); - try { await task.Run(innerProgress, cancellationToken).ConfigureAwait(false); @@ -1260,12 +1257,12 @@ namespace Emby.Server.Implementations.Library _logger.LogError(ex, "Error running post-scan task"); } - numComplete++; - double percent = numComplete; - percent /= numTasks; - progress.Report(percent * 100); + progressValues[taskIndex] = 100; + progress.Report(progressValues.Average()); } + await Task.WhenAll(tasks.Select((task, i) => RunOneTask(task, i))).ConfigureAwait(false); + _itemRepository.UpdateInheritedValues(); progress.Report(100); @@ -1997,7 +1994,7 @@ namespace Emby.Server.Implementations.Library /// public void CreateItems(IReadOnlyList items, BaseItem? parent, CancellationToken cancellationToken) { - _itemRepository.SaveItems(items, cancellationToken); + _itemRepository.SaveItemsAsync(items, cancellationToken).GetAwaiter().GetResult(); foreach (var item in items) { @@ -2165,7 +2162,7 @@ namespace Emby.Server.Implementations.Library item.DateLastSaved = DateTime.UtcNow; } - _itemRepository.SaveItems(items, cancellationToken); + await _itemRepository.SaveItemsAsync(items, cancellationToken).ConfigureAwait(false); if (parent is Folder folder) { diff --git a/Emby.Server.Implementations/Library/UserDataManager.cs b/Emby.Server.Implementations/Library/UserDataManager.cs index fbf438c5..d3506d4d 100644 --- a/Emby.Server.Implementations/Library/UserDataManager.cs +++ b/Emby.Server.Implementations/Library/UserDataManager.cs @@ -62,24 +62,28 @@ namespace Emby.Server.Implementations.Library var keys = item.GetUserDataKeys(); using var dbContext = _repository.CreateDbContext(); - using var transaction = dbContext.Database.BeginTransaction(); - - foreach (var key in keys) + var executionStrategy = dbContext.Database.CreateExecutionStrategy(); + executionStrategy.Execute(() => { - userData.Key = key; - var userDataEntry = Map(userData, user.Id, item.Id); - if (dbContext.UserData.Any(f => f.ItemId == userDataEntry.ItemId && f.UserId == userDataEntry.UserId && f.CustomDataKey == userDataEntry.CustomDataKey)) - { - dbContext.UserData.Attach(userDataEntry).State = EntityState.Modified; - } - else - { - dbContext.UserData.Add(userDataEntry); - } - } + using var transaction = dbContext.Database.BeginTransaction(); - dbContext.SaveChanges(); - transaction.Commit(); + foreach (var key in keys) + { + userData.Key = key; + var userDataEntry = Map(userData, user.Id, item.Id); + if (dbContext.UserData.Any(f => f.ItemId == userDataEntry.ItemId && f.UserId == userDataEntry.UserId && f.CustomDataKey == userDataEntry.CustomDataKey)) + { + dbContext.UserData.Attach(userDataEntry).State = EntityState.Modified; + } + else + { + dbContext.UserData.Add(userDataEntry); + } + } + + dbContext.SaveChanges(); + transaction.Commit(); + }); var userId = user.InternalId; var cacheKey = GetCacheKey(userId, item.Id); diff --git a/Jellyfin.Api/Controllers/DatabaseViewsController.cs b/Jellyfin.Api/Controllers/DatabaseViewsController.cs new file mode 100644 index 00000000..e69ae6b2 --- /dev/null +++ b/Jellyfin.Api/Controllers/DatabaseViewsController.cs @@ -0,0 +1,302 @@ +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +namespace Jellyfin.Api.Controllers; + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Jellyfin.Database.Implementations; +using Jellyfin.Database.Implementations.Entities.Views; +using MediaBrowser.Common.Api; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +/// +/// Exposes the PostgreSQL reporting views as read-only API endpoints. +/// All endpoints require administrator privileges. +/// +[Route("DatabaseViews")] +[Authorize(Policy = Policies.RequiresElevation)] +public class DatabaseViewsController : BaseJellyfinApiController +{ + private readonly IDbContextFactory _dbFactory; + + /// + /// Initializes a new instance of the class. + /// + /// The EF Core context factory. + public DatabaseViewsController(IDbContextFactory dbFactory) + { + _dbFactory = dbFactory; + } + + /// + /// Gets a flat list of all media streams (audio + video columns merged). + /// Maps to library."MediaStreamInfos_v". + /// + /// Optional item ID filter. + /// Optional stream type filter (0=Audio, 1=Video, 2=Subtitle). + /// Record index to start at. + /// Maximum records to return (1-1000, default 100). + /// List of media stream rows. + [HttpGet("MediaStreamInfos")] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task>> GetMediaStreamInfos( + [FromQuery] Guid? itemId = null, + [FromQuery] int? streamType = null, + [FromQuery] int startIndex = 0, + [FromQuery] int limit = 100) + { + limit = Math.Clamp(limit, 1, 1000); + await using var db = await _dbFactory.CreateDbContextAsync().ConfigureAwait(false); + + var query = db.MediaStreamInfoViews.AsNoTracking(); + if (itemId.HasValue) + { + var id = itemId.Value; + query = query.Where(x => x.ItemId.HasValue && x.ItemId.Value.Equals(id)); + } + + if (streamType.HasValue) + { + query = query.Where(x => x.StreamType == streamType.Value); + } + + IEnumerable results = await query + .OrderBy(x => x.ItemId) + .ThenBy(x => x.StreamIndex) + .Skip(startIndex) + .Take(limit) + .ToListAsync() + .ConfigureAwait(false); + + return Ok(results); + } + + /// + /// Gets video items joined with primary stream technical details. + /// Maps to library."VideoItems_v". + /// + /// Optional partial type filter (e.g. "Movie", "Episode"). + /// Optional minimum video height (e.g. 2160 for 4K). + /// Optional HDR format ("Dolby Vision", "HDR10+", "HDR10", "HLG", "SDR"). + /// Record index to start at. + /// Maximum records to return (1-1000, default 100). + /// List of video item rows. + [HttpGet("VideoItems")] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task>> GetVideoItems( + [FromQuery] string? type = null, + [FromQuery] int? minHeight = null, + [FromQuery] string? hdrFormat = null, + [FromQuery] int startIndex = 0, + [FromQuery] int limit = 100) + { + limit = Math.Clamp(limit, 1, 1000); + await using var db = await _dbFactory.CreateDbContextAsync().ConfigureAwait(false); + + var query = db.VideoItemViews.AsNoTracking(); + if (!string.IsNullOrEmpty(type)) + { + query = query.Where(x => x.Type != null && x.Type.Contains(type)); + } + + if (minHeight.HasValue) + { + query = query.Where(x => x.Height >= minHeight.Value); + } + + if (!string.IsNullOrEmpty(hdrFormat)) + { + query = query.Where(x => x.HDRFormat == hdrFormat); + } + + IEnumerable results = await query + .OrderBy(x => x.Name) + .Skip(startIndex) + .Take(limit) + .ToListAsync() + .ConfigureAwait(false); + + return Ok(results); + } + + /// + /// Gets per-user playback history with calculated progress percentages. + /// Maps to library."UserPlaybackHistory_v". + /// + /// Optional exact username filter. + /// Optional item ID filter. + /// When true, returns only items started but not fully played. + /// Record index to start at. + /// Maximum records to return (1-1000, default 100). + /// List of playback history rows. + [HttpGet("PlaybackHistory")] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task>> GetPlaybackHistory( + [FromQuery] string? username = null, + [FromQuery] Guid? itemId = null, + [FromQuery] bool inProgressOnly = false, + [FromQuery] int startIndex = 0, + [FromQuery] int limit = 100) + { + limit = Math.Clamp(limit, 1, 1000); + await using var db = await _dbFactory.CreateDbContextAsync().ConfigureAwait(false); + + var query = db.UserPlaybackHistoryViews.AsNoTracking(); + if (!string.IsNullOrEmpty(username)) + { + query = query.Where(x => x.Username == username); + } + + if (itemId.HasValue) + { + var id = itemId.Value; + query = query.Where(x => x.ItemId.HasValue && x.ItemId.Value.Equals(id)); + } + + if (inProgressOnly) + { + query = query.Where(x => x.Played != true && x.ProgressPct > 0); + } + + IEnumerable results = await query + .OrderByDescending(x => x.LastPlayedDate) + .Skip(startIndex) + .Take(limit) + .ToListAsync() + .ConfigureAwait(false); + + return Ok(results); + } + + /// + /// Gets items with their external provider IDs (IMDb, TMDB, TVDB, etc.) in named columns. + /// Maps to library."ItemProviders_v". + /// + /// Optional partial type filter. + /// Optional exact IMDb ID filter. + /// Optional exact TMDB ID filter. + /// Optional exact TVDB ID filter. + /// Record index to start at. + /// Maximum records to return (1-1000, default 100). + /// List of item provider rows. + [HttpGet("ItemProviders")] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task>> GetItemProviders( + [FromQuery] string? type = null, + [FromQuery] string? imdbId = null, + [FromQuery] string? tmdbId = null, + [FromQuery] string? tvdbId = null, + [FromQuery] int startIndex = 0, + [FromQuery] int limit = 100) + { + limit = Math.Clamp(limit, 1, 1000); + await using var db = await _dbFactory.CreateDbContextAsync().ConfigureAwait(false); + + var query = db.ItemProviderViews.AsNoTracking(); + if (!string.IsNullOrEmpty(type)) + { + query = query.Where(x => x.Type != null && x.Type.Contains(type)); + } + + if (!string.IsNullOrEmpty(imdbId)) + { + query = query.Where(x => x.ImdbId == imdbId); + } + + if (!string.IsNullOrEmpty(tmdbId)) + { + query = query.Where(x => x.TmdbId == tmdbId); + } + + if (!string.IsNullOrEmpty(tvdbId)) + { + query = query.Where(x => x.TvdbId == tvdbId); + } + + IEnumerable results = await query + .OrderBy(x => x.Name) + .Skip(startIndex) + .Take(limit) + .ToListAsync() + .ConfigureAwait(false); + + return Ok(results); + } + + /// + /// Gets cast and crew entries linked to the items they appear in. + /// Maps to library."ItemPeople_v". + /// + /// Optional exact person name filter. + /// Optional person type filter (e.g. "Actor", "Director"). + /// Optional item ID filter. + /// Record index to start at. + /// Maximum records to return (1-1000, default 100). + /// List of item person rows. + [HttpGet("ItemPeople")] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task>> GetItemPeople( + [FromQuery] string? personName = null, + [FromQuery] string? personType = null, + [FromQuery] Guid? itemId = null, + [FromQuery] int startIndex = 0, + [FromQuery] int limit = 100) + { + limit = Math.Clamp(limit, 1, 1000); + await using var db = await _dbFactory.CreateDbContextAsync().ConfigureAwait(false); + + var query = db.ItemPersonViews.AsNoTracking(); + if (!string.IsNullOrEmpty(personName)) + { + query = query.Where(x => x.PersonName == personName); + } + + if (!string.IsNullOrEmpty(personType)) + { + query = query.Where(x => x.PersonType == personType); + } + + if (itemId.HasValue) + { + var id = itemId.Value; + query = query.Where(x => x.ItemId.HasValue && x.ItemId.Value.Equals(id)); + } + + IEnumerable results = await query + .OrderBy(x => x.PersonName) + .ThenBy(x => x.SortOrder) + .Skip(startIndex) + .Take(limit) + .ToListAsync() + .ConfigureAwait(false); + + return Ok(results); + } + + /// + /// Gets aggregate library statistics - one row per item type. + /// Maps to library."LibrarySummary_v". + /// + /// List of library summary rows, one per item type. + [HttpGet("LibrarySummary")] + [ProducesResponseType(StatusCodes.Status200OK)] + public async Task>> GetLibrarySummary() + { + await using var db = await _dbFactory.CreateDbContextAsync().ConfigureAwait(false); + + IEnumerable results = await db.LibrarySummaryViews + .AsNoTracking() + .OrderBy(x => x.Type) + .ToListAsync() + .ConfigureAwait(false); + + return Ok(results); + } +} diff --git a/Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs b/Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs index 1f06f742..00f4a8bf 100644 --- a/Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs +++ b/Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs @@ -99,23 +99,13 @@ public static class ServiceCollectionExtensions } else { - // when nothing is setup via new Database configuration, fallback to SQLite with default settings. + // PostgreSQL-only build: default to PostgreSQL when no database.xml exists. efCoreConfiguration = new DatabaseConfigurationOptions() { - DatabaseType = "Jellyfin-SQLite", + DatabaseType = "Jellyfin-PostgreSQL", LockingBehavior = DatabaseLockingBehaviorTypes.NoLock, PresetConfigurations = [ - new PresetConfigurationItem - { - Key = "SQLite", - Value = new PresetDatabaseConfiguration - { - DatabaseType = "Jellyfin-SQLite", - LockingBehavior = DatabaseLockingBehaviorTypes.NoLock, - Description = "Default SQLite database configuration. Database stored in data directory." - } - }, new PresetConfigurationItem { Key = "PostgreSQL-Local", @@ -135,7 +125,7 @@ public static class ServiceCollectionExtensions // Ensure DatabaseType is set (handle corrupted or empty configuration files) if (string.IsNullOrWhiteSpace(efCoreConfiguration.DatabaseType)) { - efCoreConfiguration.DatabaseType = "Jellyfin-SQLite"; + efCoreConfiguration.DatabaseType = "Jellyfin-PostgreSQL"; configurationManager.SaveConfiguration("database", efCoreConfiguration); } diff --git a/Jellyfin.Server.Implementations/FullSystemBackup/BackupService.cs b/Jellyfin.Server.Implementations/FullSystemBackup/BackupService.cs index c77bc3c1..d56b5569 100644 --- a/Jellyfin.Server.Implementations/FullSystemBackup/BackupService.cs +++ b/Jellyfin.Server.Implementations/FullSystemBackup/BackupService.cs @@ -15,13 +15,13 @@ using System.Text.Json.Serialization; using System.Threading; using System.Threading.Tasks; using Jellyfin.Database.Implementations; +using Jellyfin.Server.Implementations.Migrations; using Jellyfin.Server.Implementations.StorageHelpers; using Jellyfin.Server.Implementations.SystemBackupService; using MediaBrowser.Controller; using MediaBrowser.Controller.SystemBackupService; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; @@ -156,34 +156,31 @@ public class BackupService : IBackupService await using (dbContext.ConfigureAwait(false)) { // restore migration history manually - var historyEntry = zipArchive.GetEntry(NormalizePathSeparator(Path.Combine("Database", $"{nameof(HistoryRow)}.json"))); + var historyEntry = zipArchive.GetEntry(NormalizePathSeparator(Path.Combine("Database", $"{MigrationTracker.BackupEntryName}.json"))); if (historyEntry is null) { _logger.LogInformation("No backup of the history table in archive. This is required for Jellyfin operation"); throw new InvalidOperationException("Cannot restore backup that has no History data."); } - HistoryRow[] historyEntries; + MigrationRecord[] historyEntries; var historyArchive = await historyEntry.OpenAsync().ConfigureAwait(false); await using (historyArchive.ConfigureAwait(false)) { - historyEntries = await JsonSerializer.DeserializeAsync(historyArchive).ConfigureAwait(false) ?? + historyEntries = await JsonSerializer.DeserializeAsync(historyArchive).ConfigureAwait(false) ?? throw new InvalidOperationException("Cannot restore backup that has no History data."); } - var historyRepository = dbContext.GetService(); - await historyRepository.CreateIfNotExistsAsync().ConfigureAwait(false); + await MigrationTracker.EnsureTableExistsAsync(dbContext).ConfigureAwait(false); - foreach (var item in await historyRepository.GetAppliedMigrationsAsync(CancellationToken.None).ConfigureAwait(false)) + foreach (var item in await MigrationTracker.GetAppliedMigrationIdsAsync(dbContext, CancellationToken.None).ConfigureAwait(false)) { - var insertScript = historyRepository.GetDeleteScript(item.MigrationId); - await dbContext.Database.ExecuteSqlRawAsync(insertScript).ConfigureAwait(false); + await MigrationTracker.DeleteAsync(dbContext, item).ConfigureAwait(false); } foreach (var item in historyEntries) { - var insertScript = historyRepository.GetInsertScript(item); - await dbContext.Database.ExecuteSqlRawAsync(insertScript).ConfigureAwait(false); + await MigrationTracker.InsertAsync(dbContext, item.MigrationId, item.ProductVersion).ConfigureAwait(false); } dbContext.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; @@ -310,8 +307,7 @@ public class BackupService : IBackupService } // include the migration history as well - var historyRepository = dbContext.GetService(); - var migrations = await historyRepository.GetAppliedMigrationsAsync().ConfigureAwait(false); + var migrations = await MigrationTracker.GetAppliedMigrationsAsync(dbContext).ConfigureAwait(false); ICollection<(Type Type, string SourceName, Func> ValueFactory)> entityTypes = [ @@ -319,7 +315,7 @@ public class BackupService : IBackupService .GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance) .Where(e => e.PropertyType.IsAssignableTo(typeof(IQueryable))) .Select(e => (Type: e.PropertyType, dbContext.Model.FindEntityType(e.PropertyType.GetGenericArguments()[0])!.GetSchemaQualifiedTableName()!, ValueFactory: new Func>(() => GetValues((IQueryable)e.GetValue(dbContext)!)))), - (Type: typeof(HistoryRow), SourceName: nameof(HistoryRow), ValueFactory: () => migrations.ToAsyncEnumerable()) + (Type: typeof(MigrationRecord), SourceName: MigrationTracker.BackupEntryName, ValueFactory: () => migrations.ToAsyncEnumerable()) ]; manifest.DatabaseTables = entityTypes.Select(e => e.Type.Name).ToArray(); diff --git a/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs b/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs index 2e39a56b..8ce77df5 100644 --- a/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs +++ b/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs @@ -127,65 +127,69 @@ public sealed class BaseItemRepository var context = await _dbProvider.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); await using (context.ConfigureAwait(false)) { - var transaction = await context.Database.BeginTransactionAsync(cancellationToken).ConfigureAwait(false); - await using (transaction.ConfigureAwait(false)) + var executionStrategy = context.Database.CreateExecutionStrategy(); + await executionStrategy.ExecuteAsync(async () => { - var date = (DateTime?)DateTime.UtcNow; + var transaction = await context.Database.BeginTransactionAsync(cancellationToken).ConfigureAwait(false); + await using (transaction.ConfigureAwait(false)) + { + var date = (DateTime?)DateTime.UtcNow; - await EnsurePlaceholderItemAsync(context, cancellationToken).ConfigureAwait(false); + await EnsurePlaceholderItemAsync(context, cancellationToken).ConfigureAwait(false); - var relatedItems = ids.SelectMany(f => TraverseHirachyDown(f, context)).ToArray(); + var relatedItems = ids.SelectMany(f => TraverseHirachyDown(f, context)).ToArray(); - // Remove any UserData entries for the placeholder item that would conflict with the UserData - // being detached from the item being deleted. This is necessary because, during an update, - // UserData may be reattached to a new entry, but some entries can be left behind. - // Ensures there are no duplicate UserId/CustomDataKey combinations for the placeholder. - await context.UserData - .Join( - context.UserData.WhereOneOrMany(relatedItems, e => e.ItemId), - placeholder => new { placeholder.UserId, placeholder.CustomDataKey }, - userData => new { userData.UserId, userData.CustomDataKey }, - (placeholder, userData) => placeholder) - .Where(e => e.ItemId == PlaceholderId) - .ExecuteDeleteAsync(cancellationToken) - .ConfigureAwait(false); + // Remove any UserData entries for the placeholder item that would conflict with the UserData + // being detached from the item being deleted. This is necessary because, during an update, + // UserData may be reattached to a new entry, but some entries can be left behind. + // Ensures there are no duplicate UserId/CustomDataKey combinations for the placeholder. + await context.UserData + .Join( + context.UserData.WhereOneOrMany(relatedItems, e => e.ItemId), + placeholder => new { placeholder.UserId, placeholder.CustomDataKey }, + userData => new { userData.UserId, userData.CustomDataKey }, + (placeholder, userData) => placeholder) + .Where(e => e.ItemId == PlaceholderId) + .ExecuteDeleteAsync(cancellationToken) + .ConfigureAwait(false); - // Detach all user watch data - await context.UserData.WhereOneOrMany(relatedItems, e => e.ItemId) - .ExecuteUpdateAsync( - e => e - .SetProperty(f => f.RetentionDate, date) - .SetProperty(f => f.ItemId, PlaceholderId), - cancellationToken) - .ConfigureAwait(false); + // Detach all user watch data + await context.UserData.WhereOneOrMany(relatedItems, e => e.ItemId) + .ExecuteUpdateAsync( + e => e + .SetProperty(f => f.RetentionDate, date) + .SetProperty(f => f.ItemId, PlaceholderId), + cancellationToken) + .ConfigureAwait(false); - await context.AncestorIds.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); - await context.AncestorIds.WhereOneOrMany(relatedItems, e => e.ParentItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); - await context.AttachmentStreamInfos.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); - await context.BaseItemImageInfos.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); - await context.BaseItemMetadataFields.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); - await context.BaseItemProviders.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); - await context.BaseItemTrailerTypes.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); - await context.BaseItems.WhereOneOrMany(relatedItems, e => e.Id).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); - await context.Chapters.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); - await context.CustomItemDisplayPreferences.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); - await context.ItemDisplayPreferences.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); - await context.ItemValues.Where(e => e.BaseItemsMap!.Count == 0).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); - await context.ItemValuesMap.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); - await context.KeyframeData.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); - await context.MediaSegments.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); - await context.MediaStreamInfos.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); - var query = await context.PeopleBaseItemMap.WhereOneOrMany(relatedItems, e => e.ItemId) - .Select(f => f.PeopleId) - .Distinct() - .ToArrayAsync(cancellationToken) - .ConfigureAwait(false); - await context.PeopleBaseItemMap.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); - await context.Peoples.WhereOneOrMany(query, e => e.Id).Where(e => e.BaseItems!.Count == 0).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); - await context.TrickplayInfos.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); - await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); - await transaction.CommitAsync(cancellationToken).ConfigureAwait(false); - } + await context.AncestorIds.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + await context.AncestorIds.WhereOneOrMany(relatedItems, e => e.ParentItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + await context.AttachmentStreamInfos.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + await context.BaseItemImageInfos.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + await context.BaseItemMetadataFields.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + await context.BaseItemProviders.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + await context.BaseItemTrailerTypes.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + await context.BaseItems.WhereOneOrMany(relatedItems, e => e.Id).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + await context.Chapters.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + await context.CustomItemDisplayPreferences.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + await context.ItemDisplayPreferences.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + await context.ItemValues.Where(e => e.BaseItemsMap!.Count == 0).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + await context.ItemValuesMap.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + await context.KeyframeData.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + await context.MediaSegments.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + await context.MediaStreamInfos.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + var query = await context.PeopleBaseItemMap.WhereOneOrMany(relatedItems, e => e.ItemId) + .Select(f => f.PeopleId) + .Distinct() + .ToArrayAsync(cancellationToken) + .ConfigureAwait(false); + await context.PeopleBaseItemMap.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + await context.Peoples.WhereOneOrMany(query, e => e.Id).Where(e => e.BaseItems!.Count == 0).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + await context.TrickplayInfos.WhereOneOrMany(relatedItems, e => e.ItemId).ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); + await transaction.CommitAsync(cancellationToken).ConfigureAwait(false); + } + }).ConfigureAwait(false); } } catch (Npgsql.PostgresException ex) when (ex.SqlState == "40P01") // Deadlock detected @@ -237,13 +241,17 @@ public sealed class BaseItemRepository public void UpdateInheritedValues() { using var context = _dbProvider.CreateDbContext(); - using var transaction = context.Database.BeginTransaction(); + var executionStrategy = context.Database.CreateExecutionStrategy(); + executionStrategy.Execute(() => + { + using var transaction = context.Database.BeginTransaction(); - context.ItemValuesMap.Where(e => e.ItemValue.Type == ItemValueType.InheritedTags).ExecuteDelete(); - // ItemValue Inheritance is now correctly mapped via AncestorId on demand - context.SaveChanges(); + context.ItemValuesMap.Where(e => e.ItemValue.Type == ItemValueType.InheritedTags).ExecuteDelete(); + // ItemValue Inheritance is now correctly mapped via AncestorId on demand + context.SaveChanges(); - transaction.Commit(); + transaction.Commit(); + }); } /// @@ -444,7 +452,7 @@ public sealed class BaseItemRepository // Get IDs only, without DistinctBy to avoid translation errors var allIds = await dbQuery - .Select(e => new { e.Id, e.PresentationUniqueKey, e.SeriesPresentationUniqueKey }) + .Select(e => new { e.Id, e.PresentationUniqueKey, SeriesPresentationUniqueKey = e.TvExtras!.SeriesPresentationUniqueKey }) .ToListAsync(cancellationToken) .ConfigureAwait(false); @@ -500,7 +508,7 @@ public sealed class BaseItemRepository { e.Id, e.PresentationUniqueKey, - e.SeriesPresentationUniqueKey + SeriesPresentationUniqueKey = e.TvExtras!.SeriesPresentationUniqueKey }) .ToListAsync(cancellationToken) .ConfigureAwait(false); @@ -570,7 +578,7 @@ public sealed class BaseItemRepository subquery = TranslateQuery(subquery, context, filter); var subqueryGrouped = subquery - .GroupBy(g => collectionType == CollectionType.tvshows ? g.SeriesName : g.Album) + .GroupBy(g => collectionType == CollectionType.tvshows ? g.TvExtras!.SeriesName : g.AudioExtras!.Album) .Select(g => new { Key = g.Key, @@ -605,7 +613,7 @@ public sealed class BaseItemRepository // Get IDs + keys to memory (without DistinctBy in the query) var itemsWithKeys = await mainquery - .Select(e => new { e.Id, e.PresentationUniqueKey, e.SeriesPresentationUniqueKey }) + .Select(e => new { e.Id, e.PresentationUniqueKey, SeriesPresentationUniqueKey = e.TvExtras!.SeriesPresentationUniqueKey }) .ToListAsync(cancellationToken) .ConfigureAwait(false); @@ -655,7 +663,7 @@ public sealed class BaseItemRepository // Get IDs + keys to memory (without DistinctBy in the query) var itemsWithKeys = await mainquery - .Select(e => new { e.Id, e.PresentationUniqueKey, e.SeriesPresentationUniqueKey }) + .Select(e => new { e.Id, e.PresentationUniqueKey, SeriesPresentationUniqueKey = e.TvExtras!.SeriesPresentationUniqueKey }) .ToListAsync(cancellationToken) .ConfigureAwait(false); @@ -711,7 +719,7 @@ public sealed class BaseItemRepository i => new { UserId = filter.User.Id, ItemId = i.Id }, u => new { UserId = u.UserId, ItemId = u.ItemId }, (entity, data) => new { Item = entity, UserData = data }) - .GroupBy(g => g.Item.SeriesPresentationUniqueKey) + .GroupBy(g => g.Item.TvExtras!.SeriesPresentationUniqueKey) .Select(g => new { g.Key, LastPlayedDate = g.Max(u => u.UserData.LastPlayedDate) }) .Where(g => g.Key != null && g.LastPlayedDate != null && g.LastPlayedDate >= dateCutoff) .OrderByDescending(g => g.LastPlayedDate) @@ -745,7 +753,7 @@ public sealed class BaseItemRepository { // PERFORMANCE FIX: Use DistinctBy() instead of GroupBy().Select().FirstOrDefault() // to prevent correlated subqueries. See docs/database-query-optimization.md - dbQuery = dbQuery.DistinctBy(e => new { e.PresentationUniqueKey, e.SeriesPresentationUniqueKey }); + dbQuery = dbQuery.DistinctBy(e => new { e.PresentationUniqueKey, SeriesPresentationUniqueKey = e.TvExtras!.SeriesPresentationUniqueKey }); } else if (enableGroupByPresentationUniqueKey) { @@ -756,7 +764,7 @@ public sealed class BaseItemRepository else if (filter.GroupBySeriesPresentationUniqueKey) { // PERFORMANCE FIX: Use DistinctBy() instead of GroupBy().Select().FirstOrDefault() - dbQuery = dbQuery.DistinctBy(e => e.SeriesPresentationUniqueKey); + dbQuery = dbQuery.DistinctBy(e => e.TvExtras!.SeriesPresentationUniqueKey); } else { @@ -795,6 +803,11 @@ public sealed class BaseItemRepository dbQuery = dbQuery.Include(e => e.Images); } + dbQuery = dbQuery + .Include(e => e.TvExtras) + .Include(e => e.LiveTvExtras) + .Include(e => e.AudioExtras); + return dbQuery; } @@ -1100,12 +1113,20 @@ public sealed class BaseItemRepository .ToArrayAsync(cancellationToken) .ConfigureAwait(false); + var extensionUpserts = new List<(Guid ExtItemId, BaseItemTvExtras? TvExtras, BaseItemLiveTvExtras? LiveTvExtras, BaseItemAudioExtras? AudioExtras)>(); + foreach (var item in tuples) { var entity = Map(item.Item); // TODO: refactor this "inconsistency" entity.TopParentId = item.TopParent?.Id; + // Extract extension data and clear nav props before EF Core tracking + extensionUpserts.Add((entity.Id, entity.TvExtras, entity.LiveTvExtras, entity.AudioExtras)); + entity.TvExtras = null; + entity.LiveTvExtras = null; + entity.AudioExtras = null; + if (!existingItems.Any(e => e == entity.Id)) { context.BaseItems.Add(entity); @@ -1140,18 +1161,17 @@ public sealed class BaseItemRepository .ConfigureAwait(false); } - // UPSERT all providers using raw SQL with ON CONFLICT - // This is atomic and handles concurrent operations correctly - foreach (var provider in providersToUpsert) - { - await context.Database.ExecuteSqlAsync( - $@"INSERT INTO library.""BaseItemProviders"" (""ItemId"", ""ProviderId"", ""ProviderValue"") - VALUES ({entity.Id}, {provider.ProviderId}, {provider.ProviderValue}) - ON CONFLICT (""ItemId"", ""ProviderId"") - DO UPDATE SET ""ProviderValue"" = EXCLUDED.""ProviderValue""", - cancellationToken) - .ConfigureAwait(false); - } + // UPSERT all providers in a single UNNEST-based INSERT instead of one round-trip per provider + var providerItemIds = providersToUpsert.Select(_ => entity.Id).ToArray(); + var providerIds = providersToUpsert.Select(p => p.ProviderId).ToArray(); + var providerValues = providersToUpsert.Select(p => p.ProviderValue).ToArray(); + await context.Database.ExecuteSqlAsync( + $@"INSERT INTO library.base_item_providers (item_id, provider_id, provider_value) + SELECT * FROM UNNEST({providerItemIds}, {providerIds}, {providerValues}) + ON CONFLICT (item_id, provider_id) + DO UPDATE SET provider_value = EXCLUDED.provider_value", + cancellationToken) + .ConfigureAwait(false); // CRITICAL: Clear the navigation property so EF Core doesn't try to track/save these entity.Provider = null; @@ -1183,6 +1203,78 @@ public sealed class BaseItemRepository await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); + // Upsert extension table rows (BaseItemTvExtras, BaseItemLiveTvExtras, BaseItemAudioExtras) + foreach (var (extItemId, tvExtras, liveTvExtras, audioExtras) in extensionUpserts) + { + if (tvExtras is not null) + { + await context.Database.ExecuteSqlAsync( + $@"INSERT INTO library.base_item_tv_extras (item_id, series_id, season_id, series_name, season_name, series_presentation_unique_key) + VALUES ({extItemId}, {tvExtras.SeriesId}, {tvExtras.SeasonId}, {tvExtras.SeriesName}, {tvExtras.SeasonName}, {tvExtras.SeriesPresentationUniqueKey}) + ON CONFLICT (item_id) DO UPDATE SET + series_id = EXCLUDED.series_id, + season_id = EXCLUDED.season_id, + series_name = EXCLUDED.series_name, + season_name = EXCLUDED.season_name, + series_presentation_unique_key = EXCLUDED.series_presentation_unique_key", + cancellationToken).ConfigureAwait(false); + } + else + { + await context.BaseItemTvExtras + .Where(e => e.ItemId == extItemId) + .ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + } + + if (liveTvExtras is not null) + { + var startDate = liveTvExtras.StartDate.HasValue + ? (DateTime?)DateTime.SpecifyKind(liveTvExtras.StartDate.Value, DateTimeKind.Utc) + : null; + var endDate = liveTvExtras.EndDate.HasValue + ? (DateTime?)DateTime.SpecifyKind(liveTvExtras.EndDate.Value, DateTimeKind.Utc) + : null; + await context.Database.ExecuteSqlAsync( + $@"INSERT INTO library.base_item_live_tv_extras (item_id, start_date, end_date, episode_title, show_id, external_series_id, external_service_id, audio) + VALUES ({extItemId}, {startDate}, {endDate}, {liveTvExtras.EpisodeTitle}, {liveTvExtras.ShowId}, {liveTvExtras.ExternalSeriesId}, {liveTvExtras.ExternalServiceId}, {(int?)liveTvExtras.Audio}) + ON CONFLICT (item_id) DO UPDATE SET + start_date = EXCLUDED.start_date, + end_date = EXCLUDED.end_date, + episode_title = EXCLUDED.episode_title, + show_id = EXCLUDED.show_id, + external_series_id = EXCLUDED.external_series_id, + external_service_id = EXCLUDED.external_service_id, + audio = EXCLUDED.audio", + cancellationToken).ConfigureAwait(false); + } + else + { + await context.BaseItemLiveTvExtras + .Where(e => e.ItemId == extItemId) + .ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + } + + if (audioExtras is not null) + { + await context.Database.ExecuteSqlAsync( + $@"INSERT INTO library.base_item_audio_extras (item_id, album, artists, album_artists, lufs, normalization_gain) + VALUES ({extItemId}, {audioExtras.Album}, {audioExtras.Artists}, {audioExtras.AlbumArtists}, {audioExtras.LUFS}, {audioExtras.NormalizationGain}) + ON CONFLICT (item_id) DO UPDATE SET + album = EXCLUDED.album, + artists = EXCLUDED.artists, + album_artists = EXCLUDED.album_artists, + lufs = EXCLUDED.lufs, + normalization_gain = EXCLUDED.normalization_gain", + cancellationToken).ConfigureAwait(false); + } + else + { + await context.BaseItemAudioExtras + .Where(e => e.ItemId == extItemId) + .ExecuteDeleteAsync(cancellationToken).ConfigureAwait(false); + } + } + var itemValueMaps = tuples .Select(e => (e.Item, Values: GetItemValuesToSave(e.Item, e.InheritedTags))) .ToArray(); @@ -1208,7 +1300,6 @@ public sealed class BaseItemRepository Value = f.Value }).ToArray(); context.ItemValues.AddRange(missingItemValues); - await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); var itemValuesStore = existingValues.Concat(missingItemValues).ToArray(); var valueMap = itemValueMaps @@ -1249,19 +1340,36 @@ public sealed class BaseItemRepository await context.SaveChangesAsync(cancellationToken).ConfigureAwait(false); + // Hoist ancestor queries outside the per-item loop to avoid N×2 DB round-trips + var ancestorItemIds = tuples + .Where(t => t.Item.SupportsAncestors && t.AncestorIds != null) + .Select(t => t.Item.Id) + .ToArray(); + var allNeededAncestorIds = tuples + .Where(t => t.Item.SupportsAncestors && t.AncestorIds != null) + .SelectMany(t => t.AncestorIds!) + .Distinct() + .ToArray(); + var allExistingAncestorIds = ancestorItemIds.Length > 0 + ? await context.AncestorIds + .Where(e => ancestorItemIds.Contains(e.ItemId)) + .ToListAsync(cancellationToken) + .ConfigureAwait(false) + : []; + var validAncestorIdSet = allNeededAncestorIds.Length > 0 + ? (await context.BaseItems + .Where(e => allNeededAncestorIds.Contains(e.Id)) + .Select(f => f.Id) + .ToArrayAsync(cancellationToken) + .ConfigureAwait(false)).ToHashSet() + : []; + foreach (var item in tuples) { if (item.Item.SupportsAncestors && item.AncestorIds != null) { - var existingAncestorIds = await context.AncestorIds - .Where(e => e.ItemId == item.Item.Id) - .ToListAsync(cancellationToken) - .ConfigureAwait(false); - var validAncestorIds = await context.BaseItems - .Where(e => item.AncestorIds.Contains(e.Id)) - .Select(f => f.Id) - .ToArrayAsync(cancellationToken) - .ConfigureAwait(false); + var existingAncestorIds = allExistingAncestorIds.Where(e => e.ItemId == item.Item.Id).ToList(); + var validAncestorIds = item.AncestorIds.Where(validAncestorIdSet.Contains).ToArray(); foreach (var ancestorId in validAncestorIds) { var existingAncestorId = existingAncestorIds.FirstOrDefault(e => e.ParentItemId == ancestorId); @@ -1357,7 +1465,10 @@ public sealed class BaseItemRepository .Include(e => e.Provider) .Include(e => e.LockedFields) .Include(e => e.UserData) - .Include(e => e.Images); + .Include(e => e.Images) + .Include(e => e.TvExtras) + .Include(e => e.LiveTvExtras) + .Include(e => e.AudioExtras); var item = await dbQuery .FirstOrDefaultAsync(e => e.Id == id, cancellationToken) @@ -1385,7 +1496,7 @@ public sealed class BaseItemRepository dto.Id = entity.Id; dto.ParentId = entity.ParentId.GetValueOrDefault(); dto.Path = appHost?.ExpandVirtualPath(entity.Path) ?? entity.Path; - dto.EndDate = entity.EndDate; + dto.EndDate = entity.LiveTvExtras?.EndDate; dto.CommunityRating = entity.CommunityRating; dto.CustomRating = entity.CustomRating; dto.IndexNumber = entity.IndexNumber; @@ -1407,11 +1518,11 @@ public sealed class BaseItemRepository dto.CriticRating = entity.CriticRating; dto.PresentationUniqueKey = entity.PresentationUniqueKey; dto.OriginalTitle = entity.OriginalTitle; - dto.Album = entity.Album; - dto.LUFS = entity.LUFS; - dto.NormalizationGain = entity.NormalizationGain; + dto.Album = entity.AudioExtras?.Album; + dto.LUFS = entity.AudioExtras?.LUFS; + dto.NormalizationGain = entity.AudioExtras?.NormalizationGain; dto.IsVirtualItem = entity.IsVirtualItem; - dto.ExternalSeriesId = entity.ExternalSeriesId; + dto.ExternalSeriesId = entity.LiveTvExtras?.ExternalSeriesId; dto.Tagline = entity.Tagline; dto.TotalBitrate = entity.TotalBitrate; dto.ExternalId = entity.ExternalId; @@ -1442,9 +1553,10 @@ public sealed class BaseItemRepository dto.LockedFields = entity.LockedFields?.Select(e => (MetadataField)e.Id).ToArray() ?? []; } - if (entity.Audio is not null) + var audioEnum = entity.LiveTvExtras?.Audio; + if (audioEnum is not null) { - dto.Audio = (ProgramAudio)entity.Audio; + dto.Audio = (ProgramAudio)audioEnum; } dto.ExtraIds = string.IsNullOrWhiteSpace(entity.ExtraIds) ? [] : entity.ExtraIds.Split('|').Select(e => Guid.Parse(e)).ToArray(); @@ -1456,13 +1568,13 @@ public sealed class BaseItemRepository { hasProgramAttributes.IsMovie = entity.IsMovie; hasProgramAttributes.IsSeries = entity.IsSeries; - hasProgramAttributes.EpisodeTitle = entity.EpisodeTitle; + hasProgramAttributes.EpisodeTitle = entity.LiveTvExtras?.EpisodeTitle; hasProgramAttributes.IsRepeat = entity.IsRepeat; } if (dto is LiveTvChannel liveTvChannel) { - liveTvChannel.ServiceName = entity.ExternalServiceId; + liveTvChannel.ServiceName = entity.LiveTvExtras?.ExternalServiceId; } if (dto is Trailer trailer) @@ -1477,30 +1589,30 @@ public sealed class BaseItemRepository if (dto is IHasSeries hasSeriesName) { - hasSeriesName.SeriesName = entity.SeriesName; - hasSeriesName.SeriesId = entity.SeriesId.GetValueOrDefault(); - hasSeriesName.SeriesPresentationUniqueKey = entity.SeriesPresentationUniqueKey; + hasSeriesName.SeriesName = entity.TvExtras?.SeriesName; + hasSeriesName.SeriesId = entity.TvExtras?.SeriesId ?? Guid.Empty; + hasSeriesName.SeriesPresentationUniqueKey = entity.TvExtras?.SeriesPresentationUniqueKey; } if (dto is Episode episode) { - episode.SeasonName = entity.SeasonName; - episode.SeasonId = entity.SeasonId.GetValueOrDefault(); + episode.SeasonName = entity.TvExtras?.SeasonName; + episode.SeasonId = entity.TvExtras?.SeasonId ?? Guid.Empty; } if (dto is IHasArtist hasArtists) { - hasArtists.Artists = entity.Artists?.Split('|', StringSplitOptions.RemoveEmptyEntries) ?? []; + hasArtists.Artists = entity.AudioExtras?.Artists?.Split('|', StringSplitOptions.RemoveEmptyEntries) ?? []; } if (dto is IHasAlbumArtist hasAlbumArtists) { - hasAlbumArtists.AlbumArtists = entity.AlbumArtists?.Split('|', StringSplitOptions.RemoveEmptyEntries) ?? []; + hasAlbumArtists.AlbumArtists = entity.AudioExtras?.AlbumArtists?.Split('|', StringSplitOptions.RemoveEmptyEntries) ?? []; } if (dto is LiveTvProgram program) { - program.ShowId = entity.ShowId; + program.ShowId = entity.LiveTvExtras?.ShowId; } if (entity.Images is not null) @@ -1513,7 +1625,7 @@ public sealed class BaseItemRepository // dto.MediaType = Enum.TryParse(entity.MediaType); if (dto is IHasStartDate hasStartDate) { - hasStartDate.StartDate = entity.StartDate.GetValueOrDefault(); + hasStartDate.StartDate = entity.LiveTvExtras?.StartDate ?? default; } // Fields that are present in the DB but are never actually used @@ -1551,7 +1663,6 @@ public sealed class BaseItemRepository entity.ParentId = !dto.ParentId.IsEmpty() ? dto.ParentId : null; entity.Path = GetPathToSave(dto.Path); - entity.EndDate = dto.EndDate; entity.CommunityRating = dto.CommunityRating; entity.CustomRating = dto.CustomRating; entity.IndexNumber = dto.IndexNumber; @@ -1574,11 +1685,7 @@ public sealed class BaseItemRepository entity.CriticRating = dto.CriticRating; entity.PresentationUniqueKey = dto.PresentationUniqueKey; entity.OriginalTitle = dto.OriginalTitle; - entity.Album = dto.Album; - entity.LUFS = dto.LUFS; - entity.NormalizationGain = dto.NormalizationGain; entity.IsVirtualItem = dto.IsVirtualItem; - entity.ExternalSeriesId = dto.ExternalSeriesId; entity.Tagline = dto.Tagline; entity.TotalBitrate = dto.TotalBitrate; entity.ExternalId = dto.ExternalId; @@ -1599,11 +1706,6 @@ public sealed class BaseItemRepository ProviderValue = e.Value }).ToList(); - if (dto.Audio.HasValue) - { - entity.Audio = (ProgramAudioEntity)dto.Audio; - } - if (dto.ExtraType.HasValue) { entity.ExtraType = (BaseItemExtraType)dto.ExtraType; @@ -1626,48 +1728,14 @@ public sealed class BaseItemRepository { entity.IsMovie = hasProgramAttributes.IsMovie; entity.IsSeries = hasProgramAttributes.IsSeries; - entity.EpisodeTitle = hasProgramAttributes.EpisodeTitle; entity.IsRepeat = hasProgramAttributes.IsRepeat; } - if (dto is LiveTvChannel liveTvChannel) - { - entity.ExternalServiceId = liveTvChannel.ServiceName; - } - if (dto is Video video) { entity.PrimaryVersionId = video.PrimaryVersionId; } - if (dto is IHasSeries hasSeriesName) - { - entity.SeriesName = hasSeriesName.SeriesName; - entity.SeriesId = hasSeriesName.SeriesId; - entity.SeriesPresentationUniqueKey = hasSeriesName.SeriesPresentationUniqueKey; - } - - if (dto is Episode episode) - { - entity.SeasonName = episode.SeasonName; - entity.SeasonId = episode.SeasonId; - } - - if (dto is IHasArtist hasArtists) - { - entity.Artists = hasArtists.Artists is not null ? string.Join('|', hasArtists.Artists) : null; - } - - if (dto is IHasAlbumArtist hasAlbumArtists) - { - entity.AlbumArtists = hasAlbumArtists.AlbumArtists is not null ? string.Join('|', hasAlbumArtists.AlbumArtists) : null; - } - - if (dto is LiveTvProgram program) - { - entity.ShowId = program.ShowId; - } - if (dto.ImageInfos is not null) { entity.Images = dto.ImageInfos.Select(f => Map(dto.Id, f)).ToArray(); @@ -1686,16 +1754,85 @@ public sealed class BaseItemRepository // dto.Type = entity.Type; // dto.Data = entity.Data; entity.MediaType = dto.MediaType.ToString(); - if (dto is IHasStartDate hasStartDate) - { - entity.StartDate = hasStartDate.StartDate; - } entity.UnratedType = dto.GetBlockUnratedType().ToString(); // Fields that are present in the DB but are never actually used // dto.UserDataKey = entity.UserDataKey; + // Populate extension navigation properties (persisted to extension tables in UpdateOrInsertItemsAsync) + if (dto is IHasSeries seriesExt) + { + entity.TvExtras = new BaseItemTvExtras + { + ItemId = entity.Id, + SeriesName = seriesExt.SeriesName, + SeriesId = seriesExt.SeriesId, + SeriesPresentationUniqueKey = seriesExt.SeriesPresentationUniqueKey + }; + } + + if (dto is Episode episodeExt) + { + entity.TvExtras ??= new BaseItemTvExtras { ItemId = entity.Id }; + entity.TvExtras.SeasonName = episodeExt.SeasonName; + entity.TvExtras.SeasonId = episodeExt.SeasonId; + } + + if (dto.EndDate is not null || dto.ExternalSeriesId is not null || dto.Audio.HasValue + || dto is IHasProgramAttributes || dto is LiveTvChannel || dto is LiveTvProgram || dto is IHasStartDate) + { + var liveTvExt = new BaseItemLiveTvExtras { ItemId = entity.Id }; + liveTvExt.EndDate = dto.EndDate; + liveTvExt.ExternalSeriesId = dto.ExternalSeriesId; + if (dto.Audio.HasValue) + { + liveTvExt.Audio = (ProgramAudioEntity)dto.Audio; + } + + if (dto is IHasProgramAttributes hpaExt) + { + liveTvExt.EpisodeTitle = hpaExt.EpisodeTitle; + } + + if (dto is LiveTvChannel liveTvChExt) + { + liveTvExt.ExternalServiceId = liveTvChExt.ServiceName; + } + + if (dto is LiveTvProgram progExt) + { + liveTvExt.ShowId = progExt.ShowId; + } + + if (dto is IHasStartDate hasSDExt) + { + liveTvExt.StartDate = hasSDExt.StartDate; + } + + entity.LiveTvExtras = liveTvExt; + } + + if (dto.Album is not null || dto.LUFS is not null || dto.NormalizationGain is not null + || dto is IHasArtist || dto is IHasAlbumArtist) + { + var audioExt = new BaseItemAudioExtras { ItemId = entity.Id }; + audioExt.Album = dto.Album; + audioExt.LUFS = dto.LUFS; + audioExt.NormalizationGain = dto.NormalizationGain; + if (dto is IHasArtist hasArtistsExt) + { + audioExt.Artists = hasArtistsExt.Artists is not null ? string.Join('|', hasArtistsExt.Artists) : null; + } + + if (dto is IHasAlbumArtist hasAlbumArtistsExt) + { + audioExt.AlbumArtists = hasAlbumArtistsExt.AlbumArtists is not null ? string.Join('|', hasAlbumArtistsExt.AlbumArtists) : null; + } + + entity.AudioExtras = audioExt; + } + if (dto is Folder folder) { entity.DateLastMediaAdded = folder.DateLastMediaAdded == DateTime.MinValue ? null : folder.DateLastMediaAdded; @@ -2696,22 +2833,22 @@ public sealed class BaseItemRepository if (minEndDate.HasValue) { - baseQuery = baseQuery.Where(e => e.EndDate >= minEndDate); + baseQuery = baseQuery.Where(e => e.LiveTvExtras!.EndDate >= minEndDate); } if (maxEndDate.HasValue) { - baseQuery = baseQuery.Where(e => e.EndDate <= maxEndDate); + baseQuery = baseQuery.Where(e => e.LiveTvExtras!.EndDate <= maxEndDate); } if (filter.MinStartDate.HasValue) { - baseQuery = baseQuery.Where(e => e.StartDate >= filter.MinStartDate.Value); + baseQuery = baseQuery.Where(e => e.LiveTvExtras!.StartDate >= filter.MinStartDate.Value); } if (filter.MaxStartDate.HasValue) { - baseQuery = baseQuery.Where(e => e.StartDate <= filter.MaxStartDate.Value); + baseQuery = baseQuery.Where(e => e.LiveTvExtras!.StartDate <= filter.MaxStartDate.Value); } if (filter.MinPremiereDate.HasValue) @@ -2734,11 +2871,11 @@ public sealed class BaseItemRepository { if (filter.IsAiring.Value) { - baseQuery = baseQuery.Where(e => e.StartDate <= now && e.EndDate >= now); + baseQuery = baseQuery.Where(e => e.LiveTvExtras!.StartDate <= now && e.LiveTvExtras!.EndDate >= now); } else { - baseQuery = baseQuery.Where(e => e.StartDate > now && e.EndDate < now); + baseQuery = baseQuery.Where(e => e.LiveTvExtras!.StartDate > now && e.LiveTvExtras!.EndDate < now); } } @@ -2772,7 +2909,7 @@ public sealed class BaseItemRepository if (!string.IsNullOrWhiteSpace(filter.ExternalSeriesId)) { - baseQuery = baseQuery.Where(e => e.ExternalSeriesId == filter.ExternalSeriesId); + baseQuery = baseQuery.Where(e => e.LiveTvExtras!.ExternalSeriesId == filter.ExternalSeriesId); } if (!string.IsNullOrWhiteSpace(filter.ExternalId)) @@ -2860,7 +2997,7 @@ public sealed class BaseItemRepository baseQuery = baseQuery.Where(e => context.BaseItems.Where(e => e.Id != EF.Constant(PlaceholderId)) .Where(e => e.IsFolder == false && e.IsVirtualItem == false) .Where(f => f.UserData!.FirstOrDefault(e => e.UserId == filter.User!.Id && e.Played)!.Played) - .Any(f => f.SeriesPresentationUniqueKey == e.PresentationUniqueKey) == filter.IsPlayed); + .Any(f => f.TvExtras!.SeriesPresentationUniqueKey == e.PresentationUniqueKey) == filter.IsPlayed); } else { @@ -2918,7 +3055,7 @@ public sealed class BaseItemRepository if (filter.AlbumIds.Length > 0) { var subQuery = context.BaseItems.WhereOneOrMany(filter.AlbumIds, f => f.Id); - baseQuery = baseQuery.Where(e => subQuery.Any(f => f.Name == e.Album)); + baseQuery = baseQuery.Where(e => subQuery.Any(f => f.Name == e.AudioExtras!.Album)); } if (filter.ExcludeArtistIds.Length > 0) @@ -3279,7 +3416,7 @@ public sealed class BaseItemRepository if (!string.IsNullOrWhiteSpace(filter.SeriesPresentationUniqueKey)) { baseQuery = baseQuery - .Where(e => e.SeriesPresentationUniqueKey == filter.SeriesPresentationUniqueKey); + .Where(e => e.TvExtras!.SeriesPresentationUniqueKey == filter.SeriesPresentationUniqueKey); } if (filter.ExcludeInheritedTags.Length > 0) @@ -3287,7 +3424,7 @@ public sealed class BaseItemRepository var excludedTags = filter.ExcludeInheritedTags; baseQuery = baseQuery.Where(e => !e.ItemValues!.Any(f => f.ItemValue.Type == ItemValueType.Tags && excludedTags.Contains(f.ItemValue.CleanValue)) - && (!e.SeriesId.HasValue || !context.ItemValuesMap.Any(f => f.ItemId == e.SeriesId.Value && f.ItemValue.Type == ItemValueType.Tags && excludedTags.Contains(f.ItemValue.CleanValue)))); + && (!e.TvExtras!.SeriesId.HasValue || !context.ItemValuesMap.Any(f => f.ItemId == e.TvExtras!.SeriesId.Value && f.ItemValue.Type == ItemValueType.Tags && excludedTags.Contains(f.ItemValue.CleanValue)))); } if (filter.IncludeInheritedTags.Length > 0) @@ -3298,7 +3435,7 @@ public sealed class BaseItemRepository e.ItemValues!.Any(f => f.ItemValue.Type == ItemValueType.Tags && includeTags.Contains(f.ItemValue.CleanValue)) // For seasons and episodes, we also need to check the parent series' tags. - || (e.SeriesId.HasValue && context.ItemValuesMap.Any(f => f.ItemId == e.SeriesId.Value && f.ItemValue.Type == ItemValueType.Tags && includeTags.Contains(f.ItemValue.CleanValue))) + || (e.TvExtras!.SeriesId.HasValue && context.ItemValuesMap.Any(f => f.ItemId == e.TvExtras!.SeriesId.Value && f.ItemValue.Type == ItemValueType.Tags && includeTags.Contains(f.ItemValue.CleanValue))) // A playlist should be accessible to its owner regardless of allowed tags || (isPlaylistOnlyQuery && e.Data!.Contains($"OwnerUserId\":\"{filter.User!.Id:N}\""))); diff --git a/Jellyfin.Server.Implementations/Item/OrderMapper.cs b/Jellyfin.Server.Implementations/Item/OrderMapper.cs index bde1ea39..85658ff8 100644 --- a/Jellyfin.Server.Implementations/Item/OrderMapper.cs +++ b/Jellyfin.Server.Implementations/Item/OrderMapper.cs @@ -46,11 +46,11 @@ public static class OrderMapper (ItemSortBy.AlbumArtist, _) => e => e.ItemValues!.Where(f => f.ItemValue.Type == ItemValueType.AlbumArtist).Select(f => f.ItemValue.CleanValue).FirstOrDefault(), (ItemSortBy.Studio, _) => e => e.ItemValues!.Where(f => f.ItemValue.Type == ItemValueType.Studios).Select(f => f.ItemValue.CleanValue).FirstOrDefault(), (ItemSortBy.OfficialRating, _) => e => e.InheritedParentalRatingValue, - (ItemSortBy.SeriesSortName, _) => e => e.SeriesName, - (ItemSortBy.Album, _) => e => e.Album, + (ItemSortBy.SeriesSortName, _) => e => e.TvExtras!.SeriesName, + (ItemSortBy.Album, _) => e => e.AudioExtras!.Album, (ItemSortBy.DateCreated, _) => e => e.DateCreated, (ItemSortBy.PremiereDate, _) => e => (e.PremiereDate ?? (e.ProductionYear.HasValue ? DateTime.MinValue.AddYears(e.ProductionYear.Value - 1) : null)), - (ItemSortBy.StartDate, _) => e => e.StartDate, + (ItemSortBy.StartDate, _) => e => e.LiveTvExtras!.StartDate, (ItemSortBy.Name, _) => e => e.CleanName, (ItemSortBy.CommunityRating, _) => e => e.CommunityRating, (ItemSortBy.ProductionYear, _) => e => e.ProductionYear, @@ -60,10 +60,10 @@ public static class OrderMapper (ItemSortBy.IndexNumber, _) => e => e.IndexNumber, (ItemSortBy.SeriesDatePlayed, not null) => e => jellyfinDbContext.BaseItems - .Where(w => w.SeriesPresentationUniqueKey == e.PresentationUniqueKey) + .Where(w => w.TvExtras!.SeriesPresentationUniqueKey == e.PresentationUniqueKey) .Join(jellyfinDbContext.UserData.Where(w => w.UserId == query.User.Id && w.Played), f => f.Id, f => f.ItemId, (item, userData) => userData.LastPlayedDate) .Max(f => f), - (ItemSortBy.SeriesDatePlayed, null) => e => jellyfinDbContext.BaseItems.Where(w => w.SeriesPresentationUniqueKey == e.PresentationUniqueKey) + (ItemSortBy.SeriesDatePlayed, null) => e => jellyfinDbContext.BaseItems.Where(w => w.TvExtras!.SeriesPresentationUniqueKey == e.PresentationUniqueKey) .Join(jellyfinDbContext.UserData.Where(w => w.Played), f => f.Id, f => f.ItemId, (item, userData) => userData.LastPlayedDate) .Max(f => f), // ItemSortBy.SeriesDatePlayed => e => jellyfinDbContext.UserData diff --git a/Jellyfin.Server.Implementations/Migrations/MigrationRecord.cs b/Jellyfin.Server.Implementations/Migrations/MigrationRecord.cs new file mode 100644 index 00000000..e171461b --- /dev/null +++ b/Jellyfin.Server.Implementations/Migrations/MigrationRecord.cs @@ -0,0 +1,15 @@ +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +namespace Jellyfin.Server.Implementations.Migrations; + +/// Represents one row of the EF migrations history table. +public sealed class MigrationRecord +{ + /// Gets or sets the migration identifier. + public string MigrationId { get; set; } = string.Empty; + + /// Gets or sets the product version that applied this migration. + public string ProductVersion { get; set; } = string.Empty; +} diff --git a/Jellyfin.Server.Implementations/Migrations/MigrationTracker.cs b/Jellyfin.Server.Implementations/Migrations/MigrationTracker.cs new file mode 100644 index 00000000..b2939238 --- /dev/null +++ b/Jellyfin.Server.Implementations/Migrations/MigrationTracker.cs @@ -0,0 +1,80 @@ +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using Jellyfin.Database.Implementations; +using Microsoft.EntityFrameworkCore; + +namespace Jellyfin.Server.Implementations.Migrations; + +/// +/// Plain-SQL tracker for the EF migrations history table. +/// Replaces the EF-internal IHistoryRepository / SnakeCaseHistoryRepository. +/// +public static class MigrationTracker +{ + /// + /// Entry name used when writing/reading migration history from backup archives. + /// Kept as "HistoryRow" for backward compatibility with existing backup files. + /// + public const string BackupEntryName = "HistoryRow"; + + private const string CreateTableSql = """ + CREATE TABLE IF NOT EXISTS public."__EFMigrationsHistory" ( + migration_id character varying(150) NOT NULL, + product_version character varying(32) NOT NULL, + CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY (migration_id) + ) + """; + + /// Ensures the migrations history table exists. + /// The database context. + /// Cancellation token. + /// A representing the operation. + public static async Task EnsureTableExistsAsync(JellyfinDbContext dbContext, CancellationToken ct = default) + => await dbContext.Database.ExecuteSqlRawAsync(CreateTableSql, ct).ConfigureAwait(false); + + /// Returns the migration_id of every applied migration. + /// The database context. + /// Cancellation token. + /// A read-only list of applied migration identifiers. + public static async Task> GetAppliedMigrationIdsAsync(JellyfinDbContext dbContext, CancellationToken ct = default) + => await dbContext.Database + .SqlQueryRaw("""SELECT migration_id AS "Value" FROM public."__EFMigrationsHistory" """) + .ToListAsync(ct).ConfigureAwait(false); + + /// Returns all applied migration rows. + /// The database context. + /// Cancellation token. + /// A read-only list of instances. + public static async Task> GetAppliedMigrationsAsync(JellyfinDbContext dbContext, CancellationToken ct = default) + => await dbContext.Database + .SqlQueryRaw(""" + SELECT migration_id AS "MigrationId", product_version AS "ProductVersion" + FROM public."__EFMigrationsHistory" + """) + .ToListAsync(ct).ConfigureAwait(false); + + /// Inserts a migration row, ignoring conflicts. + /// The database context. + /// The migration identifier. + /// The product version. + /// Cancellation token. + /// A representing the operation. + public static async Task InsertAsync(JellyfinDbContext dbContext, string migrationId, string productVersion, CancellationToken ct = default) + => await dbContext.Database.ExecuteSqlAsync( + $""" + INSERT INTO public."__EFMigrationsHistory" (migration_id, product_version) + VALUES ({migrationId}, {productVersion}) ON CONFLICT DO NOTHING + """, + ct).ConfigureAwait(false); + + /// Deletes a migration row by id. + /// The database context. + /// The migration identifier to delete. + /// Cancellation token. + /// A representing the operation. + public static async Task DeleteAsync(JellyfinDbContext dbContext, string migrationId, CancellationToken ct = default) + => await dbContext.Database.ExecuteSqlAsync( + $"""DELETE FROM public."__EFMigrationsHistory" WHERE migration_id = {migrationId}""", + ct).ConfigureAwait(false); +} diff --git a/Jellyfin.Server.Implementations/ScheduledTasks/PostgresPeriodicTuner.cs b/Jellyfin.Server.Implementations/ScheduledTasks/PostgresPeriodicTuner.cs new file mode 100644 index 00000000..f48ac429 --- /dev/null +++ b/Jellyfin.Server.Implementations/ScheduledTasks/PostgresPeriodicTuner.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Jellyfin.Data.Queries; +using Jellyfin.Extensions.Dapper; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Plugins; +using MediaBrowser.Controller.Session; +using MediaBrowser.Model.Tasks; +using Microsoft.Extensions.Logging; + +namespace Jellyfin.Server.Implementations.ScheduledTasks +{ + /// + /// Class PostgresPeriodicTuner. + /// + public class PostgresPeriodicTuner : IScheduledTask, IConfigurableScheduledTask + { + private readonly ILogger _logger; + private readonly IDbContext _dbContext; + + /// + /// Initializes a new instance of the class. + /// + /// The logger. + /// The database context. + public PostgresPeriodicTuner(ILogger logger, IDbContext dbContext) + { + _logger = logger; + _dbContext = dbContext; + } + + /// + public string Name => "PostgreSQL Periodic Tuner"; + + /// + public string Key => "PostgresPeriodicTuner"; + + /// + public string Description => "Periodically checks for dead tuples and runs VACUUM ANALYZE on tables that need it."; + + /// + public string Category => "Database"; + + /// + public bool IsHidden => false; + + /// + public bool IsEnabled => true; + + /// + public bool IsLogged => true; + + /// + /// Executes the task. + /// + /// The cancellation token. + /// The progress. + /// A representing the asynchronous operation. + public async Task ExecuteAsync(CancellationToken cancellationToken, IProgress progress) + { + _logger.LogInformation("PostgreSQL Periodic Tuner task started."); + + try + { + const string DeadTupleQuery = @" + SELECT + relname AS TableName, + n_dead_tup AS DeadTuples + FROM + pg_stat_user_tables + WHERE + n_dead_tup > 1000 -- Example threshold: more than 1000 dead tuples + ORDER BY + n_dead_tup DESC;"; + + var tablesToVacuum = (await _dbContext.QueryAsync<(string TableName, long DeadTuples)>(DeadTupleQuery)).ToList(); + + if (tablesToVacuum.Count == 0) + { + _logger.LogInformation("No tables require vacuuming at this time."); + return; + } + + progress.Report(10); + + double progressStep = 90.0 / tablesToVacuum.Count; + double currentProgress = 10.0; + + foreach (var table in tablesToVacuum) + { + cancellationToken.ThrowIfCancellationRequested(); + _logger.LogInformation("Found {DeadTuples} dead tuples in table {TableName}. Running VACUUM ANALYZE.", table.DeadTuples, table.TableName); + + try + { + await _dbContext.ExecuteAsync($"VACUUM ANALYZE \"{table.TableName}\""); + _logger.LogInformation("Successfully vacuumed and analyzed table {TableName}.", table.TableName); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error running VACUUM ANALYZE on table {TableName}.", table.TableName); + } + + currentProgress += progressStep; + progress.Report(currentProgress); + } + } + catch (Exception ex) + { + _logger.LogError(ex, "Error during PostgreSQL Periodic Tuner task."); + } + finally + { + _logger.LogInformation("PostgreSQL Periodic Tuner task finished."); + progress.Report(100); + } + } + + /// + /// Gets the default triggers. + /// + /// IEnumerable<TaskTriggerInfo>. + public IEnumerable GetDefaultTriggers() + { + return new[] + { + new TaskTriggerInfo + { + Type = TaskTriggerInfo.TriggerInterval, + IntervalTicks = TimeSpan.FromHours(24).Ticks + } + }; + } + } +} diff --git a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs index d4203dfc..d96a0a2a 100644 --- a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs +++ b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs @@ -149,7 +149,7 @@ namespace Jellyfin.Server.Implementations.Security return authInfo; } - var tokenPreview = token?.Length > 8 ? token.Substring(0, 8) + "..." : token ?? "null"; + var tokenPreview = token?.Length > 8 ? string.Concat(token.AsSpan(0, 8), "...") : token ?? "null"; _logger.LogDebug( "Validating authentication token. Client: {Client}, Device: {Device}, DeviceId: {DeviceId}, Token: {Token}", client ?? "unknown", @@ -255,7 +255,7 @@ namespace Jellyfin.Server.Implementations.Security } else { - var tokenPreview2 = token?.Length > 8 ? token.Substring(0, 8) + "..." : token ?? "null"; + var tokenPreview2 = token?.Length > 8 ? string.Concat(token.AsSpan(0, 8), "...") : token ?? "null"; _logger.LogDebug( "Token validation failed: Token not found in devices or API keys. Token: {Token}", tokenPreview2); diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 3529a443..d3a3a861 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -28,7 +28,6 @@ namespace Jellyfin.Server.Extensions using Jellyfin.Database.Implementations.Enums; using Jellyfin.Extensions.Json; using Jellyfin.Server.Configuration; - using Jellyfin.Server.Filters; using MediaBrowser.Common.Api; using MediaBrowser.Common.Net; using MediaBrowser.Model.Entities; @@ -43,7 +42,6 @@ namespace Jellyfin.Server.Extensions using Microsoft.OpenApi.Any; using Microsoft.OpenApi.Interfaces; using Microsoft.OpenApi.Models; - using Swashbuckle.AspNetCore.Swagger; using Swashbuckle.AspNetCore.SwaggerGen; using AuthenticationSchemes = Jellyfin.Api.Constants.AuthenticationSchemes; @@ -254,20 +252,7 @@ namespace Jellyfin.Server.Extensions // Allow parameters to properly be nullable. c.UseAllOfToExtendReferenceSchemas(); c.SupportNonNullableReferenceTypes(); - - // TODO - remove when all types are supported in System.Text.Json - c.AddSwaggerTypeMappings(); - - c.SchemaFilter(); - c.SchemaFilter(); - c.OperationFilter(); - c.OperationFilter(); - c.OperationFilter(); - c.OperationFilter(); - c.OperationFilter(); - c.DocumentFilter(); - }) - .Replace(ServiceDescriptor.Transient()); + }); } private static void AddPolicy(this AuthorizationOptions authorizationOptions, string policyName, IAuthorizationRequirement authorizationRequirement) @@ -327,40 +312,5 @@ namespace Jellyfin.Server.Extensions options.KnownIPNetworks.Add(new System.Net.IPNetwork(addr, prefixLength)); } } - - private static void AddSwaggerTypeMappings(this SwaggerGenOptions options) - { - /* - * TODO remove when System.Text.Json properly supports non-string keys. - * Used in BaseItemDto.ImageBlurHashes - */ - options.MapType>(() => - new OpenApiSchema - { - Type = "object", - AdditionalProperties = new OpenApiSchema - { - Type = "string" - } - }); - - // Support dictionary with nullable string value. - options.MapType>(() => - new OpenApiSchema - { - Type = "object", - AdditionalProperties = new OpenApiSchema - { - Type = "string", - Nullable = true - } - }); - - // Swashbuckle doesn't use JsonOptions to describe responses, so we need to manually describe it. - options.MapType(() => new OpenApiSchema - { - Type = "string" - }); - } } } diff --git a/Jellyfin.Server/Helpers/StartupHelpers.cs b/Jellyfin.Server/Helpers/StartupHelpers.cs index 860bcb5c..f2f7e36f 100644 --- a/Jellyfin.Server/Helpers/StartupHelpers.cs +++ b/Jellyfin.Server/Helpers/StartupHelpers.cs @@ -31,6 +31,11 @@ public static class StartupHelpers { private static readonly string[] _relevantEnvVarPrefixes = { "JELLYFIN_", "DOTNET_", "ASPNETCORE_" }; + private static readonly System.Text.Json.JsonSerializerOptions _jsonSerializerOptions = new() + { + WriteIndented = true + }; + /// /// Logs relevant environment variables and information about the host. /// @@ -235,10 +240,7 @@ public static class StartupHelpers } }; - var json = System.Text.Json.JsonSerializer.Serialize(defaultConfig, new System.Text.Json.JsonSerializerOptions - { - WriteIndented = true - }); + var json = System.Text.Json.JsonSerializer.Serialize(defaultConfig, _jsonSerializerOptions); File.WriteAllText(configPath, json); Console.WriteLine($"Created default startup configuration at: {configPath}"); @@ -368,7 +370,7 @@ public static class StartupHelpers // If $XDG_CACHE_HOME is either not set or a relative path, // a default equal to $HOME/.cache should be used. - if (cacheHome is null || !cacheHome.StartsWith("/", StringComparison.Ordinal)) + if (cacheHome is null || !cacheHome.StartsWith('/', StringComparison.Ordinal)) { cacheHome = Path.Join( Environment.GetFolderPath(Environment.SpecialFolder.UserProfile, Environment.SpecialFolderOption.DoNotVerify), diff --git a/Jellyfin.Server/Jellyfin.Server.csproj b/Jellyfin.Server/Jellyfin.Server.csproj index f9731c45..f4320974 100644 --- a/Jellyfin.Server/Jellyfin.Server.csproj +++ b/Jellyfin.Server/Jellyfin.Server.csproj @@ -2,12 +2,12 @@ - $(NoWarn);CA1024;CA1031;CA1032;CA1034;CA1054;CA1055;CA1056;CA1062;CA1308;CA1303;CA1305;CA1508;CA1722;CA1724;CA1805;CA1813;CA1815;CA1816;CA1819;CA1821;CA1822;CA1823;CA1824;CA1825;CA1826;CA1830;CA1836;CA1839;CA1840;CA1841;CA1859;CA1861;CA1873;CA1911;CA2000;CA2007;CA2016;CA2025;CA2026;CA2100;CA2101;CA2102;CA2201;CA2202;CA2207;CA2208;CA2219;CA2220;CA2222;CA2225;CA2226;CA2230;CA2231;CA2234;CA2241;CA2242;CA2243;CA2244;CA2245;CA2246;CA2247;CA2248;CA2249;CA2250;CA2253;CA3001;CA3002;CA3003;CA3004;CA3005;CA3006;CA3007;CA3008;CA3009;CA3010;CA3011;CA3012;CA3061;CA3062;CA5359;CA5360;CA5361;CA5362;CA5363;CA5364;CA5365;CA5366;CA5367;CA5368;CA5369;CA5370;CA5371;CA5372;CA5373;CA5374;CA5375;CA5376;CA5377;CA5378;CA5379;CA5380;CA5381;CA5382;CA5383;CA5384;CA5385;CA5386;CA5387;CA5388;CA5389;CA5390;CA5391;CA5392;CA5393;CA5394;CA5395;CA5396;CA5397;CA5398;CA5399;CA5400;CA5401;CA5402;CA5403;NU1903;CA1848;CA1515;CA1812;CA1849;CA1860;CA1867;CA1517 + $(NoWarn);CA1024;CA1031;CA1032;CA1034;CA1054;CA1055;CA1056;CA1062;CA1308;CA1303;CA1305;CA1508;CA1722;CA1724;CA1805;CA1813;CA1815;CA1816;CA1819;CA1821;CA1822;CA1823;CA1824;CA1825;CA1826;CA1830;CA1836;CA1839;CA1840;CA1841;CA1859;CA1861;CA1873;CA1911;CA2000;CA2007;CA2016;CA2025;CA2026;CA2100;CA2101;CA2102;CA2201;CA2202;CA2207;CA2208;CA2219;CA2220;CA2222;CA2225;CA2226;CA2230;CA2231;CA2234;CA2241;CA2242;CA2243;CA2244;CA2245;CA2246;CA2247;CA2248;CA2249;CA2250;CA2253;CA3001;CA3002;CA3003;CA3004;CA3005;CA3006;CA3007;CA3008;CA3009;CA3010;CA3011;CA3012;CA3061;CA3062;CA5359;CA5360;CA5361;CA5362;CA5363;CA5364;CA5365;CA5366;CA5367;CA5368;CA5369;CA5370;CA5371;CA5372;CA5373;CA5374;CA5375;CA5376;CA5377;CA5378;CA5379;CA5380;CA5381;CA5382;CA5383;CA5384;CA5385;CA5386;CA5387;CA5388;CA5389;CA5390;CA5391;CA5392;CA5393;CA5394;CA5395;CA5396;CA5397;CA5398;CA5399;CA5400;CA5401;CA5402;CA5403;NU1903;CA1848;CA1515;CA1812;CA1849;CA1860;CA1867;CA1517;CS1061;CS0103 {07E39F42-A2C6-4B32-AF8C-725F957A73FF} - $(NoWarn);CA1024;CA1031;CA1032;CA1034;CA1054;CA1055;CA1056;CA1062;CA1308;CA1303;CA1305;CA1508;CA1722;CA1724;CA1805;CA1813;CA1815;CA1816;CA1819;CA1821;CA1822;CA1823;CA1824;CA1825;CA1826;CA1830;CA1836;CA1839;CA1840;CA1841;CA1859;CA1861;CA1873;CA1911;CA2000;CA2007;CA2016;CA2025;CA2026;CA2100;CA2101;CA2102;CA2201;CA2202;CA2207;CA2208;CA2219;CA2220;CA2222;CA2225;CA2226;CA2230;CA2231;CA2234;CA2241;CA2242;CA2243;CA2244;CA2245;CA2246;CA2247;CA2248;CA2249;CA2250;CA2253;CA3001;CA3002;CA3003;CA3004;CA3005;CA3006;CA3007;CA3008;CA3009;CA3010;CA3011;CA3012;CA3061;CA3062;CA5359;CA5360;CA5361;CA5362;CA5363;CA5364;CA5365;CA5366;CA5367;CA5368;CA5369;CA5370;CA5371;CA5372;CA5373;CA5374;CA5375;CA5376;CA5377;CA5378;CA5379;CA5380;CA5381;CA5382;CA5383;CA5384;CA5385;CA5386;CA5387;CA5388;CA5389;CA5390;CA5391;CA5392;CA5393;CA5394;CA5395;CA5396;CA5397;CA5398;CA5399;CA5400;CA5401;CA5402;CA5403;NU1903;CA1848;CA1515;CA1812;CA1849;CA1860;CA1867;CA1517 + $(NoWarn);CA1024;CA1031;CA1032;CA1034;CA1054;CA1055;CA1056;CA1062;CA1308;CA1303;CA1305;CA1508;CA1722;CA1724;CA1805;CA1813;CA1815;CA1816;CA1819;CA1821;CA1822;CA1823;CA1824;CA1825;CA1826;CA1830;CA1836;CA1839;CA1840;CA1841;CA1859;CA1861;CA1873;CA1911;CA2000;CA2007;CA2016;CA2025;CA2026;CA2100;CA2101;CA2102;CA2201;CA2202;CA2207;CA2208;CA2219;CA2220;CA2222;CA2225;CA2226;CA2230;CA2231;CA2234;CA2241;CA2242;CA2243;CA2244;CA2245;CA2246;CA2247;CA2248;CA2249;CA2250;CA2253;CA3001;CA3002;CA3003;CA3004;CA3005;CA3006;CA3007;CA3008;CA3009;CA3010;CA3011;CA3012;CA3061;CA3062;CA5359;CA5360;CA5361;CA5362;CA5363;CA5364;CA5365;CA5366;CA5367;CA5368;CA5369;CA5370;CA5371;CA5372;CA5373;CA5374;CA5375;CA5376;CA5377;CA5378;CA5379;CA5380;CA5381;CA5382;CA5383;CA5384;CA5385;CA5386;CA5387;CA5388;CA5389;CA5390;CA5391;CA5392;CA5393;CA5394;CA5395;CA5396;CA5397;CA5398;CA5399;CA5400;CA5401;CA5402;CA5403;NU1903;CA1848;CA1515;CA1812;CA1849;CA1860;CA1867;CA1517;CS1061;CS0103 jellyfin Exe net11.0 @@ -18,6 +18,10 @@ true + + + + @@ -81,6 +85,7 @@ + diff --git a/Jellyfin.Server/Migrations/JellyfinMigrationService.cs b/Jellyfin.Server/Migrations/JellyfinMigrationService.cs index aa772cf7..10aa5efe 100644 --- a/Jellyfin.Server/Migrations/JellyfinMigrationService.cs +++ b/Jellyfin.Server/Migrations/JellyfinMigrationService.cs @@ -2,6 +2,8 @@ // Copyright (c) PlaceholderCompany. All rights reserved. // +#pragma warning disable CS8602 // Dereference of a possibly null reference + namespace Jellyfin.Server.Migrations; using System; @@ -14,6 +16,7 @@ using System.Threading; using System.Threading.Tasks; using Emby.Server.Implementations.Serialization; using Jellyfin.Database.Implementations; +using Jellyfin.Server.Implementations.Migrations; using Jellyfin.Server.Implementations.SystemBackupService; using Jellyfin.Server.Migrations.Stages; using Jellyfin.Server.ServerSetupApp; @@ -22,7 +25,6 @@ using MediaBrowser.Controller.SystemBackupService; using MediaBrowser.Model.Configuration; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -97,7 +99,7 @@ internal class JellyfinMigrationService public async Task CheckFirstTimeRunOrMigration(IApplicationPaths appPaths) { - var logger = _startupLogger.With(_loggerFactory.CreateLogger()).BeginGroup($"Migration Startup"); + var logger = _startupLogger.Attach(_loggerFactory.CreateLogger()).BeginGroup($"Migration Startup"); logger.LogInformation("Initialise Migration service."); var xmlSerializer = new MyXmlSerializer(); var serverConfig = File.Exists(appPaths.SystemConfigurationFilePath) @@ -121,18 +123,15 @@ internal class JellyfinMigrationService } */ - var historyRepository = dbContext.GetService(); - - await historyRepository.CreateIfNotExistsAsync().ConfigureAwait(false); - var appliedMigrations = await dbContext.Database.GetAppliedMigrationsAsync().ConfigureAwait(false); - var startupScripts = flatApplyMigrations + await MigrationTracker.EnsureTableExistsAsync(dbContext).ConfigureAwait(false); + var appliedMigrations = await MigrationTracker.GetAppliedMigrationIdsAsync(dbContext).ConfigureAwait(false); + var migrationsToSeed = flatApplyMigrations .Where(e => !appliedMigrations.Any(f => f != e.BuildCodeMigrationId())) - .Select(e => (Migration: e.Metadata, Script: historyRepository.GetInsertScript(new HistoryRow(e.BuildCodeMigrationId(), GetJellyfinVersion())))) .ToArray(); - foreach (var item in startupScripts) + foreach (var item in migrationsToSeed) { - logger.LogInformation("Seed migration {Key}-{Name}.", item.Migration.Key, item.Migration.Name); - await dbContext.Database.ExecuteSqlRawAsync(item.Script).ConfigureAwait(false); + logger.LogInformation("Seed migration {Key}-{Name}.", item.Metadata.Key, item.Metadata.Name); + await MigrationTracker.InsertAsync(dbContext, item.BuildCodeMigrationId(), GetJellyfinVersion()).ConfigureAwait(false); } } @@ -153,8 +152,8 @@ internal class JellyfinMigrationService var dbContext = await _dbContextFactory.CreateDbContextAsync().ConfigureAwait(false); await using (dbContext.ConfigureAwait(false)) { - var historyRepository = dbContext.GetService(); - var appliedMigrations = await dbContext.Database.GetAppliedMigrationsAsync().ConfigureAwait(false); + await MigrationTracker.EnsureTableExistsAsync(dbContext).ConfigureAwait(false); + var appliedMigrations = await MigrationTracker.GetAppliedMigrationIdsAsync(dbContext).ConfigureAwait(false); var lastOldAppliedMigration = Migrations .SelectMany(e => e.Where(e => e.Metadata.Key is not null)) // only consider migrations that have the key set as its the reference marker for legacy migrations. .Where(e => migrationOptions.Applied.Any(f => f.Id.Equals(e.Metadata.Key!.Value))) @@ -171,11 +170,10 @@ internal class JellyfinMigrationService ]; // those are all migrations that had to run in the old migration system, even if not noted in the migration.xml file. - var startupScripts = oldMigrations.Select(e => (Migration: e.Metadata, Script: historyRepository.GetInsertScript(new HistoryRow(e.BuildCodeMigrationId(), GetJellyfinVersion())))); - foreach (var item in startupScripts) + foreach (var item in oldMigrations) { - logger.LogInformation("Migrate migration {Key}-{Name}.", item.Migration.Key, item.Migration.Name); - await dbContext.Database.ExecuteSqlRawAsync(item.Script).ConfigureAwait(false); + logger.LogInformation("Migrate migration {Key}-{Name}.", item.Metadata.Key, item.Metadata.Name); + await MigrationTracker.InsertAsync(dbContext, item.BuildCodeMigrationId(), GetJellyfinVersion()).ConfigureAwait(false); } logger.LogInformation("Rename old migration.xml to migration.xml.backup"); @@ -193,7 +191,7 @@ internal class JellyfinMigrationService public async Task MigrateStepAsync(JellyfinMigrationStageTypes stage, IServiceProvider? serviceProvider) { - var logger = _startupLogger.With(_loggerFactory.CreateLogger()).BeginGroup($"Migrate stage {stage}."); + var logger = _startupLogger.Attach(_loggerFactory.CreateLogger()).BeginGroup($"Migrate stage {stage}."); // Ensure database exists before attempting migrations (PostgreSQL-specific) if (stage == JellyfinMigrationStageTypes.CoreInitialisation && _jellyfinDatabaseProvider is Jellyfin.Database.Providers.Postgres.PostgresDatabaseProvider postgresProvider) @@ -248,32 +246,14 @@ internal class JellyfinMigrationService logger.LogInformation("Empty database created successfully"); } - var historyRepository = dbContext.GetService(); - - // Explicitly ensure the __EFMigrationsHistory table exists - await historyRepository.CreateIfNotExistsAsync().ConfigureAwait(false); - - var migrationsAssembly = dbContext.GetService(); - var appliedMigrations = await historyRepository.GetAppliedMigrationsAsync().ConfigureAwait(false); + await MigrationTracker.EnsureTableExistsAsync(dbContext).ConfigureAwait(false); + var appliedMigrations = await MigrationTracker.GetAppliedMigrationIdsAsync(dbContext).ConfigureAwait(false); var pendingCodeMigrations = migrationStage - .Where(e => appliedMigrations.All(f => f.MigrationId != e.BuildCodeMigrationId())) + .Where(e => !appliedMigrations.Contains(e.BuildCodeMigrationId())) .Select(e => (Key: e.BuildCodeMigrationId(), Migration: new InternalCodeMigration(e, serviceProvider, dbContext))) .ToArray(); - (string Key, InternalDatabaseMigration Migration)[] pendingDatabaseMigrations = []; - - // DISABLED for .NET 11 preview: EF Core database migrations don't work with preview SDK - // Database schema is initialized from SQL scripts in PostgresDatabaseProvider instead - /* - if (stage is JellyfinMigrationStageTypes.CoreInitialisation) - { - pendingDatabaseMigrations = migrationsAssembly.Migrations.Where(f => appliedMigrations.All(e => e.MigrationId != f.Key)) - .Select(e => (Key: e.Key, Migration: new InternalDatabaseMigration(e, dbContext))) - .ToArray(); - } - */ - - (string Key, IInternalMigration Migration)[] pendingMigrations = [.. pendingCodeMigrations, .. pendingDatabaseMigrations]; + (string Key, IInternalMigration Migration)[] pendingMigrations = [.. pendingCodeMigrations]; logger.LogInformation("There are {Pending} migrations for stage {Stage}.", pendingMigrations.Length, stage); var migrations = pendingMigrations.OrderBy(e => e.Key).ToArray(); @@ -394,16 +374,15 @@ internal class JellyfinMigrationService { logger.LogInformation("Prepare system for possible migrations"); JellyfinMigrationBackupAttribute backupInstruction; - IReadOnlyList appliedMigrations; + IReadOnlyList appliedMigrations; var dbContext = await _dbContextFactory.CreateDbContextAsync().ConfigureAwait(false); await using (dbContext.ConfigureAwait(false)) { - var historyRepository = dbContext.GetService(); - var migrationsAssembly = dbContext.GetService(); - appliedMigrations = await historyRepository.GetAppliedMigrationsAsync().ConfigureAwait(false); + await MigrationTracker.EnsureTableExistsAsync(dbContext).ConfigureAwait(false); + appliedMigrations = await MigrationTracker.GetAppliedMigrationIdsAsync(dbContext).ConfigureAwait(false); backupInstruction = new JellyfinMigrationBackupAttribute() { - JellyfinDb = migrationsAssembly.Migrations.Any(f => appliedMigrations.All(e => e.MigrationId != f.Key)) + JellyfinDb = false // Schema migrations are disabled; no EF schema migrations are ever pending }; } @@ -412,7 +391,7 @@ internal class JellyfinMigrationService bool isSqliteProvider = false; backupInstruction = Migrations.SelectMany(e => e) - .Where(e => appliedMigrations.All(f => f.MigrationId != e.BuildCodeMigrationId())) + .Where(e => !appliedMigrations.Contains(e.BuildCodeMigrationId())) .Where(e => isSqliteProvider || !e.Metadata.RequiresSqlite) // Skip SQLite migrations for non-SQLite providers .Select(e => e.BackupRequirements) .Where(e => e is not null) @@ -504,27 +483,8 @@ internal class JellyfinMigrationService { await _codeMigration.Perform(_serviceProvider, logger, CancellationToken.None).ConfigureAwait(false); - var historyRepository = _dbContext.GetService(); - var createScript = historyRepository.GetInsertScript(new HistoryRow(_codeMigration.BuildCodeMigrationId(), GetJellyfinVersion())); - await _dbContext.Database.ExecuteSqlRawAsync(createScript).ConfigureAwait(false); - } - } - - private class InternalDatabaseMigration : IInternalMigration - { - private readonly JellyfinDbContext _jellyfinDbContext; - private KeyValuePair _databaseMigrationInfo; - - public InternalDatabaseMigration(KeyValuePair databaseMigrationInfo, JellyfinDbContext jellyfinDbContext) - { - _databaseMigrationInfo = databaseMigrationInfo; - _jellyfinDbContext = jellyfinDbContext; - } - - public async Task PerformAsync(IStartupLogger logger) - { - var migrator = _jellyfinDbContext.GetService(); - await migrator.MigrateAsync(_databaseMigrationInfo.Key).ConfigureAwait(false); + await MigrationTracker.InsertAsync(_dbContext, _codeMigration.BuildCodeMigrationId(), GetJellyfinVersion()).ConfigureAwait(false); } } } + diff --git a/Jellyfin.Server/Migrations/Routines/FixDates.cs b/Jellyfin.Server/Migrations/Routines/FixDates.cs index 5c69a049..7259d5c2 100644 --- a/Jellyfin.Server/Migrations/Routines/FixDates.cs +++ b/Jellyfin.Server/Migrations/Routines/FixDates.cs @@ -36,7 +36,7 @@ public class FixDates : IAsyncMigrationRoutine IStartupLogger startupLogger, IDbContextFactory dbProvider) { - _logger = startupLogger.With(logger); + _logger = startupLogger.Attach(logger); _dbProvider = dbProvider; } diff --git a/Jellyfin.Server/Migrations/Routines/MigrateKeyframeData.cs b/Jellyfin.Server/Migrations/Routines/MigrateKeyframeData.cs index 5c97ae4b..cc425c56 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateKeyframeData.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateKeyframeData.cs @@ -64,30 +64,36 @@ public class MigrateKeyframeData : IDatabaseMigrationRoutine _logger.LogInformation("Checking {Count} items for importable keyframe data.", records); context.KeyframeData.ExecuteDelete(); - using var transaction = context.Database.BeginTransaction(); - do + + // NpgsqlRetryingExecutionStrategy requires all operations inside a user-initiated + // transaction to be wrapped with CreateExecutionStrategy().Execute(...). + context.Database.CreateExecutionStrategy().Execute(() => { - var results = baseQuery.Skip(offset).Take(Limit).Select(b => new Tuple(b.Id, b.Path)).ToList(); - foreach (var result in results) + using var transaction = context.Database.BeginTransaction(); + do { - if (TryGetKeyframeData(result.Item1, result.Item2, out var data)) + var results = baseQuery.Skip(offset).Take(Limit).Select(b => new Tuple(b.Id, b.Path)).ToList(); + foreach (var result in results) { - itemCount++; - context.KeyframeData.Add(data); + if (TryGetKeyframeData(result.Item1, result.Item2, out var data)) + { + itemCount++; + context.KeyframeData.Add(data); + } } - } - offset += Limit; - if (offset > records) - { - offset = records; - } + offset += Limit; + if (offset > records) + { + offset = records; + } - _logger.LogInformation("Checked: {Count} - Imported: {Items} - Time: {Time}", offset, itemCount, sw.Elapsed); - } while (offset < records); + _logger.LogInformation("Checked: {Count} - Imported: {Items} - Time: {Time}", offset, itemCount, sw.Elapsed); + } while (offset < records); - context.SaveChanges(); - transaction.Commit(); + context.SaveChanges(); + transaction.Commit(); + }); _logger.LogInformation("Imported keyframes for {Count} items in {Time}", itemCount, sw.Elapsed); diff --git a/Jellyfin.Server/Migrations/Routines/MigrateLibraryDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateLibraryDb.cs index 8f476bb2..c7d95a7d 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateLibraryDb.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateLibraryDb.cs @@ -3,6 +3,8 @@ // #pragma warning disable RS0030 // Do not use banned APIs +#pragma warning disable CS1061 // Type does not contain definition (legacy schema migration) +#pragma warning disable CS0103 // Name does not exist (legacy code) using System; using System.Collections.Generic; @@ -95,7 +97,7 @@ internal class MigrateLibraryDb : IDatabaseMigrationRoutine } // notify the other migration to just silently abort because the fix has been applied here already. - ReseedFolderFlag.RerunGuardFlag = true; + // ReseedFolderFlag.RerunGuardFlag = true; var legacyBaseItemWithUserKeys = new Dictionary(); connection.Open(); @@ -879,12 +881,12 @@ internal class MigrateLibraryDb : IDatabaseMigrationRoutine if (reader.TryReadDateTime(index++, out var startDate)) { - entity.StartDate = startDate; + // entity.StartDate = startDate; // Property removed in new schema } if (reader.TryReadDateTime(index++, out var endDate)) { - entity.EndDate = endDate; + // entity.EndDate = endDate; // Property removed in new schema } if (reader.TryGetGuid(index++, out var guid)) @@ -904,7 +906,7 @@ internal class MigrateLibraryDb : IDatabaseMigrationRoutine if (reader.TryGetString(index++, out var episodeTitle)) { - entity.EpisodeTitle = episodeTitle; + // entity.EpisodeTitle = episodeTitle; // Property removed in new schema } if (reader.TryGetBoolean(index++, out var isRepeat)) @@ -1034,12 +1036,12 @@ internal class MigrateLibraryDb : IDatabaseMigrationRoutine if (reader.TryGetString(index++, out var audioString) && Enum.TryParse(audioString, out var audioType)) { - entity.Audio = audioType; + // entity.Audio = audioType; // Property removed in new schema } if (reader.TryGetString(index++, out var serviceName)) { - entity.ExternalServiceId = serviceName; + // entity.ExternalServiceId = serviceName; // Property removed in new schema } if (reader.TryGetBoolean(index++, out var isInMixedFolder)) @@ -1103,17 +1105,17 @@ internal class MigrateLibraryDb : IDatabaseMigrationRoutine if (reader.TryGetString(index++, out var album)) { - entity.Album = album; + // entity.Album = album; // Property removed in new schema } if (reader.TryGetSingle(index++, out var lUFS)) { - entity.LUFS = lUFS; + // entity.LUFS = lUFS; // Property removed in new schema } if (reader.TryGetSingle(index++, out var normalizationGain)) { - entity.NormalizationGain = normalizationGain; + // entity.NormalizationGain = normalizationGain; // Property removed in new schema } if (reader.TryGetSingle(index++, out var criticRating)) @@ -1128,7 +1130,7 @@ internal class MigrateLibraryDb : IDatabaseMigrationRoutine if (reader.TryGetString(index++, out var seriesName)) { - entity.SeriesName = seriesName; + // entity.SeriesName = seriesName; // Property removed in new schema } var userDataKeys = new List(); @@ -1139,17 +1141,17 @@ internal class MigrateLibraryDb : IDatabaseMigrationRoutine if (reader.TryGetString(index++, out var seasonName)) { - entity.SeasonName = seasonName; + // entity.SeasonName = seasonName; // Property removed in new schema } if (reader.TryGetGuid(index++, out var seasonId)) { - entity.SeasonId = seasonId; + // entity.SeasonId = seasonId; // Property removed in new schema } if (reader.TryGetGuid(index++, out var seriesId)) { - entity.SeriesId = seriesId; + // entity.SeriesId = seriesId; // Property removed in new schema } if (reader.TryGetString(index++, out var presentationUniqueKey)) @@ -1164,7 +1166,7 @@ internal class MigrateLibraryDb : IDatabaseMigrationRoutine if (reader.TryGetString(index++, out var externalSeriesId)) { - entity.ExternalSeriesId = externalSeriesId; + // entity.ExternalSeriesId = externalSeriesId; // Property removed in new schema } if (reader.TryGetString(index++, out var tagLine)) @@ -1212,12 +1214,12 @@ internal class MigrateLibraryDb : IDatabaseMigrationRoutine if (reader.TryGetString(index++, out var artists)) { - entity.Artists = artists; + // entity.Artists = artists; // Property removed in new schema } if (reader.TryGetString(index++, out var albumArtists)) { - entity.AlbumArtists = albumArtists; + // entity.AlbumArtists = albumArtists; // Property removed in new schema } if (reader.TryGetString(index++, out var externalId)) @@ -1227,12 +1229,12 @@ internal class MigrateLibraryDb : IDatabaseMigrationRoutine if (reader.TryGetString(index++, out var seriesPresentationUniqueKey)) { - entity.SeriesPresentationUniqueKey = seriesPresentationUniqueKey; + // entity.SeriesPresentationUniqueKey = seriesPresentationUniqueKey; // Property removed in new schema } if (reader.TryGetString(index++, out var showId)) { - entity.ShowId = showId; + // entity.ShowId = showId; // Property removed in new schema } if (reader.TryGetString(index++, out var ownerId)) diff --git a/Jellyfin.Server/Migrations/Routines/MigrateRatingLevels.cs b/Jellyfin.Server/Migrations/Routines/MigrateRatingLevels.cs index 773aaba4..b7167216 100644 --- a/Jellyfin.Server/Migrations/Routines/MigrateRatingLevels.cs +++ b/Jellyfin.Server/Migrations/Routines/MigrateRatingLevels.cs @@ -40,37 +40,43 @@ internal class MigrateRatingLevels : IDatabaseMigrationRoutine { _logger.LogInformation("Recalculating parental rating levels based on rating string."); using var context = _provider.CreateDbContext(); - using var transaction = context.Database.BeginTransaction(); - // Materialize the ratings list first to avoid "command in progress" error - var ratings = context.BaseItems.AsNoTracking().Select(e => e.OfficialRating).Distinct().ToList(); - - foreach (var rating in ratings) + // NpgsqlRetryingExecutionStrategy requires all operations inside a user-initiated + // transaction to be wrapped with CreateExecutionStrategy().Execute(...). + context.Database.CreateExecutionStrategy().Execute(() => { - if (string.IsNullOrEmpty(rating)) - { - int? value = null; - context.BaseItems - .Where(e => e.OfficialRating == null || e.OfficialRating == string.Empty) - .ExecuteUpdate(f => f.SetProperty(e => e.InheritedParentalRatingValue, value)); - context.BaseItems - .Where(e => e.OfficialRating == null || e.OfficialRating == string.Empty) - .ExecuteUpdate(f => f.SetProperty(e => e.InheritedParentalRatingSubValue, value)); - } - else - { - var ratingValue = _localizationManager.GetRatingScore(rating); - var score = ratingValue?.Score; - var subScore = ratingValue?.SubScore; - context.BaseItems - .Where(e => e.OfficialRating == rating) - .ExecuteUpdate(f => f.SetProperty(e => e.InheritedParentalRatingValue, score)); - context.BaseItems - .Where(e => e.OfficialRating == rating) - .ExecuteUpdate(f => f.SetProperty(e => e.InheritedParentalRatingSubValue, subScore)); - } - } + using var transaction = context.Database.BeginTransaction(); - transaction.Commit(); + // Materialize the ratings list first to avoid "command in progress" error + var ratings = context.BaseItems.AsNoTracking().Select(e => e.OfficialRating).Distinct().ToList(); + + foreach (var rating in ratings) + { + if (string.IsNullOrEmpty(rating)) + { + int? value = null; + context.BaseItems + .Where(e => e.OfficialRating == null || e.OfficialRating == string.Empty) + .ExecuteUpdate(f => f.SetProperty(e => e.InheritedParentalRatingValue, value)); + context.BaseItems + .Where(e => e.OfficialRating == null || e.OfficialRating == string.Empty) + .ExecuteUpdate(f => f.SetProperty(e => e.InheritedParentalRatingSubValue, value)); + } + else + { + var ratingValue = _localizationManager.GetRatingScore(rating); + var score = ratingValue?.Score; + var subScore = ratingValue?.SubScore; + context.BaseItems + .Where(e => e.OfficialRating == rating) + .ExecuteUpdate(f => f.SetProperty(e => e.InheritedParentalRatingValue, score)); + context.BaseItems + .Where(e => e.OfficialRating == rating) + .ExecuteUpdate(f => f.SetProperty(e => e.InheritedParentalRatingSubValue, subScore)); + } + } + + transaction.Commit(); + }); } } diff --git a/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs b/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs deleted file mode 100644 index 9d263f31..00000000 --- a/Jellyfin.Server/Migrations/Routines/MigrateUserDb.cs +++ /dev/null @@ -1,237 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Jellyfin.Server.Migrations.Routines; - -using System; -using System.IO; -using Emby.Server.Implementations.Data; -using Jellyfin.Data; -using Jellyfin.Database.Implementations; -using Jellyfin.Database.Implementations.Entities; -using Jellyfin.Database.Implementations.Enums; -using Jellyfin.Extensions.Json; -using Jellyfin.Server.Implementations.Users; -using MediaBrowser.Controller; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Serialization; -using MediaBrowser.Model.Users; -using Microsoft.Data.Sqlite; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Logging; -using JsonSerializer = System.Text.Json.JsonSerializer; - -/// -/// The migration routine for migrating the user database to EF Core. -/// -#pragma warning disable CS0618 // Type or member is obsolete -[JellyfinMigration("2025-04-20T10:00:00", nameof(MigrateUserDb), "5C4B82A2-F053-4009-BD05-B6FCAD82F14C", RequiresSqlite = true)] -public class MigrateUserDb : IMigrationRoutine -#pragma warning restore CS0618 // Type or member is obsolete -{ - private const string DbFilename = "users.db"; - - private readonly ILogger _logger; - private readonly IServerApplicationPaths _paths; - private readonly IDbContextFactory _provider; - private readonly IXmlSerializer _xmlSerializer; - - /// - /// Initializes a new instance of the class. - /// - /// The logger. - /// The server application paths. - /// The database provider. - /// The xml serializer. - public MigrateUserDb( - ILogger logger, - IServerApplicationPaths paths, - IDbContextFactory provider, - IXmlSerializer xmlSerializer) - { - _logger = logger; - _paths = paths; - _provider = provider; - _xmlSerializer = xmlSerializer; - } - - /// - public void Perform() - { - var dataPath = _paths.DataPath; - var userDbPath = Path.Combine(dataPath, DbFilename); - if (!File.Exists(userDbPath)) - { - _logger.LogWarning("{UserDbPath} doesn't exist, nothing to migrate", userDbPath); - return; - } - - _logger.LogInformation("Migrating the user database may take a while, do not stop Jellyfin."); - - using (var connection = new SqliteConnection($"Filename={userDbPath}")) - { - connection.Open(); - var tableQuery = connection.Query("SELECT count(*) FROM sqlite_master WHERE type='table' AND name='LocalUsersv2';"); - foreach (var row in tableQuery) - { - if (row.GetInt32(0) == 0) - { - _logger.LogWarning("Table 'LocalUsersv2' doesn't exist in {UserDbPath}, nothing to migrate", userDbPath); - return; - } - } - - using var dbContext = _provider.CreateDbContext(); - - var queryResult = connection.Query("SELECT * FROM LocalUsersv2"); - - dbContext.RemoveRange(dbContext.Users); - dbContext.SaveChanges(); - - foreach (var entry in queryResult) - { - UserMockup? mockup = JsonSerializer.Deserialize(entry.GetStream(2), JsonDefaults.Options); - if (mockup is null) - { - continue; - } - - var userDataDir = Path.Combine(_paths.UserConfigurationDirectoryPath, mockup.Name); - - var configPath = Path.Combine(userDataDir, "config.xml"); - var config = File.Exists(configPath) - ? (UserConfiguration?)_xmlSerializer.DeserializeFromFile(typeof(UserConfiguration), configPath) ?? new UserConfiguration() - : new UserConfiguration(); - - var policyPath = Path.Combine(userDataDir, "policy.xml"); - var policy = File.Exists(policyPath) - ? (UserPolicy?)_xmlSerializer.DeserializeFromFile(typeof(UserPolicy), policyPath) ?? new UserPolicy() - : new UserPolicy(); - policy.AuthenticationProviderId = policy.AuthenticationProviderId?.Replace( - "Emby.Server.Implementations.Library", - "Jellyfin.Server.Implementations.Users", - StringComparison.Ordinal) - ?? typeof(DefaultAuthenticationProvider).FullName; - - policy.PasswordResetProviderId = typeof(DefaultPasswordResetProvider).FullName; - int? maxLoginAttempts = policy.LoginAttemptsBeforeLockout switch - { - -1 => null, - 0 => 3, - _ => policy.LoginAttemptsBeforeLockout - }; - - var user = new User(mockup.Name, policy.AuthenticationProviderId!, policy.PasswordResetProviderId!) - { - Id = entry.GetGuid(1), - InternalId = entry.GetInt64(0), - MaxParentalRatingScore = policy.MaxParentalRating, - MaxParentalRatingSubScore = null, - EnableUserPreferenceAccess = policy.EnableUserPreferenceAccess, - RemoteClientBitrateLimit = policy.RemoteClientBitrateLimit, - InvalidLoginAttemptCount = policy.InvalidLoginAttemptCount, - LoginAttemptsBeforeLockout = maxLoginAttempts, - SubtitleMode = config.SubtitleMode, - HidePlayedInLatest = config.HidePlayedInLatest, - EnableLocalPassword = config.EnableLocalPassword, - PlayDefaultAudioTrack = config.PlayDefaultAudioTrack, - DisplayCollectionsView = config.DisplayCollectionsView, - DisplayMissingEpisodes = config.DisplayMissingEpisodes, - AudioLanguagePreference = config.AudioLanguagePreference, - RememberAudioSelections = config.RememberAudioSelections, - EnableNextEpisodeAutoPlay = config.EnableNextEpisodeAutoPlay, - RememberSubtitleSelections = config.RememberSubtitleSelections, - SubtitleLanguagePreference = config.SubtitleLanguagePreference, - Password = mockup.Password, - LastLoginDate = mockup.LastLoginDate, - LastActivityDate = mockup.LastActivityDate - }; - - if (mockup.ImageInfos.Length > 0) - { - ItemImageInfo info = mockup.ImageInfos[0]; - - user.ProfileImage = new ImageInfo(info.Path) - { - LastModified = info.DateModified - }; - } - - user.SetPermission(PermissionKind.IsAdministrator, policy.IsAdministrator); - user.SetPermission(PermissionKind.IsHidden, policy.IsHidden); - user.SetPermission(PermissionKind.IsDisabled, policy.IsDisabled); - user.SetPermission(PermissionKind.EnableSharedDeviceControl, policy.EnableSharedDeviceControl); - user.SetPermission(PermissionKind.EnableRemoteAccess, policy.EnableRemoteAccess); - user.SetPermission(PermissionKind.EnableLiveTvManagement, policy.EnableLiveTvManagement); - user.SetPermission(PermissionKind.EnableLiveTvAccess, policy.EnableLiveTvAccess); - user.SetPermission(PermissionKind.EnableMediaPlayback, policy.EnableMediaPlayback); - user.SetPermission(PermissionKind.EnableAudioPlaybackTranscoding, policy.EnableAudioPlaybackTranscoding); - user.SetPermission(PermissionKind.EnableVideoPlaybackTranscoding, policy.EnableVideoPlaybackTranscoding); - user.SetPermission(PermissionKind.EnableContentDeletion, policy.EnableContentDeletion); - user.SetPermission(PermissionKind.EnableContentDownloading, policy.EnableContentDownloading); - user.SetPermission(PermissionKind.EnableSyncTranscoding, policy.EnableSyncTranscoding); - user.SetPermission(PermissionKind.EnableMediaConversion, policy.EnableMediaConversion); - user.SetPermission(PermissionKind.EnableAllChannels, policy.EnableAllChannels); - user.SetPermission(PermissionKind.EnableAllDevices, policy.EnableAllDevices); - user.SetPermission(PermissionKind.EnableAllFolders, policy.EnableAllFolders); - user.SetPermission(PermissionKind.EnableRemoteControlOfOtherUsers, policy.EnableRemoteControlOfOtherUsers); - user.SetPermission(PermissionKind.EnablePlaybackRemuxing, policy.EnablePlaybackRemuxing); - user.SetPermission(PermissionKind.ForceRemoteSourceTranscoding, policy.ForceRemoteSourceTranscoding); - user.SetPermission(PermissionKind.EnablePublicSharing, policy.EnablePublicSharing); - user.SetPermission(PermissionKind.EnableCollectionManagement, policy.EnableCollectionManagement); - - foreach (var policyAccessSchedule in policy.AccessSchedules) - { - user.AccessSchedules.Add(policyAccessSchedule); - } - - user.SetPreference(PreferenceKind.BlockedTags, policy.BlockedTags); - user.SetPreference(PreferenceKind.EnabledChannels, policy.EnabledChannels); - user.SetPreference(PreferenceKind.EnabledDevices, policy.EnabledDevices); - user.SetPreference(PreferenceKind.EnabledFolders, policy.EnabledFolders); - user.SetPreference(PreferenceKind.EnableContentDeletionFromFolders, policy.EnableContentDeletionFromFolders); - user.SetPreference(PreferenceKind.OrderedViews, config.OrderedViews); - user.SetPreference(PreferenceKind.GroupedFolders, config.GroupedFolders); - user.SetPreference(PreferenceKind.MyMediaExcludes, config.MyMediaExcludes); - user.SetPreference(PreferenceKind.LatestItemExcludes, config.LatestItemsExcludes); - - dbContext.Users.Add(user); - } - - dbContext.SaveChanges(); - } - - try - { - File.Move(Path.Combine(dataPath, DbFilename), Path.Combine(dataPath, DbFilename + ".old")); - - var journalPath = Path.Combine(dataPath, DbFilename + "-journal"); - if (File.Exists(journalPath)) - { - File.Move(journalPath, Path.Combine(dataPath, DbFilename + ".old-journal")); - } - } - catch (IOException e) - { - _logger.LogError(e, "Error renaming legacy user database to 'users.db.old'"); - } - } - -#nullable disable - internal class UserMockup - { - public string Password { get; set; } - - public string EasyPassword { get; set; } - - public DateTime? LastLoginDate { get; set; } - - public DateTime? LastActivityDate { get; set; } - - public string Name { get; set; } - - public ItemImageInfo[] ImageInfos { get; set; } - } -} diff --git a/Jellyfin.Server/Migrations/Routines/MoveExtractedFiles.cs b/Jellyfin.Server/Migrations/Routines/MoveExtractedFiles.cs index efd82258..a65874ab 100644 --- a/Jellyfin.Server/Migrations/Routines/MoveExtractedFiles.cs +++ b/Jellyfin.Server/Migrations/Routines/MoveExtractedFiles.cs @@ -57,7 +57,7 @@ public class MoveExtractedFiles : IAsyncMigrationRoutine IDbContextFactory dbProvider) { _appPaths = appPaths; - _logger = startupLogger.With(logger); + _logger = startupLogger.Attach(logger); _pathManager = pathManager; _fileSystem = fileSystem; _dbProvider = dbProvider; diff --git a/Jellyfin.Server/Migrations/Routines/RemoveDuplicateExtras.cs b/Jellyfin.Server/Migrations/Routines/RemoveDuplicateExtras.cs deleted file mode 100644 index 1080bbd2..00000000 --- a/Jellyfin.Server/Migrations/Routines/RemoveDuplicateExtras.cs +++ /dev/null @@ -1,88 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Jellyfin.Server.Migrations.Routines; - -using System; -using System.Globalization; -using System.IO; -using System.Linq; -using Emby.Server.Implementations.Data; -using MediaBrowser.Controller; -using Microsoft.Data.Sqlite; -using Microsoft.Extensions.Logging; - -/// -/// Remove duplicate entries which were caused by a bug where a file was considered to be an "Extra" to itself. -/// -#pragma warning disable CS0618 // Type or member is obsolete -[JellyfinMigration("2025-04-20T08:00:00", nameof(RemoveDuplicateExtras), "ACBE17B7-8435-4A83-8B64-6FCF162CB9BD", RequiresSqlite = true)] -internal class RemoveDuplicateExtras : IMigrationRoutine -#pragma warning restore CS0618 // Type or member is obsolete -{ - private const string DbFilename = "library.db"; - private readonly ILogger _logger; - private readonly IServerApplicationPaths _paths; - - public RemoveDuplicateExtras(ILogger logger, IServerApplicationPaths paths) - { - _logger = logger; - _paths = paths; - } - - /// - public void Perform() - { - var dataPath = _paths.DataPath; - var dbPath = Path.Combine(dataPath, DbFilename); - - // Skip this migration if using PostgreSQL or if library.db doesn't exist - if (!File.Exists(dbPath)) - { - _logger.LogInformation("SQLite library.db not found, skipping SQLite-specific migration."); - return; - } - - using var connection = new SqliteConnection($"Filename={dbPath}"); - connection.Open(); - using (var transaction = connection.BeginTransaction()) - { - // Query the database for the ids of duplicate extras - var queryResult = connection.Query("SELECT t1.Path FROM TypedBaseItems AS t1, TypedBaseItems AS t2 WHERE t1.Path=t2.Path AND t1.Type!=t2.Type AND t1.Type='MediaBrowser.Controller.Entities.Video'"); - var bads = string.Join(", ", queryResult.Select(x => x.GetString(0))); - - // Do nothing if no duplicate extras were detected - if (bads.Length == 0) - { - _logger.LogInformation("No duplicate extras detected, skipping migration."); - return; - } - - // Back up the database before deleting any entries - for (int i = 1; ; i++) - { - var bakPath = string.Format(CultureInfo.InvariantCulture, "{0}.bak{1}", dbPath, i); - if (!File.Exists(bakPath)) - { - try - { - File.Copy(dbPath, bakPath); - _logger.LogInformation("Library database backed up to {BackupPath}", bakPath); - break; - } - catch (Exception ex) - { - _logger.LogError(ex, "Cannot make a backup of {Library} at path {BackupPath}", DbFilename, bakPath); - throw; - } - } - } - - // Delete all duplicate extras - _logger.LogInformation("Removing found duplicated extras for the following items: {DuplicateExtras}", bads); - connection.Execute("DELETE FROM TypedBaseItems WHERE rowid IN (SELECT t1.rowid FROM TypedBaseItems AS t1, TypedBaseItems AS t2 WHERE t1.Path=t2.Path AND t1.Type!=t2.Type AND t1.Type='MediaBrowser.Controller.Entities.Video')"); - transaction.Commit(); - } - } -} diff --git a/Jellyfin.Server/Migrations/Routines/ReseedFolderFlag.cs b/Jellyfin.Server/Migrations/Routines/ReseedFolderFlag.cs deleted file mode 100644 index 46a16ce0..00000000 --- a/Jellyfin.Server/Migrations/Routines/ReseedFolderFlag.cs +++ /dev/null @@ -1,78 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#pragma warning disable RS0030 // Do not use banned APIs -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Emby.Server.Implementations.Data; -using Jellyfin.Database.Implementations; -using Jellyfin.Server.ServerSetupApp; -using MediaBrowser.Controller; -using Microsoft.Data.Sqlite; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Logging; - -namespace Jellyfin.Server.Migrations.Routines; - -[JellyfinMigration("2025-07-30T21:50:00", nameof(ReseedFolderFlag), RequiresSqlite = true)] -[JellyfinMigrationBackup(JellyfinDb = true)] -internal class ReseedFolderFlag : IAsyncMigrationRoutine -{ - private const string DbFilename = "library.db.old"; - - private readonly IStartupLogger _logger; - private readonly IServerApplicationPaths _paths; - private readonly IDbContextFactory _provider; - - public ReseedFolderFlag( - IStartupLogger startupLogger, - IDbContextFactory provider, - IServerApplicationPaths paths) - { - _logger = startupLogger; - _provider = provider; - _paths = paths; - } - - internal static bool RerunGuardFlag { get; set; } = false; - - public async Task PerformAsync(CancellationToken cancellationToken) - { - if (RerunGuardFlag) - { - _logger.LogInformation("Migration is skipped because it does not apply."); - return; - } - - _logger.LogInformation("Migrating the IsFolder flag from library.db.old may take a while, do not stop Jellyfin."); - - var dataPath = _paths.DataPath; - var libraryDbPath = Path.Combine(dataPath, DbFilename); - if (!File.Exists(libraryDbPath)) - { - _logger.LogError("Cannot migrate IsFolder flag from {LibraryDb} as it does not exist. This migration expects the MigrateLibraryDb to run first.", libraryDbPath); - return; - } - - var dbContext = await _provider.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); - await using (dbContext.ConfigureAwait(false)) - { - using var connection = new SqliteConnection($"Filename={libraryDbPath};Mode=ReadOnly"); - var queryResult = connection.Query( - """ - SELECT guid FROM TypedBaseItems - WHERE IsFolder = true - """) - .Select(entity => entity.GetGuid(0)) - .ToList(); - _logger.LogInformation("Migrating the IsFolder flag for {Count} items.", queryResult.Count); - foreach (var id in queryResult) - { - await dbContext.BaseItems.Where(e => e.Id == id).ExecuteUpdateAsync(e => e.SetProperty(f => f.IsFolder, true), cancellationToken).ConfigureAwait(false); - } - } - } -} diff --git a/Jellyfin.Server/Program.cs b/Jellyfin.Server/Program.cs index 7f2e7a17..150f3b4f 100644 --- a/Jellyfin.Server/Program.cs +++ b/Jellyfin.Server/Program.cs @@ -139,7 +139,7 @@ namespace Jellyfin.Server } } - StorageHelper.TestCommonPathsForStorageCapacity(appPaths, StartupLogger.Logger.With(_loggerFactory.CreateLogger()).BeginGroup($"Storage Check")); + StorageHelper.TestCommonPathsForStorageCapacity(appPaths, StartupLogger.Logger.Attach(_loggerFactory.CreateLogger()).BeginGroup($"Storage Check")); StartupHelpers.PerformStaticInitialization(); diff --git a/Jellyfin.Server/ServerSetupApp/IStartupLogger.cs b/Jellyfin.Server/ServerSetupApp/IStartupLogger.cs index 0b963568..0d06f2d5 100644 --- a/Jellyfin.Server/ServerSetupApp/IStartupLogger.cs +++ b/Jellyfin.Server/ServerSetupApp/IStartupLogger.cs @@ -22,7 +22,7 @@ public interface IStartupLogger : ILogger /// /// Other logger to rely messages to. /// A combined logger. - IStartupLogger With(ILogger logger); + IStartupLogger Attach(ILogger logger); /// /// Opens a new Group logger within the parent logger. @@ -37,7 +37,7 @@ public interface IStartupLogger : ILogger /// Other logger to rely messages to. /// A combined logger. /// The logger cateogry. - IStartupLogger With(ILogger logger); + IStartupLogger Attach(ILogger logger); /// /// Opens a new Group logger within the parent logger. @@ -59,7 +59,7 @@ public interface IStartupLogger : IStartupLogger /// /// Other logger to rely messages to. /// A combined logger. - new IStartupLogger With(ILogger logger); + new IStartupLogger Attach(ILogger logger); /// /// Opens a new Group logger within the parent logger. diff --git a/Jellyfin.Server/ServerSetupApp/StartupLogger.cs b/Jellyfin.Server/ServerSetupApp/StartupLogger.cs index 65643f9e..194001b1 100644 --- a/Jellyfin.Server/ServerSetupApp/StartupLogger.cs +++ b/Jellyfin.Server/ServerSetupApp/StartupLogger.cs @@ -12,8 +12,6 @@ using Microsoft.Extensions.Logging.Abstractions; /// public class StartupLogger : IStartupLogger { - private readonly StartupLogTopic? _topic; - /// /// Initializes a new instance of the class. /// @@ -21,6 +19,7 @@ public class StartupLogger : IStartupLogger public StartupLogger(ILogger logger) { BaseLogger = logger; + Topic = null; } /// @@ -30,13 +29,13 @@ public class StartupLogger : IStartupLogger /// The group for this logger. internal StartupLogger(ILogger logger, StartupLogTopic? topic) : this(logger) { - _topic = topic; + Topic = topic; } internal static IStartupLogger Logger { get; set; } = new StartupLogger(NullLogger.Instance); /// - public StartupLogTopic? Topic => _topic; + public StartupLogTopic? Topic { get; private set; } /// /// Gets or Sets the underlying base logger. @@ -50,13 +49,13 @@ public class StartupLogger : IStartupLogger } /// - public IStartupLogger With(ILogger logger) + public IStartupLogger Attach(ILogger logger) { return new StartupLogger(logger, Topic); } /// - public IStartupLogger With(ILogger logger) + public IStartupLogger Attach(ILogger logger) { return new StartupLogger(logger, Topic); } diff --git a/Jellyfin.Server/ServerSetupApp/StartupLoggerOfCategory.cs b/Jellyfin.Server/ServerSetupApp/StartupLoggerOfCategory.cs index facc7d33..20937a2a 100644 --- a/Jellyfin.Server/ServerSetupApp/StartupLoggerOfCategory.cs +++ b/Jellyfin.Server/ServerSetupApp/StartupLoggerOfCategory.cs @@ -53,7 +53,7 @@ public class StartupLogger : StartupLogger, IStartupLogger return new StartupLogger(BaseLogger, startupEntry); } - IStartupLogger IStartupLogger.With(ILogger logger) + IStartupLogger IStartupLogger.Attach(ILogger logger) { return new StartupLogger(logger, Topic); } diff --git a/Jellyfin.Server/Startup.cs b/Jellyfin.Server/Startup.cs index 3a2269cc..fde6e4b6 100644 --- a/Jellyfin.Server/Startup.cs +++ b/Jellyfin.Server/Startup.cs @@ -85,18 +85,25 @@ namespace Jellyfin.Server var acceptJsonHeader = new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Json, 1.0); var acceptXmlHeader = new MediaTypeWithQualityHeaderValue(MediaTypeNames.Application.Xml, 0.9); var acceptAnyHeader = new MediaTypeWithQualityHeaderValue("*/*", 0.8); - Func eyeballsHttpClientHandlerDelegate = (_) => new SocketsHttpHandler() - { - AutomaticDecompression = DecompressionMethods.All, - RequestHeaderEncodingSelector = (_, _) => Encoding.UTF8, - ConnectCallback = HttpClientExtension.OnConnect - }; - Func defaultHttpClientHandlerDelegate = (_) => new SocketsHttpHandler() + HttpMessageHandler CreateEyeballsHttpClientHandler(IServiceProvider serviceProvider) { - AutomaticDecompression = DecompressionMethods.All, - RequestHeaderEncodingSelector = (_, _) => Encoding.UTF8 - }; + return new SocketsHttpHandler() + { + AutomaticDecompression = DecompressionMethods.All, + RequestHeaderEncodingSelector = (_, _) => Encoding.UTF8, + ConnectCallback = HttpClientExtension.OnConnect + }; + } + + HttpMessageHandler CreateDefaultHttpClientHandler(IServiceProvider serviceProvider) + { + return new SocketsHttpHandler() + { + AutomaticDecompression = DecompressionMethods.All, + RequestHeaderEncodingSelector = (_, _) => Encoding.UTF8 + }; + } services.AddHttpClient(NamedClient.Default, c => { @@ -105,7 +112,7 @@ namespace Jellyfin.Server c.DefaultRequestHeaders.Accept.Add(acceptXmlHeader); c.DefaultRequestHeaders.Accept.Add(acceptAnyHeader); }) - .ConfigurePrimaryHttpMessageHandler(eyeballsHttpClientHandlerDelegate); + .ConfigurePrimaryHttpMessageHandler(CreateEyeballsHttpClientHandler); services.AddHttpClient(NamedClient.MusicBrainz, c => { @@ -114,7 +121,7 @@ namespace Jellyfin.Server c.DefaultRequestHeaders.Accept.Add(acceptXmlHeader); c.DefaultRequestHeaders.Accept.Add(acceptAnyHeader); }) - .ConfigurePrimaryHttpMessageHandler(eyeballsHttpClientHandlerDelegate); + .ConfigurePrimaryHttpMessageHandler(CreateEyeballsHttpClientHandler); services.AddHttpClient(NamedClient.DirectIp, c => { @@ -123,7 +130,7 @@ namespace Jellyfin.Server c.DefaultRequestHeaders.Accept.Add(acceptXmlHeader); c.DefaultRequestHeaders.Accept.Add(acceptAnyHeader); }) - .ConfigurePrimaryHttpMessageHandler(defaultHttpClientHandlerDelegate); + .ConfigurePrimaryHttpMessageHandler(CreateDefaultHttpClientHandler); services.AddHealthChecks() .AddCheck>(nameof(JellyfinDbContext)); diff --git a/Jellyfin.Server/sql/schema_init/create_database_schema.sql b/Jellyfin.Server/sql/schema_init/create_database_schema.sql index 96a7dc13..d705231e 100644 --- a/Jellyfin.Server/sql/schema_init/create_database_schema.sql +++ b/Jellyfin.Server/sql/schema_init/create_database_schema.sql @@ -89,28 +89,28 @@ SET default_table_access_method = heap; -- Name: ActivityLogs; Type: TABLE; Schema: activitylog; Owner: jellyfin -- -CREATE TABLE activitylog."ActivityLogs" ( - "Id" integer NOT NULL, - "Name" character varying(512) NOT NULL, - "Overview" character varying(512), - "ShortOverview" character varying(512), - "Type" character varying(256) NOT NULL, - "UserId" uuid NOT NULL, - "ItemId" character varying(256), - "DateCreated" timestamp with time zone NOT NULL, - "LogSeverity" integer NOT NULL, - "RowVersion" bigint NOT NULL +CREATE TABLE activitylog.activity_logs ( + id integer NOT NULL, + name character varying(512) NOT NULL, + overview character varying(512), + short_overview character varying(512), + type character varying(256) NOT NULL, + user_id uuid NOT NULL, + item_id character varying(256), + date_created timestamp with time zone NOT NULL, + log_severity integer NOT NULL, + row_version bigint NOT NULL ); -ALTER TABLE activitylog."ActivityLogs" OWNER TO jellyfin; +ALTER TABLE activitylog.activity_logs OWNER TO jellyfin; -- --- Name: ActivityLogs_Id_seq; Type: SEQUENCE; Schema: activitylog; Owner: jellyfin +-- Name: activity_logs_id_seq; Type: SEQUENCE; Schema: activitylog; Owner: jellyfin -- -ALTER TABLE activitylog."ActivityLogs" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( - SEQUENCE NAME activitylog."ActivityLogs_Id_seq" +ALTER TABLE activitylog.activity_logs ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME activitylog.activity_logs_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE @@ -123,23 +123,23 @@ ALTER TABLE activitylog."ActivityLogs" ALTER COLUMN "Id" ADD GENERATED BY DEFAUL -- Name: ApiKeys; Type: TABLE; Schema: authentication; Owner: jellyfin -- -CREATE TABLE authentication."ApiKeys" ( - "Id" integer NOT NULL, - "DateCreated" timestamp with time zone NOT NULL, - "DateLastActivity" timestamp with time zone NOT NULL, - "Name" character varying(64) NOT NULL, - "AccessToken" text NOT NULL +CREATE TABLE authentication.api_keys ( + id integer NOT NULL, + date_created timestamp with time zone NOT NULL, + date_last_activity timestamp with time zone NOT NULL, + name character varying(64) NOT NULL, + access_token text NOT NULL ); -ALTER TABLE authentication."ApiKeys" OWNER TO jellyfin; +ALTER TABLE authentication.api_keys OWNER TO jellyfin; -- --- Name: ApiKeys_Id_seq; Type: SEQUENCE; Schema: authentication; Owner: jellyfin +-- Name: api_keys_id_seq; Type: SEQUENCE; Schema: authentication; Owner: jellyfin -- -ALTER TABLE authentication."ApiKeys" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( - SEQUENCE NAME authentication."ApiKeys_Id_seq" +ALTER TABLE authentication.api_keys ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME authentication.api_keys_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE @@ -152,21 +152,21 @@ ALTER TABLE authentication."ApiKeys" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT -- Name: DeviceOptions; Type: TABLE; Schema: authentication; Owner: jellyfin -- -CREATE TABLE authentication."DeviceOptions" ( - "Id" integer NOT NULL, - "DeviceId" text NOT NULL, - "CustomName" text +CREATE TABLE authentication.device_options ( + id integer NOT NULL, + device_id text NOT NULL, + custom_name text ); -ALTER TABLE authentication."DeviceOptions" OWNER TO jellyfin; +ALTER TABLE authentication.device_options OWNER TO jellyfin; -- --- Name: DeviceOptions_Id_seq; Type: SEQUENCE; Schema: authentication; Owner: jellyfin +-- Name: device_options_id_seq; Type: SEQUENCE; Schema: authentication; Owner: jellyfin -- -ALTER TABLE authentication."DeviceOptions" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( - SEQUENCE NAME authentication."DeviceOptions_Id_seq" +ALTER TABLE authentication.device_options ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME authentication.device_options_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE @@ -179,29 +179,29 @@ ALTER TABLE authentication."DeviceOptions" ALTER COLUMN "Id" ADD GENERATED BY DE -- Name: Devices; Type: TABLE; Schema: authentication; Owner: jellyfin -- -CREATE TABLE authentication."Devices" ( - "Id" integer NOT NULL, - "UserId" uuid NOT NULL, - "AccessToken" text NOT NULL, - "AppName" character varying(64) NOT NULL, - "AppVersion" character varying(32) NOT NULL, - "DeviceName" character varying(64) NOT NULL, - "DeviceId" character varying(256) NOT NULL, - "IsActive" boolean NOT NULL, - "DateCreated" timestamp with time zone NOT NULL, - "DateModified" timestamp with time zone NOT NULL, - "DateLastActivity" timestamp with time zone NOT NULL +CREATE TABLE authentication.devices ( + id integer NOT NULL, + user_id uuid NOT NULL, + access_token text NOT NULL, + app_name character varying(64) NOT NULL, + app_version character varying(32) NOT NULL, + device_name character varying(64) NOT NULL, + device_id character varying(256) NOT NULL, + is_active boolean NOT NULL, + date_created timestamp with time zone NOT NULL, + date_modified timestamp with time zone NOT NULL, + date_last_activity timestamp with time zone NOT NULL ); -ALTER TABLE authentication."Devices" OWNER TO jellyfin; +ALTER TABLE authentication.devices OWNER TO jellyfin; -- --- Name: Devices_Id_seq; Type: SEQUENCE; Schema: authentication; Owner: jellyfin +-- Name: devices_id_seq; Type: SEQUENCE; Schema: authentication; Owner: jellyfin -- -ALTER TABLE authentication."Devices" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( - SEQUENCE NAME authentication."Devices_Id_seq" +ALTER TABLE authentication.devices ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME authentication.devices_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE @@ -214,24 +214,24 @@ ALTER TABLE authentication."Devices" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT -- Name: CustomItemDisplayPreferences; Type: TABLE; Schema: displaypreferences; Owner: jellyfin -- -CREATE TABLE displaypreferences."CustomItemDisplayPreferences" ( - "Id" integer NOT NULL, - "UserId" uuid NOT NULL, - "ItemId" uuid NOT NULL, - "Client" character varying(32) NOT NULL, - "Key" text NOT NULL, - "Value" text +CREATE TABLE displaypreferences.custom_item_display_preferences ( + id integer NOT NULL, + user_id uuid NOT NULL, + item_id uuid NOT NULL, + client character varying(32) NOT NULL, + key text NOT NULL, + value text ); -ALTER TABLE displaypreferences."CustomItemDisplayPreferences" OWNER TO jellyfin; +ALTER TABLE displaypreferences.custom_item_display_preferences OWNER TO jellyfin; -- --- Name: CustomItemDisplayPreferences_Id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin +-- Name: custom_item_display_preferences_id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE displaypreferences."CustomItemDisplayPreferences" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( - SEQUENCE NAME displaypreferences."CustomItemDisplayPreferences_Id_seq" +ALTER TABLE displaypreferences.custom_item_display_preferences ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME displaypreferences.custom_item_display_preferences_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE @@ -244,32 +244,32 @@ ALTER TABLE displaypreferences."CustomItemDisplayPreferences" ALTER COLUMN "Id" -- Name: DisplayPreferences; Type: TABLE; Schema: displaypreferences; Owner: jellyfin -- -CREATE TABLE displaypreferences."DisplayPreferences" ( - "Id" integer NOT NULL, - "UserId" uuid NOT NULL, - "ItemId" uuid NOT NULL, - "Client" character varying(32) NOT NULL, - "ShowSidebar" boolean NOT NULL, - "ShowBackdrop" boolean NOT NULL, - "ScrollDirection" integer NOT NULL, - "IndexBy" integer, - "SkipForwardLength" integer NOT NULL, - "SkipBackwardLength" integer NOT NULL, - "ChromecastVersion" integer NOT NULL, - "EnableNextVideoInfoOverlay" boolean NOT NULL, - "DashboardTheme" character varying(32), - "TvHome" character varying(32) +CREATE TABLE displaypreferences.display_preferences ( + id integer NOT NULL, + user_id uuid NOT NULL, + item_id uuid NOT NULL, + client character varying(32) NOT NULL, + show_sidebar boolean NOT NULL, + show_backdrop boolean NOT NULL, + scroll_direction integer NOT NULL, + index_by integer, + skip_forward_length integer NOT NULL, + skip_backward_length integer NOT NULL, + chromecast_version integer NOT NULL, + enable_next_video_info_overlay boolean NOT NULL, + dashboard_theme character varying(32), + tv_home character varying(32) ); -ALTER TABLE displaypreferences."DisplayPreferences" OWNER TO jellyfin; +ALTER TABLE displaypreferences.display_preferences OWNER TO jellyfin; -- --- Name: DisplayPreferences_Id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin +-- Name: display_preferences_id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE displaypreferences."DisplayPreferences" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( - SEQUENCE NAME displaypreferences."DisplayPreferences_Id_seq" +ALTER TABLE displaypreferences.display_preferences ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME displaypreferences.display_preferences_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE @@ -282,22 +282,22 @@ ALTER TABLE displaypreferences."DisplayPreferences" ALTER COLUMN "Id" ADD GENERA -- Name: HomeSection; Type: TABLE; Schema: displaypreferences; Owner: jellyfin -- -CREATE TABLE displaypreferences."HomeSection" ( - "Id" integer NOT NULL, - "DisplayPreferencesId" integer NOT NULL, - "Order" integer NOT NULL, - "Type" integer NOT NULL +CREATE TABLE displaypreferences.home_sections ( + id integer NOT NULL, + display_preferences_id integer NOT NULL, + order integer NOT NULL, + type integer NOT NULL ); -ALTER TABLE displaypreferences."HomeSection" OWNER TO jellyfin; +ALTER TABLE displaypreferences.home_sections OWNER TO jellyfin; -- --- Name: HomeSection_Id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin +-- Name: home_sections_id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE displaypreferences."HomeSection" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( - SEQUENCE NAME displaypreferences."HomeSection_Id_seq" +ALTER TABLE displaypreferences.home_sections ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME displaypreferences.home_sections_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE @@ -310,28 +310,28 @@ ALTER TABLE displaypreferences."HomeSection" ALTER COLUMN "Id" ADD GENERATED BY -- Name: ItemDisplayPreferences; Type: TABLE; Schema: displaypreferences; Owner: jellyfin -- -CREATE TABLE displaypreferences."ItemDisplayPreferences" ( - "Id" integer NOT NULL, - "UserId" uuid NOT NULL, - "ItemId" uuid NOT NULL, - "Client" character varying(32) NOT NULL, - "ViewType" integer NOT NULL, - "RememberIndexing" boolean NOT NULL, - "IndexBy" integer, - "RememberSorting" boolean NOT NULL, - "SortBy" character varying(64) NOT NULL, - "SortOrder" integer NOT NULL +CREATE TABLE displaypreferences.item_display_preferences ( + id integer NOT NULL, + user_id uuid NOT NULL, + item_id uuid NOT NULL, + client character varying(32) NOT NULL, + view_type integer NOT NULL, + remember_indexing boolean NOT NULL, + index_by integer, + remember_sorting boolean NOT NULL, + sort_by character varying(64) NOT NULL, + sort_order integer NOT NULL ); -ALTER TABLE displaypreferences."ItemDisplayPreferences" OWNER TO jellyfin; +ALTER TABLE displaypreferences.item_display_preferences OWNER TO jellyfin; -- --- Name: ItemDisplayPreferences_Id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin +-- Name: item_display_preferences_id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE displaypreferences."ItemDisplayPreferences" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( - SEQUENCE NAME displaypreferences."ItemDisplayPreferences_Id_seq" +ALTER TABLE displaypreferences.item_display_preferences ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME displaypreferences.item_display_preferences_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE @@ -344,204 +344,204 @@ ALTER TABLE displaypreferences."ItemDisplayPreferences" ALTER COLUMN "Id" ADD GE -- Name: AncestorIds; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."AncestorIds" ( - "ParentItemId" uuid NOT NULL, - "ItemId" uuid NOT NULL +CREATE TABLE library.ancestor_ids ( + parent_item_id uuid NOT NULL, + item_id uuid NOT NULL ); -ALTER TABLE library."AncestorIds" OWNER TO jellyfin; +ALTER TABLE library.ancestor_ids OWNER TO jellyfin; -- -- Name: AttachmentStreamInfos; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."AttachmentStreamInfos" ( - "ItemId" uuid NOT NULL, - "Index" integer NOT NULL, - "Codec" text, - "CodecTag" text, - "Comment" text, - "Filename" text, - "MimeType" text +CREATE TABLE library.attachment_stream_infos ( + item_id uuid NOT NULL, + index integer NOT NULL, + codec text, + codec_tag text, + comment text, + filename text, + mime_type text ); -ALTER TABLE library."AttachmentStreamInfos" OWNER TO jellyfin; +ALTER TABLE library.attachment_stream_infos OWNER TO jellyfin; -- -- Name: BaseItemImageInfos; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."BaseItemImageInfos" ( - "Id" uuid NOT NULL, - "Path" text NOT NULL, - "DateModified" timestamp with time zone, - "ImageType" integer NOT NULL, - "Width" integer NOT NULL, - "Height" integer NOT NULL, - "Blurhash" bytea, - "ItemId" uuid NOT NULL +CREATE TABLE library.base_item_image_infos ( + id uuid NOT NULL, + path text NOT NULL, + date_modified timestamp with time zone, + image_type integer NOT NULL, + width integer NOT NULL, + height integer NOT NULL, + blurhash bytea, + item_id uuid NOT NULL ); -ALTER TABLE library."BaseItemImageInfos" OWNER TO jellyfin; +ALTER TABLE library.base_item_image_infos OWNER TO jellyfin; -- -- Name: BaseItemMetadataFields; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."BaseItemMetadataFields" ( - "Id" integer NOT NULL, - "ItemId" uuid NOT NULL +CREATE TABLE library.base_item_metadata_fields ( + id integer NOT NULL, + item_id uuid NOT NULL ); -ALTER TABLE library."BaseItemMetadataFields" OWNER TO jellyfin; +ALTER TABLE library.base_item_metadata_fields OWNER TO jellyfin; -- -- Name: BaseItemProviders; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."BaseItemProviders" ( - "ItemId" uuid NOT NULL, - "ProviderId" text NOT NULL, - "ProviderValue" text NOT NULL +CREATE TABLE library.base_item_providers ( + item_id uuid NOT NULL, + provider_id text NOT NULL, + provider_value text NOT NULL ); -ALTER TABLE library."BaseItemProviders" OWNER TO jellyfin; +ALTER TABLE library.base_item_providers OWNER TO jellyfin; -- -- Name: BaseItemTrailerTypes; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."BaseItemTrailerTypes" ( - "Id" integer NOT NULL, - "ItemId" uuid NOT NULL +CREATE TABLE library.base_item_trailer_types ( + id integer NOT NULL, + item_id uuid NOT NULL ); -ALTER TABLE library."BaseItemTrailerTypes" OWNER TO jellyfin; +ALTER TABLE library.base_item_trailer_types OWNER TO jellyfin; -- -- Name: BaseItems; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."BaseItems" ( - "Id" uuid NOT NULL, - "Type" text NOT NULL, - "Data" text, - "Path" text, - "StartDate" timestamp with time zone, - "EndDate" timestamp with time zone, - "ChannelId" uuid, - "IsMovie" boolean NOT NULL, - "CommunityRating" real, - "CustomRating" text, - "IndexNumber" integer, - "IsLocked" boolean NOT NULL, - "Name" text, - "OfficialRating" text, - "MediaType" text, - "Overview" text, - "ParentIndexNumber" integer, - "PremiereDate" timestamp with time zone, - "ProductionYear" integer, - "Genres" text, - "SortName" text, - "ForcedSortName" text, - "RunTimeTicks" bigint, - "DateCreated" timestamp with time zone, - "DateModified" timestamp with time zone, - "IsSeries" boolean NOT NULL, - "EpisodeTitle" text, - "IsRepeat" boolean NOT NULL, - "PreferredMetadataLanguage" text, - "PreferredMetadataCountryCode" text, - "DateLastRefreshed" timestamp with time zone, - "DateLastSaved" timestamp with time zone, - "IsInMixedFolder" boolean NOT NULL, - "Studios" text, - "ExternalServiceId" text, - "Tags" text, - "IsFolder" boolean NOT NULL, - "InheritedParentalRatingValue" integer, - "InheritedParentalRatingSubValue" integer, - "UnratedType" text, - "CriticRating" real, - "CleanName" text, - "PresentationUniqueKey" text, - "OriginalTitle" text, - "PrimaryVersionId" text, - "DateLastMediaAdded" timestamp with time zone, - "Album" text, - "LUFS" real, - "NormalizationGain" real, - "IsVirtualItem" boolean NOT NULL, - "SeriesName" text, - "SeasonName" text, - "ExternalSeriesId" text, - "Tagline" text, - "ProductionLocations" text, - "ExtraIds" text, - "TotalBitrate" integer, - "ExtraType" integer, - "Artists" text, - "AlbumArtists" text, - "ExternalId" text, - "SeriesPresentationUniqueKey" text, - "ShowId" text, - "OwnerId" text, - "Width" integer, - "Height" integer, - "Size" bigint, - "Audio" integer, - "ParentId" uuid, - "TopParentId" uuid, - "SeasonId" uuid, - "SeriesId" uuid +CREATE TABLE library.base_items ( + id uuid NOT NULL, + type text NOT NULL, + data text, + path text, + start_date timestamp with time zone, + end_date timestamp with time zone, + channel_id uuid, + is_movie boolean NOT NULL, + community_rating real, + custom_rating text, + index_number integer, + is_locked boolean NOT NULL, + name text, + official_rating text, + media_type text, + overview text, + parent_index_number integer, + premiere_date timestamp with time zone, + production_year integer, + genres text, + sort_name text, + forced_sort_name text, + run_time_ticks bigint, + date_created timestamp with time zone, + date_modified timestamp with time zone, + is_series boolean NOT NULL, + episode_title text, + is_repeat boolean NOT NULL, + preferred_metadata_language text, + preferred_metadata_country_code text, + date_last_refreshed timestamp with time zone, + date_last_saved timestamp with time zone, + is_in_mixed_folder boolean NOT NULL, + studios text, + external_service_id text, + tags text, + is_folder boolean NOT NULL, + inherited_parental_rating_value integer, + inherited_parental_rating_sub_value integer, + unrated_type text, + critic_rating real, + clean_name text, + presentation_unique_key text, + original_title text, + primary_version_id text, + date_last_media_added timestamp with time zone, + album text, + lufs real, + normalization_gain real, + is_virtual_item boolean NOT NULL, + series_name text, + season_name text, + external_series_id text, + tagline text, + production_locations text, + extra_ids text, + total_bitrate integer, + extra_type integer, + artists text, + album_artists text, + external_id text, + series_presentation_unique_key text, + show_id text, + owner_id text, + width integer, + height integer, + size bigint, + audio integer, + parent_id uuid, + top_parent_id uuid, + season_id uuid, + series_id uuid ); -ALTER TABLE library."BaseItems" OWNER TO jellyfin; +ALTER TABLE library.base_items OWNER TO jellyfin; -- -- Name: Chapters; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."Chapters" ( - "ItemId" uuid NOT NULL, - "ChapterIndex" integer NOT NULL, - "StartPositionTicks" bigint NOT NULL, - "Name" text, - "ImagePath" text, - "ImageDateModified" timestamp with time zone +CREATE TABLE library.chapters ( + item_id uuid NOT NULL, + chapter_index integer NOT NULL, + start_position_ticks bigint NOT NULL, + name text, + image_path text, + image_date_modified timestamp with time zone ); -ALTER TABLE library."Chapters" OWNER TO jellyfin; +ALTER TABLE library.chapters OWNER TO jellyfin; -- -- Name: ImageInfos; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."ImageInfos" ( - "Id" integer NOT NULL, - "UserId" uuid, - "Path" character varying(512) NOT NULL, - "LastModified" timestamp with time zone NOT NULL +CREATE TABLE library.image_infos ( + id integer NOT NULL, + user_id uuid, + path character varying(512) NOT NULL, + last_modified timestamp with time zone NOT NULL ); -ALTER TABLE library."ImageInfos" OWNER TO jellyfin; +ALTER TABLE library.image_infos OWNER TO jellyfin; -- --- Name: ImageInfos_Id_seq; Type: SEQUENCE; Schema: library; Owner: jellyfin +-- Name: image_infos_id_seq; Type: SEQUENCE; Schema: library; Owner: jellyfin -- -ALTER TABLE library."ImageInfos" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( - SEQUENCE NAME library."ImageInfos_Id_seq" +ALTER TABLE library.image_infos ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME library.image_infos_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE @@ -554,194 +554,194 @@ ALTER TABLE library."ImageInfos" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS I -- Name: ItemValues; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."ItemValues" ( - "ItemValueId" uuid NOT NULL, - "Type" integer NOT NULL, - "Value" text NOT NULL, - "CleanValue" text NOT NULL +CREATE TABLE library.item_values ( + item_value_id uuid NOT NULL, + type integer NOT NULL, + value text NOT NULL, + clean_value text NOT NULL ); -ALTER TABLE library."ItemValues" OWNER TO jellyfin; +ALTER TABLE library.item_values OWNER TO jellyfin; -- -- Name: ItemValuesMap; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."ItemValuesMap" ( - "ItemId" uuid NOT NULL, - "ItemValueId" uuid NOT NULL +CREATE TABLE library.item_values_map ( + item_id uuid NOT NULL, + item_value_id uuid NOT NULL ); -ALTER TABLE library."ItemValuesMap" OWNER TO jellyfin; +ALTER TABLE library.item_values_map OWNER TO jellyfin; -- -- Name: KeyframeData; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."KeyframeData" ( - "ItemId" uuid NOT NULL, - "TotalDuration" bigint NOT NULL, - "KeyframeTicks" bigint[] +CREATE TABLE library.keyframe_data ( + item_id uuid NOT NULL, + total_duration bigint NOT NULL, + keyframe_ticks bigint[] ); -ALTER TABLE library."KeyframeData" OWNER TO jellyfin; +ALTER TABLE library.keyframe_data OWNER TO jellyfin; -- -- Name: MediaSegments; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."MediaSegments" ( - "Id" uuid NOT NULL, - "ItemId" uuid NOT NULL, - "Type" integer NOT NULL, - "EndTicks" bigint NOT NULL, - "StartTicks" bigint NOT NULL, - "SegmentProviderId" text NOT NULL +CREATE TABLE library.media_segments ( + id uuid NOT NULL, + item_id uuid NOT NULL, + type integer NOT NULL, + end_ticks bigint NOT NULL, + start_ticks bigint NOT NULL, + segment_provider_id text NOT NULL ); -ALTER TABLE library."MediaSegments" OWNER TO jellyfin; +ALTER TABLE library.media_segments OWNER TO jellyfin; -- -- Name: MediaStreamInfos; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."MediaStreamInfos" ( - "ItemId" uuid NOT NULL, - "StreamIndex" integer NOT NULL, - "StreamType" integer NOT NULL, - "Codec" text, - "Language" text, - "ChannelLayout" text, - "Profile" text, - "AspectRatio" text, - "Path" text, - "IsInterlaced" boolean, - "BitRate" integer, - "Channels" integer, - "SampleRate" integer, - "IsDefault" boolean NOT NULL, - "IsForced" boolean NOT NULL, - "IsExternal" boolean NOT NULL, - "Height" integer, - "Width" integer, - "AverageFrameRate" real, - "RealFrameRate" real, - "Level" real, - "PixelFormat" text, - "BitDepth" integer, - "IsAnamorphic" boolean, - "RefFrames" integer, - "CodecTag" text, - "Comment" text, - "NalLengthSize" text, - "IsAvc" boolean, - "Title" text, - "TimeBase" text, - "CodecTimeBase" text, - "ColorPrimaries" text, - "ColorSpace" text, - "ColorTransfer" text, - "DvVersionMajor" integer, - "DvVersionMinor" integer, - "DvProfile" integer, - "DvLevel" integer, - "RpuPresentFlag" integer, - "ElPresentFlag" integer, - "BlPresentFlag" integer, - "DvBlSignalCompatibilityId" integer, - "IsHearingImpaired" boolean, - "Rotation" integer, - "KeyFrames" text, - "Hdr10PlusPresentFlag" boolean +CREATE TABLE library.media_stream_infos ( + item_id uuid NOT NULL, + stream_index integer NOT NULL, + stream_type integer NOT NULL, + codec text, + language text, + channel_layout text, + profile text, + aspect_ratio text, + path text, + is_interlaced boolean, + bit_rate integer, + channels integer, + sample_rate integer, + is_default boolean NOT NULL, + is_forced boolean NOT NULL, + is_external boolean NOT NULL, + height integer, + width integer, + average_frame_rate real, + real_frame_rate real, + level real, + pixel_format text, + bit_depth integer, + is_anamorphic boolean, + ref_frames integer, + codec_tag text, + comment text, + nal_length_size text, + is_avc boolean, + title text, + time_base text, + codec_time_base text, + color_primaries text, + color_space text, + color_transfer text, + dv_version_major integer, + dv_version_minor integer, + dv_profile integer, + dv_level integer, + rpu_present_flag integer, + el_present_flag integer, + bl_present_flag integer, + dv_bl_signal_compatibility_id integer, + is_hearing_impaired boolean, + rotation integer, + key_frames text, + hdr10_plus_present_flag boolean ); -ALTER TABLE library."MediaStreamInfos" OWNER TO jellyfin; +ALTER TABLE library.media_stream_infos OWNER TO jellyfin; -- -- Name: PeopleBaseItemMap; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."PeopleBaseItemMap" ( - "Role" text NOT NULL, - "ItemId" uuid NOT NULL, - "PeopleId" uuid NOT NULL, - "SortOrder" integer, - "ListOrder" integer +CREATE TABLE library.people_base_item_map ( + role text NOT NULL, + item_id uuid NOT NULL, + people_id uuid NOT NULL, + sort_order integer, + list_order integer ); -ALTER TABLE library."PeopleBaseItemMap" OWNER TO jellyfin; +ALTER TABLE library.people_base_item_map OWNER TO jellyfin; -- -- Name: Peoples; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."Peoples" ( - "Id" uuid NOT NULL, - "Name" text NOT NULL, - "PersonType" text +CREATE TABLE library.peoples ( + id uuid NOT NULL, + name text NOT NULL, + person_type text ); -ALTER TABLE library."Peoples" OWNER TO jellyfin; +ALTER TABLE library.peoples OWNER TO jellyfin; -- -- Name: TrickplayInfos; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."TrickplayInfos" ( - "ItemId" uuid NOT NULL, - "Width" integer NOT NULL, - "Height" integer NOT NULL, - "TileWidth" integer NOT NULL, - "TileHeight" integer NOT NULL, - "ThumbnailCount" integer NOT NULL, - "Interval" integer NOT NULL, - "Bandwidth" integer NOT NULL +CREATE TABLE library.trickplay_infos ( + item_id uuid NOT NULL, + width integer NOT NULL, + height integer NOT NULL, + tile_width integer NOT NULL, + tile_height integer NOT NULL, + thumbnail_count integer NOT NULL, + interval integer NOT NULL, + bandwidth integer NOT NULL ); -ALTER TABLE library."TrickplayInfos" OWNER TO jellyfin; +ALTER TABLE library.trickplay_infos OWNER TO jellyfin; -- -- Name: UserData; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."UserData" ( - "CustomDataKey" text NOT NULL, - "ItemId" uuid NOT NULL, - "UserId" uuid NOT NULL, - "Rating" double precision, - "PlaybackPositionTicks" bigint NOT NULL, - "PlayCount" integer NOT NULL, - "IsFavorite" boolean NOT NULL, - "LastPlayedDate" timestamp with time zone, - "Played" boolean NOT NULL, - "AudioStreamIndex" integer, - "SubtitleStreamIndex" integer, - "Likes" boolean, - "RetentionDate" timestamp with time zone +CREATE TABLE library.user_data ( + custom_data_key text NOT NULL, + item_id uuid NOT NULL, + user_id uuid NOT NULL, + rating double precision, + playback_position_ticks bigint NOT NULL, + play_count integer NOT NULL, + is_favorite boolean NOT NULL, + last_played_date timestamp with time zone, + played boolean NOT NULL, + audio_stream_index integer, + subtitle_stream_index integer, + likes boolean, + retention_date timestamp with time zone ); -ALTER TABLE library."UserData" OWNER TO jellyfin; +ALTER TABLE library.user_data OWNER TO jellyfin; -- -- Name: __EFMigrationsHistory; Type: TABLE; Schema: public; Owner: jellyfin -- -CREATE TABLE public."__EFMigrationsHistory" ( - "MigrationId" character varying(150) NOT NULL, - "ProductVersion" character varying(32) NOT NULL +CREATE TABLE public.__ef_migrations_history ( + migration_id character varying(150) NOT NULL, + product_version character varying(32) NOT NULL ); -ALTER TABLE public."__EFMigrationsHistory" OWNER TO jellyfin; +ALTER TABLE public.__ef_migrations_history OWNER TO jellyfin; -- -- Name: bloat_tables; Type: TABLE; Schema: public; Owner: postgres @@ -758,23 +758,23 @@ ALTER TABLE public.bloat_tables OWNER TO postgres; -- Name: AccessSchedules; Type: TABLE; Schema: users; Owner: jellyfin -- -CREATE TABLE users."AccessSchedules" ( - "Id" integer NOT NULL, - "UserId" uuid NOT NULL, - "DayOfWeek" integer NOT NULL, - "StartHour" double precision NOT NULL, - "EndHour" double precision NOT NULL +CREATE TABLE users.access_schedules ( + id integer NOT NULL, + user_id uuid NOT NULL, + day_of_week integer NOT NULL, + start_hour double precision NOT NULL, + end_hour double precision NOT NULL ); -ALTER TABLE users."AccessSchedules" OWNER TO jellyfin; +ALTER TABLE users.access_schedules OWNER TO jellyfin; -- --- Name: AccessSchedules_Id_seq; Type: SEQUENCE; Schema: users; Owner: jellyfin +-- Name: access_schedules_id_seq; Type: SEQUENCE; Schema: users; Owner: jellyfin -- -ALTER TABLE users."AccessSchedules" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( - SEQUENCE NAME users."AccessSchedules_Id_seq" +ALTER TABLE users.access_schedules ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME users.access_schedules_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE @@ -787,24 +787,24 @@ ALTER TABLE users."AccessSchedules" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT A -- Name: Permissions; Type: TABLE; Schema: users; Owner: jellyfin -- -CREATE TABLE users."Permissions" ( - "Id" integer NOT NULL, - "UserId" uuid, - "Kind" integer NOT NULL, - "Value" boolean NOT NULL, - "RowVersion" bigint NOT NULL, - "Permission_Permissions_Guid" uuid +CREATE TABLE users.permissions ( + id integer NOT NULL, + user_id uuid, + kind integer NOT NULL, + value boolean NOT NULL, + row_version bigint NOT NULL, + permission_permissions_guid uuid ); -ALTER TABLE users."Permissions" OWNER TO jellyfin; +ALTER TABLE users.permissions OWNER TO jellyfin; -- --- Name: Permissions_Id_seq; Type: SEQUENCE; Schema: users; Owner: jellyfin +-- Name: permissions_id_seq; Type: SEQUENCE; Schema: users; Owner: jellyfin -- -ALTER TABLE users."Permissions" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( - SEQUENCE NAME users."Permissions_Id_seq" +ALTER TABLE users.permissions ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME users.permissions_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE @@ -817,24 +817,24 @@ ALTER TABLE users."Permissions" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS ID -- Name: Preferences; Type: TABLE; Schema: users; Owner: jellyfin -- -CREATE TABLE users."Preferences" ( - "Id" integer NOT NULL, - "UserId" uuid, - "Kind" integer NOT NULL, - "Value" character varying(65535) NOT NULL, - "RowVersion" bigint NOT NULL, - "Preference_Preferences_Guid" uuid +CREATE TABLE users.preferences ( + id integer NOT NULL, + user_id uuid, + kind integer NOT NULL, + value character varying(65535) NOT NULL, + row_version bigint NOT NULL, + preference_preferences_guid uuid ); -ALTER TABLE users."Preferences" OWNER TO jellyfin; +ALTER TABLE users.preferences OWNER TO jellyfin; -- --- Name: Preferences_Id_seq; Type: SEQUENCE; Schema: users; Owner: jellyfin +-- Name: preferences_id_seq; Type: SEQUENCE; Schema: users; Owner: jellyfin -- -ALTER TABLE users."Preferences" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( - SEQUENCE NAME users."Preferences_Id_seq" +ALTER TABLE users.preferences ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME users.preferences_id_seq START WITH 1 INCREMENT BY 1 NO MINVALUE @@ -847,1028 +847,1028 @@ ALTER TABLE users."Preferences" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS ID -- Name: Users; Type: TABLE; Schema: users; Owner: jellyfin -- -CREATE TABLE users."Users" ( - "Id" uuid NOT NULL, - "Username" character varying(255) NOT NULL, - "Password" character varying(65535), - "MustUpdatePassword" boolean NOT NULL, - "AudioLanguagePreference" character varying(255), - "AuthenticationProviderId" character varying(255) NOT NULL, - "PasswordResetProviderId" character varying(255) NOT NULL, - "InvalidLoginAttemptCount" integer NOT NULL, - "LastActivityDate" timestamp with time zone, - "LastLoginDate" timestamp with time zone, - "LoginAttemptsBeforeLockout" integer, - "MaxActiveSessions" integer NOT NULL, - "SubtitleMode" integer NOT NULL, - "PlayDefaultAudioTrack" boolean NOT NULL, - "SubtitleLanguagePreference" character varying(255), - "DisplayMissingEpisodes" boolean NOT NULL, - "DisplayCollectionsView" boolean NOT NULL, - "EnableLocalPassword" boolean NOT NULL, - "HidePlayedInLatest" boolean NOT NULL, - "RememberAudioSelections" boolean NOT NULL, - "RememberSubtitleSelections" boolean NOT NULL, - "EnableNextEpisodeAutoPlay" boolean NOT NULL, - "EnableAutoLogin" boolean NOT NULL, - "EnableUserPreferenceAccess" boolean NOT NULL, - "MaxParentalRatingScore" integer, - "MaxParentalRatingSubScore" integer, - "RemoteClientBitrateLimit" integer, - "InternalId" bigint NOT NULL, - "SyncPlayAccess" integer NOT NULL, - "CastReceiverId" character varying(32), - "RowVersion" bigint NOT NULL +CREATE TABLE users.users ( + id uuid NOT NULL, + username character varying(255) NOT NULL, + password character varying(65535), + must_update_password boolean NOT NULL, + audio_language_preference character varying(255), + authentication_provider_id character varying(255) NOT NULL, + password_reset_provider_id character varying(255) NOT NULL, + invalid_login_attempt_count integer NOT NULL, + last_activity_date timestamp with time zone, + last_login_date timestamp with time zone, + login_attempts_before_lockout integer, + max_active_sessions integer NOT NULL, + subtitle_mode integer NOT NULL, + play_default_audio_track boolean NOT NULL, + subtitle_language_preference character varying(255), + display_missing_episodes boolean NOT NULL, + display_collections_view boolean NOT NULL, + enable_local_password boolean NOT NULL, + hide_played_in_latest boolean NOT NULL, + remember_audio_selections boolean NOT NULL, + remember_subtitle_selections boolean NOT NULL, + enable_next_episode_auto_play boolean NOT NULL, + enable_auto_login boolean NOT NULL, + enable_user_preference_access boolean NOT NULL, + max_parental_rating_score integer, + max_parental_rating_sub_score integer, + remote_client_bitrate_limit integer, + internal_id bigint NOT NULL, + sync_play_access integer NOT NULL, + cast_receiver_id character varying(32), + row_version bigint NOT NULL ); -ALTER TABLE users."Users" OWNER TO jellyfin; +ALTER TABLE users.users OWNER TO jellyfin; -- -- Name: ActivityLogs PK_ActivityLogs; Type: CONSTRAINT; Schema: activitylog; Owner: jellyfin -- -ALTER TABLE ONLY activitylog."ActivityLogs" - ADD CONSTRAINT "PK_ActivityLogs" PRIMARY KEY ("Id"); +ALTER TABLE ONLY activitylog.activity_logs + ADD CONSTRAINT PK_ActivityLogs PRIMARY KEY (id); -- -- Name: ApiKeys PK_ApiKeys; Type: CONSTRAINT; Schema: authentication; Owner: jellyfin -- -ALTER TABLE ONLY authentication."ApiKeys" - ADD CONSTRAINT "PK_ApiKeys" PRIMARY KEY ("Id"); +ALTER TABLE ONLY authentication.api_keys + ADD CONSTRAINT PK_ApiKeys PRIMARY KEY (id); -- -- Name: DeviceOptions PK_DeviceOptions; Type: CONSTRAINT; Schema: authentication; Owner: jellyfin -- -ALTER TABLE ONLY authentication."DeviceOptions" - ADD CONSTRAINT "PK_DeviceOptions" PRIMARY KEY ("Id"); +ALTER TABLE ONLY authentication.device_options + ADD CONSTRAINT PK_DeviceOptions PRIMARY KEY (id); -- -- Name: Devices PK_Devices; Type: CONSTRAINT; Schema: authentication; Owner: jellyfin -- -ALTER TABLE ONLY authentication."Devices" - ADD CONSTRAINT "PK_Devices" PRIMARY KEY ("Id"); +ALTER TABLE ONLY authentication.devices + ADD CONSTRAINT PK_Devices PRIMARY KEY (id); -- -- Name: CustomItemDisplayPreferences PK_CustomItemDisplayPreferences; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE ONLY displaypreferences."CustomItemDisplayPreferences" - ADD CONSTRAINT "PK_CustomItemDisplayPreferences" PRIMARY KEY ("Id"); +ALTER TABLE ONLY displaypreferences.custom_item_display_preferences + ADD CONSTRAINT PK_CustomItemDisplayPreferences PRIMARY KEY (id); -- -- Name: DisplayPreferences PK_DisplayPreferences; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE ONLY displaypreferences."DisplayPreferences" - ADD CONSTRAINT "PK_DisplayPreferences" PRIMARY KEY ("Id"); +ALTER TABLE ONLY displaypreferences.display_preferences + ADD CONSTRAINT PK_DisplayPreferences PRIMARY KEY (id); -- -- Name: HomeSection PK_HomeSection; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE ONLY displaypreferences."HomeSection" - ADD CONSTRAINT "PK_HomeSection" PRIMARY KEY ("Id"); +ALTER TABLE ONLY displaypreferences.home_sections + ADD CONSTRAINT PK_HomeSection PRIMARY KEY (id); -- -- Name: ItemDisplayPreferences PK_ItemDisplayPreferences; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE ONLY displaypreferences."ItemDisplayPreferences" - ADD CONSTRAINT "PK_ItemDisplayPreferences" PRIMARY KEY ("Id"); +ALTER TABLE ONLY displaypreferences.item_display_preferences + ADD CONSTRAINT PK_ItemDisplayPreferences PRIMARY KEY (id); -- -- Name: AncestorIds PK_AncestorIds; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."AncestorIds" - ADD CONSTRAINT "PK_AncestorIds" PRIMARY KEY ("ItemId", "ParentItemId"); +ALTER TABLE ONLY library.ancestor_ids + ADD CONSTRAINT PK_AncestorIds PRIMARY KEY (item_id, parent_item_id); -- -- Name: AttachmentStreamInfos PK_AttachmentStreamInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."AttachmentStreamInfos" - ADD CONSTRAINT "PK_AttachmentStreamInfos" PRIMARY KEY ("ItemId", "Index"); +ALTER TABLE ONLY library.attachment_stream_infos + ADD CONSTRAINT PK_AttachmentStreamInfos PRIMARY KEY (item_id, index); -- -- Name: BaseItemImageInfos PK_BaseItemImageInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."BaseItemImageInfos" - ADD CONSTRAINT "PK_BaseItemImageInfos" PRIMARY KEY ("Id"); +ALTER TABLE ONLY library.base_item_image_infos + ADD CONSTRAINT PK_BaseItemImageInfos PRIMARY KEY (id); -- -- Name: BaseItemMetadataFields PK_BaseItemMetadataFields; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."BaseItemMetadataFields" - ADD CONSTRAINT "PK_BaseItemMetadataFields" PRIMARY KEY ("Id", "ItemId"); +ALTER TABLE ONLY library.base_item_metadata_fields + ADD CONSTRAINT PK_BaseItemMetadataFields PRIMARY KEY (id, item_id); -- -- Name: BaseItemProviders PK_BaseItemProviders; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."BaseItemProviders" - ADD CONSTRAINT "PK_BaseItemProviders" PRIMARY KEY ("ItemId", "ProviderId"); +ALTER TABLE ONLY library.base_item_providers + ADD CONSTRAINT PK_BaseItemProviders PRIMARY KEY (item_id, provider_id); -- -- Name: BaseItemTrailerTypes PK_BaseItemTrailerTypes; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."BaseItemTrailerTypes" - ADD CONSTRAINT "PK_BaseItemTrailerTypes" PRIMARY KEY ("Id", "ItemId"); +ALTER TABLE ONLY library.base_item_trailer_types + ADD CONSTRAINT PK_BaseItemTrailerTypes PRIMARY KEY (id, item_id); -- -- Name: BaseItems PK_BaseItems; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."BaseItems" - ADD CONSTRAINT "PK_BaseItems" PRIMARY KEY ("Id"); +ALTER TABLE ONLY library.base_items + ADD CONSTRAINT PK_BaseItems PRIMARY KEY (id); -- -- Name: Chapters PK_Chapters; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."Chapters" - ADD CONSTRAINT "PK_Chapters" PRIMARY KEY ("ItemId", "ChapterIndex"); +ALTER TABLE ONLY library.chapters + ADD CONSTRAINT PK_Chapters PRIMARY KEY (item_id, chapter_index); -- -- Name: ImageInfos PK_ImageInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."ImageInfos" - ADD CONSTRAINT "PK_ImageInfos" PRIMARY KEY ("Id"); +ALTER TABLE ONLY library.image_infos + ADD CONSTRAINT PK_ImageInfos PRIMARY KEY (id); -- -- Name: ItemValues PK_ItemValues; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."ItemValues" - ADD CONSTRAINT "PK_ItemValues" PRIMARY KEY ("ItemValueId"); +ALTER TABLE ONLY library.item_values + ADD CONSTRAINT PK_ItemValues PRIMARY KEY (item_value_id); -- -- Name: ItemValuesMap PK_ItemValuesMap; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."ItemValuesMap" - ADD CONSTRAINT "PK_ItemValuesMap" PRIMARY KEY ("ItemValueId", "ItemId"); +ALTER TABLE ONLY library.item_values_map + ADD CONSTRAINT PK_ItemValuesMap PRIMARY KEY (item_value_id, item_id); -- -- Name: KeyframeData PK_KeyframeData; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."KeyframeData" - ADD CONSTRAINT "PK_KeyframeData" PRIMARY KEY ("ItemId"); +ALTER TABLE ONLY library.keyframe_data + ADD CONSTRAINT PK_KeyframeData PRIMARY KEY (item_id); -- -- Name: MediaSegments PK_MediaSegments; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."MediaSegments" - ADD CONSTRAINT "PK_MediaSegments" PRIMARY KEY ("Id"); +ALTER TABLE ONLY library.media_segments + ADD CONSTRAINT PK_MediaSegments PRIMARY KEY (id); -- -- Name: MediaStreamInfos PK_MediaStreamInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."MediaStreamInfos" - ADD CONSTRAINT "PK_MediaStreamInfos" PRIMARY KEY ("ItemId", "StreamIndex"); +ALTER TABLE ONLY library.media_stream_infos + ADD CONSTRAINT PK_MediaStreamInfos PRIMARY KEY (item_id, stream_index); -- -- Name: PeopleBaseItemMap PK_PeopleBaseItemMap; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."PeopleBaseItemMap" - ADD CONSTRAINT "PK_PeopleBaseItemMap" PRIMARY KEY ("ItemId", "PeopleId", "Role"); +ALTER TABLE ONLY library.people_base_item_map + ADD CONSTRAINT PK_PeopleBaseItemMap PRIMARY KEY (item_id, people_id, role); -- -- Name: Peoples PK_Peoples; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."Peoples" - ADD CONSTRAINT "PK_Peoples" PRIMARY KEY ("Id"); +ALTER TABLE ONLY library.peoples + ADD CONSTRAINT PK_Peoples PRIMARY KEY (id); -- -- Name: TrickplayInfos PK_TrickplayInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."TrickplayInfos" - ADD CONSTRAINT "PK_TrickplayInfos" PRIMARY KEY ("ItemId", "Width"); +ALTER TABLE ONLY library.trickplay_infos + ADD CONSTRAINT PK_TrickplayInfos PRIMARY KEY (item_id, "Width"); -- -- Name: UserData PK_UserData; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."UserData" - ADD CONSTRAINT "PK_UserData" PRIMARY KEY ("ItemId", "UserId", "CustomDataKey"); +ALTER TABLE ONLY library.user_data + ADD CONSTRAINT PK_UserData PRIMARY KEY (item_id, user_id, custom_data_key); -- -- Name: __EFMigrationsHistory PK___EFMigrationsHistory; Type: CONSTRAINT; Schema: public; Owner: jellyfin -- -ALTER TABLE ONLY public."__EFMigrationsHistory" - ADD CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY ("MigrationId"); +ALTER TABLE ONLY public.__ef_migrations_history + ADD CONSTRAINT PK___EFMigrationsHistory PRIMARY KEY (migration_id); -- -- Name: AccessSchedules PK_AccessSchedules; Type: CONSTRAINT; Schema: users; Owner: jellyfin -- -ALTER TABLE ONLY users."AccessSchedules" - ADD CONSTRAINT "PK_AccessSchedules" PRIMARY KEY ("Id"); +ALTER TABLE ONLY users.access_schedules + ADD CONSTRAINT PK_AccessSchedules PRIMARY KEY (id); -- -- Name: Permissions PK_Permissions; Type: CONSTRAINT; Schema: users; Owner: jellyfin -- -ALTER TABLE ONLY users."Permissions" - ADD CONSTRAINT "PK_Permissions" PRIMARY KEY ("Id"); +ALTER TABLE ONLY users.permissions + ADD CONSTRAINT PK_Permissions PRIMARY KEY (id); -- -- Name: Preferences PK_Preferences; Type: CONSTRAINT; Schema: users; Owner: jellyfin -- -ALTER TABLE ONLY users."Preferences" - ADD CONSTRAINT "PK_Preferences" PRIMARY KEY ("Id"); +ALTER TABLE ONLY users.preferences + ADD CONSTRAINT PK_Preferences PRIMARY KEY (id); -- -- Name: Users PK_Users; Type: CONSTRAINT; Schema: users; Owner: jellyfin -- -ALTER TABLE ONLY users."Users" - ADD CONSTRAINT "PK_Users" PRIMARY KEY ("Id"); +ALTER TABLE ONLY users.users + ADD CONSTRAINT PK_Users PRIMARY KEY (id); -- -- Name: IX_ActivityLogs_DateCreated; Type: INDEX; Schema: activitylog; Owner: jellyfin -- -CREATE INDEX "IX_ActivityLogs_DateCreated" ON activitylog."ActivityLogs" USING btree ("DateCreated"); +CREATE INDEX IX_ActivityLogs_DateCreated ON activitylog.activity_logs USING btree (date_created); -- -- Name: idx_activitylogs_userid_datecreated; Type: INDEX; Schema: activitylog; Owner: jellyfin -- -CREATE INDEX idx_activitylogs_userid_datecreated ON activitylog."ActivityLogs" USING btree ("UserId", "DateCreated" DESC) WHERE ("UserId" IS NOT NULL); +CREATE INDEX idx_activitylogs_userid_datecreated ON activitylog.activity_logs USING btree (user_id, date_created DESC) WHERE (user_id IS NOT NULL); -- -- Name: IX_ApiKeys_AccessToken; Type: INDEX; Schema: authentication; Owner: jellyfin -- -CREATE UNIQUE INDEX "IX_ApiKeys_AccessToken" ON authentication."ApiKeys" USING btree ("AccessToken"); +CREATE UNIQUE INDEX IX_ApiKeys_AccessToken ON authentication.api_keys USING btree (access_token); -- -- Name: IX_DeviceOptions_DeviceId; Type: INDEX; Schema: authentication; Owner: jellyfin -- -CREATE UNIQUE INDEX "IX_DeviceOptions_DeviceId" ON authentication."DeviceOptions" USING btree ("DeviceId"); +CREATE UNIQUE INDEX IX_DeviceOptions_DeviceId ON authentication.device_options USING btree (device_id); -- -- Name: IX_Devices_AccessToken_DateLastActivity; Type: INDEX; Schema: authentication; Owner: jellyfin -- -CREATE INDEX "IX_Devices_AccessToken_DateLastActivity" ON authentication."Devices" USING btree ("AccessToken", "DateLastActivity"); +CREATE INDEX IX_Devices_AccessToken_DateLastActivity ON authentication.devices USING btree (access_token, date_last_activity); -- -- Name: IX_Devices_DeviceId; Type: INDEX; Schema: authentication; Owner: jellyfin -- -CREATE INDEX "IX_Devices_DeviceId" ON authentication."Devices" USING btree ("DeviceId"); +CREATE INDEX IX_Devices_DeviceId ON authentication.devices USING btree (device_id); -- -- Name: IX_Devices_DeviceId_DateLastActivity; Type: INDEX; Schema: authentication; Owner: jellyfin -- -CREATE INDEX "IX_Devices_DeviceId_DateLastActivity" ON authentication."Devices" USING btree ("DeviceId", "DateLastActivity"); +CREATE INDEX IX_Devices_DeviceId_DateLastActivity ON authentication.devices USING btree (device_id, date_last_activity); -- -- Name: IX_Devices_UserId_DeviceId; Type: INDEX; Schema: authentication; Owner: jellyfin -- -CREATE INDEX "IX_Devices_UserId_DeviceId" ON authentication."Devices" USING btree ("UserId", "DeviceId"); +CREATE INDEX IX_Devices_UserId_DeviceId ON authentication.devices USING btree (user_id, device_id); -- -- Name: IX_CustomItemDisplayPreferences_UserId_ItemId_Client_Key; Type: INDEX; Schema: displaypreferences; Owner: jellyfin -- -CREATE UNIQUE INDEX "IX_CustomItemDisplayPreferences_UserId_ItemId_Client_Key" ON displaypreferences."CustomItemDisplayPreferences" USING btree ("UserId", "ItemId", "Client", "Key"); +CREATE UNIQUE INDEX IX_CustomItemDisplayPreferences_UserId_ItemId_Client_Key ON displaypreferences.custom_item_display_preferences USING btree (user_id, item_id, client, "Key"); -- -- Name: IX_DisplayPreferences_UserId_ItemId_Client; Type: INDEX; Schema: displaypreferences; Owner: jellyfin -- -CREATE UNIQUE INDEX "IX_DisplayPreferences_UserId_ItemId_Client" ON displaypreferences."DisplayPreferences" USING btree ("UserId", "ItemId", "Client"); +CREATE UNIQUE INDEX IX_DisplayPreferences_UserId_ItemId_Client ON displaypreferences.display_preferences USING btree (user_id, item_id, client); -- -- Name: IX_HomeSection_DisplayPreferencesId; Type: INDEX; Schema: displaypreferences; Owner: jellyfin -- -CREATE INDEX "IX_HomeSection_DisplayPreferencesId" ON displaypreferences."HomeSection" USING btree ("DisplayPreferencesId"); +CREATE INDEX IX_HomeSection_DisplayPreferencesId ON displaypreferences.home_sections USING btree (display_preferences_id); -- -- Name: IX_ItemDisplayPreferences_UserId; Type: INDEX; Schema: displaypreferences; Owner: jellyfin -- -CREATE INDEX "IX_ItemDisplayPreferences_UserId" ON displaypreferences."ItemDisplayPreferences" USING btree ("UserId"); +CREATE INDEX IX_ItemDisplayPreferences_UserId ON displaypreferences.item_display_preferences USING btree (user_id); -- -- Name: IX_AncestorIds_ParentItemId; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_AncestorIds_ParentItemId" ON library."AncestorIds" USING btree ("ParentItemId"); +CREATE INDEX IX_AncestorIds_ParentItemId ON library.ancestor_ids USING btree (parent_item_id); -- -- Name: IX_BaseItemImageInfos_ItemId; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItemImageInfos_ItemId" ON library."BaseItemImageInfos" USING btree ("ItemId"); +CREATE INDEX IX_BaseItemImageInfos_ItemId ON library.base_item_image_infos USING btree (item_id); -- -- Name: IX_BaseItemMetadataFields_ItemId; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItemMetadataFields_ItemId" ON library."BaseItemMetadataFields" USING btree ("ItemId"); +CREATE INDEX IX_BaseItemMetadataFields_ItemId ON library.base_item_metadata_fields USING btree (item_id); -- -- Name: IX_BaseItemProviders_ProviderId_ProviderValue_ItemId; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItemProviders_ProviderId_ProviderValue_ItemId" ON library."BaseItemProviders" USING btree ("ProviderId", "ProviderValue", "ItemId"); +CREATE INDEX IX_BaseItemProviders_ProviderId_ProviderValue_ItemId ON library.base_item_providers USING btree (provider_id, provider_value, item_id); -- -- Name: IX_BaseItemTrailerTypes_ItemId; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItemTrailerTypes_ItemId" ON library."BaseItemTrailerTypes" USING btree ("ItemId"); +CREATE INDEX IX_BaseItemTrailerTypes_ItemId ON library.base_item_trailer_types USING btree (item_id); -- -- Name: IX_BaseItems_Id_Type_IsFolder_IsVirtualItem; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItems_Id_Type_IsFolder_IsVirtualItem" ON library."BaseItems" USING btree ("Id", "Type", "IsFolder", "IsVirtualItem"); +CREATE INDEX IX_BaseItems_Id_Type_IsFolder_IsVirtualItem ON library.base_items USING btree (id, type, is_folder, is_virtual_item); -- -- Name: IX_BaseItems_IsFolder_TopParentId_IsVirtualItem_PresentationUn~; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItems_IsFolder_TopParentId_IsVirtualItem_PresentationUn~" ON library."BaseItems" USING btree ("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); +CREATE INDEX IX_BaseItems_IsFolder_TopParentId_IsVirtualItem_PresentationUn~ ON library.base_items USING btree (is_folder, top_parent_id, is_virtual_item, presentation_unique_key, date_created); -- -- Name: IX_BaseItems_MediaType_TopParentId_IsVirtualItem_PresentationU~; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItems_MediaType_TopParentId_IsVirtualItem_PresentationU~" ON library."BaseItems" USING btree ("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); +CREATE INDEX IX_BaseItems_MediaType_TopParentId_IsVirtualItem_PresentationU~ ON library.base_items USING btree ("MediaType", top_parent_id, is_virtual_item, presentation_unique_key); -- -- Name: IX_BaseItems_ParentId; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItems_ParentId" ON library."BaseItems" USING btree ("ParentId"); +CREATE INDEX IX_BaseItems_ParentId ON library.base_items USING btree ("ParentId"); -- -- Name: IX_BaseItems_Path; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItems_Path" ON library."BaseItems" USING btree ("Path"); +CREATE INDEX IX_BaseItems_Path ON library.base_items USING btree (path); -- -- Name: IX_BaseItems_PresentationUniqueKey; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItems_PresentationUniqueKey" ON library."BaseItems" USING btree ("PresentationUniqueKey"); +CREATE INDEX IX_BaseItems_PresentationUniqueKey ON library.base_items USING btree (presentation_unique_key); -- -- Name: IX_BaseItems_TopParentId_Id; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItems_TopParentId_Id" ON library."BaseItems" USING btree ("TopParentId", "Id"); +CREATE INDEX IX_BaseItems_TopParentId_Id ON library.base_items USING btree (top_parent_id, id); -- -- Name: IX_BaseItems_Type_SeriesPresentationUniqueKey_IsFolder_IsVirtu~; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItems_Type_SeriesPresentationUniqueKey_IsFolder_IsVirtu~" ON library."BaseItems" USING btree ("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); +CREATE INDEX IX_BaseItems_Type_SeriesPresentationUniqueKey_IsFolder_IsVirtu~ ON library.base_items USING btree (type, series_presentation_unique_key, is_folder, is_virtual_item); -- -- Name: IX_BaseItems_Type_SeriesPresentationUniqueKey_PresentationUniq~; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItems_Type_SeriesPresentationUniqueKey_PresentationUniq~" ON library."BaseItems" USING btree ("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); +CREATE INDEX IX_BaseItems_Type_SeriesPresentationUniqueKey_PresentationUniq~ ON library.base_items USING btree (type, series_presentation_unique_key, presentation_unique_key, sort_name); -- -- Name: IX_BaseItems_Type_TopParentId_Id; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItems_Type_TopParentId_Id" ON library."BaseItems" USING btree ("Type", "TopParentId", "Id"); +CREATE INDEX IX_BaseItems_Type_TopParentId_Id ON library.base_items USING btree (type, top_parent_id, id); -- -- Name: IX_BaseItems_Type_TopParentId_IsVirtualItem_PresentationUnique~; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItems_Type_TopParentId_IsVirtualItem_PresentationUnique~" ON library."BaseItems" USING btree ("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); +CREATE INDEX IX_BaseItems_Type_TopParentId_IsVirtualItem_PresentationUnique~ ON library.base_items USING btree (type, top_parent_id, is_virtual_item, presentation_unique_key, date_created); -- -- Name: IX_BaseItems_Type_TopParentId_PresentationUniqueKey; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItems_Type_TopParentId_PresentationUniqueKey" ON library."BaseItems" USING btree ("Type", "TopParentId", "PresentationUniqueKey"); +CREATE INDEX IX_BaseItems_Type_TopParentId_PresentationUniqueKey ON library.base_items USING btree (type, top_parent_id, presentation_unique_key); -- -- Name: IX_BaseItems_Type_TopParentId_StartDate; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItems_Type_TopParentId_StartDate" ON library."BaseItems" USING btree ("Type", "TopParentId", "StartDate"); +CREATE INDEX IX_BaseItems_Type_TopParentId_StartDate ON library.base_items USING btree (type, top_parent_id, start_date); -- -- Name: IX_ImageInfos_UserId; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE UNIQUE INDEX "IX_ImageInfos_UserId" ON library."ImageInfos" USING btree ("UserId"); +CREATE UNIQUE INDEX IX_ImageInfos_UserId ON library.image_infos USING btree (user_id); -- -- Name: IX_ItemValuesMap_ItemId; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_ItemValuesMap_ItemId" ON library."ItemValuesMap" USING btree ("ItemId"); +CREATE INDEX IX_ItemValuesMap_ItemId ON library.item_values_map USING btree (item_id); -- -- Name: IX_ItemValues_Type_CleanValue; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_ItemValues_Type_CleanValue" ON library."ItemValues" USING btree ("Type", "CleanValue"); +CREATE INDEX IX_ItemValues_Type_CleanValue ON library.item_values USING btree (type, clean_value); -- -- Name: IX_ItemValues_Type_Value; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE UNIQUE INDEX "IX_ItemValues_Type_Value" ON library."ItemValues" USING btree ("Type", "Value"); +CREATE UNIQUE INDEX IX_ItemValues_Type_Value ON library.item_values USING btree (type, value); -- -- Name: IX_MediaStreamInfos_StreamIndex; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_MediaStreamInfos_StreamIndex" ON library."MediaStreamInfos" USING btree ("StreamIndex"); +CREATE INDEX IX_MediaStreamInfos_StreamIndex ON library.media_stream_infos USING btree (stream_index); -- -- Name: IX_MediaStreamInfos_StreamIndex_StreamType; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_MediaStreamInfos_StreamIndex_StreamType" ON library."MediaStreamInfos" USING btree ("StreamIndex", "StreamType"); +CREATE INDEX IX_MediaStreamInfos_StreamIndex_StreamType ON library.media_stream_infos USING btree (stream_index, stream_type); -- -- Name: IX_MediaStreamInfos_StreamIndex_StreamType_Language; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_MediaStreamInfos_StreamIndex_StreamType_Language" ON library."MediaStreamInfos" USING btree ("StreamIndex", "StreamType", "Language"); +CREATE INDEX IX_MediaStreamInfos_StreamIndex_StreamType_Language ON library.media_stream_infos USING btree (stream_index, stream_type, language); -- -- Name: IX_MediaStreamInfos_StreamType; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_MediaStreamInfos_StreamType" ON library."MediaStreamInfos" USING btree ("StreamType"); +CREATE INDEX IX_MediaStreamInfos_StreamType ON library.media_stream_infos USING btree (stream_type); -- -- Name: IX_PeopleBaseItemMap_ItemId_ListOrder; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_PeopleBaseItemMap_ItemId_ListOrder" ON library."PeopleBaseItemMap" USING btree ("ItemId", "ListOrder"); +CREATE INDEX IX_PeopleBaseItemMap_ItemId_ListOrder ON library.people_base_item_map USING btree (item_id, list_order); -- -- Name: IX_PeopleBaseItemMap_ItemId_SortOrder; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_PeopleBaseItemMap_ItemId_SortOrder" ON library."PeopleBaseItemMap" USING btree ("ItemId", "SortOrder"); +CREATE INDEX IX_PeopleBaseItemMap_ItemId_SortOrder ON library.people_base_item_map USING btree (item_id, sort_order); -- -- Name: IX_PeopleBaseItemMap_PeopleId; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_PeopleBaseItemMap_PeopleId" ON library."PeopleBaseItemMap" USING btree ("PeopleId"); +CREATE INDEX IX_PeopleBaseItemMap_PeopleId ON library.people_base_item_map USING btree (people_id); -- -- Name: IX_Peoples_Name; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_Peoples_Name" ON library."Peoples" USING btree ("Name"); +CREATE INDEX IX_Peoples_Name ON library.peoples USING btree (name); -- -- Name: IX_UserData_ItemId_UserId_IsFavorite; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_UserData_ItemId_UserId_IsFavorite" ON library."UserData" USING btree ("ItemId", "UserId", "IsFavorite"); +CREATE INDEX IX_UserData_ItemId_UserId_IsFavorite ON library.user_data USING btree (item_id, user_id, is_favorite); -- -- Name: IX_UserData_ItemId_UserId_LastPlayedDate; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_UserData_ItemId_UserId_LastPlayedDate" ON library."UserData" USING btree ("ItemId", "UserId", "LastPlayedDate"); +CREATE INDEX IX_UserData_ItemId_UserId_LastPlayedDate ON library.user_data USING btree (item_id, user_id, last_played_date); -- -- Name: IX_UserData_ItemId_UserId_PlaybackPositionTicks; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_UserData_ItemId_UserId_PlaybackPositionTicks" ON library."UserData" USING btree ("ItemId", "UserId", "PlaybackPositionTicks"); +CREATE INDEX IX_UserData_ItemId_UserId_PlaybackPositionTicks ON library.user_data USING btree (item_id, user_id, playback_position_ticks); -- -- Name: IX_UserData_ItemId_UserId_Played; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_UserData_ItemId_UserId_Played" ON library."UserData" USING btree ("ItemId", "UserId", "Played"); +CREATE INDEX IX_UserData_ItemId_UserId_Played ON library.user_data USING btree (item_id, user_id, played); -- -- Name: IX_UserData_UserId; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_UserData_UserId" ON library."UserData" USING btree ("UserId"); +CREATE INDEX IX_UserData_UserId ON library.user_data USING btree (user_id); -- -- Name: baseitemproviders_providerid_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX baseitemproviders_providerid_idx ON library."BaseItemProviders" USING btree ("ProviderId", "ItemId"); +CREATE INDEX baseitemproviders_providerid_idx ON library.base_item_providers USING btree (provider_id, item_id); -- -- Name: baseitemproviders_providervalue_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX baseitemproviders_providervalue_idx ON library."BaseItemProviders" USING btree ("ProviderValue", "ProviderId"); +CREATE INDEX baseitemproviders_providervalue_idx ON library.base_item_providers USING btree (provider_value, provider_id); -- -- Name: baseitems_communityrating_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX baseitems_communityrating_idx ON library."BaseItems" USING btree ("CommunityRating" DESC); +CREATE INDEX baseitems_communityrating_idx ON library.base_items USING btree (community_rating DESC); -- -- Name: baseitems_datecreated_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX baseitems_datecreated_idx ON library."BaseItems" USING btree ("DateCreated" DESC); +CREATE INDEX baseitems_datecreated_idx ON library.base_items USING btree (date_created DESC); -- -- Name: baseitems_datemodified_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX baseitems_datemodified_idx ON library."BaseItems" USING btree ("DateModified" DESC); +CREATE INDEX baseitems_datemodified_idx ON library.base_items USING btree (date_modified DESC); -- -- Name: baseitems_parentid_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX baseitems_parentid_idx ON library."BaseItems" USING btree ("ParentId", "Type"); +CREATE INDEX baseitems_parentid_idx ON library.base_items USING btree ("ParentId", type); -- -- Name: baseitems_premieredate_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX baseitems_premieredate_idx ON library."BaseItems" USING btree ("PremiereDate" DESC); +CREATE INDEX baseitems_premieredate_idx ON library.base_items USING btree (premiere_date DESC); -- -- Name: baseitems_productionyear_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX baseitems_productionyear_idx ON library."BaseItems" USING btree ("ProductionYear" DESC); +CREATE INDEX baseitems_productionyear_idx ON library.base_items USING btree (production_year DESC); -- -- Name: baseitems_seriespresentationuniquekey_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX baseitems_seriespresentationuniquekey_idx ON library."BaseItems" USING btree ("SeriesPresentationUniqueKey", "IndexNumber", "ParentIndexNumber"); +CREATE INDEX baseitems_seriespresentationuniquekey_idx ON library.base_items USING btree (series_presentation_unique_key, "IndexNumber", "ParentIndexNumber"); -- -- Name: baseitems_sortname_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX baseitems_sortname_idx ON library."BaseItems" USING btree ("SortName"); +CREATE INDEX baseitems_sortname_idx ON library.base_items USING btree (sort_name); -- -- Name: baseitems_topparentid_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX baseitems_topparentid_idx ON library."BaseItems" USING btree ("TopParentId", "Type"); +CREATE INDEX baseitems_topparentid_idx ON library.base_items USING btree (top_parent_id, type); -- -- Name: idx_baseitems_datecreated_filtered; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX idx_baseitems_datecreated_filtered ON library."BaseItems" USING btree ("DateCreated" DESC, "Type", "IsVirtualItem") WHERE (("DateCreated" IS NOT NULL) AND ("IsVirtualItem" = false)); +CREATE INDEX idx_baseitems_datecreated_filtered ON library.base_items USING btree (date_created DESC, type, is_virtual_item) WHERE ((date_created IS NOT NULL) AND (is_virtual_item = false)); -- -- Name: idx_baseitems_presentationuniquekey_episodes; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX idx_baseitems_presentationuniquekey_episodes ON library."BaseItems" USING btree ("PresentationUniqueKey", "TopParentId", "IsVirtualItem") WHERE (("Type" = 'MediaBrowser.Controller.Entities.TV.Episode'::text) AND ("PresentationUniqueKey" IS NOT NULL)); +CREATE INDEX idx_baseitems_presentationuniquekey_episodes ON library.base_items USING btree (presentation_unique_key, top_parent_id, is_virtual_item) WHERE ((type = 'MediaBrowser.Controller.Entities.TV.Episode'::text) AND (presentation_unique_key IS NOT NULL)); -- -- Name: idx_baseitems_topparentid_isfolder; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX idx_baseitems_topparentid_isfolder ON library."BaseItems" USING btree ("TopParentId", "IsFolder", "IsVirtualItem") WHERE ("TopParentId" IS NOT NULL); +CREATE INDEX idx_baseitems_topparentid_isfolder ON library.base_items USING btree (top_parent_id, is_folder, is_virtual_item) WHERE (top_parent_id IS NOT NULL); -- -- Name: idx_baseitems_type_isvirtualitem_topparentid; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX idx_baseitems_type_isvirtualitem_topparentid ON library."BaseItems" USING btree ("Type", "IsVirtualItem", "TopParentId") WHERE ("IsVirtualItem" = false); +CREATE INDEX idx_baseitems_type_isvirtualitem_topparentid ON library.base_items USING btree (type, is_virtual_item, top_parent_id) WHERE (is_virtual_item = false); -- -- Name: idx_itemvalues_cleanvalue; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX idx_itemvalues_cleanvalue ON library."ItemValues" USING btree ("CleanValue") WHERE ("CleanValue" IS NOT NULL); +CREATE INDEX idx_itemvalues_cleanvalue ON library.item_values USING btree (clean_value) WHERE (clean_value IS NOT NULL); -- -- Name: idx_itemvalues_id_cleanvalue; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX idx_itemvalues_id_cleanvalue ON library."ItemValues" USING btree ("ItemValueId", "CleanValue"); +CREATE INDEX idx_itemvalues_id_cleanvalue ON library.item_values USING btree (item_value_id, clean_value); -- -- Name: idx_itemvalues_value; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX idx_itemvalues_value ON library."ItemValues" USING btree ("Value") WHERE ("Value" IS NOT NULL); +CREATE INDEX idx_itemvalues_value ON library.item_values USING btree (value) WHERE (value IS NOT NULL); -- -- Name: idx_itemvaluesmap_itemvalueid_itemid; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX idx_itemvaluesmap_itemvalueid_itemid ON library."ItemValuesMap" USING btree ("ItemValueId", "ItemId"); +CREATE INDEX idx_itemvaluesmap_itemvalueid_itemid ON library.item_values_map USING btree (item_value_id, item_id); -- -- Name: mediastreaminfos_codec_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX mediastreaminfos_codec_idx ON library."MediaStreamInfos" USING btree ("Codec"); +CREATE INDEX mediastreaminfos_codec_idx ON library.media_stream_infos USING btree (codec); -- -- Name: mediastreaminfos_itemid_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX mediastreaminfos_itemid_idx ON library."MediaStreamInfos" USING btree ("ItemId", "StreamType"); +CREATE INDEX mediastreaminfos_itemid_idx ON library.media_stream_infos USING btree (item_id, stream_type); -- -- Name: peoplebaseitemmap_itemid_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX peoplebaseitemmap_itemid_idx ON library."PeopleBaseItemMap" USING btree ("ItemId", "PeopleId"); +CREATE INDEX peoplebaseitemmap_itemid_idx ON library.people_base_item_map USING btree (item_id, people_id); -- -- Name: peoplebaseitemmap_peopleid_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX peoplebaseitemmap_peopleid_idx ON library."PeopleBaseItemMap" USING btree ("PeopleId", "ItemId"); +CREATE INDEX peoplebaseitemmap_peopleid_idx ON library.people_base_item_map USING btree (people_id, item_id); -- -- Name: userdata_lastplayeddate_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX userdata_lastplayeddate_idx ON library."UserData" USING btree ("LastPlayedDate" DESC); +CREATE INDEX userdata_lastplayeddate_idx ON library.user_data USING btree (last_played_date DESC); -- -- Name: userdata_userid_isfavorite_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX userdata_userid_isfavorite_idx ON library."UserData" USING btree ("UserId", "IsFavorite"); +CREATE INDEX userdata_userid_isfavorite_idx ON library.user_data USING btree (user_id, is_favorite); -- -- Name: userdata_userid_played_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX userdata_userid_played_idx ON library."UserData" USING btree ("UserId", "Played"); +CREATE INDEX userdata_userid_played_idx ON library.user_data USING btree (user_id, played); -- -- Name: IX_AccessSchedules_UserId; Type: INDEX; Schema: users; Owner: jellyfin -- -CREATE INDEX "IX_AccessSchedules_UserId" ON users."AccessSchedules" USING btree ("UserId"); +CREATE INDEX IX_AccessSchedules_UserId ON users.access_schedules USING btree (user_id); -- -- Name: IX_Permissions_UserId_Kind; Type: INDEX; Schema: users; Owner: jellyfin -- -CREATE UNIQUE INDEX "IX_Permissions_UserId_Kind" ON users."Permissions" USING btree ("UserId", "Kind") WHERE ("UserId" IS NOT NULL); +CREATE UNIQUE INDEX IX_Permissions_UserId_Kind ON users.permissions USING btree (user_id, kind) WHERE (user_id IS NOT NULL); -- -- Name: IX_Preferences_UserId_Kind; Type: INDEX; Schema: users; Owner: jellyfin -- -CREATE UNIQUE INDEX "IX_Preferences_UserId_Kind" ON users."Preferences" USING btree ("UserId", "Kind") WHERE ("UserId" IS NOT NULL); +CREATE UNIQUE INDEX IX_Preferences_UserId_Kind ON users.preferences USING btree (user_id, kind) WHERE (user_id IS NOT NULL); -- -- Name: IX_Users_Username; Type: INDEX; Schema: users; Owner: jellyfin -- -CREATE UNIQUE INDEX "IX_Users_Username" ON users."Users" USING btree ("Username"); +CREATE UNIQUE INDEX IX_Users_Username ON users.users USING btree (username); -- -- Name: Devices FK_Devices_Users_UserId; Type: FK CONSTRAINT; Schema: authentication; Owner: jellyfin -- -ALTER TABLE ONLY authentication."Devices" - ADD CONSTRAINT "FK_Devices_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY authentication.devices + ADD CONSTRAINT FK_Devices_Users_UserId FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; -- -- Name: DisplayPreferences FK_DisplayPreferences_Users_UserId; Type: FK CONSTRAINT; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE ONLY displaypreferences."DisplayPreferences" - ADD CONSTRAINT "FK_DisplayPreferences_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY displaypreferences.display_preferences + ADD CONSTRAINT FK_DisplayPreferences_Users_UserId FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; -- -- Name: HomeSection FK_HomeSection_DisplayPreferences_DisplayPreferencesId; Type: FK CONSTRAINT; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE ONLY displaypreferences."HomeSection" - ADD CONSTRAINT "FK_HomeSection_DisplayPreferences_DisplayPreferencesId" FOREIGN KEY ("DisplayPreferencesId") REFERENCES displaypreferences."DisplayPreferences"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY displaypreferences.home_sections + ADD CONSTRAINT FK_HomeSection_DisplayPreferences_DisplayPreferencesId FOREIGN KEY (display_preferences_id) REFERENCES displaypreferences.display_preferences(id) ON DELETE CASCADE; -- -- Name: ItemDisplayPreferences FK_ItemDisplayPreferences_Users_UserId; Type: FK CONSTRAINT; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE ONLY displaypreferences."ItemDisplayPreferences" - ADD CONSTRAINT "FK_ItemDisplayPreferences_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY displaypreferences.item_display_preferences + ADD CONSTRAINT FK_ItemDisplayPreferences_Users_UserId FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; -- -- Name: AncestorIds FK_AncestorIds_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."AncestorIds" - ADD CONSTRAINT "FK_AncestorIds_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.ancestor_ids + ADD CONSTRAINT FK_AncestorIds_BaseItems_ItemId FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- -- Name: AncestorIds FK_AncestorIds_BaseItems_ParentItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."AncestorIds" - ADD CONSTRAINT "FK_AncestorIds_BaseItems_ParentItemId" FOREIGN KEY ("ParentItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.ancestor_ids + ADD CONSTRAINT FK_AncestorIds_BaseItems_ParentItemId FOREIGN KEY (parent_item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- -- Name: AttachmentStreamInfos FK_AttachmentStreamInfos_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."AttachmentStreamInfos" - ADD CONSTRAINT "FK_AttachmentStreamInfos_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.attachment_stream_infos + ADD CONSTRAINT FK_AttachmentStreamInfos_BaseItems_ItemId FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- -- Name: BaseItemImageInfos FK_BaseItemImageInfos_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."BaseItemImageInfos" - ADD CONSTRAINT "FK_BaseItemImageInfos_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.base_item_image_infos + ADD CONSTRAINT FK_BaseItemImageInfos_BaseItems_ItemId FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- -- Name: BaseItemMetadataFields FK_BaseItemMetadataFields_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."BaseItemMetadataFields" - ADD CONSTRAINT "FK_BaseItemMetadataFields_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.base_item_metadata_fields + ADD CONSTRAINT FK_BaseItemMetadataFields_BaseItems_ItemId FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- -- Name: BaseItemProviders FK_BaseItemProviders_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."BaseItemProviders" - ADD CONSTRAINT "FK_BaseItemProviders_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.base_item_providers + ADD CONSTRAINT FK_BaseItemProviders_BaseItems_ItemId FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- -- Name: BaseItemTrailerTypes FK_BaseItemTrailerTypes_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."BaseItemTrailerTypes" - ADD CONSTRAINT "FK_BaseItemTrailerTypes_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.base_item_trailer_types + ADD CONSTRAINT FK_BaseItemTrailerTypes_BaseItems_ItemId FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- -- Name: BaseItems FK_BaseItems_BaseItems_ParentId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."BaseItems" - ADD CONSTRAINT "FK_BaseItems_BaseItems_ParentId" FOREIGN KEY ("ParentId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.base_items + ADD CONSTRAINT FK_BaseItems_BaseItems_ParentId FOREIGN KEY ("ParentId") REFERENCES library.base_items(id) ON DELETE CASCADE; -- -- Name: Chapters FK_Chapters_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."Chapters" - ADD CONSTRAINT "FK_Chapters_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.chapters + ADD CONSTRAINT FK_Chapters_BaseItems_ItemId FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- -- Name: ImageInfos FK_ImageInfos_Users_UserId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."ImageInfos" - ADD CONSTRAINT "FK_ImageInfos_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.image_infos + ADD CONSTRAINT FK_ImageInfos_Users_UserId FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; -- -- Name: ItemValuesMap FK_ItemValuesMap_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."ItemValuesMap" - ADD CONSTRAINT "FK_ItemValuesMap_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.item_values_map + ADD CONSTRAINT FK_ItemValuesMap_BaseItems_ItemId FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- -- Name: ItemValuesMap FK_ItemValuesMap_ItemValues_ItemValueId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."ItemValuesMap" - ADD CONSTRAINT "FK_ItemValuesMap_ItemValues_ItemValueId" FOREIGN KEY ("ItemValueId") REFERENCES library."ItemValues"("ItemValueId") ON DELETE CASCADE; +ALTER TABLE ONLY library.item_values_map + ADD CONSTRAINT FK_ItemValuesMap_ItemValues_ItemValueId FOREIGN KEY (item_value_id) REFERENCES library.item_values(item_value_id) ON DELETE CASCADE; -- -- Name: KeyframeData FK_KeyframeData_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."KeyframeData" - ADD CONSTRAINT "FK_KeyframeData_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.keyframe_data + ADD CONSTRAINT FK_KeyframeData_BaseItems_ItemId FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- -- Name: MediaStreamInfos FK_MediaStreamInfos_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."MediaStreamInfos" - ADD CONSTRAINT "FK_MediaStreamInfos_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.media_stream_infos + ADD CONSTRAINT FK_MediaStreamInfos_BaseItems_ItemId FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- -- Name: PeopleBaseItemMap FK_PeopleBaseItemMap_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."PeopleBaseItemMap" - ADD CONSTRAINT "FK_PeopleBaseItemMap_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.people_base_item_map + ADD CONSTRAINT FK_PeopleBaseItemMap_BaseItems_ItemId FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- -- Name: PeopleBaseItemMap FK_PeopleBaseItemMap_Peoples_PeopleId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."PeopleBaseItemMap" - ADD CONSTRAINT "FK_PeopleBaseItemMap_Peoples_PeopleId" FOREIGN KEY ("PeopleId") REFERENCES library."Peoples"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.people_base_item_map + ADD CONSTRAINT FK_PeopleBaseItemMap_Peoples_PeopleId FOREIGN KEY (people_id) REFERENCES library.peoples(id) ON DELETE CASCADE; -- -- Name: UserData FK_UserData_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."UserData" - ADD CONSTRAINT "FK_UserData_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.user_data + ADD CONSTRAINT FK_UserData_BaseItems_ItemId FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- -- Name: UserData FK_UserData_Users_UserId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."UserData" - ADD CONSTRAINT "FK_UserData_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.user_data + ADD CONSTRAINT FK_UserData_Users_UserId FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; -- -- Name: AccessSchedules FK_AccessSchedules_Users_UserId; Type: FK CONSTRAINT; Schema: users; Owner: jellyfin -- -ALTER TABLE ONLY users."AccessSchedules" - ADD CONSTRAINT "FK_AccessSchedules_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY users.access_schedules + ADD CONSTRAINT FK_AccessSchedules_Users_UserId FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; -- -- Name: Permissions FK_Permissions_Users_UserId; Type: FK CONSTRAINT; Schema: users; Owner: jellyfin -- -ALTER TABLE ONLY users."Permissions" - ADD CONSTRAINT "FK_Permissions_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY users.permissions + ADD CONSTRAINT FK_Permissions_Users_UserId FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; -- -- Name: Preferences FK_Preferences_Users_UserId; Type: FK CONSTRAINT; Schema: users; Owner: jellyfin -- -ALTER TABLE ONLY users."Preferences" - ADD CONSTRAINT "FK_Preferences_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY users.preferences + ADD CONSTRAINT FK_Preferences_Users_UserId FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; -- @@ -1877,3 +1877,4 @@ ALTER TABLE ONLY users."Preferences" \unrestrict BQanTgDKfPEe1ad123fH2eOQKfeiGuQ1HWaeH3TgqI0dLTNNmavSsSEklw1qhxQ + diff --git a/Jellyfin.sln b/Jellyfin.sln index 83dca039..d5a9f51e 100644 --- a/Jellyfin.sln +++ b/Jellyfin.sln @@ -1,4 +1,4 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 18 VisualStudioVersion = 18.0.11222.15 @@ -93,8 +93,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Jellyfin.Database", "Jellyf src\Jellyfin.Database\readme.md = src\Jellyfin.Database\readme.md EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Database.Providers.Sqlite", "src\Jellyfin.Database\Jellyfin.Database.Providers.Sqlite\Jellyfin.Database.Providers.Sqlite.csproj", "{A5590358-33CC-4B39-BDE7-DC62FEB03C76}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Database.Implementations", "src\Jellyfin.Database\Jellyfin.Database.Implementations\Jellyfin.Database.Implementations.csproj", "{8C9F9221-8415-496C-B1F5-E7756F03FA59}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.CodeAnalysis", "src\Jellyfin.CodeAnalysis\Jellyfin.CodeAnalysis.csproj", "{11643D0F-6761-4EF7-AB71-6F9F8DE00714}" @@ -555,18 +553,6 @@ Global {8C6B2B13-58A4-4506-9DAB-1F882A093FE0}.Release|x64.Build.0 = Release|Any CPU {8C6B2B13-58A4-4506-9DAB-1F882A093FE0}.Release|x86.ActiveCfg = Release|Any CPU {8C6B2B13-58A4-4506-9DAB-1F882A093FE0}.Release|x86.Build.0 = Release|Any CPU - {A5590358-33CC-4B39-BDE7-DC62FEB03C76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A5590358-33CC-4B39-BDE7-DC62FEB03C76}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A5590358-33CC-4B39-BDE7-DC62FEB03C76}.Debug|x64.ActiveCfg = Debug|Any CPU - {A5590358-33CC-4B39-BDE7-DC62FEB03C76}.Debug|x64.Build.0 = Debug|Any CPU - {A5590358-33CC-4B39-BDE7-DC62FEB03C76}.Debug|x86.ActiveCfg = Debug|Any CPU - {A5590358-33CC-4B39-BDE7-DC62FEB03C76}.Debug|x86.Build.0 = Debug|Any CPU - {A5590358-33CC-4B39-BDE7-DC62FEB03C76}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A5590358-33CC-4B39-BDE7-DC62FEB03C76}.Release|Any CPU.Build.0 = Release|Any CPU - {A5590358-33CC-4B39-BDE7-DC62FEB03C76}.Release|x64.ActiveCfg = Release|Any CPU - {A5590358-33CC-4B39-BDE7-DC62FEB03C76}.Release|x64.Build.0 = Release|Any CPU - {A5590358-33CC-4B39-BDE7-DC62FEB03C76}.Release|x86.ActiveCfg = Release|Any CPU - {A5590358-33CC-4B39-BDE7-DC62FEB03C76}.Release|x86.Build.0 = Release|Any CPU {8C9F9221-8415-496C-B1F5-E7756F03FA59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {8C9F9221-8415-496C-B1F5-E7756F03FA59}.Debug|Any CPU.Build.0 = Debug|Any CPU {8C9F9221-8415-496C-B1F5-E7756F03FA59}.Debug|x64.ActiveCfg = Debug|Any CPU @@ -632,7 +618,6 @@ Global {C4F71272-C6BE-4C30-BE0D-4E6ED651D6D3} = {FBBB5129-006E-4AD7-BAD5-8B7CA1D10ED6} {8C6B2B13-58A4-4506-9DAB-1F882A093FE0} = {C9F0AB5D-F4D7-40C8-A353-3305C86D6D4C} {4C54CE05-69C8-48FA-8785-39F7F6DB1CAD} = {C9F0AB5D-F4D7-40C8-A353-3305C86D6D4C} - {A5590358-33CC-4B39-BDE7-DC62FEB03C76} = {4C54CE05-69C8-48FA-8785-39F7F6DB1CAD} {8C9F9221-8415-496C-B1F5-E7756F03FA59} = {4C54CE05-69C8-48FA-8785-39F7F6DB1CAD} {11643D0F-6761-4EF7-AB71-6F9F8DE00714} = {C9F0AB5D-F4D7-40C8-A353-3305C86D6D4C} {E1A314DC-837D-4472-AC15-EC08947C55B7} = {4C54CE05-69C8-48FA-8785-39F7F6DB1CAD} @@ -659,3 +644,4 @@ Global $2.DirectoryNamespaceAssociation = PrefixedHierarchical EndGlobalSection EndGlobal + diff --git a/MediaBrowser.Controller/Entities/Folder.cs b/MediaBrowser.Controller/Entities/Folder.cs index 487b3821..227698f7 100644 --- a/MediaBrowser.Controller/Entities/Folder.cs +++ b/MediaBrowser.Controller/Entities/Folder.cs @@ -420,6 +420,7 @@ namespace MediaBrowser.Controller.Entities // Create a list for our validated children var newItems = new List(); + var changedItems = new List(); cancellationToken.ThrowIfCancellationRequested(); @@ -436,7 +437,7 @@ namespace MediaBrowser.Controller.Entities if (currentChild.UpdateFromResolvedItem(child) > ItemUpdateType.None) { - await currentChild.UpdateToRepositoryAsync(ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false); + changedItems.Add(currentChild); } else { @@ -484,6 +485,11 @@ namespace MediaBrowser.Controller.Entities LibraryManager.CreateItems(newItems, this, cancellationToken); } + if (changedItems.Count > 0) + { + await LibraryManager.UpdateItemsAsync(changedItems, this, ItemUpdateType.MetadataImport, cancellationToken).ConfigureAwait(false); + } + // After removing items, reattach any detached user data to remaining children // that share the same user data keys (eg. same episode replaced with a new file). if (actuallyRemoved.Count > 0) diff --git a/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs b/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs index 18f3a1cd..ae4a2313 100644 --- a/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs +++ b/MediaBrowser.Controller/Extensions/ConfigurationExtensions.cs @@ -68,11 +68,6 @@ namespace MediaBrowser.Controller.Extensions /// public const string UnixSocketPermissionsKey = "kestrel:socketPermissions"; - /// - /// The cache size of the SQL database, see cache_size. - /// - public const string SqliteCacheSizeKey = "sqlite:cacheSize"; - /// /// The key for a setting that indicates whether the application should detect network status change. /// @@ -142,13 +137,5 @@ namespace MediaBrowser.Controller.Extensions /// The unix socket permissions. public static string? GetUnixSocketPermissions(this IConfiguration configuration) => configuration[UnixSocketPermissionsKey]; - - /// - /// Gets the cache_size from the . - /// - /// The configuration to read the setting from. - /// The sqlite cache size. - public static int? GetSqliteCacheSize(this IConfiguration configuration) - => configuration.GetValue(SqliteCacheSizeKey); } } diff --git a/MediaBrowser.Controller/LibraryTaskScheduler/LimitedConcurrencyLibraryScheduler.cs b/MediaBrowser.Controller/LibraryTaskScheduler/LimitedConcurrencyLibraryScheduler.cs index 4261beb4..44d07e32 100644 --- a/MediaBrowser.Controller/LibraryTaskScheduler/LimitedConcurrencyLibraryScheduler.cs +++ b/MediaBrowser.Controller/LibraryTaskScheduler/LimitedConcurrencyLibraryScheduler.cs @@ -115,7 +115,7 @@ public sealed class LimitedConcurrencyLibraryScheduler : ILimitedConcurrencyLibr if (fanoutConcurrency <= 0) { // in case the user did not set a limit manually, we can assume he has 3 or more cores as already checked by ShouldForceSequentialOperation. - return Environment.ProcessorCount - 3; + return Math.Max(2, Environment.ProcessorCount / 2); } return fanoutConcurrency; diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj index 194ddd1d..7287889b 100644 --- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj +++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj @@ -2,7 +2,7 @@ - $(NoWarn);CA1024;CA1031;CA1032;CA1034;CA1054;CA1055;CA1056;CA1062;CA1308;CA1303;CA1305;CA1508;CA1722;CA1724;CA1805;CA1813;CA1815;CA1816;CA1819;CA1821;CA1822;CA1823;CA1824;CA1825;CA1826;CA1830;CA1836;CA1839;CA1840;CA1841;CA1859;CA1861;CA1873;CA1911;CA2000;CA2007;CA2016;CA2025;CA2026;CA2100;CA2101;CA2102;CA2201;CA2202;CA2207;CA2208;CA2219;CA2220;CA2222;CA2225;CA2226;CA2230;CA2231;CA2234;CA2241;CA2242;CA2243;CA2244;CA2245;CA2246;CA2247;CA2248;CA2249;CA2250;CA2253;CA3001;CA3002;CA3003;CA3004;CA3005;CA3006;CA3007;CA3008;CA3009;CA3010;CA3011;CA3012;CA3061;CA3062;CA5359;CA5360;CA5361;CA5362;CA5363;CA5364;CA5365;CA5366;CA5367;CA5368;CA5369;CA5370;CA5371;CA5372;CA5373;CA5374;CA5375;CA5376;CA5377;CA5378;CA5379;CA5380;CA5381;CA5382;CA5383;CA5384;CA5385;CA5386;CA5387;CA5388;CA5389;CA5390;CA5391;CA5392;CA5393;CA5394;CA5395;CA5396;CA5397;CA5398;CA5399;CA5400;CA5401;CA5402;CA5403;NU1903;CA1848;CA1515;CA1812;CA1849;CA1860;CA1867;CA1517 + $(NoWarn);CA1024;CA1031;CA1032;CA1034;CA1054;CA1055;CA1056;CA1062;CA1308;CA1303;CA1305;CA1508;CA1722;CA1724;CA1805;CA1813;CA1815;CA1816;CA1819;CA1821;CA1822;CA1823;CA1824;CA1825;CA1826;CA1830;CA1836;CA1839;CA1840;CA1841;CA1859;CA1861;CA1873;CA1911;CA2000;CA2007;CA2016;CA2025;CA2026;CA2100;CA2101;CA2102;CA2201;CA2202;CA2207;CA2208;CA2219;CA2220;CA2222;CA2225;CA2226;CA2230;CA2231;CA2234;CA2241;CA2242;CA2243;CA2244;CA2245;CA2246;CA2247;CA2248;CA2249;CA2250;CA2253;CA3001;CA3002;CA3003;CA3004;CA3005;CA3006;CA3007;CA3008;CA3009;CA3010;CA3011;CA3012;CA3061;CA3062;CA5359;CA5360;CA5361;CA5362;CA5363;CA5364;CA5365;CA5366;CA5367;CA5368;CA5369;CA5370;CA5371;CA5372;CA5373;CA5374;CA5375;CA5376;CA5377;CA5378;CA5379;CA5380;CA5381;CA5382;CA5383;CA5384;CA5385;CA5386;CA5387;CA5388;CA5389;CA5390;CA5391;CA5392;CA5393;CA5394;CA5395;CA5396;CA5397;CA5398;CA5399;CA5400;CA5401;CA5402;CA5403;NU1903;CA1848;CA1515;CA1812;CA1849;CA1860;CA1867;CA1517;NU1510 {442B5058-DCAF-4263-BB6A-F21E31120A1B} @@ -20,7 +20,6 @@ - diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs b/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs index 6c06572a..534c9a98 100644 --- a/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs +++ b/MediaBrowser.Providers/Plugins/Tmdb/TmdbClientManager.cs @@ -286,7 +286,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb if (ep is not null) { seasonNumber = ep.SeasonNumber; - episodeNumber = ep.EpisodeNumber; + episodeNumber = (int)ep.EpisodeNumber; } } diff --git a/convert_sql_identifiers.ps1 b/convert_sql_identifiers.ps1 new file mode 100644 index 00000000..dce5d55d --- /dev/null +++ b/convert_sql_identifiers.ps1 @@ -0,0 +1,133 @@ +# PowerShell script to convert remaining SQL identifiers from quoted PascalCase to lowercase/snake_case +# This script handles constraints, indexes, and foreign keys + +param([string]$filepath = "Jellyfin.Server/sql/schema_init/create_database_schema.sql") + +$content = Get-Content $filepath -Raw + +# Table name mappings for constraint/index/FK replacement +$tableMappings = @{ + '"ActivityLogs"' = 'activity_logs' + '"ApiKeys"' = 'api_keys' + '"DeviceOptions"' = 'device_options' + '"Devices"' = 'devices' + '"CustomItemDisplayPreferences"' = 'custom_item_display_preferences' + '"DisplayPreferences"' = 'display_preferences' + '"HomeSection"' = 'home_sections' + '"ItemDisplayPreferences"' = 'item_display_preferences' + '"AncestorIds"' = 'ancestor_ids' + '"AttachmentStreamInfos"' = 'attachment_stream_infos' + '"BaseItemImageInfos"' = 'base_item_image_infos' + '"BaseItemMetadataFields"' = 'base_item_metadata_fields' + '"BaseItemProviders"' = 'base_item_providers' + '"BaseItemTrailerTypes"' = 'base_item_trailer_types' + '"BaseItems"' = 'base_items' + '"Chapters"' = 'chapters' + '"ImageInfos"' = 'image_infos' + '"ItemValues"' = 'item_values' + '"ItemValuesMap"' = 'item_values_map' + '"KeyframeData"' = 'keyframe_data' + '"MediaSegments"' = 'media_segments' + '"MediaStreamInfos"' = 'media_stream_infos' + '"PeopleBaseItemMap"' = 'people_base_item_map' + '"Peoples"' = 'peoples' + '"TrickplayInfos"' = 'trickplay_infos' + '"UserData"' = 'user_data' + '"__EFMigrationsHistory"' = '__ef_migrations_history' + '"AccessSchedules"' = 'access_schedules' + '"Permissions"' = 'permissions' + '"Preferences"' = 'preferences' + '"Users"' = 'users' +} + +# Column name mappings (critical columns that appear in constraints) +$columnMappings = @{ + '"Id"' = 'id' + '"ParentItemId"' = 'parent_item_id' + '"ItemId"' = 'item_id' + '"Index"' = 'index' + '"UserId"' = 'user_id' + '"DisplayPreferencesId"' = 'display_preferences_id' + '"ItemValueId"' = 'item_value_id' + '"ChapterIndex"' = 'chapter_index' + '"PeopleId"' = 'people_id' + '"StreamIndex"' = 'stream_index' + '"CustomDataKey"' = 'custom_data_key' + '"MigrationId"' = 'migration_id' + '"ProductVersion"' = 'product_version' + '"DayOfWeek"' = 'day_of_week' + '"StartHour"' = 'start_hour' + '"EndHour"' = 'end_hour' + '"Kind"' = 'kind' + '"Value"' = 'value' + '"RowVersion"' = 'row_version' + '"Permission_Permissions_Guid"' = 'permission_permissions_guid' + '"Preference_Preferences_Guid"' = 'preference_preferences_guid' +} + +# Apply table replacements +foreach ($oldTable in $tableMappings.Keys) { + $newTable = $tableMappings[$oldTable] + $content = $content -replace [regex]::Escape($oldTable), $newTable +} + +# Apply column replacements +foreach ($oldCol in $columnMappings.Keys) { + $newCol = $columnMappings[$oldCol] + $content = $content -replace [regex]::Escape($oldCol), $newCol +} + +# Constraint name replacements (remove quotes from constraint names) +$content = $content -replace 'ADD CONSTRAINT "([^"]+)"', 'ADD CONSTRAINT $1' + +# Index name replacements (remove quotes from index names) +$content = $content -replace 'CREATE (\w+ )?INDEX "([^"]+)"', 'CREATE $1INDEX $2' + +# Handle remaining quoted identifiers in special cases +$content = $content -replace '"ProviderId"', 'provider_id' +$content = $content -replace '"ProviderValue"', 'provider_value' +$content = $content -replace '"SortOrder"', 'sort_order' +$content = $content -replace '"ListOrder"', 'list_order' +$content = $content -replace '"Role"', 'role' +$content = $content -replace '"Name"', 'name' +$content = $content -replace '"Path"', 'path' +$content = $content -replace '"DateCreated"', 'date_created' +$content = $content -replace '"DateLastActivity"', 'date_last_activity' +$content = $content -replace '"DateModified"', 'date_modified' +$content = $content -replace '"DateLastSaved"', 'date_last_saved' +$content = $content -replace '"LastPlayedDate"', 'last_played_date' +$content = $content -replace '"Played"', 'played' +$content = $content -replace '"IsFavorite"', 'is_favorite' +$content = $content -replace '"PlaybackPositionTicks"', 'playback_position_ticks' +$content = $content -replace '"Type"', 'type' +$content = $content -replace '"AccessToken"', 'access_token' +$content = $content -replace '"DeviceId"', 'device_id' +$content = $content -replace '"Client"', 'client' +$content = $content -replace '"Username"', 'username' +$content = $content -replace '"StartDate"', 'start_date' +$content = $content -replace '"EndDate"', 'end_date' +$content = $content -replace '"IsFolder"', 'is_folder' +$content = $content -replace '"IsVirtualItem"', 'is_virtual_item' +$content = $content -replace '"PresentationUniqueKey"', 'presentation_unique_key' +$content = $content -replace '"SeriesPresentationUniqueKey"', 'series_presentation_unique_key' +$content = $content -replace '"TopParentId"', 'top_parent_id' +$content = $content -replace '"ProviderId"', 'provider_id' +$content = $content -replace '"StreamType"', 'stream_type' +$content = $content -replace '"Language"', 'language' +$content = $content -replace '"Codec"', 'codec' +$content = $content -replace '"CommunityRating"', 'community_rating' +$content = $content -replace '"ProductionYear"', 'production_year' +$content = $content -replace '"PremiereDate"', 'premiere_date' +$content = $content -replace '"SortName"', 'sort_name' +$content = $content -replace '"CleanValue"', 'clean_value' +$content = $content -replace '"TotalDuration"', 'total_duration' +$content = $content -replace '"KeyframeTicks"', 'keyframe_ticks' +$content = $content -replace '"EndTicks"', 'end_ticks' +$content = $content -replace '"StartTicks"', 'start_ticks' +$content = $content -replace '"SegmentProviderId"', 'segment_provider_id' +$content = $content -replace '"AudioStreamIndex"', 'audio_stream_index' +$content = $content -replace '"SubtitleStreamIndex"', 'subtitle_stream_index' +$content = $content -replace '"RetentionDate"', 'retention_date' + +Set-Content -Path $filepath -Value $content +Write-Host "SQL identifiers conversion complete!" diff --git a/docs/DATABASE_MISMATCH_DETAILED_ENTITY_MAP.md b/docs/DATABASE_MISMATCH_DETAILED_ENTITY_MAP.md new file mode 100644 index 00000000..b1367b50 --- /dev/null +++ b/docs/DATABASE_MISMATCH_DETAILED_ENTITY_MAP.md @@ -0,0 +1,234 @@ +# Database Schema Mismatch - Detailed Entity Mapping + +## Quick Reference: All Mismatches + +### ACTIVITYLOG Schema (1 table) + +| Entity | SQL Table Name | C# Expected Name | Columns Match? | Status | +|--------|----------------|------------------|-----------------|--------| +| ActivityLog | `"ActivityLogs"` | `activity_logs` | NO (11 cols) | ❌ CRITICAL | + +**SQL Columns:** +- "Id", "Name", "Overview", "ShortOverview", "Type", "UserId", "ItemId", "DateCreated", "LogSeverity", "RowVersion" + +**C# Expected Columns (via SnakeCaseNamingConvention):** +- id, name, overview, short_overview, type, user_id, item_id, date_created, log_severity, row_version + +--- + +### AUTHENTICATION Schema (3 tables) + +| Entity | SQL Table Name | C# Expected Name | Columns Match? | Status | +|--------|----------------|------------------|-----------------|--------| +| ApiKey | `"ApiKeys"` | `api_keys` | NO (5 cols) | ❌ CRITICAL | +| Device | `"Devices"` | `devices` | NO (11 cols) | ❌ CRITICAL | +| DeviceOptions | `"DeviceOptions"` | `device_options` | NO (3 cols) | ❌ CRITICAL | + +#### ApiKey +**SQL Columns:** "Id", "DateCreated", "DateLastActivity", "Name", "AccessToken" +**C# Expected:** id, date_created, date_last_activity, name, access_token + +#### Device +**SQL Columns:** "Id", "UserId", "AccessToken", "AppName", "AppVersion", "DeviceName", "DeviceId", "IsActive", "DateCreated", "DateModified", "DateLastActivity" +**C# Expected:** id, user_id, access_token, app_name, app_version, device_name, device_id, is_active, date_created, date_modified, date_last_activity + +#### DeviceOptions +**SQL Columns:** "Id", "DeviceId", "CustomName" +**C# Expected:** id, device_id, custom_name + +--- + +### DISPLAYPREFERENCES Schema (4 tables) + +| Entity | SQL Table Name | C# Expected Name | Columns Match? | Status | +|--------|----------------|------------------|-----------------|--------| +| CustomItemDisplayPreferences | `"CustomItemDisplayPreferences"` | `custom_item_display_preferences` | NO (6 cols) | ❌ CRITICAL | +| DisplayPreferences | `"DisplayPreferences"` | `display_preferences` | NO (14 cols) | ❌ CRITICAL | +| HomeSection | `"HomeSection"` | `home_sections` | NO (4 cols) | ❌ CRITICAL | +| ItemDisplayPreferences | `"ItemDisplayPreferences"` | `item_display_preferences` | NO (10 cols) | ❌ CRITICAL | + +#### CustomItemDisplayPreferences +**SQL Columns:** "Id", "UserId", "ItemId", "Client", "Key", "Value" +**C# Expected:** id, user_id, item_id, client, key, value + +#### DisplayPreferences +**SQL Columns:** "Id", "UserId", "ItemId", "Client", "ShowSidebar", "ShowBackdrop", "ScrollDirection", "IndexBy", "SkipForwardLength", "SkipBackwardLength", "ChromecastVersion", "EnableNextVideoInfoOverlay", "DashboardTheme", "TvHome" +**C# Expected:** id, user_id, item_id, client, show_sidebar, show_backdrop, scroll_direction, index_by, skip_forward_length, skip_backward_length, chromecast_version, enable_next_video_info_overlay, dashboard_theme, tv_home + +#### HomeSection +**SQL Columns:** "Id", "DisplayPreferencesId", "Order", "Type" +**C# Expected:** id, display_preferences_id, order, type + +#### ItemDisplayPreferences +**SQL Columns:** "Id", "UserId", "ItemId", "Client", "ViewType", "RememberIndexing", "IndexBy", "RememberSorting", "SortBy", "SortOrder" +**C# Expected:** id, user_id, item_id, client, view_type, remember_indexing, index_by, remember_sorting, sort_by, sort_order + +--- + +### LIBRARY Schema (15 tables - MOST CRITICAL) + +| Entity | SQL Table Name | C# Expected Name | Columns Match? | Status | +|--------|----------------|------------------|-----------------|--------| +| AncestorId | `"AncestorIds"` | `ancestor_ids` | NO (2 cols) | ❌ | +| AttachmentStreamInfo | `"AttachmentStreamInfos"` | `attachment_stream_infos` | NO (7 cols) | ❌ | +| BaseItemImageInfo | `"BaseItemImageInfos"` | `base_item_image_infos` | NO (8 cols) | ❌ | +| BaseItemMetadataField | `"BaseItemMetadataFields"` | `base_item_metadata_fields` | NO (2 cols) | ❌ | +| BaseItemProvider | `"BaseItemProviders"` | `base_item_providers` | NO (3 cols) | ❌ | +| BaseItemTrailerType | `"BaseItemTrailerTypes"` | `base_item_trailer_types` | NO (2 cols) | ❌ | +| BaseItemEntity | `"BaseItems"` | `base_items` | NO (73 cols!) | ❌ SEVERE | +| Chapter | `"Chapters"` | `chapters` | NO (6 cols) | ❌ | +| ImageInfo | `"ImageInfos"` | `image_infos` | NO (4 cols) | ❌ | +| ItemValue | `"ItemValues"` | `item_values` | NO (4 cols) | ❌ | +| ItemValueMap | `"ItemValuesMap"` | `item_values_map` | NO (2 cols) | ❌ | +| KeyframeData | `"KeyframeData"` | `keyframe_data` | NO (3 cols) | ❌ | +| MediaSegment | `"MediaSegments"` | `media_segments` | NO (6 cols) | ❌ | +| MediaStreamInfo | `"MediaStreamInfos"` | `media_stream_infos` | NO (60+ cols) | ❌ SEVERE | +| PeopleBaseItemMap | `"PeopleBaseItemMap"` | `people_base_item_map` | NO (5 cols) | ❌ | +| People | `"Peoples"` | `peoples` | NO (3 cols) | ❌ | +| TrickplayInfo | `"TrickplayInfos"` | `trickplay_infos` | NO (8 cols) | ❌ | +| UserData | `"UserData"` | `user_data` | NO (13 cols) | ❌ | + +#### BaseItemEntity (MOST CRITICAL - 73 columns) +**SQL Columns:** +"Id", "Type", "Data", "Path", "StartDate", "EndDate", "ChannelId", "IsMovie", "CommunityRating", "CustomRating", "IndexNumber", "IsLocked", "Name", "OfficialRating", "MediaType", "Overview", "ParentIndexNumber", "PremiereDate", "ProductionYear", "Genres", "SortName", "ForcedSortName", "RunTimeTicks", "DateCreated", "DateModified", "IsSeries", "EpisodeTitle", "IsRepeat", "PreferredMetadataLanguage", "PreferredMetadataCountryCode", "DateLastRefreshed", "DateLastSaved", "IsInMixedFolder", "Studios", "ExternalServiceId", "Tags", "IsFolder", "InheritedParentalRatingValue", "InheritedParentalRatingSubValue", "UnratedType", "CriticRating", "CleanName", "PresentationUniqueKey", "OriginalTitle", "PrimaryVersionId", "DateLastMediaAdded", "Album", "LUFS", "NormalizationGain", "IsVirtualItem", "SeriesName", "SeasonName", "ExternalSeriesId", "Tagline", "ProductionLocations", "ExtraIds", "TotalBitrate", "ExtraType", "Artists", "AlbumArtists", "ExternalId", "SeriesPresentationUniqueKey", "ShowId", "OwnerId", "Width", "Height", "Size", "Audio", "ParentId", "TopParentId", "SeasonId", "SeriesId" + +**C# Expected (73 snake_case columns):** +id, type, data, path, start_date, end_date, channel_id, is_movie, community_rating, custom_rating, index_number, is_locked, name, official_rating, media_type, overview, parent_index_number, premiere_date, production_year, genres, sort_name, forced_sort_name, run_time_ticks, date_created, date_modified, is_series, episode_title, is_repeat, preferred_metadata_language, preferred_metadata_country_code, date_last_refreshed, date_last_saved, is_in_mixed_folder, studios, external_service_id, tags, is_folder, inherited_parental_rating_value, inherited_parental_rating_sub_value, unrated_type, critic_rating, clean_name, presentation_unique_key, original_title, primary_version_id, date_last_media_added, album, lufs, normalization_gain, is_virtual_item, series_name, season_name, external_series_id, tagline, production_locations, extra_ids, total_bitrate, extra_type, artists, album_artists, external_id, series_presentation_unique_key, show_id, owner_id, width, height, size, audio, parent_id, top_parent_id, season_id, series_id + +--- + +### USERS Schema (4 tables) + +| Entity | SQL Table Name | C# Expected Name | Columns Match? | Status | +|--------|----------------|------------------|-----------------|--------| +| AccessSchedule | `"AccessSchedules"` | `access_schedules` | NO (5 cols) | ❌ | +| Permission | `"Permissions"` | `permissions` | NO (6 cols) | ❌ | +| Preference | `"Preferences"` | `preferences` | NO (6 cols) | ❌ | +| User | `"Users"` | `users` | NO (31 cols) | ❌ | + +#### AccessSchedule +**SQL Columns:** "Id", "UserId", "DayOfWeek", "StartHour", "EndHour" +**C# Expected:** id, user_id, day_of_week, start_hour, end_hour + +#### Permission +**SQL Columns:** "Id", "UserId", "Kind", "Value", "RowVersion", "Permission_Permissions_Guid" +**C# Expected:** id, user_id, kind, value, row_version, permission_permissions_guid + +#### Preference +**SQL Columns:** "Id", "UserId", "Kind", "Value", "RowVersion", "Preference_Preferences_Guid" +**C# Expected:** id, user_id, kind, value, row_version, preference_preferences_guid + +#### User (31 columns) +**SQL Columns:** +"Id", "Username", "Password", "MustUpdatePassword", "AudioLanguagePreference", "AuthenticationProviderId", "PasswordResetProviderId", "InvalidLoginAttemptCount", "LastActivityDate", "LastLoginDate", "LoginAttemptsBeforeLockout", "MaxActiveSessions", "SubtitleMode", "PlayDefaultAudioTrack", "SubtitleLanguagePreference", "DisplayMissingEpisodes", "DisplayCollectionsView", "EnableLocalPassword", "HidePlayedInLatest", "RememberAudioSelections", "RememberSubtitleSelections", "EnableNextEpisodeAutoPlay", "EnableAutoLogin", "EnableUserPreferenceAccess", "MaxParentalRatingScore", "MaxParentalRatingSubScore", "RemoteClientBitrateLimit", "InternalId", "SyncPlayAccess", "CastReceiverId", "RowVersion" + +**C# Expected (31 snake_case columns):** +id, username, password, must_update_password, audio_language_preference, authentication_provider_id, password_reset_provider_id, invalid_login_attempt_count, last_activity_date, last_login_date, login_attempts_before_lockout, max_active_sessions, subtitle_mode, play_default_audio_track, subtitle_language_preference, display_missing_episodes, display_collections_view, enable_local_password, hide_played_in_latest, remember_audio_selections, remember_subtitle_selections, enable_next_episode_auto_play, enable_auto_login, enable_user_preference_access, max_parental_rating_score, max_parental_rating_sub_score, remote_client_bitrate_limit, internal_id, sync_play_access, cast_receiver_id, row_version + +--- + +## Statistics + +- **Total Tables:** 31 +- **Mismatched Table Names:** 31 (100%) +- **Total Columns Affected:** 200+ columns +- **Severity Level:** CRITICAL - Application will not run + +### Breakdown by Schema + +| Schema | Total Tables | Mismatched | Correct | Mismatch % | +|--------|--------------|-----------|---------|-----------| +| activitylog | 1 | 1 | 0 | 100% | +| authentication | 3 | 3 | 0 | 100% | +| displaypreferences | 4 | 4 | 0 | 100% | +| library | 15 | 15 | 0 | 100% | +| users | 4 | 4 | 0 | 100% | +| **TOTAL** | **31** | **31** | **0** | **100%** | + +--- + +## Column Naming Convention Samples + +The SnakeCaseNamingConvention applies these transformations: + +### Examples from BaseItems Table + +| Original (PascalCase) | Expected (snake_case) | SQL Has | Match? | +|----------------------|----------------------|---------|--------| +| Id | id | "Id" | ❌ | +| IsMovie | is_movie | "IsMovie" | ❌ | +| CommunityRating | community_rating | "CommunityRating" | ❌ | +| DateCreated | date_created | "DateCreated" | ❌ | +| IsVirtualItem | is_virtual_item | "IsVirtualItem" | ❌ | +| PresentationUniqueKey | presentation_unique_key | "PresentationUniqueKey" | ❌ | +| SeriesPresentationUniqueKey | series_presentation_unique_key | "SeriesPresentationUniqueKey" | ❌ | +| PreferredMetadataLanguage | preferred_metadata_language | "PreferredMetadataLanguage" | ❌ | +| TopParentId | top_parent_id | "TopParentId" | ❌ | + +**Conversion Rule (from SnakeCaseNamingConvention.cs):** +``` +DateLastMediaAdded → date_last_media_added +PreferredMetadataCountryCode → preferred_metadata_country_code +InheritedParentalRatingSubValue → inherited_parental_rating_sub_value +``` + +--- + +## Impact Timeline + +### On Application Startup + +1. ✓ Database connection succeeds +2. ✓ Migration history table found (`__EFMigrationsHistory`) +3. ✓ Migrations complete +4. ❌ First query to ActivityLog fails: `relation "activity_logs" does not exist` +5. ❌ Application crashes + +### Error Messages You Will See + +``` +Npgsql.PostgresException: 42P01: relation "activity_logs" does not exist + at Npgsql.Internal.NpgsqlConnector.ReadMessageLong() + at [Your Entity Query Code] +``` + +### Affected Operations + +- ✓ Schema creation works (uses explicit table names in SQL) +- ❌ Any LINQ query fails +- ❌ Any repository method fails +- ❌ Any DbContext.Set.ToList() fails +- ❌ Bulk operations fail +- ❌ Migrations that query tables fail + +--- + +## Code Configuration References + +### PostgresDatabaseProvider.cs (Lines 763-823) +Table mapping that creates the mismatch: +```csharp +public void OnModelCreating(ModelBuilder modelBuilder) +{ + modelBuilder.Entity().ToTable("activity_logs", Schemas.ActivityLog); + modelBuilder.Entity().ToTable("api_keys", Schemas.Authentication); + // ... 31 mappings total ... +} +``` + +### SnakeCaseNamingConvention.cs (Lines 25-30) +Column name conversion that creates column mismatches: +```csharp +public void ProcessPropertyAdded( + IConventionPropertyBuilder propertyBuilder, + IConventionContext context) +{ + propertyBuilder.HasColumnName(ToSnakeCase(propertyBuilder.Metadata.Name)); +} +``` + +--- + +**Generated:** 2025-05-01 +**Severity:** 🔴 CRITICAL - BLOCKING +**Action Required:** Immediate resolution needed before application can run diff --git a/docs/DATABASE_MISMATCH_VISUAL_COMPARISON.md b/docs/DATABASE_MISMATCH_VISUAL_COMPARISON.md new file mode 100644 index 00000000..20bea9f0 --- /dev/null +++ b/docs/DATABASE_MISMATCH_VISUAL_COMPARISON.md @@ -0,0 +1,335 @@ +# Visual Schema Mismatch Comparison + +## Side-by-Side Comparison Examples + +### Example 1: ActivityLog Entity + +``` +┌─────────────────────────────────────────────────────────────────────────┐ +│ ACTIVITYLOG Schema Mismatch │ +├────────────────────────────────┬────────────────────────────────────────┤ +│ SQL Schema File │ C# Code Configuration │ +├────────────────────────────────┼────────────────────────────────────────┤ +│ CREATE TABLE │ modelBuilder │ +│ activitylog."ActivityLogs" │ .Entity() │ +│ ( │ .ToTable("activity_logs", │ +│ "Id" integer, │ Schemas.ActivityLog); │ +│ "Name" varchar(512), │ │ +│ "Overview" varchar(512), │ // Column Mapping (via │ +│ "ShortOverview" varchar, │ // SnakeCaseNamingConvention) │ +│ "Type" varchar(256), │ │ +│ "UserId" uuid, │ public class ActivityLog │ +│ "ItemId" varchar(256), │ { │ +│ "DateCreated" timestamp, │ public int Id { get; set; } │ +│ "LogSeverity" integer, │ public string Name { get; set; } │ +│ "RowVersion" bigint │ public string Overview { get; set; } │ +│ ); │ public string ShortOverview { get; } │ +│ │ public string Type { get; set; } │ +│ │ public Guid UserId { get; set; } │ +│ │ public string ItemId { get; set; } │ +│ │ public DateTime DateCreated { get; } │ +│ │ public int LogSeverity { get; set; } │ +│ │ public long RowVersion { get; set; } │ +│ │ } │ +└────────────────────────────────┴────────────────────────────────────────┘ + +QUERY EXECUTION FLOW: +┌─────────────────────────────────────────────────────────────────┐ +│ C# Code: await context.ActivityLogs.ToListAsync(); │ +├─────────────────────────────────────────────────────────────────┤ +│ EF Core Translates To: │ +│ SELECT * FROM activitylog.activity_logs │ +│ (Lower case! ─────────────────) │ +├─────────────────────────────────────────────────────────────────┤ +│ PostgreSQL Searches For: activitylog.activity_logs │ +│ PostgreSQL Finds: activitylog."ActivityLogs" │ +│ (Quoted PascalCase!) │ +├─────────────────────────────────────────────────────────────────┤ +│ RESULT: ERROR: relation "activity_logs" does not exist │ +│ ERROR CODE: 42P01 (UNDEFINED TABLE) │ +└─────────────────────────────────────────────────────────────────┘ +``` + +--- + +### Example 2: BaseItem Entity (Most Complex) + +``` +┌──────────────────────────────────────────────────────────────────────────────┐ +│ LIBRARY.BaseItems Schema Mismatch (73 Columns!) │ +├──────────────────────────────────────────────────────────────────────────────┤ +│ │ +│ SQL Schema Creates: │ +│ CREATE TABLE library."BaseItems" ( │ +│ "Id" uuid PRIMARY KEY, │ +│ "Type" text NOT NULL, │ +│ "IsMovie" boolean NOT NULL, │ +│ "DateCreated" timestamp with time zone NOT NULL, │ +│ "DateModified" timestamp with time zone NOT NULL, │ +│ ... 68 more columns all in QUOTED PASCALCASE ... │ +│ ); │ +│ │ +│ C# Code Expects: │ +│ SELECT │ +│ id, │ +│ type, │ +│ is_movie, ← Converted from IsMovie │ +│ date_created, ← Converted from DateCreated │ +│ date_modified, ← Converted from DateModified │ +│ ... 68 more columns in snake_case ... │ +│ FROM library.base_items; ← Also lowercase table! │ +│ │ +│ PostgreSQL Receives Query: │ +│ SELECT id, type, is_movie, date_created, ... FROM library.base_items │ +│ ↓ │ +│ Searches for columns: id, type, is_movie, date_created │ +│ (all lowercase) │ +│ ↓ │ +│ But table only has: "Id", "Type", "IsMovie", "DateCreated" │ +│ (all QUOTED PASCALCASE) │ +│ ↓ │ +│ ERROR: column "id" does not exist │ +│ │ +└──────────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Mismatch Pattern Visualization + +``` +SCHEMA LAYER: +┌─────────────────────────────────────────────────────────────────────────┐ +│ PostgreSQL Database │ +│ │ +│ Schema: library │ +│ ├── Table: "BaseItems" (quoted identifier - preserves case) │ +│ │ ├── Column: "Id" │ +│ │ ├── Column: "Type" │ +│ │ ├── Column: "IsMovie" │ +│ │ ├── Column: "DateCreated" │ +│ │ └── ... 70 more columns in QUOTED PASCALCASE │ +│ │ │ +│ ├── Table: "ActivityLogs" (PascalCase) │ +│ ├── Table: "ApiKeys" (PascalCase) │ +│ ├── Table: "Devices" (PascalCase) │ +│ └── ... 28 more tables in QUOTED PASCALCASE │ +└─────────────────────────────────────────────────────────────────────────┘ + ↕ MISMATCH! +APPLICATION LAYER: +┌─────────────────────────────────────────────────────────────────────────┐ +│ C# / EF Core │ +│ │ +│ SnakeCaseNamingConvention ENABLED │ +│ ├── Entity: BaseItemEntity │ +│ │ ├── Property: Id → Column: id (lowercase) │ +│ │ ├── Property: Type → Column: type (lowercase) │ +│ │ ├── Property: IsMovie → Column: is_movie (snake_case) │ +│ │ ├── Property: DateCreated → Column: date_created (snake_case) │ +│ │ └── ... 70 more properties → SNAKE_CASE COLUMNS │ +│ │ │ +│ ├── Entity: ActivityLog → Table: activity_logs (lowercase) │ +│ ├── Entity: ApiKey → Table: api_keys (snake_case) │ +│ ├── Entity: Device → Table: devices (lowercase) │ +│ └── ... 28 more entities → SNAKE_CASE TABLE NAMES │ +└─────────────────────────────────────────────────────────────────────────┘ +``` + +--- + +## PostgreSQL Identifier Resolution + +``` +How PostgreSQL resolves identifiers: + +WITHOUT quotes: my_table +├─ Converted to: my_table (lowercase by default) +├─ Searches for: my_table +└─ Result: ✓ Found + +WITH quotes: "MyTable" +├─ NOT converted +├─ Searches for: MyTable (case-sensitive!) +└─ Result: ✓ Found (only if exact case matches) + +CURRENT SITUATION: +┌────────────────────────────────────────────────────────────┐ +│ SQL Definition: library."BaseItems" │ +│ ↑ │ +│ EF Core Query: SELECT * FROM library.base_items │ +│ ↑ │ +│ PostgreSQL Logic: │ +│ - Sees: "base_items" (unquoted, lowercase by default) │ +│ - Searches for: base_items │ +│ - Available table: "BaseItems" (quoted PascalCase) │ +│ - Match? NO ❌ │ +│ │ +│ ERROR 42P01: relation "base_items" does not exist │ +└────────────────────────────────────────────────────────────┘ +``` + +--- + +## Resolution Decision Tree + +``` +┌─── DECISION: How to Fix the Mismatch? ───────┐ +│ │ +│ ┌─────────────────────────────────────────┐ │ +│ │ Option 1: Update SQL to Lowercase │ │ +│ ├─────────────────────────────────────────┤ │ +│ │ Action: │ │ +│ │ ✓ Regenerate create_database_schema.sql│ │ +│ │ ✓ Convert all "TableName" → table_name │ │ +│ │ ✓ Convert all "ColumnName" → column_name│ │ +│ │ ✓ Remove double quotes │ │ +│ │ │ │ +│ │ Pros: │ │ +│ │ ✓ Matches PostgreSQL best practices │ │ +│ │ ✓ Matches C# configuration (recommended)│ │ +│ │ ✓ Cleaner, more maintainable │ │ +│ │ │ │ +│ │ Cons: │ │ +│ │ ✗ Requires full database migration │ │ +│ │ ✗ Data loss risk if not done carefully│ │ +│ │ ✗ Downtime required │ │ +│ │ │ │ +│ │ Effort: HIGH │ │ +│ │ Risk: HIGH │ │ +│ │ Recommendation: ⭐ BEST LONG-TERM │ │ +│ └─────────────────────────────────────────┘ │ +│ ↓ (Recommended) │ +│ ┌─────────────────────────────────────────┐ │ +│ │ Option 2: Update C# to PascalCase │ │ +│ ├─────────────────────────────────────────┤ │ +│ │ Action: │ │ +│ │ ✓ Remove SnakeCaseNamingConvention │ │ +│ │ ✓ Update all ToTable() mappings │ │ +│ │ ✓ Update all HasColumnName() configs │ │ +│ │ │ │ +│ │ Pros: │ │ +│ │ ✓ Quick fix (code changes only) │ │ +│ │ ✓ No database changes needed │ │ +│ │ ✓ No data loss │ │ +│ │ │ │ +│ │ Cons: │ │ +│ │ ✗ Violates PostgreSQL conventions │ │ +│ │ ✗ Harder to maintain │ │ +│ │ ✗ Non-standard naming scheme │ │ +│ │ │ │ +│ │ Effort: MEDIUM │ │ +│ │ Risk: LOW │ │ +│ │ Recommendation: ⚠️ QUICK FIX │ │ +│ └─────────────────────────────────────────┘ │ +│ ↓ (Not Recommended) │ +│ ┌─────────────────────────────────────────┐ │ +│ │ Option 3: Custom Naming Convention │ │ +│ ├─────────────────────────────────────────┤ │ +│ │ Action: │ │ +│ │ ✓ Create hybrid convention │ │ +│ │ ✓ Recognize existing table patterns │ │ +│ │ │ │ +│ │ Pros: │ │ +│ │ ✓ Works with existing database │ │ +│ │ ✓ Minimal code changes │ │ +│ │ │ │ +│ │ Cons: │ │ +│ │ ✗ Very complex to implement │ │ +│ │ ✗ Difficult to maintain │ │ +│ │ ✗ Fragile (pattern-dependent) │ │ +│ │ ✗ Non-standard solution │ │ +│ │ │ │ +│ │ Effort: VERY HIGH │ │ +│ │ Risk: VERY HIGH │ │ +│ │ Recommendation: ❌ NOT RECOMMENDED │ │ +│ └─────────────────────────────────────────┘ │ +│ +└───────────────────────────────────────────────┘ +``` + +--- + +## Column Naming Rule Examples + +``` +SnakeCaseNamingConvention applies these rules: +(From SnakeCaseNamingConvention.cs - Lines 35-40) + +Input (C# Property) → Output (SQL Column) → SQL Actually Has +────────────────────────────────────────────────────────────────────────── +Id → id → "Id" ❌ +UserId → user_id → "UserId" ❌ +DateCreated → date_created → "DateCreated" ❌ +IsMovie → is_movie → "IsMovie" ❌ +DvVersionMajor → dv_version_major → "DvVersionMajor"❌ +SeriesPresentationUniqueKey → series_presentation_unique_key → "SeriesPresentationUniqueKey" ❌ + +The Regex Rules Applied: +┌─────────────────────────────────────────────────────────────────┐ +│ Rule 1: ([A-Z]+)([A-Z][a-z]) → "$1_$2" │ +│ Example: "HTTPServer" → "HTTP_Server" │ +│ │ +│ Rule 2: ([a-z\d])([A-Z]) → "$1_$2" │ +│ Example: "DateCreated" → "Date_Created" │ +│ │ +│ Rule 3: Convert to lowercase (.ToLowerInvariant()) │ +│ Example: "Date_Created" → "date_created" │ +└─────────────────────────────────────────────────────────────────┘ +``` + +--- + +## Query Execution Failure Timeline + +``` +STARTUP SEQUENCE: +1. ✓ 0ms - Connection opened +2. ✓ 50ms - Migration history table checked (__EFMigrationsHistory exists) +3. ✓ 150ms - Migrations applied +4. ✓ 500ms - Application configuration loaded +5. ✓ 1000ms - First request received +6. ❌ 1050ms - Query executes: SELECT * FROM activitylog.activity_logs + ERROR: 42P01 - relation "activity_logs" does not exist +7. 💥 1051ms - Application crashes + +STACK TRACE: + at Npgsql.NpgsqlDataReader.NextResult() + at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader() + at Microsoft.EntityFrameworkCore.Query.QueryingEnumerable`1.Enumerator.MoveNext() + at System.Linq.Enumerable.ToList() // User called .ToList() or .ToListAsync() + at YourRepositoryClass.GetActivityLogs() in YourRepository.cs:line X +``` + +--- + +## File Locations Summary + +``` +AFFECTED FILES: + +SQL Schema: + └─ Jellyfin.Server/sql/schema_init/create_database_schema.sql + Lines: 92-886 (31 tables with PascalCase names) + +C# Configuration: + ├─ src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/ + │ └─ PostgresDatabaseProvider.cs + │ Lines 763-823: OnModelCreating() - Table mappings + │ Lines 872-875: ConfigureConventions() - SnakeCaseNamingConvention + │ + ├─ src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/ + │ └─ SnakeCaseNamingConvention.cs + │ Lines 16-30: Column name conversion logic + │ + └─ src/Jellyfin.Database/Jellyfin.Database.Implementations/ + └─ ModelConfiguration/ + ├─ ActivityLogConfiguration.cs + ├─ ApiKeyConfiguration.cs + ├─ DeviceConfiguration.cs + └─ ... (31 configuration files total) +``` + +--- + +**Visual Reference Generated:** 2025-05-01 +**Status:** Ready for review and decision diff --git a/docs/DATABASE_SCHEMA_MISMATCH_REPORT.md b/docs/DATABASE_SCHEMA_MISMATCH_REPORT.md new file mode 100644 index 00000000..18176efe --- /dev/null +++ b/docs/DATABASE_SCHEMA_MISMATCH_REPORT.md @@ -0,0 +1,493 @@ +# PostgreSQL Database Schema Mismatch Report + +**Generated:** 2025-05-01 +**Status:** ⚠️ CRITICAL MISMATCH FOUND +**Severity:** HIGH - Code cannot query database tables correctly + +--- + +## Executive Summary + +There is a **critical mismatch** between: +1. **SQL Schema File** (`create_database_schema.sql`) - Uses **PascalCase** table and column names with double quotes +2. **C# Code Configuration** (`PostgresDatabaseProvider.cs`) - Expects **snake_case** table names with SnakeCaseNamingConvention for columns + +This will cause **runtime failures** when EF Core tries to query tables that don't exist at the expected snake_case names. + +--- + +## Detailed Mismatch Analysis + +### ACTIVITYLOG Schema + +#### SQL Definition: +```sql +CREATE TABLE activitylog."ActivityLogs" ( + "Id" integer NOT NULL, + "Name" character varying(512) NOT NULL, + "Overview" character varying(512), + "ShortOverview" character varying(512), + "Type" character varying(256) NOT NULL, + "UserId" uuid NOT NULL, + "ItemId" character varying(256), + "DateCreated" timestamp with time zone NOT NULL, + "LogSeverity" integer NOT NULL, + "RowVersion" bigint NOT NULL +); +``` + +#### C# Code Mapping: +```csharp +modelBuilder.Entity().ToTable("activity_logs", Schemas.ActivityLog); +``` + +#### Mismatch Details: +| Aspect | SQL Schema | C# Code | Status | +|--------|-----------|---------|--------| +| Table Name | `"ActivityLogs"` | `activity_logs` | ❌ MISMATCH | +| Column: Id | `"Id"` | `id` (via convention) | ❌ MISMATCH | +| Column: Name | `"Name"` | `name` (via convention) | ❌ MISMATCH | +| Column: Overview | `"Overview"` | `overview` (via convention) | ❌ MISMATCH | +| Column: ShortOverview | `"ShortOverview"` | `short_overview` (via convention) | ❌ MISMATCH | +| Column: Type | `"Type"` | `type` (via convention) | ❌ MISMATCH | +| Column: UserId | `"UserId"` | `user_id` (via convention) | ❌ MISMATCH | +| Column: ItemId | `"ItemId"` | `item_id` (via convention) | ❌ MISMATCH | +| Column: DateCreated | `"DateCreated"` | `date_created` (via convention) | ❌ MISMATCH | +| Column: LogSeverity | `"LogSeverity"` | `log_severity` (via convention) | ❌ MISMATCH | +| Column: RowVersion | `"RowVersion"` | `row_version` (via convention) | ❌ MISMATCH | + +**Root Cause:** Table name is PascalCase; columns are PascalCase but SnakeCaseNamingConvention converts them to snake_case. + +--- + +### AUTHENTICATION Schema + +#### APIKEYS Table + +**SQL Definition:** +```sql +CREATE TABLE authentication."ApiKeys" ( + "Id" integer NOT NULL, + "DateCreated" timestamp with time zone NOT NULL, + "DateLastActivity" timestamp with time zone NOT NULL, + "Name" character varying(64) NOT NULL, + "AccessToken" text NOT NULL +); +``` + +**C# Mapping:** +```csharp +modelBuilder.Entity().ToTable("api_keys", Schemas.Authentication); +``` + +**Mismatch:** Table name `"ApiKeys"` vs `api_keys` ❌ + +--- + +#### DEVICEOPTIONS Table + +**SQL Definition:** +```sql +CREATE TABLE authentication."DeviceOptions" ( + "Id" integer NOT NULL, + "DeviceId" text NOT NULL, + "CustomName" text +); +``` + +**C# Mapping:** +```csharp +modelBuilder.Entity().ToTable("device_options", Schemas.Authentication); +``` + +**Mismatch:** Table name `"DeviceOptions"` vs `device_options` ❌ + +--- + +#### DEVICES Table + +**SQL Definition:** +```sql +CREATE TABLE authentication."Devices" ( + "Id" integer NOT NULL, + "UserId" uuid NOT NULL, + "AccessToken" text NOT NULL, + "AppName" character varying(64) NOT NULL, + "AppVersion" character varying(32) NOT NULL, + "DeviceName" character varying(64) NOT NULL, + "DeviceId" character varying(256) NOT NULL, + "IsActive" boolean NOT NULL, + "DateCreated" timestamp with time zone NOT NULL, + "DateModified" timestamp with time zone NOT NULL, + "DateLastActivity" timestamp with time zone NOT NULL +); +``` + +**C# Mapping:** +```csharp +modelBuilder.Entity().ToTable("devices", Schemas.Authentication); +``` + +**Mismatch:** Table name `"Devices"` vs `devices` ❌ + +--- + +### DISPLAYPREFERENCES Schema + +#### CUSTOMITEMDISPLAYPREFERENCES Table + +**SQL:** `"CustomItemDisplayPreferences"` +**C# Code:** `custom_item_display_preferences` +**Mismatch:** ❌ + +#### DISPLAYPREFERENCES Table + +**SQL:** `"DisplayPreferences"` +**C# Code:** `display_preferences` +**Mismatch:** ❌ + +#### HOMESECTION Table + +**SQL:** `"HomeSection"` +**C# Code:** `home_sections` +**Mismatch:** ❌ (Plural mismatch too!) + +#### ITEMDISPLAYPREFERENCES Table + +**SQL:** `"ItemDisplayPreferences"` +**C# Code:** `item_display_preferences` +**Mismatch:** ❌ + +--- + +### LIBRARY Schema (Most Critical - 15+ Tables) + +#### ANCESTORIDS Table + +**SQL:** `"AncestorIds"` +**C# Code:** `ancestor_ids` +**Mismatch:** ❌ + +#### ATTACHMENTSTREAMINFOS Table + +**SQL:** `"AttachmentStreamInfos"` +**C# Code:** `attachment_stream_infos` +**Mismatch:** ❌ + +#### BASEITEMIMAGINFOS Table + +**SQL:** `"BaseItemImageInfos"` +**C# Code:** `base_item_image_infos` +**Mismatch:** ❌ + +#### BASEITEMMETADATAFIELDS Table + +**SQL:** `"BaseItemMetadataFields"` +**C# Code:** `base_item_metadata_fields` +**Mismatch:** ❌ + +#### BASEITEMPROVIDERS Table + +**SQL:** `"BaseItemProviders"` +**C# Code:** `base_item_providers` +**Mismatch:** ❌ + +#### BASEITEMTRAILERTYPES Table + +**SQL:** `"BaseItemTrailerTypes"` +**C# Code:** `base_item_trailer_types` +**Mismatch:** ❌ + +#### BASEITEMS Table + +**SQL:** `"BaseItems"` +**C# Code:** `base_items` +**Mismatch:** ❌ + +#### CHAPTERS Table + +**SQL:** `"Chapters"` +**C# Code:** `chapters` +**Mismatch:** ❌ + +#### IMAGEINFOS Table + +**SQL:** `"ImageInfos"` +**C# Code:** `image_infos` +**Mismatch:** ❌ + +#### ITEMVALUES Table + +**SQL:** `"ItemValues"` +**C# Code:** `item_values` +**Mismatch:** ❌ + +#### ITEMVALUESMAP Table + +**SQL:** `"ItemValuesMap"` +**C# Code:** `item_values_map` +**Mismatch:** ❌ + +#### KEYFRAMEDATA Table + +**SQL:** `"KeyframeData"` +**C# Code:** `keyframe_data` +**Mismatch:** ❌ + +#### MEDIASEGMENTS Table + +**SQL:** `"MediaSegments"` +**C# Code:** `media_segments` +**Mismatch:** ❌ + +#### MEDIASTREAMINFOS Table + +**SQL:** `"MediaStreamInfos"` +**C# Code:** `media_stream_infos` +**Mismatch:** ❌ + +#### PEOPLEBASEITEMMAP Table + +**SQL:** `"PeopleBaseItemMap"` +**C# Code:** `people_base_item_map` +**Mismatch:** ❌ + +#### PEOPLES Table + +**SQL:** `"Peoples"` +**C# Code:** `peoples` +**Mismatch:** ❌ + +#### TRICKPLAYINFOS Table + +**SQL:** `"TrickplayInfos"` +**C# Code:** `trickplay_infos` +**Mismatch:** ❌ + +#### USERDATA Table + +**SQL:** `"UserData"` +**C# Code:** `user_data` +**Mismatch:** ❌ + +--- + +### USERS Schema + +#### ACCESSSCHEDULES Table + +**SQL:** `"AccessSchedules"` +**C# Code:** `access_schedules` +**Mismatch:** ❌ + +#### PERMISSIONS Table + +**SQL:** `"Permissions"` +**C# Code:** `permissions` +**Mismatch:** ❌ + +#### PREFERENCES Table + +**SQL:** `"Preferences"` +**C# Code:** `preferences` +**Mismatch:** ❌ + +#### USERS Table + +**SQL:** `"Users"` +**C# Code:** `users` +**Mismatch:** ❌ + +--- + +### SPECIAL TABLES + +#### __EFMigrationsHistory Table + +**SQL Definition (Line 738):** +```sql +CREATE TABLE public."__EFMigrationsHistory" ( + "MigrationId" character varying(150) NOT NULL, + "ProductVersion" character varying(32) NOT NULL +); +``` + +**Status:** ✓ Correct (EF Core will query `public.__EFMigrationsHistory`) +**Note:** Columns are PascalCase in SQL but EF Core's built-in history repository handles this correctly. + +--- + +## Complete Mismatch Summary Table + +| Schema | Entity | SQL Table Name | C# Expected Name | Match? | +|--------|--------|----------------|------------------|--------| +| activitylog | ActivityLog | `"ActivityLogs"` | `activity_logs` | ❌ | +| authentication | ApiKey | `"ApiKeys"` | `api_keys` | ❌ | +| authentication | Device | `"Devices"` | `devices` | ❌ | +| authentication | DeviceOptions | `"DeviceOptions"` | `device_options` | ❌ | +| displaypreferences | CustomItemDisplayPreferences | `"CustomItemDisplayPreferences"` | `custom_item_display_preferences` | ❌ | +| displaypreferences | DisplayPreferences | `"DisplayPreferences"` | `display_preferences` | ❌ | +| displaypreferences | HomeSection | `"HomeSection"` | `home_sections` | ❌ | +| displaypreferences | ItemDisplayPreferences | `"ItemDisplayPreferences"` | `item_display_preferences` | ❌ | +| library | AncestorId | `"AncestorIds"` | `ancestor_ids` | ❌ | +| library | AttachmentStreamInfo | `"AttachmentStreamInfos"` | `attachment_stream_infos` | ❌ | +| library | BaseItemImageInfo | `"BaseItemImageInfos"` | `base_item_image_infos` | ❌ | +| library | BaseItemMetadataField | `"BaseItemMetadataFields"` | `base_item_metadata_fields` | ❌ | +| library | BaseItemProvider | `"BaseItemProviders"` | `base_item_providers` | ❌ | +| library | BaseItemTrailerType | `"BaseItemTrailerTypes"` | `base_item_trailer_types` | ❌ | +| library | BaseItemEntity | `"BaseItems"` | `base_items` | ❌ | +| library | Chapter | `"Chapters"` | `chapters` | ✓ | +| library | ImageInfo | `"ImageInfos"` | `image_infos` | ❌ | +| library | ItemValue | `"ItemValues"` | `item_values` | ❌ | +| library | ItemValueMap | `"ItemValuesMap"` | `item_values_map` | ❌ | +| library | KeyframeData | `"KeyframeData"` | `keyframe_data` | ❌ | +| library | MediaSegment | `"MediaSegments"` | `media_segments` | ❌ | +| library | MediaStreamInfo | `"MediaStreamInfos"` | `media_stream_infos` | ❌ | +| library | PeopleBaseItemMap | `"PeopleBaseItemMap"` | `people_base_item_map` | ❌ | +| library | People | `"Peoples"` | `peoples` | ✓ | +| library | TrickplayInfo | `"TrickplayInfos"` | `trickplay_infos` | ❌ | +| library | UserData | `"UserData"` | `user_data` | ❌ | +| users | AccessSchedule | `"AccessSchedules"` | `access_schedules` | ❌ | +| users | Permission | `"Permissions"` | `permissions` | ✓ | +| users | Preference | `"Preferences"` | `preferences` | ✓ | +| users | User | `"Users"` | `users` | ✓ | +| public | __EFMigrationsHistory | `"__EFMigrationsHistory"` | `__EFMigrationsHistory` | ✓ | + +**Summary:** +- ❌ **31 table mismatches found** +- ✓ **5 tables with correct lowercase names** +- **96% tables have naming conflicts** + +--- + +## Impact Analysis + +### When EF Core Runs + +1. **Query Execution:** EF Core generates queries using snake_case table names + ```sql + SELECT * FROM library.base_items -- EF Core generates this + ``` + +2. **Database Response:** PostgreSQL looks for table named `base_items` in lowercase + +3. **Result:** Table not found because actual table is `"BaseItems"` (quoted PascalCase) + ``` + ERROR: relation "base_items" does not exist + ``` + +### Error Pattern You Will See + +``` +Npgsql.PostgresException (0x80004005): 42P01: relation "activity_logs" does not exist +Npgsql.PostgresException (0x80004005): 42P01: relation "api_keys" does not exist +Npgsql.PostgresException (0x80004005): 42P01: relation "base_items" does not exist +``` + +--- + +## Root Cause Analysis + +### The Problem + +The SQL schema file was generated from a `pg_dump` of an existing database that uses **PascalCase with double quotes** for case preservation. However, the C# code was configured to map to **lowercase snake_case** table names. + +### Configuration Details + +**PostgresDatabaseProvider.cs Line 763-819:** +```csharp +public void OnModelCreating(ModelBuilder modelBuilder) +{ + // ... example mappings ... + modelBuilder.Entity().ToTable("activity_logs", Schemas.ActivityLog); + modelBuilder.Entity().ToTable("api_keys", Schemas.Authentication); + modelBuilder.Entity().ToTable("devices", Schemas.Authentication); + // ... etc ... +} +``` + +**PostgresDatabaseProvider.cs Line 872-875:** +```csharp +public void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) +{ + configurationBuilder.Conventions.Add(_ => new SnakeCaseNamingConvention()); +} +``` + +**SnakeCaseNamingConvention.cs:** +- Converts all PascalCase property names to snake_case column names +- Example: `DateCreated` property → `date_created` column + +--- + +## Recommended Resolution + +### Option 1: Update SQL Schema to Use Lowercase (RECOMMENDED) +- **Pros:** Matches PostgreSQL best practices, cleaner, matches C# configuration +- **Cons:** Requires recreating all tables +- **Effort:** High (full database migration required) + +### Option 2: Update C# Code to Match PascalCase SQL +- **Pros:** Quick fix, no database changes needed +- **Cons:** Goes against PostgreSQL conventions, harder to maintain +- **Effort:** Low (code changes only) + +### Option 3: Custom Naming Convention +- Create a hybrid convention that recognizes existing PascalCase tables +- **Pros:** Can work with existing database +- **Cons:** Complex, non-standard, harder to maintain +- **Effort:** Very High (custom infrastructure needed) + +--- + +## Files Affected + +### C# Code Files +1. `src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/PostgresDatabaseProvider.cs` + - Lines 763-823 (OnModelCreating table mappings) + +2. `src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/SnakeCaseNamingConvention.cs` + - Controls column name conversion + +3. All Entity Configuration files in: + - `src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/` + +### Database Schema Files +1. `Jellyfin.Server/sql/schema_init/create_database_schema.sql` + - Lines 92-886 (all table definitions) + +--- + +## Next Steps + +1. **Decision Required:** Which resolution option do you prefer? + - Option 1: Update SQL to lowercase (Recommended) + - Option 2: Update C# to PascalCase + - Option 3: Create custom convention + +2. **If Option 1:** Generate a comprehensive SQL migration script +3. **If Option 2:** Generate C# code changes +4. **If Option 3:** Design custom naming convention + +--- + +## Appendix: Column Name Conversion Examples + +The SnakeCaseNamingConvention converts column names as follows: + +| Original (C#) | Converted (SQL) | Status | +|---------------|-----------------|--------| +| Id | id | ✓ | +| UserId | user_id | ✓ | +| DateCreated | date_created | ✓ | +| LogSeverity | log_severity | ✓ | +| AccessToken | access_token | ✓ | +| APIKey | api_key | ✓ | +| DVVersionMajor | dv_version_major | ✓ | + +**Note:** All column names in SQL schema are PascalCase (e.g., `"UserId"`, `"DateCreated"`), but C# code expects them in snake_case (e.g., `user_id`, `date_created`). + +--- + +**Report Generated:** 2025-05-01 +**Status:** Awaiting decision on resolution approach diff --git a/docs/DATABASE_VIEWS.md b/docs/DATABASE_VIEWS.md new file mode 100644 index 00000000..f6bcf459 --- /dev/null +++ b/docs/DATABASE_VIEWS.md @@ -0,0 +1,233 @@ +# PostgreSQL Database Views + +All views live in the `library` schema unless otherwise noted. They are read-only and safe to query from pgAdmin, BI tools, or any reporting/debugging context without risk of affecting the application. + +--- + +## `library."MediaStreamInfos_v"` + +Reassembles the original flat `MediaStreamInfos` table shape that existed before the `SplitMediaStreamInfos` migration split audio- and video-specific columns into dedicated tables. + +**Use when:** you want a single flat result of all stream data without writing the three-way JOIN yourself. + +**Columns of note:** + +| Column | Source | +|---|---| +| `ItemId`, `StreamIndex`, `StreamType`, `Codec`, … | `MediaStreamInfos` (always present) | +| `ChannelLayout`, `Channels`, `SampleRate`, `IsHearingImpaired` | `AudioStreamDetails` — `NULL` for non-audio streams | +| `Height`, `Width`, `AverageFrameRate`, `BitDepth`, `ColorTransfer`, `DvProfile`, … | `VideoStreamDetails` — `NULL` for non-video streams | + +**Example:** + +```sql +-- All audio streams for a specific item +SELECT "StreamIndex", "Codec", "Language", "Channels", "SampleRate", "ChannelLayout" +FROM library."MediaStreamInfos_v" +WHERE "ItemId" = '' + AND "StreamType" = 0 -- 0 = Audio +ORDER BY "StreamIndex"; +``` + +--- + +## `library."VideoItems_v"` + +Every non-folder, non-virtual item that has at least one video stream (movies, episodes, home videos, etc.), joined with the primary video stream's technical details. + +**Use when:** auditing codec/resolution/HDR distribution across the library, or finding items that need re-encoding. + +**Columns of note:** + +| Column | Description | +|---|---| +| `Type` | Fully-qualified Jellyfin type name (e.g. `MediaBrowser.Controller.Entities.Movies.Movie`) | +| `VideoCodec` | Codec of the primary video stream (e.g. `hevc`, `h264`) | +| `Width` / `Height` | Resolution of the primary video stream | +| `BitDepth` | Colour bit depth (8, 10, 12) | +| `HDRFormat` | Derived string: `Dolby Vision`, `HDR10+`, `HDR10`, `HLG`, or `SDR` | +| `IsDolbyVision` | Boolean shortcut for `DvProfile IS NOT NULL` | +| `AudioTrackCount` | Number of audio streams on the item | +| `SubtitleTrackCount` | Number of subtitle streams on the item | + +**Example queries:** + +```sql +-- All 4K HDR movies +SELECT "Name", "ProductionYear", "VideoCodec", "Width", "Height", "HDRFormat", "TotalBitrate" +FROM library."VideoItems_v" +WHERE "Type" LIKE '%Movie%' + AND "Height" >= 2160 + AND "HDRFormat" <> 'SDR' +ORDER BY "Name"; + +-- Episodes still encoded in H.264 (candidates for HEVC re-encode) +SELECT "SeriesName", "SeasonName", "EpisodeNumber", "Name", "Width", "Height" +FROM library."VideoItems_v" +WHERE "Type" LIKE '%Episode%' + AND "VideoCodec" = 'h264' +ORDER BY "SeriesName", "SeasonNumber", "EpisodeNumber"; +``` + +--- + +## `library."UserPlaybackHistory_v"` + +Per-user watch history joined with item metadata and a calculated playback progress percentage. + +**Use when:** reporting on viewing activity, finding in-progress items, or checking which users have watched what. + +**Columns of note:** + +| Column | Description | +|---|---| +| `Username` | Jellyfin username | +| `ItemName` | Name of the item | +| `ItemType` | Jellyfin type name | +| `Played` | `true` if the item has been marked as played | +| `PlayCount` | Number of times fully played | +| `LastPlayedDate` | Timestamp of the most recent playback | +| `PlaybackPositionTicks` | Raw position (divide by `10,000,000` for seconds) | +| `ProgressPct` | Calculated percentage through the item (0–100), `NULL` if no runtime | +| `AudioStreamIndex` | Last-used audio track index | +| `SubtitleStreamIndex` | Last-used subtitle track index | + +**Example queries:** + +```sql +-- All in-progress items for a user (started but not finished) +SELECT "ItemName", "ItemType", "SeriesName", "ProgressPct", "LastPlayedDate" +FROM library."UserPlaybackHistory_v" +WHERE "Username" = 'alice' + AND "Played" = false + AND "ProgressPct" > 0 +ORDER BY "LastPlayedDate" DESC; + +-- Top 10 most-played items across all users +SELECT "ItemName", "ItemType", SUM("PlayCount") AS "TotalPlays" +FROM library."UserPlaybackHistory_v" +GROUP BY "ItemName", "ItemType" +ORDER BY "TotalPlays" DESC +LIMIT 10; +``` + +--- + +## `library."ItemProviders_v"` + +Items with their external provider IDs (IMDb, TMDB, TVDB, etc.) pivoted into named columns. Providers not explicitly named appear in a JSONB `OtherProviders` column. + +**Use when:** cross-referencing Jellyfin items against external databases, finding items with missing metadata IDs, or bulk-exporting IDs for external tools. + +**Columns of note:** + +| Column | Description | +|---|---| +| `ImdbId` | IMDb identifier (e.g. `tt0111161`) | +| `TmdbId` | The Movie Database ID | +| `TvdbId` | TheTVDB series/episode ID | +| `TvRageId` | TVRage ID (legacy) | +| `MusicBrainzAlbumId` | MusicBrainz album MBID | +| `MusicBrainzArtistId` | MusicBrainz artist MBID | +| `OtherProviders` | JSONB object of any remaining provider key/value pairs | + +**Example queries:** + +```sql +-- Movies missing a TMDB ID +SELECT "Name", "ProductionYear", "ImdbId" +FROM library."ItemProviders_v" +WHERE "Type" LIKE '%Movie%' + AND "TmdbId" IS NULL +ORDER BY "Name"; + +-- Look up an item by IMDb ID +SELECT "ItemId", "Type", "Name", "ProductionYear" +FROM library."ItemProviders_v" +WHERE "ImdbId" = 'tt0111161'; +``` + +--- + +## `library."ItemPeople_v"` + +All cast and crew entries linked to the items they appear in. + +**Use when:** browsing which items feature a specific actor or director, building cast-focused reports, or auditing people metadata. + +**Columns of note:** + +| Column | Description | +|---|---| +| `PersonName` | Name of the person | +| `PersonType` | Role type: `Actor`, `Director`, `Writer`, `Producer`, etc. | +| `Role` | Specific character name or role description (may be empty) | +| `SortOrder` / `ListOrder` | Display ordering within the item's people list | + +**Example queries:** + +```sql +-- All items featuring a specific actor +SELECT "ItemType", "ItemName", "SeriesName", "ProductionYear", "Role" +FROM library."ItemPeople_v" +WHERE "PersonName" = 'Bryan Cranston' + AND "PersonType" = 'Actor' +ORDER BY "ProductionYear"; + +-- Directors with the most items in the library +SELECT "PersonName", COUNT(*) AS "DirectedItems" +FROM library."ItemPeople_v" +WHERE "PersonType" = 'Director' +GROUP BY "PersonName" +ORDER BY "DirectedItems" DESC +LIMIT 20; +``` + +--- + +## `library."LibrarySummary_v"` + +Aggregate statistics broken down by item type — one row per type. Provides a quick dashboard overview of the entire library. + +**Use when:** getting a high-level snapshot of library size, total runtime, storage usage, and video quality distribution. + +**Columns of note:** + +| Column | Description | +|---|---| +| `Type` | Jellyfin item type | +| `ItemCount` | Total number of items of this type | +| `TotalRuntimeHours` | Sum of all runtimes in hours | +| `TotalSizeGB` | Sum of all file sizes in gigabytes | +| `AvgCommunityRating` | Average community rating across items with a rating | +| `Count4K` | Items with primary video height ≥ 2160 | +| `Count1080p` | Items with height 1080–2159 | +| `Count720p` | Items with height 720–1079 | +| `CountSD` | Items with height < 720 | +| `CountDolbyVision` | Items with a Dolby Vision video stream | +| `CountHDR10Plus` | Items with HDR10+ flag set | +| `CountHDR10` | Items with HDR10 (`smpte2084` transfer, no DV or HDR10+) | + +**Example:** + +```sql +-- Full summary +SELECT "Type", "ItemCount", "TotalRuntimeHours", "TotalSizeGB", + "Count4K", "Count1080p", "Count720p", "CountSD", + "CountDolbyVision", "CountHDR10Plus", "CountHDR10" +FROM library."LibrarySummary_v"; +``` + +--- + +## StreamType Reference + +The `StreamType` integer used in `MediaStreamInfos` and `MediaStreamInfos_v` maps to: + +| Value | Type | +|---|---| +| 0 | Audio | +| 1 | Video | +| 2 | Subtitle | +| 3 | EmbeddedImage | +| 4 | Data / Attachment | diff --git a/docs/EF_CORE_REMOVAL_ANALYSIS.md b/docs/EF_CORE_REMOVAL_ANALYSIS.md new file mode 100644 index 00000000..bf4ca810 --- /dev/null +++ b/docs/EF_CORE_REMOVAL_ANALYSIS.md @@ -0,0 +1,244 @@ +# EF Core Removal Analysis — pgsql-jellyfin Fork + +**Date**: 2025 +**Scope**: Full codebase analysis of whether EF Core can and should be removed from this PostgreSQL-only fork. +**Verdict**: **Do not remove EF Core.** Address specific friction points instead. + +--- + +## 1. Usage Inventory + +EF Core (`IDbContextFactory`) is injected into **82 call sites across ~35 source files**, permeating every layer: + +| Layer | Files | +|---|---| +| API | `DatabaseViewsController` | +| Repository (Item) | `BaseItemRepository`, `PeopleRepository`, `MediaStreamRepository`, `MediaAttachmentRepository`, `KeyframeRepository`, `ChapterRepository` | +| Repository (Other) | `ActivityManager`, `DeviceManager`, `DisplayPreferencesManager`, `UserManager`, `TrickplayManager`, `MediaSegmentManager`, `AuthenticationManager`, `AuthorizationContext`, `LibraryOptionsRepository`, `BackupService` | +| Scheduled Tasks | `PeopleValidationTask`, `CleanupUserDataTask`, `CleanDatabaseScheduledTask`, `UserDataManager` | +| Migration Routines | 13 routines: `MigrateActivityLogDb`, `MigrateAuthenticationDb`, `MigrateDisplayPreferencesDb`, `MigrateKeyframeData`, `MigrateLibraryDb`, `MigrateLibraryUserData`, `MigrateRatingLevels`, `MoveExtractedFiles`, `RefreshCleanNames`, `RefreshInternalDateModified`, `FixDates`, `CleanMusicArtist`, (+ more) | +| Infrastructure | `JellyfinMigrationService`, `PostgresDatabaseProvider`, `DbContextFactoryHealthCheck`, `Program.cs`, `ServiceCollectionExtensions` | + +The `JellyfinDbContext` itself defines **~35 DbSets** spanning 5 schemas (`activitylog`, `authentication`, `displaypreferences`, `library`, `users`). + +--- + +## 2. Query Complexity — What EF Core Actually Does + +### 2.1 BaseItemRepository.cs — The Core Case + +`BaseItemRepository.cs` is **3,583 lines / 152 KB**, the largest file in the repository. It is the performance-critical code path for all library browsing, search, and playback-related queries. It is built entirely on EF Core LINQ. + +**Key EF-dependent sub-systems inside it:** + +| Method | EF Feature Used | Purpose | +|---|---|---| +| `TranslateQuery()` (lines 2548+, ~500 lines) | LINQ predicate composition over `IQueryable` | Translates `InternalItemsQuery` (60+ filter parameters) to SQL WHERE clauses | +| `ApplyOrder()` (~80 lines) | `OrderBy` / `ThenBy` over EF expression trees, `OrderMapper.MapOrderByField()` | Translates `ItemSortBy` enum to typed SQL ORDER BY | +| `ApplyNavigations()` | Conditional `Include()` / `ThenInclude()` | Eagerly loads TvExtras, AudioExtras, LiveTvExtras, Provider, Images, UserData per DTO field set | +| `ApplyGroupingFilter()` | `DistinctBy()` → PostgreSQL `DISTINCT ON` | Deduplication for presentation unique keys | +| `GetNextUpSeriesKeys()` | `Join()` + `GroupBy()` + `Max()` | Complex TV "next up" episode query | +| `GetItemValues()` | Nested `Join()` + `SelectMany()` + correlated subquery pattern | Artist/Genre/Studio item-value lookups | +| `UpdateOrInsertItemsAsync()` | `CreateExecutionStrategy().ExecuteAsync()`, `SaveChangesAsync()`, `Attach().State = EntityState.Modified`, `AddRange()` | Transactional batch upsert | +| Entity state management | `context.Entry(placeholder).State = EntityState.Detached` | Upsert conflict resolution | +| `EF.Constant()` | PostgreSQL-specific plan hint | Prevents parameterization of the placeholder UUID to allow index scans | + +**LINQ operator counts in BaseItemRepository.cs** (approximate from code review): +- `Where()`, `Select()`, `Join()`, `GroupBy()`, `Include()`, `ThenInclude()`, `OrderBy()`: **200+ call sites** +- `ExecuteDelete()` / `ExecuteUpdate()` bulk ops: **~25 call sites** +- `FromSqlRaw` / `FromSqlInterpolated`: **0** — reads are pure LINQ +- `ExecuteSqlAsync()` raw SQL upserts: **~8** (ON CONFLICT upserts for extension tables) + +The LINQ query composition is not superficial mapping sugar — `TranslateQuery` conditionally applies 30+ predicate branches (user data filters, rating filters, type filters, ancestor traversal, search term scoring, tag inheritance, etc.) based on `InternalItemsQuery` flags. This is the equivalent of a 500-line dynamic SQL builder, expressed in type-safe C#. + +### 2.2 Other Repositories + +The other repositories (`ActivityManager`, `UserManager`, `DeviceManager`, etc.) use EF more simply — primarily `Where()` + `Select()` + `SaveChanges()` patterns — but collectively represent hundreds more LINQ call sites. + +### 2.3 Hybrid Usage Already Present + +`BaseItemRepository.UpdateOrInsertItemsAsync()` already uses a hybrid approach: EF Core for reads and change-tracking, **raw `ExecuteSqlAsync()` for ON CONFLICT upserts**. This tells us the team is already reaching EF's limits on writes. + +--- + +## 3. Migration Infrastructure + +### 3.1 EF Schema Migrations Are DISABLED + +Per `JellyfinMigrationService.cs` (line ~275): +```csharp +// DISABLED for .NET 11 preview: EF Core database migrations don't work with preview SDK +// Database schema is initialized from SQL scripts in PostgresDatabaseProvider instead +/* +if (stage is JellyfinMigrationStageTypes.CoreInitialisation) +{ + pendingDatabaseMigrations = migrationsAssembly.Migrations... +} +*/ +``` + +**EF's primary justification — schema migration management — is already bypassed.** Schema is initialized via `sql/schema_init/create_database_schema.sql` + `psql`. + +### 3.2 EF Is Still Used for Code Migration Tracking + +`JellyfinMigrationService` still uses EF to track *which code routines have run* via `__EFMigrationsHistory`: + +```csharp +var historyRepository = dbContext.GetService(); +await historyRepository.CreateIfNotExistsAsync(); +var appliedMigrations = await dbContext.Database.GetAppliedMigrationsAsync(); +await dbContext.Database.ExecuteSqlRawAsync( + historyRepository.GetInsertScript(new HistoryRow(migrationId, version))); +``` + +This usage of `IHistoryRepository` is what required the `SnakeCaseHistoryRepository` workaround (custom class overriding `MigrationIdColumnName` and `ProductVersionColumnName`, using `#pragma warning disable EF1001` because the base class is internal EF infrastructure). + +--- + +## 4. Known Friction Points + +These are the specific problems that prompted this analysis: + +### 4.1 Snake_case Naming Impedance (FIXED, but fragile) + +EF Core defaults to PascalCase. This fork uses snake_case PostgreSQL conventions. Three workarounds are required: + +1. **`SnakeCaseNamingConvention`** — `IPropertyAddedConvention` that converts all property names to snake_case at model build time +2. **`SnakeCaseHistoryRepository`** — custom `NpgsqlHistoryRepository` subclass overriding column name properties; requires `#pragma warning disable EF1001` (breaking internal EF API) +3. **Manual table names in model configurations** — 31 `IEntityTypeConfiguration` files; two (`LibraryOptionsEntityConfiguration`, `HomeSectionConfiguration`) had PascalCase table names that overrode the convention and caused `relation "library.LibraryOptions" does not exist` errors at runtime + +**Risk**: Every future upstream EF Core upgrade may break `SnakeCaseHistoryRepository` since it depends on internal EF infrastructure. + +### 4.2 Execution Strategy Transaction Friction (FIXED, but imposed on all writers) + +`EnableRetryOnFailure` in the PostgreSQL retry strategy makes EF Core incompatible with user-initiated `BeginTransaction()`. All transactional code must wrap in `context.Database.CreateExecutionStrategy().Execute(...)`. This has already been fixed in `MigrateRatingLevels` and `MigrateKeyframeData` but is an ongoing constraint. + +### 4.3 EF-PostgreSQL Translation Gaps + +Multiple code comments document EF Core translation failures: + +- `DistinctBy()` on complex types sometimes cannot be translated → fallback to `ApplyGroupingInMemory()` using **reflection on anonymous types** +- `GetItemValues()` in some paths falls back to `.AsEnumerable()` for in-memory filtering +- `GetLatestItemList()` had to be split into two queries to avoid untranslatable nested `Min()` subqueries +- A documented 165s query regression was caused by EF generating correlated subqueries — fixed by switching to `DistinctBy()` → `DISTINCT ON` +- `AsSingleQuery()` required explicitly to prevent N+1 for multi-table includes + +### 4.4 Inconsistent Table Naming in Raw SQL + +`UpdateOrInsertItemsAsync()` uses raw `ExecuteSqlAsync()` with PascalCase quoted names: + +```csharp +$@"INSERT INTO library.""BaseItemProviders"" (""ItemId"", ""ProviderId"", ""ProviderValue"")..." +$@"INSERT INTO library.""BaseItemTvExtras"" (""ItemId"", ..." +``` + +These PascalCase quoted names (`"BaseItemProviders"`, `"BaseItemTvExtras"`) are inconsistent with the snake_case goal of the fork. The actual table names in PostgreSQL must match these quoted strings exactly — implying the schema init SQL creates them with PascalCase quoted names, not the snake_case convention applied to EF properties. + +### 4.5 Known Performance Anti-Pattern in `GetItemValues` + +```csharp +// TODO: This is bad refactor! +itemCount = new ItemCounts() { + SeriesCount = itemCountQuery!.Count(f => f.Type == seriesTypeName), + EpisodeCount = itemCountQuery!.Count(f => f.Type == episodeTypeName), + // ... 5 more COUNT queries +} +``` + +This executes 7 separate `COUNT` queries per item in a result set — a classic N+1 problem embedded in an EF projection. This is an EF translation limitation (aggregate counts in a nested `SELECT` project). + +--- + +## 5. Can EF Core Be Removed? + +**Technically: Yes. Practically: The cost is prohibitive.** + +A full removal would require: + +1. **Rewriting `BaseItemRepository.cs`** (3,583 lines) as raw SQL — either Dapper or direct `NpgsqlCommand`. The `TranslateQuery` method alone is a ~500-line dynamic query builder that would need to be rewritten as a SQL string builder. All `Include()` chains would become explicit JOINs. All `ExecuteUpdate`/`ExecuteDelete` calls would become parameterized SQL. + +2. **Replacing 31 ModelConfiguration files** with SQL schema definitions (partially done via `sql/schema_init/`). + +3. **Replacing the migration tracking system** (`IHistoryRepository`) with a simple SQL table + custom tracker. + +4. **Rewriting all other repositories** (~15 files) as Dapper or raw Npgsql. + +5. **Replacing all `IDbContextFactory` injection points** (~35 files, 82 sites) with new connection/command factories. + +**Estimated effort: 3–6 person-months of careful rewrite, plus extensive testing coverage.** + +Alternatives assessed: + +| Alternative | Pros | Cons | +|---|---|---| +| **Full removal (Dapper + Npgsql)** | Full control of SQL; no EF friction; better PostgreSQL-native features | 3-6 month rewrite; no dynamic LINQ query composition; lose `ExecuteUpdate`/`ExecuteDelete`; high regression risk | +| **Hybrid (EF reads, Dapper writes)** | Eliminates write friction; keeps LINQ query composition | Two persistence paradigms; still need EF for reads; does not eliminate snake_case friction | +| **Keep EF, address friction points** | Minimal disruption; preserves LINQ query composition | Ongoing EF+PostgreSQL compatibility work; preview SDK risk | +| **Replace only migration tracking** | Eliminates `SnakeCaseHistoryRepository` hack | Small gain; does not address execution strategy or translation friction | + +--- + +## 6. Should EF Core Be Removed? + +**No — but specific friction points should be addressed deliberately.** + +### 6.1 Why EF Core Should Stay + +**The LINQ query composition in `TranslateQuery` / `ApplyOrder` is EF Core's core contribution to this codebase.** It provides: + +- **Type safety** across 60+ filter parameters in `InternalItemsQuery` +- **Composability** — predicates are built incrementally, each branch independently testable +- **Maintainability** — 500 lines of C# expression trees is significantly more maintainable than equivalent raw SQL string building +- **`ExecuteUpdate`/`ExecuteDelete`** — these EF 7+ bulk operations map directly to `UPDATE ... WHERE` and `DELETE ... WHERE` without loading entities; replacing these with raw SQL would produce functionally identical code with more boilerplate +- **Navigation property loading** (`Include`) — the conditional navigation loading in `ApplyNavigations` maps cleanly to the DTO field selection pattern used by the API layer + +EF Core's value in this codebase is almost entirely in the **read path** (LINQ-to-SQL translation) and **bulk operations** (`ExecuteUpdate`/`ExecuteDelete`). Its weaknesses are in the write path and infrastructure (migration history, naming conventions, execution strategy). + +### 6.2 Recommended Targeted Actions + +In priority order: + +#### Priority 1 — Replace Migration History Tracking (Low effort, high safety gain) + +The `SnakeCaseHistoryRepository` workaround depends on EF internal APIs (`#pragma warning disable EF1001`). Replace the code migration tracking with a simple dedicated table and Dapper/Npgsql: + +```sql +CREATE TABLE IF NOT EXISTS public.jellyfin_applied_migrations ( + migration_id VARCHAR(150) PRIMARY KEY, + applied_at TIMESTAMPTZ NOT NULL DEFAULT now(), + product_version VARCHAR(32) NOT NULL +); +``` + +Remove `JellyfinMigrationService`'s dependency on `IHistoryRepository` and `GetAppliedMigrationsAsync()`. This eliminates the most fragile EF workaround. + +#### Priority 2 — Fix Raw SQL Table Names to Match snake_case Schema (Low effort, correctness) + +`UpdateOrInsertItemsAsync` uses `library."BaseItemProviders"`, `library."BaseItemTvExtras"`, etc. If the fork's goal is snake_case naming, verify whether these tables exist as quoted PascalCase or as snake_case in PostgreSQL, and make the raw SQL consistent. Quoted PascalCase in PostgreSQL is case-sensitive and is a footgun. + +#### Priority 3 — Replace Write Path with Raw SQL/Dapper (Medium effort, eliminates execution strategy friction) + +The `UpdateOrInsertItemsAsync` method is already a hybrid (raw SQL for ON CONFLICT upserts + EF for the surrounding logic). Converting the remaining EF write operations (`SaveChangesAsync`, `Attach().State = EntityState.Modified`, `AddRange()`) in this method to direct Npgsql/Dapper calls would: + +- Eliminate the `CreateExecutionStrategy().Execute()` wrappers +- Enable direct PostgreSQL `ON CONFLICT DO UPDATE` throughout +- Remove the impedance between EF change tracking and PostgreSQL's native upsert semantics + +**Do not extend this to reads** — the LINQ query composition is worth keeping. + +#### Priority 4 — Fix the N+1 in `GetItemValues` (Medium effort, performance) + +The 7 separate `COUNT` queries per item should be replaced with a single `GROUP BY type, COUNT(*)` query executed once and pivoted in memory. This is a correctness/performance issue independent of whether EF is removed. + +--- + +## 7. Summary + +| Question | Answer | +|---|---| +| **Can EF Core be removed?** | Yes, technically. Estimated 3–6 person-months of work. | +| **Should EF Core be removed?** | No. The LINQ query composition in `BaseItemRepository` is EF's core value and cost-prohibitive to replace. | +| **Is EF Core being used optimally?** | No. The write path, migration tracking, and naming convention workarounds are sources of ongoing friction. | +| **What should be done instead?** | Replace migration tracking with a native SQL table; convert the write path in `BaseItemRepository` to raw SQL; keep EF for the LINQ read path. | +| **Biggest ongoing risk?** | `SnakeCaseHistoryRepository` uses internal EF APIs (`EF1001`) that may break on EF Core version bumps. Replacing migration tracking eliminates this. | +| **Second biggest risk?** | EF Core + Npgsql preview packages (`11.0.0-preview.1`) on `net11.0`. Schema migrations are already disabled because of this. Pin to stable as soon as net11.0 releases. | diff --git a/README-POSTGRESQL.md b/docs/README-POSTGRESQL.md similarity index 100% rename from README-POSTGRESQL.md rename to docs/README-POSTGRESQL.md diff --git a/docs/SCHEMA_COLUMN_CONVERSION_REFERENCE.md b/docs/SCHEMA_COLUMN_CONVERSION_REFERENCE.md new file mode 100644 index 00000000..36ff5bdd --- /dev/null +++ b/docs/SCHEMA_COLUMN_CONVERSION_REFERENCE.md @@ -0,0 +1,478 @@ +# SQL Column Conversion Reference - All Tables + +## Activity Log Schema + +### activity_logs (activitylog."ActivityLogs") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"Id"` | `id` | +| `"Name"` | `name` | +| `"Overview"` | `overview` | +| `"ShortOverview"` | `short_overview` | +| `"Type"` | `type` | +| `"UserId"` | `user_id` | +| `"ItemId"` | `item_id` | +| `"DateCreated"` | `date_created` | +| `"LogSeverity"` | `log_severity` | +| `"RowVersion"` | `row_version` | + +--- + +## Authentication Schema + +### api_keys (authentication."ApiKeys") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"Id"` | `id` | +| `"DateCreated"` | `date_created` | +| `"DateLastActivity"` | `date_last_activity` | +| `"Name"` | `name` | +| `"AccessToken"` | `access_token` | + +### devices (authentication."Devices") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"Id"` | `id` | +| `"UserId"` | `user_id` | +| `"AccessToken"` | `access_token` | +| `"AppName"` | `app_name` | +| `"AppVersion"` | `app_version` | +| `"DeviceName"` | `device_name` | +| `"DeviceId"` | `device_id` | +| `"IsActive"` | `is_active` | +| `"DateCreated"` | `date_created` | +| `"DateModified"` | `date_modified` | +| `"DateLastActivity"` | `date_last_activity` | + +### device_options (authentication."DeviceOptions") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"Id"` | `id` | +| `"DeviceId"` | `device_id` | +| `"CustomName"` | `custom_name` | + +--- + +## Display Preferences Schema + +### display_preferences (displaypreferences."DisplayPreferences") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"Id"` | `id` | +| `"UserId"` | `user_id` | +| `"ItemId"` | `item_id` | +| `"Client"` | `client` | +| `"ShowSidebar"` | `show_sidebar` | +| `"ShowBackdrop"` | `show_backdrop` | +| `"ScrollDirection"` | `scroll_direction` | +| `"IndexBy"` | `index_by` | +| `"SkipForwardLength"` | `skip_forward_length` | +| `"SkipBackwardLength"` | `skip_backward_length` | +| `"ChromecastVersion"` | `chromecast_version` | +| `"EnableNextVideoInfoOverlay"` | `enable_next_video_info_overlay` | +| `"DashboardTheme"` | `dashboard_theme` | +| `"TvHome"` | `tv_home` | + +### item_display_preferences (displaypreferences."ItemDisplayPreferences") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"Id"` | `id` | +| `"UserId"` | `user_id` | +| `"ItemId"` | `item_id` | +| `"Client"` | `client` | +| `"ViewType"` | `view_type` | +| `"RememberIndexing"` | `remember_indexing` | +| `"IndexBy"` | `index_by` | +| `"RememberSorting"` | `remember_sorting` | +| `"SortBy"` | `sort_by` | +| `"SortOrder"` | `sort_order` | + +### custom_item_display_preferences (displaypreferences."CustomItemDisplayPreferences") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"Id"` | `id` | +| `"UserId"` | `user_id` | +| `"ItemId"` | `item_id` | +| `"Client"` | `client` | +| `"Key"` | `key` | +| `"Value"` | `value` | + +### home_sections (displaypreferences."HomeSection") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"Id"` | `id` | +| `"DisplayPreferencesId"` | `display_preferences_id` | +| `"Order"` | `order` | +| `"Type"` | `type` | + +--- + +## Library Schema + +### base_items (library."BaseItems") - 73 columns +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"Id"` | `id` | +| `"Type"` | `type` | +| `"Data"` | `data` | +| `"Path"` | `path` | +| `"StartDate"` | `start_date` | +| `"EndDate"` | `end_date` | +| `"ChannelId"` | `channel_id` | +| `"IsMovie"` | `is_movie` | +| `"CommunityRating"` | `community_rating` | +| `"CustomRating"` | `custom_rating` | +| `"IndexNumber"` | `index_number` | +| `"IsLocked"` | `is_locked` | +| `"Name"` | `name` | +| `"OfficialRating"` | `official_rating` | +| `"MediaType"` | `media_type` | +| `"Overview"` | `overview` | +| `"ParentIndexNumber"` | `parent_index_number` | +| `"PremiereDate"` | `premiere_date` | +| `"ProductionYear"` | `production_year` | +| `"Genres"` | `genres` | +| `"SortName"` | `sort_name` | +| `"ForcedSortName"` | `forced_sort_name` | +| `"RunTimeTicks"` | `run_time_ticks` | +| `"DateCreated"` | `date_created` | +| `"DateModified"` | `date_modified` | +| `"IsSeries"` | `is_series` | +| `"EpisodeTitle"` | `episode_title` | +| `"IsRepeat"` | `is_repeat` | +| `"PreferredMetadataLanguage"` | `preferred_metadata_language` | +| `"PreferredMetadataCountryCode"` | `preferred_metadata_country_code` | +| `"DateLastRefreshed"` | `date_last_refreshed` | +| `"DateLastSaved"` | `date_last_saved` | +| `"IsInMixedFolder"` | `is_in_mixed_folder` | +| `"Studios"` | `studios` | +| `"ExternalServiceId"` | `external_service_id` | +| `"Tags"` | `tags` | +| `"IsFolder"` | `is_folder` | +| `"InheritedParentalRatingValue"` | `inherited_parental_rating_value` | +| `"InheritedParentalRatingSubValue"` | `inherited_parental_rating_sub_value` | +| `"UnratedType"` | `unrated_type` | +| `"CriticRating"` | `critic_rating` | +| `"CleanName"` | `clean_name` | +| `"PresentationUniqueKey"` | `presentation_unique_key` | +| `"OriginalTitle"` | `original_title` | +| `"PrimaryVersionId"` | `primary_version_id` | +| `"DateLastMediaAdded"` | `date_last_media_added` | +| `"Album"` | `album` | +| `"LUFS"` | `lufs` | +| `"NormalizationGain"` | `normalization_gain` | +| `"IsVirtualItem"` | `is_virtual_item` | +| `"SeriesName"` | `series_name` | +| `"SeasonName"` | `season_name` | +| `"ExternalSeriesId"` | `external_series_id` | +| `"Tagline"` | `tagline` | +| `"ProductionLocations"` | `production_locations` | +| `"ExtraIds"` | `extra_ids` | +| `"TotalBitrate"` | `total_bitrate` | +| `"ExtraType"` | `extra_type` | +| `"Artists"` | `artists` | +| `"AlbumArtists"` | `album_artists` | +| `"ExternalId"` | `external_id` | +| `"SeriesPresentationUniqueKey"` | `series_presentation_unique_key` | +| `"ShowId"` | `show_id` | +| `"OwnerId"` | `owner_id` | +| `"Width"` | `width` | +| `"Height"` | `height` | +| `"Size"` | `size` | +| `"Audio"` | `audio` | +| `"ParentId"` | `parent_id` | +| `"TopParentId"` | `top_parent_id` | +| `"SeasonId"` | `season_id` | +| `"SeriesId"` | `series_id` | + +### chapters (library."Chapters") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"ItemId"` | `item_id` | +| `"ChapterIndex"` | `chapter_index` | +| `"StartPositionTicks"` | `start_position_ticks` | +| `"Name"` | `name` | +| `"ImagePath"` | `image_path` | +| `"ImageDateModified"` | `image_date_modified` | + +### media_stream_infos (library."MediaStreamInfos") - 51 columns +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"ItemId"` | `item_id` | +| `"StreamIndex"` | `stream_index` | +| `"StreamType"` | `stream_type` | +| `"Codec"` | `codec` | +| `"Language"` | `language` | +| `"ChannelLayout"` | `channel_layout` | +| `"Profile"` | `profile` | +| `"AspectRatio"` | `aspect_ratio` | +| `"Path"` | `path` | +| `"IsInterlaced"` | `is_interlaced` | +| `"BitRate"` | `bit_rate` | +| `"Channels"` | `channels` | +| `"SampleRate"` | `sample_rate` | +| `"IsDefault"` | `is_default` | +| `"IsForced"` | `is_forced` | +| `"IsExternal"` | `is_external` | +| `"Height"` | `height` | +| `"Width"` | `width` | +| `"AverageFrameRate"` | `average_frame_rate` | +| `"RealFrameRate"` | `real_frame_rate` | +| `"Level"` | `level` | +| `"PixelFormat"` | `pixel_format` | +| `"BitDepth"` | `bit_depth` | +| `"IsAnamorphic"` | `is_anamorphic` | +| `"RefFrames"` | `ref_frames` | +| `"CodecTag"` | `codec_tag` | +| `"Comment"` | `comment` | +| `"NalLengthSize"` | `nal_length_size` | +| `"IsAvc"` | `is_avc` | +| `"Title"` | `title` | +| `"TimeBase"` | `time_base` | +| `"CodecTimeBase"` | `codec_time_base` | +| `"ColorPrimaries"` | `color_primaries` | +| `"ColorSpace"` | `color_space` | +| `"ColorTransfer"` | `color_transfer` | +| `"DvVersionMajor"` | `dv_version_major` | +| `"DvVersionMinor"` | `dv_version_minor` | +| `"DvProfile"` | `dv_profile` | +| `"DvLevel"` | `dv_level` | +| `"RpuPresentFlag"` | `rpu_present_flag` | +| `"ElPresentFlag"` | `el_present_flag` | +| `"BlPresentFlag"` | `bl_present_flag` | +| `"DvBlSignalCompatibilityId"` | `dv_bl_signal_compatibility_id` | +| `"IsHearingImpaired"` | `is_hearing_impaired` | +| `"Rotation"` | `rotation` | +| `"KeyFrames"` | `key_frames` | +| `"Hdr10PlusPresentFlag"` | `hdr10_plus_present_flag` | + +### attachment_stream_infos (library."AttachmentStreamInfos") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"ItemId"` | `item_id` | +| `"Index"` | `index` | +| `"Codec"` | `codec` | +| `"CodecTag"` | `codec_tag` | +| `"Comment"` | `comment` | +| `"Filename"` | `filename` | +| `"MimeType"` | `mime_type` | + +### image_infos (library."ImageInfos") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"Id"` | `id` | +| `"UserId"` | `user_id` | +| `"Path"` | `path` | +| `"LastModified"` | `last_modified` | + +### base_item_image_infos (library."BaseItemImageInfos") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"Id"` | `id` | +| `"Path"` | `path` | +| `"DateModified"` | `date_modified` | +| `"ImageType"` | `image_type` | +| `"Width"` | `width` | +| `"Height"` | `height` | +| `"Blurhash"` | `blurhash` | +| `"ItemId"` | `item_id` | + +### base_item_metadata_fields (library."BaseItemMetadataFields") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"Id"` | `id` | +| `"ItemId"` | `item_id` | + +### base_item_providers (library."BaseItemProviders") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"ItemId"` | `item_id` | +| `"ProviderId"` | `provider_id` | +| `"ProviderValue"` | `provider_value` | + +### base_item_trailer_types (library."BaseItemTrailerTypes") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"Id"` | `id` | +| `"ItemId"` | `item_id` | + +### item_values (library."ItemValues") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"ItemValueId"` | `item_value_id` | +| `"Type"` | `type` | +| `"Value"` | `value` | +| `"CleanValue"` | `clean_value` | + +### item_values_map (library."ItemValuesMap") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"ItemId"` | `item_id` | +| `"ItemValueId"` | `item_value_id` | + +### peoples (library."Peoples") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"Id"` | `id` | +| `"Name"` | `name` | +| `"PersonType"` | `person_type` | + +### people_base_item_map (library."PeopleBaseItemMap") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"Role"` | `role` | +| `"ItemId"` | `item_id` | +| `"PeopleId"` | `people_id` | +| `"SortOrder"` | `sort_order` | +| `"ListOrder"` | `list_order` | + +### user_data (library."UserData") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"CustomDataKey"` | `custom_data_key` | +| `"ItemId"` | `item_id` | +| `"UserId"` | `user_id` | +| `"Rating"` | `rating` | +| `"PlaybackPositionTicks"` | `playback_position_ticks` | +| `"PlayCount"` | `play_count` | +| `"IsFavorite"` | `is_favorite` | +| `"LastPlayedDate"` | `last_played_date` | +| `"Played"` | `played` | +| `"AudioStreamIndex"` | `audio_stream_index` | +| `"SubtitleStreamIndex"` | `subtitle_stream_index` | +| `"Likes"` | `likes` | +| `"RetentionDate"` | `retention_date` | + +### ancestor_ids (library."AncestorIds") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"ParentItemId"` | `parent_item_id` | +| `"ItemId"` | `item_id` | + +### trickplay_infos (library."TrickplayInfos") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"ItemId"` | `item_id` | +| `"Width"` | `width` | +| `"Height"` | `height` | +| `"TileWidth"` | `tile_width` | +| `"TileHeight"` | `tile_height` | +| `"ThumbnailCount"` | `thumbnail_count` | +| `"Interval"` | `interval` | +| `"Bandwidth"` | `bandwidth` | + +### media_segments (library."MediaSegments") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"Id"` | `id` | +| `"ItemId"` | `item_id` | +| `"Type"` | `type` | +| `"EndTicks"` | `end_ticks` | +| `"StartTicks"` | `start_ticks` | +| `"SegmentProviderId"` | `segment_provider_id` | + +### keyframe_data (library."KeyframeData") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"ItemId"` | `item_id` | +| `"TotalDuration"` | `total_duration` | +| `"KeyframeTicks"` | `keyframe_ticks` | + +### library_options (library."LibraryOptions") - Note: Not yet found in schema, may need verification +Expected columns (from LibraryOptionsEntity EF mapping): +- LibraryPath (primary key, text/string) +- DateModified (timestamp with time zone) + +--- + +## Users Schema + +### users (users."Users") - 36+ columns +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"Id"` | `id` | +| `"Username"` | `username` | +| `"Password"` | `password` | +| `"MustUpdatePassword"` | `must_update_password` | +| `"AudioLanguagePreference"` | `audio_language_preference` | +| `"AuthenticationProviderId"` | `authentication_provider_id` | +| `"PasswordResetProviderId"` | `password_reset_provider_id` | +| `"InvalidLoginAttemptCount"` | `invalid_login_attempt_count` | +| `"LastActivityDate"` | `last_activity_date` | +| `"LastLoginDate"` | `last_login_date` | +| `"LoginAttemptsBeforeLockout"` | `login_attempts_before_lockout` | +| `"MaxActiveSessions"` | `max_active_sessions` | +| `"SubtitleMode"` | `subtitle_mode` | +| `"PlayDefaultAudioTrack"` | `play_default_audio_track` | +| `"SubtitleLanguagePreference"` | `subtitle_language_preference` | +| `"DisplayMissingEpisodes"` | `display_missing_episodes` | +| `"DisplayCollectionsView"` | `display_collections_view` | +| `"EnableLocalPassword"` | `enable_local_password` | +| `"HidePlayedInLatest"` | `hide_played_in_latest` | +| `"RememberAudioSelections"` | `remember_audio_selections` | +| `"RememberSubtitleSelections"` | `remember_subtitle_selections` | +| `"EnableNextEpisodeAutoPlay"` | `enable_next_episode_auto_play` | +| `"EnableAutoLogin"` | `enable_auto_login` | +| `"EnableUserPreferenceAccess"` | `enable_user_preference_access` | +| `"MaxParentalRatingScore"` | `max_parental_rating_score` | +| `"MaxParentalRatingSubScore"` | `max_parental_rating_sub_score` | +| `"RemoteClientBitrateLimit"` | `remote_client_bitrate_limit` | +| `"InternalId"` | `internal_id` | +| `"SyncPlayAccess"` | `sync_play_access` | +| `"CastReceiverId"` | `cast_receiver_id` | +| `"RowVersion"` | `row_version` | + +### permissions (users."Permissions") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"Id"` | `id` | +| `"UserId"` | `user_id` | +| `"Kind"` | `kind` | +| `"Value"` | `value` | +| `"RowVersion"` | `row_version` | +| `"Permission_Permissions_Guid"` | `permission_permissions_guid` | + +### preferences (users."Preferences") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"Id"` | `id` | +| `"UserId"` | `user_id` | +| `"Kind"` | `kind` | +| `"Value"` | `value` | +| `"RowVersion"` | `row_version` | +| `"Preference_Preferences_Guid"` | `preference_preferences_guid` | + +### access_schedules (users."AccessSchedules") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"Id"` | `id` | +| `"UserId"` | `user_id` | +| `"DayOfWeek"` | `day_of_week` | +| `"StartHour"` | `start_hour` | +| `"EndHour"` | `end_hour` | + +--- + +## Special System Tables + +### __ef_migrations_history (public."__EFMigrationsHistory") +| Current (SQL) | Target (snake_case) | +|--------------|-------------------| +| `"MigrationId"` | `migration_id` | +| `"ProductVersion"` | `product_version` | + +--- + +## Summary Statistics + +- **Total Application Tables**: 19 +- **Total Library Schema Tables**: 19 (with BaseItems being the largest at 73 columns) +- **Total Media Stream Columns**: 51 (MediaStreamInfos is the second-largest table) +- **Total Columns Across All Tables**: ~250+ +- **Sequences to Rename**: 17 (one per auto-increment table) +- **Special System Table**: 1 (`__EFMigrationsHistory`) + +--- + +Generated: 2025-05-01 +For use in create_database_schema.sql conversion from quoted PascalCase to lowercase/snake_case identifiers diff --git a/docs/SCHEMA_CONVERSION_GUIDE.md b/docs/SCHEMA_CONVERSION_GUIDE.md new file mode 100644 index 00000000..a7250f4d --- /dev/null +++ b/docs/SCHEMA_CONVERSION_GUIDE.md @@ -0,0 +1,182 @@ +# SQL Schema Conversion Guide - PascalCase to snake_case + +## Authoritative Table Mappings (from PostgresDatabaseProvider.OnModelCreating) + +### Activity Log Schema +| Current (SQL) | Target (C#/PostgreSQL) | Entity Class | +|--------------|------------------------|--------------| +| `"ActivityLogs"` | `activity_logs` | `ActivityLog` | + +### Authentication Schema +| Current (SQL) | Target (C#/PostgreSQL) | Entity Class | +|--------------|------------------------|--------------| +| `"ApiKeys"` | `api_keys` | `ApiKey` | +| `"Devices"` | `devices` | `Device` | +| `"DeviceOptions"` | `device_options` | `DeviceOptions` | + +### Display Preferences Schema +| Current (SQL) | Target (C#/PostgreSQL) | Entity Class | +|--------------|------------------------|--------------| +| `"DisplayPreferences"` | `display_preferences` | `DisplayPreferences` | +| `"ItemDisplayPreferences"` | `item_display_preferences` | `ItemDisplayPreferences` | +| `"CustomItemDisplayPreferences"` | `custom_item_display_preferences` | `CustomItemDisplayPreferences` | +| `"HomeSections"` | `home_sections` | `HomeSection` | + +### Users Schema +| Current (SQL) | Target (C#/PostgreSQL) | Entity Class | +|--------------|------------------------|--------------| +| `"Users"` | `users` | `User` | +| `"Permissions"` | `permissions` | `Permission` | +| `"Preferences"` | `preferences` | `Preference` | +| `"AccessSchedules"` | `access_schedules` | `AccessSchedule` | + +### Library Schema +| Current (SQL) | Target (C#/PostgreSQL) | Entity Class | +|--------------|------------------------|--------------| +| `"BaseItems"` | `base_items` | `BaseItemEntity` | +| `"Chapters"` | `chapters` | `Chapter` | +| `"MediaStreamInfos"` | `media_stream_infos` | `MediaStreamInfo` | +| `"AttachmentStreamInfos"` | `attachment_stream_infos` | `AttachmentStreamInfo` | +| `"ImageInfos"` | `image_infos` | `ImageInfo` | +| `"BaseItemImageInfos"` | `base_item_image_infos` | `BaseItemImageInfo` | +| `"BaseItemProviders"` | `base_item_providers` | `BaseItemProvider` | +| `"BaseItemMetadataFields"` | `base_item_metadata_fields` | `BaseItemMetadataField` | +| `"BaseItemTrailerTypes"` | `base_item_trailer_types` | `BaseItemTrailerType` | +| `"ItemValues"` | `item_values` | `ItemValue` | +| `"ItemValuesMaps"` | `item_values_map` | `ItemValueMap` | +| `"Peoples"` | `peoples` | `People` | +| `"PeopleBaseItemMaps"` | `people_base_item_map` | `PeopleBaseItemMap` | +| `"UserData"` | `user_data` | `UserData` | +| `"AncestorIds"` | `ancestor_ids` | `AncestorId` | +| `"TrickplayInfos"` | `trickplay_infos` | `TrickplayInfo` | +| `"MediaSegments"` | `media_segments` | `MediaSegment` | +| `"KeyframeData"` | `keyframe_data` | `KeyframeData` | +| `"LibraryOptions"` | `library_options` | `LibraryOptionsEntity` | + +### Special Tables +| Current (SQL) | Target (C#/PostgreSQL) | Notes | +|--------------|------------------------|-------| +| `"__EFMigrationsHistory"` | `__ef_migrations_history` | System table, special handling | + +### Views (Library Schema) +| Current (SQL) | Target (C#/PostgreSQL) | Entity Class | +|--------------|------------------------|--------------| +| `"media_stream_infos_v"` | `media_stream_infos_v` | `MediaStreamInfoView` (already lowercase) | +| `"video_items_v"` | `video_items_v` | `VideoItemView` (already lowercase) | +| `"user_playback_history_v"` | `user_playback_history_v` | `UserPlaybackHistoryView` (already lowercase) | +| `"item_providers_v"` | `item_providers_v` | `ItemProviderView` (already lowercase) | +| `"item_people_v"` | `item_people_v` | `ItemPersonView` (already lowercase) | +| `"library_summary_v"` | `library_summary_v` | `LibrarySummaryView` (already lowercase) | + +--- + +## Column Naming Rules + +### SnakeCaseNamingConvention Conversion Rules + +```csharp +// From SnakeCaseNamingConvention.cs - regex patterns applied: +// Rule 1: ([A-Z]+)([A-Z][a-z]) → "$1_$2" // Consecutive capitals: HTTPServer → HTTP_Server +// Rule 2: ([a-z\d])([A-Z]) → "$1_$2" // Lowercase/digit to capital: dateCreated → date_Created +// Rule 3: .ToLowerInvariant() // Lowercase: date_Created → date_created +``` + +### Common Column Conversions + +Single-Word Columns: +- `"Id"` → `id` +- `"Name"` → `name` +- `"Type"` → `type` +- `"UserId"` → `user_id` +- `"ItemId"` → `item_id` + +Multi-Word Columns: +- `"DateCreated"` → `date_created` +- `"DateModified"` → `date_modified` +- `"DateLastActivity"` → `date_last_activity` +- `"AccessToken"` → `access_token` +- `"IsMovie"` → `is_movie` +- `"IsSeries"` → `is_series` +- `"ShortOverview"` → `short_overview` +- `"LogSeverity"` → `log_severity` +- `"RowVersion"` → `row_version` +- `"DisplayOrder"` → `display_order` +- `"BaseItemId"` → `base_item_id` +- `"DeviceId"` → `device_id` +- `"ProviderId"` → `provider_id` +- `"SortName"` → `sort_name` +- `"ProviderIds"` → `provider_ids` +- `"DvVersionMajor"` → `dv_version_major` +- `"DvVersionMinor"` → `dv_version_minor` +- `"DvProfile"` → `dv_profile` +- `"DvLevel"` → `dv_level` +- `"RpuVersion"` → `rpu_version` +- `"CodecTag"` → `codec_tag` +- `"IsHDR"` → `is_hdr` +- `"IsHDR10"` → `is_hdr10` +- `"SeriesPresentationUniqueKey"` → `series_presentation_unique_key` + +--- + +## Conversion Strategy in create_database_schema.sql + +### Phase 1: Table Definition Lines +Find and replace quoted PascalCase table names immediately after `CREATE TABLE`: +- `CREATE TABLE activitylog."ActivityLogs"` → `CREATE TABLE activitylog.activity_logs` +- `CREATE TABLE authentication."ApiKeys"` → `CREATE TABLE authentication.api_keys` +- etc. (all 19 tables in schema sections) + +### Phase 2: Column Definitions +Within each `CREATE TABLE` block, replace all quoted column names: +- `"Id"` → `id` +- `"Name"` → `name` +- `"DateCreated"` → `date_created` +- etc. (200+ column replacements across all tables) + +### Phase 3: Sequence Names +Update sequence definitions to match renamed tables: +- `SEQUENCE NAME activitylog."ActivityLogs_Id_seq"` → `SEQUENCE NAME activitylog.activity_logs_id_seq` +- etc. + +### Phase 4: Constraint References +Update all foreign key and constraint definitions: +- `CONSTRAINT "fk_base_items_users_user_id" FOREIGN KEY ("BaseItemId") REFERENCES users."Users" ("Id")` + → `CONSTRAINT fk_base_items_users_user_id FOREIGN KEY (base_item_id) REFERENCES users.users (id)` + +### Phase 5: Index References +Update index definitions: +- `CREATE INDEX "idx_activity_logs_user_id" ON activitylog."ActivityLogs" ("UserId")` + → `CREATE INDEX idx_activity_logs_user_id ON activitylog.activity_logs (user_id)` + +### Phase 6: Special Table (__EFMigrationsHistory) +Update system table for consistency: +- `"__EFMigrationsHistory"` → `__ef_migrations_history` +- All its columns follow the same snake_case rule + +--- + +## File Location +- **Source**: `Jellyfin.Server/sql/schema_init/create_database_schema.sql` (1879 lines) +- **Output**: Same file (in-place conversion) + +--- + +## Validation Checklist +- [ ] All 19 application tables converted from PascalCase to snake_case +- [ ] All 200+ columns converted to lowercase/snake_case +- [ ] All sequence names updated +- [ ] All foreign key references updated +- [ ] All indexes updated +- [ ] Special table `__ef_migrations_history` created with lowercase columns +- [ ] Views remain unchanged (already lowercase) +- [ ] SQL syntax is valid +- [ ] No orphaned quotes remain in identifier positions +- [ ] Schema still respects owner = jellyfin + +--- + +Generated: 2025-05-01 +Reference Documents: +- `PostgresDatabaseProvider.cs` lines 763-875 +- `SnakeCaseNamingConvention.cs` lines 16-40 +- `create_database_schema.sql` full schema dump diff --git a/WEBSOCKET_AUTHENTICATION.md b/docs/WEBSOCKET_AUTHENTICATION.md similarity index 100% rename from WEBSOCKET_AUTHENTICATION.md rename to docs/WEBSOCKET_AUTHENTICATION.md diff --git a/publish/Emby.Naming.xml b/publish/Emby.Naming.xml new file mode 100644 index 00000000..1fb4a4f9 --- /dev/null +++ b/publish/Emby.Naming.xml @@ -0,0 +1,2076 @@ + + + + Emby.Naming + + + + + Represents a single video file. + + + + + Initializes a new instance of the class. + + Path to audiobook file. + File type. + Number of part this file represents. + Number of chapter this file represents. + + + + Gets or sets the path. + + The path. + + + + Gets or sets the container. + + The container. + + + + Gets or sets the part number. + + The part number. + + + + Gets or sets the chapter number. + + The chapter number. + + + + + + + Parser class to extract part and/or chapter number from audiobook filename. + + + + + Initializes a new instance of the class. + + Naming options containing AudioBookPartsExpressions. + + + + Based on regex determines if filename includes part/chapter number. + + Path to audiobook file. + Returns object. + + + + Data object for passing result of audiobook part/chapter extraction. + + + + + Gets or sets optional number of path extracted from audiobook filename. + + + + + Gets or sets optional number of chapter extracted from audiobook filename. + + + + + Represents a complete video, including all parts and subtitles. + + + + + Initializes a new instance of the class. + + Name of audiobook. + Year of audiobook release. + List of files composing the actual audiobook. + List of extra files. + Alternative version of files. + + + + Gets or sets the name. + + The name. + + + + Gets or sets the year. + + + + + Gets or sets the files. + + The files. + + + + Gets or sets the extras. + + The extras. + + + + Gets or sets the alternate versions. + + The alternate versions. + + + + Class used to resolve Name, Year, alternative files and extras from stack of files. + + + + + Initializes a new instance of the class. + + Naming options passed along to and . + + + + Resolves Name, Year and differentiate alternative files and extras from regular audiobook files. + + List of files related to audiobook. + Returns IEnumerable of . + + + + Helper class to retrieve name and year from audiobook previously retrieved name. + + + + + Initializes a new instance of the class. + + Naming options containing AudioBookNamesExpressions. + + + + Parse name and year from previously determined name of audiobook. + + Name of the audiobook. + Returns object. + + + + Data object used to pass result of name and year parsing. + + + + + Gets or sets name of audiobook. + + + + + Gets or sets optional year of release. + + + + + Resolve specifics (path, container, partNumber, chapterNumber) about audiobook file. + + + + + Initializes a new instance of the class. + + containing AudioFileExtensions and also used to pass to AudioBookFilePathParser. + + + + Resolve specifics (path, container, partNumber, chapterNumber) about audiobook file. + + Path to audiobook file. + Returns object. + + + + Helper class to determine if Album is multipart. + + + + + Initializes a new instance of the class. + + Naming options containing AlbumStackingPrefixes. + + + + Pattern:
+ [-\.\(\)\s]+
+ Explanation:
+ + ○ Match a character in the set [()\-.\s] atomically at least once.
+
+
+
+ + + Function that determines if album is multipart. + + Path to file. + True if album is multipart. + + + + Static helper class to determine if file at path is audio file. + + + + + Static helper method to determine if file at path is audio file. + + Path to file. + containing AudioFileExtensions. + True if file at path is audio file. + + + + Helper class to retrieve basic metadata from a book filename. + + + + + Parse a filename name to retrieve the book name, series name, index, and year. + + Book filename to parse for information. + Returns object. + + + + Data object used to pass metadata parsed from a book filename. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the name of the book. + + + + + Gets or sets the book index. + + + + + Gets or sets the publication year. + + + + + Gets or sets the series name. + + + + + Regular expressions for parsing TV Episodes. + + + + + Initializes a new instance of the class. + + Regular expressions. + True if date is expected. + + + + Gets or sets raw expressions string. + + + + + Gets or sets a value indicating whether gets or sets property indicating if date can be find in expression. + + + + + Gets or sets a value indicating whether gets or sets property indicating if expression is optimistic. + + + + + Gets or sets a value indicating whether gets or sets property indicating if expression is named. + + + + + Gets or sets a value indicating whether gets or sets property indicating if expression supports episodes with absolute numbers. + + + + + Gets or sets optional list of date formats used for date parsing. + + + + + Gets a expressions objects (creates it if null). + + + + + Type of audiovisual media. + + + + + The audio. + + + + + The photo. + + + + + The video. + + + + + Big ugly class containing lot of different naming options that should be split and injected instead of passes everywhere. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the folder name to extra types mapping. + + + + + Gets or sets list of audio file extensions. + + + + + Gets or sets list of external media flag delimiters. + + + + + Gets or sets list of external media forced flags. + + + + + Gets or sets list of external media default flags. + + + + + Gets or sets list of external media hearing impaired flags. + + + + + Gets or sets list of album stacking prefixes. + + + + + Gets or sets list of artist subfolders. + + + + + Gets or sets list of subtitle file extensions. + + + + + Gets the list of lyric file extensions. + + + + + Gets or sets list of episode regular expressions. + + + + + Gets or sets list of video file extensions. + + + + + Gets or sets list of video stub file extensions. + + + + + Gets or sets list of raw audiobook parts regular expressions strings. + + + + + Gets or sets list of raw audiobook names regular expressions strings. + + + + + Gets or sets list of stub type rules. + + + + + Gets or sets list of video flag delimiters. + + + + + Gets or sets list of 3D Format rules. + + + + + Gets the file stacking rules. + + + + + Gets or sets list of raw clean DateTimes regular expressions strings. + + + + + Gets or sets list of raw clean strings regular expressions strings. + + + + + Gets or sets list of multi-episode regular expressions. + + + + + Gets or sets list of extra rules for videos. + + + + + Gets list of clean datetime regular expressions. + + + + + Gets list of clean string regular expressions. + + + + + Compiles raw regex strings into regexes. + + + + + External media file parser class. + + + + + Initializes a new instance of the class. + + The localization manager. + The object containing FileExtensions, MediaDefaultFlags, MediaForcedFlags and MediaFlagDelimiters. + The of the parsed file. + + + + Parse filename and extract information. + + Path to file. + Part of the filename only containing the extra information. + Returns null or an object if parsing is successful. + + + + Class holding information about external files. + + + + + Initializes a new instance of the class. + + Path to file. + Is default. + Is forced. + For the hearing impaired. + + + + Gets or sets the path. + + The path. + + + + Gets or sets the language. + + The language. + + + + Gets or sets the title. + + The title. + + + + Gets or sets a value indicating whether this instance is default. + + true if this instance is default; otherwise, false. + + + + Gets or sets a value indicating whether this instance is forced. + + true if this instance is forced; otherwise, false. + + + + Gets or sets a value indicating whether this instance is for the hearing impaired. + + true if this instance is for the hearing impaired; otherwise, false. + + + + Holder object for Episode information. + + + + + Initializes a new instance of the class. + + Path to the file. + + + + Gets or sets the path. + + The path. + + + + Gets or sets the container. + + The container. + + + + Gets or sets the name of the series. + + The name of the series. + + + + Gets or sets the format3 d. + + The format3 d. + + + + Gets or sets a value indicating whether [is3 d]. + + true if [is3 d]; otherwise, false. + + + + Gets or sets a value indicating whether this instance is stub. + + true if this instance is stub; otherwise, false. + + + + Gets or sets the type of the stub. + + The type of the stub. + + + + Gets or sets optional season number. + + + + + Gets or sets optional episode number. + + + + + Gets or sets optional ending episode number. For multi-episode files 1-13. + + + + + Gets or sets optional year of release. + + + + + Gets or sets optional year of release. + + + + + Gets or sets optional day of release. + + + + + Gets or sets a value indicating whether by date expression was used. + + + + + Used to parse information about episode from path. + + + + + Initializes a new instance of the class. + + object containing EpisodeExpressions and MultipleEpisodeExpressions. + + + + Parses information about episode from path. + + Path. + Is path for a directory or file. + Do we want to use IsNamed expressions. + Do we want to use Optimistic expressions. + Do we want to use expressions supporting absolute episode numbers. + Should we attempt to retrieve extended information. + Returns object. + + + + Holder object for result. + + + + + Gets or sets optional season number. + + + + + Gets or sets optional episode number. + + + + + Gets or sets optional ending episode number. For multi-episode files 1-13. + + + + + Gets or sets the name of the series. + + The name of the series. + + + + Gets or sets a value indicating whether parsing was successful. + + + + + Gets or sets a value indicating whether by date expression was used. + + + + + Gets or sets optional year of release. + + + + + Gets or sets optional year of release. + + + + + Gets or sets optional day of release. + + + + + Used to resolve information about episode from path. + + + + + Initializes a new instance of the class. + + object containing VideoFileExtensions and passed to , and . + + + + Resolve information about episode from path. + + Path. + Is path for a directory or file. + Do we want to use IsNamed expressions. + Do we want to use Optimistic expressions. + Do we want to use expressions supporting absolute episode numbers. + Should we attempt to retrieve extended information. + Returns null or object if successful. + + + + Class to parse season paths. + + + + + Pattern:
+ ^\s*((?<seasonnumber>(?>\d+))(?:st|nd|rd|th|\.)*(?!\s*[Ee]\d+))\s*(?:[[시즌]*|[シーズン]*|[sS](?:eason|æson|aison|taffel|eries|tagione|äsong|eizoen|easong|ezon|ezona|ezóna|ezonul)*|[tT](?:emporada)*|[kK](?:ausi)*|[Сс](?:езон)*)\s*(?<rightpart>.*)$
+ Options:
+ RegexOptions.IgnoreCase
+ Explanation:
+ + ○ Match if at the beginning of the string.
+ ○ Match a whitespace character atomically any number of times.
+ ○ 1st capture group.
+ ○ "seasonnumber" capture group.
+ ○ Match a Unicode digit atomically at least once.
+ ○ Loop greedily any number of times.
+ ○ Match with 5 alternative expressions.
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Ss].
+ ○ Match a character in the set [Tt].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Nn].
+ ○ Match a character in the set [Dd].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Rr].
+ ○ Match a character in the set [Dd].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Tt].
+ ○ Match a character in the set [Hh].
+ ○ Match '.'.
+ ○ Zero-width negative lookahead.
+ ○ Match a whitespace character atomically any number of times.
+ ○ Match a character in the set [Ee].
+ ○ Match a Unicode digit atomically at least once.
+ ○ Match a whitespace character greedily any number of times.
+ ○ Match with 6 alternative expressions.
+ ○ Match a character in the set [[\uC2DC\uC98C] greedily any number of times.
+ ○ Match a character in the set [\u30B7\u30BA\u30F3\u30FC] greedily any number of times.
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Ss].
+ ○ Loop greedily any number of times.
+ ○ Match with 8 alternative expressions.
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Ee].
+ ○ Match a character in the set [Aa].
+ ○ Match a character in the set [Ss].
+ ○ Match a character in the set [Oo].
+ ○ Match a character in the set [Nn].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [\u00C6\u00E6].
+ ○ Match a character in the set [Ss].
+ ○ Match a character in the set [Oo].
+ ○ Match a character in the set [Nn].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Aa].
+ ○ Match a character in the set [Ii].
+ ○ Match a character in the set [Ss].
+ ○ Match a character in the set [Oo].
+ ○ Match a character in the set [Nn].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Tt].
+ ○ Match a character in the set [Aa].
+ ○ Match a character in the set [Ff] exactly 2 times.
+ ○ Match a character in the set [Ee].
+ ○ Match a character in the set [Ll].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Ee].
+ ○ Match a character in the set [Rr].
+ ○ Match a character in the set [Ii].
+ ○ Match a character in the set [Ee].
+ ○ Match a character in the set [Ss].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Tt].
+ ○ Match a character in the set [Aa].
+ ○ Match a character in the set [Gg].
+ ○ Match a character in the set [Ii].
+ ○ Match a character in the set [Oo].
+ ○ Match a character in the set [Nn].
+ ○ Match a character in the set [Ee].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [\u00C4\u00E4].
+ ○ Match a character in the set [Ss].
+ ○ Match a character in the set [Oo].
+ ○ Match a character in the set [Nn].
+ ○ Match a character in the set [Gg].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Ee].
+ ○ Match with 3 alternative expressions.
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Ii].
+ ○ Match a character in the set [Zz].
+ ○ Match a character in the set [Oo].
+ ○ Match a character in the set [Ee].
+ ○ Match a character in the set [Nn].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Aa].
+ ○ Match a character in the set [Ss].
+ ○ Match a character in the set [Oo].
+ ○ Match a character in the set [Nn].
+ ○ Match a character in the set [Gg].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Zz].
+ ○ Match with 3 alternative expressions.
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Oo].
+ ○ Match a character in the set [Nn].
+ ○ Match a character in the set [Aa] lazily, optionally.
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [\u00D3\u00F3].
+ ○ Match a character in the set [Nn].
+ ○ Match a character in the set [Aa].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Oo].
+ ○ Match a character in the set [Nn].
+ ○ Match a character in the set [Uu].
+ ○ Match a character in the set [Ll].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Tt].
+ ○ Loop greedily any number of times.
+ ○ Match a character in the set [Ee].
+ ○ Match a character in the set [Mm].
+ ○ Match a character in the set [Pp].
+ ○ Match a character in the set [Oo].
+ ○ Match a character in the set [Rr].
+ ○ Match a character in the set [Aa].
+ ○ Match a character in the set [Dd].
+ ○ Match a character in the set [Aa].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Kk\u212A].
+ ○ Loop greedily any number of times.
+ ○ Match a character in the set [Aa].
+ ○ Match a character in the set [Uu].
+ ○ Match a character in the set [Ss].
+ ○ Match a character in the set [Ii].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [\u0421\u0441].
+ ○ Loop greedily any number of times.
+ ○ Match a character in the set [\u0415\u0435].
+ ○ Match a character in the set [\u0417\u0437].
+ ○ Match a character in the set [\u041E\u043E].
+ ○ Match a character in the set [\u041D\u043D].
+ ○ Match a whitespace character greedily any number of times.
+ ○ "rightpart" capture group.
+ ○ Match a character other than '\n' greedily any number of times.
+ ○ Match if at the end of the string or if before an ending newline.
+
+
+
+ + + Pattern:
+ ^\s*(?:[[시즌]*|[シーズン]*|[sS](?:eason|æson|aison|taffel|eries|tagione|äsong|eizoen|easong|ezon|ezona|ezóna|ezonul)*|[tT](?:emporada)*|[kK](?:ausi)*|[Сс](?:езон)*)\s*(?<seasonnumber>\d+?)(?=\d{3,4}p|[^\d]|$)(?!\s*[Ee]\d)(?<rightpart>.*)$
+ Options:
+ RegexOptions.IgnoreCase
+ Explanation:
+ + ○ Match if at the beginning of the string.
+ ○ Match a whitespace character greedily any number of times.
+ ○ Match with 6 alternative expressions.
+ ○ Match a character in the set [[\uC2DC\uC98C] atomically any number of times.
+ ○ Match a character in the set [\u30B7\u30BA\u30F3\u30FC] atomically any number of times.
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Ss].
+ ○ Loop greedily any number of times.
+ ○ Match with 8 alternative expressions.
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Ee].
+ ○ Match a character in the set [Aa].
+ ○ Match a character in the set [Ss].
+ ○ Match a character in the set [Oo].
+ ○ Match a character in the set [Nn].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [\u00C6\u00E6].
+ ○ Match a character in the set [Ss].
+ ○ Match a character in the set [Oo].
+ ○ Match a character in the set [Nn].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Aa].
+ ○ Match a character in the set [Ii].
+ ○ Match a character in the set [Ss].
+ ○ Match a character in the set [Oo].
+ ○ Match a character in the set [Nn].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Tt].
+ ○ Match a character in the set [Aa].
+ ○ Match a character in the set [Ff] exactly 2 times.
+ ○ Match a character in the set [Ee].
+ ○ Match a character in the set [Ll].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Ee].
+ ○ Match a character in the set [Rr].
+ ○ Match a character in the set [Ii].
+ ○ Match a character in the set [Ee].
+ ○ Match a character in the set [Ss].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Tt].
+ ○ Match a character in the set [Aa].
+ ○ Match a character in the set [Gg].
+ ○ Match a character in the set [Ii].
+ ○ Match a character in the set [Oo].
+ ○ Match a character in the set [Nn].
+ ○ Match a character in the set [Ee].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [\u00C4\u00E4].
+ ○ Match a character in the set [Ss].
+ ○ Match a character in the set [Oo].
+ ○ Match a character in the set [Nn].
+ ○ Match a character in the set [Gg].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Ee].
+ ○ Match with 3 alternative expressions.
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Ii].
+ ○ Match a character in the set [Zz].
+ ○ Match a character in the set [Oo].
+ ○ Match a character in the set [Ee].
+ ○ Match a character in the set [Nn].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Aa].
+ ○ Match a character in the set [Ss].
+ ○ Match a character in the set [Oo].
+ ○ Match a character in the set [Nn].
+ ○ Match a character in the set [Gg].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Zz].
+ ○ Match with 3 alternative expressions.
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Oo].
+ ○ Match a character in the set [Nn].
+ ○ Match a character in the set [Aa] lazily, optionally.
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [\u00D3\u00F3].
+ ○ Match a character in the set [Nn].
+ ○ Match a character in the set [Aa].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Oo].
+ ○ Match a character in the set [Nn].
+ ○ Match a character in the set [Uu].
+ ○ Match a character in the set [Ll].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Tt].
+ ○ Loop atomically any number of times.
+ ○ Match a character in the set [Ee].
+ ○ Match a character in the set [Mm].
+ ○ Match a character in the set [Pp].
+ ○ Match a character in the set [Oo].
+ ○ Match a character in the set [Rr].
+ ○ Match a character in the set [Aa].
+ ○ Match a character in the set [Dd].
+ ○ Match a character in the set [Aa].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Kk\u212A].
+ ○ Loop atomically any number of times.
+ ○ Match a character in the set [Aa].
+ ○ Match a character in the set [Uu].
+ ○ Match a character in the set [Ss].
+ ○ Match a character in the set [Ii].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [\u0421\u0441].
+ ○ Loop atomically any number of times.
+ ○ Match a character in the set [\u0415\u0435].
+ ○ Match a character in the set [\u0417\u0437].
+ ○ Match a character in the set [\u041E\u043E].
+ ○ Match a character in the set [\u041D\u043D].
+ ○ Match a whitespace character atomically any number of times.
+ ○ "seasonnumber" capture group.
+ ○ Match a Unicode digit lazily at least once.
+ ○ Zero-width positive lookahead.
+ ○ Match with 3 alternative expressions, atomically.
+ ○ Match a sequence of expressions.
+ ○ Match a Unicode digit atomically at least 3 and at most 4 times.
+ ○ Match a character in the set [Pp].
+ ○ Match any character other than a Unicode digit.
+ ○ Match if at the end of the string or if before an ending newline.
+ ○ Zero-width negative lookahead.
+ ○ Match a whitespace character atomically any number of times.
+ ○ Match a character in the set [Ee].
+ ○ Match a Unicode digit.
+ ○ "rightpart" capture group.
+ ○ Match a character other than '\n' greedily any number of times.
+ ○ Match if at the end of the string or if before an ending newline.
+
+
+
+ + + Pattern:
+ [sS](\d{1,4})(?!\d|[eE]\d)(?=\.|_|-|\[|\]|\s|$)
+ Explanation:
+ + ○ Match a character in the set [Ss].
+ ○ 1st capture group.
+ ○ Match a Unicode digit greedily at least 1 and at most 4 times.
+ ○ Zero-width negative lookahead.
+ ○ Match with 2 alternative expressions, atomically.
+ ○ Match a Unicode digit.
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [Ee].
+ ○ Match a Unicode digit.
+ ○ Zero-width positive lookahead.
+ ○ Match with 2 alternative expressions, atomically.
+ ○ Match a character in the set [\-.[]_\s].
+ ○ Match if at the end of the string or if before an ending newline.
+
+
+
+ + + Attempts to parse season number from path. + + Path to season. + Folder name of the parent. + Support special aliases when parsing. + Support numeric season folders when parsing. + Returns object. + + + + Gets the season number from path. + + The path. + The parent folder name. + if set to true [support special aliases]. + if set to true [support numeric season folders]. + System.Nullable{System.Int32}. + + + + Data object to pass result of . + + + + + Gets or sets the season number. + + The season number. + + + + Gets or sets a value indicating whether this is success. + + true if success; otherwise, false. + + + + Gets or sets a value indicating whether "Is season folder". + Seems redundant and barely used. + + + + + Holder object for Series information. + + + + + Initializes a new instance of the class. + + Path to the file. + + + + Gets or sets the path. + + The path. + + + + Gets or sets the name of the series. + + The name of the series. + + + + Used to parse information about series from paths containing more information that only the series name. + Uses the same regular expressions as the EpisodePathParser but have different success criteria. + + + + + Parses information about series from path. + + object containing EpisodeExpressions and MultipleEpisodeExpressions. + Path. + Returns object. + + + + Holder object for result. + + + + + Gets or sets the name of the series. + + The name of the series. + + + + Gets or sets a value indicating whether parsing was successful. + + + + + Used to resolve information about series from path. + + + + + Pattern:
+ ((?<a>[^\._]{2,})[\._]*)|([\._](?<b>[^\._]{2,}))
+ Explanation:
+ + ○ Match with 2 alternative expressions, atomically.
+ ○ 1st capture group.
+ ○ "a" capture group.
+ ○ Match a character in the set [^._] atomically at least twice.
+ ○ Match a character in the set [._] atomically any number of times.
+ ○ 2nd capture group.
+ ○ Match a character in the set [._].
+ ○ "b" capture group.
+ ○ Match a character in the set [^._] atomically at least twice.
+
+
+
+ + + Pattern:
+ (?<title>.+?)\s*\(\d{4}\)
+ Explanation:
+ + ○ "title" capture group.
+ ○ Match a character other than '\n' lazily at least once.
+ ○ Match a whitespace character atomically any number of times.
+ ○ Match '('.
+ ○ Match a Unicode digit exactly 4 times.
+ ○ Match ')'.
+
+
+
+ + + Resolve information about series from path. + + object passed to . + Path to series. + SeriesInfo. + + + + Helper class for TV metadata parsing. + + + + + Tries to parse a string into . + + The status string. + The . + Returns true if parsing was successful. + + + + . + + + + + Attempts to clean the name. + + Name of video. + Optional list of regexes to clean the name. + Returns object. + + + + Holder structure for name and year. + + + + + Initializes a new instance of the struct. + + Name of video. + Year of release. + + + + Gets the name. + + The name. + + + + Gets the year. + + The year. + + + + . + + + + + Attempts to extract clean name with regular expressions. + + Name of file. + List of regex to parse name and year from. + Parsing result string. + True if parsing was successful. + + + + Holder object for passing results from ExtraResolver. + + + + + Gets or sets the type of the extra. + + The type of the extra. + + + + Gets or sets the rule. + + The rule. + + + + A rule used to match a file path with an . + + + + + Initializes a new instance of the class. + + Type of extra. + Type of rule. + Token. + Media type. + + + + Gets or sets the token to use for matching against the file path. + + + + + Gets or sets the type of the extra to return when matched. + + + + + Gets or sets the type of the rule. + + + + + Gets or sets the type of the media to return when matched. + + + + + Resolve if file is extra for video. + + + + + Attempts to resolve if file is extra. + + Path to file. + The naming options. + Top-level folder for the containing library. + Returns object. + + + + Extra rules type to determine against what should be matched. + + + + + Match against a suffix in the file name. + + + + + Match against the file name, excluding the file extension. + + + + + Match against the file name, including the file extension. + + + + + Match against the name of the directory containing the file. + + + + + Object holding list of files paths with additional information. + + + + + Initializes a new instance of the class. + + The stack name. + Whether the stack files are directories. + The stack files. + + + + Gets the name of file stack. + + + + + Gets the list of paths in stack. + + + + + Gets a value indicating whether stack is directory stack. + + + + + Helper function to determine if path is in the stack. + + Path of desired file. + Requested type of stack. + True if file is in the stack. + + + + Regex based rule for file stacking (eg. disc1, disc2). + + + + + Initializes a new instance of the class. + + Token. + Whether the file stack rule uses numerical or alphabetical numbering. + + + + Gets a value indicating whether the rule uses numerical or alphabetical numbering. + + + + + Match the input against the rule regex. + + The input. + The part type and number or null. + A value indicating whether the input matched the rule. + + + + Parse 3D format related flags. + + + + + Parse 3D format related flags. + + Path to file. + The naming options. + Returns object. + + + + Helper object to return data from . + + + + + Initializes a new instance of the class. + + A value indicating whether the parsed string contains 3D tokens. + The 3D format. Value might be null if [is3D] is false. + + + + Gets a value indicating whether [is3 d]. + + true if [is3 d]; otherwise, false. + + + + Gets the format3 d. + + The format3 d. + + + + Data holder class for 3D format rule. + + + + + Initializes a new instance of the class. + + Token. + Token present before current token. + + + + Gets or sets the token. + + The token. + + + + Gets or sets the preceding token. + + The preceding token. + + + + Resolve from list of paths. + + + + + Resolves only directories from paths. + + List of paths. + The naming options. + Enumerable of directories. + + + + Resolves only files from paths. + + List of paths. + The naming options. + Enumerable of files. + + + + Resolves audiobooks from paths. + + List of paths. + Enumerable of directories. + + + + Resolves videos from paths. + + List of paths. + The naming options. + Enumerable of videos. + + + + Resolve if file is stub (.disc). + + + + + Tries to resolve if file is stub (.disc). + + Path to file. + NamingOptions containing StubFileExtensions and StubTypes. + Stub type. + True if file is a stub. + + + + Data class holding information about Stub type rule. + + + + + Initializes a new instance of the class. + + Token. + Stub type. + + + + Gets or sets the token. + + The token. + + + + Gets or sets the type of the stub. + + The type of the stub. + + + + Represents a single video file. + + + + + Initializes a new instance of the class. + + Name of file. + Path to the file. + Container type. + Year of release. + Extra type. + Extra rule. + Format 3D. + Is 3D. + Is Stub. + Stub type. + Is directory. + + + + Gets or sets the path. + + The path. + + + + Gets or sets the container. + + The container. + + + + Gets or sets the name. + + The name. + + + + Gets or sets the year. + + The year. + + + + Gets or sets the type of the extra, e.g. trailer, theme song, behind the scenes, etc. + + The type of the extra. + + + + Gets or sets the extra rule. + + The extra rule. + + + + Gets or sets the format3 d. + + The format3 d. + + + + Gets or sets a value indicating whether [is3 d]. + + true if [is3 d]; otherwise, false. + + + + Gets or sets a value indicating whether this instance is stub. + + true if this instance is stub; otherwise, false. + + + + Gets or sets the type of the stub. + + The type of the stub. + + + + Gets or sets a value indicating whether this instance is a directory. + + The type. + + + + Gets the file name without extension. + + The file name without extension. + + + + + + + Represents a complete video, including all parts and subtitles. + + + + + Initializes a new instance of the class. + + The name. + + + + Gets or sets the name. + + The name. + + + + Gets or sets the year. + + The year. + + + + Gets or sets the files. + + The files. + + + + Gets or sets the alternate versions. + + The alternate versions. + + + + Gets or sets the extra type. + + + + + Resolves alternative versions and extras from list of video files. + + + + + Pattern:
+ [0-9]{2}[0-9]+[ip]
+ Options:
+ RegexOptions.IgnoreCase
+ Explanation:
+ + ○ Match a character in the set [0-9] atomically at least 3 times.
+ ○ Match a character in the set [IPip].
+
+
+
+ + + Pattern:
+ ^\[([^]]*)\]
+ Explanation:
+ + ○ Match if at the beginning of the string.
+ ○ Match '['.
+ ○ 1st capture group.
+ ○ Match a character other than ']' atomically any number of times.
+ ○ Match ']'.
+
+
+
+ + + Resolves alternative versions and extras from list of video files. + + List of related video files. + The naming options. + Indication we should consider multi-versions of content. + Whether to parse the name or use the filename. + Top-level folder for the containing library. + Returns enumerable of which groups files together when related. + + + + Resolves from file path. + + + + + Resolves the directory. + + The path. + The naming options. + Whether to parse the name or use the filename. + Top-level folder for the containing library. + VideoFileInfo. + + + + Resolves the file. + + The path. + The naming options. + Top-level folder for the containing library. + VideoFileInfo. + + + + Resolves the specified path. + + The path. + if set to true [is folder]. + The naming options. + Whether or not the name should be parsed for info. + Top-level folder for the containing library. + VideoFileInfo. + path is null. + + + + Determines if path is video file based on extension. + + Path to file. + The naming options. + True if is video file. + + + + Determines if path is video file stub based on extension. + + Path to file. + The naming options. + True if is video file stub. + + + + Tries to clean name of clutter. + + Raw name. + The naming options. + Clean name. + True if cleaning of name was successful. + + + + Tries to get name and year from raw name. + + Raw name. + The naming options. + Returns with name and optional year. + + + Custom -derived type for the CleanRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Custom -derived type for the ProcessPre method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Custom -derived type for the ProcessPost method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Custom -derived type for the SeasonPrefix method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Custom -derived type for the SeriesNameRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Custom -derived type for the TitleWithYearRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Custom -derived type for the ResolutionRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Custom -derived type for the CheckMultiVersionRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Helper methods used by generated -derived implementations. + + + Default timeout value set in , or if none was set. + + + Whether is non-infinite. + + + Finds the next index of any character that matches a character in the set [()\-.\s]. + + + Pops 2 values from the backtracking stack. + + + Pops 3 values from the backtracking stack. + + + Pushes 2 values onto the backtracking stack. + + + Pushes 3 values onto the backtracking stack. + + + Supports searching for characters in or not in "IPip". + + + Supports searching for characters in or not in "\0\u0001\u0002\u0003\u0004\u0005\u0006\a\b\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f!\"#$%&'*+,/0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u007f". + +
+
diff --git a/publish/Emby.Photos.xml b/publish/Emby.Photos.xml new file mode 100644 index 00000000..e1b69b91 --- /dev/null +++ b/publish/Emby.Photos.xml @@ -0,0 +1,31 @@ + + + + Emby.Photos + + + + + Metadata provider for photos. + + The logger. + The image processor. + + + + Metadata provider for photos. + + The logger. + The image processor. + + + + + + + + + + + + diff --git a/publish/Emby.Server.Implementations.xml b/publish/Emby.Server.Implementations.xml new file mode 100644 index 00000000..174c6ff8 --- /dev/null +++ b/publish/Emby.Server.Implementations.xml @@ -0,0 +1,5609 @@ + + + + Emby.Server.Implementations + + + + + Provides a base class to hold common application paths used by both the UI and Server. + This can be subclassed to add application-specific paths. + + + + + Initializes a new instance of the class. + + The program data path. + The log directory path. + The configuration directory path. + The cache directory path. + The web directory path. + The temp directory path. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Class BaseConfigurationManager. + + + + + The _configuration. + + + + + Initializes a new instance of the class. + + The application paths. + The logger factory. + The XML serializer. + + + + Occurs when [configuration updated]. + + + + + Occurs when [configuration updating]. + + + + + Occurs when [named configuration updated]. + + + + + Gets the type of the configuration. + + The type of the configuration. + + + + Gets the logger. + + The logger. + + + + Gets the XML serializer. + + The XML serializer. + + + + Gets the application paths. + + The application paths. + + + + Gets or sets the system configuration. + + The configuration. + + + + Manually pre-loads a factory so that it is available pre system initialisation. + + Class to register. + + + + Adds parts. + + The configuration factories. + + + + Saves the configuration. + + + + + Called when [configuration updated]. + + + + + Replaces the configuration. + + The new configuration. + newConfiguration is null. + + + + Updates the items by name path. + + + + + Replaces the cache path. + + The new configuration. + The new cache path doesn't exist. + + + + Ensures that we have write access to the path. + + The path. + + + + + + + + + + Event handler for when a named configuration has been updated. + + The key of the configuration. + The old configuration. + + + + + + + + + + Class ConfigurationHelper. + + + + + Reads an xml configuration file from the file system + It will immediately re-serialize and save if new serialization data is available due to property changes. + + The type. + The path. + The XML serializer. + System.Object. + + + + Reads a JSON configuration file from the file system using System.Text.Json. + It will immediately re-serialize and save if new serialization data is available due to property changes. + + The type of configuration to deserialize. + The path to the JSON configuration file. + The deserialized configuration object. + + + + Class CompositionRoot. + + + + + The disposable parts. + + + + + Gets or sets all concrete types. + + All concrete types. + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + The interface. + + + + Occurs when [has pending restart changed]. + + + + + Gets the value of the PublishedServerUrl setting. + + + + + Gets the singleton instance. + + + + + + + + + + + Gets the logger. + + + + + Gets the logger factory. + + + + + Gets the application paths. + + The application paths. + + + + Gets the configuration manager. + + The configuration manager. + + + + Gets or sets the service provider. + + + + + Gets the http port for the webhost. + + + + + Gets the https port for the webhost. + + + + + + + + + + + Gets the current application user agent. + + The application user agent. + + + + Gets the email address for use within a comment section of a user agent field. + Presently used to provide contact information to MusicBrainz service. + + + + + Gets the current application name. + + The application name. + + + + + + + + + + Creates the instance safe. + + The type. + System.Object. + + + + Resolves this instance. + + The type. + ``0. + + + + + + + + + + + + + Runs the startup tasks. + + . + + + + + + + Registers services/resources with the service collection that will be available via DI. + + Instance of the interface. + + + + Create services registered with the service container that need to be initialized at application startup. + + The configuration used to initialise the application. + A task representing the service initialization operation. + + + + Dirty hacks. + + + + + Finds plugin components and register them with the appropriate services. + + + + + Discovers the types. + + + + + Called when [configuration updated]. + + The sender. + The instance containing the event data. + + + + Validates the SSL certificate. + + The new configuration. + The certificate path doesn't exist. + + + + Notifies the kernel that a change has been made that requires a restart. + + + + + Gets the composable part assemblies. + + IEnumerable{Assembly}. + + + + + + + + + + + + + + + + + + + + + + Releases unmanaged and - optionally - managed resources. + + true to release both managed and unmanaged resources; false to release only unmanaged resources. + + + + A configuration factory for . + + + + + + + + The chapter manager. + + + + + The first chapter ticks. + + + + + Initializes a new instance of the class. + + The . + The . + The . + The . + The . + The . + + + + Determines whether [is eligible for chapter image extraction] [the specified video]. + + The video. + The library options for the video. + true if [is eligible for chapter image extraction] [the specified video]; otherwise, false. + + + + + + + + + + + + + + + + + + + + + + + + + + + + A collection image provider. + + + + + Initializes a new instance of the class. + + The filesystem. + The provider manager. + The application paths. + The image processor. + + + + + + + + + + + + + The collection manager. + + + + + Initializes a new instance of the class. + + The library manager. + The application paths. + The localization manager. + The filesystem. + The library monitor. + The logger factory. + The provider manager. + + + + + + + + + + + + + + + + + + + + + + + + + + + + Static class containing the default configuration options for the web server. + + + + + Gets a new copy of the default configuration options. + + + + + Class ServerConfigurationManager. + + + + + Initializes a new instance of the class. + + The application paths. + The logger factory. + The XML serializer. + + + + Configuration updating event. + + + + + Gets the type of the configuration. + + The type of the configuration. + + + + Gets the application paths. + + The application paths. + + + + Gets the configuration. + + The configuration. + + + + Called when [configuration updated]. + + + + + Updates the metadata path. + + If the directory does not exist, and the caller does not have the required permission to create it. + If there is a custom path transcoding path specified, but it is invalid. + If the directory does not exist, and it also could not be created. + + + + Replaces the configuration. + + The new configuration. + If the configuration path doesn't exist. + + + + Validates the metadata path. + + The new configuration. + The new config path doesn't exist. + + + + Class providing abstractions over cryptographic functions. + + + + + + + + + + + + + + Extracts and validates the iterations parameter from a password hash. + + The password hash containing parameters. + The number of iterations. + Thrown when iterations parameter is missing or invalid. + + + + + + + + + + + + + + + + + + + Class TypeMapper. + + + + + This holds all the types in the running assemblies + so that we can de-serialize properly when we don't have strong types. + + + + + Gets the type. + + Name of the type. + Type. + typeName is null. + + + + + + + TODO refactor this to use the new SetItemByNameInfo. + Some callers already have the counts extracted so no reason to retrieve them again. + + + + Attaches the user specific info. + + + + + Attaches People DTO's to a DTOBaseItem. + + The dto. + The item. + The requesting user. + + + + Attaches the studios. + + The dto. + The item. + + + + Sets simple property values on a DTOBaseItem. + + The dto. + The item. + The owner. + The options. + + + + Attaches the primary image aspect ratio. + + The dto. + The item. + + + + A responsible for notifying users when libraries are updated. + + + + + Initializes a new instance of the class. + + The . + The . + The . + The . + The . + The . + + + + + + + + + + + + + responsible for notifying users when associated item data is updated. + + + + + Initializes a new instance of the class. + + The . + The . + The . + + + + + + + + + + + + + Class WebSocketConnection. + Represents an authenticated WebSocket connection to a Jellyfin client. + + Authentication is performed during connection establishment in WebSocketManager. + The client must provide a valid API token via one of these methods: + - Query parameter: ws://server:8096/socket?api_key=TOKEN + - Authorization header: MediaBrowser Token="..." + - Legacy headers: X-Emby-Token or X-MediaBrowser-Token + + Once established, AuthorizationInfo contains the authenticated user/device information. + + + + + The logger. + + + + + The json serializer options. + + + + + The socket. + + + + + Initializes a new instance of the class. + + The logger. + The socket. + The authorization information containing authenticated user/device details. + The remote end point. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Releases unmanaged and - optionally - managed resources. + + true to release both managed and unmanaged resources; false to release only unmanaged resources. + + + + + + + Used to perform asynchronous cleanup of managed resources or for cascading calls to . + + A ValueTask. + + + + Manages WebSocket connections with authentication support. + + Clients should authenticate when connecting to WebSocket endpoints by providing an API token + through one of these methods: + + 1. Query String Parameter (Recommended): + - URL: ws://jellyfin-server:8096/socket?api_key=YOUR_API_TOKEN + - JavaScript: const ws = new WebSocket(`ws://jellyfin-server:8096/socket?api_key=${token}`); + + 2. Query String Parameter (Legacy): + - URL: ws://jellyfin-server:8096/socket?ApiKey=YOUR_API_TOKEN + + 3. Authorization Header: + - Header: MediaBrowser Device="...", Token="YOUR_API_TOKEN" + + The API token can be obtained from the server's API key management interface or + generated for specific clients/devices. + + + + + + + + Processes the web socket message received. + + The result. + + + + Class ArtistImageProvider. + + + + + Get children objects used to create an artist image. + + The artist used to create the image. + Any relevant children objects. + + + + + + + Class GenreImageProvider. + + + + + The library manager. + + + + + Get children objects used to create an genre image. + + The genre used to create the image. + Any relevant children objects. + + + + Class MusicGenreImageProvider. + + + + + The library manager. + + + + + Get children objects used to create an music genre image. + + The music genre used to create the image. + Any relevant children objects. + + + + Gets the affected base item. + + The path. + BaseItem. + + + + + + + + + + The file system watchers. + + + + + The affected paths. + + + + + A dynamic list of paths that should be ignored. Added to during our own file system modifications. + + + + + Initializes a new instance of the class. + + The logger. + The library manager. + The configuration manager. + The filesystem. + The . + + + + + + + + + + + + + Handles the ItemRemoved event of the LibraryManager control. + + The source of the event. + The instance containing the event data. + + + + Handles the ItemAdded event of the LibraryManager control. + + The source of the event. + The instance containing the event data. + + + + Examine a list of strings assumed to be file paths to see if it contains a parent of + the provided path. + + The LST. + The path. + true if [contains parent folder] [the specified LST]; otherwise, false. + is null. + + + + Starts the watching path. + + The path. + + + + Stops the watching path. + + The path. + + + + Disposes the watcher. + + + + + Handles the Error event of the watcher control. + + The source of the event. + The instance containing the event data. + + + + Handles the Changed event of the watcher control. + + The source of the event. + The instance containing the event data. + + + + + + + Stops this instance. + + + + + + + + Class ManagedFileSystem. + + + + + Initializes a new instance of the class. + + The instance to use. + The instance to use. + the 's to use. + + + + Determines whether the specified filename is shortcut. + + The filename. + true if the specified filename is shortcut; otherwise, false. + is null. + + + + Resolves the shortcut. + + The filename. + System.String. + is null. + + + + + + + Creates the shortcut. + + The shortcut path. + The target. + The shortcutPath or target is null. + + + + + + + Returns a object for the specified file or directory path. + + A path to a file or directory. + A object. + If the specified path points to a directory, the returned object's + property will be set to true and all other properties will reflect the properties of the directory. + + + + Returns a object for the specified file path. + + A path to a file. + A object. + If the specified path points to a directory, the returned object's + property and the property will both be set to false. + For automatic handling of files and directories, use . + + + + Returns a object for the specified directory path. + + A path to a directory. + A object. + If the specified path points to a file, the returned object's + property will be set to true and the property will be set to false. + For automatic handling of files and directories, use . + + + + Takes a filename and removes invalid characters. + + The filename. + System.String. + The filename is null. + + + + Gets the creation time UTC. + + The info. + DateTime. + + + + + + + + + + + + + Gets the creation time UTC. + + The info. + DateTime. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Specifies the contract for server startup options. + + + + + Gets the value of the --ffmpeg command line option. + + + + + Gets a value indicating whether to run as service by the --service command line option. + + + + + Gets the value of the --package-name command line option. + + + + + Gets the value of the --published-server-url command line option. + + + + + Provides the core resolver ignore rules. + + + + + Initializes a new instance of the class. + + The naming options. + The server application paths. + + + + + + + Resolver rule class for ignoring files via .ignore. + + + + + + + + Checks whether or not the file is ignored. + + The file information. + The parent BaseItem. + True if the file should be ignored. + + + + Checks whether a path should be ignored based on an array of ignore rules. + + The path to check. + The array of ignore rules. + Whether the path is a directory. + True if the path should be ignored. + + + + Checks whether a path should be ignored based on an array of ignore rules. + + The path to check. + The array of ignore rules. + Whether the path is a directory. + Whether to normalize backslashes to forward slashes (for Windows paths). + True if the path should be ignored. + + + + IExternalDataManager implementation. + + + + + Initializes a new instance of the class. + + The keyframe manager. + The media segment manager. + The path manager. + The trickplay manager. + The chapter manager. + The logger. + + + + + + + Glob patterns for files to ignore. + + + + + Files matching these glob patterns will be ignored. + + + + + Returns true if the supplied path should be ignored. + + The path to test. + Whether to ignore the path. + + + + Manager for Keyframe data. + + + + + Initializes a new instance of the class. + + The keyframe repository. + + + + + + + + + + + + + Class LibraryManager. + + + + + The _root folder sync lock. + + + + + The _root folder. + + + + + Initializes a new instance of the class. + + The application host. + The logger factory. + The task manager. + The user manager. + The configuration manager. + The user data manager. + The library monitor. + The file system. + The provider manager. + The user view manager. + The media encoder. + The item repository. + The image processor. + The naming options. + The directory service. + The people repository. + The path manager. + + + + Occurs when [item added]. + + + + + Occurs when [item updated]. + + + + + Occurs when [item removed]. + + + + + Gets the root folder. + + The root folder. + + + + Gets or sets the postscan tasks. + + The postscan tasks. + + + + Gets or sets the intro providers. + + The intro providers. + + + + Gets or sets the list of entity resolution ignore rules. + + The entity resolution ignore rules. + + + + Gets or sets the list of currently registered entity resolvers. + + The entity resolvers enumerable. + + + + Gets or sets the comparers. + + The comparers. + + + + Adds the parts. + + The rules. + The resolvers. + The intro providers. + The item comparers. + The post scan tasks. + + + + Records the configuration values. + + The configuration. + + + + Configurations the updated. + + The sender. + The instance containing the event data. + + + + Resolves the item. + + The args. + The resolvers. + BaseItem. + + + + Creates the root media folder. + + AggregateFolder. + Cannot create the root folder until plugins have loaded. + + + + + + + + + + Gets the studio. + + The name. + Task{Studio}. + + + + Gets the genre. + + The name. + Task{Genre}. + + + + Gets the music genre. + + The name. + Task{MusicGenre}. + + + + Gets the year. + + The value. + Task{Year}. + + + + Gets a Genre. + + The name. + Task{Genre}. + + + + + + + Reloads the root media folder. + + The progress. + The cancellation token. + Task. + + + + Validates the media library internal. + + The progress. + The cancellation token. + Task. + + + + Runs the post scan tasks. + + The progress. + The cancellation token. + Task. + + + + Gets the default view. + + IEnumerable{VirtualFolderInfo}. + + + + + + + + + + + + + + + + Gets the intros. + + The item. + The user. + IEnumerable{System.String}. + + + + Gets the intros. + + The provider. + The item. + The user. + Task<IEnumerable<IntroInfo>>. + + + + Resolves the intro. + + The info. + Video. + + + + + + + + + + Gets the comparer. + + The name. + The user. + IBaseItemComparer. + + + + + + + + + + + + + + + + + + + + + + Reports the item removed. + + The item. + The parent item. + + + + Retrieves the item. + + The id. + BaseItem. + + + + + + + + + + + + + + + + + + + Repository for persisting collection-folder library options in the database. + + + + + Initializes a new instance of the class. + + The db context factory. + The application host. + The logger. + + + + + + + + + + Gets library options from the database if the backing table is available. + + The collection folder path. + The cancellation token. + The expanded library options, or null if no row exists. + + + + Saves library options to the database if the backing table is available. + + The collection folder path. + The options to save. + The cancellation token. + A task representing the asynchronous operation. + + + + + + + + + > + + + + + + + + + + Releases unmanaged and - optionally - managed resources. + + true to release both managed and unmanaged resources; false to release only unmanaged resources. + + + + + + + Class providing extension methods for working with paths. + + + + + Gets the attribute value. + + The STR. + The attrib. + System.String. + or is empty. + + + + Replaces a sub path with another sub path and normalizes the final path. + + The original path. + The original sub path. + The new sub path. + The result of the sub path replacement. + The path after replacing the sub path. + , or is empty. + + + + Retrieves the full resolved path and normalizes path separators to the . + + The path to canonicalize. + The fully expanded, normalized path. + + + + Normalizes the path's directory separator character to the currently defined . + + The path to normalize. + The normalized path string or if the input path is null or empty. + + + + Normalizes the path's directory separator character. + + The path to normalize. + The separator character the path now uses or . + The normalized path string or if the input path is null or empty. + + + + Normalizes the path's directory separator character to the specified character. + + The path to normalize. + The replacement directory separator character. Must be a valid directory separator. + The normalized path. + Thrown if the new separator character is not a directory separator. + + + + IPathManager implementation. + + + + + Initializes a new instance of the class. + + The server configuration manager. + The application paths. + + + + + + + + + + + + + + + + + + + + + + + + + + + + Class ResolverHelper. + + + + + Sets the initial item values. + + The item. + The parent. + The library manager. + The directory service. + True if initializing was successful. + Item must have a path. + + + + Sets the initial item values. + + The item. + The args. + The file system. + The library manager. + + + + Ensures the name. + + + + + Ensures DateCreated and DateModified have values. + + The file system. + The item. + The args. + + + + Class AudioResolver. + + + + + Gets the priority. + + The priority. + + + + Resolves the specified args. + + The args. + Entities.Audio.Audio. + + + + The music album resolver. + + + + + Initializes a new instance of the class. + + The logger. + The naming options. + The directory service. + + + + Gets the priority. + + The priority. + + + + Resolves the specified args. + + The args. + MusicAlbum. + + + + Determine if the supplied file data points to a music album. + + The path to check. + The directory service. + true if the provided path points to a music album; otherwise, false. + + + + Determine if the supplied resolve args should be considered a music album. + + The args. + true if [is music album] [the specified args]; otherwise, false. + + + + Determine if the supplied list contains what we should consider music. + + true if the provided path list contains music; otherwise, false. + + + + The music artist resolver. + + + + + Initializes a new instance of the class. + + Instance of the interface. + The . + The directory service. + + + + Gets the priority. + + The priority. + + + + Resolves the specified resolver arguments. + + The resolver arguments. + A . + + + + Resolves a Path into a Video or Video subclass. + + The type of item to resolve. + + + + Resolves the specified args. + + The args. + `0. + + + + Resolves the video. + + The type of the T video type. + The args. + if set to true [parse name]. + ``0. + + + + Determines whether [is DVD directory] [the specified directory name]. + + The full path of the directory. + The name of the directory. + The directory service. + true if the provided directory is a DVD directory, false otherwise. + + + + Determines whether [is DVD file] [the specified name]. + + The name. + true if [is DVD file] [the specified name]; otherwise, false. + + + + Determines whether [is bluray directory] [the specified directory name]. + + The directory name. + Whether the directory is a bluray directory. + + + + Resolves a Path into a Video or Video subclass. + + + + + Initializes a new instance of the class. + + The logger. + An instance of . + The directory service. + + + + Gets the resolvers for the extra type. + + The extra type. + The resolvers for the extra type. + + + + Class FolderResolver. + + + + + Gets the priority. + + The priority. + + + + Resolves the specified args. + + The args. + Folder. + + + + Class FolderResolver. + + The type of the T item type. + + + + Sets the initial item values. + + The item. + The args. + + + + Resolves a Path into an instance of the class. + + The type of item to resolve. + + + + Initializes a new instance of the class. + + The logger. + The naming options. + The directory service. + + + + Class BoxSetResolver. + + + + + Resolves the specified args. + + The args. + BoxSet. + + + + Sets the initial item values. + + The item. + The args. + + + + Sets the provider id from path. + + The item. + + + + Class MovieResolver. + + + + + Initializes a new instance of the class. + + The image processor. + The logger. + The naming options. + The directory service. + + + + Gets the priority. + + The priority. + + + + Pattern:
+ \bsample\b
+ Options:
+ RegexOptions.IgnoreCase
+ Explanation:
+ + ○ Match if at a word boundary.
+ ○ Match a character in the set [Ss].
+ ○ Match a character in the set [Aa].
+ ○ Match a character in the set [Mm].
+ ○ Match a character in the set [Pp].
+ ○ Match a character in the set [Ll].
+ ○ Match a character in the set [Ee].
+ ○ Match if at a word boundary.
+
+
+
+ + + + + + Resolves the specified args. + + The args. + Video. + + + + Sets the initial item values. + + The item. + The args. + + + + Sets the provider id from path. + + The item. + + + + Finds a movie based on a child file system entries. + + Movie. + + + + Gets the multi disc movie. + + The folders. + The directory service. + ``0. + + + + Class PhotoAlbumResolver. + + + + + Initializes a new instance of the class. + + The image processor. + The naming options. + + + + + + + Resolves the specified args. + + The args. + Trailer. + + + + Class PhotoResolver. + + + + + Initializes a new instance of the class. + + The image processor. + The naming options. + The directory service. + + + + Resolves the specified args. + + The args. + Trailer. + + + + for library items. + + + + + + + + Gets the priority. + + The priority. + + + + Resolves the specified args. + + The args. + Folder. + + + + Class EpisodeResolver. + + + + + Initializes a new instance of the class. + + The logger. + The naming options. + The directory service. + + + + Resolves the specified args. + + The args. + Episode. + + + + Class SeasonResolver. + + + + + Initializes a new instance of the class. + + The naming options. + The localization. + The logger. + + + + Resolves the specified args. + + The args. + Season. + + + + Class SeriesResolver. + + + + + Initializes a new instance of the class. + + The logger. + The naming options. + + + + Gets the priority. + + The priority. + + + + Resolves the specified args. + + The args. + Series. + + + + Determines whether [is season folder] [the specified path]. + + The path. + The parentpath. + if set to true [is tv content type]. + true if [is season folder] [the specified path]; otherwise, false. + + + + Sets the initial item values. + + The item. + The args. + + + + Sets the provider id from path. + + The item. + The path. + + + + Gets the search hints. + + The query. + The user. + IEnumerable{SearchHintResult}. + query.SearchTerm is null or empty. + + + + The splashscreen post scan task. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + Class UserDataManager. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + Gets the internal key. + + System.String. + + + + + + + + + + + + + Converts a UserItemData to a DTOUserItemData. + + The data. + The reference key to an Item. + DtoUserItemData. + is null. + + + + + + + Class ArtistsPostScanTask. + + + + + The _library manager. + + + + + Initializes a new instance of the class. + + The library manager. + The logger. + The item repository. + + + + Runs the specified progress. + + The progress. + The cancellation token. + Task. + + + + Class ArtistsValidator. + + + + + The library manager. + + + + + The logger. + + + + + Initializes a new instance of the class. + + The library manager. + The logger. + The item repository. + + + + Runs the specified progress. + + The progress. + The cancellation token. + Task. + + + + Class CollectionPostScanTask. + + + + + Initializes a new instance of the class. + + The library manager. + The collection manager. + The logger. + + + + Runs the specified progress. + + The progress. + The cancellation token. + Task. + + + + Class GenresPostScanTask. + + + + + The _library manager. + + + + + Initializes a new instance of the class. + + The library manager. + The logger. + The item repository. + + + + Runs the specified progress. + + The progress. + The cancellation token. + Task. + + + + Class GenresValidator. + + + + + The library manager. + + + + + The logger. + + + + + Initializes a new instance of the class. + + The library manager. + The logger. + The item repository. + + + + Runs the specified progress. + + The progress. + The cancellation token. + Task. + + + + Class MusicGenresPostScanTask. + + + + + The library manager. + + + + + Initializes a new instance of the class. + + The library manager. + The logger. + The item repository. + + + + Runs the specified progress. + + The progress. + The cancellation token. + Task. + + + + Class MusicGenresValidator. + + + + + The library manager. + + + + + The logger. + + + + + Initializes a new instance of the class. + + The library manager. + The logger. + The item repository. + + + + Runs the specified progress. + + The progress. + The cancellation token. + Task. + + + + Class PeopleValidator. + + + + + The _library manager. + + + + + The _logger. + + + + + Initializes a new instance of the class. + + The library manager. + The logger. + The file system. + + + + Validates the people. + + The cancellation token. + The progress. + Task. + + + + Class MusicGenresPostScanTask. + + + + + The _library manager. + + + + + Initializes a new instance of the class. + + The library manager. + The logger. + The item repository. + + + + Runs the specified progress. + + The progress. + The cancellation token. + Task. + + + + Class StudiosValidator. + + + + + The library manager. + + + + + The logger. + + + + + Initializes a new instance of the class. + + The library manager. + The logger. + The item repository. + + + + Runs the specified progress. + + The progress. + The cancellation token. + Task. + + + + Class LocalizationManager. + + + + + Initializes a new instance of the class. + + The configuration manager. + The logger. + + + + Loads all resources into memory. + + . + + + + Gets the cultures. + + . + + + + + + + + + + + + + Gets the parental ratings dictionary. + + The optional two letter ISO language string. + . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A custom for loading Jellyfin plugins. + + + + + Initializes a new instance of the class. + + The path of the plugin assembly. + + + + + + + Defines the . + + + + + Initializes a new instance of the class. + + The . + The . + The . + The plugin path. + The application version. + + + + Gets the Plugins. + + + + + Returns all the assemblies. + + An IEnumerable{Assembly}. + + + + Creates all the plugin instances. + + + + + Registers the plugin's services with the DI. + Note: DI is not yet instantiated yet. + + A instance. + + + + Imports a plugin manifest from . + + Folder of the plugin. + + + + Removes the plugin reference '. + + The plugin. + Outcome of the operation. + + + + Attempts to find the plugin with and id of . + + The of plugin. + Optional of the plugin to locate. + A if located, or null if not. + + + + Enables the plugin, disabling all other versions. + + The of the plug to disable. + + + + Disable the plugin. + + The of the plug to disable. + + + + Disable the plugin. + + The of the plug to disable. + + + + + + + + + + + + + Reconciles the manifest against any properties that exist locally in a pre-packaged meta.json found at the path. + If no file is found, no reconciliation occurs. + + The to reconcile against. + The plugin path. + The reconciled . + + + + Changes a plugin's load status. + + The instance. + The of the plugin. + Success of the task. + + + + Finds the plugin record using the assembly. + + The being sought. + The matching record, or null if not found. + + + + Creates the instance safe. + + The type. + System.Object. + + + + Attempts to delete a plugin. + + A instance to delete. + True if successful. + + + + Gets the list of local plugins. + + Enumerable of local plugins. + + + + Attempts to retrieve valid DLLs from the plugin path. This method will consider the assembly whitelist + from the manifest. + + + Loading DLLs from externally supplied paths introduces a path traversal risk. This method + uses a safelisting tactic of considering DLLs from the plugin directory and only using + the plugin's canonicalized assembly whitelist for comparison. See + for more details. + + The plugin. + The whitelisted DLLs. If the method returns , this will be empty. + + if all assemblies listed in the manifest were available in the plugin directory. + if any assemblies were invalid or missing from the plugin directory. + + If the is null. + + + + Changes the status of the other versions of the plugin to "Superseded". + + The that's master. + + + + Quick connect implementation. + + + + + The length of user facing codes. + + + + + The time (in minutes) that the quick connect token is valid. + + + + + Initializes a new instance of the class. + Should only be called at server startup when a singleton is created. + + Configuration. + Logger. + Session Manager. + + + + + + + Assert that quick connect is currently active and throws an exception if it is not. + + + + + + + + + + + Generates a short code to display to the user to uniquely identify this request. + + A short, unique alphanumeric string. + + + + + + + + + + Expire quick connect requests that are over the time limit. If is true, all requests are unconditionally expired. + + If true, all requests will be expired. + + + + Class ScheduledTaskWorker. + + + + + Initializes a new instance of the class. + + The scheduled task. + The application paths. + The task manager. + The logger. + + scheduledTask + or + applicationPaths + or + taskManager + or + jsonSerializer + or + logger. + + + + + + + + + + + + + + + + + + + + + + + Gets or sets the current cancellation token. + + The current cancellation token source. + + + + Gets or sets the current execution start time. + + The current execution start time. + + + + + + + + + + Gets or sets the triggers that define when the task will run. + + The triggers. + + + + + + + + + + + + + Reloads the trigger events. + + if set to true [is application startup]. + + + + Handles the Triggered event of the trigger control. + + The source of the event. + The instance containing the event data. + + + + Executes the task. + + Task options. + Task. + Cannot execute a Task that is already running. + + + + Progress_s the progress changed. + + The sender. + The e. + + + + Stops the task if it is currently executing. + + Cannot cancel a Task unless it is in the Running state. + + + + Cancels if running. + + + + + Gets the scheduled tasks configuration directory. + + System.String. + + + + Gets the scheduled tasks data directory. + + System.String. + + + + Gets the history file path. + + The history file path. + + + + Gets the configuration file path. + + System.String. + + + + Loads the triggers. + + IEnumerable{BaseTaskTrigger}. + + + + Saves the triggers. + + The triggers. + + + + Called when [task completed]. + + The start time. + The end time. + The status. + The exception. + + + + + + + Releases unmanaged and - optionally - managed resources. + + true to release both managed and unmanaged resources; false to release only unmanaged resources. + + + + Converts a TaskTriggerInfo into a concrete BaseTaskTrigger. + + The info. + BaseTaskTrigger. + Invalid trigger type: + info.Type. + + + + Disposes each trigger. + + + + + Class TaskManager. + + + + + The _task queue. + + + + + Initializes a new instance of the class. + + The application paths. + The logger. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Queues the scheduled task. + + The task. + The task options. + + + + + + + + + + Releases unmanaged and - optionally - managed resources. + + true to release both managed and unmanaged resources; false to release only unmanaged resources. + + + + + + + + + + Called when [task executing]. + + The task. + + + + Called when [task completed]. + + The task. + The result. + + + + Executes the queued tasks. + + + + + The audio normalization task. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + + + + Pattern:
+ ^\s+I:\s+(.*?)\s+LUFS
+ Explanation:
+ + ○ Match if at the beginning of the string.
+ ○ Match a whitespace character atomically at least once.
+ ○ Match the string "I:".
+ ○ Match a whitespace character greedily at least once.
+ ○ 1st capture group.
+ ○ Match a character other than '\n' lazily any number of times.
+ ○ Match a whitespace character atomically at least once.
+ ○ Match the string "LUFS".
+
+
+
+ + + + + + + + + Class ChapterImagesTask. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + + + + + + + + + + Deletes old activity log entries. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deletes path references from collections and playlists that no longer exists. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + + + + + + + + + + Task to clean up any detached userdata from the database. + + + + + Initializes a new instance of the class. + + The localisation Provider. + The DB context factory. + A logger. + + + + + + + + + + + + + + + + + + + + + + Deletes old cache files. + + + + + Gets or sets the application paths. + + The application paths. + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deletes the cache files from directory with a last write time less than a given date. + + The directory. + The min date modified. + The progress. + The task cancellation token. + + + + Deletes old log files. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deletes all transcoding temp files. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Deletes the transcoded temp files from directory with a last write time less than a given date. + + The directory. + The min date modified. + The progress. + The task cancellation token. + + + + Task to obtain media segments. + + + + + The library manager. + + + + + Initializes a new instance of the class. + + The library manager. + The localization manager. + The segment manager. + + + + + + + + + + + + + + + + + + + + + + Optimizes Jellyfin's database by issuing a VACUUM command. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the JellyfinDatabaseProvider that can be used for provider specific operations. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Class PeopleValidationTask. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + + + + + + + + + + + + + Creates the triggers that define when the task will run. + + An containing the default trigger infos for this task. + + + + + + + Plugin Update Task. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Class RefreshMediaLibraryTask. + + + + + The _library manager. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + + + + + + + + + + Represents a task trigger that fires everyday. + + + + + Initializes a new instance of the class. + + The time of day to trigger the task to run. + The options of this task. + + + + + + + + + + + + + + + + Disposes the timer. + + + + + Called when [triggered]. + + + + + + + + Represents a task trigger that runs repeatedly on an interval. + + + + + Initializes a new instance of the class. + + The interval. + The options of this task. + + + + + + + + + + + + + + + + Disposes the timer. + + + + + Called when [triggered]. + + + + + + + + Class StartupTaskTrigger. + + + + + Initializes a new instance of the class. + + The options of this task. + + + + + + + + + + + + + + + + Called when [triggered]. + + + + + Represents a task trigger that fires on a weekly basis. + + + + + Initializes a new instance of the class. + + The time of day to trigger the task to run. + The day of week. + The options of this task. + + + + + + + + + + + + + Gets the next trigger date time. + + DateTime. + + + + + + + Disposes the timer. + + + + + Called when [triggered]. + + + + + + + + Provides a wrapper around third party xml serialization. + + + + + Serializes to writer. + + The obj. + The writer. + + + + Deserializes from stream. + + The type. + The stream. + System.Object. + + + + Serializes to stream. + + The obj. + The stream. + + + + Serializes to file. + + The obj. + The file. + + + + Deserializes from file. + + The type. + The file. + System.Object. + + + + Deserializes from bytes. + + The type. + The buffer. + System.Object. + + + + Extends BaseApplicationPaths to add paths that are only applicable on the server. + + + + + Initializes a new instance of the class. + + The path for Jellyfin's data. + The path for Jellyfin's logging directory. + The path for Jellyfin's configuration directory. + The path for Jellyfin's cache directory. + The path for Jellyfin's web UI. + The path for Jellyfin's temp files. + + + + Gets the path to the base root media directory. + + The root folder path. + + + + Gets the path to the default user view directory. Used if no specific user view is defined. + + The default user views path. + + + + Gets the path to the People directory. + + The people path. + + + + + + + Gets the path to the Genre directory. + + The genre path. + + + + Gets the path to the Genre directory. + + The genre path. + + + + Gets the path to the Studio directory. + + The studio path. + + + + Gets the path to the Year directory. + + The year path. + + + + Gets the path to the user configuration directory. + + The user configuration directory path. + + + + + + + + + + + + + + + + Class SessionManager. + + + + + Initializes a new instance of the class. + + Instance of interface. + Instance of interface. + Instance of interface. + Instance of interface. + Instance of interface. + Instance of interface. + Instance of interface. + Instance of interface. + Instance of interface. + Instance of interface. + Instance of interface. + Instance of interface. + Instance of interface. + + + + Occurs when playback has started. + + + + + Occurs when playback has progressed. + + + + + Occurs when playback has stopped. + + + + + + + + + + + + + + + + + + + + Gets all connections. + + All connections. + + + + + + + Logs the user activity. + + Type of the client. + The app version. + The device id. + Name of the device. + The remote end point. + The user. + SessionInfo. + + + + + + + + + + + + + + + + Updates the now playing item id. + + Task. + + + + Removes the now playing item id. + + The session. + + + + Gets the connection. + + Type of the client. + The app version. + The device id. + Name of the device. + The remote end point. + The user. + SessionInfo. + + + + Used to report that playback has started for an item. + + The info. + Task. + info is null. + + + + Called when [playback start]. + + The user object. + The item. + + + + + + + Used to report playback progress for an item. + + The playback progress info. + Whether this is an automated update. + Task. + + + + Used to report that playback has ended for an item. + + The info. + Task. + info is null. + info.PositionTicks is null or negative. + + + + Gets the session. + + The session identifier. + if set to true [throw on missing]. + SessionInfo. + + No session with an Id equal to sessionId was found + and throwOnMissing is true. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sends the restart required message. + + The cancellation token. + Task. + + + + Adds the additional user. + + The session identifier. + The user identifier. + Cannot modify additional users without authenticating first. + The requested user is already the primary user of the session. + + + + Removes the additional user. + + The session identifier. + The user identifier. + Cannot modify additional users without authenticating first. + The requested user is already the primary user of the session. + + + + Authenticates the new session. + + The authenticationrequest. + The authentication result. + + + + Directly authenticates the session without enforcing password. + + The authentication request. + The authentication result. + + + + + + + + + + + + + Reports the capabilities. + + The session identifier. + The capabilities. + + + + Converts a BaseItem to a BaseItemInfo. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Class SessionWebSocketListener. + + + + + The timeout in seconds after which a WebSocket is considered to be lost. + + + + + The keep-alive interval factor; controls how often the watcher will check on the status of the WebSockets. + + + + + The ForceKeepAlive factor; controls when a ForceKeepAlive is sent. + + + + + The WebSocket watchlist. + + + + + Lock used for accessing the WebSockets watchlist. + + + + + The KeepAlive cancellation token. + + + + + Initializes a new instance of the class. + + The logger. + The session manager. + The user manager. + The logger factory. + + + + + + + Processes the message. + + The message. + Task. + + + + + + + Called when a WebSocket is closed. + + The WebSocket. + The event arguments. + + + + Adds a WebSocket to the KeepAlive watchlist. + + The WebSocket to monitor. + + + + Removes a WebSocket from the KeepAlive watchlist. + + The WebSocket to remove. + + + + Checks status of KeepAlive of WebSockets. + + + + + Sends a ForceKeepAlive message to a WebSocket. + + The WebSocket. + Task. + + + + + + + + + + + + + + + + Gets the name. + + The name. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Allows comparing artists of albums. Only the first artist of each album is considered. + + + + + Gets the item type this comparer compares. + + + + + Compares the specified arguments on their primary artist. + + First item to compare. + Second item to compare. + Zero if equal, else negative or positive number to indicate order. + + + + Class AlbumComparer. + + + + + Gets the name. + + The name. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Gets the value. + + The x. + System.String. + + + + Class ArtistComparer. + + + + + + + + + + + Gets the value. + + The x. + System.String. + + + + Gets the name. + + The name. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Class CriticRatingComparer. + + + + + Gets the name. + + The name. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Class DateCreatedComparer. + + + + + Gets the name. + + The name. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Gets or sets the user. + + The user. + + + + Gets or sets the user manager. + + The user manager. + + + + Gets or sets the user data manager. + + The user data manager. + + + + Gets the name. + + The name. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Gets the date. + + The x. + DateTime. + + + + Class DatePlayedComparer. + + + + + Gets or sets the user. + + The user. + + + + Gets or sets the user manager. + + The user manager. + + + + Gets or sets the user data manager. + + The user data manager. + + + + Gets the name. + + The name. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Gets the date. + + The x. + DateTime. + + + + Class IndexNumberComparer. + + + + + Gets the name. + + The name. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Gets or sets the user. + + The user. + + + + Gets the name. + + The name. + + + + Gets or sets the user data manager. + + The user data manager. + + + + Gets or sets the user manager. + + The user manager. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Gets the date. + + The x. + DateTime. + + + + Gets the name. + + The name. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Gets the value. + + The x. + System.String. + + + + Gets or sets the user. + + The user. + + + + Gets the name. + + The name. + + + + Gets or sets the user data manager. + + The user data manager. + + + + Gets or sets the user manager. + + The user manager. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Gets the date. + + The x. + DateTime. + + + + Gets or sets the user. + + The user. + + + + Gets the name. + + The name. + + + + Gets or sets the user data manager. + + The user data manager. + + + + Gets or sets the user manager. + + The user manager. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Gets the date. + + The x. + DateTime. + + + + Class NameComparer. + + + + + Gets the name. + + The name. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Class providing comparison for official ratings. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + Gets the name. + + The name. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Class ParentIndexNumberComparer. + + + + + Gets the name. + + The name. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Class PlayCountComparer. + + + + + Gets or sets the user. + + The user. + + + + Gets the name. + + The name. + + + + Gets or sets the user data manager. + + The user data manager. + + + + Gets or sets the user manager. + + The user manager. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Gets the date. + + The x. + DateTime. + + + + Class PremiereDateComparer. + + + + + Gets the name. + + The name. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Gets the date. + + The x. + DateTime. + + + + Class ProductionYearComparer. + + + + + Gets the name. + + The name. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Gets the date. + + The x. + DateTime. + + + + Class RandomComparer. + + + + + Gets the name. + + The name. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Class RuntimeComparer. + + + + + Gets the name. + + The name. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Gets the name. + + The name. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Class SortNameComparer. + + + + + Gets the name. + + The name. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Gets the name. + + The name. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Gets the date. + + The x. + DateTime. + + + + Gets the name. + + The name. + + + + Compares the specified x. + + The x. + The y. + System.Int32. + + + + Class Group. + + + Class is not thread-safe, external locking is required when accessing methods. + + + + + The logger. + + + + + The logger factory. + + + + + The user manager. + + + + + The session manager. + + + + + The library manager. + + + + + The participants, or members of the group. + + + + + The internal group state. + + + + + Initializes a new instance of the class. + + The logger factory. + The user manager. + The session manager. + The library manager. + + + + Gets the default ping value used for sessions. + + The default ping. + + + + Gets the maximum time offset error accepted for dates reported by clients, in milliseconds. + + The maximum time offset error. + + + + Gets the maximum offset error accepted for position reported by clients, in milliseconds. + + The maximum offset error. + + + + Gets the group identifier. + + The group identifier. + + + + Gets the group name. + + The group name. + + + + Gets the group identifier. + + The group identifier. + + + + Gets the runtime ticks of current playing item. + + The runtime ticks of current playing item. + + + + Gets or sets the position ticks. + + The position ticks. + + + + Gets or sets the last activity. + + The last activity. + + + + Adds the session to the group. + + The session. + + + + Removes the session from the group. + + The session. + + + + Filters sessions of this group. + + The current session identifier. + The filtering type. + The list of sessions matching the filter. + + + + Checks if a given user can access all items of a given queue, that is, + the user has the required minimum parental access and has access to all required folders. + + The user. + The queue. + true if the user can access all the items in the queue, false otherwise. + + + + Checks if the group is empty. + + true if the group is empty, false otherwise. + + + + Initializes the group with the session's info. + + The session. + The request. + The cancellation token. + + + + Adds the session to the group. + + The session. + The request. + The cancellation token. + + + + Removes the session from the group. + + The session. + The request. + The cancellation token. + + + + Handles the requested action by the session. + + The session. + The requested action. + The cancellation token. + + + + Gets the info about the group for the clients. + + The group info for the clients. + + + + Checks if a user has access to all content in the play queue. + + The user. + true if the user can access the play queue; false otherwise. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Class SyncPlayManager. + + + + + The logger. + + + + + The logger factory. + + + + + The user manager. + + + + + The session manager. + + + + + The library manager. + + + + + The map between users and counter of active sessions. + + + + + The map between sessions and groups. + + + + + The groups. + + + + + Lock used for accessing multiple groups at once. + + + This lock has priority on locks made on . + + + + + Initializes a new instance of the class. + + The logger factory. + The user manager. + The session manager. + The library manager. + + + + + + + + + + + + + + + + + + + + + + + + + + + + Releases unmanaged and optionally managed resources. + + true to release both managed and unmanaged resources; false to release only unmanaged resources. + + + + + + + Initializes a new instance of the class. + + Instance of . + Instance of . + Instance of . + Instance of . + Instance of . + Instance of . + Instance of . + + + + + + + + + + + + + + + + + + + Gets the next up. + + Task{Episode}. + + + + Manages all install, uninstall, and update operations for the system and individual plugins. + + + + + The logger. + + + + + Gets the application host. + + The application host. + + + + The current installations. + + + + + The completed installations. + + + + + Initializes a new instance of the class. + + The . + The . + The . + The . + The . + The . + The . + + + + + + + + + + + + + + + + + + + + + + + + + Uninstalls a plugin. + + The to uninstall. + + + + + + + + + + Releases unmanaged and optionally managed resources. + + true to release both managed and unmanaged resources or false to release only unmanaged resources. + + + + Merges two sorted lists. + + The source instance to merge. + The destination instance to merge with. + + + Custom -derived type for the IsIgnoredRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Custom -derived type for the LUFSRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Helper methods used by generated -derived implementations. + + + Default timeout value set in , or if none was set. + + + Whether is non-infinite. + + + Determines whether the specified index is a boundary word character. + This is the same as \w plus U+200C ZERO WIDTH NON-JOINER and U+200D ZERO WIDTH JOINER. + + + Determines whether the specified index is a boundary. + This variant is only employed when the previous character has already been validated as a word character. + + + Determines whether the specified index is a boundary. + This variant is only employed when the subsequent character will separately be validated as a word character. + + + Provides a mask of Unicode categories that combine to form [\w]. + + + Gets a bitmap for whether each character 0 through 127 is in [\w] + + + Supports searching for the string "sample". + +
+
diff --git a/publish/Jellyfin.Api.xml b/publish/Jellyfin.Api.xml new file mode 100644 index 00000000..4f6eb7d3 --- /dev/null +++ b/publish/Jellyfin.Api.xml @@ -0,0 +1,8824 @@ + + + + Jellyfin.Api + + + + + Internal produces image attribute. + + + + + Initializes a new instance of the class. + + Content types this endpoint produces. + + + + Gets the configured content types. + + the configured content types. + + + + Produces file attribute of "image/*". + + + + + Initializes a new instance of the class. + + + + + Attribute to mark a parameter as obsolete. + + + + + Produces file attribute of "image/*". + + + + + Initializes a new instance of the class. + + + + + Internal produces image attribute. + + + + + Initializes a new instance of the class. + + Content types this endpoint produces. + + + + Gets the configured content types. + + the configured content types. + + + + Produces file attribute of "image/*". + + + + + Initializes a new instance of the class. + + + + + Produces file attribute of "image/*". + + + + + Initializes a new instance of the class. + + + + + Produces file attribute of "video/*". + + + + + Initializes a new instance of the class. + + + + + LAN access handler. Allows anonymous users. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + + + + + The local network authorization requirement. Allows anonymous users. + + + + + Custom authentication handler wrapping the legacy authentication. + + + + + Initializes a new instance of the class. + + The jellyfin authentication service. + Options monitor. + The logger. + The url encoder. + + + + + + + Default authorization handler. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + The default authorization requirement. + + + + + Initializes a new instance of the class. + + A value indicating whether to validate parental schedule. + + + + Gets a value indicating whether to ignore parental schedule. + + + + + Authorization handler for requiring first time setup or default privileges. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + The authorization requirement, requiring incomplete first time setup or default privileges, for the authorization handler. + + + + + Initializes a new instance of the class. + + A value indicating whether to ignore parental schedule. + A value indicating whether administrator role is required. + + + + Gets a value indicating whether administrator role is required. + + + + + Local access or require elevated privileges handler. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + + + + + The local access or elevated privileges authorization requirement. + + + + + Default authorization handler. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + The default authorization requirement. + + + + + Initializes a new instance of the class. + + A value of . + + + + Gets the required SyncPlay access. + + + + + User permission authorization handler. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + The user permission requirement. + + + + + Initializes a new instance of the class. + + The required . + Whether to validate the user's parental schedule. + + + + Gets the required user permission. + + + + + Base api controller for the API setting a default route. + + + + + Create a new . + + The value to return. + The type to return. + The . + + + + Create a new . + + The value to return. + The type to return. + The . + + + + Authentication schemes for user authentication in the API. + + + + + Scheme name for the custom legacy authentication. + + + + + Internal claim types for authorization. + + + + + User Id. + + + + + Device Id. + + + + + Device. + + + + + Client. + + + + + Version. + + + + + Token. + + + + + Is Api Key. + + + + + Constants for user roles used in the authentication and authorization for the API. + + + + + Guest user. + + + + + Regular user with no special privileges. + + + + + Administrator user with elevated privileges. + + + + + Activity log controller. + + + + + Initializes a new instance of the class. + + Instance of interface. + + + + Gets activity log entries. + + The record index to start at. All items with a lower index will be dropped from the results. + The maximum number of records to return. + The minimum date. + The maximum date. + Filter log entries if it has user id, or not. + Filter by name. + Filter by overview. + Filter by short overview. + Filter by type. + Filter by item id. + Filter by username. + Filter by log severity. + Specify one or more sort orders. Format: SortBy=Name,Type. + Sort Order.. + Activity log returned. + A containing the log entries. + + + + Authentication controller. + + + + + Initializes a new instance of the class. + + Instance of interface. + + + + Get all keys. + + Api keys retrieved. + A with all keys. + + + + Create a new api key. + + Name of the app using the authentication key. + Api key created. + A . + + + + Remove an api key. + + The access token to delete. + Api key deleted. + A . + + + + The artists controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Gets all artists from a given item, folder, or the entire library. + + Optional filter by minimum community rating. + Optional. The record index to start at. All items with a lower index will be dropped from the results. + Optional. The maximum number of records to return. + Optional. Search term. + Specify this to localize the search to a specific item or folder. Omit to use the root. + Optional. Specify additional fields of information to return in the output. + Optional. If specified, results will be filtered out based on item type. This allows multiple, comma delimited. + Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited. + Optional. Specify additional filters to apply. + Optional filter by items that are marked as favorite, or not. + Optional filter by MediaType. Allows multiple, comma delimited. + Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on genre id. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on OfficialRating. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on tag. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on production year. This allows multiple, comma delimited. + Optional, include user data. + Optional, the max number of images to return, per image type. + Optional. The image types to include in the output. + Optional. If specified, results will be filtered to include only those containing the specified person. + Optional. If specified, results will be filtered to include only those containing the specified person ids. + Optional. If specified, along with Person, results will be filtered to include only those containing the specified person and PersonType. Allows multiple, comma-delimited. + Optional. If specified, results will be filtered based on studio. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on studio id. This allows multiple, pipe delimited. + User id. + Optional filter by items whose name is sorted equally or greater than a given input string. + Optional filter by items whose name is sorted equally than a given input string. + Optional filter by items whose name is equally or lesser than a given input string. + Optional. Specify one or more sort orders, comma delimited. + Sort Order - Ascending,Descending. + Optional, include image information in output. + Total record count. + Artists returned. + An containing the artists. + + + + Gets all album artists from a given item, folder, or the entire library. + + Optional filter by minimum community rating. + Optional. The record index to start at. All items with a lower index will be dropped from the results. + Optional. The maximum number of records to return. + Optional. Search term. + Specify this to localize the search to a specific item or folder. Omit to use the root. + Optional. Specify additional fields of information to return in the output. + Optional. If specified, results will be filtered out based on item type. This allows multiple, comma delimited. + Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited. + Optional. Specify additional filters to apply. + Optional filter by items that are marked as favorite, or not. + Optional filter by MediaType. Allows multiple, comma delimited. + Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on genre id. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on OfficialRating. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on tag. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on production year. This allows multiple, comma delimited. + Optional, include user data. + Optional, the max number of images to return, per image type. + Optional. The image types to include in the output. + Optional. If specified, results will be filtered to include only those containing the specified person. + Optional. If specified, results will be filtered to include only those containing the specified person ids. + Optional. If specified, along with Person, results will be filtered to include only those containing the specified person and PersonType. Allows multiple, comma-delimited. + Optional. If specified, results will be filtered based on studio. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on studio id. This allows multiple, pipe delimited. + User id. + Optional filter by items whose name is sorted equally or greater than a given input string. + Optional filter by items whose name is sorted equally than a given input string. + Optional filter by items whose name is equally or lesser than a given input string. + Optional. Specify one or more sort orders, comma delimited. + Sort Order - Ascending,Descending. + Optional, include image information in output. + Total record count. + Album artists returned. + An containing the album artists. + + + + Gets an artist by name. + + Studio name. + Optional. Filter by user id, and attach user data. + Artist returned. + An containing the artist. + + + + The audio controller. + + + + + Initializes a new instance of the class. + + Instance of . + + + + Gets an audio stream. + + The item id. + The audio container. + Optional. If true, the original file will be streamed statically without any encoding. Use either no url extension or the original file extension. true/false. + The streaming parameters. + The tag. + Optional. The dlna device profile id to utilize. + The play session id. + The segment container. + The segment length. + The minimum number of segments. + The media version id, if playing an alternate version. + The device id of the client requesting. Used to stop encoding processes when needed. + Optional. Specify an audio codec to encode to, e.g. mp3. If omitted the server will auto-select using the url's extension. + Whether or not to allow automatic stream copy if requested values match the original source. Defaults to true. + Whether or not to allow copying of the video stream url. + Whether or not to allow copying of the audio stream url. + Optional. Specify a specific audio sample rate, e.g. 44100. + Optional. The maximum audio bit depth. + Optional. Specify an audio bitrate to encode to, e.g. 128000. If omitted this will be left to encoder defaults. + Optional. Specify a specific number of audio channels to encode to, e.g. 2. + Optional. Specify a maximum number of audio channels to encode to, e.g. 2. + Optional. Specify a specific an encoder profile (varies by encoder), e.g. main, baseline, high. + Optional. Specify a level for the encoder profile (varies by encoder), e.g. 3, 3.1. + Optional. A specific video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements. + Optional. A specific maximum video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements. + Whether or not to copy timestamps when transcoding with an offset. Defaults to false. + Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms. + Optional. The fixed horizontal resolution of the encoded video. + Optional. The fixed vertical resolution of the encoded video. + Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be left to encoder defaults. + Optional. The index of the subtitle stream to use. If omitted no subtitles will be used. + Optional. Specify the subtitle delivery method. + Optional. + Optional. The maximum video bit depth. + Optional. Whether to require avc. + Optional. Whether to deinterlace the video. + Optional. Whether to require a non anamorphic stream. + Optional. The maximum number of audio channels to transcode. + Optional. The limit of how many cpu cores to use. + The live stream id. + Optional. Whether to enable the MpegtsM2Ts mode. + Optional. Specify a video codec to encode to, e.g. h264. If omitted the server will auto-select using the url's extension. + Optional. Specify a subtitle codec to encode to. + Optional. The transcoding reason. + Optional. The index of the audio stream to use. If omitted the first audio stream will be used. + Optional. The index of the video stream to use. If omitted the first video stream will be used. + Optional. The . + Optional. The streaming options. + Optional. Whether to enable Audio Encoding. + Audio stream returned. + A containing the audio file. + + + + Gets an audio stream. + + The item id. + The audio container. + Optional. If true, the original file will be streamed statically without any encoding. Use either no url extension or the original file extension. true/false. + The streaming parameters. + The tag. + Optional. The dlna device profile id to utilize. + The play session id. + The segment container. + The segment length. + The minimum number of segments. + The media version id, if playing an alternate version. + The device id of the client requesting. Used to stop encoding processes when needed. + Optional. Specify an audio codec to encode to, e.g. mp3. If omitted the server will auto-select using the url's extension. + Whether or not to allow automatic stream copy if requested values match the original source. Defaults to true. + Whether or not to allow copying of the video stream url. + Whether or not to allow copying of the audio stream url. + Optional. Specify a specific audio sample rate, e.g. 44100. + Optional. The maximum audio bit depth. + Optional. Specify an audio bitrate to encode to, e.g. 128000. If omitted this will be left to encoder defaults. + Optional. Specify a specific number of audio channels to encode to, e.g. 2. + Optional. Specify a maximum number of audio channels to encode to, e.g. 2. + Optional. Specify a specific an encoder profile (varies by encoder), e.g. main, baseline, high. + Optional. Specify a level for the encoder profile (varies by encoder), e.g. 3, 3.1. + Optional. A specific video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements. + Optional. A specific maximum video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements. + Whether or not to copy timestamps when transcoding with an offset. Defaults to false. + Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms. + Optional. The fixed horizontal resolution of the encoded video. + Optional. The fixed vertical resolution of the encoded video. + Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be left to encoder defaults. + Optional. The index of the subtitle stream to use. If omitted no subtitles will be used. + Optional. Specify the subtitle delivery method. + Optional. + Optional. The maximum video bit depth. + Optional. Whether to require avc. + Optional. Whether to deinterlace the video. + Optional. Whether to require a non anamorphic stream. + Optional. The maximum number of audio channels to transcode. + Optional. The limit of how many cpu cores to use. + The live stream id. + Optional. Whether to enable the MpegtsM2Ts mode. + Optional. Specify a video codec to encode to, e.g. h264. If omitted the server will auto-select using the url's extension. + Optional. Specify a subtitle codec to encode to. + Optional. The transcoding reason. + Optional. The index of the audio stream to use. If omitted the first audio stream will be used. + Optional. The index of the video stream to use. If omitted the first video stream will be used. + Optional. The . + Optional. The streaming options. + Optional. Whether to enable Audio Encoding. + Audio stream returned. + A containing the audio file. + + + + The backup controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + + Creates a new Backup. + + The backup options. + Backup created. + User does not have permission to retrieve information. + The created backup manifest. + + + + Restores to a backup by restarting the server and applying the backup. + + The data to start a restore process. + Backup restore started. + User does not have permission to retrieve information. + No-Content. + + + + Gets a list of all currently present backups in the backup directory. + + Backups available. + User does not have permission to retrieve information. + The list of backups. + + + + Gets the descriptor from an existing archive is present. + + The data to start a restore process. + Backup archive manifest. + Not a valid jellyfin Archive. + Not a valid path. + User does not have permission to retrieve information. + The backup manifest. + + + + Branding controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + Gets branding configuration. + + Branding configuration returned. + An containing the branding configuration. + + + + Gets branding css. + + Branding css returned. + No branding css configured. + + An containing the branding css if exist, + or a if the css is not configured. + + + + + Channels Controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + + Gets available channels. + + User Id to filter by. Use to not filter by user. + Optional. The record index to start at. All items with a lower index will be dropped from the results. + Optional. The maximum number of records to return. + Optional. Filter by channels that support getting latest items. + Optional. Filter by channels that support media deletion. + Optional. Filter by channels that are favorite. + Channels returned. + An containing the channels. + + + + Get all channel features. + + All channel features returned. + An containing the channel features. + + + + Get channel features. + + Channel id. + Channel features returned. + An containing the channel features. + + + + Get channel items. + + Channel Id. + Optional. Folder Id. + Optional. User Id. + Optional. The record index to start at. All items with a lower index will be dropped from the results. + Optional. The maximum number of records to return. + Optional. Sort Order - Ascending,Descending. + Optional. Specify additional filters to apply. + Optional. Specify one or more sort orders, comma delimited. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime. + Optional. Specify additional fields of information to return in the output. + Channel items returned. + + A representing the request to get the channel items. + The task result contains an containing the channel items. + + + + + Gets latest channel items. + + Optional. User Id. + Optional. The record index to start at. All items with a lower index will be dropped from the results. + Optional. The maximum number of records to return. + Optional. Specify additional filters to apply. + Optional. Specify additional fields of information to return in the output. + Optional. Specify one or more channel id's, comma delimited. + Latest channel items returned. + + A representing the request to get the latest channel items. + The task result contains an containing the latest channel items. + + + + + Client log controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + + Upload a document. + + Document saved. + Event logging disabled. + Upload size too large. + Create response. + + + + The collection controller. + + + + + Initializes a new instance of the class. + + Instance of interface. + Instance of interface. + + + + Creates a new collection. + + The name of the collection. + Item Ids to add to the collection. + Optional. Create the collection within a specific folder. + Whether or not to lock the new collection. + Collection created. + A with information about the new collection. + + + + Adds items to a collection. + + The collection id. + Item ids, comma delimited. + Items added to collection. + A indicating success. + + + + Removes items from a collection. + + The collection id. + Item ids, comma delimited. + Items removed from collection. + A indicating success. + + + + Configuration Controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + + Gets application configuration. + + Application configuration returned. + Application configuration. + + + + Updates application configuration. + + Configuration. + Configuration updated. + Update status. + + + + Gets a named configuration. + + Configuration key. + Configuration returned. + Configuration. + + + + Updates named configuration. + + Configuration key. + Configuration. + Named configuration updated. + Update status. + + + + Gets a default MetadataOptions object. + + Metadata options returned. + Default MetadataOptions. + + + + Updates branding configuration. + + Branding configuration. + Branding configuration updated. + Update status. + + + + The dashboard controller. + + + + + Initializes a new instance of the class. + + Instance of interface. + Instance of interface. + + + + Gets the configuration pages. + + Whether to enable in the main menu. + ConfigurationPages returned. + Server still loading. + An with infos about the plugins. + + + + Gets a dashboard configuration page. + + The name of the page. + ConfigurationPage returned. + Plugin configuration page not found. + The configuration page. + + + + Exposes the PostgreSQL reporting views as read-only API endpoints. + All endpoints require administrator privileges. + + + + + Initializes a new instance of the class. + + The EF Core context factory. + + + + Gets a flat list of all media streams (audio + video columns merged). + Maps to library."MediaStreamInfos_v". + + Optional item ID filter. + Optional stream type filter (0=Audio, 1=Video, 2=Subtitle). + Record index to start at. + Maximum records to return (1-1000, default 100). + List of media stream rows. + + + + Gets video items joined with primary stream technical details. + Maps to library."VideoItems_v". + + Optional partial type filter (e.g. "Movie", "Episode"). + Optional minimum video height (e.g. 2160 for 4K). + Optional HDR format ("Dolby Vision", "HDR10+", "HDR10", "HLG", "SDR"). + Record index to start at. + Maximum records to return (1-1000, default 100). + List of video item rows. + + + + Gets per-user playback history with calculated progress percentages. + Maps to library."UserPlaybackHistory_v". + + Optional exact username filter. + Optional item ID filter. + When true, returns only items started but not fully played. + Record index to start at. + Maximum records to return (1-1000, default 100). + List of playback history rows. + + + + Gets items with their external provider IDs (IMDb, TMDB, TVDB, etc.) in named columns. + Maps to library."ItemProviders_v". + + Optional partial type filter. + Optional exact IMDb ID filter. + Optional exact TMDB ID filter. + Optional exact TVDB ID filter. + Record index to start at. + Maximum records to return (1-1000, default 100). + List of item provider rows. + + + + Gets cast and crew entries linked to the items they appear in. + Maps to library."ItemPeople_v". + + Optional exact person name filter. + Optional person type filter (e.g. "Actor", "Director"). + Optional item ID filter. + Record index to start at. + Maximum records to return (1-1000, default 100). + List of item person rows. + + + + Gets aggregate library statistics - one row per item type. + Maps to library."LibrarySummary_v". + + List of library summary rows, one per item type. + + + + Devices Controller. + + + + + Initializes a new instance of the class. + + Instance of interface. + Instance of interface. + + + + Get Devices. + + Gets or sets the user identifier. + Devices retrieved. + An containing the list of devices. + + + + Get info for a device. + + Device Id. + Device info retrieved. + Device not found. + An containing the device info on success, or a if the device could not be found. + + + + Get options for a device. + + Device Id. + Device options retrieved. + Device not found. + An containing the device info on success, or a if the device could not be found. + + + + Update device options. + + Device Id. + Device Options. + Device options updated. + A . + + + + Deletes a device. + + Device Id. + Device deleted. + Device not found. + A on success, or a if the device could not be found. + + + + Display Preferences Controller. + + + + + Initializes a new instance of the class. + + Instance of interface. + Instance of interface. + + + + Get Display Preferences. + + Display preferences id. + User id. + Client. + Display preferences retrieved. + An containing the display preferences on success, or a if the display preferences could not be found. + + + + Update Display Preferences. + + Display preferences id. + User Id. + Client. + New Display Preferences object. + Display preferences updated. + An on success. + + + + Dynamic hls controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of . + Instance of . + Instance of . + + + + Gets a hls live stream. + + The item id. + The audio container. + Optional. If true, the original file will be streamed statically without any encoding. Use either no url extension or the original file extension. true/false. + The streaming parameters. + The tag. + Optional. The dlna device profile id to utilize. + The play session id. + The segment container. + The segment length. + The minimum number of segments. + The media version id, if playing an alternate version. + The device id of the client requesting. Used to stop encoding processes when needed. + Optional. Specify an audio codec to encode to, e.g. mp3. + Whether or not to allow automatic stream copy if requested values match the original source. Defaults to true. + Whether or not to allow copying of the video stream url. + Whether or not to allow copying of the audio stream url. + Optional. Specify a specific audio sample rate, e.g. 44100. + Optional. The maximum audio bit depth. + Optional. Specify an audio bitrate to encode to, e.g. 128000. If omitted this will be left to encoder defaults. + Optional. Specify a specific number of audio channels to encode to, e.g. 2. + Optional. Specify a maximum number of audio channels to encode to, e.g. 2. + Optional. Specify a specific an encoder profile (varies by encoder), e.g. main, baseline, high. + Optional. Specify a level for the encoder profile (varies by encoder), e.g. 3, 3.1. + Optional. A specific video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements. + Optional. A specific maximum video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements. + Whether or not to copy timestamps when transcoding with an offset. Defaults to false. + Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms. + Optional. The fixed horizontal resolution of the encoded video. + Optional. The fixed vertical resolution of the encoded video. + Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be left to encoder defaults. + Optional. The index of the subtitle stream to use. If omitted no subtitles will be used. + Optional. Specify the subtitle delivery method. + Optional. + Optional. The maximum video bit depth. + Optional. Whether to require avc. + Optional. Whether to deinterlace the video. + Optional. Whether to require a non anamorphic stream. + Optional. The maximum number of audio channels to transcode. + Optional. The limit of how many cpu cores to use. + The live stream id. + Optional. Whether to enable the MpegtsM2Ts mode. + Optional. Specify a video codec to encode to, e.g. h264. + Optional. Specify a subtitle codec to encode to. + Optional. The transcoding reason. + Optional. The index of the audio stream to use. If omitted the first audio stream will be used. + Optional. The index of the video stream to use. If omitted the first video stream will be used. + Optional. The . + Optional. The streaming options. + Optional. The max width. + Optional. The max height. + Optional. Whether to enable subtitles in the manifest. + Optional. Whether to enable Audio Encoding. + Whether to always burn in subtitles when transcoding. + Hls live stream retrieved. + A containing the hls file. + + + + Gets a video hls playlist stream. + + The item id. + Optional. If true, the original file will be streamed statically without any encoding. Use either no url extension or the original file extension. true/false. + The streaming parameters. + The tag. + Optional. The dlna device profile id to utilize. + The play session id. + The segment container. + The segment length. + The minimum number of segments. + The media version id, if playing an alternate version. + The device id of the client requesting. Used to stop encoding processes when needed. + Optional. Specify an audio codec to encode to, e.g. mp3. + Whether or not to allow automatic stream copy if requested values match the original source. Defaults to true. + Whether or not to allow copying of the video stream url. + Whether or not to allow copying of the audio stream url. + Optional. Specify a specific audio sample rate, e.g. 44100. + Optional. The maximum audio bit depth. + Optional. Specify an audio bitrate to encode to, e.g. 128000. If omitted this will be left to encoder defaults. + Optional. Specify a specific number of audio channels to encode to, e.g. 2. + Optional. Specify a maximum number of audio channels to encode to, e.g. 2. + Optional. Specify a specific an encoder profile (varies by encoder), e.g. main, baseline, high. + Optional. Specify a level for the encoder profile (varies by encoder), e.g. 3, 3.1. + Optional. A specific video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements. + Optional. A specific maximum video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements. + Whether or not to copy timestamps when transcoding with an offset. Defaults to false. + Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms. + Optional. The fixed horizontal resolution of the encoded video. + Optional. The fixed vertical resolution of the encoded video. + Optional. The maximum horizontal resolution of the encoded video. + Optional. The maximum vertical resolution of the encoded video. + Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be left to encoder defaults. + Optional. The index of the subtitle stream to use. If omitted no subtitles will be used. + Optional. Specify the subtitle delivery method. + Optional. + Optional. The maximum video bit depth. + Optional. Whether to require avc. + Optional. Whether to deinterlace the video. + Optional. Whether to require a non anamorphic stream. + Optional. The maximum number of audio channels to transcode. + Optional. The limit of how many cpu cores to use. + The live stream id. + Optional. Whether to enable the MpegtsM2Ts mode. + Optional. Specify a video codec to encode to, e.g. h264. + Optional. Specify a subtitle codec to encode to. + Optional. The transcoding reason. + Optional. The index of the audio stream to use. If omitted the first audio stream will be used. + Optional. The index of the video stream to use. If omitted the first video stream will be used. + Optional. The . + Optional. The streaming options. + Enable adaptive bitrate streaming. + Enable trickplay image playlists being added to master playlist. + Whether to enable Audio Encoding. + Whether to always burn in subtitles when transcoding. + Video stream returned. + A containing the playlist file. + + + + Gets an audio hls playlist stream. + + The item id. + Optional. If true, the original file will be streamed statically without any encoding. Use either no url extension or the original file extension. true/false. + The streaming parameters. + The tag. + Optional. The dlna device profile id to utilize. + The play session id. + The segment container. + The segment length. + The minimum number of segments. + The media version id, if playing an alternate version. + The device id of the client requesting. Used to stop encoding processes when needed. + Optional. Specify an audio codec to encode to, e.g. mp3. + Whether or not to allow automatic stream copy if requested values match the original source. Defaults to true. + Whether or not to allow copying of the video stream url. + Whether or not to allow copying of the audio stream url. + Optional. Specify a specific audio sample rate, e.g. 44100. + Optional. The maximum audio bit depth. + Optional. The maximum streaming bitrate. + Optional. Specify an audio bitrate to encode to, e.g. 128000. If omitted this will be left to encoder defaults. + Optional. Specify a specific number of audio channels to encode to, e.g. 2. + Optional. Specify a maximum number of audio channels to encode to, e.g. 2. + Optional. Specify a specific an encoder profile (varies by encoder), e.g. main, baseline, high. + Optional. Specify a level for the encoder profile (varies by encoder), e.g. 3, 3.1. + Optional. A specific video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements. + Optional. A specific maximum video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements. + Whether or not to copy timestamps when transcoding with an offset. Defaults to false. + Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms. + Optional. The fixed horizontal resolution of the encoded video. + Optional. The fixed vertical resolution of the encoded video. + Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be left to encoder defaults. + Optional. The index of the subtitle stream to use. If omitted no subtitles will be used. + Optional. Specify the subtitle delivery method. + Optional. + Optional. The maximum video bit depth. + Optional. Whether to require avc. + Optional. Whether to deinterlace the video. + Optional. Whether to require a non anamorphic stream. + Optional. The maximum number of audio channels to transcode. + Optional. The limit of how many cpu cores to use. + The live stream id. + Optional. Whether to enable the MpegtsM2Ts mode. + Optional. Specify a video codec to encode to, e.g. h264. + Optional. Specify a subtitle codec to encode to. + Optional. The transcoding reason. + Optional. The index of the audio stream to use. If omitted the first audio stream will be used. + Optional. The index of the video stream to use. If omitted the first video stream will be used. + Optional. The . + Optional. The streaming options. + Enable adaptive bitrate streaming. + Optional. Whether to enable Audio Encoding. + Audio stream returned. + A containing the playlist file. + + + + Gets a video stream using HTTP live streaming. + + The item id. + Optional. If true, the original file will be streamed statically without any encoding. Use either no url extension or the original file extension. true/false. + The streaming parameters. + The tag. + Optional. The dlna device profile id to utilize. + The play session id. + The segment container. + The segment length. + The minimum number of segments. + The media version id, if playing an alternate version. + The device id of the client requesting. Used to stop encoding processes when needed. + Optional. Specify an audio codec to encode to, e.g. mp3. + Whether or not to allow automatic stream copy if requested values match the original source. Defaults to true. + Whether or not to allow copying of the video stream url. + Whether or not to allow copying of the audio stream url. + Optional. Specify a specific audio sample rate, e.g. 44100. + Optional. The maximum audio bit depth. + Optional. Specify an audio bitrate to encode to, e.g. 128000. If omitted this will be left to encoder defaults. + Optional. Specify a specific number of audio channels to encode to, e.g. 2. + Optional. Specify a maximum number of audio channels to encode to, e.g. 2. + Optional. Specify a specific an encoder profile (varies by encoder), e.g. main, baseline, high. + Optional. Specify a level for the encoder profile (varies by encoder), e.g. 3, 3.1. + Optional. A specific video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements. + Optional. A specific maximum video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements. + Whether or not to copy timestamps when transcoding with an offset. Defaults to false. + Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms. + Optional. The fixed horizontal resolution of the encoded video. + Optional. The fixed vertical resolution of the encoded video. + Optional. The maximum horizontal resolution of the encoded video. + Optional. The maximum vertical resolution of the encoded video. + Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be left to encoder defaults. + Optional. The index of the subtitle stream to use. If omitted no subtitles will be used. + Optional. Specify the subtitle delivery method. + Optional. + Optional. The maximum video bit depth. + Optional. Whether to require avc. + Optional. Whether to deinterlace the video. + Optional. Whether to require a non anamorphic stream. + Optional. The maximum number of audio channels to transcode. + Optional. The limit of how many cpu cores to use. + The live stream id. + Optional. Whether to enable the MpegtsM2Ts mode. + Optional. Specify a video codec to encode to, e.g. h264. + Optional. Specify a subtitle codec to encode to. + Optional. The transcoding reason. + Optional. The index of the audio stream to use. If omitted the first audio stream will be used. + Optional. The index of the video stream to use. If omitted the first video stream will be used. + Optional. The . + Optional. The streaming options. + Optional. Whether to enable Audio Encoding. + Whether to always burn in subtitles when transcoding. + Video stream returned. + A containing the audio file. + + + + Gets an audio stream using HTTP live streaming. + + The item id. + Optional. If true, the original file will be streamed statically without any encoding. Use either no url extension or the original file extension. true/false. + The streaming parameters. + The tag. + Optional. The dlna device profile id to utilize. + The play session id. + The segment container. + The segment length. + The minimum number of segments. + The media version id, if playing an alternate version. + The device id of the client requesting. Used to stop encoding processes when needed. + Optional. Specify an audio codec to encode to, e.g. mp3. + Whether or not to allow automatic stream copy if requested values match the original source. Defaults to true. + Whether or not to allow copying of the video stream url. + Whether or not to allow copying of the audio stream url. + Optional. Specify a specific audio sample rate, e.g. 44100. + Optional. The maximum audio bit depth. + Optional. The maximum streaming bitrate. + Optional. Specify an audio bitrate to encode to, e.g. 128000. If omitted this will be left to encoder defaults. + Optional. Specify a specific number of audio channels to encode to, e.g. 2. + Optional. Specify a maximum number of audio channels to encode to, e.g. 2. + Optional. Specify a specific an encoder profile (varies by encoder), e.g. main, baseline, high. + Optional. Specify a level for the encoder profile (varies by encoder), e.g. 3, 3.1. + Optional. A specific video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements. + Optional. A specific maximum video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements. + Whether or not to copy timestamps when transcoding with an offset. Defaults to false. + Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms. + Optional. The fixed horizontal resolution of the encoded video. + Optional. The fixed vertical resolution of the encoded video. + Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be left to encoder defaults. + Optional. The index of the subtitle stream to use. If omitted no subtitles will be used. + Optional. Specify the subtitle delivery method. + Optional. + Optional. The maximum video bit depth. + Optional. Whether to require avc. + Optional. Whether to deinterlace the video. + Optional. Whether to require a non anamorphic stream. + Optional. The maximum number of audio channels to transcode. + Optional. The limit of how many cpu cores to use. + The live stream id. + Optional. Whether to enable the MpegtsM2Ts mode. + Optional. Specify a video codec to encode to, e.g. h264. + Optional. Specify a subtitle codec to encode to. + Optional. The transcoding reason. + Optional. The index of the audio stream to use. If omitted the first audio stream will be used. + Optional. The index of the video stream to use. If omitted the first video stream will be used. + Optional. The . + Optional. The streaming options. + Optional. Whether to enable Audio Encoding. + Audio stream returned. + A containing the audio file. + + + + Gets a video stream using HTTP live streaming. + + The item id. + The playlist id. + The segment id. + The video container. Possible values are: ts, webm, asf, wmv, ogv, mp4, m4v, mkv, mpeg, mpg, avi, 3gp, wmv, wtv, m2ts, mov, iso, flv. + The position of the requested segment in ticks. + The length of the requested segment in ticks. + Optional. If true, the original file will be streamed statically without any encoding. Use either no url extension or the original file extension. true/false. + The streaming parameters. + The tag. + Optional. The dlna device profile id to utilize. + The play session id. + The segment container. + The desired segment length. + The minimum number of segments. + The media version id, if playing an alternate version. + The device id of the client requesting. Used to stop encoding processes when needed. + Optional. Specify an audio codec to encode to, e.g. mp3. + Whether or not to allow automatic stream copy if requested values match the original source. Defaults to true. + Whether or not to allow copying of the video stream url. + Whether or not to allow copying of the audio stream url. + Optional. Specify a specific audio sample rate, e.g. 44100. + Optional. The maximum audio bit depth. + Optional. Specify an audio bitrate to encode to, e.g. 128000. If omitted this will be left to encoder defaults. + Optional. Specify a specific number of audio channels to encode to, e.g. 2. + Optional. Specify a maximum number of audio channels to encode to, e.g. 2. + Optional. Specify a specific an encoder profile (varies by encoder), e.g. main, baseline, high. + Optional. Specify a level for the encoder profile (varies by encoder), e.g. 3, 3.1. + Optional. A specific video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements. + Optional. A specific maximum video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements. + Whether or not to copy timestamps when transcoding with an offset. Defaults to false. + Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms. + Optional. The fixed horizontal resolution of the encoded video. + Optional. The fixed vertical resolution of the encoded video. + Optional. The maximum horizontal resolution of the encoded video. + Optional. The maximum vertical resolution of the encoded video. + Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be left to encoder defaults. + Optional. The index of the subtitle stream to use. If omitted no subtitles will be used. + Optional. Specify the subtitle delivery method. + Optional. + Optional. The maximum video bit depth. + Optional. Whether to require avc. + Optional. Whether to deinterlace the video. + Optional. Whether to require a non anamorphic stream. + Optional. The maximum number of audio channels to transcode. + Optional. The limit of how many cpu cores to use. + The live stream id. + Optional. Whether to enable the MpegtsM2Ts mode. + Optional. Specify a video codec to encode to, e.g. h264. + Optional. Specify a subtitle codec to encode to. + Optional. The transcoding reason. + Optional. The index of the audio stream to use. If omitted the first audio stream will be used. + Optional. The index of the video stream to use. If omitted the first video stream will be used. + Optional. The . + Optional. The streaming options. + Optional. Whether to enable Audio Encoding. + Whether to always burn in subtitles when transcoding. + Video stream returned. + A containing the audio file. + + + + Gets a video stream using HTTP live streaming. + + The item id. + The playlist id. + The segment id. + The video container. Possible values are: ts, webm, asf, wmv, ogv, mp4, m4v, mkv, mpeg, mpg, avi, 3gp, wmv, wtv, m2ts, mov, iso, flv. + The position of the requested segment in ticks. + The length of the requested segment in ticks. + Optional. If true, the original file will be streamed statically without any encoding. Use either no url extension or the original file extension. true/false. + The streaming parameters. + The tag. + Optional. The dlna device profile id to utilize. + The play session id. + The segment container. + The segment length. + The minimum number of segments. + The media version id, if playing an alternate version. + The device id of the client requesting. Used to stop encoding processes when needed. + Optional. Specify an audio codec to encode to, e.g. mp3. + Whether or not to allow automatic stream copy if requested values match the original source. Defaults to true. + Whether or not to allow copying of the video stream url. + Whether or not to allow copying of the audio stream url. + Optional. Specify a specific audio sample rate, e.g. 44100. + Optional. The maximum audio bit depth. + Optional. The maximum streaming bitrate. + Optional. Specify an audio bitrate to encode to, e.g. 128000. If omitted this will be left to encoder defaults. + Optional. Specify a specific number of audio channels to encode to, e.g. 2. + Optional. Specify a maximum number of audio channels to encode to, e.g. 2. + Optional. Specify a specific an encoder profile (varies by encoder), e.g. main, baseline, high. + Optional. Specify a level for the encoder profile (varies by encoder), e.g. 3, 3.1. + Optional. A specific video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements. + Optional. A specific maximum video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements. + Whether or not to copy timestamps when transcoding with an offset. Defaults to false. + Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms. + Optional. The fixed horizontal resolution of the encoded video. + Optional. The fixed vertical resolution of the encoded video. + Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be left to encoder defaults. + Optional. The index of the subtitle stream to use. If omitted no subtitles will be used. + Optional. Specify the subtitle delivery method. + Optional. + Optional. The maximum video bit depth. + Optional. Whether to require avc. + Optional. Whether to deinterlace the video. + Optional. Whether to require a non anamorphic stream. + Optional. The maximum number of audio channels to transcode. + Optional. The limit of how many cpu cores to use. + The live stream id. + Optional. Whether to enable the MpegtsM2Ts mode. + Optional. Specify a video codec to encode to, e.g. h264. + Optional. Specify a subtitle codec to encode to. + Optional. The transcoding reason. + Optional. The index of the audio stream to use. If omitted the first audio stream will be used. + Optional. The index of the video stream to use. If omitted the first video stream will be used. + Optional. The . + Optional. The streaming options. + Optional. Whether to enable Audio Encoding. + Video stream returned. + A containing the audio file. + + + + Gets the audio arguments for transcoding. + + The . + The command line arguments for audio transcoding. + + + + Gets the video arguments for transcoding. + + The . + The first number in the hls sequence. + Whether the playlist is EVENT or VOD. + The segment container. + The command line arguments for video transcoding. + + + + Environment Controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + + Gets the contents of a given directory in the file system. + + The path. + An optional filter to include or exclude files from the results. true/false. + An optional filter to include or exclude folders from the results. true/false. + Directory contents returned. + Directory contents. + + + + Validates path. + + Validate request object. + Path validated. + Path not found. + Validation status. + + + + Gets available drives from the server's file system. + + List of entries returned. + List of entries. + + + + Gets the parent path of a given path. + + The path. + Parent path. + + + + Get Default directory browser. + + Default directory browser returned. + Default directory browser. + + + + Filters controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + + Gets legacy query filters. + + Optional. User id. + Optional. Parent id. + Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited. + Optional. Filter by MediaType. Allows multiple, comma delimited. + Legacy filters retrieved. + Legacy query filters. + + + + Gets query filters. + + Optional. User id. + Optional. Specify this to localize the search to a specific item or folder. Omit to use the root. + Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited. + Optional. Is item airing. + Optional. Is item movie. + Optional. Is item sports. + Optional. Is item kids. + Optional. Is item news. + Optional. Is item series. + Optional. Search recursive. + Filters retrieved. + Query filters. + + + + The genres controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Gets all genres from a given item, folder, or the entire library. + + Optional. The record index to start at. All items with a lower index will be dropped from the results. + Optional. The maximum number of records to return. + The search term. + Specify this to localize the search to a specific item or folder. Omit to use the root. + Optional. Specify additional fields of information to return in the output. + Optional. If specified, results will be filtered out based on item type. This allows multiple, comma delimited. + Optional. If specified, results will be filtered in based on item type. This allows multiple, comma delimited. + Optional filter by items that are marked as favorite, or not. + Optional, the max number of images to return, per image type. + Optional. The image types to include in the output. + User id. + Optional filter by items whose name is sorted equally or greater than a given input string. + Optional filter by items whose name is sorted equally than a given input string. + Optional filter by items whose name is equally or lesser than a given input string. + Optional. Specify one or more sort orders, comma delimited. + Sort Order - Ascending,Descending. + Optional, include image information in output. + Optional. Include total record count. + Genres returned. + An containing the queryresult of genres. + + + + Gets a genre, by name. + + The genre name. + The user id. + Genres returned. + An containing the genre. + + + + The hls segment controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Gets the specified audio segment for an audio item. + + The item id. + The segment id. + Hls audio segment returned. + A containing the audio stream. + + + + Gets a hls video playlist. + + The video id. + The playlist id. + Hls video playlist returned. + A containing the playlist. + + + + Stops an active encoding. + + The device id of the client requesting. Used to stop encoding processes when needed. + The play session id. + Encoding stopped successfully. + A indicating success. + + + + Gets a hls video segment. + + The item id. + The playlist id. + The segment id. + The segment container. + Hls video segment returned. + Hls segment not found. + A containing the video segment. + + + + Image controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Sets the user image. + + User Id. + Image updated. + User does not have permission to delete the image. + Item not found. + A . + + + + Sets the user image. + + User Id. + (Unused) Image type. + Image updated. + User does not have permission to delete the image. + A . + + + + Sets the user image. + + User Id. + (Unused) Image type. + (Unused) Image index. + Image updated. + User does not have permission to delete the image. + A . + + + + Delete the user's image. + + User Id. + Image deleted. + User does not have permission to delete the image. + A . + + + + Delete the user's image. + + User Id. + (Unused) Image type. + (Unused) Image index. + Image deleted. + User does not have permission to delete the image. + A . + + + + Delete the user's image. + + User Id. + (Unused) Image type. + (Unused) Image index. + Image deleted. + User does not have permission to delete the image. + A . + + + + Delete an item's image. + + Item id. + Image type. + The image index. + Image deleted. + Item not found. + A on success, or a if item not found. + + + + Delete an item's image. + + Item id. + Image type. + The image index. + Image deleted. + Item not found. + A on success, or a if item not found. + + + + Set item image. + + Item id. + Image type. + Image saved. + Item not found. + A on success, or a if item not found. + + + + Set item image. + + Item id. + Image type. + (Unused) Image index. + Image saved. + Item not found. + A on success, or a if item not found. + + + + Updates the index for an item image. + + Item id. + Image type. + Old image index. + New image index. + Image index updated. + Item not found. + A on success, or a if item not found. + + + + Get item image infos. + + Item id. + Item images returned. + Item not found. + The list of image infos on success, or if item not found. + + + + Gets the item's image. + + Item id. + Image type. + The maximum image width to return. + The maximum image height to return. + The fixed image width to return. + The fixed image height to return. + Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases. + Width of box to fill. + Height of box to fill. + Optional. Supply the cache tag from the item object to receive strong caching headers. + Optional. The of the returned image. + Optional. Percent to render for the percent played overlay. + Optional. Unplayed count overlay to render. + Optional. Blur image. + Optional. Apply a background color for transparent images. + Optional. Apply a foreground layer on top of the image. + Image index. + Image stream returned. + Item not found. + + A containing the file stream on success, + or a if item not found. + + + + + Gets the item's image. + + Item id. + Image type. + Image index. + The maximum image width to return. + The maximum image height to return. + The fixed image width to return. + The fixed image height to return. + Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases. + Width of box to fill. + Height of box to fill. + Optional. Supply the cache tag from the item object to receive strong caching headers. + Optional. The of the returned image. + Optional. Percent to render for the percent played overlay. + Optional. Unplayed count overlay to render. + Optional. Blur image. + Optional. Apply a background color for transparent images. + Optional. Apply a foreground layer on top of the image. + Image stream returned. + Item not found. + + A containing the file stream on success, + or a if item not found. + + + + + Gets the item's image. + + Item id. + Image type. + The maximum image width to return. + The maximum image height to return. + The fixed image width to return. + The fixed image height to return. + Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases. + Width of box to fill. + Height of box to fill. + Optional. Supply the cache tag from the item object to receive strong caching headers. + Determines the output format of the image - original,gif,jpg,png. + Optional. Percent to render for the percent played overlay. + Optional. Unplayed count overlay to render. + Optional. Blur image. + Optional. Apply a background color for transparent images. + Optional. Apply a foreground layer on top of the image. + Image index. + Image stream returned. + Item not found. + + A containing the file stream on success, + or a if item not found. + + + + + Get artist image by name. + + Artist name. + Image type. + Optional. Supply the cache tag from the item object to receive strong caching headers. + Determines the output format of the image - original,gif,jpg,png. + The maximum image width to return. + The maximum image height to return. + Optional. Percent to render for the percent played overlay. + Optional. Unplayed count overlay to render. + The fixed image width to return. + The fixed image height to return. + Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases. + Width of box to fill. + Height of box to fill. + Optional. Blur image. + Optional. Apply a background color for transparent images. + Optional. Apply a foreground layer on top of the image. + Image index. + Image stream returned. + Item not found. + + A containing the file stream on success, + or a if item not found. + + + + + Get genre image by name. + + Genre name. + Image type. + Optional. Supply the cache tag from the item object to receive strong caching headers. + Determines the output format of the image - original,gif,jpg,png. + The maximum image width to return. + The maximum image height to return. + Optional. Percent to render for the percent played overlay. + Optional. Unplayed count overlay to render. + The fixed image width to return. + The fixed image height to return. + Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases. + Width of box to fill. + Height of box to fill. + Optional. Blur image. + Optional. Apply a background color for transparent images. + Optional. Apply a foreground layer on top of the image. + Image index. + Image stream returned. + Item not found. + + A containing the file stream on success, + or a if item not found. + + + + + Get genre image by name. + + Genre name. + Image type. + Image index. + Optional. Supply the cache tag from the item object to receive strong caching headers. + Determines the output format of the image - original,gif,jpg,png. + The maximum image width to return. + The maximum image height to return. + Optional. Percent to render for the percent played overlay. + Optional. Unplayed count overlay to render. + The fixed image width to return. + The fixed image height to return. + Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases. + Width of box to fill. + Height of box to fill. + Optional. Blur image. + Optional. Apply a background color for transparent images. + Optional. Apply a foreground layer on top of the image. + Image stream returned. + Item not found. + + A containing the file stream on success, + or a if item not found. + + + + + Get music genre image by name. + + Music genre name. + Image type. + Optional. Supply the cache tag from the item object to receive strong caching headers. + Determines the output format of the image - original,gif,jpg,png. + The maximum image width to return. + The maximum image height to return. + Optional. Percent to render for the percent played overlay. + Optional. Unplayed count overlay to render. + The fixed image width to return. + The fixed image height to return. + Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases. + Width of box to fill. + Height of box to fill. + Optional. Blur image. + Optional. Apply a background color for transparent images. + Optional. Apply a foreground layer on top of the image. + Image index. + Image stream returned. + Item not found. + + A containing the file stream on success, + or a if item not found. + + + + + Get music genre image by name. + + Music genre name. + Image type. + Image index. + Optional. Supply the cache tag from the item object to receive strong caching headers. + Determines the output format of the image - original,gif,jpg,png. + The maximum image width to return. + The maximum image height to return. + Optional. Percent to render for the percent played overlay. + Optional. Unplayed count overlay to render. + The fixed image width to return. + The fixed image height to return. + Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases. + Width of box to fill. + Height of box to fill. + Optional. Blur image. + Optional. Apply a background color for transparent images. + Optional. Apply a foreground layer on top of the image. + Image stream returned. + Item not found. + + A containing the file stream on success, + or a if item not found. + + + + + Get person image by name. + + Person name. + Image type. + Optional. Supply the cache tag from the item object to receive strong caching headers. + Determines the output format of the image - original,gif,jpg,png. + The maximum image width to return. + The maximum image height to return. + Optional. Percent to render for the percent played overlay. + Optional. Unplayed count overlay to render. + The fixed image width to return. + The fixed image height to return. + Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases. + Width of box to fill. + Height of box to fill. + Optional. Blur image. + Optional. Apply a background color for transparent images. + Optional. Apply a foreground layer on top of the image. + Image index. + Image stream returned. + Item not found. + + A containing the file stream on success, + or a if item not found. + + + + + Get person image by name. + + Person name. + Image type. + Image index. + Optional. Supply the cache tag from the item object to receive strong caching headers. + Determines the output format of the image - original,gif,jpg,png. + The maximum image width to return. + The maximum image height to return. + Optional. Percent to render for the percent played overlay. + Optional. Unplayed count overlay to render. + The fixed image width to return. + The fixed image height to return. + Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases. + Width of box to fill. + Height of box to fill. + Optional. Blur image. + Optional. Apply a background color for transparent images. + Optional. Apply a foreground layer on top of the image. + Image stream returned. + Item not found. + + A containing the file stream on success, + or a if item not found. + + + + + Get studio image by name. + + Studio name. + Image type. + Optional. Supply the cache tag from the item object to receive strong caching headers. + Determines the output format of the image - original,gif,jpg,png. + The maximum image width to return. + The maximum image height to return. + Optional. Percent to render for the percent played overlay. + Optional. Unplayed count overlay to render. + The fixed image width to return. + The fixed image height to return. + Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases. + Width of box to fill. + Height of box to fill. + Optional. Blur image. + Optional. Apply a background color for transparent images. + Optional. Apply a foreground layer on top of the image. + Image index. + Image stream returned. + Item not found. + + A containing the file stream on success, + or a if item not found. + + + + + Get studio image by name. + + Studio name. + Image type. + Image index. + Optional. Supply the cache tag from the item object to receive strong caching headers. + Determines the output format of the image - original,gif,jpg,png. + The maximum image width to return. + The maximum image height to return. + Optional. Percent to render for the percent played overlay. + Optional. Unplayed count overlay to render. + The fixed image width to return. + The fixed image height to return. + Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases. + Width of box to fill. + Height of box to fill. + Optional. Blur image. + Optional. Apply a background color for transparent images. + Optional. Apply a foreground layer on top of the image. + Image stream returned. + Item not found. + + A containing the file stream on success, + or a if item not found. + + + + + Get user profile image. + + User id. + Optional. Supply the cache tag from the item object to receive strong caching headers. + Determines the output format of the image - original,gif,jpg,png. + Image stream returned. + User id not provided. + Item not found. + + A containing the file stream on success, + or a if item not found. + + + + + Get user profile image. + + User id. + Image type. + Optional. Supply the cache tag from the item object to receive strong caching headers. + Determines the output format of the image - original,gif,jpg,png. + The maximum image width to return. + The maximum image height to return. + Optional. Percent to render for the percent played overlay. + Optional. Unplayed count overlay to render. + The fixed image width to return. + The fixed image height to return. + Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases. + Width of box to fill. + Height of box to fill. + Optional. Blur image. + Optional. Apply a background color for transparent images. + Optional. Apply a foreground layer on top of the image. + Image index. + Image stream returned. + Item not found. + + A containing the file stream on success, + or a if item not found. + + + + + Get user profile image. + + User id. + Image type. + Image index. + Optional. Supply the cache tag from the item object to receive strong caching headers. + Determines the output format of the image - original,gif,jpg,png. + The maximum image width to return. + The maximum image height to return. + Optional. Percent to render for the percent played overlay. + Optional. Unplayed count overlay to render. + The fixed image width to return. + The fixed image height to return. + Optional. Quality setting, from 0-100. Defaults to 90 and should suffice in most cases. + Width of box to fill. + Height of box to fill. + Optional. Blur image. + Optional. Apply a background color for transparent images. + Optional. Apply a foreground layer on top of the image. + Image stream returned. + Item not found. + + A containing the file stream on success, + or a if item not found. + + + + + Generates or gets the splashscreen. + + Supply the cache tag from the item object to receive strong caching headers. + Determines the output format of the image - original,gif,jpg,png. + Splashscreen returned successfully. + The splashscreen. + + + + Uploads a custom splashscreen. + The body is expected to the image contents base64 encoded. + + A indicating success. + Successfully uploaded new splashscreen. + Error reading MimeType from uploaded image. + User does not have permission to upload splashscreen.. + Error reading the image format. + + + + Delete a custom splashscreen. + + A indicating success. + Successfully deleted the custom splashscreen. + User does not have permission to delete splashscreen.. + + + + The instant mix controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Creates an instant playlist based on a given song. + + The item id. + Optional. Filter by user id, and attach user data. + Optional. The maximum number of records to return. + Optional. Specify additional fields of information to return in the output. + Optional. Include image information in output. + Optional. Include user data. + Optional. The max number of images to return, per image type. + Optional. The image types to include in the output. + Instant playlist returned. + Item not found. + A with the playlist items. + + + + Creates an instant playlist based on a given album. + + The item id. + Optional. Filter by user id, and attach user data. + Optional. The maximum number of records to return. + Optional. Specify additional fields of information to return in the output. + Optional. Include image information in output. + Optional. Include user data. + Optional. The max number of images to return, per image type. + Optional. The image types to include in the output. + Instant playlist returned. + Item not found. + A with the playlist items. + + + + Creates an instant playlist based on a given playlist. + + The item id. + Optional. Filter by user id, and attach user data. + Optional. The maximum number of records to return. + Optional. Specify additional fields of information to return in the output. + Optional. Include image information in output. + Optional. Include user data. + Optional. The max number of images to return, per image type. + Optional. The image types to include in the output. + Instant playlist returned. + Item not found. + A with the playlist items. + + + + Creates an instant playlist based on a given genre. + + The genre name. + Optional. Filter by user id, and attach user data. + Optional. The maximum number of records to return. + Optional. Specify additional fields of information to return in the output. + Optional. Include image information in output. + Optional. Include user data. + Optional. The max number of images to return, per image type. + Optional. The image types to include in the output. + Instant playlist returned. + A with the playlist items. + + + + Creates an instant playlist based on a given artist. + + The item id. + Optional. Filter by user id, and attach user data. + Optional. The maximum number of records to return. + Optional. Specify additional fields of information to return in the output. + Optional. Include image information in output. + Optional. Include user data. + Optional. The max number of images to return, per image type. + Optional. The image types to include in the output. + Instant playlist returned. + Item not found. + A with the playlist items. + + + + Creates an instant playlist based on a given item. + + The item id. + Optional. Filter by user id, and attach user data. + Optional. The maximum number of records to return. + Optional. Specify additional fields of information to return in the output. + Optional. Include image information in output. + Optional. Include user data. + Optional. The max number of images to return, per image type. + Optional. The image types to include in the output. + Instant playlist returned. + Item not found. + A with the playlist items. + + + + Creates an instant playlist based on a given artist. + + The item id. + Optional. Filter by user id, and attach user data. + Optional. The maximum number of records to return. + Optional. Specify additional fields of information to return in the output. + Optional. Include image information in output. + Optional. Include user data. + Optional. The max number of images to return, per image type. + Optional. The image types to include in the output. + Instant playlist returned. + Item not found. + A with the playlist items. + + + + Creates an instant playlist based on a given genre. + + The item id. + Optional. Filter by user id, and attach user data. + Optional. The maximum number of records to return. + Optional. Specify additional fields of information to return in the output. + Optional. Include image information in output. + Optional. Include user data. + Optional. The max number of images to return, per image type. + Optional. The image types to include in the output. + Instant playlist returned. + Item not found. + A with the playlist items. + + + + Item lookup controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Get the item's external id info. + + Item id. + External id info retrieved. + Item not found. + List of external id info. + + + + Get movie remote search. + + Remote search query. + Movie remote search executed. + + A that represents the asynchronous operation to get the remote search results. + The task result contains an containing the list of remote search results. + + + + + Get trailer remote search. + + Remote search query. + Trailer remote search executed. + + A that represents the asynchronous operation to get the remote search results. + The task result contains an containing the list of remote search results. + + + + + Get music video remote search. + + Remote search query. + Music video remote search executed. + + A that represents the asynchronous operation to get the remote search results. + The task result contains an containing the list of remote search results. + + + + + Get series remote search. + + Remote search query. + Series remote search executed. + + A that represents the asynchronous operation to get the remote search results. + The task result contains an containing the list of remote search results. + + + + + Get box set remote search. + + Remote search query. + Box set remote search executed. + + A that represents the asynchronous operation to get the remote search results. + The task result contains an containing the list of remote search results. + + + + + Get music artist remote search. + + Remote search query. + Music artist remote search executed. + + A that represents the asynchronous operation to get the remote search results. + The task result contains an containing the list of remote search results. + + + + + Get music album remote search. + + Remote search query. + Music album remote search executed. + + A that represents the asynchronous operation to get the remote search results. + The task result contains an containing the list of remote search results. + + + + + Get person remote search. + + Remote search query. + Person remote search executed. + + A that represents the asynchronous operation to get the remote search results. + The task result contains an containing the list of remote search results. + + + + + Get book remote search. + + Remote search query. + Book remote search executed. + + A that represents the asynchronous operation to get the remote search results. + The task result contains an containing the list of remote search results. + + + + + Applies search criteria to an item and refreshes metadata. + + Item id. + The remote search result. + Optional. Whether or not to replace all images. Default: True. + Item metadata refreshed. + Item not found. + + A that represents the asynchronous operation to get the remote search results. + The task result contains an . + + + + + Item Refresh Controller. + + + + + Initializes a new instance of the class. + + Instance of interface. + Instance of interface. + Instance of interface. + + + + Refreshes metadata for an item. + + Item id. + (Optional) Specifies the metadata refresh mode. + (Optional) Specifies the image refresh mode. + (Optional) Determines if metadata should be replaced. Only applicable if mode is FullRefresh. + (Optional) Determines if images should be replaced. Only applicable if mode is FullRefresh. + (Optional) Determines if trickplay images should be replaced. Only applicable if mode is FullRefresh. + Item metadata refresh queued. + Item to refresh not found. + An on success, or a if the item could not be found. + + + + The items controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Gets items based on a query. + + The user id supplied as query parameter; this is required when not using an API key. + Optional filter by maximum official rating (PG, PG-13, TV-MA, etc). + Optional filter by items with theme songs. + Optional filter by items with theme videos. + Optional filter by items with subtitles. + Optional filter by items with special features. + Optional filter by items with trailers. + Optional. Return items that are siblings of a supplied item. + Optional filter by index number. + Optional filter by parent index number. + Optional filter by items that have or do not have a parental rating. + Optional filter by items that are HD or not. + Optional filter by items that are 4K or not. + Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimited. + Optional. If specified, results will be filtered based on the LocationType. This allows multiple, comma delimited. + Optional filter by items that are missing episodes or not. + Optional filter by items that are unaired episodes or not. + Optional filter by minimum community rating. + Optional filter by minimum critic rating. + Optional. The minimum premiere date. Format = ISO. + Optional. The minimum last saved date. Format = ISO. + Optional. The minimum last saved date for the current user. Format = ISO. + Optional. The maximum premiere date. Format = ISO. + Optional filter by items that have an overview or not. + Optional filter by items that have an IMDb id or not. + Optional filter by items that have a TMDb id or not. + Optional filter by items that have a TVDb id or not. + Optional filter for live tv movies. + Optional filter for live tv series. + Optional filter for live tv news. + Optional filter for live tv kids. + Optional filter for live tv sports. + Optional. If specified, results will be filtered by excluding item ids. This allows multiple, comma delimited. + Optional. The record index to start at. All items with a lower index will be dropped from the results. + Optional. The maximum number of records to return. + When searching within folders, this determines whether or not the search will be recursive. true/false. + Optional. Filter based on a search term. + Sort Order - Ascending, Descending. + Specify this to localize the search to a specific item or folder. Omit to use the root. + Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines. + Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited. + Optional. If specified, results will be filtered based on the item type. This allows multiple, comma delimited. + Optional. Specify additional filters to apply. This allows multiple, comma delimited. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes. + Optional filter by items that are marked as favorite, or not. + Optional filter by MediaType. Allows multiple, comma delimited. + Optional. If specified, results will be filtered based on those containing image types. This allows multiple, comma delimited. + Optional. Specify one or more sort orders, comma delimited. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime. + Optional filter by items that are played, or not. + Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on OfficialRating. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on tag. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on production year. This allows multiple, comma delimited. + Optional, include user data. + Optional, the max number of images to return, per image type. + Optional. The image types to include in the output. + Optional. If specified, results will be filtered to include only those containing the specified person. + Optional. If specified, results will be filtered to include only those containing the specified person id. + Optional. If specified, along with Person, results will be filtered to include only those containing the specified person and PersonType. Allows multiple, comma-delimited. + Optional. If specified, results will be filtered based on studio. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on artists. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on artist id. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered to include only those containing the specified artist id. + Optional. If specified, results will be filtered to include only those containing the specified album artist id. + Optional. If specified, results will be filtered to include only those containing the specified contributing artist id. + Optional. If specified, results will be filtered based on album. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on album id. This allows multiple, pipe delimited. + Optional. If specific items are needed, specify a list of item id's to retrieve. This allows multiple, comma delimited. + Optional filter by VideoType (videofile, dvd, bluray, iso). Allows multiple, comma delimited. + Optional filter by minimum official rating (PG, PG-13, TV-MA, etc). + Optional filter by items that are locked. + Optional filter by items that are placeholders. + Optional filter by items that have official ratings. + Whether or not to hide items behind their boxsets. + Optional. Filter by the minimum width of the item. + Optional. Filter by the minimum height of the item. + Optional. Filter by the maximum width of the item. + Optional. Filter by the maximum height of the item. + Optional filter by items that are 3D, or not. + Optional filter by Series Status. Allows multiple, comma delimited. + Optional filter by items whose name is sorted equally or greater than a given input string. + Optional filter by items whose name is sorted equally than a given input string. + Optional filter by items whose name is equally or lesser than a given input string. + Optional. If specified, results will be filtered based on studio id. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on genre id. This allows multiple, pipe delimited. + Optional. Enable the total record count. + Optional, include image information in output. + A with the items. + + + + Gets items based on a query. + + The user id supplied as query parameter. + Optional filter by maximum official rating (PG, PG-13, TV-MA, etc). + Optional filter by items with theme songs. + Optional filter by items with theme videos. + Optional filter by items with subtitles. + Optional filter by items with special features. + Optional filter by items with trailers. + Optional. Return items that are siblings of a supplied item. + Optional filter by parent index number. + Optional filter by items that have or do not have a parental rating. + Optional filter by items that are HD or not. + Optional filter by items that are 4K or not. + Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimited. + Optional. If specified, results will be filtered based on the LocationType. This allows multiple, comma delimited. + Optional filter by items that are missing episodes or not. + Optional filter by items that are unaired episodes or not. + Optional filter by minimum community rating. + Optional filter by minimum critic rating. + Optional. The minimum premiere date. Format = ISO. + Optional. The minimum last saved date. Format = ISO. + Optional. The minimum last saved date for the current user. Format = ISO. + Optional. The maximum premiere date. Format = ISO. + Optional filter by items that have an overview or not. + Optional filter by items that have an IMDb id or not. + Optional filter by items that have a TMDb id or not. + Optional filter by items that have a TVDb id or not. + Optional filter for live tv movies. + Optional filter for live tv series. + Optional filter for live tv news. + Optional filter for live tv kids. + Optional filter for live tv sports. + Optional. If specified, results will be filtered by excluding item ids. This allows multiple, comma delimited. + Optional. The record index to start at. All items with a lower index will be dropped from the results. + Optional. The maximum number of records to return. + When searching within folders, this determines whether or not the search will be recursive. true/false. + Optional. Filter based on a search term. + Sort Order - Ascending, Descending. + Specify this to localize the search to a specific item or folder. Omit to use the root. + Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines. + Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited. + Optional. If specified, results will be filtered based on the item type. This allows multiple, comma delimited. + Optional. Specify additional filters to apply. This allows multiple, comma delimited. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes. + Optional filter by items that are marked as favorite, or not. + Optional filter by MediaType. Allows multiple, comma delimited. + Optional. If specified, results will be filtered based on those containing image types. This allows multiple, comma delimited. + Optional. Specify one or more sort orders, comma delimited. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime. + Optional filter by items that are played, or not. + Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on OfficialRating. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on tag. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on production year. This allows multiple, comma delimited. + Optional, include user data. + Optional, the max number of images to return, per image type. + Optional. The image types to include in the output. + Optional. If specified, results will be filtered to include only those containing the specified person. + Optional. If specified, results will be filtered to include only those containing the specified person id. + Optional. If specified, along with Person, results will be filtered to include only those containing the specified person and PersonType. Allows multiple, comma-delimited. + Optional. If specified, results will be filtered based on studio. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on artists. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on artist id. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered to include only those containing the specified artist id. + Optional. If specified, results will be filtered to include only those containing the specified album artist id. + Optional. If specified, results will be filtered to include only those containing the specified contributing artist id. + Optional. If specified, results will be filtered based on album. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on album id. This allows multiple, pipe delimited. + Optional. If specific items are needed, specify a list of item id's to retrieve. This allows multiple, comma delimited. + Optional filter by VideoType (videofile, dvd, bluray, iso). Allows multiple, comma delimited. + Optional filter by minimum official rating (PG, PG-13, TV-MA, etc). + Optional filter by items that are locked. + Optional filter by items that are placeholders. + Optional filter by items that have official ratings. + Whether or not to hide items behind their boxsets. + Optional. Filter by the minimum width of the item. + Optional. Filter by the minimum height of the item. + Optional. Filter by the maximum width of the item. + Optional. Filter by the maximum height of the item. + Optional filter by items that are 3D, or not. + Optional filter by Series Status. Allows multiple, comma delimited. + Optional filter by items whose name is sorted equally or greater than a given input string. + Optional filter by items whose name is sorted equally than a given input string. + Optional filter by items whose name is equally or lesser than a given input string. + Optional. If specified, results will be filtered based on studio id. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on genre id. This allows multiple, pipe delimited. + Optional. Enable the total record count. + Optional, include image information in output. + A with the items. + + + + Gets items based on a query. + + The user id. + The start index. + The item limit. + The search term. + Specify this to localize the search to a specific item or folder. Omit to use the root. + Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines. + Optional. Filter by MediaType. Allows multiple, comma delimited. + Optional. Include user data. + Optional. The max number of images to return, per image type. + Optional. The image types to include in the output. + Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited. + Optional. If specified, results will be filtered based on the item type. This allows multiple, comma delimited. + Optional. Enable the total record count. + Optional. Include image information in output. + Optional. Whether to exclude the currently active sessions. + Items returned. + A with the items that are resumable. + + + + Gets items based on a query. + + The user id. + The start index. + The item limit. + The search term. + Specify this to localize the search to a specific item or folder. Omit to use the root. + Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines. + Optional. Filter by MediaType. Allows multiple, comma delimited. + Optional. Include user data. + Optional. The max number of images to return, per image type. + Optional. The image types to include in the output. + Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited. + Optional. If specified, results will be filtered based on the item type. This allows multiple, comma delimited. + Optional. Enable the total record count. + Optional. Include image information in output. + Optional. Whether to exclude the currently active sessions. + Items returned. + A with the items that are resumable. + + + + Get Item User Data. + + The user id. + The item id. + return item user data. + Item is not found. + Return . + + + + Get Item User Data. + + The user id. + The item id. + return item user data. + Item is not found. + Return . + + + + Update Item User Data. + + The user id. + The item id. + New user data object. + return updated user item data. + Item is not found. + Return . + + + + Update Item User Data. + + The user id. + The item id. + New user data object. + return updated user item data. + Item is not found. + Return . + + + + Item update controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Updates an item. + + The item id. + The new item properties. + Item updated. + Item not found. + An on success, or a if the item could not be found. + + + + Gets metadata editor info for an item. + + The item id. + Item metadata editor returned. + Item not found. + An on success containing the metadata editor, or a if the item could not be found. + + + + Updates an item's content type. + + The item id. + The content type of the item. + Item content type updated. + Item not found. + An on success, or a if the item could not be found. + + + + Library Controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Get the original file of an item. + + The item id. + File stream returned. + Item not found. + A with the original file. + + + + Gets critic review for an item. + + Critic reviews returned. + The list of critic reviews. + + + + Get theme songs for an item. + + The item id. + Optional. Filter by user id, and attach user data. + Optional. Determines whether or not parent items should be searched for theme media. + Optional. Specify one or more sort orders, comma delimited. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime. + Optional. Sort Order - Ascending, Descending. + Theme songs returned. + Item not found. + The item theme songs. + + + + Get theme videos for an item. + + The item id. + Optional. Filter by user id, and attach user data. + Optional. Determines whether or not parent items should be searched for theme media. + Optional. Specify one or more sort orders, comma delimited. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime. + Optional. Sort Order - Ascending, Descending. + Theme videos returned. + Item not found. + The item theme videos. + + + + Get theme songs and videos for an item. + + The item id. + Optional. Filter by user id, and attach user data. + Optional. Determines whether or not parent items should be searched for theme media. + Optional. Specify one or more sort orders, comma delimited. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime. + Optional. Sort Order - Ascending, Descending. + Theme songs and videos returned. + Item not found. + The item theme videos. + + + + Starts a library scan. + + Library scan started. + A . + + + + Deletes an item from the library and filesystem. + + The item id. + Item deleted. + Unauthorized access. + Item not found. + A . + + + + Deletes items from the library and filesystem. + + The item ids. + Items deleted. + Unauthorized access. + A . + + + + Get item counts. + + Optional. Get counts from a specific user's library. + Optional. Get counts of favorite items. + Item counts returned. + Item counts. + + + + Gets all parents of an item. + + The item id. + Optional. Filter by user id, and attach user data. + Item parents returned. + Item not found. + Item parents. + + + + Gets a list of physical paths from virtual folders. + + Physical paths returned. + List of physical paths. + + + + Gets all user media folders. + + Optional. Filter by folders that are marked hidden, or not. + Media folders returned. + List of user media folders. + + + + Reports that new episodes of a series have been added by an external source. + + The tvdbId. + Report success. + A . + + + + Reports that new movies have been added by an external source. + + The tmdbId. + The imdbId. + Report success. + A . + + + + Reports that new movies have been added by an external source. + + The update paths. + Report success. + A . + + + + Downloads item media. + + The item id. + Media downloaded. + Item not found. + A containing the media stream. + User can't download or item can't be downloaded. + + + + Gets similar items. + + The item id. + Exclude artist ids. + Optional. Filter by user id, and attach user data. + Optional. The maximum number of records to return. + Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls. + Similar items returned. + A containing the similar items. + + + + Gets the library options info. + + Library content type. + Whether this is a new library. + Library options info returned. + Library options info. + + + + The library structure controller. + + + + + Initializes a new instance of the class. + + Instance of interface. + Instance of interface. + Instance of interface. + + + + Gets all virtual folders. + + Virtual folders retrieved. + An with the virtual folders. + + + + Adds a virtual folder. + + The name of the virtual folder. + The type of the collection. + The paths of the virtual folder. + The library options. + Whether to refresh the library. + Folder added. + A . + + + + Removes a virtual folder. + + The name of the folder. + Whether to refresh the library. + Folder removed. + Folder not found. + A . + + + + Renames a virtual folder. + + The name of the virtual folder. + The new name. + Whether to refresh the library. + Folder renamed. + Library doesn't exist. + Library already exists. + A on success, a if the library doesn't exist, a if the new name is already taken. + The new name may not be null. + + + + Add a media path to a library. + + The media path dto. + Whether to refresh the library. + A . + Media path added. + The name of the library may not be empty. + + + + Updates a media path. + + The name of the library and path infos. + A . + Media path updated. + The name of the library may not be empty. + + + + Remove a media path. + + The name of the library. + The path to remove. + Whether to refresh the library. + A . + Media path removed. + The name of the library and path may not be empty. + + + + Update library options. + + The library name and options. + Library updated. + Item not found. + A . + + + + Live tv controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Gets available live tv services. + + Available live tv services returned. + + An containing the available live tv services. + + + + + Gets available live tv channels. + + Optional. Filter by channel type. + Optional. Filter by user and attach user data. + Optional. The record index to start at. All items with a lower index will be dropped from the results. + Optional. Filter for movies. + Optional. Filter for series. + Optional. Filter for news. + Optional. Filter for kids. + Optional. Filter for sports. + Optional. The maximum number of records to return. + Optional. Filter by channels that are favorites, or not. + Optional. Filter by channels that are liked, or not. + Optional. Filter by channels that are disliked, or not. + Optional. Include image information in output. + Optional. The max number of images to return, per image type. + "Optional. The image types to include in the output. + Optional. Specify additional fields of information to return in the output. + Optional. Include user data. + Optional. Key to sort by. + Optional. Sort order. + Optional. Incorporate favorite and like status into channel sorting. + Optional. Adds current program info to each channel. + Available live tv channels returned. + + An containing the resulting available live tv channels. + + + + + Gets a live tv channel. + + Channel id. + Optional. Attach user data. + Live tv channel returned. + Item not found. + An containing the live tv channel. + + + + Gets live tv recordings. + + Optional. Filter by channel id. + Optional. Filter by user and attach user data. + Optional. The record index to start at. All items with a lower index will be dropped from the results. + Optional. The maximum number of records to return. + Optional. Filter by recording status. + Optional. Filter by recordings that are in progress, or not. + Optional. Filter by recordings belonging to a series timer. + Optional. Include image information in output. + Optional. The max number of images to return, per image type. + Optional. The image types to include in the output. + Optional. Specify additional fields of information to return in the output. + Optional. Include user data. + Optional. Filter for movies. + Optional. Filter for series. + Optional. Filter for kids. + Optional. Filter for sports. + Optional. Filter for news. + Optional. Filter for is library item. + Optional. Return total record count. + Live tv recordings returned. + An containing the live tv recordings. + + + + Gets live tv recording series. + + Optional. Filter by channel id. + Optional. Filter by user and attach user data. + Optional. Filter by recording group. + Optional. The record index to start at. All items with a lower index will be dropped from the results. + Optional. The maximum number of records to return. + Optional. Filter by recording status. + Optional. Filter by recordings that are in progress, or not. + Optional. Filter by recordings belonging to a series timer. + Optional. Include image information in output. + Optional. The max number of images to return, per image type. + Optional. The image types to include in the output. + Optional. Specify additional fields of information to return in the output. + Optional. Include user data. + Optional. Return total record count. + Live tv recordings returned. + An containing the live tv recordings. + + + + Gets live tv recording groups. + + Optional. Filter by user and attach user data. + Recording groups returned. + An containing the recording groups. + + + + Gets recording folders. + + Optional. Filter by user and attach user data. + Recording folders returned. + An containing the recording folders. + + + + Gets a live tv recording. + + Recording id. + Optional. Attach user data. + Recording returned. + Item not found. + An containing the live tv recording. + + + + Resets a tv tuner. + + Tuner id. + Tuner reset. + A . + + + + Gets a timer. + + Timer id. + Timer returned. + + A containing an which contains the timer. + + + + + Gets the default values for a new timer. + + Optional. To attach default values based on a program. + Default values returned. + + A containing an which contains the default values for a timer. + + + + + Gets the live tv timers. + + Optional. Filter by channel id. + Optional. Filter by timers belonging to a series timer. + Optional. Filter by timers that are active. + Optional. Filter by timers that are scheduled. + + A containing an which contains the live tv timers. + + + + + Gets available live tv epgs. + + The channels to return guide information for. + Optional. Filter by user id. + Optional. The minimum premiere start date. + Optional. Filter by programs that have completed airing, or not. + Optional. Filter by programs that are currently airing, or not. + Optional. The maximum premiere start date. + Optional. The minimum premiere end date. + Optional. The maximum premiere end date. + Optional. Filter for movies. + Optional. Filter for series. + Optional. Filter for news. + Optional. Filter for kids. + Optional. Filter for sports. + Optional. The record index to start at. All items with a lower index will be dropped from the results. + Optional. The maximum number of records to return. + Optional. Specify one or more sort orders, comma delimited. Options: Name, StartDate. + Sort Order - Ascending,Descending. + The genres to return guide information for. + The genre ids to return guide information for. + Optional. Include image information in output. + Optional. The max number of images to return, per image type. + Optional. The image types to include in the output. + Optional. Include user data. + Optional. Filter by series timer id. + Optional. Filter by library series id. + Optional. Specify additional fields of information to return in the output. + Retrieve total record count. + Live tv epgs returned. + + A containing a which contains the live tv epgs. + + + + + Gets available live tv epgs. + + Request body. + Live tv epgs returned. + + A containing a which contains the live tv epgs. + + + + + Gets recommended live tv epgs. + + Optional. filter by user id. + Optional. The record index to start at. All items with a lower index will be dropped from the results. + Optional. The maximum number of records to return. + Optional. Filter by programs that are currently airing, or not. + Optional. Filter by programs that have completed airing, or not. + Optional. Filter for series. + Optional. Filter for movies. + Optional. Filter for news. + Optional. Filter for kids. + Optional. Filter for sports. + Optional. Include image information in output. + Optional. The max number of images to return, per image type. + Optional. The image types to include in the output. + The genres to return guide information for. + Optional. Specify additional fields of information to return in the output. + Optional. include user data. + Retrieve total record count. + Recommended epgs returned. + A containing the queryresult of recommended epgs. + + + + Gets a live tv program. + + Program id. + Optional. Attach user data. + Program returned. + An containing the livetv program. + + + + Deletes a live tv recording. + + Recording id. + Recording deleted. + Item not found. + A on success, or a if item not found. + + + + Cancels a live tv timer. + + Timer id. + Timer deleted. + A . + + + + Updates a live tv timer. + + Timer id. + New timer info. + Timer updated. + A . + + + + Creates a live tv timer. + + New timer info. + Timer created. + A . + + + + Gets a live tv series timer. + + Timer id. + Series timer returned. + Series timer not found. + A on success, or a if timer not found. + + + + Gets live tv series timers. + + Optional. Sort by SortName or Priority. + Optional. Sort in Ascending or Descending order. + Timers returned. + An of live tv series timers. + + + + Cancels a live tv series timer. + + Timer id. + Timer cancelled. + A . + + + + Updates a live tv series timer. + + Timer id. + New series timer info. + Series timer updated. + A . + + + + Creates a live tv series timer. + + New series timer info. + Series timer info created. + A . + + + + Get recording group. + + Group id. + A . + + + + Get guide info. + + Guide info returned. + An containing the guide info. + + + + Adds a tuner host. + + New tuner host. + Created tuner host returned. + A containing the created tuner host. + + + + Deletes a tuner host. + + Tuner host id. + Tuner host deleted. + A . + + + + Gets default listings provider info. + + Default listings provider info returned. + An containing the default listings provider info. + + + + Adds a listings provider. + + Password. + New listings info. + Validate listings. + Validate login. + Created listings provider returned. + A containing the created listings provider. + + + + Delete listing provider. + + Listing provider id. + Listing provider deleted. + A . + + + + Gets available lineups. + + Provider id. + Provider type. + Location. + Country. + Available lineups returned. + A containing the available lineups. + + + + Gets available countries. + + Available countries returned. + A containing the available countries. + + + + Get channel mapping options. + + Provider id. + Channel mapping options returned. + An containing the channel mapping options. + + + + Set channel mappings. + + The set channel mapping dto. + Created channel mapping returned. + An containing the created channel mapping. + + + + Get tuner host types. + + Tuner host types returned. + An containing the tuner host types. + + + + Discover tuners. + + Only discover new tuners. + Tuners returned. + An containing the tuners. + + + + Gets a live tv recording stream. + + Recording id. + Recording stream returned. + Recording not found. + + An containing the recording stream on success, + or a if recording not found. + + + + + Gets a live tv channel stream. + + Stream id. + Container type. + Stream returned. + Stream not found. + + An containing the channel stream on success, + or a if stream not found. + + + + + Localization controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + Gets known cultures. + + Known cultures returned. + An containing the list of cultures. + + + + Gets known countries. + + Known countries returned. + An containing the list of countries. + + + + Gets known parental ratings. + + Known parental ratings returned. + An containing the list of parental ratings. + + + + Gets localization options. + + Localization options returned. + An containing the list of localization options. + + + + Lyrics controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Gets an item's lyrics. + + Item id. + Lyrics returned. + Something went wrong. No Lyrics will be returned. + An containing the item's lyrics. + + + + Upload an external lyric file. + + The item the lyric belongs to. + Name of the file being uploaded. + Lyrics uploaded. + Error processing upload. + Item not found. + The uploaded lyric. + + + + Deletes an external lyric file. + + The item id. + Lyric deleted. + Item not found. + A . + + + + Search remote lyrics. + + The item id. + Lyrics retrieved. + Item not found. + An array of . + + + + Downloads a remote lyric. + + The item id. + The lyric id. + Lyric downloaded. + Item not found. + A . + + + + Gets the remote lyrics. + + The remote provider item id. + File returned. + Lyric not found. + A with the lyric file. + + + + The media info controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the . + Instance of the interface.. + + + + Gets live playback media info for an item. + + The item id. + The user id. + Playback info returned. + Item not found. + A containing a with the playback information. + + + + Gets live playback media info for an item. + + + For backwards compatibility parameters can be sent via Query or Body, with Query having higher precedence. + Query parameters are obsolete. + + The item id. + The user id. + The maximum streaming bitrate. + The start time in ticks. + The audio stream index. + The subtitle stream index. + The maximum number of audio channels. + The media source id. + The livestream id. + Whether to auto open the livestream. + Whether to enable direct play. Default: true. + Whether to enable direct stream. Default: true. + Whether to enable transcoding. Default: true. + Whether to allow to copy the video stream. Default: true. + Whether to allow to copy the audio stream. Default: true. + The playback info. + Playback info returned. + Item not found. + A containing a with the playback info. + + + + Opens a media source. + + The open token. + The user id. + The play session id. + The maximum streaming bitrate. + The start time in ticks. + The audio stream index. + The subtitle stream index. + The maximum number of audio channels. + The item id. + The open live stream dto. + Whether to enable direct play. Default: true. + Whether to enable direct stream. Default: true. + Always burn-in subtitle when transcoding. + Media source opened. + A containing a . + + + + Closes a media source. + + The livestream id. + Livestream closed. + A indicating success. + + + + Tests the network with a request with the size of the bitrate. + + The bitrate. Defaults to 102400. + Test buffer returned. + A with specified bitrate. + + + + Media Segments api. + + + + + Initializes a new instance of the class. + + MediaSegments Manager. + The Library manager. + + + + Gets all media segments based on an itemId. + + The ItemId. + Optional filter of requested segment types. + A list of media segment objects related to the requested itemId. + + + + Movies controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Gets movie recommendations. + + Optional. Filter by user id, and attach user data. + Specify this to localize the search to a specific item or folder. Omit to use the root. + Optional. The fields to return. + The max number of categories to return. + The max number of items to return per category. + Movie recommendations returned. + The list of movie recommendations. + + + + The music genres controller. + + + + + Initializes a new instance of the class. + + Instance of interface. + Instance of interface. + Instance of interface. + + + + Gets all music genres from a given item, folder, or the entire library. + + Optional. The record index to start at. All items with a lower index will be dropped from the results. + Optional. The maximum number of records to return. + The search term. + Specify this to localize the search to a specific item or folder. Omit to use the root. + Optional. Specify additional fields of information to return in the output. + Optional. If specified, results will be filtered out based on item type. This allows multiple, comma delimited. + Optional. If specified, results will be filtered in based on item type. This allows multiple, comma delimited. + Optional filter by items that are marked as favorite, or not. + Optional, the max number of images to return, per image type. + Optional. The image types to include in the output. + User id. + Optional filter by items whose name is sorted equally or greater than a given input string. + Optional filter by items whose name is sorted equally than a given input string. + Optional filter by items whose name is equally or lesser than a given input string. + Optional. Specify one or more sort orders, comma delimited. + Sort Order - Ascending,Descending. + Optional, include image information in output. + Optional. Include total record count. + Music genres returned. + An containing the queryresult of music genres. + + + + Gets a music genre, by name. + + The genre name. + Optional. Filter by user id, and attach user data. + An containing a with the music genre. + + + + Package Controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + + Gets a package by name or assembly GUID. + + The name of the package. + The GUID of the associated assembly. + Package retrieved. + A containing package information. + + + + Gets available packages. + + Available packages returned. + An containing available packages information. + + + + Installs a package. + + Package name. + GUID of the associated assembly. + Optional version. Defaults to latest version. + Optional. Specify the repository to install from. + Package found. + Package not found. + A on success, or a if the package could not be found. + + + + Cancels a package installation. + + Installation Id. + Installation cancelled. + A on successfully cancelling a package installation. + + + + Gets all package repositories. + + Package repositories returned. + An containing the list of package repositories. + + + + Sets the enabled and existing package repositories. + + The list of package repositories. + Package repositories saved. + A . + + + + Persons controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Gets all persons. + + Optional. The maximum number of records to return. + The search term. + Optional. Specify additional fields of information to return in the output. + Optional. Specify additional filters to apply. + Optional filter by items that are marked as favorite, or not. userId is required. + Optional, include user data. + Optional, the max number of images to return, per image type. + Optional. The image types to include in the output. + Optional. If specified results will be filtered to exclude those containing the specified PersonType. Allows multiple, comma-delimited. + Optional. If specified results will be filtered to include only those containing the specified PersonType. Allows multiple, comma-delimited. + Optional. If specified, person results will be filtered on items related to said persons. + User id. + Optional, include image information in output. + Persons returned. + An containing the queryresult of persons. + + + + Get person by name. + + Person name. + Optional. Filter by user id, and attach user data. + Person returned. + Person not found. + An containing the person on success, + or a if person not found. + + + + Playlists controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Creates a new playlist. + + + For backwards compatibility parameters can be sent via Query or Body, with Query having higher precedence. + Query parameters are obsolete. + + The playlist name. + The item ids. + The user id. + The media type. + The create playlist payload. + Playlist created. + + A that represents the asynchronous operation to create a playlist. + The task result contains an indicating success. + + + + + Updates a playlist. + + The playlist id. + The id. + Playlist updated. + Access forbidden. + Playlist not found. + + A that represents the asynchronous operation to update a playlist. + The task result contains an indicating success. + + + + + Get a playlist. + + The playlist id. + The playlist. + Playlist not found. + + A objects. + + + + + Get a playlist's users. + + The playlist id. + Found shares. + Access forbidden. + Playlist not found. + + A list of objects. + + + + + Get a playlist user. + + The playlist id. + The user id. + User permission found. + Access forbidden. + Playlist not found. + + . + + + + + Modify a user of a playlist's users. + + The playlist id. + The user id. + The . + User's permissions modified. + Access forbidden. + Playlist not found. + + A that represents the asynchronous operation to modify an user's playlist permissions. + The task result contains an indicating success. + + + + + Remove a user from a playlist's users. + + The playlist id. + The user id. + User permissions removed from playlist. + Unauthorized access. + No playlist or user permissions found. + + A that represents the asynchronous operation to delete a user from a playlist's shares. + The task result contains an indicating success. + + + + + Adds items to a playlist. + + The playlist id. + Item id, comma delimited. + Optional. 0-based index where to place the items or at the end if null. + The userId. + Items added to playlist. + Access forbidden. + Playlist not found. + An on success. + + + + Moves a playlist item. + + The playlist id. + The item id. + The new index. + Item moved to new index. + Access forbidden. + Playlist not found. + An on success. + + + + Removes items from a playlist. + + The playlist id. + The item ids, comma delimited. + Items removed. + Access forbidden. + Playlist not found. + An on success. + + + + Gets the original items of a playlist. + + The playlist id. + User id. + Optional. The record index to start at. All items with a lower index will be dropped from the results. + Optional. The maximum number of records to return. + Optional. Specify additional fields of information to return in the output. + Optional. Include image information in output. + Optional. Include user data. + Optional. The max number of images to return, per image type. + Optional. The image types to include in the output. + Original playlist returned. + Access forbidden. + Playlist not found. + The original playlist items. + + + + Playstate controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Marks an item as played for user. + + User id. + Item id. + Optional. The date the item was played. + Item marked as played. + Item not found. + An containing the , or a if item was not found. + + + + Marks an item as played for user. + + User id. + Item id. + Optional. The date the item was played. + Item marked as played. + Item not found. + An containing the , or a if item was not found. + + + + Marks an item as unplayed for user. + + User id. + Item id. + Item marked as unplayed. + Item not found. + A containing the , or a if item was not found. + + + + Marks an item as unplayed for user. + + User id. + Item id. + Item marked as unplayed. + Item not found. + A containing the , or a if item was not found. + + + + Reports playback has started within a session. + + The playback start info. + Playback start recorded. + A . + + + + Reports playback progress within a session. + + The playback progress info. + Playback progress recorded. + A . + + + + Pings a playback session. + + Playback session id. + Playback session pinged. + A . + + + + Reports playback has stopped within a session. + + The playback stop info. + Playback stop recorded. + A . + + + + Reports that a session has begun playing an item. + + Item id. + The id of the MediaSource. + The audio stream index. + The subtitle stream index. + The play method. + The live stream id. + The play session id. + Indicates if the client can seek. + Play start recorded. + A . + + + + Reports that a user has begun playing an item. + + User id. + Item id. + The id of the MediaSource. + The audio stream index. + The subtitle stream index. + The play method. + The live stream id. + The play session id. + Indicates if the client can seek. + Play start recorded. + A . + + + + Reports a session's playback progress. + + Item id. + The id of the MediaSource. + Optional. The current position, in ticks. 1 tick = 10000 ms. + The audio stream index. + The subtitle stream index. + Scale of 0-100. + The play method. + The live stream id. + The play session id. + The repeat mode. + Indicates if the player is paused. + Indicates if the player is muted. + Play progress recorded. + A . + + + + Reports a user's playback progress. + + User id. + Item id. + The id of the MediaSource. + Optional. The current position, in ticks. 1 tick = 10000 ms. + The audio stream index. + The subtitle stream index. + Scale of 0-100. + The play method. + The live stream id. + The play session id. + The repeat mode. + Indicates if the player is paused. + Indicates if the player is muted. + Play progress recorded. + A . + + + + Reports that a session has stopped playing an item. + + Item id. + The id of the MediaSource. + The next media type that will play. + Optional. The position, in ticks, where playback stopped. 1 tick = 10000 ms. + The live stream id. + The play session id. + Playback stop recorded. + A . + + + + Reports that a user has stopped playing an item. + + User id. + Item id. + The id of the MediaSource. + The next media type that will play. + Optional. The position, in ticks, where playback stopped. 1 tick = 10000 ms. + The live stream id. + The play session id. + Playback stop recorded. + A . + + + + Updates the played status. + + The user. + The item. + if set to true [was played]. + The date played. + Task. + + + + Plugins controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + + Gets a list of currently installed plugins. + + Installed plugins returned. + List of currently installed plugins. + + + + Enables a disabled plugin. + + Plugin id. + Plugin version. + Plugin enabled. + Plugin not found. + An on success, or a if the plugin could not be found. + + + + Disable a plugin. + + Plugin id. + Plugin version. + Plugin disabled. + Plugin not found. + An on success, or a if the plugin could not be found. + + + + Uninstalls a plugin by version. + + Plugin id. + Plugin version. + Plugin uninstalled. + Plugin not found. + An on success, or a if the plugin could not be found. + + + + Uninstalls a plugin. + + Plugin id. + Plugin uninstalled. + Plugin not found. + An on success, or a if the plugin could not be found. + + + + Gets plugin configuration. + + Plugin id. + Plugin configuration returned. + Plugin not found or plugin configuration not found. + Plugin configuration. + + + + Updates plugin configuration. + + + Accepts plugin configuration as JSON body. + + Plugin id. + Plugin configuration updated. + Plugin not found or plugin does not have configuration. + An on success, or a if the plugin could not be found. + + + + Gets a plugin's image. + + Plugin id. + Plugin version. + Plugin image returned. + Plugin's image. + + + + Gets a plugin's manifest. + + Plugin id. + Plugin manifest returned. + Plugin not found. + A on success, or a if the plugin could not be found. + + + + Quick connect controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + + Gets the current quick connect state. + + Quick connect state returned. + Whether Quick Connect is enabled on the server or not. + + + + Initiate a new quick connect request. + + Quick connect request successfully created. + Quick connect is not active on this server. + A with a secret and code for future use or an error message. + + + + Attempts to retrieve authentication information. + + Secret previously returned from the Initiate endpoint. + Quick connect result returned. + Unknown quick connect secret. + An updated . + + + + Authorizes a pending quick connect request. + + Quick connect code to authorize. + The user the authorize. Access to the requested user is required. + Quick connect result authorized successfully. + Unknown user id. + Boolean indicating if the authorization was successful. + + + + Remote Images Controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Gets available remote images for an item. + + Item Id. + The image type. + Optional. The record index to start at. All items with a lower index will be dropped from the results. + Optional. The maximum number of records to return. + Optional. The image provider to use. + Optional. Include all languages. + Remote Images returned. + Item not found. + Remote Image Result. + + + + Gets available remote image providers for an item. + + Item Id. + Returned remote image providers. + Item not found. + List of remote image providers. + + + + Downloads a remote image for an item. + + Item Id. + The image type. + The image url. + Remote image downloaded. + Remote image not found. + Download status. + + + + Gets the full cache path. + + The filename. + System.String. + + + + Scheduled Tasks Controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + Get tasks. + + Optional filter tasks that are hidden, or not. + Optional filter tasks that are enabled, or not. + Scheduled tasks retrieved. + The list of scheduled tasks. + + + + Get task by id. + + Task Id. + Task retrieved. + Task not found. + An containing the task on success, or a if the task could not be found. + + + + Start specified task. + + Task Id. + Task started. + Task not found. + An on success, or a if the file could not be found. + + + + Stop specified task. + + Task Id. + Task stopped. + Task not found. + An on success, or a if the file could not be found. + + + + Update specified task triggers. + + Task Id. + Triggers. + Task triggers updated. + Task not found. + An on success, or a if the file could not be found. + + + + Search controller. + + + + + Initializes a new instance of the class. + + Instance of interface. + Instance of interface. + Instance of interface. + Instance of interface. + + + + Gets the search hint result. + + Optional. The record index to start at. All items with a lower index will be dropped from the results. + Optional. The maximum number of records to return. + Optional. Supply a user id to search within a user's library or omit to search all. + The search term to filter on. + If specified, only results with the specified item types are returned. This allows multiple, comma delimited. + If specified, results with these item types are filtered out. This allows multiple, comma delimited. + If specified, only results with the specified media types are returned. This allows multiple, comma delimited. + If specified, only children of the parent are returned. + Optional filter for movies. + Optional filter for series. + Optional filter for news. + Optional filter for kids. + Optional filter for sports. + Optional filter whether to include people. + Optional filter whether to include media. + Optional filter whether to include genres. + Optional filter whether to include studios. + Optional filter whether to include artists. + Search hint returned. + An with the results of the search. + + + + Gets the search hint result. + + The hint info. + SearchHintResult. + + + + The session controller. + + + + + Initializes a new instance of the class. + + Instance of interface. + Instance of interface. + + + + Gets a list of sessions. + + Filter by sessions that a given user is allowed to remote control. + Filter by device Id. + Optional. Filter by sessions that were active in the last n seconds. + List of sessions returned. + An with the available sessions. + + + + Instructs a session to browse to an item or view. + + The session Id. + The type of item to browse to. + The Id of the item. + The name of the item. + Instruction sent to session. + A . + + + + Instructs a session to play an item. + + The session id. + The type of play command to issue (PlayNow, PlayNext, PlayLast). Clients who have not yet implemented play next and play last may play now. + The ids of the items to play, comma delimited. + The starting position of the first item. + Optional. The media source id. + Optional. The index of the audio stream to play. + Optional. The index of the subtitle stream to play. + Optional. The start index. + Instruction sent to session. + A . + + + + Issues a playstate command to a client. + + The session id. + The . + The optional position ticks. + The optional controlling user id. + Playstate command sent to session. + A . + + + + Issues a system command to a client. + + The session id. + The command to send. + System command sent to session. + A . + + + + Issues a general command to a client. + + The session id. + The command to send. + General command sent to session. + A . + + + + Issues a full general command to a client. + + The session id. + The . + Full general command sent to session. + A . + + + + Issues a command to a client to display a message to the user. + + The session id. + The object containing Header, Message Text, and TimeoutMs. + Message sent. + A . + + + + Adds an additional user to a session. + + The session id. + The user id. + User added to session. + A . + + + + Removes an additional user from a session. + + The session id. + The user id. + User removed from session. + A . + + + + Updates capabilities for a device. + + The session id. + A list of playable media types, comma delimited. Audio, Video, Book, Photo. + A list of supported remote control commands, comma delimited. + Determines whether media can be played remotely.. + Determines whether the device supports a unique identifier. + Capabilities posted. + A . + + + + Updates capabilities for a device. + + The session id. + The . + Capabilities updated. + A . + + + + Reports that a session is viewing an item. + + The session id. + The item id. + Session reported to server. + A . + + + + Reports that a session has ended. + + Session end reported to server. + A . + + + + Get all auth providers. + + Auth providers retrieved. + An with the auth providers. + + + + Get all password reset providers. + + Password reset providers retrieved. + An with the password reset providers. + + + + The startup wizard controller. + + + + + Initializes a new instance of the class. + + The server configuration manager. + The user manager. + + + + Completes the startup wizard. + + Startup wizard completed. + A indicating success. + + + + Gets the initial startup wizard configuration. + + Initial startup wizard configuration retrieved. + An containing the initial startup wizard configuration. + + + + Sets the initial startup wizard configuration. + + The updated startup configuration. + Configuration saved. + A indicating success. + + + + Sets remote access and UPnP. + + The startup remote access dto. + Configuration saved. + A indicating success. + + + + Gets the first user. + + Initial user retrieved. + The first user. + + + + Sets the user name and password. + + The DTO containing username and password. + Updated user name and password. + + A that represents the asynchronous update operation. + The task result contains a indicating success. + + + + + Studios controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Gets all studios from a given item, folder, or the entire library. + + Optional. The record index to start at. All items with a lower index will be dropped from the results. + Optional. The maximum number of records to return. + Optional. Search term. + Specify this to localize the search to a specific item or folder. Omit to use the root. + Optional. Specify additional fields of information to return in the output. + Optional. If specified, results will be filtered out based on item type. This allows multiple, comma delimited. + Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited. + Optional filter by items that are marked as favorite, or not. + Optional, include user data. + Optional, the max number of images to return, per image type. + Optional. The image types to include in the output. + User id. + Optional filter by items whose name is sorted equally or greater than a given input string. + Optional filter by items whose name is sorted equally than a given input string. + Optional filter by items whose name is equally or lesser than a given input string. + Optional, include image information in output. + Total record count. + Studios returned. + An containing the studios. + + + + Gets a studio by name. + + Studio name. + Optional. Filter by user id, and attach user data. + Studio returned. + An containing the studio. + + + + Subtitle controller. + + + + + Initializes a new instance of the class. + + Instance of interface. + Instance of interface. + Instance of interface. + Instance of interface. + Instance of interface. + Instance of interface. + Instance of interface. + Instance of interface. + + + + Deletes an external subtitle file. + + The item id. + The index of the subtitle file. + Subtitle deleted. + Item not found. + A . + + + + Search remote subtitles. + + The item id. + The language of the subtitles. + Optional. Only show subtitles which are a perfect match. + Subtitles retrieved. + Item not found. + An array of . + + + + Downloads a remote subtitle. + + The item id. + The subtitle id. + Subtitle downloaded. + Item not found. + A . + + + + Gets the remote subtitles. + + The item id. + File returned. + A with the subtitle file. + + + + Gets subtitles in a specified format. + + The (route) item id. + The (route) media source id. + The (route) subtitle stream index. + The (route) format of the returned subtitle. + The item id. + The media source id. + The subtitle stream index. + The format of the returned subtitle. + Optional. The end position of the subtitle in ticks. + Optional. Whether to copy the timestamps. + Optional. Whether to add a VTT time map. + The start position of the subtitle in ticks. + File returned. + A with the subtitle file. + + + + Gets subtitles in a specified format. + + The (route) item id. + The (route) media source id. + The (route) subtitle stream index. + The (route) start position of the subtitle in ticks. + The (route) format of the returned subtitle. + The item id. + The media source id. + The subtitle stream index. + The start position of the subtitle in ticks. + The format of the returned subtitle. + Optional. The end position of the subtitle in ticks. + Optional. Whether to copy the timestamps. + Optional. Whether to add a VTT time map. + File returned. + A with the subtitle file. + + + + Gets an HLS subtitle playlist. + + The item id. + The subtitle stream index. + The media source id. + The subtitle segment length. + Subtitle playlist retrieved. + Item not found. + A with the HLS subtitle playlist. + + + + Upload an external subtitle file. + + The item the subtitle belongs to. + The request body. + Subtitle uploaded. + Item not found. + A . + + + + Encodes a subtitle in the specified format. + + The media id. + The source media id. + The subtitle index. + The format to convert to. + The start position in ticks. + The end position in ticks. + Whether to copy the timestamps. + A with the new subtitle file. + + + + Gets a list of available fallback font files. + + Information retrieved. + An array of with the available font files. + + + + Gets a fallback font file. + + The name of the fallback font file to get. + Fallback font file retrieved. + The fallback font file. + + + + The suggestions controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Gets suggestions. + + The user id. + The media types. + The type. + Optional. The start index. + Optional. The limit. + Whether to enable the total record count. + Suggestions returned. + A with the suggestions. + + + + Gets suggestions. + + The user id. + The media types. + The type. + Optional. The start index. + Optional. The limit. + Whether to enable the total record count. + Suggestions returned. + A with the suggestions. + + + + The sync play controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Create a new SyncPlay group. + + The settings of the new group. + New group created. + An for the created group. + + + + Join an existing SyncPlay group. + + The group to join. + Group join successful. + A indicating success. + + + + Leave the joined SyncPlay group. + + Group leave successful. + A indicating success. + + + + Gets all SyncPlay groups. + + Groups returned. + An containing the available SyncPlay groups. + + + + Gets a SyncPlay group by id. + + The id of the group. + Group returned. + An for the requested group. + + + + Request to set new playlist in SyncPlay group. + + The new playlist to play in the group. + Queue update sent to all group members. + A indicating success. + + + + Request to change playlist item in SyncPlay group. + + The new item to play. + Queue update sent to all group members. + A indicating success. + + + + Request to remove items from the playlist in SyncPlay group. + + The items to remove. + Queue update sent to all group members. + A indicating success. + + + + Request to move an item in the playlist in SyncPlay group. + + The new position for the item. + Queue update sent to all group members. + A indicating success. + + + + Request to queue items to the playlist of a SyncPlay group. + + The items to add. + Queue update sent to all group members. + A indicating success. + + + + Request unpause in SyncPlay group. + + Unpause update sent to all group members. + A indicating success. + + + + Request pause in SyncPlay group. + + Pause update sent to all group members. + A indicating success. + + + + Request stop in SyncPlay group. + + Stop update sent to all group members. + A indicating success. + + + + Request seek in SyncPlay group. + + The new playback position. + Seek update sent to all group members. + A indicating success. + + + + Notify SyncPlay group that member is buffering. + + The player status. + Group state update sent to all group members. + A indicating success. + + + + Notify SyncPlay group that member is ready for playback. + + The player status. + Group state update sent to all group members. + A indicating success. + + + + Request SyncPlay group to ignore member during group-wait. + + The settings to set. + Member state updated. + A indicating success. + + + + Request next item in SyncPlay group. + + The current item information. + Next item update sent to all group members. + A indicating success. + + + + Request previous item in SyncPlay group. + + The current item information. + Previous item update sent to all group members. + A indicating success. + + + + Request to set repeat mode in SyncPlay group. + + The new repeat mode. + Play queue update sent to all group members. + A indicating success. + + + + Request to set shuffle mode in SyncPlay group. + + The new shuffle mode. + Play queue update sent to all group members. + A indicating success. + + + + Update session ping. + + The new ping. + Ping updated. + A indicating success. + + + + The system controller. + + + + + Initializes a new instance of the class. + + Instance of interface. + Instance of interface. + Instance of interface. + Instance of interface. + Instance of interface. + Instance of interface. + + + + Gets information about the server. + + Information retrieved. + User does not have permission to retrieve information. + A with info about the system. + + + + Gets information about the server. + + Information retrieved. + User does not have permission to retrieve information. + A with info about the system. + + + + Gets public information about the server. + + Information retrieved. + A with public info about the system. + + + + Pings the system. + + Information retrieved. + The server name. + + + + Restarts the application. + + Server restarted. + User does not have permission to restart server. + No content. Server restarted. + + + + Shuts down the application. + + Server shut down. + User does not have permission to shutdown server. + No content. Server shut down. + + + + Gets a list of available server log files. + + Information retrieved. + User does not have permission to get server logs. + An array of with the available log files. + + + + Gets information about the request endpoint. + + Information retrieved. + User does not have permission to get endpoint information. + with information about the endpoint. + + + + Gets a log file. + + The name of the log file to get. + Log file retrieved. + User does not have permission to get log files. + Could not find a log file with the name. + The log file. + + + + The time sync controller. + + + + + Gets the current UTC time. + + Time returned. + An to sync the client and server time. + + + + The trailers controller. + + + + + Initializes a new instance of the class. + + Instance of . + + + + Finds movies and trailers similar to a given trailer. + + The user id supplied as query parameter; this is required when not using an API key. + Optional filter by maximum official rating (PG, PG-13, TV-MA, etc). + Optional filter by items with theme songs. + Optional filter by items with theme videos. + Optional filter by items with subtitles. + Optional filter by items with special features. + Optional filter by items with trailers. + Optional. Return items that are siblings of a supplied item. + Optional filter by parent index number. + Optional filter by items that have or do not have a parental rating. + Optional filter by items that are HD or not. + Optional filter by items that are 4K or not. + Optional. If specified, results will be filtered based on LocationType. This allows multiple, comma delimited. + Optional. If specified, results will be filtered based on the LocationType. This allows multiple, comma delimited. + Optional filter by items that are missing episodes or not. + Optional filter by items that are unaired episodes or not. + Optional filter by minimum community rating. + Optional filter by minimum critic rating. + Optional. The minimum premiere date. Format = ISO. + Optional. The minimum last saved date. Format = ISO. + Optional. The minimum last saved date for the current user. Format = ISO. + Optional. The maximum premiere date. Format = ISO. + Optional filter by items that have an overview or not. + Optional filter by items that have an IMDb id or not. + Optional filter by items that have a TMDb id or not. + Optional filter by items that have a TVDb id or not. + Optional filter for live tv movies. + Optional filter for live tv series. + Optional filter for live tv news. + Optional filter for live tv kids. + Optional filter for live tv sports. + Optional. If specified, results will be filtered by excluding item ids. This allows multiple, comma delimited. + Optional. The record index to start at. All items with a lower index will be dropped from the results. + Optional. The maximum number of records to return. + When searching within folders, this determines whether or not the search will be recursive. true/false. + Optional. Filter based on a search term. + Sort Order - Ascending, Descending. + Specify this to localize the search to a specific item or folder. Omit to use the root. + Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines. + Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited. + Optional. Specify additional filters to apply. This allows multiple, comma delimited. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes. + Optional filter by items that are marked as favorite, or not. + Optional filter by MediaType. Allows multiple, comma delimited. + Optional. If specified, results will be filtered based on those containing image types. This allows multiple, comma delimited. + Optional. Specify one or more sort orders, comma delimited. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime. + Optional filter by items that are played, or not. + Optional. If specified, results will be filtered based on genre. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on OfficialRating. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on tag. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on production year. This allows multiple, comma delimited. + Optional, include user data. + Optional, the max number of images to return, per image type. + Optional. The image types to include in the output. + Optional. If specified, results will be filtered to include only those containing the specified person. + Optional. If specified, results will be filtered to include only those containing the specified person id. + Optional. If specified, along with Person, results will be filtered to include only those containing the specified person and PersonType. Allows multiple, comma-delimited. + Optional. If specified, results will be filtered based on studio. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on artists. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on artist id. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered to include only those containing the specified artist id. + Optional. If specified, results will be filtered to include only those containing the specified album artist id. + Optional. If specified, results will be filtered to include only those containing the specified contributing artist id. + Optional. If specified, results will be filtered based on album. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on album id. This allows multiple, pipe delimited. + Optional. If specific items are needed, specify a list of item id's to retrieve. This allows multiple, comma delimited. + Optional filter by VideoType (videofile, dvd, bluray, iso). Allows multiple, comma delimited. + Optional filter by minimum official rating (PG, PG-13, TV-MA, etc). + Optional filter by items that are locked. + Optional filter by items that are placeholders. + Optional filter by items that have official ratings. + Whether or not to hide items behind their boxsets. + Optional. Filter by the minimum width of the item. + Optional. Filter by the minimum height of the item. + Optional. Filter by the maximum width of the item. + Optional. Filter by the maximum height of the item. + Optional filter by items that are 3D, or not. + Optional filter by Series Status. Allows multiple, comma delimited. + Optional filter by items whose name is sorted equally or greater than a given input string. + Optional filter by items whose name is sorted equally than a given input string. + Optional filter by items whose name is equally or lesser than a given input string. + Optional. If specified, results will be filtered based on studio id. This allows multiple, pipe delimited. + Optional. If specified, results will be filtered based on genre id. This allows multiple, pipe delimited. + Optional. Enable the total record count. + Optional, include image information in output. + A with the trailers. + + + + Trickplay controller. + + + + + Initializes a new instance of the class. + + Instance of . + Instance of . + + + + Gets an image tiles playlist for trickplay. + + The item id. + The width of a single tile. + The media version id, if using an alternate version. + Tiles playlist returned. + A containing the trickplay playlist file. + + + + Gets a trickplay tile image. + + The item id. + The width of a single tile. + The index of the desired tile. + The media version id, if using an alternate version. + Tile image returned. + Tile image not found at specified index. + A containing the trickplay tiles image. + + + + The tv shows controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Gets a list of next up episodes. + + The user id of the user to get the next up episodes for. + Optional. The record index to start at. All items with a lower index will be dropped from the results. + Optional. The maximum number of records to return. + Optional. Specify additional fields of information to return in the output. + Optional. Filter by series id. + Optional. Specify this to localize the search to a specific item or folder. Omit to use the root. + Optional. Include image information in output. + Optional. The max number of images to return, per image type. + Optional. The image types to include in the output. + Optional. Include user data. + Optional. Starting date of shows to show in Next Up section. + Whether to enable the total records count. Defaults to true. + Whether to include resumable episodes in next up results. + Whether to include watched episodes in next up results. + A with the next up episodes. + + + + Gets a list of upcoming episodes. + + The user id of the user to get the upcoming episodes for. + Optional. The record index to start at. All items with a lower index will be dropped from the results. + Optional. The maximum number of records to return. + Optional. Specify additional fields of information to return in the output. + Optional. Specify this to localize the search to a specific item or folder. Omit to use the root. + Optional. Include image information in output. + Optional. The max number of images to return, per image type. + Optional. The image types to include in the output. + Optional. Include user data. + A with the upcoming episodes. + + + + Gets episodes for a tv season. + + The series id. + The user id. + Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls. + Optional filter by season number. + Optional. Filter by season id. + Optional. Filter by items that are missing episodes or not. + Optional. Return items that are siblings of a supplied item. + Optional. Skip through the list until a given item is found. + Optional. The record index to start at. All items with a lower index will be dropped from the results. + Optional. The maximum number of records to return. + Optional, include image information in output. + Optional, the max number of images to return, per image type. + Optional. The image types to include in the output. + Optional. Include user data. + Optional. Specify one or more sort orders, comma delimited. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime. + A with the episodes on success or a if the series was not found. + + + + Gets seasons for a tv series. + + The series id. + The user id. + Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls. + Optional. Filter by special season. + Optional. Filter by items that are missing episodes or not. + Optional. Return items that are siblings of a supplied item. + Optional. Include image information in output. + Optional. The max number of images to return, per image type. + Optional. The image types to include in the output. + Optional. Include user data. + A on success or a if the series was not found. + + + + Applies the paging. + + The items. + The start index. + The limit. + IEnumerable{BaseItem}. + + + + The universal audio controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of . + Instance of . + Instance of . + Instance of the interface. + + + + Gets an audio stream. + + The item id. + Optional. The audio container. + The media version id, if playing an alternate version. + The device id of the client requesting. Used to stop encoding processes when needed. + Optional. The user id. + Optional. The audio codec to transcode to. + Optional. The maximum number of audio channels. + Optional. The number of how many audio channels to transcode to. + Optional. The maximum streaming bitrate. + Optional. Specify an audio bitrate to encode to, e.g. 128000. If omitted this will be left to encoder defaults. + Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms. + Optional. The container to transcode to. + Optional. The transcoding protocol. + Optional. The maximum audio sample rate. + Optional. The maximum audio bit depth. + Optional. Whether to enable remote media. + Optional. Whether to enable Audio Encoding. + Whether to enable redirection. Defaults to true. + Audio stream returned. + Redirected to remote audio stream. + Item not found. + A containing the audio file. + + + + User controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Gets a list of users. + + Optional filter by IsHidden=true or false. + Optional filter by IsDisabled=true or false. + Users returned. + An containing the users. + + + + Gets a list of publicly visible users for display on a login screen. + + Public users returned. + An containing the public users. + + + + Gets a user by Id. + + The user id. + User returned. + User not found. + An with information about the user or a if the user was not found. + + + + Deletes a user. + + The user id. + User deleted. + User not found. + A indicating success or a if the user was not found. + + + + Authenticates a user. + + The user id. + The password as plain text. + User authenticated. + Sha1-hashed password only is not allowed. + User not found. + A containing an . + + + + Authenticates a user by name. + + The request. + User authenticated. + A containing an with information about the new session. + + + + Authenticates a user with quick connect. + + The request. + User authenticated. + Missing token. + A containing an with information about the new session. + + + + Updates a user's password. + + The user id. + The request. + Password successfully reset. + User is not allowed to update the password. + User not found. + A indicating success or a or a on failure. + + + + Updates a user's password. + + The user id. + The request. + Password successfully reset. + User is not allowed to update the password. + User not found. + A indicating success or a or a on failure. + + + + Updates a user. + + The user id. + The updated user model. + User updated. + User information was not supplied. + User update forbidden. + A indicating success or a or a on failure. + + + + Updates a user. + + The user id. + The updated user model. + User updated. + User information was not supplied. + User update forbidden. + A indicating success or a or a on failure. + + + + Updates a user policy. + + The user id. + The new user policy. + User policy updated. + User policy was not supplied. + User policy update forbidden. + A indicating success or a or a on failure.. + + + + Updates a user configuration. + + The user id. + The new user configuration. + User configuration updated. + User configuration update forbidden. + A indicating success. + + + + Updates a user configuration. + + The user id. + The new user configuration. + User configuration updated. + User configuration update forbidden. + A indicating success. + + + + Creates a user. + + The create user by name request body. + User created. + An of the new user. + + + + Initiates the forgot password process for a local user. + + The forgot password request containing the entered username. + Password reset process started. + A containing a . + + + + Redeems a forgot password pin. + + The forgot password pin request containing the entered pin. + Pin reset process started. + A containing a . + + + + Gets the user based on auth token. + + User returned. + Token is not owned by a user. + A for the authenticated user. + + + + User library controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Gets an item from a user's library. + + User id. + Item id. + Item returned. + An containing the item. + + + + Gets an item from a user's library. + + User id. + Item id. + Item returned. + An containing the item. + + + + Gets the root folder from a user's library. + + User id. + Root folder returned. + An containing the user's root folder. + + + + Gets the root folder from a user's library. + + User id. + Root folder returned. + An containing the user's root folder. + + + + Gets intros to play before the main media item plays. + + User id. + Item id. + Intros returned. + An containing the intros to play. + + + + Gets intros to play before the main media item plays. + + User id. + Item id. + Intros returned. + An containing the intros to play. + + + + Marks an item as a favorite. + + User id. + Item id. + Item marked as favorite. + An containing the . + + + + Marks an item as a favorite. + + User id. + Item id. + Item marked as favorite. + An containing the . + + + + Unmarks item as a favorite. + + User id. + Item id. + Item unmarked as favorite. + An containing the . + + + + Unmarks item as a favorite. + + User id. + Item id. + Item unmarked as favorite. + An containing the . + + + + Deletes a user's saved personal rating for an item. + + User id. + Item id. + Personal rating removed. + An containing the . + + + + Deletes a user's saved personal rating for an item. + + User id. + Item id. + Personal rating removed. + An containing the . + + + + Updates a user's rating for an item. + + User id. + Item id. + Whether this is likes. + Item rating updated. + An containing the . + + + + Updates a user's rating for an item. + + User id. + Item id. + Whether this is likes. + Item rating updated. + An containing the . + + + + Gets local trailers for an item. + + User id. + Item id. + An containing the item's local trailers. + The items local trailers. + + + + Gets local trailers for an item. + + User id. + Item id. + An containing the item's local trailers. + The items local trailers. + + + + Gets special features for an item. + + User id. + Item id. + Special features returned. + An containing the special features. + + + + Gets special features for an item. + + User id. + Item id. + Special features returned. + An containing the special features. + + + + Gets latest media. + + User id. + Specify this to localize the search to a specific item or folder. Omit to use the root. + Optional. Specify additional fields of information to return in the output. + Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited. + Filter by items that are played, or not. + Optional. include image information in output. + Optional. the max number of images to return, per image type. + Optional. The image types to include in the output. + Optional. include user data. + Return item limit. + Whether or not to group items into a parent container. + Latest media returned. + An containing the latest media. + + + + Gets latest media. + + User id. + Specify this to localize the search to a specific item or folder. Omit to use the root. + Optional. Specify additional fields of information to return in the output. + Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited. + Filter by items that are played, or not. + Optional. include image information in output. + Optional. the max number of images to return, per image type. + Optional. The image types to include in the output. + Optional. include user data. + Return item limit. + Whether or not to group items into a parent container. + Latest media returned. + An containing the latest media. + + + + Marks the favorite. + + The user. + The item. + if set to true [is favorite]. + + + + Updates the user item rating. + + The user. + The item. + if set to true [likes]. + + + + User views controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Get user views. + + User id. + Whether or not to include external views such as channels or live tv. + Preset views. + Whether or not to include hidden content. + User views returned. + An containing the user views. + + + + Get user views. + + User id. + Whether or not to include external views such as channels or live tv. + Preset views. + Whether or not to include hidden content. + User views returned. + An containing the user views. + + + + Get user view grouping options. + + User id. + User view grouping options returned. + User not found. + + An containing the user view grouping options + or a if user not found. + + + + + Get user view grouping options. + + User id. + User view grouping options returned. + User not found. + + An containing the user view grouping options + or a if user not found. + + + + + Attachments controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + + Get video attachment. + + Video ID. + Media Source ID. + Attachment Index. + Attachment retrieved. + Video or attachment not found. + An containing the attachment stream on success, or a if the attachment could not be found. + + + + The videos controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of . + + + + Gets additional parts for a video. + + The item id. + Optional. Filter by user id, and attach user data. + Additional parts returned. + A with the parts. + + + + Removes alternate video sources. + + The item id. + Alternate sources deleted. + Video not found. + A indicating success, or a if the video doesn't exist. + + + + Merges videos into a single record. + + Item id list. This allows multiple, comma delimited. + Videos merged. + Supply at least 2 video ids. + A indicating success, or a if less than two ids were supplied. + + + + Gets a video stream. + + The item id. + The video container. Possible values are: ts, webm, asf, wmv, ogv, mp4, m4v, mkv, mpeg, mpg, avi, 3gp, wmv, wtv, m2ts, mov, iso, flv. + Optional. If true, the original file will be streamed statically without any encoding. Use either no url extension or the original file extension. true/false. + The streaming parameters. + The tag. + Optional. The dlna device profile id to utilize. + The play session id. + The segment container. + The segment length. + The minimum number of segments. + The media version id, if playing an alternate version. + The device id of the client requesting. Used to stop encoding processes when needed. + Optional. Specify an audio codec to encode to, e.g. mp3. If omitted the server will auto-select using the url's extension. + Whether or not to allow automatic stream copy if requested values match the original source. Defaults to true. + Whether or not to allow copying of the video stream url. + Whether or not to allow copying of the audio stream url. + Optional. Specify a specific audio sample rate, e.g. 44100. + Optional. The maximum audio bit depth. + Optional. Specify an audio bitrate to encode to, e.g. 128000. If omitted this will be left to encoder defaults. + Optional. Specify a specific number of audio channels to encode to, e.g. 2. + Optional. Specify a maximum number of audio channels to encode to, e.g. 2. + Optional. Specify a specific an encoder profile (varies by encoder), e.g. main, baseline, high. + Optional. Specify a level for the encoder profile (varies by encoder), e.g. 3, 3.1. + Optional. A specific video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements. + Optional. A specific maximum video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements. + Whether or not to copy timestamps when transcoding with an offset. Defaults to false. + Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms. + Optional. The fixed horizontal resolution of the encoded video. + Optional. The fixed vertical resolution of the encoded video. + Optional. The maximum horizontal resolution of the encoded video. + Optional. The maximum vertical resolution of the encoded video. + Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be left to encoder defaults. + Optional. The index of the subtitle stream to use. If omitted no subtitles will be used. + Optional. Specify the subtitle delivery method. + Optional. + Optional. The maximum video bit depth. + Optional. Whether to require avc. + Optional. Whether to deinterlace the video. + Optional. Whether to require a non anamorphic stream. + Optional. The maximum number of audio channels to transcode. + Optional. The limit of how many cpu cores to use. + The live stream id. + Optional. Whether to enable the MpegtsM2Ts mode. + Optional. Specify a video codec to encode to, e.g. h264. If omitted the server will auto-select using the url's extension. + Optional. Specify a subtitle codec to encode to. + Optional. The transcoding reason. + Optional. The index of the audio stream to use. If omitted the first audio stream will be used. + Optional. The index of the video stream to use. If omitted the first video stream will be used. + Optional. The . + Optional. The streaming options. + Optional. Whether to enable Audio Encoding. + Video stream returned. + A containing the audio file. + + + + Gets a video stream. + + The item id. + The video container. Possible values are: ts, webm, asf, wmv, ogv, mp4, m4v, mkv, mpeg, mpg, avi, 3gp, wmv, wtv, m2ts, mov, iso, flv. + Optional. If true, the original file will be streamed statically without any encoding. Use either no url extension or the original file extension. true/false. + The streaming parameters. + The tag. + Optional. The dlna device profile id to utilize. + The play session id. + The segment container. + The segment length. + The minimum number of segments. + The media version id, if playing an alternate version. + The device id of the client requesting. Used to stop encoding processes when needed. + Optional. Specify an audio codec to encode to, e.g. mp3. If omitted the server will auto-select using the url's extension. + Whether or not to allow automatic stream copy if requested values match the original source. Defaults to true. + Whether or not to allow copying of the video stream url. + Whether or not to allow copying of the audio stream url. + Optional. Specify a specific audio sample rate, e.g. 44100. + Optional. The maximum audio bit depth. + Optional. Specify an audio bitrate to encode to, e.g. 128000. If omitted this will be left to encoder defaults. + Optional. Specify a specific number of audio channels to encode to, e.g. 2. + Optional. Specify a maximum number of audio channels to encode to, e.g. 2. + Optional. Specify a specific an encoder profile (varies by encoder), e.g. main, baseline, high. + Optional. Specify a level for the encoder profile (varies by encoder), e.g. 3, 3.1. + Optional. A specific video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements. + Optional. A specific maximum video framerate to encode to, e.g. 23.976. Generally this should be omitted unless the device has specific requirements. + Whether or not to copy timestamps when transcoding with an offset. Defaults to false. + Optional. Specify a starting offset, in ticks. 1 tick = 10000 ms. + Optional. The fixed horizontal resolution of the encoded video. + Optional. The fixed vertical resolution of the encoded video. + Optional. The maximum horizontal resolution of the encoded video. + Optional. The maximum vertical resolution of the encoded video. + Optional. Specify a video bitrate to encode to, e.g. 500000. If omitted this will be left to encoder defaults. + Optional. The index of the subtitle stream to use. If omitted no subtitles will be used. + Optional. Specify the subtitle delivery method. + Optional. + Optional. The maximum video bit depth. + Optional. Whether to require avc. + Optional. Whether to deinterlace the video. + Optional. Whether to require a non anamorphic stream. + Optional. The maximum number of audio channels to transcode. + Optional. The limit of how many cpu cores to use. + The live stream id. + Optional. Whether to enable the MpegtsM2Ts mode. + Optional. Specify a video codec to encode to, e.g. h264. If omitted the server will auto-select using the url's extension. + Optional. Specify a subtitle codec to encode to. + Optional. The transcoding reason. + Optional. The index of the audio stream to use. If omitted the first audio stream will be used. + Optional. The index of the video stream to use. If omitted the first video stream will be used. + Optional. The . + Optional. The streaming options. + Optional. Whether to enable Audio Encoding. + Video stream returned. + A containing the audio file. + + + + Years controller. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Get years. + + Skips over a given number of items within the results. Use for paging. + Optional. The maximum number of records to return. + Sort Order - Ascending,Descending. + Specify this to localize the search to a specific item or folder. Omit to use the root. + Optional. Specify additional fields of information to return in the output. + Optional. If specified, results will be excluded based on item type. This allows multiple, comma delimited. + Optional. If specified, results will be included based on item type. This allows multiple, comma delimited. + Optional. Filter by MediaType. Allows multiple, comma delimited. + Optional. Specify one or more sort orders, comma delimited. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime. + Optional. Include user data. + Optional. The max number of images to return, per image type. + Optional. The image types to include in the output. + User Id. + Search recursively. + Optional. Include image information in output. + Year query returned. + A containing the year result. + + + + Gets a year. + + The year. + Optional. Filter by user id, and attach user data. + Year returned. + Year not found. + + An containing the year, + or a if year not found. + + + + + Extensions for . + + + + + Get user id from claims. + + Current claims principal. + User id. + + + + Get device id from claims. + + Current claims principal. + Device id. + + + + Get device from claims. + + Current claims principal. + Device. + + + + Get client from claims. + + Current claims principal. + Client. + + + + Get version from claims. + + Current claims principal. + Version. + + + + Get token from claims. + + Current claims principal. + Token. + + + + Gets a flag specifying whether the request is using an api key. + + Current claims principal. + The flag specifying whether the request is using an api key. + + + + Dto Extensions. + + + + + Add additional DtoOptions. + + + Converted from IHasDtoOptions. + Legacy order: 3. + + DtoOptions object. + Enable images. + Enable user data. + Image type limit. + Enable image types. + Modified DtoOptions object. + + + + Camel Case Json Profile Formatter. + + + + + Initializes a new instance of the class. + + + + + Css output formatter. + + + + + Initializes a new instance of the class. + + + + + Pascal Case Json Profile Formatter. + + + + + Initializes a new instance of the class. + + + + + Xml output formatter. + + + + + Initializes a new instance of the class. + + + + + + + + Audio helper. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of interface. + Instance of the interface. + Instance of the interface. + Instance of . + + + + Get audio stream. + + Transcoding job type. + Streaming controller.Request dto. + A containing the resulting . + + + + Dynamic hls helper. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of . + Instance of . + + + + Get master hls playlist. + + Transcoding job type. + Streaming request dto. + Enable adaptive bitrate streaming. + A containing the resulting . + + + + Appends a VIDEO-RANGE field containing the range of the output video stream. + + + StringBuilder to append the field to. + StreamState of the current stream. + + + + Appends a CODECS field containing formatted strings of + the active streams output video and audio codecs. + + + + + StringBuilder to append the field to. + StreamState of the current stream. + + + + Appends a SUPPLEMENTAL-CODECS field containing formatted strings of + the active streams output Dolby Vision Videos. + + + + StringBuilder to append the field to. + StreamState of the current stream. + + + + Appends a RESOLUTION field containing the resolution of the output stream. + + + StringBuilder to append the field to. + StreamState of the current stream. + + + + Appends a FRAME-RATE field containing the framerate of the output stream. + + + StringBuilder to append the field to. + StreamState of the current stream. + + + + Appends EXT-X-IMAGE-STREAM-INF playlists for each available trickplay resolution. + + StreamState of the current stream. + Dictionary of widths to corresponding tiles info. + StringBuilder to append the field to. + Http user context. + + + + Get the H.26X level of the output video stream. + + StreamState of the current stream. + H.26X level of the output video stream. + + + + Get the profile of the output video stream. + + StreamState of the current stream. + Video codec. + Profile of the output video stream. + + + + Gets a formatted string of the output audio codec, for use in the CODECS field. + + + + StreamState of the current stream. + Formatted audio codec string. + + + + Gets a formatted string of the output video codec, for use in the CODECS field. + + + + StreamState of the current stream. + Video codec. + Video level. + Formatted video codec string. + + + + The stream response helpers. + + + + + Returns a static file from a remote source. + + The current . + The making the remote request. + The current http context. + A cancellation token that can be used to cancel the operation. + A containing the API response. + + + + Returns a static file from the server. + + The path to the file. + The content type of the file. + An the file. + + + + Returns a transcoded file from the server. + + The current . + Whether the current request is a HTTP HEAD request so only the headers get returned. + The current http context. + The singleton. + The command line arguments to start ffmpeg. + The . + The . + A containing the transcoded file. + + + + Helpers to generate HLS codec strings according to + RFC 6381 section 3.3 + and the MP4 Registration Authority. + + + + + Codec name for MP3. + + + + + Codec name for AC-3. + + + + + Codec name for E-AC-3. + + + + + Codec name for FLAC. + + + + + Codec name for ALAC. + + + + + Codec name for OPUS. + + + + + Codec name for TRUEHD. + + + + + Gets a MP3 codec string. + + MP3 codec string. + + + + Gets an AAC codec string. + + AAC profile. + AAC codec string. + + + + Gets an AC-3 codec string. + + AC-3 codec string. + + + + Gets an E-AC-3 codec string. + + E-AC-3 codec string. + + + + Gets an FLAC codec string. + + FLAC codec string. + + + + Gets an ALAC codec string. + + ALAC codec string. + + + + Gets an OPUS codec string. + + OPUS codec string. + + + + Gets an TRUEHD codec string. + + TRUEHD codec string. + + + + Gets an DTS codec string. + + DTS profile. + DTS codec string. + + + + Gets a H.264 codec string. + + H.264 profile. + H.264 level. + H.264 string. + + + + Gets a H.265 codec string. + + H.265 profile. + H.265 level. + H.265 string. + + + + Gets a VP9 codec string. + + Video width. + Video height. + Video pixel format. + Video framerate. + Video bitDepth. + The VP9 codec string. + + + + Gets an AV1 codec string. + + AV1 profile. + AV1 level. + AV1 tier flag. + AV1 bit depth. + The AV1 codec string. + + + + The hls helpers. + + + + + Waits for a minimum number of segments to be available. + + The playlist string. + The segment count. + Instance of the interface. + The . + A indicating the waiting process. + + + + Gets the #EXT-X-MAP string. + + The output path of the file. + The . + Get a normal string or depends on OS. + The string text of #EXT-X-MAP. + + + + Gets the hls playlist text. + + The path to the playlist file. + The . + The playlist text as a string. + + + + Media info helper. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Get playback info. + + The item. + The user. + Media source id. + Live stream id. + A containing the . + + + + SetDeviceSpecificData. + + Item to set data for. + Media source info. + Device profile. + Current claims principal. + Max bitrate. + Start time ticks. + Media source id. + Audio stream index. + Subtitle stream index. + Max audio channels. + Play session id. + User id. + Enable direct play. + Enable direct stream. + Enable transcoding. + Allow video stream copy. + Allow audio stream copy. + Always burn-in subtitle when transcoding. + Requesting IP address. + + + + Sort media source. + + Playback info response. + Max bitrate. + + + + Open media source. + + Http Context. + Live stream request. + A containing the . + + + + Normalize media source container. + + Media source. + Device profile. + Dlna profile type. + + + + Request Extensions. + + + + + Get Order By. + + Sort By. Comma delimited string. + Sort Order. Comma delimited string. + Order By. + + + + Checks if the user can access a user. + + The for the current request. + The user id. + A whether the user can access the user. + + + + Checks if the user can update an entry. + + The for the current request. + The user id. + Whether to restrict the user preferences. + A whether the user can update the entry. + + + + Get the session based on http request. + + The session manager. + The user manager. + The http context. + The optional userid. + The session. + Session not found. + + + + The streaming helpers. + + + + + Gets the current streaming state. + + The . + The . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of . + Instance of the interface. + The . + The . + A containing the current . + + + + Parses query parameters as StreamOptions. + + The query string. + A containing the stream options. + + + + Gets the output file extension. + + The state. + The mediaSource. + System.String. + + + + Gets the output file path for transcoding. + + The current . + The file extension of the output file. + Instance of the interface. + The device id. + The play session id. + The complete file path, including the folder, for the transcoding file. + + + + Parses the parameters. + + The request. + + + + Parses the container into its file extension. + + The container. + + + + Redirect requests without baseurl prefix to the baseurl prefixed URL. + + + + + Initializes a new instance of the class. + + The next delegate in the pipeline. + The logger. + The application configuration. + + + + Executes the middleware action. + + The current HTTP context. + The server configuration manager. + The async task. + + + + Exception Middleware. + + + + + Initializes a new instance of the class. + + Next request delegate. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Invoke request. + + Request context. + Task. + + + + Validates the IP of requests coming from local networks wrt. remote access. + + + + + Initializes a new instance of the class. + + The next delegate in the pipeline. + The logger to log to. + + + + Executes the middleware action. + + The current HTTP context. + The network manager. + The async task. + + + + URL decodes the querystring before binding. + + + + + Initializes a new instance of the class. + + The next delegate in the pipeline. + + + + Executes the middleware action. + + The current HTTP context. + The async task. + + + + Response time middleware. + + + + + Initializes a new instance of the class. + + Next request delegate. + Instance of the interface. + + + + Invoke request. + + Request context. + Instance of the interface. + Task. + + + + Redirect requests to robots.txt to web/robots.txt. + + + + + Initializes a new instance of the class. + + The next delegate in the pipeline. + The logger. + + + + Executes the middleware action. + + The current HTTP context. + The async task. + + + + Shows a custom message during server startup. + + + + + Initializes a new instance of the class. + + The next delegate in the pipeline. + + + + Executes the middleware action. + + The current HTTP context. + The server application host. + The localization manager. + The async task. + + + + Defines the . + + + + + Initializes a new instance of the class. + + The instance. + + + + Gets or sets a value indicating the url decoded . + + + + + WebSocket Authentication Middleware. + Extracts and validates API tokens from WebSocket query strings. + + + + + Initializes a new instance of the class. + + The next delegate in the pipeline. + The logger. + + + + Executes the middleware action. + + The current HTTP context. + The authentication service. + The async task. + + + + Authenticates WebSocket requests by extracting api_key from query string. + + The HTTP context. + The authentication service. + The async task. + + + + Extension methods for adding WebSocket authentication to the pipeline. + + + + + Adds WebSocket authentication to the application pipeline. + + The application builder. + The updated application builder. + + + + Handles WebSocket requests. + + + + + Initializes a new instance of the class. + + The next delegate in the pipeline. + + + + Executes the middleware action. + + The current HTTP context. + The WebSocket connection manager. + The async task. + + + + Comma delimited collection model binder. + Returns an empty array of specified type if there is no query parameter. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + DateTime model binder. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + Nullable enum model binder. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + Nullable enum model binder provider. + + + + + + + + Comma delimited collection model binder. + Returns an empty collection of specified type if there is no query parameter. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + Client log document response dto. + + + + + Initializes a new instance of the class. + + The file name. + + + + Gets the resulting filename. + + + + + The configuration page info. + + + + + Initializes a new instance of the class. + + Instance of interface. + Instance of interface. + + + + Initializes a new instance of the class. + + + + + Gets or sets the name. + + The name. + + + + Gets or sets a value indicating whether the configurations page is enabled in the main menu. + + + + + Gets or sets the menu section. + + + + + Gets or sets the menu icon. + + + + + Gets or sets the display name. + + + + + Gets or sets the plugin id. + + The plugin id. + + + + Default directory browser info. + + + + + Gets or sets the path. + + + + + Validate path object. + + + + + Gets or sets a value indicating whether validate if path is writable. + + + + + Gets or sets the path. + + + + + Gets or sets is path file. + + + + + Library option info dto. + + + + + Gets or sets name. + + + + + Gets or sets a value indicating whether default enabled. + + + + + Library options result dto. + + + + + Gets or sets the metadata savers. + + + + + Gets or sets the metadata readers. + + + + + Gets or sets the subtitle fetchers. + + + + + Gets or sets the list of lyric fetchers. + + + + + Gets or sets the list of MediaSegment Providers. + + + + + Gets or sets the type options. + + + + + Library type options dto. + + + + + Gets or sets the type. + + + + + Gets or sets the metadata fetchers. + + + + + Gets or sets the image fetchers. + + + + + Gets or sets the supported image types. + + + + + Gets or sets the default image options. + + + + + Media Update Info Dto. + + + + + Gets or sets the list of updates. + + + + + The media update info path. + + + + + Gets or sets media path. + + + + + Gets or sets media update type. + Created, Modified, Deleted. + + + + + Add virtual folder dto. + + + + + Gets or sets library options. + + + + + Media Path dto. + + + + + Gets or sets the name of the library. + + + + + Gets or sets the path to add. + + + + + Gets or sets the path info. + + + + + Update library options dto. + + + + + Gets or sets the library item id. + + + + + Gets or sets library options. + + + + + Update library options dto. + + + + + Gets or sets the library name. + + + + + Gets or sets library folder path information. + + + + + Get programs dto. + + + + + Gets or sets the channels to return guide information for. + + + + + Gets or sets optional. Filter by user id. + + + + + Gets or sets the minimum premiere start date. + + + + + Gets or sets filter by programs that have completed airing, or not. + + + + + Gets or sets filter by programs that are currently airing, or not. + + + + + Gets or sets the maximum premiere start date. + + + + + Gets or sets the minimum premiere end date. + + + + + Gets or sets the maximum premiere end date. + + + + + Gets or sets filter for movies. + + + + + Gets or sets filter for series. + + + + + Gets or sets filter for news. + + + + + Gets or sets filter for kids. + + + + + Gets or sets filter for sports. + + + + + Gets or sets the record index to start at. All items with a lower index will be dropped from the results. + + + + + Gets or sets the maximum number of records to return. + + + + + Gets or sets specify one or more sort orders, comma delimited. Options: Name, StartDate. + + + + + Gets or sets sort order. + + + + + Gets or sets the genres to return guide information for. + + + + + Gets or sets the genre ids to return guide information for. + + + + + Gets or sets include image information in output. + + + + + Gets or sets a value indicating whether retrieve total record count. + + + + + Gets or sets the max number of images to return, per image type. + + + + + Gets or sets the image types to include in the output. + + + + + Gets or sets include user data. + + + + + Gets or sets filter by series timer id. + + + + + Gets or sets filter by library series id. + + + + + Gets or sets specify additional fields of information to return in the output. + + + + + Set channel mapping dto. + + + + + Gets or sets the provider id. + + + + + Gets or sets the tuner channel id. + + + + + Gets or sets the provider channel id. + + + + + Open live stream dto. + + + + + Gets or sets the open token. + + + + + Gets or sets the user id. + + + + + Gets or sets the play session id. + + + + + Gets or sets the max streaming bitrate. + + + + + Gets or sets the start time in ticks. + + + + + Gets or sets the audio stream index. + + + + + Gets or sets the subtitle stream index. + + + + + Gets or sets the max audio channels. + + + + + Gets or sets the item id. + + + + + Gets or sets a value indicating whether to enable direct play. + + + + + Gets or sets a value indicating whether to enable direct stream. + + + + + Gets or sets a value indicating whether always burn in subtitles when transcoding. + + + + + Gets or sets the device profile. + + + + + Gets or sets the device play protocols. + + + + + Playback info dto. + + + + + Gets or sets the playback userId. + + + + + Gets or sets the max streaming bitrate. + + + + + Gets or sets the start time in ticks. + + + + + Gets or sets the audio stream index. + + + + + Gets or sets the subtitle stream index. + + + + + Gets or sets the max audio channels. + + + + + Gets or sets the media source id. + + + + + Gets or sets the live stream id. + + + + + Gets or sets the device profile. + + + + + Gets or sets a value indicating whether to enable direct play. + + + + + Gets or sets a value indicating whether to enable direct stream. + + + + + Gets or sets a value indicating whether to enable transcoding. + + + + + Gets or sets a value indicating whether to enable video stream copy. + + + + + Gets or sets a value indicating whether to allow audio stream copy. + + + + + Gets or sets a value indicating whether to auto open the live stream. + + + + + Gets or sets a value indicating whether always burn in subtitles when transcoding. + + + + + Create new playlist dto. + + + + + Gets or sets the name of the new playlist. + + + + + Gets or sets item ids to add to the playlist. + + + + + Gets or sets the user id. + + + + + Gets or sets the media type. + + + + + Gets or sets the playlist users. + + + + + Gets or sets a value indicating whether the playlist is public. + + + + + Update existing playlist dto. Fields set to `null` will not be updated and keep their current values. + + + + + Gets or sets the name of the new playlist. + + + + + Gets or sets item ids of the playlist. + + + + + Gets or sets the playlist users. + + + + + Gets or sets a value indicating whether the playlist is public. + + + + + Update existing playlist user dto. Fields set to `null` will not be updated and keep their current values. + + + + + Gets or sets a value indicating whether the user can edit the playlist. + + + + + The startup configuration DTO. + + + + + Gets or sets the server name. + + + + + Gets or sets UI language culture. + + + + + Gets or sets the metadata country code. + + + + + Gets or sets the preferred language for the metadata. + + + + + Startup remote access dto. + + + + + Gets or sets a value indicating whether enable remote access. + + + + + The startup user DTO. + + + + + Gets or sets the username. + + + + + Gets or sets the user's password. + + + + + The hls video request dto. + + + + + Gets or sets a value indicating whether enable adaptive bitrate streaming. + + + + + The hls video request dto. + + + + + Gets or sets a value indicating whether enable adaptive bitrate streaming. + + + + + Upload subtitles dto. + + + + + Gets or sets the subtitle language. + + + + + Gets or sets the subtitle format. + + + + + Gets or sets a value indicating whether the subtitle is forced. + + + + + Gets or sets a value indicating whether the subtitle is for hearing impaired. + + + + + Gets or sets the subtitle data. + + + + + Class BufferRequestDto. + + + + + Initializes a new instance of the class. + + + + + Gets or sets when the request has been made by the client. + + The date of the request. + + + + Gets or sets the position ticks. + + The position ticks. + + + + Gets or sets a value indicating whether the client playback is unpaused. + + The client playback status. + + + + Gets or sets the playlist item identifier of the playing item. + + The playlist item identifier. + + + + Class IgnoreWaitRequestDto. + + + + + Gets or sets a value indicating whether the client should be ignored. + + The client group-wait status. + + + + Class JoinGroupRequestDto. + + + + + Gets or sets the group identifier. + + The identifier of the group to join. + + + + Class MovePlaylistItemRequestDto. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the playlist identifier of the item. + + The playlist identifier of the item. + + + + Gets or sets the new position. + + The new position. + + + + Class NewGroupRequestDto. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the group name. + + The name of the new group. + + + + Class NextItemRequestDto. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the playing item identifier. + + The playing item identifier. + + + + Class PingRequestDto. + + + + + Gets or sets the ping time. + + The ping time. + + + + Class PlayRequestDto. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the playing queue. + + The playing queue. + + + + Gets or sets the position of the playing item in the queue. + + The playing item position. + + + + Gets or sets the start position ticks. + + The start position ticks. + + + + Class PreviousItemRequestDto. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the playing item identifier. + + The playing item identifier. + + + + Class QueueRequestDto. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the items to enqueue. + + The items to enqueue. + + + + Gets or sets the mode in which to add the new items. + + The enqueue mode. + + + + Class ReadyRequest. + + + + + Initializes a new instance of the class. + + + + + Gets or sets when the request has been made by the client. + + The date of the request. + + + + Gets or sets the position ticks. + + The position ticks. + + + + Gets or sets a value indicating whether the client playback is unpaused. + + The client playback status. + + + + Gets or sets the playlist item identifier of the playing item. + + The playlist item identifier. + + + + Class RemoveFromPlaylistRequestDto. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the playlist identifiers of the items. Ignored when clearing the playlist. + + The playlist identifiers of the items. + + + + Gets or sets a value indicating whether the entire playlist should be cleared. + + Whether the entire playlist should be cleared. + + + + Gets or sets a value indicating whether the playing item should be removed as well. Used only when clearing the playlist. + + Whether the playing item should be removed as well. + + + + Class SeekRequestDto. + + + + + Gets or sets the position ticks. + + The position ticks. + + + + Class SetPlaylistItemRequestDto. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the playlist identifier of the playing item. + + The playlist identifier of the playing item. + + + + Class SetRepeatModeRequestDto. + + + + + Gets or sets the repeat mode. + + The repeat mode. + + + + Class SetShuffleModeRequestDto. + + + + + Gets or sets the shuffle mode. + + The shuffle mode. + + + + Contains information about a specific folder. + + + + + Gets the path of the folder in question. + + + + + Gets the free space of the underlying storage device of the . + + + + + Gets the used space of the underlying storage device of the . + + + + + Gets the kind of storage device of the . + + + + + Gets the Device Identifier. + + + + + Contains informations about a libraries storage informations. + + + + + Gets or sets the Library Id. + + + + + Gets or sets the name of the library. + + + + + Gets or sets the storage informations about the folders used in a library. + + + + + Contains informations about the systems storage. + + + + + Gets or sets the Storage information of the program data folder. + + + + + Gets or sets the Storage information of the web UI resources folder. + + + + + Gets or sets the Storage information of the folder where images are cached. + + + + + Gets or sets the Storage information of the cache folder. + + + + + Gets or sets the Storage information of the folder where logfiles are saved to. + + + + + Gets or sets the Storage information of the folder where metadata is stored. + + + + + Gets or sets the Storage information of the transcoding cache. + + + + + Gets or sets the storage informations of all libraries. + + + + + The authenticate user by name request body. + + + + + Gets or sets the username. + + + + + Gets or sets the plain text password. + + + + + The create user by name request body. + + + + + Gets or sets the username. + + + + + Gets or sets the password. + + + + + Forgot Password request body DTO. + + + + + Gets or sets the entered username to have its password reset. + + + + + Forgot Password Pin enter request body DTO. + + + + + Gets or sets the entered pin to have the password reset. + + + + + The quick connect request body. + + + + + Gets or sets the quick connect secret. + + + + + The update user password request body. + + + + + Gets or sets the current sha1-hashed password. + + + + + Gets or sets the current plain text password. + + + + + Gets or sets the new plain text password. + + + + + Gets or sets a value indicating whether to reset the password. + + + + + Special view option dto. + + + + + Gets or sets view option name. + + + + + Gets or sets view option id. + + + + + Ok result with type specified. + + The type to return. + + + + Initializes a new instance of the class. + + The value to return. + + + + Class ActivityLogWebSocketListener. + + + + + The _kernel. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + Gets the data to send. + + Task{SystemInfo}. + + + + + + + Starts sending messages over an activity log web socket. + + The message. + + + + Class ScheduledTasksWebSocketListener. + + + + + Gets or sets the task manager. + + The task manager. + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + Gets the data to send. + + Task{IEnumerable{TaskInfo}}. + + + + + + + Class SessionInfoWebSocketListener. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + Gets the data to send. + + Task{SystemInfo}. + + + + + + + + + + Starts sending messages over a session info web socket. + + The message. + + + diff --git a/publish/Jellyfin.Data.xml b/publish/Jellyfin.Data.xml new file mode 100644 index 00000000..ecc10cd2 --- /dev/null +++ b/publish/Jellyfin.Data.xml @@ -0,0 +1,1198 @@ + + + + Jellyfin.Data + + + + + Attribute to specify that the enum value is to be ignored when generating the openapi spec. + + + + + A dto representing custom options for a device. + + + + + Gets or sets the id. + + + + + Gets or sets the device id. + + + + + Gets or sets the custom name. + + + + + Activity log sorting options. + + + + + Sort by name. + + + + + Sort by overview. + + + + + Sort by short overview. + + + + + Sort by type. + + + + + Sort by date. + + + + + Sort by username. + + + + + Sort by severity. + + + + + An enum representing formats of spatial audio. + + + + + None audio spatial format. + + + + + Dolby Atmos audio spatial format. + + + + + DTS:X audio spatial format. + + + + + The base item kind. + + + This enum is generated from all classes that inherit from BaseItem. + + + + + Item is aggregate folder. + + + + + Item is audio. + + + + + Item is audio book. + + + + + Item is base plugin folder. + + + + + Item is book. + + + + + Item is box set. + + + + + Item is channel. + + + + + Item is channel folder item. + + + + + Item is collection folder. + + + + + Item is episode. + + + + + Item is folder. + + + + + Item is genre. + + + + + Item is manual playlists folder. + + + + + Item is movie. + + + + + Item is a live tv channel. + + + + + Item is a live tv program. + + + + + Item is music album. + + + + + Item is music artist. + + + + + Item is music genre. + + + + + Item is music video. + + + + + Item is person. + + + + + Item is photo. + + + + + Item is photo album. + + + + + Item is playlist. + + + + + Item is playlist folder. + + + + + Item is program. + + + + + Item is recording. + + + Manually added. + + + + + Item is season. + + + + + Item is series. + + + + + Item is studio. + + + + + Item is trailer. + + + + + Item is live tv channel. + + + Type is overridden. + + + + + Item is live tv program. + + + Type is overridden. + + + + + Item is user root folder. + + + + + Item is user view. + + + + + Item is video. + + + + + Item is year. + + + + + Collection type. + + + + + Unknown collection. + + + + + Movies collection. + + + + + Tv shows collection. + + + + + Music collection. + + + + + Music videos collection. + + + + + Trailers collection. + + + + + Home videos collection. + + + + + Box sets collection. + + + + + Books collection. + + + + + Photos collection. + + + + + Live tv collection. + + + + + Playlists collection. + + + + + Folders collection. + + + + + Tv show series collection. + + + + + Tv genres collection. + + + + + Tv genre collection. + + + + + Tv latest collection. + + + + + Tv next up collection. + + + + + Tv resume collection. + + + + + Tv favorite series collection. + + + + + Tv favorite episodes collection. + + + + + Latest movies collection. + + + + + Movies to resume collection. + + + + + Movie movie collection. + + + + + Movie collections collection. + + + + + Movie favorites collection. + + + + + Movie genres collection. + + + + + Movie genre collection. + + + + + These represent sort orders. + + + + + Default sort order. + + + + + The aired episode order. + + + + + The album. + + + + + The album artist. + + + + + The artist. + + + + + The date created. + + + + + The official rating. + + + + + The date played. + + + + + The premiere date. + + + + + The start date. + + + + + The sort name. + + + + + The name. + + + + + The random. + + + + + The runtime. + + + + + The community rating. + + + + + The production year. + + + + + The play count. + + + + + The critic rating. + + + + + The IsFolder boolean. + + + + + The IsUnplayed boolean. + + + + + The IsPlayed boolean. + + + + + The series sort. + + + + + The video bitrate. + + + + + The air time. + + + + + The studio. + + + + + The IsFavouriteOrLiked boolean. + + + + + The last content added date. + + + + + The series last played date. + + + + + The parent index number. + + + + + The index number. + + + + + Media streaming protocol. + Lowercase for backwards compatibility. + + + + + HTTP. + + + + + HTTP Live Streaming. + + + + + Media types. + + + + + Unknown media type. + + + + + Video media. + + + + + Audio media. + + + + + Photo media. + + + + + Book media. + + + + + The person kind. + + + + + An unknown person kind. + + + + + A person whose profession is acting on the stage, in films, or on television. + + + + + A person who supervises the actors and other staff in a film, play, or similar production. + + + + + A person who writes music, especially as a professional occupation. + + + + + A writer of a book, article, or document. Can also be used as a generic term for music writer if there is a lack of specificity. + + + + + A well-known actor or other performer who appears in a work in which they do not have a regular role. + + + + + A person responsible for the financial and managerial aspects of the making of a film or broadcast or for staging a play, opera, etc. + + + + + A person who directs the performance of an orchestra or choir. + + + + + A person who writes the words to a song or musical. + + + + + A person who adapts a musical composition for performance. + + + + + An audio engineer who performed a general engineering role. + + + + + An engineer responsible for using a mixing console to mix a recorded track into a single piece of music suitable for release. + + + + + A person who remixed a recording by taking one or more other tracks, substantially altering them and mixing them together with other material. + + + + + A person who created the material. + + + + + A person who was the artist. + + + + + A person who was the album artist. + + + + + A person who was the author. + + + + + A person who was the illustrator. + + + + + A person responsible for drawing the art. + + + + + A person responsible for inking the pencil art. + + + + + A person responsible for applying color to drawings. + + + + + A person responsible for drawing text and speech bubbles. + + + + + A person responsible for drawing the cover art. + + + + + A person contributing to a resource by revising or elucidating the content, e.g., adding an introduction, notes, or other critical matter. + An editor may also prepare a resource for production, publication, or distribution. + + + + + A person who renders a text from one language into another. + + + + + Enum SyncPlayAccessRequirementType. + + + + + User must have access to SyncPlay, in some form. + + + + + User must be able to create groups. + + + + + User must be able to join groups. + + + + + User must be in a group. + + + + + An enum representing an unrated item. + + + + + A movie. + + + + + A trailer. + + + + + A series. + + + + + Music. + + + + + A book. + + + + + A live TV channel. + + + + + A live TV program. + + + + + Channel content. + + + + + Another type, not covered by the other fields. + + + + + An enum representing video ranges. + + + + + Unknown video range. + + + + + SDR video range. + + + + + HDR video range. + + + + + An enum representing types of video ranges. + + + + + Unknown video range type. + + + + + SDR video range type (8bit). + + + + + HDR10 video range type (10bit). + + + + + HLG video range type (10bit). + + + + + Dolby Vision video range type (10bit encoded / 12bit remapped). + + + + + Dolby Vision with HDR10 video range fallback (10bit). + + + + + Dolby Vision with HLG video range fallback (10bit). + + + + + Dolby Vision with SDR video range fallback (8bit / 10bit). + + + + + Dolby Vision with Enhancment Layer (Profile 7). + + + + + Dolby Vision and HDR10+ Metadata coexists. + + + + + Dolby Vision with Enhancment Layer (Profile 7) and HDR10+ Metadata coexists. + + + + + Dolby Vision with invalid configuration. e.g. Profile 8 compat id 6. + When using this range, the server would assume the video is still HDR10 after removing the Dolby Vision metadata. + + + + + HDR10+ video range type (10bit to 16bit). + + + + + Provides a generic EventArgs subclass that can hold any kind of object. + + The type of this event. + + + + Initializes a new instance of the class. + + The argument. + + + + Gets the argument. + + The argument. + + + + An event that occurs when there is a pending restart. + + + + + An event that occurs when a user is created. + + + + + Initializes a new instance of the class. + + The user. + + + + An event that occurs when a user is deleted. + + + + + Initializes a new instance of the class. + + The user. + + + + An event that occurs when a user is locked out. + + + + + Initializes a new instance of the class. + + The user. + + + + An event that occurs when a user's password has changed. + + + + + Initializes a new instance of the class. + + The user. + + + + An event that occurs when a user is updated. + + + + + Initializes a new instance of the class. + + The user. + + + + A class representing a query to the activity logs. + + + + + Gets or sets a value indicating whether to take entries with a user id. + + + + + Gets or sets the minimum date to query for. + + + + + Gets or sets the maximum date to query for. + + + + + Gets or sets the name filter. + + + + + Gets or sets the overview filter. + + + + + Gets or sets the short overview filter. + + + + + Gets or sets the type filter. + + + + + Gets or sets the item filter. + + + + + Gets or sets the username filter. + + + + + Gets or sets the log level filter. + + + + + Gets or sets the result ordering. + + + + + A query to retrieve devices. + + + + + Gets or sets the user id of the device. + + + + + Gets or sets the device id. + + + + + Gets or sets the access token. + + + + + An abstract class for paginated queries. + + + + + Gets or sets the index to start at. + + + + + Gets or sets the maximum number of items to include. + + + + + Contains extension methods for manipulation of entities. + + + + + The values being delimited here are Guids, so commas work as they do not appear in Guids. + + + + + Checks whether the user has the specified permission. + + The entity to update. + The permission kind. + True if the user has the specified permission. + + + + Sets the given permission kind to the provided value. + + The entity to update. + The permission kind. + The value to set. + + + + Gets the user's preferences for the given preference kind. + + The entity to update. + The preference kind. + A string array containing the user's preferences. + + + + Gets the user's preferences for the given preference kind. + + The entity to update. + The preference kind. + Type of preference. + A {T} array containing the user's preference. + + + + Sets the specified preference to the given value. + + The entity to update. + The preference kind. + The values. + + + + Sets the specified preference to the given value. + + The entity to update. + The preference kind. + The values. + The type of value. + + + + Checks whether this user is currently allowed to use the server. + + The entity to update. + True if the current time is within an access schedule, or there are no access schedules. + + + + Checks whether the provided folder is in this user's grouped folders. + + The entity to update. + The Guid of the folder. + True if the folder is in the user's grouped folders. + + + + Initializes the default permissions for a user. Should only be called on user creation. + + The entity to update. + + + + Initializes the default preferences. Should only be called on user creation. + + The entity to update. + + + diff --git a/publish/Jellyfin.Database.Implementations.xml b/publish/Jellyfin.Database.Implementations.xml new file mode 100644 index 00000000..d385701b --- /dev/null +++ b/publish/Jellyfin.Database.Implementations.xml @@ -0,0 +1,5176 @@ + + + + Jellyfin.Database.Implementations + + + + + The custom value option for custom database providers. + + + + + Gets or sets the key of the value. + + + + + Gets or sets the value. + + + + + Defines the options for a custom database connector. + + + + + Gets or sets the Plugin name to search for database providers. + + + + + Gets or sets the plugin assembly to search for providers. + + + + + Gets or sets the connection string for the custom database provider. + + + + + Gets or sets the list of extra options for the custom provider. + + + + + Options to configure database backup behavior. + + + + + Gets or sets the path to the pg_dump executable. + If not specified, will search in system PATH. + + + Examples: + - Windows: "C:\\Program Files\\PostgreSQL\\16\\bin\\pg_dump.exe" + - Linux: "/usr/bin/pg_dump" + - Use "pg_dump" to search in PATH. + + + + + Gets or sets the path to the pg_restore executable. + If not specified, will search in system PATH. + + + + + Gets or sets the backup format. + + + Valid values: + - "custom" (default): Custom compressed format (pg_restore compatible) + - "plain": Plain SQL script + - "directory": Directory format + - "tar": Tar archive format. + + + + + Gets or sets a value indicating whether to include large objects (blobs) in backup. + + + + + Gets or sets the compression level (0-9, where 9 is maximum compression). + Only applies to custom and directory formats. + + + + + Gets or sets additional pg_dump arguments. + + + Example: "--verbose --exclude-table-data=public.logs". + + + + + Gets or sets the timeout in seconds for backup operations. + + + + + Gets or sets a value indicating whether to enable verbose output. + + + + + Gets or sets the number of parallel jobs for pg_dump (if format is 'directory'). + + + + + Options to configure jellyfins managed database. + + + + + Initializes a new instance of the class. + + + + + Gets or Sets the type of database jellyfin should use. + + + + + Gets or sets the options required to use a custom database provider. + + + + + Gets or Sets the kind of locking behavior jellyfin should perform. Possible options are "NoLock", "Pessimistic", "Optimistic". + Defaults to "NoLock". + + + + + Gets or sets the backup configuration options. + + + + + Gets or sets preset configurations for quick switching between database providers. + These are stored in the configuration file for reference but not used unless DatabaseType is set to match a preset key. + + + + + Defines all possible methods for locking database access for concurrent queries. + + + + + Defines that no explicit application level locking for reads and writes should be done and only provider specific locking should be relied on. + + + + + Defines a behavior that always blocks all reads while any one write is done. + + + + + Defines that all writes should be attempted and when fail should be retried. + + + + + Represents a key-value pair for XML serialization of preset configurations. + + + + + Gets or sets the key (name) of the preset. + + + + + Gets or sets the preset configuration value. + + + + + Represents a preset database configuration that can be quickly activated. + + + + + Gets or sets the database type for this preset. + + + + + Gets or sets the custom provider options for this preset. + + + + + Gets or sets the locking behavior for this preset. + + + + + Gets or sets a description of this preset. + + + + + An entity representing a user's access schedule. + + + + + Initializes a new instance of the class. + + The day of the week. + The start hour. + The end hour. + The associated user's id. + + + + Gets the id of this instance. + + + Identity, Indexed, Required. + + + + + Gets the id of the associated user. + + + + + Gets or sets the day of week. + + The day of week. + + + + Gets or sets the start hour. + + The start hour. + + + + Gets or sets the end hour. + + The end hour. + + + + An entity referencing an activity log entry. + + + + + Initializes a new instance of the class. + Public constructor with required data. + + The name. + The type. + The user id. + + + + Gets the identity of this instance. + + + + + Gets or sets the name. + + + Required, Max length = 512. + + + + + Gets or sets the overview. + + + Max length = 512. + + + + + Gets or sets the short overview. + + + Max length = 512. + + + + + Gets or sets the type. + + + Required, Max length = 256. + + + + + Gets or sets the user id. + + + Required. + + + + + Gets or sets the item id. + + + Max length = 256. + + + + + Gets or sets the date created. This should be in UTC. + + + Required. + + + + + Gets or sets the log severity. Default is . + + + Required. + + + + + Gets the concurrency token used for optimistic concurrency control. + + + + + Updates the concurrency token before saving changes. + + + + + Represents the relational information for an . + + + + + Gets or Sets the AncestorId. + + + + + Gets or Sets the related BaseItem. + + + + + Gets or Sets the ParentItem. + + + + + Gets or Sets the Child item. + + + + + Provides information about an Attachment to an . + + + + + Gets or Sets the reference. + + + + + Gets or Sets the reference. + + + + + Gets or Sets the index within the source file. + + + + + Gets or Sets the codec of the attachment. + + + + + Gets or Sets the codec tag of the attachment. + + + + + Gets or Sets the comment of the attachment. + + + + + Gets or Sets the filename of the attachment. + + + + + Gets or Sets the attachments mimetype. + + + + + Extension table for music-specific columns on . + Populated only for Audio.Audio items. + + + + + Gets or sets the ID of the parent . Primary key and foreign key. + + + + + Gets or sets the navigation back to the owning . + + + + + Gets or sets the album name this track belongs to. + + + + + Gets or sets the serialized list of track artists. + + + + + Gets or sets the serialized list of album artists. + + + + + Gets or sets the loudness units relative to full scale (LUFS) value for normalization. + + + + + Gets or sets the normalization gain in decibels. + + + + Gets or sets navigation to TV-specific extension data. Populated for TV.Episode, TV.Season, and TV.Series. + + + Gets or sets navigation to LiveTV-specific extension data. Populated for LiveTvProgram and LiveTvChannel. + + + Gets or sets navigation to music-specific extension data. Populated for Audio.Audio. + + + + Enum TrailerTypes. + + + + + Gets or Sets. + + + + + Gets or Sets the path to the original image. + + + + + Gets or Sets the time the image was last modified. + + + + + Gets or Sets the imagetype. + + + + + Gets or Sets the width of the original image. + + + + + Gets or Sets the height of the original image. + + + + + Gets or Sets the blurhash. + + + + + Gets or Sets the reference id to the BaseItem. + + + + + Gets or Sets the referenced Item. + + + + + Extension table for LiveTV-specific columns on . + Populated only for LiveTvProgram and LiveTvChannel items. + + + + + Gets or sets the ID of the parent . Primary key and foreign key. + + + + + Gets or sets the navigation back to the owning . + + + + + Gets or sets the scheduled start date/time of the program. + + + + + Gets or sets the scheduled end date/time of the program. + + + + + Gets or sets the episode title for the program, if it is an episode broadcast. + + + + + Gets or sets the series ID used to correlate this program to its show. Populated for LiveTvProgram. + + + + + Gets or sets the external series identifier. Populated for LiveTvProgram. + + + + + Gets or sets the service name for the channel. Populated for LiveTvChannel. + + + + + Gets or sets the audio type for the program. + + + + + Enum MetadataFields. + + + + + Gets or Sets Numerical ID of this enumerable. + + + + + Gets or Sets all referenced . + + + + + Gets or Sets all referenced . + + + + + Represents a Key-Value relation of an BaseItem's provider. + + + + + Gets or Sets the reference ItemId. + + + + + Gets or Sets the reference BaseItem. + + + + + Gets or Sets the ProvidersId. + + + + + Gets or Sets the Providers Value. + + + + + Enum TrailerTypes. + + + + + Gets or Sets Numerical ID of this enumerable. + + + + + Gets or Sets all referenced . + + + + + Gets or Sets all referenced . + + + + + Extension table for TV-specific columns on . + Populated only for TV.Episode, TV.Season, and TV.Series items. + + + + + Gets or sets the ID of the parent . Primary key and foreign key. + + + + + Gets or sets the navigation back to the owning . + + + + + Gets or sets the ID of the series this item belongs to. + + + + + Gets or sets the ID of the season this item belongs to. Populated for episodes only. + + + + + Gets or sets the name of the series. + + + + + Gets or sets the name of the season. Populated for episodes only. + + + + + Gets or sets the unique key used to group items belonging to the same series. + + + + + The Chapter entity. + + + + + Gets or Sets the reference id. + + + + + Gets or Sets the reference. + + + + + Gets or Sets the chapters index in Item. + + + + + Gets or Sets the position within the source file. + + + + + Gets or Sets the common name. + + + + + Gets or Sets the image path. + + + + + Gets or Sets the time the image was last modified. + + + + + An entity that represents a user's custom display preferences for a specific item. + + + + + Initializes a new instance of the class. + + The user id. + The item id. + The client. + The preference key. + The preference value. + + + + Gets the Id. + + + Required. + + + + + Gets or sets the user Id. + + + Required. + + + + + Gets or sets the id of the associated item. + + + Required. + + + + + Gets or sets the client string. + + + Required. Max Length = 32. + + + + + Gets or sets the preference key. + + + Required. + + + + + Gets or sets the preference value. + + + Required. + + + + + An entity representing a user's display preferences. + + + + + Initializes a new instance of the class. + + The user's id. + The item id. + The client string. + + + + Gets the Id. + + + Required. + + + + + Gets or sets the user Id. + + + Required. + + + + + Gets or sets the id of the associated item. + + + Required. + + + + + Gets or sets the client string. + + + Required. Max Length = 32. + + + + + Gets or sets a value indicating whether to show the sidebar. + + + Required. + + + + + Gets or sets a value indicating whether to show the backdrop. + + + Required. + + + + + Gets or sets the scroll direction. + + + Required. + + + + + Gets or sets what the view should be indexed by. + + + + + Gets or sets the length of time to skip forwards, in milliseconds. + + + Required. + + + + + Gets or sets the length of time to skip backwards, in milliseconds. + + + Required. + + + + + Gets or sets the Chromecast Version. + + + Required. + + + + + Gets or sets a value indicating whether the next video info overlay should be shown. + + + Required. + + + + + Gets or sets the dashboard theme. + + + + + Gets or sets the tv home screen. + + + + + Gets the home sections. + + + + + An entity representing a group. + + + + + Initializes a new instance of the class. + + The name of the group. + + + + Gets the id of this group. + + + Identity, Indexed, Required. + + + + + Gets or sets the group's name. + + + Required, Max length = 255. + + + + + + + + Gets a collection containing the group's permissions. + + + + + Gets a collection containing the group's preferences. + + + + + + + + An entity representing a section on the user's home page. + + + + + Gets the id. + + + Identity. Required. + + + + + Gets or sets the Id of the associated display preferences. + + + Required. + + + + + Gets or sets the order. + + + Required. + + + + + Gets or sets the type. + + + Required. + + + + + An entity representing an image. + + + + + Initializes a new instance of the class. + + The path. + + + + Gets the id. + + + Identity, Indexed, Required. + + + + + Gets the user id. + + + + + Gets or sets the path of the image. + + + Required. + + + + + Gets or sets the date last modified. + + + Required. + + + + + Enum ImageType. + + + + + The primary. + + + + + The art. + + + + + The backdrop. + + + + + The banner. + + + + + The logo. + + + + + The thumb. + + + + + The disc. + + + + + The box. + + + + + The screenshot. + + + This enum value is obsolete. + XmlSerializer does not serialize/deserialize objects that are marked as [Obsolete]. + + + + + The menu. + + + + + The chapter image. + + + + + The box rear. + + + + + The user profile image. + + + + + An entity that represents a user's display preferences for a specific item. + + + + + Initializes a new instance of the class. + + The user id. + The item id. + The client. + + + + Gets the id. + + + Required. + + + + + Gets or sets the user Id. + + + Required. + + + + + Gets or sets the id of the associated item. + + + Required. + + + + + Gets or sets the client string. + + + Required. Max Length = 32. + + + + + Gets or sets the view type. + + + Required. + + + + + Gets or sets a value indicating whether the indexing should be remembered. + + + Required. + + + + + Gets or sets what the view should be indexed by. + + + + + Gets or sets a value indicating whether the sorting type should be remembered. + + + Required. + + + + + Gets or sets what the view should be sorted by. + + + Required. + + + + + Gets or sets the sort order. + + + Required. + + + + + Represents an ItemValue for a BaseItem. + + + + + Gets or Sets the ItemValueId. + + + + + Gets or Sets the Type. + + + + + Gets or Sets the Value. + + + + + Gets or Sets the sanitized Value. + + + + + Gets or Sets all associated BaseItems. + + + + + Mapping table for the ItemValue BaseItem relation. + + + + + Gets or Sets the ItemId. + + + + + Gets or Sets the ItemValueId. + + + + + Gets or Sets the referenced . + + + + + Gets or Sets the referenced . + + + + + Provides the Value types for an . + + + + + Artists. + + + + + Album. + + + + + Genre. + + + + + Studios. + + + + + Tags. + + + + + InheritedTags. + + + + + Keyframe information for a specific file. + + + + + Gets or Sets the ItemId. + + + + + Gets or sets the total duration of the stream in ticks. + + + + + Gets or sets the keyframes in ticks. + + + + + Gets or sets the item reference. + + + + + An entity representing artwork. + + + + + Initializes a new instance of the class. + + The path. + The kind of art. + + + + Gets the id. + + + Identity, Indexed, Required. + + + + + Gets or sets the path. + + + Required, Max length = 65535. + + + + + Gets or sets the kind of artwork. + + + Required. + + + + + + + + + + + An entity representing a book. + + + + + Initializes a new instance of the class. + + The library. + + + + Gets a collection containing the metadata for this book. + + + + + + + + An entity containing metadata for a book. + + + + + Initializes a new instance of the class. + + The title or name of the object. + ISO-639-3 3-character language codes. + + + + Gets or sets the ISBN. + + + + + Gets a collection of the publishers for this book. + + + + + + + + An entity representing a chapter. + + + + + Initializes a new instance of the class. + + ISO-639-3 3-character language codes. + The start time for this chapter. + + + + Gets the id. + + + Identity, Indexed, Required. + + + + + Gets or sets the name. + + + Max length = 1024. + + + + + Gets or sets the language. + + + Required, Min length = 3, Max length = 3 + ISO-639-3 3-character language codes. + + + + + Gets or sets the start time. + + + Required. + + + + + Gets or sets the end time. + + + + + + + + + + + An entity representing a collection. + + + + + Initializes a new instance of the class. + + + + + Gets the id. + + + Identity, Indexed, Required. + + + + + Gets or sets the name. + + + Max length = 1024. + + + + + + + + Gets a collection containing this collection's items. + + + + + + + + An entity representing a collection item. + + + + + Initializes a new instance of the class. + + The library item. + + + + Gets or sets the id. + + + Identity, Indexed, Required. + + + + + + + + Gets or sets the library item. + + + Required. + + + + + Gets or sets the next item in the collection. + + + TODO check if this properly updated Dependent and has the proper principal relationship. + + + + + Gets or sets the previous item in the collection. + + + TODO check if this properly updated Dependent and has the proper principal relationship. + + + + + + + + An entity representing a company. + + + + + Initializes a new instance of the class. + + + + + Gets the id. + + + Identity, Indexed, Required. + + + + + + + + Gets a collection containing the metadata. + + + + + Gets a collection containing this company's child companies. + + + + + + + + + + + An entity holding metadata for a . + + + + + Initializes a new instance of the class. + + The title or name of the object. + ISO-639-3 3-character language codes. + + + + Gets or sets the description. + + + Max length = 65535. + + + + + Gets or sets the headquarters. + + + Max length = 255. + + + + + Gets or sets the country code. + + + Max length = 2. + + + + + Gets or sets the homepage. + + + Max length = 1024. + + + + + An entity representing a custom item. + + + + + Initializes a new instance of the class. + + The library. + + + + Gets a collection containing the metadata for this item. + + + + + + + + An entity containing metadata for a custom item. + + + + + Initializes a new instance of the class. + + The title or name of the object. + ISO-639-3 3-character language codes. + + + + An entity representing an episode. + + + + + Initializes a new instance of the class. + + The library. + + + + Gets or sets the episode number. + + + + + + + + Gets a collection containing the metadata for this episode. + + + + + An entity containing metadata for an . + + + + + Initializes a new instance of the class. + + The title or name of the object. + ISO-639-3 3-character language codes. + + + + Gets or sets the outline. + + + Max length = 1024. + + + + + Gets or sets the plot. + + + Max length = 65535. + + + + + Gets or sets the tagline. + + + Max length = 1024. + + + + + An entity representing a genre. + + + + + Initializes a new instance of the class. + + The name. + + + + Gets the id. + + + Identity, Indexed, Required. + + + + + Gets or sets the name. + + + Indexed, Required, Max length = 255. + + + + + + + + + + + An abstract class that holds metadata. + + + + + Initializes a new instance of the class. + + The title or name of the object. + ISO-639-3 3-character language codes. + + + + Gets the id. + + + Identity, Indexed, Required. + + + + + Gets or sets the title. + + + Required, Max length = 1024. + + + + + Gets or sets the original title. + + + Max length = 1024. + + + + + Gets or sets the sort title. + + + Max length = 1024. + + + + + Gets or sets the language. + + + Required, Min length = 3, Max length = 3. + ISO-639-3 3-character language codes. + + + + + Gets or sets the release date. + + + + + Gets the date added. + + + Required. + + + + + Gets or sets the date modified. + + + Required. + + + + + + + + Gets a collection containing the person roles for this item. + + + + + Gets a collection containing the genres for this item. + + + + + + + + Gets a collection containing the ratings for this item. + + + + + Gets a collection containing the metadata sources for this item. + + + + + + + + An entity representing a library. + + + + + Initializes a new instance of the class. + + The name of the library. + The path of the library. + + + + Gets the id. + + + Identity, Indexed, Required. + + + + + Gets or sets the name. + + + Required, Max length = 128. + + + + + Gets or sets the root path of the library. + + + Required. + + + + + + + + + + + An entity representing a library item. + + + + + Initializes a new instance of the class. + + The library of this item. + + + + Gets the id. + + + Identity, Indexed, Required. + + + + + Gets the date this library item was added. + + + + + + + + Gets or sets the library of this item. + + + Required. + + + + + + + + An entity representing a file on disk. + + + + + Initializes a new instance of the class. + + The path relative to the LibraryRoot. + The file kind. + + + + Gets the id. + + + Identity, Indexed, Required. + + + + + Gets or sets the path relative to the library root. + + + Required, Max length = 65535. + + + + + Gets or sets the kind of media file. + + + Required. + + + + + + + + Gets a collection containing the streams in this file. + + + + + + + + An entity representing a stream in a media file. + + + + + Initializes a new instance of the class. + + The number of this stream. + + + + Gets the id. + + + Identity, Indexed, Required. + + + + + Gets or sets the stream number. + + + Required. + + + + + + + + + + + An entity representing a metadata provider. + + + + + Initializes a new instance of the class. + + The name of the metadata provider. + + + + Gets the id. + + + Identity, Indexed, Required. + + + + + Gets or sets the name. + + + Required, Max length = 1024. + + + + + + + + + + + An entity representing a unique identifier for a metadata provider. + + + + + Initializes a new instance of the class. + + The provider id. + The metadata provider. + + + + Gets the id. + + + Identity, Indexed, Required. + + + + + Gets or sets the provider id. + + + Required, Max length = 255. + + + + + + + + Gets or sets the metadata provider. + + + Required. + + + + + + + + An entity representing a movie. + + + + + Initializes a new instance of the class. + + The library. + + + + + + + Gets a collection containing the metadata for this movie. + + + + + An entity holding the metadata for a movie. + + + + + Initializes a new instance of the class. + + The title or name of the movie. + ISO-639-3 3-character language codes. + + + + Gets or sets the outline. + + + Max length = 1024. + + + + + Gets or sets the tagline. + + + Max length = 1024. + + + + + Gets or sets the plot. + + + Max length = 65535. + + + + + Gets or sets the country code. + + + Max length = 2. + + + + + Gets the studios that produced this movie. + + + + + + + + An entity representing a music album. + + + + + Initializes a new instance of the class. + + The library. + + + + Gets a collection containing the album metadata. + + + + + Gets a collection containing the tracks. + + + + + An entity holding the metadata for a music album. + + + + + Initializes a new instance of the class. + + The title or name of the album. + ISO-639-3 3-character language codes. + + + + Gets or sets the barcode. + + + Max length = 255. + + + + + Gets or sets the label number. + + + Max length = 255. + + + + + Gets or sets the country code. + + + Max length = 2. + + + + + Gets a collection containing the labels. + + + + + An entity representing a person. + + + + + Initializes a new instance of the class. + + The name of the person. + + + + Gets the id. + + + Identity, Indexed, Required. + + + + + Gets or sets the name. + + + Required, Max length = 1024. + + + + + Gets or sets the source id. + + + Max length = 255. + + + + + Gets the date added. + + + Required. + + + + + Gets or sets the date modified. + + + Required. + + + + + + + + Gets a list of metadata sources for this person. + + + + + + + + An entity representing a person's role in media. + + + + + Initializes a new instance of the class. + + The role type. + The person. + + + + Gets the id. + + + Identity, Indexed, Required. + + + + + Gets or sets the name of the person's role. + + + Max length = 1024. + + + + + Gets or sets the person's role type. + + + Required. + + + + + + + + Gets or sets the person. + + + Required. + + + + + + + + Gets a collection containing the metadata sources for this person role. + + + + + + + + An entity representing a photo. + + + + + Initializes a new instance of the class. + + The library. + + + + Gets a collection containing the photo metadata. + + + + + + + + An entity that holds metadata for a photo. + + + + + Initializes a new instance of the class. + + The title or name of the photo. + ISO-639-3 3-character language codes. + + + + An entity representing a rating for an entity. + + + + + Initializes a new instance of the class. + + The value. + + + + Gets the id. + + + Identity, Indexed, Required. + + + + + Gets or sets the value. + + + Required. + + + + + Gets or sets the number of votes. + + + + + + + + Gets or sets the rating type. + If this is null it's the internal user rating. + + + + + + + + This is the entity to store review ratings, not age ratings. + + + + + Initializes a new instance of the class. + + The minimum value. + The maximum value. + + + + Gets the id. + + + Identity, Indexed, Required. + + + + + Gets or sets the name. + + + Max length = 1024. + + + + + Gets or sets the minimum value. + + + Required. + + + + + Gets or sets the maximum value. + + + Required. + + + + + + + + Gets or sets the metadata source. + + + + + + + + An entity representing a release for a library item, eg. Director's cut vs. standard. + + + + + Initializes a new instance of the class. + + The name of this release. + + + + Gets the id. + + + Identity, Indexed, Required. + + + + + Gets or sets the name. + + + Required, Max length = 1024. + + + + + + + + Gets a collection containing the media files for this release. + + + + + Gets a collection containing the chapters for this release. + + + + + + + + An entity representing a season. + + + + + Initializes a new instance of the class. + + The library. + + + + Gets or sets the season number. + + + + + Gets the season metadata. + + + + + Gets a collection containing the number of episodes. + + + + + An entity that holds metadata for seasons. + + + + + Initializes a new instance of the class. + + The title or name of the object. + ISO-639-3 3-character language codes. + + + + Gets or sets the outline. + + + Max length = 1024. + + + + + An entity representing a series. + + + + + Initializes a new instance of the class. + + The library. + + + + Gets or sets the days of week. + + + + + Gets or sets the time the show airs, ignore the date portion. + + + + + Gets or sets the date the series first aired. + + + + + Gets a collection containing the series metadata. + + + + + Gets a collection containing the seasons. + + + + + An entity representing series metadata. + + + + + Initializes a new instance of the class. + + The title or name of the object. + ISO-639-3 3-character language codes. + + + + Gets or sets the outline. + + + Max length = 1024. + + + + + Gets or sets the plot. + + + Max length = 65535. + + + + + Gets or sets the tagline. + + + Max length = 1024. + + + + + Gets or sets the country code. + + + Max length = 2. + + + + + Gets a collection containing the networks. + + + + + + + + An entity representing a track. + + + + + Initializes a new instance of the class. + + The library. + + + + Gets or sets the track number. + + + + + + + + Gets a collection containing the track metadata. + + + + + An entity holding metadata for a track. + + + + + Initializes a new instance of the class. + + The title or name of the object. + ISO-639-3 3-character language codes. + + + + Stores serialized collection-folder library options for database-backed persistence. + + + + + Gets or sets the collection folder path used as the prototype key. + + + + + Gets or sets the serialized library options JSON payload. + + + + + Gets or sets the schema version for the serialized payload. + + + + + Gets or sets the UTC timestamp when the row was created. + + + + + Gets or sets the UTC timestamp when the row was last modified. + + + + + An entity representing the metadata for a group of trickplay tiles. + + + + + Gets or sets the id of the media segment. + + + + + Gets or sets the id of the associated item. + + + + + Gets or sets the Type of content this segment defines. + + + + + Gets or sets the end of the segment. + + + + + Gets or sets the start of the segment. + + + + + Gets or sets Id of the media segment provider this entry originates from. + + + + + Gets or sets audio-specific stream details. Non-null only when is Audio. + + + + + Gets or sets video-specific stream details. Non-null only when is Video. + + + + + Enum MediaStreamType. + + + + + The audio. + + + + + The video. + + + + + The subtitle. + + + + + The embedded image. + + + + + The data. + + + + + The lyric. + + + + + People entity. + + + + + Gets or Sets the PeopleId. + + + + + Gets or Sets the Persons Name. + + + + + Gets or Sets the Type. + + + + + Gets or Sets the mapping of People to BaseItems. + + + + + Mapping table for People to BaseItems. + + + + + Gets or Sets the SortOrder. + + + + + Gets or Sets the ListOrder. + + + + + Gets or Sets the Role name the associated actor played in the . + + + + + Gets or Sets The ItemId. + + + + + Gets or Sets Reference Item. + + + + + Gets or Sets The PeopleId. + + + + + Gets or Sets Reference People. + + + + + An entity representing whether the associated user has a specific permission. + + + + + Initializes a new instance of the class. + Public constructor with required data. + + The permission kind. + The value of this permission. + + + + Gets the id of this permission. + + + Identity, Indexed, Required. + + + + + Gets or sets the id of the associated user. + + + + + Gets the type of this permission. + + + Required. + + + + + Gets or sets a value indicating whether the associated user has this permission. + + + Required. + + + + + + + + + + + An entity representing a preference attached to a user or group. + + + + + Initializes a new instance of the class. + Public constructor with required data. + + The preference kind. + The value. + + + + Gets the id of this preference. + + + Identity, Indexed, Required. + + + + + Gets or sets the id of the associated user. + + + + + Gets the type of this preference. + + + Required. + + + + + Gets or sets the value of this preference. + + + Required, Max length = 65535. + + + + + + + + + + + Lists types of Audio. + + + + + Mono. + + + + + Stereo. + + + + + Dolby. + + + + + DolbyDigital. + + + + + Thx. + + + + + Atmos. + + + + + An entity representing an API key. + + + + + Initializes a new instance of the class. + + The name. + + + + Gets the id. + + + Identity, Indexed, Required. + + + + + Gets or sets the date created. + + + + + Gets or sets the date of last activity. + + + + + Gets or sets the name. + + + + + Gets or sets the access token. + + + + + An entity representing a device. + + + + + Initializes a new instance of the class. + + The user id. + The app name. + The app version. + The device name. + The device id. + + + + Gets the id. + + + + + Gets the user id. + + + + + Gets or sets the access token. + + + + + Gets or sets the app name. + + + + + Gets or sets the app version. + + + + + Gets or sets the device name. + + + + + Gets or sets the device id. + + + + + Gets or sets a value indicating whether this device is active. + + + + + Gets or sets the date created. + + + + + Gets or sets the date modified. + + + + + Gets or sets the date of last activity. + + + + + Gets the user. + + + + + An entity representing custom options for a device. + + + + + Initializes a new instance of the class. + + The device id. + + + + Gets the id. + + + + + Gets the device id. + + + + + Gets or sets the custom name. + + + + + An entity representing the metadata for a group of trickplay tiles. + + + + + Gets or sets the id of the associated item. + + + Required. + + + + + Gets or sets width of an individual thumbnail. + + + Required. + + + + + Gets or sets height of an individual thumbnail. + + + Required. + + + + + Gets or sets amount of thumbnails per row. + + + Required. + + + + + Gets or sets amount of thumbnails per column. + + + Required. + + + + + Gets or sets total amount of non-black thumbnails. + + + Required. + + + + + Gets or sets interval in milliseconds between each trickplay thumbnail. + + + Required. + + + + + Gets or sets peak bandwidth usage in bits per second. + + + Required. + + + + + An entity representing a user. + + + + + Initializes a new instance of the class. + Public constructor with required data. + + The username for the new user. + The Id of the user's authentication provider. + The Id of the user's password reset provider. + + + + Gets or sets the Id of the user. + + + Identity, Indexed, Required. + + + + + Gets or sets the user's name. + + + Required, Max length = 255. + + + + + Gets or sets the user's password, or null if none is set. + + + Max length = 65535. + + + + + Gets or sets a value indicating whether the user must update their password. + + + Required. + + + + + Gets or sets the audio language preference. + + + Max length = 255. + + + + + Gets or sets the authentication provider id. + + + Required, Max length = 255. + + + + + Gets or sets the password reset provider id. + + + Required, Max length = 255. + + + + + Gets or sets the invalid login attempt count. + + + Required. + + + + + Gets or sets the last activity date. + + + + + Gets or sets the last login date. + + + + + Gets or sets the number of login attempts the user can make before they are locked out. + + + + + Gets or sets the maximum number of active sessions the user can have at once. + + + + + Gets or sets the subtitle mode. + + + Required. + + + + + Gets or sets a value indicating whether the default audio track should be played. + + + Required. + + + + + Gets or sets the subtitle language preference. + + + Max length = 255. + + + + + Gets or sets a value indicating whether missing episodes should be displayed. + + + Required. + + + + + Gets or sets a value indicating whether to display the collections view. + + + Required. + + + + + Gets or sets a value indicating whether the user has a local password. + + + Required. + + + + + Gets or sets a value indicating whether the server should hide played content in "Latest". + + + Required. + + + + + Gets or sets a value indicating whether to remember audio selections on played content. + + + Required. + + + + + Gets or sets a value indicating whether to remember subtitle selections on played content. + + + Required. + + + + + Gets or sets a value indicating whether to enable auto-play for the next episode. + + + Required. + + + + + Gets or sets a value indicating whether the user should auto-login. + + + Required. + + + + + Gets or sets a value indicating whether the user can change their preferences. + + + Required. + + + + + Gets or sets the maximum parental rating score. + + + + + Gets or sets the maximum parental rating sub score. + + + + + Gets or sets the remote client bitrate limit. + + + + + Gets or sets the internal id. + This is a temporary stopgap for until the library db is migrated. + This corresponds to the value of the index of this user in the library db. + + + + + Gets or sets the user's profile image. Can be null. + + + + + Gets the user's display preferences. + + + + + Gets or sets the level of sync play permissions this user has. + + + + + Gets or sets the cast receiver id. + + + + + + + + Gets the list of access schedules this user has. + + + + + Gets the list of item display preferences. + + + + + Gets the list of permissions this user has. + + + + + Gets the list of preferences this user has. + + + + + + + + Provides and related data. + + + + + Gets or sets the custom data key. + + The rating. + + + + Gets or sets the users 0-10 rating. + + The rating. + + + + Gets or sets the playback position ticks. + + The playback position ticks. + + + + Gets or sets the play count. + + The play count. + + + + Gets or sets a value indicating whether this instance is favorite. + + true if this instance is favorite; otherwise, false. + + + + Gets or sets the last played date. + + The last played date. + + + + Gets or sets a value indicating whether this is played. + + true if played; otherwise, false. + + + + Gets or sets the index of the audio stream. + + The index of the audio stream. + + + + Gets or sets the index of the subtitle stream. + + The index of the subtitle stream. + + + + Gets or sets a value indicating whether the item is liked or not. + This should never be serialized. + + null if [likes] contains no value, true if [likes]; otherwise, false. + + + + Gets or Sets the date the referenced has been deleted. + + + + + Gets or sets the key. + + The key. + + + + Gets or Sets the BaseItem. + + + + + Gets or Sets the UserId. + + + + + Gets or Sets the User. + + + + + Read-only projection of the library."ItemPeople_v" view. + All cast and crew entries linked to the items they appear in. + + + + + Read-only projection of library."ItemProviders_v". + Items with external provider IDs pivoted into named columns. + + + + Gets or sets remaining providers as a JSON object string. + + + + Read-only projection of the library."LibrarySummary_v" view. + One row per item type with aggregate statistics across the whole library. + + + + + Read-only projection of library."MediaStreamInfos_v". + Flat view of all media streams with audio- and video-specific columns merged. + + + + + Read-only projection of library."UserPlaybackHistory_v". + Per-user watch history with calculated progress percentage. + + + + Gets or sets playback progress 0–100. NULL when no runtime. + + + + Read-only projection of library."VideoItems_v". + Every non-folder, non-virtual item with at least one video stream. + + + + Gets or sets derived HDR format: "Dolby Vision", "HDR10+", "HDR10", "HLG", or "SDR". + + + + An enum representing types of art. + + + + + Another type of art, not covered by the other members. + + + + + A poster. + + + + + A banner. + + + + + A thumbnail. + + + + + A logo. + + + + + An enum representing the version of Chromecast to be used by clients. + + + + + Stable Chromecast version. + + + + + Unstable Chromecast version. + + + + + An enum that represents a day of the week, weekdays, weekends, or all days. + + + + + Sunday. + + + + + Monday. + + + + + Tuesday. + + + + + Wednesday. + + + + + Thursday. + + + + + Friday. + + + + + Saturday. + + + + + All days of the week. + + + + + A week day, or Monday-Friday. + + + + + Saturday and Sunday. + + + + + An enum representing the different options for the home screen sections. + + + + + None. + + + + + My Media. + + + + + My Media Small. + + + + + Active Recordings. + + + + + Continue Watching. + + + + + Continue Listening. + + + + + Latest Media. + + + + + Next Up. + + + + + Live TV. + + + + + Continue Reading. + + + + + An enum representing a type of indexing in a user's display preferences. + + + + + Index by the premiere date. + + + + + Index by the production year. + + + + + Index by the community rating. + + + + + An enum representing the type of media file. + + + + + The main file. + + + + + A sidecar file. + + + + + An additional part to the main file. + + + + + An alternative format to the main file. + + + + + An additional stream for the main file. + + + + + Defines the types of content an individual represents. + + + + + Default media type or custom one. + + + + + Commercial. + + + + + Preview. + + + + + Recap. + + + + + Outro. + + + + + Intro. + + + + + The types of user permissions. + + + + + Whether the user is an administrator. + + + + + Whether the user is hidden. + + + + + Whether the user is disabled. + + + + + Whether the user can control shared devices. + + + + + Whether the user can access the server remotely. + + + + + Whether the user can manage live tv. + + + + + Whether the user can access live tv. + + + + + Whether the user can play media. + + + + + Whether the server should transcode audio for the user if requested. + + + + + Whether the server should transcode video for the user if requested. + + + + + Whether the user can delete content. + + + + + Whether the user can download content. + + + + + Whether to enable sync transcoding for the user. + + + + + Whether the user can do media conversion. + + + + + Whether the user has access to all devices. + + + + + Whether the user has access to all channels. + + + + + Whether the user has access to all folders. + + + + + Whether to enable public sharing for the user. + + + + + Whether the user can remotely control other users. + + + + + Whether the user is permitted to do playback remuxing. + + + + + Whether the server should force transcoding on remote connections for the user. + + + + + Whether the user can create, modify and delete collections. + + + + + Whether the user can edit subtitles. + + + + + Whether the user can edit lyrics. + + + + + An enum representing a person's role in a specific media item. + + + + + Another role, not covered by the other types. + + + + + The director of the media. + + + + + An artist. + + + + + The original artist. + + + + + An actor. + + + + + A voice actor. + + + + + A producer. + + + + + A remixer. + + + + + A conductor. + + + + + A composer. + + + + + An author. + + + + + An editor. + + + + + The types of user preferences. + + + + + A list of blocked tags. + + + + + A list of blocked channels. + + + + + A list of blocked media folders. + + + + + A list of enabled devices. + + + + + A list of enabled channels. + + + + + A list of enabled folders. + + + + + A list of folders to allow content deletion from. + + + + + A list of latest items to exclude. + + + + + A list of media to exclude. + + + + + A list of grouped folders. + + + + + A list of unrated items to block. + + + + + A list of ordered views. + + + + + A list of allowed tags. + + + + + An enum representing the axis that should be scrolled. + + + + + Horizontal scrolling direction. + + + + + Vertical scrolling direction. + + + + + An enum representing the sorting order. + + + + + Sort in increasing order. + + + + + Sort in decreasing order. + + + + + An enum representing a subtitle playback mode. + + + + + The default subtitle playback mode. + + + + + Always show subtitles. + + + + + Only show forced subtitles. + + + + + Don't show subtitles. + + + + + Only show subtitles when the current audio stream is in a different language. + + + + + Enum SyncPlayUserAccessType. + + + + + User can create groups and join them. + + + + + User can only join already existing groups. + + + + + SyncPlay is disabled for the user. + + + + + An enum representing the type of view for a library or collection. + + + + + Shows albums. + + + + + Shows album artists. + + + + + Shows artists. + + + + + Shows channels. + + + + + Shows collections. + + + + + Shows episodes. + + + + + Shows favorites. + + + + + Shows genres. + + + + + Shows guide. + + + + + Shows movies. + + + + + Shows networks. + + + + + Shows playlists. + + + + + Shows programs. + + + + + Shows recordings. + + + + + Shows schedule. + + + + + Shows series. + + + + + Shows shows. + + + + + Shows songs. + + + + + Shows songs. + + + + + Shows trailers. + + + + + Shows upcoming. + + + + + Defines the type and extension points for multi database support. + + + + + Gets or Sets the Database Factory when initialisaition is done. + + + + + Initialises jellyfins EFCore database access. + + The EFCore database options. + The Jellyfin database options. + + + + Will be invoked when EFCore wants to build its model. + + The ModelBuilder from EFCore. + + + + Will be invoked when EFCore wants to configure its model. + + The ModelConfigurationBuilder from EFCore. + + + + If supported this should run any periodic maintaince tasks. + + The token to abort the operation. + A representing the asynchronous operation. + + + + If supported this should perform any actions that are required on stopping the jellyfin server. + + The token that will be used to abort the operation. + A representing the asynchronous operation. + + + + Runs a full Database backup that can later be restored to. + + A cancellation token. + A key to identify the backup. + May throw an NotImplementException if this operation is not supported for this database. + + + + Restores a backup that has been previously created by . + + The key to the backup from which the current database should be restored from. + A cancellation token. + A representing the result of the asynchronous operation. + + + + Deletes a backup that has been previously created by . + + The key to the backup which should be cleaned up. + A representing the result of the asynchronous operation. + + + + Removes all contents from the database. + + The Database context. + The names of the tables to purge or null for all tables to be purged. + A Task. + + + + Ensures all required database tables exist by applying pending migrations if necessary. + This method should be called during startup to verify database schema integrity. + + Cancellation token. + A representing the asynchronous operation. + + + + An interface abstracting an entity that has artwork. + + + + + Gets a collection containing this entity's artwork. + + + + + An abstraction representing an entity that has companies. + + + + + Gets a collection containing this entity's companies. + + + + + An interface abstracting an entity that has a concurrency token. + + + + + Gets the version of this row. Acts as a concurrency token. + + + + + Called when saving changes to this entity. + + + + + An abstraction representing an entity that has permissions. + + + + + Gets a collection containing this entity's permissions. + + + + + An abstraction representing an entity that has releases. + + + + + Gets a collection containing this entity's releases. + + + + + Defines the key of the database provider. + + + + + Initializes a new instance of the class. + + The key on which to identify the annotated provider. + + + + Gets the key on which to identify the annotated provider. + + + + + + Initializes a new instance of the class. + + The database context options. + Logger. + The provider for the database engine specific operations. + The locking behavior. + + + + + Initializes a new instance of the class. + + The database context options. + Logger. + The provider for the database engine specific operations. + The locking behavior. + + + + Gets the containing the access schedules. + + + + + Gets the containing the activity logs. + + + + + Gets the containing the API keys. + + + + + Gets the containing the devices. + + + + + Gets the containing the device options. + + + + + Gets the containing the display preferences. + + + + + Gets the containing the image infos. + + + + + Gets the containing the item display preferences. + + + + + Gets the containing the custom item display preferences. + + + + + Gets the containing the permissions. + + + + + Gets the containing the preferences. + + + + + Gets the containing the users. + + + + + Gets the containing the trickplay metadata. + + + + + Gets the containing the media segments. + + + + + Gets the containing the user data. + + + + + Gets the containing the user data. + + + + + Gets the containing the user data. + + + + + Gets the containing the user data. + + + + + Gets the containing the user data. + + + + + Gets the . + + + + + Gets the . + + + + + Gets the . + + + + + Gets the containing audio-specific stream details. + + + + + Gets the containing video-specific stream details. + + + + + Gets the flat view over MediaStreamInfos joined with audio and video detail tables. + Maps to library."MediaStreamInfos_v". + + + + + Gets the view of video items joined with their primary stream details. + Maps to library."VideoItems_v". + + + + + Gets the view of per-user watch history with calculated progress. + Maps to library."UserPlaybackHistory_v". + + + + + Gets the view of items with pivoted external provider IDs. + Maps to library."ItemProviders_v". + + + + + Gets the view of cast and crew entries linked to their items. + Maps to library."ItemPeople_v". + + + + + Gets the aggregate library statistics view, one row per item type. + Maps to library."LibrarySummary_v". + + + + + Gets the . + + + + + Gets the . + + + + + Gets the containing the referenced Providers with ids. + + + + + Gets the . + + + + + Gets the . + + + + + Gets the . + + + + + Gets the . + + + + + Gets the containing persisted library options. + + + + + Gets the containing TV-specific extension data for BaseItems. + + + + + Gets the containing LiveTV-specific extension data for BaseItems. + + + + + Gets the containing music-specific extension data for BaseItems. + + + + + + + + + + + Gets the recommended batch size for bulk operations based on the number of items to process. + Smaller batches during library scans reduce dead tuple generation in PostgreSQL. + + The total number of entities being processed. + The recommended batch size for optimal performance. + + + + + + + + + + Contains a number of query related extensions. + + + + + Builds an optimised query checking one property against a list of values while maintaining an optimal query. + + The entity. + The property type to compare. + The source query. + The list of items to check. + Property expression. + A Query. + + + + Builds a query that checks referenced ItemValues for a cross BaseItem lookup. + + The source query. + The database context. + The type of item value to reference. + The list of BaseItem ids to check matches. + If set an exclusion check is performed instead. + A Query. + + + + Builds a query that checks referenced ItemValues for a cross BaseItem lookup. + + The source query. + The database context. + The type of item value to reference. + The list of BaseItem ids to check matches. + If set an exclusion check is performed instead. + A Query. + + + + Builds a query expression that checks referenced ItemValues for a cross BaseItem lookup. + + The database context. + The type of item value to reference. + The list of BaseItem ids to check matches. + If set an exclusion check is performed instead. + A Query. + + + + Builds an optimised query expression checking one property against a list of values while maintaining an optimal query. + + The entity. + The property type to compare. + The list of items to check. + Property expression. + A Query. + + + + Defines a jellyfin locking behavior that can be configured. + + + + + Provides access to the builder to setup any connection related locking behavior. + + The options builder. + + + + Will be invoked when changes should be saved in the current locking behavior. + + The database context invoking the action. + Callback for performing the actual save changes. + + + + Will be invoked when changes should be saved in the current locking behavior. + + The database context invoking the action. + Callback for performing the actual save changes. + A representing the asynchronous operation. + + + + Default lock behavior. Defines no explicit application locking behavior. + + + + + Initializes a new instance of the class. + + The Application logger. + + + + + + + + + + + + + Defines a locking mechanism that will retry any write operation for a few times. + + + + + Initializes a new instance of the class. + + The application logger. + + + + + + + + + + + + + A locking behavior that will always block any operation while a write is requested. Mimicks the old SqliteRepository behavior. + + + + + Initializes a new instance of the class. + + The application logger. + The logger factory. + + + + + + + + + + + + + Adds strict read/write locking. + + + + + FluentAPI configuration for the ActivityLog entity. + + + + + + + + AncestorId configuration. + + + + + + + + FluentAPI configuration for the ApiKey entity. + + + + + + + + FluentAPI configuration for the AttachmentStreamInfo entity. + + + + + + + + EF Core configuration for . + + + + + + + + EF Core configuration for . + + + + + + + + Configuration for BaseItem. + + + + + + + + EF Core configuration for . + + + + + + + + Provides configuration for the BaseItemMetadataField entity. + + + + + + + + BaseItemProvider configuration. + + + + + + + + Provides configuration for the BaseItemMetadataField entity. + + + + + + + + EF Core configuration for . + + + + + + + + Chapter configuration. + + + + + + + + FluentAPI configuration for the CustomItemDisplayPreferences entity. + + + + + + + + FluentAPI configuration for the Device entity. + + + + + + + + FluentAPI configuration for the DeviceOptions entity. + + + + + + + + FluentAPI configuration for the DisplayPreferencesConfiguration entity. + + + + + + + + FluentAPI configuration for the HomeSection entity. + + + + + + + + itemvalues Configuration. + + + + + + + + itemvalues Configuration. + + + + + + + + KeyframeData Configuration. + + + + + + + + LibraryOptionsEntity Configuration. + + + + + + + + People configuration. + + + + + + + + People configuration. + + + + + + + + People configuration. + + + + + + + + FluentAPI configuration for the Permission entity. + + + + + + + + FluentAPI configuration for the Permission entity. + + + + + + + + FluentAPI configuration for the TrickplayInfo entity. + + + + + + + + FluentAPI configuration for the User entity. + + + + + + + + FluentAPI configuration for the UserData entity. + + + + + + + + EF Core configuration for . + + + + + + + + Wrapper for progress reporting on Partition helpers. + + The entity to load. + + + + Contains helpers to partition EFCore queries. + + + + + Adds a callback to any directly following calls of Partition for every partition thats been invoked. + + The entity to load. + The source query. + The callback invoked for partition before enumerating items. + The callback invoked for partition after enumerating items. + A queryable that can be used to partition. + + + + Adds a callback to any directly following calls of Partition for every item thats been invoked. + + The entity to load. + The source query. + The callback invoked for each item before processing. + The callback invoked for each item after processing. + A queryable that can be used to partition. + + + + Adds a callback to any directly following calls of Partition for every partition thats been invoked. + + The entity to load. + The source query. + The callback invoked for partition before enumerating items. + The callback invoked for partition after enumerating items. + A queryable that can be used to partition. + + + + Adds a callback to any directly following calls of Partition for every item thats been invoked. + + The entity to load. + The source query. + The callback invoked for each item before processing. + The callback invoked for each item after processing. + A queryable that can be used to partition. + + + + Enumerates the source query by loading the entities in partitions in a lazy manner reading each item from the database as its requested. + + The entity to load. + The source query. + The number of elements to load per partition. + The cancellation token. + A enumerable representing the whole of the query. + + + + Enumerates the source query by loading the entities in partitions directly into memory. + + The entity to load. + The source query. + The number of elements to load per partition. + The cancellation token. + A enumerable representing the whole of the query. + + + + Enumerates the source query by loading the entities in partitions in a lazy manner reading each item from the database as its requested. + + The entity to load. + The source query. + The number of elements to load per partition. + Reporting helper. + The cancellation token. + A enumerable representing the whole of the query. + + + + Enumerates the source query by loading the entities in partitions directly into memory. + + The entity to load. + The source query. + The number of elements to load per partition. + Reporting helper. + The cancellation token. + A enumerable representing the whole of the query. + + + + Adds an Index to the enumeration of the async enumerable. + + The entity to load. + The source query. + The source list with an index added. + + + diff --git a/publish/Jellyfin.Database.Providers.Postgres.xml b/publish/Jellyfin.Database.Providers.Postgres.xml new file mode 100644 index 00000000..ed89d178 --- /dev/null +++ b/publish/Jellyfin.Database.Providers.Postgres.xml @@ -0,0 +1,484 @@ + + + + Jellyfin.Database.Providers.Postgres + + + + + Extension methods for optimized bulk operations on PostgreSQL. + These methods help reduce dead tuple generation during media library scans by batching + operations and using more efficient transaction patterns. + + + + + Gets the recommended batch size for bulk operations based on the data size. + PostgreSQL works best with smaller batches to reduce dead tuples during scans. + + The total number of entities to process. + The recommended batch size. + + + + Saves changes in batches to reduce dead tuple generation during bulk operations. + This is especially useful during media library scans where many items are created/updated/deleted. + + The database context. + The batch size for SaveChanges calls. If 0 or negative, uses automatic sizing. + Cancellation token. + Total number of changes saved. + + + + Deletes entities in batches using raw SQL for better performance. + This reduces dead tuple generation compared to loading and deleting entities individually. + + The database context. + The PostgreSQL schema name. + The table name. + Optional WHERE clause (without WHERE keyword). If null, all rows are deleted. + Cancellation token. + The number of rows deleted. + + + + Truncates a table completely, which is much faster than DELETE for large tables. + Note: This cannot be used if there are foreign key references. + + The database context. + The PostgreSQL schema name. + The table name. + If true, will CASCADE delete related rows. Use with caution. + Cancellation token. + A task representing the asynchronous operation. + + + + Adds a large collection of entities to the context in batches to avoid memory issues. + + The entity type. + The database context. + The entities to add. + The batch size for adding entities. + Whether to save changes after each batch. + Cancellation token. + Total number of entities saved. + + + + Updates entities in batches to reduce dead tuple generation. + + The entity type. + The database context. + The entities to update. + The batch size for updates. + Cancellation token. + Total number of entities updated. + + + + Removes entities in batches to reduce dead tuple generation. + + The entity type. + The database context. + The entities to remove. + The batch size for removals. + Cancellation token. + Total number of entities removed. + + + + Executes VACUUM ANALYZE on a specific table to reclaim dead tuples and update statistics. + This is useful to call after bulk deletion operations. + + The database context. + The PostgreSQL schema name. + The table name. + Cancellation token. + A task representing the asynchronous operation. + + + + Helper class for managing transactions during bulk operations to reduce dead tuple generation. + + + + + Initializes a new instance of the class. + + The database context. + + + + Gets a value indicating whether the transaction has been committed. + + + + + Begins a new transaction with isolation level optimized for bulk operations. + + Cancellation token. + A task representing the asynchronous operation. + + + + Commits the transaction. + + Cancellation token. + A task representing the asynchronous operation. + + + + Rolls back the transaction. + + Cancellation token. + A task representing the asynchronous operation. + + + + Disposes the transaction if not already committed. + + + + + Disposes the transaction asynchronously if not already committed. + + A task representing the asynchronous operation. + + + + Extension methods for managing bulk operation transactions. + + + + + Executes a bulk operation within a transaction. + + The database context. + The bulk operation to execute. + Cancellation token. + A task representing the asynchronous operation. + + + + Executes a bulk operation within a transaction and returns a result. + + The type of result returned by the operation. + The database context. + The bulk operation to execute. + Cancellation token. + The result of the operation. + + + + Exception thrown when there is a version mismatch between PostgreSQL server and client tools (pg_dump/pg_restore). + + + + + Initializes a new instance of the class. + + The PostgreSQL server version. + The pg_dump/pg_restore client version. + + + + Initializes a new instance of the class. + + The PostgreSQL server version. + The pg_dump/pg_restore client version. + The inner exception. + + + + Gets the PostgreSQL server version. + + + + + Gets the pg_dump/pg_restore client version. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Removes the 17 flat extension columns from library.BaseItems now that all data has been + migrated to the BaseItemTvExtras, BaseItemLiveTvExtras, and BaseItemAudioExtras tables. + Must run AFTER SplitBaseItemExtras (20260503000000). + + + + + + + + + + + The design time factory for . + This is only used for the creation of migrations and not during runtime. + + + + + + + + + + + + + + + + + Model builder extensions for PostgreSQL. + + + + + Specify value converter for the object type. + + The model builder. + The . + The type to convert. + The modified . + + + + Specify the default . + + The model builder to extend. + The to specify. + + + + Service for creating and restoring PostgreSQL database backups using pg_dump/pg_restore. + + + + + Initializes a new instance of the class. + + The logger. + The configuration manager. + + + + Creates a backup of the PostgreSQL database. + + The directory to save the backup file. + Cancellation token. + The path to the created backup file. + + + + Restores a PostgreSQL database from a backup file. + + The path to the backup file. + Cancellation token. + A task representing the restore operation. + + + + Parses PostgreSQL version mismatch error message to extract server and client versions. + + The error message from pg_dump. + A tuple containing server version and client version. + + + + Configures Jellyfin to use a PostgreSQL database. + + + + + Initializes a new instance of the class. + + Service to construct the fallback when the old data path configuration is used. + A logger. + The configuration manager (optional, for backup support). + + + + Schema names mapping to legacy database files. + + + + + Schema for activity log tables (legacy: activitylog.db). + + + + + Schema for authentication tables (legacy: authentication.db). + + + + + Schema for display preferences tables (legacy: displaypreferences.db). + + + + + Schema for library tables (legacy: library.db). + + + + + Schema for user tables (legacy: users.db). + + + + + Gets all schema names. + + + + + + + + + + + Ensures the PostgreSQL database exists, creating it if necessary. + + The database configuration. + Cancellation token. + A task representing the asynchronous operation. + + + + Ensures all required schemas exist in the PostgreSQL database. + + + + + Ensures all required database tables exist by applying pending migrations. + + Cancellation token. + A task representing the asynchronous operation. + + + + + + + + + + Assigns entities to PostgreSQL schemas based on their legacy database origin. + + The model builder. + + + + Registers read-only keyless view projections for PostgreSQL. + Each view lives in the library schema and is mapped with + HasNoKey().ToView() so EF Core never tries to create a table or migration for it. + + The model builder. + + + + + + + + + + + + + + + + + + + Determines if the given host is localhost. + + The host to check. + True if the host is localhost or 127.0.0.1, false otherwise. + + + + + + + EF Core convention that maps all entity property names to snake_case column names. + Applied only by the PostgreSQL provider so SQLite is unaffected. + + + + + + + Converts a PascalCase identifier to snake_case. + The identifier to convert. + The snake_case representation of the identifier. + + + + ValueConverter to specify DateTime kind for PostgreSQL. + + + + + Initializes a new instance of the class. + + The kind to specify. + The mapping hints. + + + diff --git a/publish/Jellyfin.Drawing.Skia.xml b/publish/Jellyfin.Drawing.Skia.xml new file mode 100644 index 00000000..c3e946b3 --- /dev/null +++ b/publish/Jellyfin.Drawing.Skia.xml @@ -0,0 +1,352 @@ + + + + Jellyfin.Drawing.Skia + + + + + Static helper class used to draw percentage-played indicators on images. + + + + + Draw a percentage played indicator on a canvas. + + The canvas to draw the indicator on. + The size of the image being drawn on. + The percentage played to display with the indicator. + + + + Image encoder that uses to manipulate images. + + + + + The default sampling options, equivalent to old high quality filter settings when upscaling. + + + + + The sampling options, used for downscaling images, equivalent to old high quality filter settings when not upscaling. + + + + + Initializes a new instance of the class. + + The application logger. + The application paths. + + + + + + + + + + + + + + + + + + + Gets the default typeface to use. + + + + + Check if the native lib is available. + + True if the native lib is available, otherwise false. + + + + Convert a to a . + + The format to convert. + The converted format. + + + + The path is not valid. + + + + The path is null. + The path is not valid. + + + + Decode an image. + + The filepath of the image to decode. + Whether to force clean the bitmap. + The orientation of the image. + The detected origin of the image. + The resulting bitmap of the image. + + + + Resizes an image on the CPU, by utilizing a surface and canvas. + + The convolutional matrix kernel used in this resize function gives a (light) sharpening effect. + This technique is similar to effect that can be created using for example the [Convolution matrix filter in GIMP](https://docs.gimp.org/2.10/en/gimp-filter-convolution-matrix.html). + + The source bitmap. + This specifies the target size and other information required to create the surface. + This enables anti-aliasing on the SKPaint instance. + This enables dithering on the SKPaint instance. + The resized image. + + + + + + + + + + + + + + + + Return the typeface that contains the glyph for the given character. + + The text character. + The typeface contains the character. + + + + The SkiaSharp extensions. + + + + + Draws an SKBitmap on the canvas with specified SkSamplingOptions. + + The SKCanvas to draw on. + The SKBitmap to draw. + The destination SKRect. + The SKSamplingOptions to use for rendering. + Optional SKPaint to apply additional effects or styles. + + + + Draws an SKBitmap on the canvas at the specified coordinates with the given SkSamplingOptions. + + The SKCanvas to draw on. + The SKBitmap to draw. + The x-coordinate where the bitmap will be drawn. + The y-coordinate where the bitmap will be drawn. + The SKSamplingOptions to use for rendering. + Optional SKPaint to apply additional effects or styles. + + + + Draws an SKBitmap on the canvas using a specified source rectangle, destination rectangle, + and optional paint, with the given SkSamplingOptions. + + The SKCanvas to draw on. + The SKBitmap to draw. + + The source SKRect defining the portion of the bitmap to draw. + + + The destination SKRect defining the area on the canvas where the bitmap will be drawn. + + The SKSamplingOptions to use for rendering. + Optional SKPaint to apply additional effects or styles. + + + + Class containing helper methods for working with SkiaSharp. + + + + + Gets the next valid image as a bitmap. + + The current skia encoder. + The list of image paths. + The current checked index. + The new index. + A valid bitmap, or null if no bitmap exists after currentIndex. + + + + Used to build the splashscreen. + + + + + Initializes a new instance of the class. + + The SkiaEncoder. + The logger. + + + + Generate a splashscreen. + + The poster paths. + The landscape paths. + The output path. + + + + Generates a collage of posters and landscape pictures. + + The poster paths. + The landscape paths. + The created collage as a bitmap. + + + + Transform the collage in 3D space. + + The bitmap to transform. + The transformed image. + + + + Used to build collages of multiple images arranged in vertical strips. + + + + + Initializes a new instance of the class. + + The encoder to use for building collages. + + + + Pattern:
+ \p{IsArabic}|\p{IsArmenian}|\p{IsHebrew}|\p{IsSyriac}|\p{IsThaana}
+ Explanation:
+ + ○ Match a character in the set [\u0530-\u074F\u0780-\u07BF].
+
+
+
+ + + Check which format an image has been encoded with using its filename extension. + + The path to the image to get the format for. + The image format. + + + + Create a square collage. + + The paths of the images to use in the collage. + The path at which to place the resulting collage image. + The desired width of the collage. + The desired height of the collage. + + + + Create a thumb collage. + + The paths of the images to use in the collage. + The path at which to place the resulting image. + The desired width of the collage. + The desired height of the collage. + The name of the library to draw on the collage. + + + + Draw shaped text with given SKPaint. + + If not null, draw text to this canvas, otherwise only measure the text width. + x position of the canvas to draw text. + y position of the canvas to draw text. + The text to draw. + The SKPaint to style the text. + The SKFont to style the text. + The alignment of the text. Default aligns to left. + The width of the text. + + + + Draw shaped text with given SKPaint, search defined type faces to render as many texts as possible. + + If not null, draw text to this canvas, otherwise only measure the text width. + x position of the canvas to draw text. + y position of the canvas to draw text. + The text to draw. + The SKPaint to style the text. + The SKFont to style the text. + If true, render from right to left. + The width of the text. + + + + Static helper class for drawing unplayed count indicators. + + + + + The x-offset used when drawing an unplayed count indicator. + + + + + Draw an unplayed count indicator in the top right corner of a canvas. + + The canvas to draw the indicator on. + + The dimensions of the image to draw the indicator on. The width is used to determine the x-position of the + indicator. + + The number to draw in the indicator. + + + Custom -derived type for the IsRtlTextRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Helper methods used by generated -derived implementations. + + + Default timeout value set in , or if none was set. + + + Whether is non-infinite. + + + Finds the next index of any character that matches a character in the set [\u0530-\u074F\u0780-\u07BF]. + +
+
diff --git a/publish/Jellyfin.Drawing.xml b/publish/Jellyfin.Drawing.xml new file mode 100644 index 00000000..54e60461 --- /dev/null +++ b/publish/Jellyfin.Drawing.xml @@ -0,0 +1,143 @@ + + + + Jellyfin.Drawing + + + + + Class ImageProcessor. + + + + + Initializes a new instance of the class. + + The logger. + The server application paths. + The filesystem. + The image encoder. + The configuration. + + + + + + + + + + + + + + + + Gets the cache file path based on a set of parameters. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Gets the cache path. + + The path. + Name of the unique. + The file extension. + System.String. + + path + or + uniqueName + or + fileExtension. + + + + + Gets the cache path. + + The path. + The filename. + System.String. + + path + or + filename. + + + + + + + + + + + A fallback implementation of . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/publish/Jellyfin.Extensions.xml b/publish/Jellyfin.Extensions.xml new file mode 100644 index 00000000..8f0bfc8d --- /dev/null +++ b/publish/Jellyfin.Extensions.xml @@ -0,0 +1,716 @@ + + + + Jellyfin.Extensions + + + + + Provides CopyTo extensions methods for . + + + + + Copies all the elements of the current collection to the specified list + starting at the specified destination array index. The index is specified as a 32-bit integer. + + The current collection that is the source of the elements. + The list that is the destination of the elements copied from the current collection. + A 32-bit integer that represents the index in destination at which copying begins. + The type of the array. + + + + Static extensions for the interface. + + + + + Gets a string from a string dictionary, checking all keys sequentially, + stopping at the first key that returns a result that's neither null nor blank. + + The dictionary. + The first checked key. + The second checked key. + The third checked key. + The fourth checked key. + System.String. + + + + Static extensions for the interface. + + + + + Determines whether the value is contained in the source collection. + + An instance of the interface. + The value to look for in the collection. + The string comparison. + A value indicating whether the value is contained in the collection. + The source is null. + + + + Gets an IEnumerable from a single item. + + The item to return. + The type of item. + The IEnumerable{T}. + + + + Gets an IEnumerable consisting of all flags of an enum. + + The flags enum. + The type of item. + The IEnumerable{Enum}. + + + + Provides helper functions for . + + + + + Creates, or truncates a file in the specified path. + + The path and name of the file to create. + + + + A custom StreamWriter which supports setting a IFormatProvider. + + + + + Initializes a new instance of the class. + + The stream to write to. + The format provider to use. + + + + Initializes a new instance of the class. + + The complete file path to write to. + The format provider to use. + + + + + + + Guid specific extensions. + + + + + Determine whether the guid is default. + + The guid. + Whether the guid is the default value. + + + + Determine whether the guid is null or default. + + The guid. + Whether the guid is null or the default valueF. + + + + Converts a number to a boolean. + This is needed for HDHomerun. + + + + + + + + + + + Converts a string to a boolean. + This is needed for FFprobe. + + + + + + + + + + + Convert comma delimited string to collection of type. + + Type to convert to. + + + + Initializes a new instance of the class. + + + + + + + + Json comma delimited collection converter factory. + + + This must be applied as an attribute, adding to the JsonConverter list causes stack overflow. + + + + + + + + + + + Legacy DateTime converter. + Milliseconds aren't output if zero by default. + + + + + + + + + + + Json unknown enum converter. + + The type of enum. + + + + Initializes a new instance of the class. + + The base json converter. + + + + + + + + + + Utilizes the JsonStringEnumConverter and sets a default value if not provided. + + + + + + + + + + + Convert delimited string to array of type. + + Type to convert to. + + + + Initializes a new instance of the class. + + + + + Gets the array delimiter. + + + + + + + + + + + Enum flag to json array converter. + + The type of enum. + + + + + + + + + + Json flag enum converter factory. + + + + + + + + + + + Converts a GUID object or value to/from JSON. + + + + + + + + + + + Converts a GUID object or value to/from JSON. + + + + + + + + + + + Converts a nullable struct or value to/from JSON. + Required - some clients send an empty string. + + The struct type. + + + + + + + + + + Json nullable struct converter factory. + + + + + + + + + + + Convert Pipe delimited string to array of type. + + Type to convert to. + + + + Initializes a new instance of the class. + + + + + + + + Json Pipe delimited collection converter factory. + + + This must be applied as an attribute, adding to the JsonConverter list causes stack overflow. + + + + + + + + + + + Converter to allow the serializer to read strings. + + + + + + + + + + + Converts a Version object or value to/from JSON. + + + Required to send as a string instead of an object. + + + + + + + + + + + Helper class for having compatible JSON throughout the codebase. + + + + + Pascal case json profile media type. + + + + + Camel case json profile media type. + + + + + When changing these options, update + Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs + -> AddJellyfinApi + -> AddJsonOptions. + + + + + Gets the default options. + + + The return value must not be modified. + If the defaults must be modified the author must use the copy constructor. + + The default options. + + + + Gets camelCase json options. + + + The return value must not be modified. + If the defaults must be modified the author must use the copy constructor. + + The camelCase options. + + + + Gets PascalCase json options. + + + The return value must not be modified. + If the defaults must be modified the author must use the copy constructor. + + The PascalCase options. + + + + Extensions for Utf8JsonReader and Utf8JsonWriter. + + + + + Determines if the reader contains an empty string. + + The reader. + Whether the reader contains an empty string. + + + + Determines if the reader contains a null value. + + The reader. + Whether the reader contains null. + + + + Static extensions for the interface. + + + + + Finds the index of the desired item. + + The source list. + The value to fine. + The type of item to find. + Index if found, else -1. + + + + Finds the index of the predicate. + + The source list. + The value to find. + The type of item to find. + Index if found, else -1. + + + + Get the first or default item from a list. + + The source list. + The type of item. + The first item or default if list is empty. + + + + Provides Shuffle extensions methods for . + + + + + Shuffles the items in a list. + + The list that should get shuffled. + The type. + + + + Shuffles the items in a list. + + The list that should get shuffled. + The random number generator to use. + The type. + + + + Extension class for splitting lines without unnecessary allocations. + + + + + Creates a new string split enumerator. + + The string to split. + The separator to split on. + The enumerator struct. + + + + Creates a new span split enumerator. + + The span to split. + The separator to split on. + The enumerator struct. + + + + Provides an enumerator for the substrings separated by the separator. + + + + + Initializes a new instance of the struct. + + The span to split. + The separator to split on. + + + + Gets a reference to the item at the current position of the enumerator. + + + + + Returns this. + + this. + + + + Advances the enumerator to the next item. + + true if there is a next element; otherwise false. + + + + Class BaseExtensions. + + + + + Reads all lines in the . + + The to read from. + All lines in the stream. + + + + Reads all lines in the . + + The to read from. + The character encoding to use. + All lines in the stream. + + + + Reads all lines in the . + + The to read from. + All lines in the stream. + + + + Reads all lines in the . + + The to read from. + The token to monitor for cancellation requests. + All lines in the stream. + + + + Extension methods for the class. + + + + + Concatenates and appends the members of a collection in single quotes using the specified delimiter. + + The string builder. + The character delimiter. + The collection of strings to concatenate. + The updated string builder. + + + + Provides extensions methods for . + + + Checks whether or not the specified string has diacritics in it. + + + + + Removes the diacritics character from the strings. + + The string to act on. + The string without diacritics character. + + + + Checks whether or not the specified string has diacritics in it. + + The string to check. + True if the string has diacritics, false otherwise. + + + + Counts the number of occurrences of [needle] in the string. + + The haystack to search in. + The character to search for. + The number of occurrences of the [needle] character. + + + + Returns the part on the left of the needle. + + The string to seek. + The needle to find. + The part left of the . + + + + Returns the part on the right of the needle. + + The string to seek. + The needle to find. + The part right of the . + + + + Returns a transliterated string which only contain ascii characters. + + The string to act on. + The transliterated string. + + + + Ensures all strings are non-null and trimmed of leading an trailing blanks. + + The enumerable of strings to trim. + The enumeration of trimmed strings. + + + + Truncates a string at the first null character ('\0'). + + The input string. + + The substring up to (but not including) the first null character, + or the original string if no null character is present. + + + + + Pattern:
+ ([\uD800-\uDBFF](?![\uDC00-\uDFFF]))|((?<![\uD800-\uDBFF])[\uDC00-\uDFFF])|(�)
+ Explanation:
+ + ○ Match with 3 alternative expressions, atomically.
+ ○ 1st capture group.
+ ○ Match a character in the set [\uD800-\uDBFF].
+ ○ Zero-width negative lookahead.
+ ○ Match a character in the set [\uDC00-\uDFFF].
+ ○ 2nd capture group.
+ ○ Zero-width negative lookbehind.
+ ○ Match a character in the set [\uD800-\uDBFF] right-to-left.
+ ○ Match a character in the set [\uDC00-\uDFFF].
+ ○ 3rd capture group.
+ ○ Match '�'.
+
+
+
+ + Custom -derived type for the NonConformingUnicodeRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Helper methods used by generated -derived implementations. + + + Default timeout value set in , or if none was set. + + + Whether is non-infinite. + + + Finds the next index of any character that matches a character in the set [\uD800-\uDFFF\uFFFD]. + +
+
diff --git a/publish/Jellyfin.LiveTv.xml b/publish/Jellyfin.LiveTv.xml new file mode 100644 index 00000000..e111f4d8 --- /dev/null +++ b/publish/Jellyfin.LiveTv.xml @@ -0,0 +1,1606 @@ + + + + Jellyfin.LiveTv + + + + + A media source provider for channels. + + + + + Initializes a new instance of the class. + + The channel manager. + + + + + + + + + + An image provider for channels. + + + + + Initializes a new instance of the class. + + The channel manager. + + + + + + + + + + + + + + + + + + + The LiveTV channel manager. + + + + + Initializes a new instance of the class. + + The user manager. + The dto service. + The library manager. + The logger. + The server configuration manager. + The filesystem. + The user data manager. + The provider manager. + The memory cache. + The channels. + + + + + + + + + + + + + Get the installed channel IDs. + + An containing installed channel IDs. + + + + + + + + + + Refreshes the associated channels. + + The progress. + A cancellation token that can be used to cancel the operation. + The completed task. + + + + + + + Gets the dynamic media sources based on the provided item. + + The item. + A cancellation token that can be used to cancel the operation. + The task representing the operation to get the media sources. + + + + Gets a channel with the provided Guid. + + The Guid. + The corresponding channel. + + + + + + + + + + + + + Gets the provided channel's supported features. + + The channel. + The provider. + The features. + The supported features. + + + + + + + + + + + + + + + + + + + Releases unmanaged and optionally managed resources. + + true to release both managed and unmanaged resources; false to release only unmanaged resources. + + + + A task to remove all non-installed channels from the database. + + + + + Initializes a new instance of the class. + + The channel manager. + The logger. + The library manager. + + + + Runs this task. + + The progress. + The cancellation token. + The completed task. + + + + The "Refresh Channels" scheduled task. + + + + + Initializes a new instance of the class. + + The channel manager. + The logger. + The library manager. + The localization manager. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + extensions for Live TV. + + + + + Gets the . + + The . + The . + + + + Gets the . + + The . + The . + + + + implementation for . + + + + + + + + + + + + + + Live TV extensions for . + + + + + Adds Live TV services to the . + + The to add services to. + + + + + + + Amount of days images are pre-cached from external sources. + + + + + Initializes a new instance of the class. + + The . + The . + The . + The . + The . + The . + The . + The . + The . + + + + + + + + + + The "Refresh Guide" scheduled task. + + + + + Initializes a new instance of the class. + + The live tv manager. + The guide manager. + The configuration manager. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Processes the exited. + + + + + + + + Releases unmanaged and optionally managed resources. + + true to release both managed and unmanaged resources; false to release only unmanaged resources. + + + + + + + Records the specified media source. + + The direct stream provider, or null. + The media source. + The target file. + The duration to record. + An action to perform when recording starts. + The cancellation token. + A that represents the recording operation. + + + + + + + Initializes a new instance of the class. + + The . + The . + The . + The . + The . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Releases unmanaged and optionally managed resources. + + true to release both managed and unmanaged resources; false to release only unmanaged resources. + + + + Broadcaster dto. + + + + + Gets or sets the city. + + + + + Gets or sets the state. + + + + + Gets or sets the postal code. + + + + + Gets or sets the country. + + + + + Caption dto. + + + + + Gets or sets the content. + + + + + Gets or sets the lang. + + + + + Cast dto. + + + + + Gets or sets the billing order. + + + + + Gets or sets the role. + + + + + Gets or sets the name id. + + + + + Gets or sets the person id. + + + + + Gets or sets the name. + + + + + Gets or sets the character name. + + + + + Channel dto. + + + + + Gets or sets the list of maps. + + + + + Gets or sets the list of stations. + + + + + Gets or sets the metadata. + + + + + Content rating dto. + + + + + Gets or sets the body. + + + + + Gets or sets the code. + + + + + Crew dto. + + + + + Gets or sets the billing order. + + + + + Gets or sets the role. + + + + + Gets or sets the name id. + + + + + Gets or sets the person id. + + + + + Gets or sets the name. + + + + + Day dto. + + + + + Gets or sets the station id. + + + + + Gets or sets the list of programs. + + + + + Gets or sets the metadata schedule. + + + + + Description 1_000 dto. + + + + + Gets or sets the description language. + + + + + Gets or sets the description. + + + + + Description 100 dto. + + + + + Gets or sets the description language. + + + + + Gets or sets the description. + + + + + Descriptions program dto. + + + + + Gets or sets the list of description 100. + + + + + Gets or sets the list of description1000. + + + + + Event details dto. + + + + + Gets or sets the sub type. + + + + + Gracenote dto. + + + + + Gets or sets the season. + + + + + Gets or sets the episode. + + + + + Headends dto. + + + + + Gets or sets the headend. + + + + + Gets or sets the transport. + + + + + Gets or sets the location. + + + + + Gets or sets the list of lineups. + + + + + Image data dto. + + + + + Gets or sets the width. + + + + + Gets or sets the height. + + + + + Gets or sets the uri. + + + + + Gets or sets the size. + + + + + Gets or sets the aspect. + + + + + Gets or sets the category. + + + + + Gets or sets the text. + + + + + Gets or sets the primary. + + + + + Gets or sets the tier. + + + + + Gets or sets the caption. + + + + + The lineup dto. + + + + + Gets or sets the lineup. + + + + + Gets or sets the lineup name. + + + + + Gets or sets the transport. + + + + + Gets or sets the location. + + + + + Gets or sets the uri. + + + + + Gets or sets a value indicating whether this lineup was deleted. + + + + + Lineups dto. + + + + + Gets or sets the response code. + + + + + Gets or sets the server id. + + + + + Gets or sets the datetime. + + + + + Gets or sets the list of lineups. + + + + + Logo dto. + + + + + Gets or sets the url. + + + + + Gets or sets the height. + + + + + Gets or sets the width. + + + + + Gets or sets the md5. + + + + + Map dto. + + + + + Gets or sets the station id. + + + + + Gets or sets the channel. + + + + + Gets or sets the provider callsign. + + + + + Gets or sets the logical channel number. + + + + + Gets or sets the uhfvhf. + + + + + Gets or sets the atsc major. + + + + + Gets or sets the atsc minor. + + + + + Gets or sets the match type. + + + + + Metadata dto. + + + + + Gets or sets the lineup. + + + + + Gets or sets the modified timestamp. + + + + + Gets or sets the transport. + + + + + Metadata programs dto. + + + + + Gets or sets the gracenote object. + + + + + Metadata schedule dto. + + + + + Gets or sets the modified timestamp. + + + + + Gets or sets the md5. + + + + + Gets or sets the start date. + + + + + Gets or sets the end date. + + + + + Gets or sets the days count. + + + + + Movie dto. + + + + + Gets or sets the year. + + + + + Gets or sets the duration. + + + + + Gets or sets the list of quality rating. + + + + + Multipart dto. + + + + + Gets or sets the part number. + + + + + Gets or sets the total parts. + + + + + Program details dto. + + + + + Gets or sets the audience. + + + + + Gets or sets the program id. + + + + + Gets or sets the list of titles. + + + + + Gets or sets the event details object. + + + + + Gets or sets the descriptions. + + + + + Gets or sets the original air date. + + + + + Gets or sets the list of genres. + + + + + Gets or sets the episode title. + + + + + Gets or sets the list of metadata. + + + + + Gets or sets the list of content ratings. + + + + + Gets or sets the list of cast. + + + + + Gets or sets the list of crew. + + + + + Gets or sets the entity type. + + + + + Gets or sets the show type. + + + + + Gets or sets a value indicating whether there is image artwork. + + + + + Gets or sets the primary image. + + + + + Gets or sets the thumb image. + + + + + Gets or sets the backdrop image. + + + + + Gets or sets the banner image. + + + + + Gets or sets the image id. + + + + + Gets or sets the md5. + + + + + Gets or sets the list of content advisory. + + + + + Gets or sets the movie object. + + + + + Gets or sets the list of recommendations. + + + + + Program dto. + + + + + Gets or sets the program id. + + + + + Gets or sets the air date time. + + + + + Gets or sets the duration. + + + + + Gets or sets the md5. + + + + + Gets or sets the list of audio properties. + + + + + Gets or sets the list of video properties. + + + + + Gets or sets the list of ratings. + + + + + Gets or sets a value indicating whether this program is new. + + + + + Gets or sets the multipart object. + + + + + Gets or sets the live tape delay. + + + + + Gets or sets a value indicating whether this is the premiere. + + + + + Gets or sets a value indicating whether this is a repeat. + + + + + Gets or sets the premiere or finale. + + + + + Quality rating dto. + + + + + Gets or sets the ratings body. + + + + + Gets or sets the rating. + + + + + Gets or sets the min rating. + + + + + Gets or sets the max rating. + + + + + Gets or sets the increment. + + + + + Rating dto. + + + + + Gets or sets the body. + + + + + Gets or sets the code. + + + + + Recommendation dto. + + + + + Gets or sets the program id. + + + + + Gets or sets the title. + + + + + Request schedule for channel dto. + + + + + Gets or sets the station id. + + + + + Gets or sets the list of dates. + + + + + Show image dto. + + + + + Gets or sets the program id. + + + + + Gets or sets the list of data. + + + + + Station dto. + + + + + Gets or sets the station id. + + + + + Gets or sets the name. + + + + + Gets or sets the callsign. + + + + + Gets or sets the broadcast language. + + + + + Gets or sets the description language. + + + + + Gets or sets the broadcaster. + + + + + Gets or sets the affiliate. + + + + + Gets or sets the logo. + + + + + Gets or sets a value indicating whether it is commercial free. + + + + + Title dto. + + + + + Gets or sets the title. + + + + + The token dto. + + + + + Gets or sets the response code. + + + + + Gets or sets the response message. + + + + + Gets or sets the server id. + + + + + Gets or sets the token. + + + + + Gets or sets the current datetime. + + + + + Gets or sets the response message. + + + + + Class LiveTvManager. + + + + + Gets the services. + + The services. + + + + Resets the tuner. + + The identifier. + The cancellation token. + Task. + + + + + + + + + + responsible for notifying users when a LiveTV recording is completed. + + + + + Initializes a new instance of the class. + + The . + The . + The . + The . + + + + + + + + + + responsible for Live TV recordings. + + + + + Initializes a new instance of the class. + + The . + The . + + + + + + + + + + + + + Initializes a new instance of the class. + + The . + The . + The . + The . + The . + The . + The . + The . + The . + The . + The . + The . + The . + + + + + + + + + + + + + + + + + + + + + + + + + A service responsible for saving recording metadata. + + + + + Initializes a new instance of the class. + + The . + The . + The . + + + + Saves the metadata for a provided recording. + + The recording timer. + The recording path. + The series path. + A task representing the metadata saving. + + + + + + + Returns an unused UDP port number in the range specified. + Temporarily placed here until future network PR merged. + + Upper and Lower boundary of ports to select. + System.Int32. + + + + Pattern:
+ \/ch([0-9]+)-?([0-9]*)
+ Explanation:
+ + ○ Match the string "/ch".
+ ○ 1st capture group.
+ ○ Match a character in the set [0-9] greedily at least once.
+ ○ Match '-' atomically, optionally.
+ ○ 2nd capture group.
+ ○ Match a character in the set [0-9] atomically any number of times.
+
+
+
+ + + + + + Pattern:
+ ([a-z0-9\-_]+)=\"([^"]+)\"
+ Options:
+ RegexOptions.IgnoreCase
+ Explanation:
+ + ○ 1st capture group.
+ ○ Match a character in the set [\-0-9A-Z_a-z\u0130\u212A] atomically at least once.
+ ○ Match the string "=\"".
+ ○ 2nd capture group.
+ ○ Match a character other than '"' atomically at least once.
+ ○ Match '"'.
+
+
+
+ + + + + + Initializes a new instance of the class. + + The . + The . + The . + The . + + + + + + + + + + + + + + + + + + Custom -derived type for the ChannelAndProgramRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Custom -derived type for the KeyValueRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Helper methods used by generated -derived implementations. + + + Default timeout value set in , or if none was set. + + + Whether is non-infinite. + + + Supports searching for the string "/ch". + + + Supports searching for characters in or not in "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyzİK". + +
+
diff --git a/publish/Jellyfin.MediaEncoding.Hls.xml b/publish/Jellyfin.MediaEncoding.Hls.xml new file mode 100644 index 00000000..2056dde3 --- /dev/null +++ b/publish/Jellyfin.MediaEncoding.Hls.xml @@ -0,0 +1,224 @@ + + + + Jellyfin.MediaEncoding.Hls + + + + + + + + Initializes a new instance of the class. + + An instance of the interface. + An instance of the interface. + An instance of the interface. + + + + + + + + + + Message: Failed to extract keyframes using {ExtractorName} + Level: Debug + + + + + Message: Successfully extracted keyframes using {ExtractorName} + Level: Debug + + + + + Extensions for the interface. + + + + + Adds the hls playlist generators to the . + + An instance of the interface. + The updated service collection. + + + + + + + Initializes a new instance of the class. + + An instance of the interface. + An instance of . + An instance of the interface. + + + + + + + + + + Message: Extracting keyframes from {FilePath} using ffprobe failed + Level: Error + + + + + Keyframe extractor. + + + + + Gets a value indicating whether the extractor is based on container metadata. + + + + + Attempt to extract keyframes. + + The item id. + The path to the file. + The keyframes. + A value indicating whether the keyframe extraction was successful. + + + + + + + Initializes a new instance of the class. + + An instance of the interface. + + + + + + + + + + Message: Extracting keyframes from {FilePath} using matroska metadata failed + Level: Error + + + + + Request class for the method. + + + + + Initializes a new instance of the class. + + The media source id. + The absolute file path to the file. + The desired segment length in milliseconds. + The total duration of the file in ticks. + The desired segment container eg. "ts". + The URI prefix for the relative URL in the playlist. + The desired query string to append (must start with ?). + Whether the video is being remuxed. + + + + Gets the media source id. + + + + + Gets the file path. + + + + + Gets the desired segment length in milliseconds. + + + + + Gets the total runtime in ticks. + + + + + Gets the segment container. + + + + + Gets the endpoint prefix for the URL. + + + + + Gets the query string. + + + + + Gets a value indicating whether the video is being remuxed. + + + + + + + + Initializes a new instance of the class. + + An instance of the see interface. + An instance of . + + + + + + + Generator for dynamic HLS playlists where the segment lengths aren't known in advance. + + + + + Creates the main playlist containing the main video or audio stream. + + An instance of the class. + The playlist as a formatted string. + + + + + + + Initializes a new instance of the class. + + An instance of the interface. + An instance of the interface. + The keyframe extractors. + + + + + + + + + + + + + + + + + + + + + diff --git a/publish/Jellyfin.MediaEncoding.Keyframes.xml b/publish/Jellyfin.MediaEncoding.Keyframes.xml new file mode 100644 index 00000000..e9e9961f --- /dev/null +++ b/publish/Jellyfin.MediaEncoding.Keyframes.xml @@ -0,0 +1,260 @@ + + + + Jellyfin.MediaEncoding.Keyframes + + + + + FfProbe based keyframe extractor. + + + + + Extracts the keyframes using the ffprobe executable at the specified path. + + The path to the ffprobe executable. + The file path. + An instance of . + + + + Parses the keyframe data from the FFProbe stream. + + The stream reader containing FFProbe output. + The parsed keyframe data. + + + + FfTool based keyframe extractor. + + + + + Extracts the keyframes using the fftool executable at the specified path. + + The path to the fftool executable. + The file path. + An instance of . + + + + Keyframe information for a specific file. + + + + + Initializes a new instance of the class. + + The total duration of the video stream in ticks. + The video keyframes in ticks. + + + + Gets the total duration of the stream in ticks. + + + + + Gets the keyframes in ticks. + + + + + Extension methods for the class. + + + + + Traverses the current container to find the element with identifier. + + An instance of . + The element identifier. + A value indicating whether the element was found. + + + + Reads the current position in the file as an unsigned integer converted from binary. + + An instance of . + The unsigned integer. + + + + Reads from the start of the file to retrieve the SeekHead segment. + + An instance of . + Instance of . + + + + Reads from SegmentContainer to retrieve the Info segment. + + An instance of . + The position of the info segment relative to the Segment container. + Instance of . + + + + Enters the Tracks segment and reads all tracks to find the specified type. + + Instance of . + The relative position of the tracks segment. + The track type identifier. + The first track number with the specified type. + Stream type is not found. + + + + Constants for the Matroska identifiers. + + + + + The Matroska segment container identifier. + + + + + The Matroska seek head identifier. + + + + + The Matroska seek identifier. + + + + + The Matroska info identifier. + + + + + The Matroska timestamp scale identifier. + + + + + The Matroska duration identifier. + + + + + The Matroska tracks identifier. + + + + + The Matroska track entry identifier. + + + + + The Matroska track number identifier. + + + + + The Matroska track type identifier. + + + + + The Matroska video track type value. + + + + + The Matroska subtitle track type value. + + + + + The Matroska cues identifier. + + + + + The Matroska cue time identifier. + + + + + The Matroska cue point identifier. + + + + + The Matroska cue track positions identifier. + + + + + The Matroska cue point track number identifier. + + + + + The keyframe extractor for the matroska container. + + + + + Extracts the keyframes in ticks (scaled using the container timestamp scale) from the matroska container. + + The file path. + An instance of . + + + + The matroska Info segment. + + + + + Initializes a new instance of the class. + + The timestamp scale in nanoseconds. + The duration of the entire file. + + + + Gets the timestamp scale in nanoseconds. + + + + + Gets the total duration of the file. + + + + + The matroska SeekHead segment. All positions are relative to the Segment container. + + + + + Initializes a new instance of the class. + + The relative file position of the info segment. + The relative file position of the tracks segment. + The relative file position of the cues segment. + + + + Gets relative file position of the info segment. + + + + + Gets the relative file position of the tracks segment. + + + + + Gets the relative file position of the cues segment. + + + + diff --git a/publish/Jellyfin.Networking.xml b/publish/Jellyfin.Networking.xml new file mode 100644 index 00000000..ab1979fb --- /dev/null +++ b/publish/Jellyfin.Networking.xml @@ -0,0 +1,305 @@ + + + + Jellyfin.Networking + + + + + responsible for responding to auto-discovery messages. + + + + + The port to listen on for auto-discovery messages. + + + + + Initializes a new instance of the class. + + The . + The . + The . + The . + + + + + + + Defines the class. + + Implementation taken from https://github.com/ppy/osu-framework/pull/4191 . + + + + + Gets or sets a value indicating whether the client should use IPv6. + + + + + Implements the httpclient callback method. + + The instance. + The instance. + The http steam. + + + + Class to take care of network interface management. + + + + + Threading lock for network properties. + + + + + Holds the published server URLs and the IPs to use them on. + + + + + Used to stop "event-racing conditions". + + + + + Dictionary containing interface addresses and their subnets. + + + + + Unfiltered user defined LAN subnets () + or internal interface network subnets if undefined by user. + + + + + User defined list of subnets to excluded from the LAN. + + + + + True if this object is disposed. + + + + + Initializes a new instance of the class. + + The instance. + The instance holding startup parameters. + Logger to use for messages. + + + + Event triggered on network changes. + + + + + Gets or sets a value indicating whether testing is taking place. + + + + + Gets a value indicating whether IPv4 is enabled. + + + + + Gets a value indicating whether IP6 is enabled. + + + + + Gets a value indicating whether is all IPv6 interfaces are trusted as internal. + + + + + Gets the Published server override list. + + + + + + + + Handler for network change events. + + Sender. + A containing network availability information. + + + + Handler for network change events. + + Sender. + An . + + + + Triggers our event, and re-loads interface information. + + + + + Waits for 2 seconds before re-initialising the settings, as typically these events fire multiple times in succession. + + + + + Generate a list of all the interface ip addresses and submasks where that are in the active/unknown state. + + + + + Generate a list of all the interface ip addresses and submasks where that are in the active/unknown state. + + The logger. + If true evaluates IPV4 type ip addresses. + If true evaluates IPV6 type ip addresses. + A list of all locally known up addresses and submasks that are to be considered usable. + + + + Initializes internal LAN cache. + + + + + Enforce bind addresses and exclusions on available interfaces. + + + + + Filters a list of bind addresses and exclusions on available interfaces. + + The network config to be filtered by. + A list of possible interfaces to be filtered. + If true evaluates IPV4 type ip addresses. + If true evaluates IPV6 type ip addresses. + A list of all locally known up addresses and submasks that are to be considered usable. + + + + Initializes the remote address values. + + + + + Parses the user defined overrides into the dictionary object. + Overrides are the equivalent of localised publishedServerUrl, enabling + different addresses to be advertised over different subnets. + format is subnet=ipaddress|host|uri + when subnet = 0.0.0.0, any external address matches. + + + + + Reloads all settings and re-Initializes the instance. + + The to use. + + + + Protected implementation of Dispose pattern. + + True to dispose the managed state. + + + + + + + + + + + + + + + + Reads the jellyfin configuration of the configuration manager and produces a list of interfaces that should be bound. + + Defines that only known interfaces should be used. + The ConfigurationManager. + The known interfaces that gets returned if possible or instructed. + Include IPV4 type interfaces. + Include IPV6 type interfaces. + A list of ip address of which jellyfin should bind to. + + + + + + + + + + + + + + + + + + + Get if the IPAddress is Link-local. + + The IP Address. + Bool indicates if the address is link-local. + + + + + + + Check if the address is in the LAN and not excluded. + + The IP address to check. The caller should make sure this is not an IPv4MappedToIPv6 address. + Boolean indicates whether the address is in LAN. + + + + Attempts to match the source against the published server URL overrides. + + IP source address to use. + True if the source is in an external subnet. + The published server URL that matches the source address. + true if a match is found, false otherwise. + + + + Attempts to match the source against the user defined bind interfaces. + + IP source address to use. + True if the source is in the external subnet. + The result, if a match is found. + true if a match is found, false otherwise. + + + + Attempts to match the source against external interfaces. + + IP source address to use. + The result, if a match is found. + true if a match is found, false otherwise. + + + + Factory class to create different kinds of sockets. + + + + + + + diff --git a/publish/Jellyfin.Server.Implementations.xml b/publish/Jellyfin.Server.Implementations.xml new file mode 100644 index 00000000..0f11578e --- /dev/null +++ b/publish/Jellyfin.Server.Implementations.xml @@ -0,0 +1,1434 @@ + + + + Jellyfin.Server.Implementations + + + + + Manages the storage and retrieval of instances. + + + + + Initializes a new instance of the class. + + The Jellyfin database provider. + + + + + + + + + + + + + + + + Ensures supplementary performance indexes exist on database startup. + + + + + Initializes a new instance of the class. + + The logger. + The database context. + + + + Checks if supplementary indexes exist and logs warnings if they don't. + + Cancellation token. + True if all indexes exist, false otherwise. + + + + Factory for constructing a database configuration. + + + + + + + + A configuration that stores database related settings. + + + + + The name of the configuration in the storage. + + + + + Initializes a new instance of the class. + + + + + Manages the creation, updating, and retrieval of devices. + + + + + Initializes a new instance of the class. + + The database provider. + The user manager. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Creates an entry in the activity log whenever a lyric download fails. + + + + + Initializes a new instance of the class. + + The localization manager. + The activity manager. + + + + + + + Creates an entry in the activity log whenever a subtitle download fails. + + + + + Initializes a new instance of the class. + + The localization manager. + The activity manager. + + + + + + + Creates an entry in the activity log when there is a failed login attempt. + + + + + Initializes a new instance of the class. + + The localization manager. + The activity manager. + + + + + + + Creates an entry in the activity log when there is a successful login attempt. + + + + + Initializes a new instance of the class. + + The localization manager. + The activity manager. + + + + + + + Creates an entry in the activity log whenever a user starts playback. + + + + + Initializes a new instance of the class. + + The logger. + The localization manager. + The activity manager. + + + + + + + Creates an activity log entry whenever a user stops playback. + + + + + Initializes a new instance of the class. + + The logger. + The localization manager. + The activity manager. + + + + + + + Creates an entry in the activity log whenever a session ends. + + + + + Initializes a new instance of the class. + + The localization manager. + The activity manager. + + + + + + + Creates an entry in the activity log when a session is started. + + + + + Initializes a new instance of the class. + + The localization manager. + The activity manager. + + + + + + + Notifies users when there is a pending restart. + + + + + Initializes a new instance of the class. + + The session manager. + + + + + + + Creates an activity log entry whenever a task is completed. + + + + + Initializes a new instance of the class. + + The localization manager. + The activity manager. + + + + + + + Constructs a string description of a time-span value. + + The value of this item. + The name of this item (singular form). + + + + Notifies admin users when a task is completed. + + + + + Initializes a new instance of the class. + + The session manager. + + + + + + + Notifies admin users when a plugin installation is cancelled. + + + + + Initializes a new instance of the class. + + The session manager. + + + + + + + Creates an entry in the activity log when a package installation fails. + + + + + Initializes a new instance of the class. + + The localization manager. + The activity manager. + + + + + + + Notifies admin users when a plugin installation fails. + + + + + Initializes a new instance of the class. + + The session manager. + + + + + + + Creates an entry in the activity log when a plugin is installed. + + + + + Initializes a new instance of the class. + + The localization manager. + The activity manager. + + + + + + + Notifies admin users when a plugin is installed. + + + + + Initializes a new instance of the class. + + The session manager. + + + + + + + Notifies admin users when a plugin is being installed. + + + + + Initializes a new instance of the class. + + The session manager. + + + + + + + Creates an entry in the activity log when a plugin is uninstalled. + + + + + Initializes a new instance of the class. + + The localization manager. + The activity manager. + + + + + + + Notifies admin users when a plugin is uninstalled. + + + + + Initializes a new instance of the class. + + The session manager. + + + + + + + Creates an entry in the activity log when a plugin is updated. + + + + + Initializes a new instance of the class. + + The localization manager. + The activity manager. + + + + + + + Creates an entry in the activity log when a user is created. + + + + + Initializes a new instance of the class. + + The localization manager. + The activity manager. + + + + + + + Adds an entry to the activity log when a user is deleted. + + + + + Initializes a new instance of the class. + + The localization manager. + The activity manager. + + + + + + + Notifies the user's sessions when a user is deleted. + + + + + Initializes a new instance of the class. + + The session manager. + + + + + + + Creates an entry in the activity log when a user is locked out. + + + + + Initializes a new instance of the class. + + The localization manager. + The activity manager. + + + + + + + Creates an entry in the activity log when a user's password is changed. + + + + + Initializes a new instance of the class. + + The localization manager. + The activity manager. + + + + + + + Notifies a user when their account has been updated. + + + + + Initializes a new instance of the class. + + The user manager. + The session manager. + + + + + + + A class containing extensions to for eventing. + + + + + Adds the event services to the service collection. + + The service collection. + + + + Handles the firing of events. + + + + + Initializes a new instance of the class. + + The logger. + The application host. + + + + + + + + + + Provides extension methods. + + + + + Combines two predicates into a single predicate using a logical OR operation. + + The predicate parameter type. + The first predicate expression to combine. + The second predicate expression to combine. + A new expression representing the OR combination of the input predicates. + + + + Combines multiple predicates into a single predicate using a logical OR operation. + + The predicate parameter type. + A collection of predicate expressions to combine. + A new expression representing the OR combination of all input predicates. + + + + Combines two predicates into a single predicate using a logical AND operation. + + The predicate parameter type. + The first predicate expression to combine. + The second predicate expression to combine. + A new expression representing the AND combination of the input predicates. + + + + Combines multiple predicates into a single predicate using a logical AND operation. + + The predicate parameter type. + A collection of predicate expressions to combine. + A new expression representing the AND combination of all input predicates. + + + + Extensions for the interface. + + + + + Adds the interface to the service collection with second level caching enabled. + + An instance of the interface. + The server configuration manager. + The startup Configuration. + The updated service collection. + + + + Manifest type for backups internal structure. + + + + + Defines the optional contents of the backup archive. + + + + + Contains methods for creating and restoring backups. + + + + + Initializes a new instance of the class. + + A logger. + A Database Factory. + The Application host. + The application paths. + The Jellyfin database Provider in use. + The SystemManager. + + + + + + + + + + + + + + + + + + + Windows is able to handle '/' as a path seperator in zip files + but linux isn't able to handle '\' as a path seperator in zip files, + So normalize to '/'. + + The path to normalize. + The normalized path. + + + + Handles all storage logic for BaseItems. + + + + + Gets the placeholder id for UserData detached items. + + + + + This holds all the types in the running assemblies + so that we can de-serialize properly when we don't have strong types. + + + + + Initializes a new instance of the class. + + The db factory. + The Application host. + The static type lookup. + The server Configuration manager. + System logger. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Gets the type. + + Name of the type. + Type. + typeName is null. + + + + + + + + + + + + + + + + + + + + + + + + + + + + Maps a Entity to the DTO. + + The entity. + The dto base instance. + The Application server Host. + The applogger. + The dto to map. + + + + Maps a Entity to the DTO. + + The entity. + The dto to map. + + + + Deserializes a BaseItemEntity and sets all properties. + + The DB entity. + Logger. + The application server Host. + If only mapping should be processed. + A mapped BaseItem, or null if the item type is unknown. + + + + Gets the clean value for search and sorting purposes. + + The value to clean. + The cleaned value. + + + + + + + + + + + + + The Chapter manager. + + + + + Initializes a new instance of the class. + + The EFCore provider. + The Image Processor. + + + + + + + + + + + + + + + + Repository for obtaining Keyframe data. + + + + + Initializes a new instance of the class. + + The EFCore db factory. + + + + + + + + + + + + + Manager for handling Media Attachments. + + Efcore Factory. + + + + Manager for handling Media Attachments. + + Efcore Factory. + + + + + + + + + + Repository for obtaining MediaStreams. + + + + + Initializes a new instance of the class. + + The EFCore db factory. + The Application host. + The Localisation Provider. + + + + + + + + + + Static class for methods which maps types of ordering to their respecting ordering functions. + + + + + Creates Func to be executed later with a given BaseItemEntity input for sorting items on query. + + Item property to sort by. + Context Query. + Context. + Func to be executed later for sorting query. + + + + Creates an expression to order search results by match quality. + Prioritizes: exact match (0) > prefix match with word boundary (1) > prefix match (2) > contains (3). + + The search term to match against. + An expression that returns an integer representing match quality (lower is better). + + + + Manager for handling people. + + Efcore Factory. + Items lookup service. + + Initializes a new instance of the class. + + + + + Manager for handling people. + + Efcore Factory. + Items lookup service. + + Initializes a new instance of the class. + + + + + + + + + + + + + + + + + + + + + + + Manages media segments retrieval and storage. + + + + + Initializes a new instance of the class. + + Logger. + EFCore Database factory. + List of all media segment providers. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Initializes a new instance of the class. + + The database provider. + + + + + + + + + + + + + Gets the authorization. + + The HTTP context. + Dictionary{System.StringSystem.String}. + + + + Gets the auth. + + The HTTP request. + Dictionary{System.StringSystem.String}. + + + + Gets the authorization. + + The authorization header. + Dictionary{System.StringSystem.String}. + + + + Get the authorization header components. + + The authorization header. + Dictionary{System.StringSystem.String}. + + + + Contains methods to help with checking for storage and returning storage data for jellyfin folders. + + + + + Tests the available storage capacity on the jellyfin paths with estimated minimum values. + + The application paths. + Logger. + + + + Gets the free space of a specific directory. + + Path to a folder. + The number of bytes available space. + + + + Gets the underlying drive data from a given path and checks if the available storage capacity matches the threshold. + + The path to a folder to evaluate. + The logger. + The threshold to check for or -1 to just log the data. + Thrown when the threshold is not available on the underlying storage. + + + + Formats a size in bytes into a common human readable form. + + + Taken and slightly modified from https://stackoverflow.com/a/4975942/1786007 . + + The size in bytes. + A human readable approximate representation of the argument. + + + + ITrickplayManager implementation. + + + + + Initializes a new instance of the class. + + The logger. + The media encoder. + The file system. + The encoding helper. + The server configuration manager. + The image encoder. + The database provider. + The application paths. + The path manager. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The default authentication provider. + + + + + Initializes a new instance of the class. + + The logger. + The cryptography provider. + + + + + + + + + + + + + + + + + + + The default password reset provider. + + + + + Initializes a new instance of the class. + + The configuration manager. + The application host. + + + + + + + + + + + + + + + + responsible for managing user device permissions. + + + + + Initializes a new instance of the class. + + The . + The . + The . + + + + + + + + + + Manages the storage and retrieval of display preferences through Entity Framework. + + + + + Initializes a new instance of the class. + + The database context factory. + + + + + + + + + + + + + + + + + + + + + + + + + An invalid authentication provider. + + + + + + + + + + + + + + + + + Manages the creation and retrieval of instances. + + + + + Initializes a new instance of the class. + + The database provider. + The event manager. + The network manager. + The application host. + The image processor. + The logger. + The system config manager. + The password reset providers. + The authentication providers. + + + + + + + + + + + + + Pattern:
+ ^(?!\s)[\w\ \-'._@+]+(?<!\s)$
+ Explanation:
+ + ○ Match if at the beginning of the string.
+ ○ Zero-width negative lookahead.
+ ○ Match a whitespace character.
+ ○ Match a character in the set [ '+\-.@_\w] greedily at least once.
+ ○ Zero-width negative lookbehind.
+ ○ Match a whitespace character right-to-left.
+ ○ Match if at the end of the string or if before an ending newline.
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Custom -derived type for the ValidUsernameRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Helper methods used by generated -derived implementations. + + + Default timeout value set in , or if none was set. + + + Whether is non-infinite. + +
+
diff --git a/publish/MediaBrowser.Common.xml b/publish/MediaBrowser.Common.xml new file mode 100644 index 00000000..d67c1eac --- /dev/null +++ b/publish/MediaBrowser.Common.xml @@ -0,0 +1,1907 @@ + + + + MediaBrowser.Common + + + + + Policies for the API authorization. + + + + + Policy name for requiring first time setup or elevated privileges. + + + + + Policy name for requiring elevated privileges. + + + + + Policy name for allowing local access only. + + + + + Policy name for escaping schedule controls. + + + + + Policy name for requiring download permission. + + + + + Policy name for requiring first time setup or default permissions. + + + + + Policy name for requiring local access or elevated privileges. + + + + + Policy name for requiring (anonymous) LAN access. + + + + + Policy name for escaping schedule controls or requiring first time setup. + + + + + Policy name for accessing SyncPlay. + + + + + Policy name for creating a SyncPlay group. + + + + + Policy name for joining a SyncPlay group. + + + + + Policy name for accessing a SyncPlay group. + + + + + Policy name for accessing collection management. + + + + + Policy name for accessing LiveTV. + + + + + Policy name for managing LiveTV. + + + + + Policy name for accessing subtitles management. + + + + + Policy name for accessing lyric management. + + + + + Describes a single entry in the application configuration. + + + + + Gets or sets the unique identifier for the configuration. + + + + + Gets or sets the type used to store the data for this configuration entry. + + + + + for the ConfigurationUpdated event. + + + + + Initializes a new instance of the class. + + The configuration key. + The new configuration. + + + + Gets the key. + + The key. + + + + Gets the new configuration. + + The new configuration. + + + + Class containing extension methods for working with the encoding configuration. + + + + + Gets the encoding options. + + The configuration manager. + The encoding options. + + + + Retrieves the transcoding temp path from the encoding configuration, falling back to a default if no path + is specified in configuration. If the directory does not exist, it will be created. + + The configuration manager. + The transcoding temp path. + If the directory does not exist, and the caller does not have the required permission to create it. + If there is a custom path transcoding path specified, but it is invalid. + If the directory does not exist, and it also could not be created. + + + + Interface IApplicationPaths. + + + + + Gets the path to the program data folder. + + The program data path. + + + + Gets the path to the web UI resources folder. + + + This value is not relevant if the server is configured to not host any static web content. + + + + + Gets the path to the program system folder. + + The program data path. + + + + Gets the folder path to the data directory. + + The data directory. + + + + Gets the image cache path. + + The image cache path. + + + + Gets the path to the plugin directory. + + The plugins path. + + + + Gets the path to the plugin configurations directory. + + The plugin configurations path. + + + + Gets the path to the log directory. + + The log directory path. + + + + Gets the path to the application configuration root directory. + + The configuration directory path. + + + + Gets the path to the system configuration file. + + The system configuration file path. + + + + Gets the folder path to the cache directory. + + The cache directory. + + + + Gets the folder path to the temp directory within the cache folder. + + The temp directory. + + + + Gets the magic string used for virtual path manipulation. + + The magic string used for virtual path manipulation. + + + + Gets the path used for storing trickplay files. + + The trickplay path. + + + + Gets the path used for storing backup archives. + + The backup path. + + + + Checks and creates all known base paths. + + + + + Checks and creates the given path and adds it with a marker file if non existent. + + The path to check. + The common marker file name. + Check for other settings paths recursively. + + + + Provides an interface to retrieve a configuration store. Classes with this interface are scanned for at + application start to dynamically register configuration for various modules/plugins. + + + + + Get the configuration store for this module. + + The configuration store. + + + + Occurs when [configuration updating]. + + + + + Occurs when [configuration updated]. + + + + + Occurs when [named configuration updated]. + + + + + Gets the application paths. + + The application paths. + + + + Gets the configuration. + + The configuration. + + + + Saves the configuration. + + + + + Replaces the configuration. + + The new configuration. + + + + Manually pre-loads a factory so that it is available pre system initialisation. + + Class to register. + + + + Gets the configuration. + + The key. + System.Object. + + + + Gets the array of configuration stores. + + Array of ConfigurationStore. + + + + Gets the type of the configuration. + + The key. + Type. + + + + Saves the configuration. + + The key. + The configuration. + + + + Adds the parts. + + The factories. + + + + A configuration store that can be validated. + + + + + Validation method to be invoked before saving the configuration. + + The old configuration. + The new configuration. + + + + Class EventHelper. + + + + + Fires the event. + + The handler. + The sender. + The instance containing the event data. + The logger. + + + + Queues the event. + + Argument type for the handler. + The handler. + The sender. + The args. + The logger. + + + + Class BaseExtensions. + + + + + Pattern:
+ <(.|\n)*?>
+ Explanation:
+ + ○ Match '<'.
+ ○ Loop lazily any number of times.
+ ○ 1st capture group.
+ ○ Match with 2 alternative expressions.
+ ○ Match any character other than '\n'.
+ ○ Match '\n'.
+ ○ Match '>'.
+
+
+
+ + + Strips the HTML. + + The HTML string. + . + + + + Gets the Md5. + + The string. + . + + + + Static class containing extension methods for . + + + + + Checks the origin of the HTTP context. + + The incoming HTTP context. + true if the request is coming from the same machine as is running the server, false otherwise. + + + + Extracts the remote IP address of the caller of the HTTP context. + + The HTTP context. + The remote caller IP address. + + + + Class MethodNotAllowedException. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + The message. + + + + Extension methods for . + + + + + Asynchronously wait for the process to exit. + + The process to wait for. + The duration to wait before cancelling waiting for the task. + A task that will complete when the process has exited, cancellation has been requested, or an error occurs. + The timeout ended. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + The message. + + + + Class ResourceNotFoundException. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + The message. + + + + Represents errors that occur during interaction with FFmpeg. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class with a specified error message. + + The message that describes the error. + + + + Initializes a new instance of the class with a specified error message and a + reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + + The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if + no inner exception is specified. + + + + + Delegate used with GetExports{T}. + + Type to create. + New instance of type type. + + + + An interface to be implemented by the applications hosting a kernel. + + + + + Occurs when [has pending restart changed]. + + + + + Gets the name. + + The name. + + + + Gets the device identifier. + + The device identifier. + + + + Gets a value indicating whether this instance has pending changes requiring a restart. + + true if this instance has a pending restart; otherwise, false. + + + + Gets or sets a value indicating whether the application should restart. + + + + + Gets the application version. + + The application version. + + + + Gets or sets the service provider. + + + + + Gets the application version. + + The application version. + + + + Gets the application user agent. + + The application user agent. + + + + Gets the email address for use within a comment section of a user agent field. + Presently used to provide contact information to MusicBrainz service. + + + + + Gets all plugin assemblies which implement a custom rest api. + + An containing the plugin assemblies. + + + + Notifies the pending restart. + + + + + Gets the exports. + + The type. + If set to true [manage lifetime]. + . + + + + Gets the exports. + + The type. + Delegate function that gets called to create the object. + If set to true [manage lifetime]. + . + + + + Gets the export types. + + The type. + IEnumerable{Type}. + + + + Resolves this instance. + + The Type. + ``0. + + + + Initializes this instance. + + Instance of the interface. + + + + Interface for the NetworkManager class. + + + + + Event triggered on network changes. + + + + + Gets a value indicating whether IPv4 is enabled. + + + + + Gets a value indicating whether IPv6 is enabled. + + + + + Calculates the list of interfaces to use for Kestrel. + + A IReadOnlyList{IPData} object containing all the interfaces to bind. + If all the interfaces are specified, and none are excluded, it returns zero items + to represent any address. + When false, return or for all interfaces. + + + + Returns a list containing the loopback interfaces. + + IReadOnlyList{IPData}. + + + + Retrieves the bind address to use in system URLs. (Server Discovery, PlayTo, LiveTV, SystemInfo) + If no bind addresses are specified, an internal interface address is selected. + The priority of selection is as follows:- + + The value contained in the startup parameter --published-server-url. + + If the user specified custom subnet overrides, the correct subnet for the source address. + + If the user specified bind interfaces to use:- + The bind interface that contains the source subnet. + The first bind interface specified that suits best first the source's endpoint. eg. external or internal. + + If the source is from a public subnet address range and the user hasn't specified any bind addresses:- + The first public interface that isn't a loopback and contains the source subnet. + The first public interface that isn't a loopback. + The first internal interface that isn't a loopback. + + If the source is from a private subnet address range and the user hasn't specified any bind addresses:- + The first private interface that contains the source subnet. + The first private interface that isn't a loopback. + + If no interfaces meet any of these criteria, then a loopback address is returned. + + Interfaces that have been specifically excluded from binding are not used in any of the calculations. + + Source of the request. + Optional port returned, if it's part of an override. + IP address to use, or loopback address if all else fails. + + + + Retrieves the bind address to use in system URLs. (Server Discovery, PlayTo, LiveTV, SystemInfo) + If no bind addresses are specified, an internal interface address is selected. + + IP address of the request. + Optional port returned, if it's part of an override. + Optional boolean denoting if published server overrides should be ignored. Defaults to false. + IP address to use, or loopback address if all else fails. + + + + Retrieves the bind address to use in system URLs. (Server Discovery, PlayTo, LiveTV, SystemInfo) + If no bind addresses are specified, an internal interface address is selected. + (See . + + Source of the request. + Optional port returned, if it's part of an override. + IP address to use, or loopback address if all else fails. + + + + Returns true if the address is part of the user defined LAN. + + IP to check. + True if endpoint is within the LAN range. + + + + Returns true if the address is part of the user defined LAN. + + IP to check. + True if endpoint is within the LAN range. + + + + Attempts to convert the interface name to an IP address. + eg. "eth1", or "enp3s5". + + Interface name. + Resulting object's IP addresses, if successful. + Success of the operation. + + + + Returns all internal (LAN) bind interface addresses. + + An list of internal (LAN) interfaces addresses. + + + + Checks if has access to the server. + + IP address of the client. + The result of evaluating the access policy, Allow if it should be allowed. + + + + Registered http client names. + + + + + Gets the value for the default named http client which implements happy eyeballs. + + + + + Gets the value for the MusicBrainz named http client. + + + + + Gets the value for the DLNA named http client. + + + + + Non happy eyeballs implementation. + + + + + Defines the . + + + + + The default value for . + + + + + The default value for and . + + + + + Gets or sets a value used to specify the URL prefix that your Jellyfin instance can be accessed at. + + + + + Gets or sets a value indicating whether to use HTTPS. + + + In order for HTTPS to be used, in addition to setting this to true, valid values must also be + provided for and . + + + + + Gets or sets a value indicating whether the server should force connections over HTTPS. + + + + + Gets or sets the filesystem path of an X.509 certificate to use for SSL. + + + + + Gets or sets the password required to access the X.509 certificate data in the file specified by . + + + + + Gets or sets the internal HTTP server port. + + The HTTP server port. + + + + Gets or sets the internal HTTPS server port. + + The HTTPS server port. + + + + Gets or sets the public HTTP port. + + The public HTTP port. + + + + Gets or sets the public HTTPS port. + + The public HTTPS port. + + + + Gets or sets a value indicating whether Autodiscovery is enabled. + + + + + Gets or sets a value indicating whether to enable automatic port forwarding. + + + + + Gets or sets a value indicating whether IPv6 is enabled. + + + + + Gets or sets a value indicating whether IPv6 is enabled. + + + + + Gets or sets a value indicating whether access from outside of the LAN is permitted. + + + + + Gets or sets the subnets that are deemed to make up the LAN. + + + + + Gets or sets the interface addresses which Jellyfin will bind to. If empty, all interfaces will be used. + + + + + Gets or sets the known proxies. + + + + + Gets or sets a value indicating whether address names that match should be ignored for the purposes of binding. + + + + + Gets or sets a value indicating the interface name prefixes that should be ignored. The list can be comma separated and values are case-insensitive. . + + + + + Gets or sets a value indicating whether the published server uri is based on information in HTTP requests. + + + + + Gets or sets the PublishedServerUriBySubnet + Gets or sets PublishedServerUri to advertise for specific subnets. + + + + + Gets or sets the filter for remote IP connectivity. Used in conjunction with . + + + + + Gets or sets a value indicating whether contains a blacklist or a whitelist. Default is a whitelist. + + + + + Defines the . + + + + + Retrieves the network configuration. + + The . + The . + + + + Defines the . + + + + + The GetConfigurations. + + The . + + + + A configuration that stores network related settings. + + + + + The name of the configuration in the storage. + + + + + Initializes a new instance of the class. + + + + + Networking constants. + + + + + IPv4 mask bytes. + + + + + IPv6 mask bytes. + + + + + Minimum IPv4 prefix size. + + + + + Minimum IPv6 prefix size. + + + + + Whole IPv4 address space. + + + + + Whole IPv6 address space. + + + + + IPv4 Loopback as defined in RFC 5735. + + + + + IPv4 private class A as defined in RFC 1918. + + + + + IPv4 private class B as defined in RFC 1918. + + + + + IPv4 private class C as defined in RFC 1918. + + + + + IPv4 Link-Local as defined in RFC 3927. + + + + + IPv6 loopback as defined in RFC 4291. + + + + + IPv6 site local as defined in RFC 4291. + + + + + IPv6 unique local as defined in RFC 4193. + + + + + Defines the . + + + + + Pattern:
+ (?im)^(?!:\/\/)(?=.{1,255}$)((.{1,63}\.){0,127}(?![0-9]*$)[a-z0-9-]+\.?)(:(\d){1,5}){0,1}$
+ Options:
+ RegexOptions.IgnoreCase
+ Explanation:
+ + ○ Match if at the beginning of a line.
+ ○ Zero-width negative lookahead.
+ ○ Match the string "://".
+ ○ Zero-width positive lookahead.
+ ○ Match a character other than '\n' greedily at least 1 and at most 255 times.
+ ○ Match if at the end of a line.
+ ○ 1st capture group.
+ ○ Loop greedily at most 127 times.
+ ○ 2nd capture group.
+ ○ Match a character other than '\n' greedily at least 1 and at most 63 times.
+ ○ Match '.'.
+ ○ Zero-width negative lookahead.
+ ○ Match a character in the set [0-9] atomically any number of times.
+ ○ Match if at the end of a line.
+ ○ Match a character in the set [\-0-9A-Za-z\u0130\u212A] greedily at least once.
+ ○ Match '.' greedily, optionally.
+ ○ Optional (greedy).
+ ○ 3rd capture group.
+ ○ Match ':'.
+ ○ Loop greedily at least 1 and at most 5 times.
+ ○ 4th capture group.
+ ○ Match a Unicode digit.
+ ○ Match if at the end of a line.
+
+
+
+ + + Returns true if the IPAddress contains an IP6 Local link address. + + IPAddress object to check. + True if it is a local link address. + + See https://stackoverflow.com/questions/6459928/explain-the-instance-properties-of-system-net-ipaddress + it appears that the IPAddress.IsIPv6LinkLocal is out of date. + + + + + Convert a subnet mask in CIDR notation to a dotted decimal string value. IPv4 only. + + Subnet mask in CIDR notation. + IPv4 or IPv6 family. + String value of the subnet mask in dotted decimal notation. + + + + Convert a subnet mask in CIDR notation to a dotted decimal string value. IPv4 only. + + Subnet mask in CIDR notation. + IPv4 or IPv6 family. + String value of the subnet mask in dotted decimal notation. + + + + Convert a subnet mask to a CIDR. IPv4 only. + https://stackoverflow.com/questions/36954345/get-cidr-from-netmask. + + Subnet mask. + Byte CIDR representing the mask. + + + + Converts an IPAddress into a string. + IPv6 addresses are returned in [ ], with their scope removed. + + Address to convert. + URI safe conversion of the address. + + + + Try parsing an array of strings into objects, respecting exclusions. + Elements without a subnet mask will be represented as with a single IP. + + Input string array to be parsed. + Collection of . + Boolean signaling if negated or not negated values should be parsed. + True if parsing was successful. + + + + Try parsing a string into an , respecting exclusions. + Inputs without a subnet mask will be represented as with a single IP. + + Input string to be parsed. + An . + Boolean signaling if negated or not negated values should be parsed. + True if parsing was successful. + + + + Attempts to parse a host span. + + Host name to parse. + Object representing the span, if it has successfully been parsed. + true if IPv4 is enabled. + true if IPv6 is enabled. + true if the parsing is successful, false if not. + + + + Gets the broadcast address for a . + + The . + The broadcast address. + + + + Check if a subnet contains an address. This method also handles IPv4 mapped to IPv6 addresses. + + The . + The . + Whether the supplied IP is in the supplied network. + + + + Result of . + + + + + The connection should be allowed. + + + + + The connection should be rejected since it is not from a local IP and remote access is disabled. + + + + + The connection should be rejected since it is from a blocklisted IP. + + + + + The connection should be rejected since it is from a remote IP that is not in the allowlist. + + + + + Provides a common base class for all plugins. + + + + + Gets the name of the plugin. + + The name. + + + + Gets the description. + + The description. + + + + Gets the unique id. + + The unique id. + + + + Gets the plugin version. + + The version. + + + + Gets the path to the assembly file. + + The assembly file path. + + + + Gets the full path to the data folder, where the plugin can store any miscellaneous files needed. + + The data folder path. + + + + Gets a value indicating whether the plugin can be uninstalled. + + + + + Gets the plugin info. + + PluginInfo. + + + + Called just before the plugin is uninstalled from the server. + + + + + + + + + + + Provides a common base class for all plugins. + + The type of the T configuration type. + + + + The configuration sync lock. + + + + + The configuration save lock. + + + + + The configuration. + + + + + Initializes a new instance of the class. + + The application paths. + The XML serializer. + + + + Gets the application paths. + + The application paths. + + + + Gets the XML serializer. + + The XML serializer. + + + + Gets the type of configuration this plugin uses. + + The type of the configuration. + + + + Gets or sets the event handler that is triggered when this configuration changes. + + + + + Gets the name the assembly file. + + The name of the assembly file. + + + + Gets or sets the plugin configuration. + + The configuration. + + + + Gets the name of the configuration file. Subclasses should override. + + The name of the configuration file. + + + + Gets the full path to the configuration file. + + The configuration file path. + + + + Gets the plugin configuration. + + The configuration. + + + + Saves the current configuration to the file system. + + Configuration to save. + + + + Saves the current configuration to the file system. + + + + + + + + + + + Defines the . + + + + + Gets the type of configuration this plugin uses. + + + + + Gets the plugin's configuration. + + + + + Completely overwrites the current configuration with a new copy. + + The configuration. + + + + Defines the . + + + + + Gets the name of the plugin. + + + + + Gets the Description. + + + + + Gets the unique id. + + + + + Gets the plugin version. + + + + + Gets the path to the assembly file. + + + + + Gets a value indicating whether the plugin can be uninstalled. + + + + + Gets the full path to the data folder, where the plugin can store any miscellaneous files needed. + + + + + Gets the . + + PluginInfo. + + + + Called when just before the plugin is uninstalled from the server. + + + + + Defines the . + + + + + Gets the Plugins. + + + + + Creates the plugins. + + + + + Returns all the assemblies. + + An IEnumerable{Assembly}. + + + + Registers the plugin's services with the DI. + Note: DI is not yet instantiated yet. + + A instance. + + + + Saves the manifest back to disk. + + The to save. + The path where to save the manifest. + True if successful. + + + + Generates a manifest from repository data. + + The used to generate a manifest. + Version to be installed. + The path where to save the manifest. + Initial status of the plugin. + True if successful. + + + + Imports plugin details from a folder. + + Folder of the plugin. + + + + Disable the plugin. + + The of the plug to disable. + + + + Disable the plugin. + + The of the plug to disable. + + + + Enables the plugin, disabling all other versions. + + The of the plug to disable. + + + + Attempts to find the plugin with and id of . + + Id of plugin. + The version of the plugin to locate. + A if located, or null if not. + + + + Removes the plugin. + + The plugin. + Outcome of the operation. + + + + Local plugin class. + + + + + Initializes a new instance of the class. + + The plugin path. + True if Jellyfin supports this version of the plugin. + The manifest record for this plugin, or null if one does not exist. + + + + Gets the plugin id. + + + + + Gets the plugin name. + + + + + Gets the plugin version. + + + + + Gets the plugin path. + + + + + Gets or sets the list of dll files for this plugin. + + + + + Gets or sets the instance of this plugin. + + + + + Gets a value indicating whether Jellyfin supports this version of the plugin, and it's enabled. + + + + + Gets a value indicating whether the plugin has a manifest. + + + + + Compare two . + + The first item. + The second item. + Comparison result. + + + + Returns the plugin information. + + A instance containing the information. + + + + + + + + + + + + + Defines a Plugin manifest file. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the category of the plugin. + + + + + Gets or sets the changelog information. + + + + + Gets or sets the description of the plugin. + + + + + Gets or sets the Global Unique Identifier for the plugin. + + + + + Gets or sets the Name of the plugin. + + + + + Gets or sets an overview of the plugin. + + + + + Gets or sets the owner of the plugin. + + + + + Gets or sets the compatibility version for the plugin. + + + + + Gets or sets the timestamp of the plugin. + + + + + Gets or sets the Version number of the plugin. + + + + + Gets or sets a value indicating the operational status of this plugin. + + + + + Gets or sets a value indicating whether this plugin should automatically update. + + + + + Gets or sets the ImagePath + Gets or sets a value indicating whether this plugin has an image. + Image must be located in the local plugin folder. + + + + + Gets or sets the collection of assemblies that should be loaded. + Paths are considered relative to the plugin folder. + + + + + Parsers for provider ids. + + + + + Parses an IMDb id from a string. + + The text to parse. + The parsed IMDb id. + True if parsing was successful, false otherwise. + + + + Parses an TMDb id from a movie url. + + The text with the url to parse. + The parsed TMDb id. + True if parsing was successful, false otherwise. + + + + Parses an TMDb id from a series url. + + The text with the url to parse. + The parsed TMDb id. + True if parsing was successful, false otherwise. + + + + Parses an TVDb id from a url. + + The text with the url to parse. + The parsed TVDb id. + True if parsing was successful, false otherwise. + + + + + + + Marks a BaseItem as needing custom serialisation from the Data field of the db. + + + + + Defines the . + + + + + Gets the completed installations. + + + + + Parses a plugin manifest at the supplied URL. + + Name of the repository. + The URL to query. + Filter out incompatible plugins. + The cancellation token. + Task{IReadOnlyList{PackageInfo}}. + + + + Gets all available packages that are supported by this version. + + The cancellation token. + Task{IReadOnlyList{PackageInfo}}. + + + + Returns all plugins matching the requirements. + + The available packages. + The name of the plugin. + The id of the plugin. + The version of the plugin. + All plugins matching the requirements. + + + + Returns all compatible versions ordered from newest to oldest. + + The available packages. + The name. + The id of the plugin. + The minimum required version of the plugin. + The specific version of the plugin to install. + All compatible versions ordered from newest to oldest. + + + + Returns the available compatible plugin updates. + + The cancellation token. + The available plugin updates. + + + + Installs the package. + + The package. + The cancellation token. + . + + + + Uninstalls a plugin. + + The plugin. + + + + Cancels the installation. + + The id of the package that is being installed. + Returns true if the install was cancelled. + + + + Defines the . + + + + + Gets or sets the . + + + + + Gets or sets the . + + + + Custom -derived type for the StripHtmlRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Custom -derived type for the FqdnGeneratedRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Helper methods used by generated -derived implementations. + + + Default timeout value set in , or if none was set. + + + Whether is non-infinite. + + + Pops 2 values from the backtracking stack. + + + Pushes 1 value onto the backtracking stack. + + + Pushes 2 values onto the backtracking stack. + + + Pushes 3 values onto the backtracking stack. + + + Supports searching for characters in or not in "-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzİK". + +
+
diff --git a/publish/MediaBrowser.Controller.xml b/publish/MediaBrowser.Controller.xml new file mode 100644 index 00000000..dd0e6ca3 --- /dev/null +++ b/publish/MediaBrowser.Controller.xml @@ -0,0 +1,12327 @@ + + + + MediaBrowser.Controller + + + + + The exception that is thrown when an attempt to authenticate fails. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + The message that describes the error. + + + + Initializes a new instance of the class. + + The message that describes the error. + The exception that is the cause of the current exception, or a null reference if no inner exception is specified. + + + + A class representing an authentication result. + + + + + Gets or sets the user. + + + + + Gets or sets the session info. + + + + + Gets or sets the access token. + + + + + Gets or sets the server id. + + + + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + + + + The BaseItem manager. + + + + + Is metadata fetcher enabled. + + The base item. + The type options for baseItem from the library (if defined). + The metadata fetcher name. + true if metadata fetcher is enabled, else false. + + + + Is image fetcher enabled. + + The base item. + The type options for baseItem from the library (if defined). + The image fetcher name. + true if image fetcher is enabled, else false. + + + + Determines whether this channel is visible to the specified user. + + The user. + Whether to skip the allowed tags check. + True if visible; otherwise, false. + + + + Gets items from the channel. + + The items query. + The query result. + + + + Gets the internal metadata path for this channel. + + The base path. + The internal metadata path. + + + + Gets the internal metadata path for a channel with the specified ID. + + The base path. + The channel ID. + The internal metadata path. + + + + Determines whether this channel can be deleted. + + True if deletable; otherwise, false. + + + + Determines whether the channel item is visible to the specified user. + + The channel item. + The user. + True if visible; otherwise, false. + + + + Gets the name. + + The name. + + + + Gets the description. + + The description. + + + + Gets the data version. + + The data version. + + + + Gets the home page URL. + + The home page URL. + + + + Gets the parental rating. + + The parental rating. + + + + Gets the channel information. + + ChannelFeatures. + + + + Determines whether [is enabled for] [the specified user]. + + The user identifier. + true if [is enabled for] [the specified user]; otherwise, false. + + + + Gets the channel items. + + The query. + The cancellation token. + Task{IEnumerable{ChannelItem}}. + + + + Gets the channel image. + + The type. + The cancellation token. + Task{DynamicImageResponse}. + + + + Gets the supported channel images. + + IEnumerable{ImageType}. + + + + Gets the channel features. + + The identifier. + ChannelFeatures. + + + + Gets all channel features. + + IEnumerable{ChannelFeatures}. + + + + Gets the channel. + + The identifier. + Channel. + + + + Gets the channels internal. + + The query. + The channels. + + + + Gets the channels. + + The query. + The channels. + + + + Gets the latest channel items. + + The item query. + The cancellation token. + The latest channels. + + + + Gets the latest channel items. + + The item query. + The cancellation token. + The latest channels. + + + + Gets the channel items. + + The query. + The cancellation token. + The channel items. + + + + Gets the channel items. + + The query. + The progress to report to. + The cancellation token. + The channel items. + + + + Gets the channel item media sources. + + The item. + The cancellation token. + The item media sources. + + + + Disable media source display. + + + can inherit this interface to disable being displayed. + + + + + Gets the cache key. + + The user identifier. + System.String. + + + + Gets or sets the media types. + + The media types. + + + + Gets or sets the content types. + + The content types. + + + + Gets or sets the maximum number of records the channel allows retrieving at a time. + + + + + Gets or sets the default sort orders. + + The default sort orders. + + + + Gets or sets a value indicating whether a sort ascending/descending toggle is supported or not. + + + + + Gets or sets the automatic refresh levels. + + The automatic refresh levels. + + + + Gets or sets the daily download limit. + + The daily download limit. + + + + Gets or sets a value indicating whether [supports downloading]. + + true if [supports downloading]; otherwise, false. + + + + The channel requires a media info callback. + + + + + Gets the channel item media information. + + The channel item id. + The cancellation token. + The enumerable of media source info. + + + + Gets the latest media. + + The request. + The cancellation token. + The latest media. + + + + Channel supports media probe. + + + + + Interface IChapterManager. + + + + + Saves the chapters. + + The video. + The set of chapters. + + + + Saves the chapters asynchronously. + + The video. + The set of chapters. + The cancellation token. + A task representing the asynchronous operation. + + + + Gets a single chapter of a BaseItem on a specific index. + + The BaseItems id. + The index of that chapter. + A chapter instance. + + + + Gets a single chapter of a BaseItem on a specific index asynchronously. + + The BaseItems id. + The index of that chapter. + The cancellation token. + A chapter instance. + + + + Gets all chapters associated with the baseItem. + + The BaseItems id. + A readonly list of chapter instances. + + + + Gets all chapters associated with the baseItem asynchronously. + + The BaseItems id. + The cancellation token. + A readonly list of chapter instances. + + + + Refreshes the chapter images. + + Video to use. + Directory service to use. + Set of chapters to refresh. + Option to extract images. + Option to save chapters. + CancellationToken to use for operation. + true if successful, false if not. + + + + Deletes the chapter data. + + The item id. + The cancellation token. + Task. + + + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + The client event logger. + + + + + Writes a file to the log directory. + + The client name writing the document. + The client version writing the document. + The file contents to write. + The created file name. + + + + Gets or sets the collection. + + The collection. + + + + Gets or sets the options. + + The options. + + + + Gets or sets the collection. + + The collection. + + + + Gets or sets the items changed. + + The items changed. + + + + Occurs when [collection created]. + + + + + Occurs when [items added to collection]. + + + + + Occurs when [items removed from collection]. + + + + + Creates the collection. + + The options. + BoxSet wrapped in an awaitable task. + + + + Adds to collection. + + The collection identifier. + The item ids. + representing the asynchronous operation. + + + + Removes from collection. + + The collection identifier. + The item ids. + A representing the asynchronous operation. + + + + Collapses the items within box sets. + + The items. + The user. + IEnumerable{BaseItem}. + + + + Gets the folder where collections are stored. + + Will create the collection folder on the storage if set to true. + The folder instance referencing the collection storage. + + + + Interface IServerConfigurationManager. + + + + + Gets the application paths. + + The application paths. + + + + Gets the configuration. + + The configuration. + + + + Device manager interface. + + + + + Event handler for updated device options. + + + + + Creates a new device. + + The device to create. + A representing the creation of the device. + + + + Saves the capabilities. + + The device id. + The capabilities. + + + + Gets the capabilities. + + The device id. + ClientCapabilities. + + + + Gets the device information. + + The identifier. + DeviceInfoDto. + + + + Gets devices based on the provided query. + + The device query. + A representing the retrieval of the devices. + + + + Gets device information based on the provided query. + + The device query. + A representing the retrieval of the device information. + + + + Gets the device information. + + The user's id, or null. + IEnumerable<DeviceInfoDto>. + + + + Deletes a device. + + The device. + A representing the deletion of the device. + + + + Updates a device. + + The device. + A representing the update of the device. + + + + Determines whether this instance [can access device] the specified user identifier. + + The user to test. + The device id to test. + Whether the user can access the device. + + + + Updates the options of a device. + + The device id. + The device name. + A representing the update of the device options. + + + + Gets the options of a device. + + The device id. + of the device. + + + + Gets the dto for client capabilities. + + The client capabilities. + of the device. + + + + Gets the supported input formats. + + The supported input formats. + + + + Gets the supported output formats. + + The supported output formats. + + + + Gets the display name for the encoder. + + The display name. + + + + Gets a value indicating whether [supports image collage creation]. + + true if [supports image collage creation]; otherwise, false. + + + + Gets a value indicating whether [supports image encoding]. + + true if [supports image encoding]; otherwise, false. + + + + Get the dimensions of an image from the filesystem. + + The filepath of the image. + The image dimensions. + + + + Gets the blurhash of an image. + + Amount of X components of DCT to take. + Amount of Y components of DCT to take. + The filepath of the image. + The blurhash. + + + + Encode an image. + + Input path of image. + Date modified. + Output path of image. + Auto-orient image. + Desired orientation of image. + Quality of encoded image. + Image processing options. + Image format of output. + Path of encoded image. + + + + Create an image collage. + + The options to use when creating the collage. + Optional. + + + + Creates a new splashscreen image. + + The list of poster paths. + The list of backdrop paths. + + + + Creates a new trickplay tile image. + + The options to use when creating the image. Width and Height are a quantity of thumbnails in this case, not pixels. + The image encode quality. + The width of a single trickplay thumbnail. + Optional height of a single trickplay thumbnail, if it is known. + Height of single decoded trickplay thumbnail. + + + + Interface IImageProcessor. + + + + + Gets the supported input formats. + + The supported input formats. + + + + Gets a value indicating whether [supports image collage creation]. + + true if [supports image collage creation]; otherwise, false. + + + + Gets the dimensions of the image. + + Path to the image file. + ImageDimensions. + + + + Gets the dimensions of the image. + + The base item. + The information. + ImageDimensions. + + + + Gets the blurhash of the image. + + Path to the image file. + BlurHash. + + + + Gets the blurhash of the image. + + Path to the image file. + The image dimensions. + BlurHash. + + + + Gets the image cache tag. + + The items basePath. + The image last modification date. + Guid. + + + + Gets the image cache tag. + + The item. + The image. + Guid. + + + + Gets the image cache tag. + + The item. + The image. + Guid. + + + + Gets the image cache tag. + + The item. + The image. + Guid. + + + + Processes the image. + + The options. + Task. + + + + Gets the supported image output formats. + + . + + + + Creates the image collage. + + The options. + The library name to draw onto the collage. + + + + Gets or sets the input paths. + + The input paths. + + + + Gets or sets the output path. + + The output path. + + + + Gets or sets the width. + + The width. + + + + Gets or sets the height. + + The height. + + + + Interface IDtoService. + + + + + Gets the primary image aspect ratio. + + The item. + System.Nullable<System.Double>. + + + + Gets the base item dto. + + The item. + The options. + The user. + The owner. + BaseItemDto. + + + + Gets the base item dtos. + + The items. + The options. + The user. + The owner. + The of . + + + + Gets the item by name dto. + + The item. + The dto options. + The list of tagged items. + The user. + The item dto. + + + + Specialized folder that can have items added to it's children by external entities. + Used for our RootFolder so plugins can add items. + + + + + The _virtual children. + + + + + Gets the virtual children. + + The virtual children. + + + + Adds the virtual child. + + The child. + Throws if child is null. + + + + Finds the virtual child. + + The id. + BaseItem. + The id is empty. + + + + Finds the series sort name. + + The series sort name. + + + + Finds the series name. + + The series name. + + + + Finds the series presentation unique key. + + The series presentation unique key. + + + + Gets the default primary image aspect ratio. + + The default primary image aspect ratio. + + + + Finds the series identifier. + + The series identifier. + + + + Determines whether this audiobook can be downloaded. + + True if downloadable; otherwise, false. + + + + Gets the unrated type for blocking purposes. + + The unrated item type. + + + + Class Audio. + + + + + + + + + + + Gets the type of the media. + + The type of the media. + + + + Gets or sets a value indicating whether this audio has lyrics. + + + + + Gets or sets the list of lyric paths. + + + + + Creates the name of the sort. + + System.String. + + + + Gets or sets the artists. + + The artists. + + + + Class MusicAlbum. + + + + + + + + + + + Gets the tracks. + + The tracks. + + + + Class MusicArtist. + + + + + Gets the folder containing the item. + If the item is a folder, it returns the folder itself. + + The containing folder path. + + + + Gets the user data key. + + The item. + System.String. + + + + This is called before any metadata refresh and returns true or false indicating if changes were made. + + Option to replace metadata. + True if metadata changed. + + + + Class MusicGenre. + + + + + Gets the folder containing the item. + If the item is a folder, it returns the folder itself. + + The containing folder path. + + + + This is called before any metadata refresh and returns true or false indicating if changes were made. + + Option to replace metadata. + True if metadata changed. + + + + Class BaseItem. + + + + + The supported image extensions. + + + + + Extra types that should be counted and displayed as "Special Features" in the UI. + + + + + Gets or Sets the user data collection as cached from the last Db query. + + + + + Gets or sets the album. + + The album. + + + + Gets or sets the LUFS value. + + The LUFS Value. + + + + Gets or sets the gain required for audio normalization. + + The gain required for audio normalization. + + + + Gets or sets the channel identifier. + + The channel identifier. + + + + Gets or sets a value indicating whether this instance is in mixed folder. + + true if this instance is in mixed folder; otherwise, false. + + + + Gets or sets the name. + + The name. + + + + Gets or sets the id. + + The id. + + + + Gets or sets the audio. + + The audio. + + + + Gets the id that should be used to key display prefs for this item. + Default is based on the type for everything except actual generic folders. + + The display prefs id. + + + + Gets or sets the path. + + The path. + + + + Gets the folder containing the item. + If the item is a folder, it returns the folder itself. + + + + + Gets or sets the name of the service. + + The name of the service. + + + + Gets or sets the external id. + + + If this content came from an external service, the id of the content on that service. + + + + + Gets the type of the location. + + The type of the location. + + + + Gets the primary image path. + + + This is just a helper for convenience. + + The primary image path. + + + + Gets or sets the date created. + + The date created. + + + + Gets or sets the date modified. + + The date modified. + + + + Gets or sets the locked fields. + + The locked fields. + + + + Gets the type of the media. + + The type of the media. + + + + Gets or sets the logger. + + + + + Gets or sets the name of the forced sort. + + The name of the forced sort. + + + + Gets or sets the name of the sort. + + The name of the sort. + + + + Gets or sets the date that the item first debuted. For movies this could be premiere date, episodes would be first aired. + + The premiere date. + + + + Gets or sets the end date. + + The end date. + + + + Gets or sets the official rating. + + The official rating. + + + + Gets or sets the critic rating. + + The critic rating. + + + + Gets or sets the custom rating. + + The custom rating. + + + + Gets or sets the overview. + + The overview. + + + + Gets or sets the studios. + + The studios. + + + + Gets or sets the genres. + + The genres. + + + + Gets or sets the tags. + + The tags. + + + + Gets or sets the home page URL. + + The home page URL. + + + + Gets or sets the community rating. + + The community rating. + + + + Gets or sets the run time ticks. + + The run time ticks. + + + + Gets or sets the production year. + + The production year. + + + + Gets or sets the index number. If the item is part of a series, this is it's number in the series. + This could be episode number, album track number, etc. + + The index number. + + + + Gets or sets the parent index number. For an episode this could be the season number, or for a song this could be the disc number. + + The parent index number. + + + + Gets or sets the provider ids. + + The provider ids. + + + + Gets a value indicating whether this instance is folder. + + true if this instance is folder; otherwise, false. + + + + Gets or sets the remote trailers. + + The remote trailers. + + + + + + + Creates the name of the sort. + + System.String. + + + + Finds a parent of a given type. + + Type of parent. + ``0. + + + + Gets the play access. + + The user. + PlayAccess. + + + + The base implementation to refresh metadata. + + The options. + The cancellation token. + true if a provider reports we changed. + + + + Refreshes owned items such as trailers, theme videos, special features, etc. + Returns true or false indicating if changes were found. + + The metadata refresh options. + The list of filesystem children. + The cancellation token. + true if any items have changed, else false. + + + + Gets the preferred metadata language. + + System.String. + + + + Gets the preferred metadata language. + + System.String. + + + + Determines if a given user has access to this item. + + The user. + Don't check for allowed tags. + true if [is parental allowed] [the specified user]; otherwise, false. + If user is null. + + + + Gets a bool indicating if access to the unrated item is blocked or not. + + The configuration. + true if blocked, false otherwise. + + + + Determines if this folder should be visible to a given user. + Default is just parental allowed. Can be overridden for more functionality. + + The user. + Don't check for allowed tags. + true if the specified user is visible; otherwise, false. + is null. + + + + Gets the linked child. + + The info. + BaseItem. + + + + Adds a studio to the item. + + The name. + Throws if name is null. + + + + Adds a genre to the item. + + The name. + Throws if name is null. + + + + Marks the played. + + The user. + The date played. + if set to true [reset position]. + Throws if user is null. + + + + Marks the unplayed. + + The user. + Throws if user is null. + + + + Do whatever refreshing is necessary when the filesystem pertaining to this item has changed. + + + + + Gets an image. + + The type. + Index of the image. + true if the specified type has image; otherwise, false. + Backdrops should be accessed using Item.Backdrops. + + + + Deletes the image. + + The type. + The index. + A task. + + + + Validates that images within the item are still on the filesystem. + + true if the images validate, false if not. + + + + Gets the image path. + + Type of the image. + Index of the image. + System.String. + Item is null. + + + + Gets the image information. + + Type of the image. + Index of the image. + ItemImageInfo. + + + + Computes image index for given image or raises if no matching image found. + + Image to compute index for. + Image index cannot be computed as no matching image found. + + Image index. + + + + Adds the images, updating metadata if they already are part of this item. + + Type of the image. + The images. + true if images were added or updated, false otherwise. + Cannot call AddImages with chapter images. + + + + Gets the file system path to delete when the item is to be deleted. + + The metadata for the deleted paths. + + + + This is called before any metadata refresh and returns true if changes were made. + + Whether to replace all metadata. + true if the item has change, else false. + + + + Updates the official rating based on content and returns true or false indicating if it changed. + + Media children. + true if the rating was updated; otherwise false. + + + + Get all extras associated with this item, sorted by . + + An enumerable containing the items. + + + + Get all extras with specific types that are associated with this item. + + The types of extras to retrieve. + An enumerable containing the extras. + + + + + + + + + + + + + Gets the image path. + + The item. + Type of the image. + System.String. + + + + Sets the image path. + + The item. + Type of the image. + The file. + + + + Sets the image path. + + The item. + Type of the image. + The file. + + + + Copies all properties on object. Skips properties that do not exist. + + The source object. + The destination object. + Source type. + Destination type. + + + + Copies all properties on newly created object. Skips properties that do not exist. + + The source object. + Source type. + Destination type. + Destination object. + + + + Determines if the item has changed. + + The source object. + The timestamp to detect changes as of. + Source type. + Whether the item has changed. + + + + Plugins derive from and export this class to create a folder that will appear in the root along + with all the other actual physical folders in the system. + + + + + + + + + + + Specialized Folder class that points to a subset of the physical folders in the system. + It is created from the user-specific folders within the system root. + + + + + Initializes a new instance of the class. + + + + + Gets the display preferences id. + + + Allow different display preferences for each collection folder. + + The display prefs id. + + + + Gets the item's children. + + + Our children are actually just references to the ones in the physical root... + + The actual children. + + + + Compare our current children (presumably just read from the repo) with the current state of the file system and adjust for any changes + ***Currently does not contain logic to maintain items that are unavailable in the file system***. + + The progress. + if set to true [recursive]. + if set to true [refresh child metadata]. + remove item even this folder is root. + The refresh options. + The directory service. + The cancellation token. + Task. + + + + Class Extensions. + + + + + Adds the trailer URL. + + Media item. + Trailer URL. + + + + Class Folder. + + + + + Gets or sets a value indicating whether this instance is root. + + true if this instance is root; otherwise, false. + + + + Gets a value indicating whether this instance is folder. + + true if this instance is folder; otherwise, false. + + + + Gets or Sets the actual children. + + The actual children. + + + + Gets thread-safe access to all recursive children of this folder - without regard to user. + + The recursive children. + + + + Adds the child. + + The item. + Unable to add + item.Name. + + + + Loads our children. Validation will occur externally. + We want this synchronous. + + Returns children. + + + + Validates that the children of the folder still exist. + + The progress. + The metadata refresh options. + if set to true [recursive]. + remove item even this folder is root. + The cancellation token. + Task. + + + + Validates the children internal. + + The progress. + if set to true [recursive]. + if set to true [refresh child metadata]. + remove item even this folder is root. + The refresh options. + The directory service. + The cancellation token. + Task. + + + + Refreshes the children. + + The children. + The directory service. + The progress. + The cancellation token. + Task. + + + + Runs an action block on a list of children. + + The task to run for each child. + The list of children. + The progress. + The cancellation token. + Task. + + + + Get the children of this folder from the actual file system. + + IEnumerable{BaseItem}. + The directory service to use for operation. + Returns set of base items. + + + + Get our children from the repo - stubbed for now. + + IEnumerable{BaseItem}. + + + + Adds the children to list. + + + + + Gets the recursive children. + + IList{BaseItem}. + + + + Adds the children to list. + + + + + Gets the linked children. + + IEnumerable{BaseItem}. + + + + Gets the linked children. + + IEnumerable{BaseItem}. + + + + Refreshes the linked children. + + The enumerable of file system metadata. + true if the linked children were updated, false otherwise. + + + + Marks the played. + + The user. + The date played. + if set to true [reset position]. + + + + Marks the unplayed. + + The user. + + + + Contains constants used when reporting scan progress. + + + + + Reported after the folders immediate children are retrieved. + + + + + Reported after add, updating, or deleting child items from the LibraryManager. + + + + + Reported once subfolders are scanned. + When scanning subfolders, the progress will be between [UpdatedItems, ScannedSubfolders]. + + + + + Reported once metadata is refreshed. + When refreshing metadata, the progress will be between [ScannedSubfolders, MetadataRefreshed]. + + + + + Gets the current progress given the previous step, next step, and progress in between. + + The previous progress step. + The next progress step. + The current progress step. + The progress. + + + + Class Genre. + + + + + Gets the folder containing the item. + If the item is a folder, it returns the folder itself. + + The containing folder path. + + + + This is called before any metadata refresh and returns true if changes were made. + + Whether to replace all metadata. + true if the item has change, else false. + + + + This is just a marker interface to denote top level folders. + + + + + Interface IHasAspectRatio. + + + + + Gets or sets the aspect ratio. + + The aspect ratio. + + + + Interface IHasDisplayOrder. + + + + + Gets or sets the display order. + + The display order. + + + + Gets the media sources. + + true to enable path substitution, false to not. + A list of media sources. + + + + Gets or sets the name of the series. + + The name of the series. + + + + Gets the special feature ids. + + The special feature ids. + + + + Gets or sets the remote trailers. + + The remote trailers. + + + + Gets the local trailers. + + The local trailers. + + + + Class providing extension methods for working with . + + + + + Gets the trailer count. + + Media item. + . + + + + Marker interface. + + + + + Refreshes all metadata. + + The refresh options. + The progress. + The cancellation token. + Task. + + + + Gets or sets the minimum ParentIndexNumber and IndexNumber. + + + It produces this where clause: + (ParentIndexNumber = X and IndexNumber >= Y) or ParentIndexNumber > X. + + + + + + Gets or sets a value indicating whether album sub-folders should be returned if they exist. + + + + + Gets or sets the maximum number of items the query should return. + + + + + Marker interface to denote a class that supports being hidden underneath it's boxset. + Just about anything can be placed into a boxset, + but movies should also only appear underneath and not outside separately (subject to configuration). + + + + + Gets a value indicating whether this instance is place holder. + + true if this instance is place holder; otherwise, false. + + + + Gets or sets the path. + + The path. + + + + Gets or sets the type. + + The type. + + + + Gets or sets the date modified. + + The date modified. + + + + Gets or sets the blurhash. + + The blurhash. + + + + Gets or sets the linked item id. + + + + + The linked child type. + + + + + Manually linked child. + + + + + Shortcut linked child. + + + + + Compare MediaSource of the same file by Video width . + + + + + + + + Class BoxSet. + + + + + + + + Gets or sets the display order. + + The display order. + + + + Class Movie. + + + + + + + + + + + Gets or sets the name of the TMDb collection. + + The name of the TMDb collection. + + + + + + + + + + + + + This is the full Person object that can be retrieved with all of it's data. + + + + + Gets the folder containing the item. + If the item is a folder, it returns the folder itself. + + The containing folder path. + + + + Gets a value indicating whether to enable alpha numeric sorting. + + + + + This is called before any metadata refresh and returns true or false indicating if changes were made. + + true to replace all metadata, false to not. + true if changes were made, false if not. + + + + This is a small Person stub that is attached to BaseItems. + + + + + Gets or Sets the PersonId. + + + + + Gets or sets the name. + + The name. + + + + Gets or sets the role. + + The role. + + + + Gets or sets the type. + + The type. + + + + Gets or sets the ascending sort order. + + The sort order. + + + + Returns a that represents this instance. + + A that represents this instance. + + + + Class Studio. + + + + + Gets the folder containing the item. + If the item is a folder, it returns the folder itself. + + The containing folder path. + + + + This is called before any metadata refresh and returns true or false indicating if changes were made. + + true to replace all metadata, false to not. + true if changes were made, false if not. + + + + Class Trailer. + + + + + Class Episode. + + + + + + + + Gets or sets the season in which it aired. + + The aired season. + + + + Gets or sets the ending episode number for double episodes. + + The index number. + + + + Gets the Episode's Series Instance. + + The series. + + + + Creates the name of the sort. + + System.String. + + + + Determines whether [contains episode number] [the specified number]. + + The number. + true if [contains episode number] [the specified number]; otherwise, false. + + + + Class Season. + + + + + Gets this Episode's Series Instance. + + The series. + + + + Creates the name of the sort. + + System.String. + + + + Gets the episodes. + + The user. + The options to use. + If missing episodes should be included. + Set of episodes. + + + + Gets the lookup information. + + SeasonInfo. + + + + This is called before any metadata refresh and returns true or false indicating if changes were made. + + true to replace metadata, false to not. + true if XXXX, false otherwise. + + + + Class Series. + + + + + + + + Gets or sets the display order. + + + Valid options are airdate, dvd or absolute. + + + + + Gets or sets the status. + + The status. + + + + Gets the user data key. + + System.String. + + + + Filters the episodes by season. + + The episodes. + The season. + true to include special, false to not. + The set of episodes. + + + + Filters the episodes by season. + + The episodes. + The season. + true to include special, false to not. + The set of episodes. + + + + Class UserItemData. + + + + + The _rating. + + + + + Gets or sets the key. + + The key. + + + + Gets or sets the users 0-10 rating. + + The rating. + Rating;A 0 to 10 rating is required for UserItemData. + + + + Gets or sets the playback position ticks. + + The playback position ticks. + + + + Gets or sets the play count. + + The play count. + + + + Gets or sets a value indicating whether this instance is favorite. + + true if this instance is favorite; otherwise, false. + + + + Gets or sets the last played date. + + The last played date. + + + + Gets or sets a value indicating whether this is played. + + true if played; otherwise, false. + + + + Gets or sets the index of the audio stream. + + The index of the audio stream. + + + + Gets or sets the index of the subtitle stream. + + The index of the subtitle stream. + + + + Gets or sets a value indicating whether the item is liked or not. + This should never be serialized. + + null if [likes] contains no value, true if [likes]; otherwise, false. + + + + Special class used for User Roots. Children contain actual ones defined for this user + PLUS the virtual folders from the physical root (added by plug-ins). + + + + + Initializes a new instance of the class. + + + + + Gets or sets the view type. + + + + + Gets or sets the display parent id. + + + + + Gets or sets the user id. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Class Video. + + + + + Gets or sets the timestamp. + + The timestamp. + + + + Gets or sets the subtitle paths. + + The subtitle paths. + + + + Gets or sets the audio paths. + + The audio paths. + + + + Gets or sets a value indicating whether this instance has subtitles. + + true if this instance has subtitles; otherwise, false. + + + + Gets or sets the default index of the video stream. + + The default index of the video stream. + + + + Gets or sets the type of the video. + + The type of the video. + + + + Gets or sets the type of the iso. + + The type of the iso. + + + + Gets or sets the video3 D format. + + The video3 D format. + + + + Gets or sets the aspect ratio. + + The aspect ratio. + + + + Gets a value indicating whether [is3 D]. + + true if [is3 D]; otherwise, false. + + + + Gets the type of the media. + + The type of the media. + + + + Gets the additional parts. + + IEnumerable{Video}. + + + + + + + Class Year. + + + + + Gets the folder containing the item. + If the item is a folder, it returns the folder itself. + + The containing folder path. + + + + This is called before any metadata refresh and returns true if changes were made. + + Whether to replace all metadata. + true if the item has change, else false. + + + + A class representing an authentication result event. + + + + + Initializes a new instance of the class. + + The . + + + + Gets or sets the user name. + + + + + Gets or sets the user id. + + + + + Gets or sets the app. + + + + + Gets or sets the app version. + + + + + Gets or sets the device id. + + + + + Gets or sets the device name. + + + + + Gets or sets the remote endpoint. + + + + + A class representing an authentication result event. + + + + + Initializes a new instance of the class. + + The . + + + + Gets or sets the user. + + + + + Gets or sets the session information. + + + + + Gets or sets the server id. + + + + + An interface representing a type that consumes events of type T. + + The type of events this consumes. + + + + A method that is called when an event of type T is fired. + + The event. + A task representing the consumption of the event. + + + + An interface that handles eventing. + + + + + Publishes an event. + + the event arguments. + The type of event. + + + + Publishes an event asynchronously. + + The event arguments. + The type of event. + A task representing the publishing of the event. + + + + An event that fires when a session is ended. + + + + + Initializes a new instance of the class. + + The session info. + + + + An event that fires when a session is started. + + + + + Initializes a new instance of the class. + + The session info. + + + + An event that occurs when a plugin installation is cancelled. + + + + + Initializes a new instance of the class. + + The installation info. + + + + An event that occurs when a plugin is installed. + + + + + Initializes a new instance of the class. + + The installation info. + + + + An event that occurs when a plugin is installing. + + + + + Initializes a new instance of the class. + + The installation info. + + + + An event that occurs when a plugin is uninstalled. + + + + + Initializes a new instance of the class. + + The plugin. + + + + An event that occurs when a plugin is updated. + + + + + Initializes a new instance of the class. + + The installation info. + + + + Configuration extensions for MediaBrowser.Controller. + + + + + The key for a setting that specifies the default redirect path + to use for requests where the URL base prefix is invalid or missing.. + + + + + The key for the address override option. + + + + + The key for a setting that indicates whether the application should host web client content. + + + + + The key for the FFmpeg probe size option. + + + + + The key for the skipping FFmpeg validation. + + + + + The key for the FFmpeg analyze duration option. + + + + + The key for the FFmpeg image extraction performance tradeoff option. + + + + + The key for the FFmpeg path option. + + + + + The key for a setting that indicates whether kestrel should bind to a unix socket. + + + + + The key for the unix socket path. + + + + + The permissions for the unix socket. + + + + + The key for a setting that indicates whether the application should detect network status change. + + + + + Gets a value indicating whether the application should host static web content from the . + + The configuration to retrieve the value from. + The parsed config value. + The config value is not a valid bool string. See . + + + + Gets the FFmpeg probe size from the . + + The configuration to read the setting from. + The FFmpeg probe size option. + + + + Gets the FFmpeg analyze duration from the . + + The configuration to read the setting from. + The FFmpeg analyze duration option. + + + + Gets a value indicating whether the server should validate FFmpeg during startup. + + The configuration to read the setting from. + true if the server should validate FFmpeg during startup, otherwise false. + + + + Gets a value indicating whether the server should trade off for performance during FFmpeg image extraction. + + The configuration to read the setting from. + true if the server should trade off for performance during FFmpeg image extraction, otherwise false. + + + + Gets a value indicating whether kestrel should bind to a unix socket from the . + + The configuration to read the setting from. + true if kestrel should bind to a unix socket, otherwise false. + + + + Gets the path for the unix socket from the . + + The configuration to read the setting from. + The unix socket path. + + + + Gets the permissions for the unix socket from the . + + The configuration to read the setting from. + The unix socket permissions. + + + + Provides extension methods for to parse 's. + + + + + Reads a trimmed string from the current node. + + The . + The trimmed content. + + + + Reads an int from the current node. + + The . + The parsed int. + A value indicating whether the parsing succeeded. + + + + Parses a from the current node. + + The . + The parsed . + A value indicating whether the parsing succeeded. + + + + Parses a from the current node. + + The . + The date format string. + The parsed . + A value indicating whether the parsing succeeded. + + + + Parses a from the xml node. + + The . + A , or null if none is found. + + + + Used to split names of comma or pipe delimited genres and people. + + The . + IEnumerable{System.String}. + + + + Parses a array from the xml node. + + The . + The . + The . + + + + Manages the storage and retrieval of display preferences. + + + + + Gets the display preferences for the user and client. + + + This will create the display preferences if it does not exist, but it will not save automatically. + + The user's id. + The item id. + The client string. + The associated display preferences. + + + + Gets the default item display preferences for the user and client. + + + This will create the item display preferences if it does not exist, but it will not save automatically. + + The user id. + The item id. + The client string. + The item display preferences. + + + + Gets all of the item display preferences for the user and client. + + The user id. + The client string. + A list of item display preferences. + + + + Gets all of the custom item display preferences for the user and client. + + The user id. + The item id. + The client string. + The dictionary of custom item display preferences. + + + + Sets the custom item display preference for the user and client. + + The user id. + The item id. + The client id. + A dictionary of custom item display preferences. + + + + Updates or Creates the display preferences. + + The entity to update or create. + + + + Updates or Creates the display preferences for the given item. + + The entity to update or create. + + + + Provides low level File access that is much faster than the File/Directory api's. + + + + + Gets the filtered file system entries. + + The directory service. + The path. + The file system. + The application host. + The logger. + The args. + The flatten folder depth. + if set to true [resolve shortcuts]. + Dictionary{System.StringFileSystemInfo}. + is null or empty. + + + + Helper methods for file system management. + + + + + Deletes the file. + + The fileSystem. + The path. + The logger. + + + + Recursively delete empty folders. + + The fileSystem. + The path. + The logger. + + + + Resolves a single link hop for the specified path. + + + Returns null if the path is not a symbolic link or the filesystem does not support link resolution (e.g., exFAT). + + The file path to resolve. + + A representing the next link target if the path is a link; otherwise, null. + + + + + Gets the target of the specified file link. + + + This helper exists because of this upstream runtime issue; https://github.com/dotnet/runtime/issues/92128. + + The path of the file link. + true to follow links to the final target; false to return the immediate next link. + + A if the is a link, regardless of if the target exists; otherwise, null. + + + + + Gets the target of the specified file link. + + + This helper exists because of this upstream runtime issue; https://github.com/dotnet/runtime/issues/92128. + + The file info of the file link. + true to follow links to the final target; false to return the immediate next link. + + A if the is a link, regardless of if the target exists; otherwise, null. + + + + + Interface IPathManager. + + + + + Deletes all external item data. + + The item. + The cancellation token. + Task. + + + + Interface IPathManager. + + + + + Gets the path to the trickplay image base folder. + + The item. + Whether or not the tile should be saved next to the media file. + The absolute path. + + + + Gets the path to the subtitle file. + + The media source id. + The stream index. + The subtitle file extension. + The absolute path. + + + + Gets the path to the subtitle file. + + The media source id. + The absolute path. + + + + Gets the path to the attachment file. + + The media source id. + The attachmentFileName index. + The absolute path. + + + + Gets the path to the attachment folder. + + The media source id. + The absolute path. + + + + Gets the chapter images data path. + + The base item. + The chapter images data path. + + + + Gets the chapter images path. + + The base item. + The chapter position. + The chapter images data path. + + + + Gets the paths of extracted data folders. + + The base item. + The absolute paths. + + + + Interface IKeyframeManager. + + + + + Gets the keyframe data asynchronously. + + The item id. + The cancellation token. + The keyframe data. + + + + Saves the keyframe data. + + The item id. + The keyframe data. + The cancellation token. + The task object representing the asynchronous operation. + + + + Deletes the keyframe data. + + The item id. + The cancellation token. + The task object representing the asynchronous operation. + + + + Interface IServerApplicationHost. + + + + + Gets the HTTP server port. + + The HTTP server port. + + + + Gets the HTTPS port. + + The HTTPS port. + + + + Gets a value indicating whether the server should listen on an HTTPS port. + + + + + Gets the name of the friendly. + + The name of the friendly. + + + + Gets or sets the path to the backup archive used to restore upon restart. + + + + + Gets a URL specific for the request. + + The instance. + An accessible URL. + + + + Gets a URL specific for the request. + + The remote of the connection. + An accessible URL. + + + + Gets a URL specific for the request. + + The hostname used in the connection. + An accessible URL. + + + + Gets an URL that can be used to access the API over LAN. + + An optional IP address to use. + A value indicating whether to allow HTTPS. + The API URL. + + + + Gets a local (LAN) URL that can be used to access the API. + Note: if passing non-null scheme or port it is up to the caller to ensure they form the correct pair. + + The hostname to use in the URL. + + The scheme to use for the URL. If null, the scheme will be selected automatically, + preferring HTTPS, if available. + + + The port to use for the URL. If null, the port will be selected automatically, + preferring the HTTPS port, if available. + + The API URL. + + + + Gets the path to the base root media directory. + + The root folder path. + + + + Gets the path to the default user view directory. Used if no specific user view is defined. + + The default user views path. + + + + Gets the path to the People directory. + + The people path. + + + + Gets the path to the Genre directory. + + The genre path. + + + + Gets the music genre path. + + The music genre path. + + + + Gets the path to the Studio directory. + + The studio path. + + + + Gets the path to the Year directory. + + The year path. + + + + Gets the path to the user configuration directory. + + The user configuration directory path. + + + + Gets the default internal metadata path. + + + + + Gets the internal metadata path, either a custom path or the default. + + The internal metadata path. + + + + Gets the virtual internal metadata path, either a custom path or the default. + + The virtual internal metadata path. + + + + Gets the path to the artists directory. + + The artists path. + + + + A service for managing the application instance. + + + + + Gets the system info. + + The HTTP request. + The . + + + + Gets the public system info. + + The HTTP request. + The . + + + + Starts the application restart process. + + + + + Starts the application shutdown process. + + + + + Gets the systems storage resources. + + The . + + + + Provides a shared scheduler to run library related tasks based on the . + + + + + Enqueues an action that will be invoked with the set data. + + The data Type. + The data. + The callback to process the data. + A progress reporter. + Stop token. + A task that finishes when all data has been processed by the worker. + + + + Provides Parallel action interface to process tasks with a set concurrency level. + + + + + Gets used to lock all operations on the Tasks queue and creating workers. + + + + + Initializes a new instance of the class. + + The hosting lifetime. + The logger. + The server configuration manager. + + + + + + + + + + The direct live TV stream provider. + + + Deprecated. + + + + + Gets the live stream, shared streams seek to the end of the file first. + + The stream. + + + + Class BaseIntroProvider. + + + + + Gets the name. + + The name. + + + + Gets the intros. + + The item. + The user. + IEnumerable{System.String}. + + + + Interface ILibraryManager. + + + + + Occurs when [item added]. + + + + + Occurs when [item updated]. + + + + + Occurs when [item removed]. + + + + + Gets the root folder. + + The root folder. + + + + Resolves the path. + + The file information. + The parent. + An instance of . + BaseItem. + + + + Resolves a set of files into a list of BaseItem. + + The list of tiles. + Instance of the interface. + The parent folder. + The library options. + The collection type. + The items resolved from the paths. + + + + Gets a Person. + + The name of the person. + Task{Person}. + + + + Finds the by path. + + The path. + true is the path is a directory; otherwise false. + BaseItem. + + + + Gets the artist. + + The name of the artist. + Task{Artist}. + + + + Gets a Studio. + + The name of the studio. + Task{Studio}. + + + + Gets a Genre. + + The name of the genre. + Task{Genre}. + + + + Gets the genre. + + The name of the music genre. + Task{MusicGenre}. + + + + Gets a Year. + + The value. + Task{Year}. + Throws if year is invalid. + + + + Validate and refresh the People sub-set of the IBN. + The items are stored in the db but not loaded into memory until actually requested by an operation. + + The progress. + The cancellation token. + Task. + + + + Reloads the root media folder. + + The progress. + The cancellation token. + Task. + + + + Reloads the root media folder. + + The cancellation token. + Is remove the library itself allowed. + Task. + + + + Gets the default view. + + IEnumerable{VirtualFolderInfo}. + + + + Gets the item by id. + + The id. + BaseItem. + is null. + + + + Gets the item by id, as T. + + The item id. + The type of item. + The item. + + + + Gets the item by id, as T, and validates user access. + + The item id. + The user id to validate against. + The type of item. + The item if found. + + + + Gets the item by id, as T, and validates user access. + + The item id. + The user to validate against. + The type of item. + The item if found. + + + + Gets the intros. + + The item. + The user. + IEnumerable{System.String}. + + + + Adds the parts. + + The rules. + The resolvers. + The intro providers. + The item comparers. + The post scan tasks. + + + + Sorts the specified items. + + The items. + The user. + The sort by. + The sort order. + IEnumerable{BaseItem}. + + + + Gets the user root folder. + + UserRootFolder. + + + + Creates the item. + + Item to create. + Parent of new item. + + + + Creates the items. + + Items to create. + Parent of new items. + CancellationToken to use for operation. + + + + Updates the item. + + Items to update. + Parent of updated items. + Reason for update. + CancellationToken to use for operation. + Returns a Task that can be awaited. + + + + Updates the item. + + The item. + The parent item. + The update reason. + The cancellation token. + Returns a Task that can be awaited. + + + + Reattaches the user data to the item. + + The item. + The cancellation token. + A task that represents the asynchronous reattachment operation. + + + + Retrieves the item. + + The id. + BaseItem. + + + + Retrieves the item asynchronously. + + The id. + The cancellation token. + A task representing the async operation. + + + + Finds the type of the collection. + + The item. + System.String. + + + + Gets the type of the inherited content. + + The item. + System.String. + + + + Gets the type of the configured content. + + The item. + System.String. + + + + Gets the type of the configured content. + + The path. + System.String. + + + + Normalizes the root path list. + + The paths. + IEnumerable{System.String}. + + + + Registers the item. + + The item. + + + + Deletes the item. + + Item to delete. + Options to use for deletion. + + + + Deletes items that are not having any children like Actors. + + Items to delete. + In comparison to this method skips a lot of steps assuming there are no children to recusively delete nor does it define the special handling for channels and alike. + + + + Deletes the item. + + Item to delete. + Options to use for deletion. + Notify parent of deletion. + + + + Deletes the item. + + Item to delete. + Options to use for deletion. + Parent of item. + Notify parent of deletion. + + + + Gets the named view. + + The user. + The name. + The parent identifier. + Type of the view. + Name of the sort. + The named view. + + + + Gets the named view. + + The user. + The name. + Type of the view. + Name of the sort. + The named view. + + + + Gets the named view. + + The name. + Type of the view. + Name of the sort. + The named view. + + + + Gets the named view. + + The name. + The parent identifier. + Type of the view. + Name of the sort. + The unique identifier. + The named view. + + + + Gets the shadow view. + + The parent. + Type of the view. + Name of the sort. + The shadow view. + + + + Gets the season number from path. + + The path. + The parent id. + System.Nullable<System.Int32>. + + + + Fills the missing episode numbers from path. + + Episode to use. + Option to force refresh of episode numbers. + True if successful. + + + + Parses the name. + + The name. + ItemInfo. + + + + Gets the new item identifier. + + The key. + The type. + Guid. + + + + Finds the extras. + + The owner. + The file system children. + An instance of . + IEnumerable<BaseItem>. + + + + Gets the collection folders. + + The item. + The folders that contain the item. + + + + Gets the collection folders. + + The item. + The root folders to consider. + The folders that contain the item. + + + + Gets the people. + + The item. + List<PersonInfo>. + + + + Gets the people. + + The query. + List<PersonInfo>. + + + + Gets the people items. + + The query. + List<Person>. + + + + Updates the people. + + The item. + The people. + + + + Asynchronously updates the people. + + The item. + The people. + The cancellation token. + The async task. + + + + Gets the item ids. + + The query. + List<Guid>. + + + + Gets the people names. + + The query. + List<System.String>. + + + + Queries the items. + + The query. + QueryResult<BaseItem>. + + + + Converts the image to local. + + The item. + The image. + Index of the image. + Whether to remove the image from the item on failure. + Task. + + + + Gets the items. + + The query. + QueryResult<BaseItem>. + + + + Gets the items. + + The query to use. + Items to use for query. + List of items. + + + + Gets the TVShow/Album items for Latest api. + + The query to use. + Items to use for query. + Collection Type. + List of items. + + + + Gets the list of series presentation keys for next up. + + The query to use. + Items to use for query. + The minimum date for a series to have been most recently watched. + List of series presentation keys. + + + + Gets the items result. + + The query. + QueryResult<BaseItem>. + + + + Checks if the file is ignored. + + The file. + The parent. + true if ignored, false otherwise. + + + + Queue a library scan. + + + This exists so plugins can trigger a library scan. + + + + + Add mblink file for a media path. + + The path to the virtualfolder. + The new virtualfolder. + + + + Service responsible for monitoring library filesystems for changes. + + + + + Starts this instance. + + + + + Stops this instance. + + + + + Reports the file system change beginning. + + The path. + + + + Reports the file system change complete. + + The path. + if set to true [refresh path]. + + + + Reports the file system changed. + + The path. + + + + An interface for tasks that run after the media library scan. + + + + + Runs the specified progress. + + The progress. + The cancellation token. + Task. + + + + Adds the parts. + + The providers. + + + + Gets the media streams. + + The item identifier. + IEnumerable<MediaStream>. + + + + Gets the media streams. + + The query. + IEnumerable<MediaStream>. + + + + Gets the media streams asynchronously. + + The item identifier. + The cancellation token. + IReadOnlyList<MediaStream>. + + + + Gets the media streams asynchronously. + + The query. + The cancellation token. + IReadOnlyList<MediaStream>. + + + + Gets the media attachments. + + The item identifier. + IEnumerable<MediaAttachment>. + + + + Gets the media attachments. + + The query. + IEnumerable<MediaAttachment>. + + + + Gets the media attachments asynchronously. + + The item identifier. + The cancellation token. + IReadOnlyList<MediaAttachment>. + + + + Gets the media attachments asynchronously. + + The query. + The cancellation token. + IReadOnlyList<MediaAttachment>. + + + + Gets the playback media sources. + + Item to use. + User to use for operation. + Option to allow media probe. + Option to enable path substitution. + CancellationToken to use for operation. + List of media sources wrapped in an awaitable task. + + + + Gets the static media sources. + + Item to use. + Option to enable path substitution. + User to use for operation. + List of media sources. + + + + Gets the static media source. + + Item to use. + Media source to get. + Live stream to use. + Option to enable path substitution. + CancellationToken to use for operation. + The static media source wrapped in an awaitable task. + + + + Opens the media source. + + The request. + The cancellation token. + Task<MediaSourceInfo>. + + + + Gets the live stream. + + The identifier. + The cancellation token. + Task<MediaSourceInfo>. + + + + Gets the live stream info. + + The identifier. + An instance of . + + + + Gets the live stream info using the stream's unique id. + + The unique identifier. + An instance of . + + + + Gets the media sources for an active recording. + + The . + The . + A task containing the 's for the recording. + + + + Closes the media source. + + The live stream identifier. + Task. + + + + Gets the media sources. + + The item. + The cancellation token. + Task<IEnumerable<MediaSourceInfo>>. + + + + Opens the media source. + + Token to use. + List of live streams. + CancellationToken to use for operation. + The media source wrapped as an awaitable task. + + + + Gets the save path. + + The item. + System.String. + + + + Interface IMetadataSaver. + + + + + Gets the name. + + The name. + + + + Determines whether [is enabled for] [the specified item]. + + The item. + Type of the update. + true if [is enabled for] [the specified item]; otherwise, false. + + + + Saves the specified item. + + The item. + The cancellation token. + The task object representing the asynchronous operation. + + + + Gets the instant mix from song. + + The item to use. + The user to use. + The options to use. + List of items. + + + + Gets the instant mix from artist. + + The artist to use. + The user to use. + The options to use. + List of items. + + + + Gets the instant mix from genre. + + The genres to use. + The user to use. + The options to use. + List of items. + + + + Gets or sets the path. + + The path. + + + + Gets or sets the item id. + + The item id. + + + + Interface ILibrarySearchEngine. + + + + + Gets the search hints. + + The query. + Task{IEnumerable{SearchHintInfo}}. + + + + Class ItemChangeEventArgs. + + + + + Gets or sets the item. + + The item. + + + + Gets or sets the item. + + The item. + + + + These are arguments relating to the file system that are collected once and then referred to + whenever needed. Primarily for entity resolution. + + + + + The _app paths. + + + + + Initializes a new instance of the class. + + The app paths. + The library manager. + + + + Gets or sets the file system children. + + The file system children. + + + + Gets or sets the parent. + + The parent. + + + + Gets or sets the file info. + + The file info. + + + + Gets the path. + + The path. + + + + Gets a value indicating whether this instance is directory. + + true if this instance is directory; otherwise, false. + + + + Gets a value indicating whether this instance is vf. + + true if this instance is vf; otherwise, false. + + + + Gets a value indicating whether this instance is physical root. + + true if this instance is physical root; otherwise, false. + + + + Gets or sets the additional locations. + + The additional locations. + + + + Gets the physical locations. + + The physical locations. + + + + Determines whether the specified is equal to this instance. + + The object to compare with the current object. + true if the specified is equal to this instance; otherwise, false. + + + + Adds the additional location. + + The path. + is null or empty. + + + + Gets the name of the file system entry by. + + The name. + FileSystemInfo. + is null or empty. + + + + Gets the file system entry by path. + + The path. + FileSystemInfo. + Throws if path is invalid. + + + + Determines whether [contains file system entry by name] [the specified name]. + + The name. + true if [contains file system entry by name] [the specified name]; otherwise, false. + + + + Gets the configured content type for the path. + + The configured content type. + + + + Gets the file system children that do not hit the ignore file check. + + The file system children that are not ignored. + + + + Returns a hash code for this instance. + + A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + + + + Equals the specified args. + + The args. + true if the arguments are the same, false otherwise. + + + + Interface IUserDataManager. + + + + + Occurs when [user data saved]. + + + + + Saves the user data. + + The user. + The item. + The user data. + The reason. + The cancellation token. + + + + Save the provided user data for the given user. + + The user. + The item. + The reason for updating the user data. + The reason. + + + + Gets the user data. + + User to use. + Item to use. + User data. + + + + Gets the user data dto. + + Item to use. + User to use. + User data dto. + + + + Gets the user data dto. + + Item to use. + Item dto to use. + User to use. + Dto options to use. + User data dto. + + + + Updates playstate for an item and returns true or false indicating if it was played to completion. + + Item to update. + Data to update. + New playstate. + True if playstate was updated. + + + + Interface IUserManager. + + + + + Occurs when a user is updated. + + + + + Gets the users. + + The users. + + + + Gets the user ids. + + The users ids. + + + + Initializes the user manager and ensures that a user exists. + + Awaitable task. + + + + Gets a user by Id. + + The id. + The user with the specified Id, or null if the user doesn't exist. + id is an empty Guid. + + + + Gets the name of the user by. + + The name. + User. + + + + Renames the user. + + The user. + The new name. + Task. + If user is null. + If the provided user doesn't exist. + + + + Updates the user. + + The user. + If user is null. + If the provided user doesn't exist. + A task representing the update of the user. + + + + Creates a user with the specified name. + + The name of the new user. + The created user. + is null or empty. + already exists. + + + + Deletes the specified user. + + The id of the user to be deleted. + A task representing the deletion of the user. + + + + Resets the password. + + The user. + Task. + + + + Changes the password. + + The user. + New password to use. + Awaitable task. + + + + Gets the user dto. + + The user. + The remote end point. + UserDto. + + + + Authenticates the user. + + The user. + The password to use. + Remove endpoint to use. + Specifies if a user session. + User wrapped in awaitable task. + + + + Starts the forgot password process. + + The entered username. + if set to true [is in network]. + ForgotPasswordResult. + + + + Redeems the password reset pin. + + The pin. + true if XXXX, false otherwise. + + + + This method updates the user's configuration. + This is only included as a stopgap until the new API, using this internally is not recommended. + Instead, modify the user object directly, then call . + + The user's Id. + The request containing the new user configuration. + A task representing the update. + + + + This method updates the user's policy. + This is only included as a stopgap until the new API, using this internally is not recommended. + Instead, modify the user object directly, then call . + + The user's Id. + The request containing the new user policy. + A task representing the update. + + + + Clears the user's profile image. + + The user. + A task representing the clearing of the profile image. + + + + Gets user views. + + Query to use. + Set of folders. + + + + Gets user sub views. + + Parent to use. + Type to use. + Localization key to use. + Sort to use. + User view. + + + + Gets latest items. + + Query to use. + Options to use. + Set of items. + + + + Gets the for the specified type. + + The . + The type to get the for. + The for the specified type or null. + + + + Holds information about a playback progress event. + + + + + An event that occurs when playback is started. + + + + + Gets or sets a value indicating whether [played to completion]. + + true if [played to completion]; otherwise, false. + + + + Class SearchHintInfo. + + + + + Gets or sets the item. + + The item. + + + + Gets or sets the matched term. + + The matched term. + + + + Class TVUtils. + + + + + Gets the air days. + + The day. + List{DayOfWeek}. + + + + Class UserDataSaveEventArgs. + + + + + Gets or sets the user id. + + The user id. + + + + Gets or sets the save reason. + + The save reason. + + + + Gets or sets the user data. + + The user data. + + + + Gets or sets the item. + + The item. + + + + Class ChannelInfo. + + + + + Gets or sets the name. + + The name. + + + + Gets or sets the number. + + The number. + + + + Gets or sets the Id. + + The id of the channel. + + + + Gets or sets the tuner host identifier. + + The tuner host identifier. + + + + Gets or sets the type of the channel. + + The type of the channel. + + + + Gets or sets the group of the channel. + + The group of the channel. + + + + Gets or sets the image path if it can be accessed directly from the file system. + + The image path. + + + + Gets or sets the image url if it can be downloaded. + + The image URL. + + + + Gets or sets a value indicating whether this instance has image. + + null if [has image] contains no value, true if [has image]; otherwise, false. + + + + Gets or sets a value indicating whether this instance is favorite. + + null if [is favorite] contains no value, true if [is favorite]; otherwise, false. + + + + Service responsible for managing the Live TV guide. + + + + + Gets the guide information. + + The . + + + + Refresh the guide. + + The to use. + The to use. + Task representing the refresh operation. + + + + Service responsible for managing s and mapping + their channels to channels provided by s. + + + + + Saves the listing provider. + + The listing provider information. + A value indicating whether to validate login. + A value indicating whether to validate listings.. + Task. + + + + Deletes the listing provider. + + The listing provider's id. + + + + Gets the lineups. + + Type of the provider. + The provider identifier. + The country. + The location. + The available lineups. + + + + Gets the programs for a provided channel. + + The channel to retrieve programs for. + The earliest date to retrieve programs for. + The latest date to retrieve programs for. + The to use. + The available programs. + + + + Adds metadata from the s to the provided channels. + + The channels. + A value indicating whether to use the EPG channel cache. + The to use. + A task representing the metadata population. + + + + Gets the channel mapping options for a provider. + + The id of the provider to use. + The channel mapping options. + + + + Sets the channel mapping. + + The id of the provider for the mapping. + The tuner channel number. + The provider channel number. + The updated channel mapping. + + + + Manages all live tv services installed on the server. + + + + + Gets the services. + + The services. + + + + Gets the new timer defaults asynchronous. + + The cancellation token. + Task{TimerInfo}. + + + + Gets the new timer defaults. + + The program identifier. + The cancellation token. + Task{SeriesTimerInfoDto}. + + + + Cancels the timer. + + The identifier. + Task. + + + + Cancels the series timer. + + The identifier. + Task. + + + + Gets the timer. + + The identifier. + The cancellation token. + Task{TimerInfoDto}. + + + + Gets the series timer. + + The identifier. + The cancellation token. + Task{TimerInfoDto}. + + + + Gets the recordings. + + The query. + The options. + A recording. + + + + Gets the timers. + + The query. + The cancellation token. + Task{QueryResult{TimerInfoDto}}. + + + + Gets the series timers. + + The query. + The cancellation token. + Task{QueryResult{SeriesTimerInfoDto}}. + + + + Gets the program. + + The identifier. + The cancellation token. + The user. + Task{ProgramInfoDto}. + + + + Gets the programs. + + The query. + The options. + The cancellation token. + IEnumerable{ProgramInfo}. + + + + Updates the timer. + + The timer. + The cancellation token. + Task. + + + + Updates the timer. + + The timer. + The cancellation token. + Task. + + + + Creates the timer. + + The timer. + The cancellation token. + Task. + + + + Creates the series timer. + + The timer. + The cancellation token. + Task. + + + + Gets the recommended programs. + + The query. + The options. + The cancellation token. + Recommended programs. + + + + Gets the recommended programs internal. + + The query. + The options. + The cancellation token. + Recommended programs. + + + + Gets the live tv information. + + The cancellation token. + Task{LiveTvInfo}. + + + + Resets the tuner. + + The identifier. + The cancellation token. + Task. + + + + Gets the live tv folder. + + The cancellation token. + Live TV folder. + + + + Gets the enabled users. + + IEnumerable{User}. + + + + Gets the internal channels. + + The query. + The options. + The cancellation token. + Internal channels. + + + + Adds the information to program dto. + + The programs. + The fields. + The user. + Task. + + + + Adds the channel information. + + The items. + The options. + The user. + + + + Represents a single live tv back end (next pvr, media portal, etc). + + + + + Gets the name. + + The name. + + + + Gets the home page URL. + + The home page URL. + + + + Gets the channels async. + + The cancellation token. + Task{IEnumerable{ChannelInfo}}. + + + + Cancels the timer asynchronous. + + The timer identifier. + The cancellation token. + Task. + + + + Cancels the series timer asynchronous. + + The timer identifier. + The cancellation token. + Task. + + + + Creates the timer asynchronous. + + The information. + The cancellation token. + Task. + + + + Creates the series timer asynchronous. + + The information. + The cancellation token. + Task. + + + + Updates the timer asynchronous. + + The updated timer information. + The cancellation token. + Task. + + + + Updates the series timer asynchronous. + + The information. + The cancellation token. + Task. + + + + Gets the recordings asynchronous. + + The cancellation token. + Task{IEnumerable{RecordingInfo}}. + + + + Gets the new timer defaults asynchronous. + + The cancellation token. + The program. + Task{SeriesTimerInfo}. + + + + Gets the series timers asynchronous. + + The cancellation token. + Task{IEnumerable{SeriesTimerInfo}}. + + + + Gets the programs asynchronous. + + The channel identifier. + The start date UTC. + The end date UTC. + The cancellation token. + Task{IEnumerable{ProgramInfo}}. + + + + Gets the channel stream. + + The channel identifier. + The stream identifier. + The cancellation token. + Task{Stream}. + + + + Gets the channel stream media sources. + + The channel identifier. + The cancellation token. + Task<List<MediaSourceInfo>>. + + + + Closes the live stream. + + The identifier. + The cancellation token. + Task. + + + + Resets the tuner. + + The identifier. + The cancellation token. + Task. + + + + Creates the timer asynchronous. + + The information. + The cancellation token. + Task. + + + + Creates the series timer asynchronous. + + The information. + The cancellation token. + Task. + + + + Service responsible for managing LiveTV recordings. + + + + + Gets the path for the provided timer id. + + The timer id. + The recording path, or null if none exists. + + + + Gets the information for an active recording. + + The recording path. + The , or null if none exists. + + + + Gets the recording folders. + + The for each recording folder. + + + + Ensures that the recording folders all exist, and removes unused folders. + + Task. + + + + Cancels the recording with the provided timer id, if one is active. + + The timer id. + The timer. + + + + Records a stream. + + The recording info. + The channel associated with the recording timer. + The time to stop recording. + Task representing the recording process. + + + + Gets the name. + + The name. + + + + Gets the type. + + The type. + + + + Gets the channels. + + Option to enable using cache. + The CancellationToken for this operation. + Task<IEnumerable<ChannelInfo>>. + + + + Gets the channel stream. + + The channel identifier. + The stream identifier. + The current live streams. + The cancellation token to cancel operation. + Live stream wrapped in a task. + + + + Gets the channel stream media sources. + + The channel identifier. + The cancellation token. + Task<List<MediaSourceInfo>>. + + + + Validates the specified information. + + The information. + Task. + + + + Service responsible for managing the s. + + + + + Gets the available s. + + + + + Gets the s for the available s. + + The s. + + + + Saves the tuner host. + + Turner host to save. + Option to specify that data source has changed. + Tuner host information wrapped in a task. + + + + Discovers the available tuners. + + A value indicating whether to only return new devices. + The s. + + + + Scans for tuner devices that have changed URLs. + + The to use. + A task that represents the scanning operation. + + + + Gets or sets the number. + + The number. + + + + Gets or sets the type of the channel. + + The type of the channel. + + + + Gets or sets a value indicating whether this instance is sports. + + true if this instance is sports; otherwise, false. + + + + Gets or sets a value indicating whether this instance is series. + + true if this instance is series; otherwise, false. + + + + Gets or sets a value indicating whether this instance is news. + + true if this instance is news; otherwise, false. + + + + Gets a value indicating whether this instance is kids. + + true if this instance is kids; otherwise, false. + + + + Gets or sets the episode title. + + The episode title. + + + + Class LiveTvConflictException. + + + + + Gets or sets start date of the program, in UTC. + + + + + Gets or sets a value indicating whether this instance is repeat. + + true if this instance is repeat; otherwise, false. + + + + Gets or sets the episode title. + + The episode title. + + + + Gets or sets a value indicating whether this instance is movie. + + true if this instance is movie; otherwise, false. + + + + Gets a value indicating whether this instance is sports. + + true if this instance is sports; otherwise, false. + + + + Gets or sets a value indicating whether this instance is series. + + true if this instance is series; otherwise, false. + + + + Gets a value indicating whether this instance is live. + + true if this instance is live; otherwise, false. + + + + Gets a value indicating whether this instance is news. + + true if this instance is news; otherwise, false. + + + + Gets a value indicating whether this instance is kids. + + true if this instance is kids; otherwise, false. + + + + Gets a value indicating whether this instance is premiere. + + true if this instance is premiere; otherwise, false. + + + + Gets the folder containing the item. + If the item is a folder, it returns the folder itself. + + The containing folder path. + + + + Gets or sets the id of the program. + + + + + Gets or sets the channel identifier. + + The channel identifier. + + + + Gets or sets the name of the program. + + + + + Gets or sets the official rating. + + The official rating. + + + + Gets or sets the overview. + + The overview. + + + + Gets or sets the short overview. + + The short overview. + + + + Gets or sets the start date of the program, in UTC. + + + + + Gets or sets the end date of the program, in UTC. + + + + + Gets or sets the genre of the program. + + + + + Gets or sets the original air date. + + The original air date. + + + + Gets or sets a value indicating whether this instance is hd. + + true if this instance is hd; otherwise, false. + + + + Gets or sets a value indicating whether this instance is 3d. + + + + + Gets or sets the audio. + + The audio. + + + + Gets or sets the community rating. + + The community rating. + + + + Gets or sets a value indicating whether this instance is repeat. + + true if this instance is repeat; otherwise, false. + + + + Gets or sets the episode title. + + The episode title. + + + + Gets or sets the image path if it can be accessed directly from the file system. + + The image path. + + + + Gets or sets the image url if it can be downloaded. + + The image URL. + + + + Gets or sets a value indicating whether this instance has image. + + null if [has image] contains no value, true if [has image]; otherwise, false. + + + + Gets or sets a value indicating whether this instance is movie. + + true if this instance is movie; otherwise, false. + + + + Gets or sets a value indicating whether this instance is sports. + + true if this instance is sports; otherwise, false. + + + + Gets or sets a value indicating whether this instance is series. + + true if this instance is series; otherwise, false. + + + + Gets or sets a value indicating whether this instance is live. + + true if this instance is live; otherwise, false. + + + + Gets or sets a value indicating whether this instance is news. + + true if this instance is news; otherwise, false. + + + + Gets or sets a value indicating whether this instance is kids. + + true if this instance is kids; otherwise, false. + + + + Gets or sets a value indicating whether this instance is premiere. + + true if this instance is premiere; otherwise, false. + + + + Gets or sets the production year. + + The production year. + + + + Gets or sets the home page URL. + + The home page URL. + + + + Gets or sets the series identifier. + + The series identifier. + + + + Gets or sets the show identifier. + + The show identifier. + + + + Gets or sets the season number. + + The season number. + + + + Gets or sets the episode number. + + The episode number. + + + + Gets or sets the etag. + + The etag. + + + + Gets or sets the id of the recording. + + + + + Gets or sets the channelId of the recording. + + + + + Gets or sets the program identifier. + + The program identifier. + + + + Gets or sets the name of the recording. + + + + + Gets or sets the service name. + + + + + Gets or sets the description of the recording. + + + + + Gets or sets the start date of the recording, in UTC. + + + + + Gets or sets the end date of the recording, in UTC. + + + + + Gets or sets a value indicating whether [record any time]. + + true if [record any time]; otherwise, false. + + + + Gets or sets a value indicating whether [record any channel]. + + true if [record any channel]; otherwise, false. + + + + Gets or sets a value indicating whether [record new only]. + + true if [record new only]; otherwise, false. + + + + Gets or sets the days. + + The days. + + + + Gets or sets the priority. + + The priority. + + + + Gets or sets the pre padding seconds. + + The pre padding seconds. + + + + Gets or sets the post padding seconds. + + The post padding seconds. + + + + Gets or sets a value indicating whether this instance is pre padding required. + + true if this instance is pre padding required; otherwise, false. + + + + Gets or sets a value indicating whether this instance is post padding required. + + true if this instance is post padding required; otherwise, false. + + + + Gets or sets the series identifier. + + The series identifier. + + + + Gets or sets the id of the recording. + + + + + Gets or sets the series timer identifier. + + + + + Gets or sets the channelId of the recording. + + + + + Gets or sets the program identifier. + + The program identifier. + + + + Gets or sets the name of the recording. + + + + + Gets or sets the description of the recording. + + + + + Gets or sets the start date of the recording, in UTC. + + + + + Gets or sets the end date of the recording, in UTC. + + + + + Gets or sets the status. + + The status. + + + + Gets or sets the pre padding seconds. + + The pre padding seconds. + + + + Gets or sets the post padding seconds. + + The post padding seconds. + + + + Gets or sets a value indicating whether this instance is pre padding required. + + true if this instance is pre padding required; otherwise, false. + + + + Gets or sets a value indicating whether this instance is post padding required. + + true if this instance is post padding required; otherwise, false. + + + + Gets or sets the priority. + + The priority. + + + + Gets or sets the episode number. + + The episode number. + + + + Gets a value indicating whether this instance is live. + + true if this instance is live; otherwise, false. + + + + Interface ILyricManager. + + + + + Occurs when a lyric download fails. + + + + + Search for lyrics for the specified song. + + The song. + Whether the request is automated. + CancellationToken to use for the operation. + The list of lyrics. + + + + Search for lyrics. + + The search request. + CancellationToken to use for the operation. + The list of lyrics. + + + + Download the lyrics. + + The audio. + The remote lyric id. + CancellationToken to use for the operation. + The downloaded lyrics. + + + + Download the lyrics. + + The audio. + The library options to use. + The remote lyric id. + CancellationToken to use for the operation. + The downloaded lyrics. + + + + Saves new lyrics. + + The audio file the lyrics belong to. + The lyrics format. + The lyrics. + A representing the asynchronous operation. + + + + Saves new lyrics. + + The audio file the lyrics belong to. + The lyrics format. + The lyrics. + A representing the asynchronous operation. + + + + Get the remote lyrics. + + The remote lyrics id. + CancellationToken to use for the operation. + The lyric response. + + + + Deletes the lyrics. + + The audio file to remove lyrics from. + A representing the asynchronous operation. + + + + Get the list of lyric providers. + + The item. + Lyric providers. + + + + Get the existing lyric for the audio. + + The audio item. + The cancellation token. + The parsed lyric model. + + + + Interface ILyricParser. + + + + + Gets a value indicating the provider name. + + + + + Gets the priority. + + The priority. + + + + Parses the raw lyrics into a response. + + The raw lyrics content. + The parsed lyrics or null if invalid. + + + + Interface ILyricsProvider. + + + + + Gets the provider name. + + + + + Search for lyrics. + + The search request. + The cancellation token. + The list of remote lyrics. + + + + Get the lyrics. + + The remote lyric id. + The cancellation token. + The lyric response. + + + + An event that occurs when subtitle downloading fails. + + + + + Gets or sets the item. + + + + + Gets or sets the provider. + + + + + Gets or sets the exception. + + + + + Gets or sets the id. + + The id. + + + + Gets or sets the audio codec. + + The audio codec. + + + + Gets or sets the audio sample rate. + + The audio sample rate. + + + + Gets or sets the audio bit rate. + + The audio bit rate. + + + + Gets or sets the audio channels. + + The audio channels. + + + + Gets or sets the profile. + + The profile. + + + + Gets or sets the video range type. + + The video range type. + + + + Gets or sets the level. + + The level. + + + + Gets or sets the codec tag. + + The codec tag. + + + + Gets or sets the framerate. + + The framerate. + + + + Gets or sets the start time ticks. + + The start time ticks. + + + + Gets or sets the width. + + The width. + + + + Gets or sets the height. + + The height. + + + + Gets or sets the width of the max. + + The width of the max. + + + + Gets or sets the height of the max. + + The height of the max. + + + + Gets or sets the video bit rate. + + The video bit rate. + + + + Gets or sets the index of the subtitle stream. + + The index of the subtitle stream. + + + + Gets or sets the video codec. + + The video codec. + + + + Gets or sets the index of the audio stream. + + The index of the audio stream. + + + + Gets or sets the index of the video stream. + + The index of the video stream. + + + + Enum BitStreamFilterOptionType. + + + + + hevc_metadata bsf with remove_dovi option. + + + + + hevc_metadata bsf with remove_hdr10plus option. + + + + + av1_metadata bsf with remove_dovi option. + + + + + av1_metadata bsf with remove_hdr10plus option. + + + + + dovi_rpu bsf with strip option. + + + + + Describes the downmix algorithms capabilities. + + + + + The filter string of the DownMixStereoAlgorithms. + The index is the tuple of (algorithm, layout). + + + + + Get the audio channel layout string from the audio stream + If the input audio string does not have a valid layout string, guess from channel count. + + The audio stream to get layout. + Channel Layout string. + + + + The codec validation regex. + This regular expression matches strings that consist of alphanumeric characters, hyphens, + periods, underscores, commas, and vertical bars, with a length between 0 and 40 characters. + This should matches all common valid codecs. + + + + + The level validation regex. + This regular expression matches strings representing a double. + + + + + Pattern:
+ \s+
+ Explanation:
+ + ○ Match a whitespace character atomically at least once.
+
+
+
+ + + Gets the name of the output video codec. + + Encoding state. + Encoding options. + Encoder string. + + + + Gets the user agent param. + + The state. + System.String. + + + + Gets the referer param. + + The state. + System.String. + + + + Gets decoder from a codec. + + Codec to use. + Decoder string. + + + + Infers the audio codec based on the url. + + Container to use. + Codec string. + + + + Infers the video codec. + + The URL. + System.Nullable{VideoCodecs}. + + + + Gets the audio encoder. + + The state. + System.String. + + + + Gets the input video hwaccel argument. + + Encoding state. + Encoding options. + Input video hwaccel arguments. + + + + Gets the input argument. + + Encoding state. + Encoding options. + Segment Container. + Input arguments. + + + + Determines whether the specified stream is H264. + + The stream. + true if the specified stream is H264; otherwise, false. + + + + Check if dynamic HDR metadata should be removed during stream copy. + Please note this check assumes the range check has already been done + and trivial fallbacks like HDR10+ to HDR10, DOVIWithHDR10 to HDR10 is already checked. + + + + + Gets the text subtitle param. + + The state. + Enable alpha processing. + Enable sub2video mode. + System.String. + + + + Gets the video bitrate to specify on the command line. + + Encoding state. + Video encoder to use. + Encoding options. + Default present to use for encoding. + Video bitrate. + + + + Gets the number of audio channels to specify on the command line. + + The state. + The audio stream. + The output audio codec. + System.Nullable{System.Int32}. + + + + Enforces the resolution limit. + + The state. + + + + Gets the fast seek command line parameter. + + The state. + The options. + Segment Container. + System.String. + The fast seek command line parameter. + + + + Gets the map args. + + The state. + System.String. + + + + Gets the negative map args by filters. + + The state. + The videoProcessFilters. + System.String. + + + + Determines which stream will be used for playback. + + All stream. + Index of the desired. + The type. + if set to true [return first if no index]. + MediaStream. + + + + Gets the parameter of software filter chain. + + Encoding state. + Encoding options. + Video encoder to use. + The tuple contains three lists: main, sub and overlay filters. + + + + Gets the parameter of Nvidia NVENC filter chain. + + Encoding state. + Encoding options. + Video encoder to use. + The tuple contains three lists: main, sub and overlay filters. + + + + Gets the parameter of AMD AMF filter chain. + + Encoding state. + Encoding options. + Video encoder to use. + The tuple contains three lists: main, sub and overlay filters. + + + + Gets the parameter of Intel QSV filter chain. + + Encoding state. + Encoding options. + Video encoder to use. + The tuple contains three lists: main, sub and overlay filters. + + + + Gets the parameter of Intel/AMD VAAPI filter chain. + + Encoding state. + Encoding options. + Video encoder to use. + The tuple contains three lists: main, sub and overlay filters. + + + + Gets the parameter of Apple VideoToolBox filter chain. + + Encoding state. + Encoding options. + Video encoder to use. + The tuple contains three lists: main, sub and overlay filters. + + + + Gets the parameter of Rockchip RKMPP/RKRGA filter chain. + + Encoding state. + Encoding options. + Video encoder to use. + The tuple contains three lists: main, sub and overlay filters. + + + + Gets the parameter of video processing filters. + + Encoding state. + Encoding options. + Video codec to use. + The video processing filters parameter. + + + + Gets the ffmpeg option string for the hardware accelerated video decoder. + + The encoding job info. + The encoding options. + The option string or null if none available. + + + + Gets a hw decoder name. + + Encoding options. + Decoder prefix. + Decoder suffix. + Video codec to use. + Video color bit depth. + Hardware decoder name. + + + + Gets a hwaccel type to use as a hardware decoder depending on the system. + + Encoding state. + Encoding options. + Video codec to use. + Video color bit depth. + Specifies if output hw surface. + Hardware accelerator type. + + + + Gets the number of threads. + + Encoding state. + Encoding options. + Video codec to use. + Number of threads. + + + + Attaches media source information to the encoding job state. + + The encoding job state. + The encoding options. + The media source information. + The requested URL. + + + + Gets the video sync option based on the encoder version. + + The video sync parameter. + The encoder version. + The video sync option string. + + + + Gets the target video level. + + + + + Gets the target video bit depth. + + + + + Gets the target reference frames. + + The target reference frames. + + + + Gets the target framerate. + + + + + Gets the target packet length. + + + + + Gets the target video profile. + + + + + Gets the target video range type. + + + + + Enum FilterOptionType. + + + + + The scale_cuda_format. + + + + + The tonemap_cuda_name. + + + + + The tonemap_opencl_bt2390. + + + + + The overlay_opencl_framesync. + + + + + The overlay_vaapi_framesync. + + + + + The overlay_vulkan_framesync. + + + + + The transpose_opencl_reversal. + + + + + The overlay_opencl_alpha_format. + + + + + The overlay_cuda_alpha_format. + + + + + Gets the path to the attachment file. + + The . + The media source id. + The attachment index. + The cancellation token. + The async task. + + + + Gets the path to the attachment file. + + The input file path. + The source id. + The cancellation token. + The async task. + + + + Interface IMediaEncoder. + + + + + Gets the encoder path. + + The encoder path. + + + + Gets the probe path. + + The probe path. + + + + Gets the version of encoder. + + The version of encoder. + + + + Gets a value indicating whether p key pausing is supported. + + true if p key pausing is supported, false otherwise. + + + + Gets a value indicating whether the configured Vaapi device is from AMD(radeonsi/r600 Mesa driver). + + true if the Vaapi device is an AMD(radeonsi/r600 Mesa driver) GPU, false otherwise. + + + + Gets a value indicating whether the configured Vaapi device is from Intel(iHD driver). + + true if the Vaapi device is an Intel(iHD driver) GPU, false otherwise. + + + + Gets a value indicating whether the configured Vaapi device is from Intel(legacy i965 driver). + + true if the Vaapi device is an Intel(legacy i965 driver) GPU, false otherwise. + + + + Gets a value indicating whether the configured Vaapi device supports vulkan drm format modifier. + + true if the Vaapi device supports vulkan drm format modifier, false otherwise. + + + + Gets a value indicating whether the configured Vaapi device supports vulkan drm interop via dma-buf. + + true if the Vaapi device supports vulkan drm interop, false otherwise. + + + + Gets a value indicating whether av1 decoding is available via VideoToolbox. + + true if the av1 is available via VideoToolbox, false otherwise. + + + + Whether given encoder codec is supported. + + The encoder. + true if XXXX, false otherwise. + + + + Whether given decoder codec is supported. + + The decoder. + true if XXXX, false otherwise. + + + + Whether given hardware acceleration type is supported. + + The hwaccel. + true if XXXX, false otherwise. + + + + Whether given filter is supported. + + The filter. + true if the filter is supported, false otherwise. + + + + Whether filter is supported with the given option. + + The option. + true if the filter is supported, false otherwise. + + + + Whether the bitstream filter is supported with the given option. + + The option. + true if the bitstream filter is supported, false otherwise. + + + + Extracts the audio image. + + The path. + Index of the image stream. + The cancellation token. + Task{Stream}. + + + + Extracts the video image. + + Input file. + Video container type. + Media source information. + Media stream information. + Video 3D format. + Time offset. + CancellationToken to use for operation. + Location of video image. + + + + Extracts the video image. + + Input file. + Video container type. + Media source information. + Media stream information. + Index of the stream to extract from. + The format of the file to write. + CancellationToken to use for operation. + Location of video image. + + + + Extracts the video images on interval. + + Input file. + Video container type. + Media source information. + Media stream information. + The maximum width. + The interval. + Allow for hardware acceleration. + Use hardware mjpeg encoder. + The input/output thread count for ffmpeg. + The qscale value for ffmpeg. + The process priority for the ffmpeg process. + Whether to only extract key frames. + EncodingHelper instance. + The cancellation token. + Directory where images where extracted. A given image made before another will always be named with a lower number. + + + + Gets the media info. + + The request. + The cancellation token. + Task. + + + + Gets the input argument. + + The input file. + The mediaSource. + System.String. + + + + Gets the input argument. + + The input files. + The mediaSource. + System.String. + + + + Gets the input argument for an external subtitle file. + + The input file. + System.String. + + + + Gets the time parameter. + + The ticks. + System.String. + + + + Escapes the subtitle filter path. + + The path. + System.String. + + + + Sets the path to find FFmpeg. + + bool indicates whether a valid ffmpeg is found. + + + + Gets the primary playlist of .vob files. + + The to the .vob files. + The title number to start with. + A playlist. + + + + Gets the primary playlist of .m2ts files. + + The to the .m2ts files. + A playlist. + + + + Gets the input path argument from . + + The . + The input path argument. + + + + Gets the input path argument. + + The item path. + The . + The input path argument. + + + + Generates a FFmpeg concat config for the source. + + The . + The path the config should be written to. + + + + Gets the subtitles. + + Item to use. + Media source. + Subtitle stream to use. + Output format to use. + Start time. + End time. + Option to preserve original timestamps. + The cancellation token for the operation. + Task{Stream}. + + + + Gets the subtitle language encoding parameter. + + The subtitle stream. + The language. + The media source. + The cancellation token. + System.String. + + + + Gets the path to a subtitle file. + + The subtitle stream. + The media source. + The cancellation token. + System.String. + + + + Extracts all extractable subtitles (text and pgs). + + The mediaSource. + The cancellation token. + Task. + + + + A service for managing media transcoding. + + + + + Get transcoding job. + + Playback session id. + The transcoding job. + + + + Get transcoding job. + + Path to the transcoding file. + The . + The transcoding job. + + + + Ping transcoding job. + + Play session id. + Is user paused. + Play session id is null. + + + + Kills the single transcoding job. + + The device id. + The play session identifier. + The delete files. + Task. + + + + Report the transcoding progress to the session manager. + + The of which the progress will be reported. + The of the current transcoding job. + The current transcoding position. + The framerate of the transcoding job. + The completion percentage of the transcode. + The number of bytes transcoded. + The bitrate of the transcoding job. + + + + Starts FFMpeg. + + The state. + The output path. + The command line arguments for FFmpeg. + The user id. + The . + The cancellation token source. + The working directory. + Task. + + + + Called when [transcode begin request]. + + The path. + The type. + The . + + + + Called when [transcode end]. + + The transcode job. + + + + Transcoding lock. + + The output path of the transcoded file. + The cancellation token. + An . + + + + Class TranscodingJob. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + Gets or sets the play session identifier. + + + + + Gets or sets the live stream identifier. + + + + + Gets or sets a value indicating whether is live output. + + + + + Gets or sets the path. + + + + + Gets or sets path. + + + + + Gets or sets the type. + + + + + Gets or sets the process. + + + + + Gets or sets the active request count. + + + + + Gets or sets device id. + + + + + Gets or sets cancellation token source. + + + + + Gets or sets a value indicating whether has exited. + + + + + Gets or sets exit code. + + + + + Gets or sets a value indicating whether is user paused. + + + + + Gets or sets id. + + + + + Gets or sets framerate. + + + + + Gets or sets completion percentage. + + + + + Gets or sets bytes downloaded. + + + + + Gets or sets bytes transcoded. + + + + + Gets or sets bit rate. + + + + + Gets or sets transcoding position ticks. + + + + + Gets or sets download position ticks. + + + + + Gets or sets transcoding throttler. + + + + + Gets or sets transcoding segment cleaner. + + + + + Gets or sets last ping date. + + + + + Gets or sets ping timeout. + + + + + Stop kill timer. + + + + + Dispose kill timer. + + + + + Start kill timer. + + Callback action. + + + + Start kill timer. + + Callback action. + Callback interval. + + + + Change kill timer if started. + + + + + Stops the transcoding job. + + + + + + + + Enum TranscodingJobType. + + + + + The progressive. + + + + + The HLS. + + + + + The dash. + + + + + Transcoding segment cleaner. + + + + + Initializes a new instance of the class. + + Transcoding job dto. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + The segment length of this transcoding job. + + + + Start timer. + + + + + Stop cleaner. + + + + + Dispose cleaner. + + + + + Dispose cleaner. + + Disposing. + + + + Transcoding throttler. + + + + + Initializes a new instance of the class. + + Transcoding job dto. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Start timer. + + + + + Unpause transcoding. + + A . + + + + Stop throttler. + + A . + + + + Dispose throttler. + + + + + Dispose throttler. + + Disposing. + + + + Defines methods for interacting with media segments. + + + + + Uses all segment providers enabled for the 's library to get the Media Segments. + + The Item to evaluate. + The library options. + If set, will force to remove existing segments and replace it with new ones otherwise will check for existing segments and if found any that should not be deleted, stops. + The cancellation token. + A task that indicates the Operation is finished. + + + + Returns if this item supports media segments. + + The base Item to check. + True if supported otherwise false. + + + + Creates a new Media Segment associated with an Item. + + The segment to create. + The id of the Provider who created this segment. + The created Segment entity. + + + + Deletes a single media segment. + + The to delete. + a task. + + + + Deletes all media segments of an item. + + The to delete all segments for. + The cancellation token. + a task. + + + + Obtains all segments associated with the itemId. + + The . + filters all media segments of the given type to be included. If null all types are included. + The library options. + When set filters the segments to only return those that which providers are currently enabled on their library. + An enumerator of 's. + + + + Gets information about any media segments stored for the given itemId. + + The id of the . + True if there are any segments stored for the item, otherwise false. + TODO: this should be async but as the only caller BaseItem.GetVersionInfo isn't async, this is also not. Venson. + + + + Gets a list of all registered Segment Providers and their IDs. + + The media item that should be tested for providers. + A list of all providers for the tested item. + + + + Provides methods for Obtaining the Media Segments from an Item. + + + + + Gets the provider name. + + + + + Enumerates all Media Segments from an Media Item. + + Arguments to enumerate MediaSegments. + Abort token. + A list of all MediaSegments found from this provider. + + + + Should return support state for the given item. + + The base item to extract segments from. + True if item is supported, otherwise false. + + + + The request authorization info. + + + + + Gets the user identifier. + + The user identifier. + + + + Gets or sets the device identifier. + + The device identifier. + + + + Gets or sets the device. + + The device. + + + + Gets or sets the client. + + The client. + + + + Gets or sets the version. + + The version. + + + + Gets or sets the token. + + The token. + + + + Gets or sets a value indicating whether the authorization is from an api key. + + + + + Gets or sets the user making the request. + + + + + Gets or sets a value indicating whether the token is authenticated. + + + + + Gets a value indicating whether the request has a token. + + + + + Starts sending data over a web socket periodically when a message is received, and then stops when a corresponding stop message is received. + + The type of the T return data type. + The type of the T state type. + + + + The _active connections. + + + + + The logger. + + + + + Gets the type used for the messages sent to the client. + + The type. + + + + Gets the message type received from the client to start sending messages. + + The type. + + + + Gets the message type received from the client to stop sending messages. + + The type. + + + + Gets the data to send. + + Task{`1}. + + + + Gets the data to send for a specific connection. + + The connection. + Task{`1}. + + + + Processes the message. + + The message. + Task. + + + + + + + Starts sending messages over a web socket. + + The message. + + + + Stops sending messages over a web socket. + + The message. + + + + Disposes the connection. + + The connection. + + + + + + + IAuthorization context. + + + + + Gets the authorization information. + + The request context. + A task containing the authorization info. + + + + Gets the authorization information. + + The request context. + A containing the authorization info. + + + + IAuthService. + + + + + Authenticate request. + + The request. + Authorization information. Null if unauthenticated. + + + + Interface for WebSocket connections. + + + + + Occurs when [closed]. + + + + + Gets the last activity date. + + The last activity date. + + + + Gets or sets the date of last Keepalive received. + + The date of last Keepalive received. + + + + Gets or sets the receive action. + + The receive action. + + + + Gets the state. + + The state. + + + + Gets the authorization information. + + + + + Gets the remote end point. + + The remote end point. + + + + Sends a message asynchronously. + + The message. + The cancellation token. + Task. + The message is null. + + + + Sends a message asynchronously. + + The type of websocket message data. + The message. + The cancellation token. + Task. + The message is null. + + + + Receives a message asynchronously. + + The cancellation token. + Task. + + + + Interface for listening to messages coming through a web socket connection. + + + + + Processes the message. + + The message. + Task. + + + + Processes a new web socket connection. + + An instance of the interface. + The current http context. + Task. + + + + Interface IHttpServer. + + + + + The HTTP request handler. + + The current HTTP context. + The task. + + + + The exception that is thrown when a user is authenticated, but not authorized to access a requested resource. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + The message that describes the error. + + + + Initializes a new instance of the class. + + The message that describes the error. + The exception that is the cause of the current exception, or a null reference if no inner exception is specified. + + + + Websocket message without data. + + + + + Gets or sets the type of the message. + TODO make this abstract and get only. + + + + + Gets or sets the server id. + + + + + Class WebSocketMessageInfo. + + + + + Gets or sets the connection. + + The connection. + + + + Class WebSocketMessage. + + The type of the data. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + The data to send. + + + + Gets or sets the data. + + + + + Interface representing that the websocket message is inbound. + + + + + Inbound websocket message. + + + + + Inbound websocket message with data. + + The data type. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + The data to send. + + + + Activity log entry start message. + Data is the timing data encoded as "$initialDelay,$interval" in ms. + + + + + Initializes a new instance of the class. + Data is the timing data encoded as "$initialDelay,$interval" in ms. + + The timing data encoded as "$initialDelay,$interval". + + + + + + + Activity log entry stop message. + + + + + + + + Keep alive websocket messages. + + + + + + + + Scheduled tasks info start message. + Data is the timing data encoded as "$initialDelay,$interval" in ms. + + + + + Initializes a new instance of the class. + + The timing data encoded as $initialDelay,$interval. + + + + + + + Scheduled tasks info stop message. + + + + + + + + Sessions start message. + Data is the timing data encoded as "$initialDelay,$interval" in ms. + + + + + Initializes a new instance of the class. + + The timing data encoded as $initialDelay,$interval. + + + + + + + Sessions stop message. + + + + + + + + Interface representing that the websocket message is outbound. + + + + + Outbound websocket message. + + + + + Gets or sets the message id. + + + + + Outbound websocket message with data. + + The data type. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + The data to send. + + + + Gets or sets the message id. + + + + + Activity log created message. + + + + + Initializes a new instance of the class. + + List of activity log entries. + + + + + + + Force keep alive websocket messages. + + + + + Initializes a new instance of the class. + + The timeout in seconds. + + + + + + + General command websocket message. + + + + + Initializes a new instance of the class. + + The general command. + + + + + + + Library changed message. + + + + + Initializes a new instance of the class. + + The library update info. + + + + + + + Keep alive websocket messages. + + + + + + + + Play command websocket message. + + + + + Initializes a new instance of the class. + + The play request. + + + + + + + Playstate message. + + + + + Initializes a new instance of the class. + + Playstate request data. + + + + + + + Plugin installation cancelled message. + + + + + Initializes a new instance of the class. + + Installation info. + + + + + + + Plugin installation completed message. + + + + + Initializes a new instance of the class. + + Installation info. + + + + + + + Plugin installation failed message. + + + + + Initializes a new instance of the class. + + Installation info. + + + + + + + Package installing message. + + + + + Initializes a new instance of the class. + + Installation info. + + + + + + + Plugin uninstalled message. + + + + + Initializes a new instance of the class. + + Plugin info. + + + + + + + Refresh progress message. + + + + + Initializes a new instance of the class. + + Refresh progress data. + + + + + + + Restart required. + + + + + + + + Scheduled task ended message. + + + + + Initializes a new instance of the class. + + Task result. + + + + + + + Scheduled tasks info message. + + + + + Initializes a new instance of the class. + + List of task infos. + + + + + + + Series timer cancelled message. + + + + + Initializes a new instance of the class. + + The timer event info. + + + + + + + Series timer created message. + + + + + Initializes a new instance of the class. + + timer event info. + + + + + + + Server restarting down message. + + + + + + + + Server shutting down message. + + + + + + + + Sessions message. + + + + + Initializes a new instance of the class. + + Session info. + + + + + + + Sync play command. + + + + + Initializes a new instance of the class. + + The send command. + + + + + + + Timer cancelled message. + + + + + Initializes a new instance of the class. + + Timer event info. + + + + + + + Timer created message. + + + + + Initializes a new instance of the class. + + Timer event info. + + + + + + + User data changed message. + + + + + Initializes a new instance of the class. + + The data change info. + + + + + + + User deleted message. + + + + + Initializes a new instance of the class. + + The user id. + + + + + + + User updated message. + + + + + Initializes a new instance of the class. + + The user dto. + + + + + + + Interface IChapterRepository. + + + + + Deletes the chapters. + + The item. + The cancellation token. + Task. + + + + Saves the chapters asynchronously. + + The item. + The set of chapters. + The cancellation token. + A task representing the asynchronous operation. + + + + Gets all chapters associated with the baseItem asynchronously. + + The BaseItems id. + The cancellation token. + A readonly list of chapter instances. + + + + Gets a single chapter of a BaseItem on a specific index asynchronously. + + The BaseItems id. + The index of that chapter. + The cancellation token. + A chapter instance. + + + + Provides an interface to implement an Item repository. + + + + + Deletes the item. + + The identifier to delete. + + + + Deletes the item asynchronously. + + The identifier to delete. + The cancellation token. + A task representing the async operation. + + + + Saves the items. + + The items. + The cancellation token. + + + + Saves the items asynchronously. + + The items. + The cancellation token. + A task representing the async operation. + + + + Reattaches the user data to the item. + + The item. + The cancellation token. + A task that represents the asynchronous reattachment operation. + + + + Retrieves the item. + + The id. + BaseItem. + + + + Retrieves the item asynchronously. + + The id. + The cancellation token. + A task representing the async operation. + + + + Gets the items. + + The query. + QueryResult<BaseItem>. + + + + Gets the items asynchronously. + + The query. + The cancellation token. + QueryResult<BaseItem>. + + + + Gets the item ids list. + + The query. + List<Guid>. + + + + Gets the item ids list asynchronously. + + The query. + The cancellation token. + List<Guid>. + + + + Gets the item list. + + The query. + List<BaseItem>. + + + + Gets the item list asynchronously. + + The query. + The cancellation token. + List<BaseItem>. + + + + Gets the item list. Used mainly by the Latest api endpoint. + + The query. + Collection Type. + List<BaseItem>. + + + + Gets the item list asynchronously. Used mainly by the Latest api endpoint. + + The query. + Collection Type. + The cancellation token. + A task representing the async operation. + + + + Gets the list of series presentation keys for next up. + + The query. + The minimum date for a series to have been most recently watched. + The list of keys. + + + + Gets the list of series presentation keys for next up asynchronously. + + The query. + The minimum date for a series to have been most recently watched. + The cancellation token. + A task representing the async operation. + + + + Updates the inherited values. + + + + + Gets the count of items asynchronously. + + The query. + The cancellation token. + The count. + + + + Gets the item counts asynchronously. + + The query. + The cancellation token. + The item counts. + + + + Checks if an item has been persisted to the database. + + The id to check. + True if the item exists, otherwise false. + + + + Gets a value indicating wherever all children of the requested Id has been played. + + The userdata to check against. + The Top id to check. + Whever the check should be done recursive. Warning expensive operation. + A value indicating whever all children has been played. + + + + Gets all artist matches from the db. + + The names of the artists. + A map of the artist name and the potential matches. + + + + Provides static lookup data for and for the domain. + + + + + Gets all serialisation target types for music related kinds. + + + + + Gets mapping for all BaseItemKinds and their expected serialization target. + + + + + Provides methods for accessing keyframe data. + + + + + Gets the keyframe data asynchronously. + + The item id. + The cancellation token. + The keyframe data. + + + + Saves the keyframe data. + + The item id. + The keyframe data. + The cancellation token. + The task object representing the asynchronous operation. + + + + Deletes the keyframe data. + + The item id. + The cancellation token. + The task object representing the asynchronous operation. + + + + Gets the media attachments asynchronously. + + The query. + The cancellation token. + IReadOnlyList{MediaAttachment}. + + + + Saves the media attachments asynchronously. + + The identifier. + The attachments. + The cancellation token. + A task representing the asynchronous operation. + + + + Provides methods for accessing MediaStreams. + + + + + Gets the media streams asynchronously. + + The query. + The cancellation token. + IReadOnlyList{MediaStream}. + + + + Saves the media streams asynchronously. + + The identifier. + The streams. + The cancellation token. + A task representing the asynchronous operation. + + + + Gets the people. + + The query. + The list of people matching the filter. + + + + Gets the people asynchronously. + + The query. + The cancellation token. + The list of people matching the filter. + + + + Updates the people. + + The item identifier. + The people. + + + + Updates the people asynchronously. + + The item identifier. + The people. + The cancellation token. + A task representing the asynchronous operation. + + + + Gets the people names. + + The query. + The list of people names matching the filter. + + + + Gets the people names asynchronously. + + The query. + The cancellation token. + The list of people names matching the filter. + + + + Gets or sets the index. + + The index. + + + + Gets or sets the item identifier. + + The item identifier. + + + + Gets or sets the type. + + The type. + + + + Gets or sets the index. + + The index. + + + + Gets or sets the item identifier. + + The item identifier. + + + + Gets the playlist. + + The playlist identifier. + The user identifier. + Playlist. + + + + Creates the playlist. + + The . + The created playlist. + + + + Updates a playlist. + + The . + Task. + + + + Gets all playlists a user has access to. + + The user identifier. + IEnumerable<Playlist>. + + + + Adds a share to the playlist. + + The . + Task. + + + + Removes a share from the playlist. + + The playlist identifier. + The user identifier. + The share. + Task. + + + + Adds to playlist. + + The playlist identifier. + The item ids. + Optional. 0-based index where to place the items or at the end if null. + The user identifier. + Task. + + + + Removes from playlist. + + The playlist identifier. + The entry ids. + Task. + + + + Gets the playlists folder. + + Folder. + + + + Gets the playlists folder for a user. + + The user identifier. + Folder. + + + + Moves the item. + + The playlist identifier. + The entry identifier. + The new index. + The calling user. + Task. + + + + Removed all playlists of a user. + If the playlist is shared, ownership is transferred. + + The user id. + Task. + + + + Saves a playlist. + + The playlist. + + + + Defines the . + + + This interface is only used for service registration and requires a parameterless constructor. + + + + + Registers the plugin's services with the service collection. + + The service collection. + The server application host. + + + + Gets or sets the album artist. + + The album artist. + + + + Gets or sets the artist provider ids. + + The artist provider ids. + + + + Fetches the metadata asynchronously. + + The item. + The . + The . + A fetching the . + + + + Gets the supported images. + + The item. + IEnumerable{ImageType}. + + + + Gets the image. + + The item. + The type. + The cancellation token. + Task{DynamicImageResponse}. + + + + Represents an identifier for an external provider. + + + + + Gets the display name of the provider associated with this ID type. + + + + + Gets the unique key to distinguish this provider/type pair. This should be unique across providers. + + + + + Gets the specific media type for this id. This is used to distinguish between the different + external id types for providers with multiple ids. + A null value indicates there is no specific media type associated with the external id, or this is the + default id for the external provider so there is no need to specify a type. + + + This can be used along with the to localize the external id on the client. + + + + + Determines whether this id supports a given item type. + + The item. + True if this item is supported, otherwise false. + + + + Interface to include related urls for an item. + + + + + Gets the external service name. + + + + + Get the list of external urls. + + The item to get external urls for. + The list of external urls. + + + + This is a marker interface that will cause a provider to run even if an item is locked from changes. + + + + + Determines whether the specified item has changed. + + The item. + The directory service. + true if the specified item has changed; otherwise, false. + + + + Interface IHasOrder. + + + + + Gets the order. + + The order. + + + + Interface IImageProvider. + + + + + Gets the name. + + The name. + + + + Supports the specified item. + + The item. + true if the provider supports the item. + + + + This is just a marker interface. + + + + + Gets the metadata. + + The information. + The directory service. + The cancellation token. + Task{MetadataResult{0}}. + + + + Gets or sets a value indicating whether old metadata should be removed if it isn't replaced. + + + + + Marker interface. + + + + + Gets the name. + + The name. + + + + Gets the order. + + The order. + + + + Determines whether this instance can refresh the specified item. + + The item. + true if this instance can refresh the specified item. + + + + Determines whether this instance primarily targets the specified type. + + The type. + true if this instance primarily targets the specified type. + + + + Refreshes the metadata. + + The item. + The options. + The cancellation token. + Task. + + + + Interface IProviderManager. + + + + + Queues the refresh. + + Item ID. + MetadataRefreshOptions for operation. + RefreshPriority for operation. + + + + Refreshes the full item. + + The item. + The options. + The cancellation token. + Task. + + + + Refreshes the metadata. + + The item. + The options. + The cancellation token. + Task. + + + + Saves the image. + + The item. + The URL. + The type. + Index of the image. + The cancellation token. + Task. + + + + Saves the image. + + The item. + The source. + Type of the MIME. + The type. + Index of the image. + The cancellation token. + Task. + + + + Saves the image by giving the image path on filesystem. + This method will remove the image on the source path after saving it to the destination. + + Image to save. + Source of image. + Mime type image. + Type of image. + Index of image. + Option to save locally. + CancellationToken to use with operation. + Task. + + + + Adds the metadata providers. + + Image providers to use. + Metadata services to use. + Metadata providers to use. + Metadata savers to use. + External IDs to use. + The list of external url providers. + + + + Gets the available remote images. + + The item. + The query. + The cancellation token. + Task{IEnumerable{RemoteImageInfo}}. + + + + Gets the image providers. + + The item. + IEnumerable{ImageProviderInfo}. + + + + Gets the image providers for the provided item. + + The item. + The image refresh options. + The image providers for the item. + + + + Gets the metadata providers for the provided item. + + The item. + The library options. + The type of metadata provider. + The metadata providers. + + + + Gets the metadata savers for the provided item. + + The item. + The library options. + The metadata savers. + + + + Gets all metadata plugins. + + IEnumerable{MetadataPlugin}. + + + + Gets the external urls. + + The item. + IEnumerable{ExternalUrl}. + + + + Gets the external identifier infos. + + The item. + IEnumerable{ExternalIdInfo}. + + + + Saves the metadata. + + The item. + Type of the update. + The task object representing the asynchronous operation. + + + + Saves the metadata. + + The item. + Type of the update. + The metadata savers. + The task object representing the asynchronous operation. + + + + Gets the metadata options. + + The item. + MetadataOptions. + + + + Gets the remote search results. + + The type of the t item type. + The type of the t lookup type. + The search information. + The cancellation token. + Task{IEnumerable{SearchResult{``1}}}. + + + + Interface IImageProvider. + + + + + Gets the supported images. + + The item. + IEnumerable{ImageType}. + + + + Gets the images. + + The item. + The cancellation token. + Task{IEnumerable{RemoteImageInfo}}. + + + + Gets the image response. + + The URL. + The cancellation token. + Task{HttpResponseInfo}. + + + + Interface IRemoteMetadataProvider. + + + + + Interface IRemoteMetadataProvider. + + The type of . + The type of . + + + + Gets the metadata for a specific LookupInfoType. + + The LookupInfoType to get metadata for. + The . + A task returning a MetadataResult for the specific LookupInfoType. + + + + Interface IRemoteMetadataProvider. + + The type of . + + + + Gets the list of for a specific LookupInfoType. + + The LookupInfoType to search for. + The . + A task returning RemoteSearchResults for the searchInfo. + + + + Gets the image response. + + The URL. + The cancellation token. + Task{HttpResponseInfo}. + + + + Gets or sets the name. + + The name. + + + + Gets or sets the original title. + + The original title of the item. + + + + Gets or sets the path. + + The path. + + + + Gets or sets the metadata language. + + The metadata language. + + + + Gets or sets the metadata country code. + + The metadata country code. + + + + Gets or sets the provider ids. + + The provider ids. + + + + Gets or sets the year. + + The year. + + + + The none. + + + + + The validation only. + + + + + Providers will be executed based on default rules. + + + + + All providers will be executed to search for new metadata. + + + + + Gets or sets a value indicating whether all existing data should be overwritten with new data from providers + when paired with MetadataRefreshMode=FullRefresh. + + + + + Gets or sets a value indicating whether all existing trickplay images should be overwritten + when paired with MetadataRefreshMode=FullRefresh. + + + + + Not only does this clear, but initializes the list so that services can differentiate between a null list and zero people. + + + + + Provider refresh priority. + + + + + High priority. + + + + + Normal priority. + + + + + Low priority. + + + + + Gets or sets the provider name to search within if set. + + + + + Gets or sets a value indicating whether disabled providers should be included. + + true if disabled providers should be included. + + + + Enum VideoContentType. + + + + + The episode. + + + + + The movie. + + + + + Quick connect standard interface. + + + + + Gets a value indicating whether quick connect is enabled or not. + + + + + Initiates a new quick connect request. + + The initiator authorization info. + A quick connect result with tokens to proceed or throws an exception if not active. + + + + Checks the status of an individual request. + + Unique secret identifier of the request. + Quick connect result. + + + + Authorizes a quick connect request to connect as the calling user. + + User id. + Identifying code for the request. + A boolean indicating if the authorization completed successfully. + + + + Gets the authorized request for the secret. + + The secret. + The authentication result. + + + + Interface IItemResolver. + + + + + Gets the priority. + + The priority. + + + + Resolves the path. + + The args. + BaseItem. + + + + Provides a base "rule" that anyone can use to have paths ignored by the resolver. + + + + + Checks whether or not the file should be ignored. + + The file information. + The parent BaseItem. + True if the file should be ignored. + + + + Class ItemResolver. + + The type of BaseItem. + + + + Gets the priority. + + The priority. + + + + Resolves the specified args. + + The args. + `0. + + + + Sets initial values on the newly resolved item. + + The item. + The args. + + + + Resolves the path. + + The args. + BaseItem. + + + + Enum ResolverPriority. + + + + + The highest priority. Used by plugins to bypass the default server resolvers. + + + + + The first. + + + + + The second. + + + + + The third. + + + + + The Fourth. + + + + + The Fifth. + + + + + The last. + + + + + Gets or sets the identifier. + + The identifier. + + + + Gets or sets the access token. + + The access token. + + + + Gets or sets the device identifier. + + The device identifier. + + + + Gets or sets the name of the application. + + The name of the application. + + + + Gets or sets the application version. + + The application version. + + + + Gets or sets the name of the device. + + The name of the device. + + + + Gets or sets the user identifier. + + The user identifier. + + + + Gets or sets a value indicating whether this instance is active. + + true if this instance is active; otherwise, false. + + + + Gets or sets the date created. + + The date created. + + + + Gets or sets the date revoked. + + The date revoked. + + + + Handles the retrieval and storage of API keys. + + + + + Creates an API key. + + The name of the key. + A task representing the creation of the key. + + + + Gets the API keys. + + A task representing the retrieval of the API keys. + + + + Deletes an API key with the provided access token. + + The access token. + A task representing the deletion of the API key. + + + + Gets a value indicating whether this instance is session active. + + true if this instance is session active; otherwise, false. + + + + Gets a value indicating whether [supports media remote control]. + + true if [supports media remote control]; otherwise, false. + + + + Sends the message. + + The type of data. + Name of message type. + Message ID. + Data to send. + CancellationToken for operation. + A task. + + + + Interface ISessionManager. + + + + + Occurs when [playback start]. + + + + + Occurs when [playback progress]. + + + + + Occurs when [playback stopped]. + + + + + Occurs when [session started]. + + + + + Occurs when [session ended]. + + + + + Occurs when [session controller connected]. + + + + + Occurs when [capabilities changed]. + + + + + Gets the sessions. + + The sessions. + + + + Logs the user activity. + + Type of the client. + The app version. + The device id. + Name of the device. + The remote end point. + The user. + A task containing the session information. + + + + Used to report that a session controller has connected. + + The session. + + + + Used to report that playback has started for an item. + + The info. + Task. + + + + Used to report playback progress for an item. + + The info. + Task. + Throws if an argument is null. + + + + Used to report that playback has ended for an item. + + The info. + Task. + Throws if an argument is null. + + + + Reports the session ended. + + The session identifier. + Task. + + + + Sends the general command. + + The controlling session identifier. + The session identifier. + The command. + The cancellation token. + Task. + + + + Sends the message command. + + The controlling session identifier. + The session id. + The command. + The cancellation token. + Task. + + + + Sends the play command. + + The controlling session identifier. + The session id. + The command. + The cancellation token. + Task. + + + + Sends a SyncPlayCommand to a session. + + The identifier of the session. + The command. + The cancellation token. + Task. + + + + Sends a SyncPlayGroupUpdate to a session. + + The identifier of the session. + The group update. + The cancellation token. + The group update type. + Task. + + + + Sends the browse command. + + The controlling session identifier. + The session id. + The command. + The cancellation token. + Task. + + + + Sends the playstate command. + + The controlling session identifier. + The session id. + The command. + The cancellation token. + Task. + + + + Sends the message to admin sessions. + + Type of data. + Message type name. + The data. + The cancellation token. + Task. + + + + Sends the message to user sessions. + + Type of data. + Users to send messages to. + Message type name. + The data. + The cancellation token. + Task. + + + + Sends the message to user sessions. + + Type of data. + Users to send messages to. + Message type name. + Data function. + The cancellation token. + Task. + + + + Sends the message to user device sessions. + + Type of data. + The device identifier. + Message type name. + The data. + The cancellation token. + Task. + + + + Sends the restart required message. + + The cancellation token. + Task. + + + + Adds the additional user. + + The session identifier. + The user identifier. + + + + Removes the additional user. + + The session identifier. + The user identifier. + + + + Reports the now viewing item. + + The session identifier. + The item identifier. + + + + Authenticates the new session. + + The request. + Task{SessionInfo}. + + + + Reports the capabilities. + + The session identifier. + The capabilities. + + + + Reports the transcoding information. + + The device identifier. + The information. + + + + Clears the transcoding information. + + The device identifier. + + + + Gets the session. + + The device identifier. + The client. + The version. + SessionInfo. + + + + Gets all sessions available to a user. + + The session identifier. + The device id. + Active within session limit. + Filter for sessions remote controllable for this user. + Is the request authenticated with API key. + IReadOnlyList{SessionInfoDto}. + + + + Gets the session by authentication token. + + The token. + The device identifier. + The remote endpoint. + SessionInfo. + + + + Gets the session by authentication token. + + The information. + The device identifier. + The remote endpoint. + The application version. + Task<SessionInfo>. + + + + Logs out the specified access token. + + The access token. + A representing the log out process. + + + + Revokes the user tokens. + + The user's id. + The current access token. + Task. + + + + Used to close the livestream if needed. + + The livestream id. + The session id or playsession id. + Task. + + + + Gets the dto for session info. + + The session info. + of the session. + + + + Class SessionInfo. + + + + + Initializes a new instance of the class. + + Instance of interface. + Instance of interface. + + + + Gets or sets the play state. + + The play state. + + + + Gets or sets the additional users. + + The additional users. + + + + Gets or sets the client capabilities. + + The client capabilities. + + + + Gets or sets the remote end point. + + The remote end point. + + + + Gets the playable media types. + + The playable media types. + + + + Gets or sets the id. + + The id. + + + + Gets or sets the user id. + + The user id. + + + + Gets or sets the username. + + The username. + + + + Gets or sets the type of the client. + + The type of the client. + + + + Gets or sets the last activity date. + + The last activity date. + + + + Gets or sets the last playback check in. + + The last playback check in. + + + + Gets or sets the last paused date. + + The last paused date. + + + + Gets or sets the name of the device. + + The name of the device. + + + + Gets or sets the type of the device. + + The type of the device. + + + + Gets or sets the now playing item. + + The now playing item. + + + + Gets or sets the now playing queue full items. + + The now playing queue full items. + + + + Gets or sets the now viewing item. + + The now viewing item. + + + + Gets or sets the device id. + + The device id. + + + + Gets or sets the application version. + + The application version. + + + + Gets or sets the session controller. + + The session controller. + + + + Gets or sets the transcoding info. + + The transcoding info. + + + + Gets a value indicating whether this instance is active. + + true if this instance is active; otherwise, false. + + + + Gets a value indicating whether the session supports media control. + + true if this session supports media control; otherwise, false. + + + + Gets a value indicating whether the session supports remote control. + + true if this session supports remote control; otherwise, false. + + + + Gets or sets the now playing queue. + + The now playing queue. + + + + Gets or sets the now playing queue full items. + + The now playing queue full items. + + + + Gets or sets a value indicating whether the session has a custom device name. + + true if this session has a custom device name; otherwise, false. + + + + Gets or sets the playlist item id. + + The playlist item id. + + + + Gets or sets the server id. + + The server id. + + + + Gets or sets the user primary image tag. + + The user primary image tag. + + + + Gets the supported commands. + + The supported commands. + + + + Ensures a controller of type exists. + + Class to register. + The factory. + Tuple{ISessionController, bool}. + + + + Adds a controller to the session. + + The controller. + + + + Gets a value indicating whether the session contains a user. + + The user id to check. + true if this session contains the user; otherwise, false. + + + + Starts automatic progressing. + + The playback progress info. + The supported commands. + + + + Stops automatic progressing. + + + + + Disposes the instance async. + + ValueTask. + + + + Interface IBaseItemComparer. + + + + + Gets the comparer type. + + + + + Represents a BaseItem comparer that requires a User to perform its comparison. + + + + + Gets or sets the user. + + The user. + + + + Gets or sets the user manager. + + The user manager. + + + + Gets or sets the user data repository. + + The user data repository. + + + + A progressive file stream for transferring transcoded files as they are written to. + + + + + Initializes a new instance of the class. + + The path to the transcoded file. + The transcoding job information. + The transcode manager. + The timeout duration in milliseconds. + + + + Initializes a new instance of the class. + + The stream to progressively copy. + The timeout duration in milliseconds. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The audio streaming request dto. + + + + + Gets or sets the params. + + + + + Gets or sets the play session id. + + + + + Gets or sets the tag. + + + + + Gets or sets the segment container. + + + + + Gets or sets the segment length. + + + + + Gets or sets the min segments. + + + + + Gets or sets the position of the requested segment in ticks. + + + + + Gets or sets the actual segment length in ticks. + + + + + The stream state dto. + + + + + Initializes a new instance of the class. + + Instance of the interface. + The . + The singleton. + + + + Gets or sets the requested url. + + + + + Gets or sets the request. + + + + + Gets the video request. + + + + + Gets or sets the direct stream provider. + + + Deprecated. + + + + + Gets or sets the path to wait for. + + + + + Gets a value indicating whether the request outputs video. + + + + + Gets the segment length. + + + + + Gets the minimum number of segments. + + + + + Gets or sets the user agent. + + + + + Gets or sets a value indicating whether to estimate the content length. + + + + + Gets or sets the transcode seek info. + + + + + Gets or sets the transcoding job. + + + + + + + + + + + Disposes the stream state. + + Whether the object is currently being disposed. + + + + The video request dto. + + + + + Gets a value indicating whether this instance has fixed resolution. + + true if this instance has fixed resolution; otherwise, false. + + + + Gets or sets a value indicating whether to enable subtitles in the manifest. + + + + + Gets or sets a value indicating whether to enable trickplay images. + + + + + Occurs when [subtitle download failure]. + + + + + Searches the subtitles. + + The video. + Subtitle language. + Require perfect match. + Request is automated. + CancellationToken to use for the operation. + Subtitles, wrapped in task. + + + + Searches the subtitles. + + The request. + The cancellation token. + Task{RemoteSubtitleInfo[]}. + + + + Downloads the subtitles. + + The video. + Subtitle ID. + CancellationToken to use for the operation. + A task. + + + + Downloads the subtitles. + + The video. + Library options to use. + Subtitle ID. + CancellationToken to use for the operation. + A task. + + + + Upload new subtitle. + + The video the subtitle belongs to. + The subtitle response. + A representing the asynchronous operation. + + + + Gets the remote subtitles. + + The identifier. + The cancellation token. + . + + + + Deletes the subtitles. + + Media item. + Subtitle index. + A task. + + + + Gets the providers. + + The media item. + Subtitles providers. + + + + Gets the name. + + The name. + + + + Gets the supported media types. + + The supported media types. + + + + Searches the subtitles. + + The request. + The cancellation token. + Task{IEnumerable{RemoteSubtitleInfo}}. + + + + Gets the subtitles. + + The identifier. + The cancellation token. + Task{SubtitleResponse}. + + + + An event that occurs when subtitle downloading fails. + + + + + Gets or sets the item. + + + + + Gets or sets the provider. + + + + + Gets or sets the exception. + + + + + Class GroupMember. + + + + + Initializes a new instance of the class. + + The session. + + + + Gets the identifier of the session. + + The session identifier. + + + + Gets the identifier of the user. + + The user identifier. + + + + Gets the username. + + The username. + + + + Gets or sets the ping, in milliseconds. + + The ping. + + + + Gets or sets a value indicating whether this member is buffering. + + true if member is buffering; false otherwise. + + + + Gets or sets a value indicating whether this member is following group playback. + + true to ignore member on group wait; false if they're following group playback. + + + + Class AbstractGroupState. + + + Class is not thread-safe, external locking is required when accessing methods. + + + + + The logger. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + Gets the logger factory. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sends a group state update to all group. + + The context of the state. + The reason of the state change. + The session. + The cancellation token. + + + + Class IdleGroupState. + + + Class is not thread-safe, external locking is required when accessing methods. + + + + + The logger. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Class PausedGroupState. + + + Class is not thread-safe, external locking is required when accessing methods. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Class PlayingGroupState. + + + Class is not thread-safe, external locking is required when accessing methods. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + Gets or sets a value indicating whether requests for buffering should be ignored. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Class WaitingGroupState. + + + Class is not thread-safe, external locking is required when accessing methods. + + + + + The logger. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + Gets or sets a value indicating whether playback should resume when group is ready. + + + + + Gets or sets a value indicating whether the initial state has been set. + + + + + Gets or sets the group state before the first ever event. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Interface IGroupPlaybackRequest. + + + + + Gets the playback request type. + + The playback request type. + + + + Applies the request to a group. + + The context of the state. + The current state. + The session. + The cancellation token. + + + + Interface IGroupState. + + + + + Gets the group state type. + + The group state type. + + + + Handles a session that joined the group. + + The context of the state. + The previous state. + The session. + The cancellation token. + + + + Handles a session that is leaving the group. + + The context of the state. + The previous state. + The session. + The cancellation token. + + + + Generic handler. Context's state can change. + + The generic request. + The context of the state. + The previous state. + The session. + The cancellation token. + + + + Handles a play request from a session. Context's state can change. + + The play request. + The context of the state. + The previous state. + The session. + The cancellation token. + + + + Handles a set-playlist-item request from a session. Context's state can change. + + The set-playlist-item request. + The context of the state. + The previous state. + The session. + The cancellation token. + + + + Handles a remove-items request from a session. Context's state can change. + + The remove-items request. + The context of the state. + The previous state. + The session. + The cancellation token. + + + + Handles a move-playlist-item request from a session. Context's state should not change. + + The move-playlist-item request. + The context of the state. + The previous state. + The session. + The cancellation token. + + + + Handles a queue request from a session. Context's state should not change. + + The queue request. + The context of the state. + The previous state. + The session. + The cancellation token. + + + + Handles an unpause request from a session. Context's state can change. + + The unpause request. + The context of the state. + The previous state. + The session. + The cancellation token. + + + + Handles a pause request from a session. Context's state can change. + + The pause request. + The context of the state. + The previous state. + The session. + The cancellation token. + + + + Handles a stop request from a session. Context's state can change. + + The stop request. + The context of the state. + The previous state. + The session. + The cancellation token. + + + + Handles a seek request from a session. Context's state can change. + + The seek request. + The context of the state. + The previous state. + The session. + The cancellation token. + + + + Handles a buffer request from a session. Context's state can change. + + The buffer request. + The context of the state. + The previous state. + The session. + The cancellation token. + + + + Handles a ready request from a session. Context's state can change. + + The ready request. + The context of the state. + The previous state. + The session. + The cancellation token. + + + + Handles a next-item request from a session. Context's state can change. + + The next-item request. + The context of the state. + The previous state. + The session. + The cancellation token. + + + + Handles a previous-item request from a session. Context's state can change. + + The previous-item request. + The context of the state. + The previous state. + The session. + The cancellation token. + + + + Handles a set-repeat-mode request from a session. Context's state should not change. + + The repeat-mode request. + The context of the state. + The previous state. + The session. + The cancellation token. + + + + Handles a set-shuffle-mode request from a session. Context's state should not change. + + The shuffle-mode request. + The context of the state. + The previous state. + The session. + The cancellation token. + + + + Updates the ping of a session. Context's state should not change. + + The ping request. + The context of the state. + The previous state. + The session. + The cancellation token. + + + + Handles a ignore-wait request from a session. Context's state can change. + + The ignore-wait request. + The context of the state. + The previous state. + The session. + The cancellation token. + + + + Interface IGroupStateContext. + + + + + Gets the default ping value used for sessions, in milliseconds. + + The default ping value used for sessions, in milliseconds. + + + + Gets the maximum time offset error accepted for dates reported by clients, in milliseconds. + + The maximum offset error accepted, in milliseconds. + + + + Gets the maximum offset error accepted for position reported by clients, in milliseconds. + + The maximum offset error accepted, in milliseconds. + + + + Gets the group identifier. + + The group identifier. + + + + Gets or sets the position ticks. + + The position ticks. + + + + Gets or sets the last activity. + + The last activity. + + + + Gets the play queue. + + The play queue. + + + + Sets a new state. + + The new state. + + + + Sends a GroupUpdate message to the interested sessions. + + The current session. + The filtering type. + The message to send. + The cancellation token. + The group update type. + The task. + + + + Sends a playback command to the interested sessions. + + The current session. + The filtering type. + The message to send. + The cancellation token. + The task. + + + + Builds a new playback command with some default values. + + The command type. + The command. + + + + Sanitizes the PositionTicks, considers the current playing item when available. + + The PositionTicks. + The sanitized position ticks. + + + + Updates the ping of a session, in milliseconds. + + The session. + The ping, in milliseconds. + + + + Gets the highest ping in the group, in milliseconds. + + The highest ping in the group. + + + + Sets the session's buffering state. + + The session. + The state. + + + + Sets the buffering state of all the sessions. + + The state. + + + + Gets the group buffering state. + + true if there is a session buffering in the group; false otherwise. + + + + Sets the session's group wait state. + + The session. + The state. + + + + Sets a new play queue. + + The new play queue. + The playing item position in the play queue. + The start position ticks. + true if the play queue has been changed; false if something went wrong. + + + + Sets the playing item. + + The new playing item identifier. + true if the play queue has been changed; false if something went wrong. + + + + Clears the play queue. + + Whether to remove the playing item as well. + + + + Removes items from the play queue. + + The items to remove. + true if playing item got removed; false otherwise. + + + + Moves an item in the play queue. + + The playlist identifier of the item to move. + The new position. + true if item has been moved; false if something went wrong. + + + + Updates the play queue. + + The new items to add to the play queue. + The mode with which the items will be added. + true if the play queue has been changed; false if something went wrong. + + + + Restarts current item in play queue. + + + + + Picks next item in play queue. + + true if the item changed; false otherwise. + + + + Picks previous item in play queue. + + true if the item changed; false otherwise. + + + + Sets the repeat mode. + + The new mode. + + + + Sets the shuffle mode. + + The new mode. + + + + Creates a play queue update. + + The reason for the update. + The play queue update. + + + + Interface ISyncPlayManager. + + + + + Creates a new group. + + The session that's creating the group. + The request. + The cancellation token. + The newly created group. + + + + Adds the session to a group. + + The session. + The request. + The cancellation token. + + + + Removes the session from a group. + + The session. + The request. + The cancellation token. + + + + Gets list of available groups for a session. + + The session. + The request. + The list of available groups. + + + + Gets available groups for a session by id. + + The session. + The group id. + The groups or null. + + + + Handle a request by a session in a group. + + The session. + The request. + The cancellation token. + + + + Checks whether a user has an active session using SyncPlay. + + The user identifier to check. + true if the user is using SyncPlay; false otherwise. + + + + Interface ISyncPlayRequest. + + + + + Gets the request type. + + The request type. + + + + Class AbstractPlaybackRequest. + + + + + Initializes a new instance of the class. + + + + + + + + + + + + + + Class BufferGroupRequest. + + + + + Initializes a new instance of the class. + + When the request has been made, as reported by the client. + The position ticks. + Whether the client playback is unpaused. + The playlist item identifier of the playing item. + + + + Gets when the request has been made by the client. + + The date of the request. + + + + Gets the position ticks. + + The position ticks. + + + + Gets a value indicating whether the client playback is unpaused. + + The client playback status. + + + + Gets the playlist item identifier of the playing item. + + The playlist item identifier. + + + + + + + + + + Class IgnoreWaitGroupRequest. + + + + + Initializes a new instance of the class. + + Whether the client should be ignored. + + + + Gets a value indicating whether the client should be ignored. + + The client group-wait status. + + + + + + + + + + Class MovePlaylistItemGroupRequest. + + + + + Initializes a new instance of the class. + + The playlist identifier of the item. + The new position. + + + + Gets the playlist identifier of the item. + + The playlist identifier of the item. + + + + Gets the new position. + + The new position. + + + + + + + + + + Class NextItemGroupRequest. + + + + + Initializes a new instance of the class. + + The playing item identifier. + + + + Gets the playing item identifier. + + The playing item identifier. + + + + + + + + + + Class PauseGroupRequest. + + + + + + + + + + + Class PingGroupRequest. + + + + + Initializes a new instance of the class. + + The ping time. + + + + Gets the ping time. + + The ping time. + + + + + + + + + + Class PlayGroupRequest. + + + + + Initializes a new instance of the class. + + The playing queue. + The playing item position. + The start position ticks. + + + + Gets the playing queue. + + The playing queue. + + + + Gets the position of the playing item in the queue. + + The playing item position. + + + + Gets the start position ticks. + + The start position ticks. + + + + + + + + + + Class PreviousItemGroupRequest. + + + + + Initializes a new instance of the class. + + The playing item identifier. + + + + Gets the playing item identifier. + + The playing item identifier. + + + + + + + + + + Class QueueGroupRequest. + + + + + Initializes a new instance of the class. + + The items to add to the queue. + The enqueue mode. + + + + Gets the items to enqueue. + + The items to enqueue. + + + + Gets the mode in which to add the new items. + + The enqueue mode. + + + + + + + + + + Class ReadyGroupRequest. + + + + + Initializes a new instance of the class. + + When the request has been made, as reported by the client. + The position ticks. + Whether the client playback is unpaused. + The playlist item identifier of the playing item. + + + + Gets when the request has been made by the client. + + The date of the request. + + + + Gets the position ticks. + + The position ticks. + + + + Gets a value indicating whether the client playback is unpaused. + + The client playback status. + + + + Gets the playlist item identifier of the playing item. + + The playlist item identifier. + + + + + + + + + + Class RemoveFromPlaylistGroupRequest. + + + + + Initializes a new instance of the class. + + The playlist ids of the items to remove. + Whether to clear the entire playlist. The items list will be ignored. + Whether to remove the playing item as well. Used only when clearing the playlist. + + + + Gets the playlist identifiers of the items. + + The playlist identifiers of the items. + + + + Gets a value indicating whether the entire playlist should be cleared. + + Whether the entire playlist should be cleared. + + + + Gets a value indicating whether the playing item should be removed as well. + + Whether the playing item should be removed as well. + + + + + + + + + + Class SeekGroupRequest. + + + + + Initializes a new instance of the class. + + The position ticks. + + + + Gets the position ticks. + + The position ticks. + + + + + + + + + + Class SetPlaylistItemGroupRequest. + + + + + Initializes a new instance of the class. + + The playlist identifier of the item. + + + + Gets the playlist identifier of the playing item. + + The playlist identifier of the playing item. + + + + + + + + + + Class SetRepeatModeGroupRequest. + + + + + Initializes a new instance of the class. + + The repeat mode. + + + + Gets the repeat mode. + + The repeat mode. + + + + + + + + + + Class SetShuffleModeGroupRequest. + + + + + Initializes a new instance of the class. + + The shuffle mode. + + + + Gets the shuffle mode. + + The shuffle mode. + + + + + + + + + + Class StopGroupRequest. + + + + + + + + + + + Class UnpauseGroupRequest. + + + + + + + + + + + Class PlayQueueManager. + + + + + Placeholder index for when no item is playing. + + The no-playing item index. + + + + The sorted playlist. + + The sorted playlist, or play queue of the group. + + + + The shuffled playlist. + + The shuffled playlist, or play queue of the group. + + + + Initializes a new instance of the class. + + + + + Gets the playing item index. + + The playing item index. + + + + Gets the last time the queue has been changed. + + The last time the queue has been changed. + + + + Gets the shuffle mode. + + The shuffle mode. + + + + Gets the repeat mode. + + The repeat mode. + + + + Checks if an item is playing. + + true if an item is playing; false otherwise. + + + + Gets the current playlist considering the shuffle mode. + + The playlist. + + + + Sets a new playlist. Playing item is reset. + + The new items of the playlist. + + + + Appends new items to the playlist. The specified order is maintained. + + The items to add to the playlist. + + + + Shuffles the playlist. Shuffle mode is changed. The playlist gets re-shuffled if already shuffled. + + + + + Resets the playlist to sorted mode. Shuffle mode is changed. + + + + + Clears the playlist. Shuffle mode is preserved. + + Whether to remove the playing item as well. + + + + Adds new items to the playlist right after the playing item. The specified order is maintained. + + The items to add to the playlist. + + + + Gets playlist identifier of the playing item, if any. + + The playlist identifier of the playing item. + + + + Gets the playing item identifier, if any. + + The playing item identifier. + + + + Sets the playing item using its identifier. If not in the playlist, the playing item is reset. + + The new playing item identifier. + + + + Sets the playing item using its playlist identifier. If not in the playlist, the playing item is reset. + + The new playing item identifier. + true if playing item has been set; false if item is not in the playlist. + + + + Sets the playing item using its position. If not in range, the playing item is reset. + + The new playing item index. + + + + Removes items from the playlist. If not removed, the playing item is preserved. + + The items to remove. + true if playing item got removed; false otherwise. + + + + Moves an item in the playlist to another position. + + The item to move. + The new position. + true if the item has been moved; false otherwise. + + + + Resets the playlist to its initial state. + + + + + Sets the repeat mode. + + The new mode. + + + + Sets the shuffle mode. + + The new mode. + + + + Toggles the shuffle mode between sorted and shuffled. + + + + + Gets the next item in the playlist considering repeat mode and shuffle mode. + + The next item in the playlist. + + + + Sets the next item in the queue as playing item. + + true if the playing item changed; false otherwise. + + + + Sets the previous item in the queue as playing item. + + true if the playing item changed; false otherwise. + + + + Creates a list from the array of items. Each item is given an unique playlist identifier. + + The list of queue items. + + + + Gets the current playlist considering the shuffle mode. + + The playlist. + + + + Gets the current playing item, depending on the shuffle mode. + + The playing item. + + + + Class JoinGroupRequest. + + + + + Initializes a new instance of the class. + + The identifier of the group to join. + + + + Gets the group identifier. + + The identifier of the group to join. + + + + + + + Class LeaveGroupRequest. + + + + + + + + Class ListGroupsRequest. + + + + + + + + Class NewGroupRequest. + + + + + Initializes a new instance of the class. + + The name of the new group. + + + + Gets the group name. + + The name of the new group. + + + + + + + Manifest type for backups internal structure. + + + + + Gets or sets the jellyfin version this backup was created with. + + + + + Gets or sets the backup engine version this backup was created with. + + + + + Gets or sets the date this backup was created with. + + + + + Gets or sets the path to the backup on the system. + + + + + Gets or sets the contents of the backup archive. + + + + + Defines the optional contents of the backup archive. + + + + + Gets or sets a value indicating whether the archive contains the Metadata contents. + + + + + Gets or sets a value indicating whether the archive contains the Trickplay contents. + + + + + Gets or sets a value indicating whether the archive contains the Subtitle contents. + + + + + Gets or sets a value indicating whether the archive contains the Database contents. + + + + + Defines properties used to start a restore process. + + + + + Gets or Sets the name of the backup archive to restore from. Must be present in . + + + + + Interface ITrickplayManager. + + + + + Generates new trickplay images and metadata. + + The video. + Whether or not existing data should be replaced. + The library options. + CancellationToken to use for operation. + Task. + + + + Creates trickplay tiles out of individual thumbnails. + + Ordered file paths of the thumbnails to be used. + The width of a single thumbnail. + The trickplay options. + The output directory. + The associated trickplay information. + + The output directory will be DELETED and replaced if it already exists. + + + + + Get available trickplay resolutions and corresponding info. + + The item. + Map of width resolutions to trickplay tiles info. + + + + Gets the item ids of all items with trickplay info. + + The limit of items to return. + The offset to start the query at. + The list of item ids that have trickplay info. + + + + Saves trickplay info. + + The trickplay info. + Task. + + + + Deletes all trickplay info for an item. + + The item id. + The cancellation token. + Task. + + + + Gets all trickplay infos for all media streams of an item. + + The item. + A map of media source id to a map of tile width to trickplay info. + + + + Gets the path to a trickplay tile image. + + The item. + The width of a single thumbnail. + The tile's index. + Whether or not the tile should be saved next to the media file. + The absolute path. + + + + Gets the path to a trickplay tile image. + + The item. + The amount of images for the tile width. + The amount of images for the tile height. + The width of a single thumbnail. + Whether or not the tile should be saved next to the media file. + The absolute path. + + + + Migrates trickplay images between local and media directories. + + The video. + The library options. + CancellationToken to use for operation. + Task. + + + + Gets the trickplay HLS playlist. + + The item. + The width of a single thumbnail. + Optional api key of the requesting user. + The text content of the .m3u8 playlist. + + + + The TV Series manager. + + + + + Gets the next up. + + The next up query. + The dto options. + The next up items. + + + + Gets the next up. + + The next up request. + The list of parent folders. + The dto options. + The next up items. + + + + Defines an interface to restore and backup the jellyfin system. + + + + + Creates a new Backup zip file containing the current state of the application. + + The backup options. + A task. + + + + Gets a list of backups that are available to be restored from. + + A list of backup paths. + + + + Gets a single backup manifest if the path defines a valid Jellyfin backup archive. + + The path to be loaded. + The containing backup manifest or null if not existing or compatiable. + + + + Restores an backup zip file created by jellyfin. + + Path to the archive. + A Task. + Thrown when an invalid or missing file is specified. + Thrown when attempt to load an unsupported backup is made. + Thrown for errors during the restore. + + + + Schedules a Restore and restarts the server. + + The path to the archive to restore from. + + + Custom -derived type for the WhiteSpaceRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Helper methods used by generated -derived implementations. + + + Default timeout value set in , or if none was set. + + + Whether is non-infinite. + + + Supports searching for characters in or not in "\t\n\v\f\r \u0085             \u2028\u2029   ". + +
+
diff --git a/publish/MediaBrowser.LocalMetadata.xml b/publish/MediaBrowser.LocalMetadata.xml new file mode 100644 index 00000000..2dc8acf3 --- /dev/null +++ b/publish/MediaBrowser.LocalMetadata.xml @@ -0,0 +1,500 @@ + + + + MediaBrowser.LocalMetadata + + + + + The BaseXmlProvider. + + Type of provider. + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + After Nfo + + + + + Gets the IFileSystem. + + + + + Gets metadata for item. + + The item info. + Instance of the interface. + The cancellation token. + The metadata for item. + + + + Get metadata from path. + + Resulting metadata. + The path. + The cancellation token. + + + + Get metadata from xml file. + + Item inf. + Instance of the interface. + The file system metadata. + + + + + + + Collection folder local image provider. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + Run after LocalImageProvider + + + + + + + + + + + Episode local image provider. + + + + + + + + + + + + + + + + + Internal metadata folder image provider. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + Make sure this is last so that all other locations are scanned first + + + + + + + + + + + + + + Local image provider. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + + + + + + + + + + Get images for item. + + The item. + The images path. + Instance of the interface. + The local image info. + + + + Get images for item from multiple paths. + + The item. + The image paths. + Instance of the interface. + The local image info. + + + + Provides a base class for parsing metadata xml. + + Type of item xml parser. + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + + Gets the logger. + + + + + Gets the provider manager. + + + + + Fetches metadata for an item from one xml file. + + The item. + The metadata file. + The cancellation token. + Item is null. + + + + Fetches the specified item. + + The item. + The metadata file. + The settings. + The encoding. + The cancellation token. + + + + Fetches metadata from one Xml Element. + + The reader. + The item result. + + + + Fetches from taglines node. + + The reader. + The item. + + + + Fetches from genres node. + + The reader. + The item. + + + + Fetches the data from persons node. + + The reader. + The item. + + + + Fetches from studios node. + + The reader. + The item. + + + + Get linked child. + + The xml reader. + The linked child. + + + + Get share. + + The xml reader. + The share. + + + + The box set xml parser. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + + + + + Playlist xml parser. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + + + + + Class BoxSetXmlProvider. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + Playlist xml provider. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Gets the file system. + + + + + Gets the configuration manager. + + + + + Gets the library manager. + + + + + Gets the logger. + + + + + + + + + + + Gets the save path. + + The item. + System.String. + + + + Gets the name of the root element. + + The item. + System.String. + + + + Determines whether [is enabled for] [the specified item]. + + The item. + Type of the update. + true if [is enabled for] [the specified item]; otherwise, false. + + + + + + + Write custom elements. + + The item. + The xml writer. + The task object representing the asynchronous operation. + + + + Adds the common nodes. + + The item. + The xml writer. + The task object representing the asynchronous operation. + + + + Add shares. + + The item. + The xml writer. + The task object representing the asynchronous operation. + + + + Appends the media info. + + The item. + The xml writer. + Type of item. + The task object representing the asynchronous operation. + + + + ADd linked children. + + The item. + The xml writer. + The plural node name. + The singular node name. + The task object representing the asynchronous operation. + + + + Box set xml saver. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + Playlist xml saver. + + + + + The default file name to use when creating a new playlist. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + Get the save path. + + The item path. + The save path. + + + + The xml provider utils. + + + + + Gets the name. + + + + diff --git a/publish/MediaBrowser.MediaEncoding.xml b/publish/MediaBrowser.MediaEncoding.xml new file mode 100644 index 00000000..985c0103 --- /dev/null +++ b/publish/MediaBrowser.MediaEncoding.xml @@ -0,0 +1,1782 @@ + + + + MediaBrowser.MediaEncoding + + + + + + + + Initializes a new instance of the class. + + The . + The . + The . + The . + The . + + + + + + + + + + + + + Class BdInfoDirectoryInfo. + + + + + Initializes a new instance of the class. + + The filesystem. + The path. + + + + Gets the name. + + + + + Gets the full name. + + + + + Gets the parent directory information. + + + + + Gets the directories. + + An array with all directories. + + + + Gets the files. + + All files of the directory. + + + + Gets the files matching a pattern. + + The search pattern. + All files of the directory matching the search pattern. + + + + Gets the files matching a pattern and search options. + + The search pattern. + The search option. + All files of the directory matching the search pattern and options. + + + + Gets the bdinfo of a file system path. + + The file system. + The path. + The BD directory information of the path on the file system. + + + + Class BdInfoExaminer. + + + + + Initializes a new instance of the class. + + The filesystem. + + + + Gets the disc info. + + The path. + BlurayDiscInfo. + + + + Adds the video stream. + + The streams. + The stream index. + The video stream. + + + + Adds the audio stream. + + The streams. + The stream index. + The audio stream. + + + + Adds the subtitle stream. + + The streams. + The stream index. + The stream. + + + + Class BdInfoFileInfo. + + + + + Initializes a new instance of the class. + + The . + + + + Gets the name. + + + + + Gets the full name. + + + + + Gets the extension. + + + + + Gets the length. + + + + + Gets a value indicating whether this is a directory. + + + + + Gets a file as file stream. + + A for the file. + + + + Gets a files's content with a stream reader. + + A for the file's content. + + + + Helper class for Apple platform specific operations. + + + + + Check if the current system has hardware acceleration for AV1 decoding. + + The logger used for error logging. + Boolean indicates the hwaccel support. + + + + Pattern:
+ ^ffmpeg version n?((?:[0-9]+\.?)+)
+ Explanation:
+ + ○ Match if at the beginning of the string.
+ ○ Match the string "ffmpeg version ".
+ ○ Match 'n' atomically, optionally.
+ ○ 1st capture group.
+ ○ Loop atomically at least once.
+ ○ Match a character in the set [0-9] greedily at least once.
+ ○ Match '.' atomically, optionally.
+
+
+
+ + + Pattern:
+ ((?<name>lib\w+)\s+(?<major>[0-9]+)\.\s*(?<minor>[0-9]+))
+ Options:
+ RegexOptions.Multiline
+ Explanation:
+ + ○ 1st capture group.
+ ○ "name" capture group.
+ ○ Match the string "lib".
+ ○ Match a word character atomically at least once.
+ ○ Match a whitespace character atomically at least once.
+ ○ "major" capture group.
+ ○ Match a character in the set [0-9] atomically at least once.
+ ○ Match '.'.
+ ○ Match a whitespace character atomically any number of times.
+ ○ "minor" capture group.
+ ○ Match a character in the set [0-9] atomically at least once.
+
+
+
+ + + Using the output from "ffmpeg -version" work out the FFmpeg version. + For pre-built binaries the first line should contain a string like "ffmpeg version x.y", which is easy + to parse. If this is not available, then we try to match known library versions to FFmpeg versions. + If that fails then we test the libraries to determine if they're newer than our minimum versions. + + The output from "ffmpeg -version". + The FFmpeg version. + + + + Grabs the library names and major.minor version numbers from the 'ffmpeg -version' output + and condenses them on to one line. Output format is "name1=major.minor,name2=major.minor,etc.". + + The 'ffmpeg -version' output. + The library names and major.minor version numbers. + + + + Pattern:
+ ^\s\S{6}\s(?<codec>[\w|-]+)\s+.+$
+ Options:
+ RegexOptions.Multiline
+ Explanation:
+ + ○ Match if at the beginning of a line.
+ ○ Match a whitespace character.
+ ○ Match any character other than a whitespace character exactly 6 times.
+ ○ Match a whitespace character.
+ ○ "codec" capture group.
+ ○ Match a character in the set [\-|\w] greedily at least once.
+ ○ Match a whitespace character greedily at least once.
+ ○ Match a character other than '\n' greedily at least once.
+ ○ Match if at the end of a line.
+
+
+
+ + + Pattern:
+ ^\s\S{3}\s(?<filter>[\w|-]+)\s+.+$
+ Options:
+ RegexOptions.Multiline
+ Explanation:
+ + ○ Match if at the beginning of a line.
+ ○ Match a whitespace character.
+ ○ Match any character other than a whitespace character exactly 3 times.
+ ○ Match a whitespace character.
+ ○ "filter" capture group.
+ ○ Match a character in the set [\-|\w] greedily at least once.
+ ○ Match a whitespace character greedily at least once.
+ ○ Match a character other than '\n' greedily at least once.
+ ○ Match if at the end of a line.
+
+
+
+ + + Gets the concat input argument. + + The input files. + The input prefix. + System.String. + + + + Gets the file input argument. + + The path. + The path prefix. + System.String. + + + + Normalizes the path. + + The path. + System.String. + + + + Class MediaEncoder. + + + + + The default SDR image extraction timeout in milliseconds. + + + + + The default HDR image extraction timeout in milliseconds. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Pattern:
+ [^\/\\]+?(\.[^\/\\\n.]+)?$
+ Explanation:
+ + ○ Match a character in the set [^/\\] lazily at least once.
+ ○ Optional (greedy).
+ ○ 1st capture group.
+ ○ Match '.'.
+ ○ Match a character in the set [^\n./\\] atomically at least once.
+ ○ Match if at the end of the string or if before an ending newline.
+
+
+
+ + + Run at startup to validate ffmpeg. + Sets global variables FFmpegPath. + Precedence is: CLI/Env var > Config > $PATH. + + bool indicates whether a valid ffmpeg is found. + + + + Validates the supplied FQPN to ensure it is a ffmpeg utility. + If checks pass, global variable FFmpegPath is updated. + + FQPN to test. + true if the version validation succeeded; otherwise, false. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Gets the media info internal. + + Task{MediaInfoResult}. + + + + + + + + + + + + + + + + + + + Releases unmanaged and - optionally - managed resources. + + true to release both managed and unmanaged resources; false to release only unmanaged resources. + + + + + + + + + + + + + + + + + + + + + + FFmpeg Codec Type. + + + + + Video. + + + + + Audio. + + + + + Opaque data information usually continuous. + + + + + Subtitles. + + + + + Opaque data information usually sparse. + + + + + Class containing helper methods for working with FFprobe output. + + + + + Normalizes the FF probe result. + + The result. + + + + Gets an int from an FFProbeResult tags dictionary. + + The tags. + The key. + System.Nullable{System.Int32}. + + + + Gets a DateTime from an FFProbeResult tags dictionary. + + The tags. + The key. + System.Nullable{DateTime}. + + + + Converts a dictionary to case-insensitive. + + The dict. + Dictionary{System.StringSystem.String}. + + + + Class MediaInfoResult. + + + + + Gets or sets the streams. + + The streams. + + + + Gets or sets the format. + + The format. + + + + Gets or sets the chapters. + + The chapters. + + + + Gets or sets the frames. + + The streams. + + + + Class MediaChapter. + + + + + Class MediaFormat. + + + + + Gets or sets the filename. + + The filename. + + + + Gets or sets the nb_streams. + + The nb_streams. + + + + Gets or sets the format_name. + + The format_name. + + + + Gets or sets the format_long_name. + + The format_long_name. + + + + Gets or sets the start_time. + + The start_time. + + + + Gets or sets the duration. + + The duration. + + + + Gets or sets the size. + + The size. + + + + Gets or sets the bit_rate. + + The bit_rate. + + + + Gets or sets the probe_score. + + The probe_score. + + + + Gets or sets the tags. + + The tags. + + + + Class MediaFrameInfo. + + + + + Gets or sets the media type. + + + + + Gets or sets the StreamIndex. + + + + + Gets or sets the KeyFrame. + + + + + Gets or sets the Pts. + + + + + Gets or sets the PtsTime. + + + + + Gets or sets the BestEffortTimestamp. + + + + + Gets or sets the BestEffortTimestampTime. + + + + + Gets or sets the Duration. + + + + + Gets or sets the DurationTime. + + + + + Gets or sets the PktPos. + + + + + Gets or sets the PktSize. + + + + + Gets or sets the Width. + + + + + Gets or sets the Height. + + + + + Gets or sets the CropTop. + + + + + Gets or sets the CropBottom. + + + + + Gets or sets the CropLeft. + + + + + Gets or sets the CropRight. + + + + + Gets or sets the PixFmt. + + + + + Gets or sets the SampleAspectRatio. + + + + + Gets or sets the PictType. + + + + + Gets or sets the InterlacedFrame. + + + + + Gets or sets the TopFieldFirst. + + + + + Gets or sets the RepeatPict. + + + + + Gets or sets the ColorRange. + + + + + Gets or sets the ColorSpace. + + + + + Gets or sets the ColorPrimaries. + + + + + Gets or sets the ColorTransfer. + + + + + Gets or sets the ChromaLocation. + + + + + Gets or sets the SideDataList. + + + + + Class MediaFrameSideDataInfo. + Currently only records the SideDataType for HDR10+ detection. + + + + + Gets or sets the SideDataType. + + + + + Represents a stream within the output. + + + + + Gets or sets the index. + + The index. + + + + Gets or sets the profile. + + The profile. + + + + Gets or sets the codec_name. + + The codec_name. + + + + Gets or sets the codec_long_name. + + The codec_long_name. + + + + Gets or sets the codec_type. + + The codec_type. + + + + Gets or sets the sample_rate. + + The sample_rate. + + + + Gets or sets the channels. + + The channels. + + + + Gets or sets the channel_layout. + + The channel_layout. + + + + Gets or sets the avg_frame_rate. + + The avg_frame_rate. + + + + Gets or sets the duration. + + The duration. + + + + Gets or sets the bit_rate. + + The bit_rate. + + + + Gets or sets the width. + + The width. + + + + Gets or sets the refs. + + The refs. + + + + Gets or sets the height. + + The height. + + + + Gets or sets the display_aspect_ratio. + + The display_aspect_ratio. + + + + Gets or sets the tags. + + The tags. + + + + Gets or sets the bits_per_sample. + + The bits_per_sample. + + + + Gets or sets the bits_per_raw_sample. + + The bits_per_raw_sample. + + + + Gets or sets the r_frame_rate. + + The r_frame_rate. + + + + Gets or sets the has_b_frames. + + The has_b_frames. + + + + Gets or sets the sample_aspect_ratio. + + The sample_aspect_ratio. + + + + Gets or sets the pix_fmt. + + The pix_fmt. + + + + Gets or sets the level. + + The level. + + + + Gets or sets the time_base. + + The time_base. + + + + Gets or sets the start_time. + + The start_time. + + + + Gets or sets the codec_time_base. + + The codec_time_base. + + + + Gets or sets the codec_tag. + + The codec_tag. + + + + Gets or sets the codec_tag_string. + + The codec_tag_string. + + + + Gets or sets the sample_fmt. + + The sample_fmt. + + + + Gets or sets the dmix_mode. + + The dmix_mode. + + + + Gets or sets the start_pts. + + The start_pts. + + + + Gets or sets a value indicating whether the stream is AVC. + + The is_avc. + + + + Gets or sets the nal_length_size. + + The nal_length_size. + + + + Gets or sets the ltrt_cmixlev. + + The ltrt_cmixlev. + + + + Gets or sets the ltrt_surmixlev. + + The ltrt_surmixlev. + + + + Gets or sets the loro_cmixlev. + + The loro_cmixlev. + + + + Gets or sets the loro_surmixlev. + + The loro_surmixlev. + + + + Gets or sets the field_order. + + The field_order. + + + + Gets or sets the disposition. + + The disposition. + + + + Gets or sets the color range. + + The color range. + + + + Gets or sets the color space. + + The color space. + + + + Gets or sets the color transfer. + + The color transfer. + + + + Gets or sets the color primaries. + + The color primaries. + + + + Gets or sets the side_data_list. + + The side_data_list. + + + + Class MediaStreamInfoSideData. + + + + + Gets or sets the SideDataType. + + The SideDataType. + + + + Gets or sets the DvVersionMajor. + + The DvVersionMajor. + + + + Gets or sets the DvVersionMinor. + + The DvVersionMinor. + + + + Gets or sets the DvProfile. + + The DvProfile. + + + + Gets or sets the DvLevel. + + The DvLevel. + + + + Gets or sets the RpuPresentFlag. + + The RpuPresentFlag. + + + + Gets or sets the ElPresentFlag. + + The ElPresentFlag. + + + + Gets or sets the BlPresentFlag. + + The BlPresentFlag. + + + + Gets or sets the DvBlSignalCompatibilityId. + + The DvBlSignalCompatibilityId. + + + + Gets or sets the Rotation in degrees. + + The Rotation. + + + + Class responsible for normalizing FFprobe output. + + + + + Initializes a new instance of the class. + + The for use with the instance. + The for use with the instance. + + + + Transforms a FFprobe response into its equivalent. + + The . + The . + A boolean indicating whether the media is audio. + Path to media file. + Path media protocol. + The . + + + + Converts ffprobe stream info to our MediaAttachment class. + + The stream info. + MediaAttachments. + + + + Converts ffprobe stream info to our MediaStream class. + + if set to true [is info]. + The stream info. + The format info. + The frame info. + MediaStream. + + + + Gets a string from an FFProbeResult tags dictionary. + + The tags. + The key. + System.String. + + + + Gets a frame rate from a string value in ffprobe output + This could be a number or in the format of 2997/125. + + The value. + System.Nullable{System.Single}. + + + + Splits the specified val. + + The val. + if set to true [allow comma delimiter]. + System.String[][]. + + + + Gets the studios from the tags collection. + + The info. + The tags. + Name of the tag. + + + + Gets the genres from the tags collection. + + The information. + The tags. + + + + Gets the track or disc number, which can be in the form of '1', or '1/3'. + + The tags. + Name of the tag. + The track or disc number, or null, if missing or not parseable. + + + + Pattern:
+ (?<name>.*) \((?<instrument>.*)\)
+ Explanation:
+ + ○ "name" capture group.
+ ○ Match a character other than '\n' greedily any number of times.
+ ○ Match the string " (".
+ ○ "instrument" capture group.
+ ○ Match a character other than '\n' greedily any number of times.
+ ○ Match ')'.
+
+
+
+ + + ASS subtitle writer. + + + + + Pattern:
+ \n
+ Options:
+ RegexOptions.IgnoreCase
+ Explanation:
+ + ○ Match '\n'.
+
+
+
+ + + + + + Parses the specified stream. + + The stream. + The file extension. + SubtitleTrackInfo. + + + + Determines whether the file extension is supported by the parser. + + The file extension. + A value indicating whether the file extension is supported. + + + + Interface ISubtitleWriter. + + + + + Writes the specified information. + + The information. + The stream. + The cancellation token. + + + + JSON subtitle writer. + + + + + + + + SRT subtitle writer. + + + + + Pattern:
+ \\n
+ Options:
+ RegexOptions.IgnoreCase
+ Explanation:
+ + ○ Match '\\'.
+ ○ Match a character in the set [Nn].
+
+
+
+ + + + + + SSA subtitle writer. + + + + + Pattern:
+ \n
+ Options:
+ RegexOptions.IgnoreCase
+ Explanation:
+ + ○ Match '\n'.
+
+
+
+ + + + + + SubStation Alpha subtitle parser. + + + + + Initializes a new instance of the class. + + The logger. + + + + + + + + + + The _semaphoreLocks. + + + + + Converts the text subtitle to SRT. + + The subtitle stream. + The input mediaSource. + The output path. + The cancellation token. + Task. + + + + Converts the text subtitle to SRT internal. + + The subtitle stream. + The input mediaSource. + The output path. + The cancellation token. + Task. + + The inputPath or outputPath is null. + + + + + + + + Extracts the text subtitle. + + The mediaSource. + The subtitle stream. + The output codec. + The output path. + The cancellation token. + Task. + Must use inputPath list overload. + + + + Sets the ass font. + + The file. + The token to monitor for cancellation requests. The default value is System.Threading.CancellationToken.None. + Task. + + + + + + + + + + Will try to find errors if supported by provider. + + The subtitle format. + The out errors value. + True if errors are available for given format. + + + + TTML subtitle writer. + + + + + Pattern:
+ \\n
+ Options:
+ RegexOptions.IgnoreCase
+ Explanation:
+ + ○ Match '\\'.
+ ○ Match a character in the set [Nn].
+
+
+
+ + + + + + Subtitle writer for the WebVTT format. + + + + + Pattern:
+ \\n
+ Options:
+ RegexOptions.IgnoreCase
+ Explanation:
+ + ○ Match '\\'.
+ ○ Match a character in the set [Nn].
+
+
+
+ + + + + + + + + Initializes a new instance of the class. + + The . + The . + The . + The . + The . + The . + The . + The . + The . + The . + + + + + + + + + + + + + + + + + + + + + + + + + + + + Transcoding lock. + + The output path of the transcoded file. + The cancellation token. + An . + + + + + + Custom -derived type for the FfmpegVersionRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Custom -derived type for the LibraryRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Custom -derived type for the CodecRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Custom -derived type for the FilterRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Custom -derived type for the FfprobePathRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Custom -derived type for the PerformerRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Custom -derived type for the NewLineRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Custom -derived type for the NewLineEscapedRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Helper methods used by generated -derived implementations. + + + Default timeout value set in , or if none was set. + + + Whether is non-infinite. + + + Determines whether the character is part of the [\w] set. + + + Pops 2 values from the backtracking stack. + + + Pushes 2 values onto the backtracking stack. + + + Pushes 3 values onto the backtracking stack. + + + Provides a mask of Unicode categories that combine to form [\w]. + + + Gets a bitmap for whether each character 0 through 127 is in [\w] + + + Supports searching for characters in or not in "\n./\\". + + + Supports searching for the string "\\n". + + + Supports searching for the string "lib". + + + Supports searching for characters in or not in "\t\n\v\f\r \u0085             \u2028\u2029   ". + +
+
diff --git a/publish/MediaBrowser.Model.xml b/publish/MediaBrowser.Model.xml new file mode 100644 index 00000000..f00f67c7 --- /dev/null +++ b/publish/MediaBrowser.Model.xml @@ -0,0 +1,11274 @@ + + + + MediaBrowser.Model + + + + + An activity log entry. + + + + + Initializes a new instance of the class. + + The name. + The type. + The user id. + + + + Gets or sets the identifier. + + The identifier. + + + + Gets or sets the name. + + The name. + + + + Gets or sets the overview. + + The overview. + + + + Gets or sets the short overview. + + The short overview. + + + + Gets or sets the type. + + The type. + + + + Gets or sets the item identifier. + + The item identifier. + + + + Gets or sets the date. + + The date. + + + + Gets or sets the user identifier. + + The user identifier. + + + + Gets or sets the user primary image tag. + + The user primary image tag. + + + + Gets or sets the log severity. + + The log severity. + + + + Interface for the activity manager. + + + + + The event that is triggered when an entity is created. + + + + + Create a new activity log entry. + + The entry to create. + A representing the asynchronous operation. + + + + Get a paged list of activity log entries. + + The activity log query. + The page of entries. + + + + Remove all activity logs before the specified date. + + Activity log start date. + A representing the asynchronous operation. + + + + The server discovery info model. + + + + + Initializes a new instance of the class. + + The server address. + The server id. + The server name. + The endpoint address. + + + + Gets the address. + + + + + Gets the server identifier. + + + + + Gets the name. + + + + + Gets the endpoint address. + + + + + The branding options. + + + + + Gets or sets the login disclaimer. + + The login disclaimer. + + + + Gets or sets the custom CSS. + + The custom CSS. + + + + Gets or sets a value indicating whether to enable the splashscreen. + + + + + Gets or sets the splashscreen location on disk. + + + + + The branding options DTO for API use. + This DTO excludes SplashscreenLocation to prevent it from being updated via API. + + + + + Gets or sets the login disclaimer. + + The login disclaimer. + + + + Gets or sets the custom CSS. + + The custom CSS. + + + + Gets or sets a value indicating whether to enable the splashscreen. + + + + + Gets or sets the name. + + The name. + + + + Gets or sets the identifier. + + The identifier. + + + + Gets or sets a value indicating whether this instance can search. + + true if this instance can search; otherwise, false. + + + + Gets or sets the media types. + + The media types. + + + + Gets or sets the content types. + + The content types. + + + + Gets or sets the maximum number of records the channel allows retrieving at a time. + + + + + Gets or sets the automatic refresh levels. + + The automatic refresh levels. + + + + Gets or sets the default sort orders. + + The default sort orders. + + + + Gets or sets a value indicating whether a sort ascending/descending toggle is supported. + + + + + Gets or sets a value indicating whether [supports latest media]. + + true if [supports latest media]; otherwise, false. + + + + Gets or sets a value indicating whether this instance can filter. + + true if this instance can filter; otherwise, false. + + + + Gets or sets a value indicating whether [supports content downloading]. + + true if [supports content downloading]; otherwise, false. + + + + Gets or sets the fields to return within the items, in addition to basic information. + + The fields. + + + + Gets or sets the user identifier. + + The user identifier. + + + + Gets or sets the start index. Use for paging. + + The start index. + + + + Gets or sets the maximum number of items to return. + + The limit. + + + + Gets or sets a value indicating whether [supports latest items]. + + true if [supports latest items]; otherwise, false. + + + + Gets or sets a value indicating whether this instance is favorite. + + null if [is favorite] contains no value, true if [is favorite]; otherwise, false. + + + + Serves as a common base class for the Server and UI application Configurations + ProtoInclude tells Protobuf about subclasses, + The number 50 can be any number, so long as it doesn't clash with any of the ProtoMember numbers either here or in subclasses. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the number of days we should retain log files. + + The log file retention days. + + + + Gets or sets a value indicating whether this instance is first run. + + true if this instance is first run; otherwise, false. + + + + Gets or sets the cache path. + + The cache path. + + + + Gets or sets the last known version that was ran using the configuration. + + The version from previous run. + + + + Gets or sets the stringified PreviousVersion to be stored/loaded, + because System.Version itself isn't xml-serializable. + + String value of PreviousVersion. + + + + An enum representing the options to disable embedded subs. + + + + + Allow all embedded subs. + + + + + Allow only embedded subs that are text based. + + + + + Allow only embedded subs that are image based. + + + + + Disable all embedded subs. + + + + + Class EncodingOptions. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the thread count used for encoding. + + + + + Gets or sets the temporary transcoding path. + + + + + Gets or sets the path to the fallback font. + + + + + Gets or sets a value indicating whether to use the fallback font. + + + + + Gets or sets a value indicating whether audio VBR is enabled. + + + + + Gets or sets the audio boost applied when downmixing audio. + + + + + Gets or sets the algorithm used for downmixing audio to stereo. + + + + + Gets or sets the maximum size of the muxing queue. + + + + + Gets or sets a value indicating whether throttling is enabled. + + + + + Gets or sets the delay after which throttling happens. + + + + + Gets or sets a value indicating whether segment deletion is enabled. + + + + + Gets or sets seconds for which segments should be kept before being deleted. + + + + + Gets or sets the hardware acceleration type. + + + + + Gets or sets the FFmpeg path as set by the user via the UI. + + + + + Gets or sets the current FFmpeg path being used by the system and displayed on the transcode page. + + + + + Gets or sets the VA-API device. + + + + + Gets or sets the QSV device. + + + + + Gets or sets a value indicating whether tonemapping is enabled. + + + + + Gets or sets a value indicating whether VPP tonemapping is enabled. + + + + + Gets or sets a value indicating whether videotoolbox tonemapping is enabled. + + + + + Gets or sets the tone-mapping algorithm. + + + + + Gets or sets the tone-mapping mode. + + + + + Gets or sets the tone-mapping range. + + + + + Gets or sets the tone-mapping desaturation. + + + + + Gets or sets the tone-mapping peak. + + + + + Gets or sets the tone-mapping parameters. + + + + + Gets or sets the VPP tone-mapping brightness. + + + + + Gets or sets the VPP tone-mapping contrast. + + + + + Gets or sets the H264 CRF. + + + + + Gets or sets the H265 CRF. + + + + + Gets or sets the encoder preset. + + + + + Gets or sets a value indicating whether the framerate is doubled when deinterlacing. + + + + + Gets or sets the deinterlace method. + + + + + Gets or sets a value indicating whether 10bit HEVC decoding is enabled. + + + + + Gets or sets a value indicating whether 10bit VP9 decoding is enabled. + + + + + Gets or sets a value indicating whether 8/10bit HEVC RExt decoding is enabled. + + + + + Gets or sets a value indicating whether 12bit HEVC RExt decoding is enabled. + + + + + Gets or sets a value indicating whether the enhanced NVDEC is enabled. + + + + + Gets or sets a value indicating whether the system native hardware decoder should be used. + + + + + Gets or sets a value indicating whether the Intel H264 low-power hardware encoder should be used. + + + + + Gets or sets a value indicating whether the Intel HEVC low-power hardware encoder should be used. + + + + + Gets or sets a value indicating whether hardware encoding is enabled. + + + + + Gets or sets a value indicating whether HEVC encoding is enabled. + + + + + Gets or sets a value indicating whether AV1 encoding is enabled. + + + + + Gets or sets a value indicating whether subtitle extraction is enabled. + + + + + Gets or sets the timeout for subtitle extraction in minutes. + + + + + Gets or sets the codecs hardware encoding is used for. + + + + + Gets or sets the file extensions on-demand metadata based keyframe extraction is enabled for. + + + + + Gets or sets the method used for audio seeking in HLS. + + + + + An enum representing the options to seek the input audio stream when + transcoding HLS segments. + + + + + If the video stream is transcoded and the audio stream is copied, + seek the video stream to the same keyframe as the audio stream. The + resulting timestamps in the output streams may be inaccurate. + + + + + Prevent audio streams from being copied if the video stream is transcoded. + The resulting timestamps will be accurate, but additional audio transcoding + overhead will be incurred. + + + + + Gets or sets the type. + + The type. + + + + Gets or sets the limit. + + The limit. + + + + Gets or sets the minimum width. + + The minimum width. + + + + Gets or sets the preferred metadata language. + + The preferred metadata language. + + + + Gets or sets the metadata country code. + + The metadata country code. + + + + Class MetadataOptions. + + + + + Gets or sets the name. + + The name. + + + + Gets or sets the type. + + The type. + + + + Gets or sets the type of the item. + + The type of the item. + + + + Gets or sets the plugins. + + The plugins. + + + + Gets or sets the supported image types. + + The supported image types. + + + + Enum MetadataPluginType. + + + + + Defines the . + + + + + Gets or sets the value to substitute. + + + + + Gets or sets the value to substitution with. + + + + + Represents the server configuration. + + + + + Initializes a new instance of the class. + + + + + Gets or sets a value indicating whether to enable prometheus metrics exporting. + + + + + Gets or sets a value indicating whether this instance is port authorized. + + true if this instance is port authorized; otherwise, false. + + + + Gets or sets a value indicating whether quick connect is available for use on this server. + + + + + Gets or sets a value indicating whether [enable case-sensitive item ids]. + + true if [enable case-sensitive item ids]; otherwise, false. + + + + Gets or sets the metadata path. + + The metadata path. + + + + Gets or sets the preferred metadata language. + + The preferred metadata language. + + + + Gets or sets the metadata country code. + + The metadata country code. + + + + Gets or sets characters to be replaced with a ' ' in strings to create a sort name. + + The sort replace characters. + + + + Gets or sets characters to be removed from strings to create a sort name. + + The sort remove characters. + + + + Gets or sets words to be removed from strings to create a sort name. + + The sort remove words. + + + + Gets or sets the minimum percentage of an item that must be played in order for playstate to be updated. + + The min resume PCT. + + + + Gets or sets the maximum percentage of an item that can be played while still saving playstate. If this percentage is crossed playstate will be reset to the beginning and the item will be marked watched. + + The max resume PCT. + + + + Gets or sets the minimum duration that an item must have in order to be eligible for playstate updates.. + + The min resume duration seconds. + + + + Gets or sets the minimum minutes of a book that must be played in order for playstate to be updated. + + The min resume in minutes. + + + + Gets or sets the remaining minutes of a book that can be played while still saving playstate. If this percentage is crossed playstate will be reset to the beginning and the item will be marked watched. + + The remaining time in minutes. + + + + Gets or sets the threshold in minutes after a inactive session gets closed automatically. + If set to 0 the check for inactive sessions gets disabled. + + The close inactive session threshold in minutes. 0 to disable. + + + + Gets or sets the delay in seconds that we will wait after a file system change to try and discover what has been added/removed. + Some delay is necessary with some items because their creation is not atomic. It involves the creation of several + different directories and files. + Minimum value: 30 seconds. + Default value: 60 seconds. + + The file watcher delay in seconds (minimum 30). + + + + Gets or sets the duration in seconds that we will wait after a library updated event before executing the library changed notification. + + The library update duration. + + + + Gets or sets the maximum amount of items to cache. + + + + + Gets or sets the image saving convention. + + The image saving convention. + + + + Gets or sets a value indicating whether slow server responses should be logged as a warning. + + + + + Gets or sets the threshold for the slow response time warning in ms. + + + + + Gets or sets the cors hosts. + + + + + Gets or sets the number of days we should retain activity logs. + + + + + Gets or sets the how the library scan fans out. + + + + + Gets or sets the how many metadata refreshes can run concurrently. + + + + + Gets or sets a value indicating whether clients should be allowed to upload logs. + + + + + Gets or sets the dummy chapter duration in seconds, use 0 (zero) or less to disable generation altogether. + + The dummy chapters duration. + + + + Gets or sets the chapter image resolution. + + The chapter image resolution. + + + + Gets or sets the limit for parallel image encoding. + + The limit for parallel image encoding. + + + + Gets or sets the list of cast receiver applications. + + + + + Gets or sets the trickplay options. + + The trickplay options. + + + + Gets or sets a value indicating whether old authorization methods are allowed. + + + + + Class TrickplayOptions. + + + + + Gets or sets a value indicating whether or not to use HW acceleration. + + + + + Gets or sets a value indicating whether or not to use HW accelerated MJPEG encoding. + + + + + Gets or sets a value indicating whether to only extract key frames. + Significantly faster, but is not compatible with all decoders and/or video files. + + + + + Gets or sets the behavior used by trickplay provider on library scan/update. + + + + + Gets or sets the process priority for the ffmpeg process. + + + + + Gets or sets the interval, in ms, between each new trickplay image. + + + + + Gets or sets the target width resolutions, in px, to generates preview images for. + + + + + Gets or sets number of tile images to allow in X dimension. + + + + + Gets or sets number of tile images to allow in Y dimension. + + + + + Gets or sets the ffmpeg output quality level. + + + + + Gets or sets the jpeg quality to use for image tiles. + + + + + Gets or sets the number of threads to be used by ffmpeg. + + + + + Enum TrickplayScanBehavior. + + + + + Starts generation, only return once complete. + + + + + Start generation, return immediately. + + + + + Class UserConfiguration. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the audio language preference. + + The audio language preference. + + + + Gets or sets a value indicating whether [play default audio track]. + + true if [play default audio track]; otherwise, false. + + + + Gets or sets the subtitle language preference. + + The subtitle language preference. + + + + Gets or sets the id of the selected cast receiver. + + + + + Class containing global constants for Jellyfin Cryptography. + + + + + The default length for new salts. + + + + + The default output length. + + + + + The default amount of iterations for hashing passwords. + + + + + Creates a new instance. + + The password that will be hashed. + A instance with the hash method, hash, salt and number of iterations. + + + + Gets the symbolic name for the function used. + + Returns the symbolic name for the function used. + + + + Gets the additional parameters used by the hash function. + + + + + Gets the salt used for hashing the password. + + Returns the salt used for hashing the password. + + + + Gets the hashed password. + + Return the hashed password. + + + + + + + A class for device Information. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the name. + + The name. + + + + Gets or sets the custom name. + + The custom name. + + + + Gets or sets the access token. + + The access token. + + + + Gets or sets the identifier. + + The identifier. + + + + Gets or sets the last name of the user. + + The last name of the user. + + + + Gets or sets the name of the application. + + The name of the application. + + + + Gets or sets the application version. + + The application version. + + + + Gets or sets the last user identifier. + + The last user identifier. + + + + Gets or sets the date last modified. + + The date last modified. + + + + Gets or sets the capabilities. + + The capabilities. + + + + Gets or sets the icon URL. + + The icon URL. + + + + Defines the . + + + + + Initializes a new instance of the class. + + + + + Gets or sets the which this container must meet. + + + + + Gets or sets the list of which this profile must meet. + + + + + Gets or sets the list of to apply if this profile is met. + + + + + Gets or sets the codec(s) that this profile applies to. + + + + + Gets or sets the container(s) which this profile will be applied to. + + + + + Gets or sets the sub-container(s) which this profile will be applied to. + + + + + Checks to see whether the codecs and containers contain the given parameters. + + The codec to match (single codec or comma-separated list). + The container to match. + When true and Container is "hls", uses SubContainer instead of Container for matching. + True if both the codec and container conditions are met. + + + + Checks to see whether the codecs and containers contain the given parameters. + + The list of codecs to match. + The container to match. + When true and Container is "hls", uses SubContainer instead of Container for matching. + True if both the codec and container conditions are met. + + + + The condition processor. + + + + + Checks if a video condition is satisfied. + + The . + The width. + The height. + The bit depth. + The bitrate. + The video profile. + The . + The video level. + The framerate. + The packet length. + The . + A value indicating whether the video is anamorphic. + A value indicating whether the video is interlaced. + The reference frames. + The number of streams. + The number of video streams. + The number of audio streams. + The video codec tag. + A value indicating whether the video is AVC. + True if the condition is satisfied. + + + + Checks if a image condition is satisfied. + + The . + The width. + The height. + True if the condition is satisfied. + + + + Checks if an audio condition is satisfied. + + The . + The channel count. + The bitrate. + The sample rate. + The bit depth. + True if the condition is satisfied. + + + + Checks if an audio condition is satisfied for a video. + + The . + The channel count. + The bitrate. + The sample rate. + The bit depth. + The profile. + A value indicating whether the audio is a secondary track. + True if the condition is satisfied. + + + + Defines the . + + + + + Gets or sets the which this container must meet. + + + + + Gets or sets the list of which this container will be applied to. + + + + + Gets or sets the container(s) which this container must meet. + + + + + Gets or sets the sub container(s) which this container must meet. + + + + + Returns true if an item in appears in the property. + + The item to match. + Consider subcontainers. + The result of the operation. + + + + A represents a set of metadata which determines which content a certain device is able to play. +
+ Specifically, it defines the supported containers and + codecs (video and/or audio, including codec profiles and levels) + the device is able to direct play (without transcoding or remuxing), + as well as which containers/codecs to transcode to in case it isn't. +
+
+ + + Gets or sets the name of this device profile. User profiles must have a unique name. + + + + + Gets or sets the unique internal identifier. + + + + + Gets or sets the maximum allowed bitrate for all streamed content. + + + + + Gets or sets the maximum allowed bitrate for statically streamed content (= direct played files). + + + + + Gets or sets the maximum allowed bitrate for transcoded music streams. + + + + + Gets or sets the maximum allowed bitrate for statically streamed (= direct played) music files. + + + + + Gets or sets the direct play profiles. + + + + + Gets or sets the transcoding profiles. + + + + + Gets or sets the container profiles. Failing to meet these optional conditions causes transcoding to occur. + + + + + Gets or sets the codec profiles. + + + + + Gets or sets the subtitle profiles. + + + + + Defines the . + + + + + Gets or sets the container. + + + + + Gets or sets the audio codec. + + + + + Gets or sets the video codec. + + + + + Gets or sets the Dlna profile type. + + + + + Returns whether the supports the . + + The container to match against. + True if supported. + + + + Returns whether the supports the . + + The codec to match against. + True if supported. + + + + Returns whether the supports the . + + The codec to match against. + True if supported. + + + + Class MediaOptions. + + + + + Initializes a new instance of the class. + + + + + Gets or sets a value indicating whether direct playback is allowed. + + + + + Gets or sets a value indicating whether direct streaming is allowed. + + + + + Gets or sets a value indicating whether direct playback is forced. + + + + + Gets or sets a value indicating whether direct streaming is forced. + + + + + Gets or sets a value indicating whether audio stream copy is allowed. + + + + + Gets or sets a value indicating whether video stream copy is allowed. + + + + + Gets or sets a value indicating whether always burn in subtitles when transcoding. + + + + + Gets or sets the item id. + + + + + Gets or sets the media sources. + + + + + Gets or sets the device profile. + + + + + Gets or sets a media source id. Optional. Only needed if a specific AudioStreamIndex or SubtitleStreamIndex are requested. + + + + + Gets or sets the device id. + + + + + Gets or sets an override of supported number of audio channels + Example: DeviceProfile supports five channel, but user only has stereo speakers. + + + + + Gets or sets the application's configured maximum bitrate. + + + + + Gets or sets the context. + + The context. + + + + Gets or sets the audio transcoding bitrate. + + The audio transcoding bitrate. + + + + Gets or sets an override for the audio stream index. + + + + + Gets or sets an override for the subtitle stream index. + + + + + Gets the maximum bitrate. + + Whether or not this is audio. + System.Nullable<System.Int32>. + + + + Initializes a new instance of the class. + + The maximum width. + The maximum bitrate. + + + + Normalizes resolution options based on bitrate and dimensions. + + The input bitrate. + The output bitrate. + The H264 equivalent output bitrate. + The maximum width. + The maximum height. + The target frames per second. + Whether the content is HDR. + The normalized resolution options. + + + + Class StreamBuilder. + + + + + Initializes a new instance of the class. + + The object. + The object. + + + + Gets the optimal audio stream. + + The object to get the audio stream from. + The of the optimal audio stream. + + + + Gets the optimal video stream. + + The object to get the video stream from. + The of the optimal video stream. + + + + Normalizes input container. + + The input container. + The . + The . + The object to get the video stream from. + The normalized input container. + + + + Normalizes input container. + + The . + The of the subtitle stream. + The list of supported s. + The . + The . + The output container. + The subtitle transcoding protocol. + The normalized input container. + + + + Check the profile conditions. + + Profile conditions. + Media source. + Video stream. + Failed profile conditions. + + + + Check the compatibility of the container. + + Media options. + Media source. + Container. + Video stream. + Transcode reasons if the container is not fully compatible. + + + + Check the compatibility of the video codec. + + Media options. + Media source. + Container. + Video stream. + Transcode reasons if the video stream is not fully compatible. + + + + Check the compatibility of the audio codec. + + Media options. + Media source. + Container. + Audio stream. + Override audio codec. + The media source is video. + The audio stream is secondary. + Transcode reasons if the audio stream is not fully compatible. + + + + Check the compatibility of the audio codec for direct playback. + + Media options. + Media source. + Container. + Audio stream. + The media source is video. + The audio stream is secondary. + Transcode reasons if the audio stream is not fully compatible for direct playback. + + + + Class holding information on a stream. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the item id. + + The item id. + + + + Gets or sets the play method. + + The play method. + + + + Gets or sets the encoding context. + + The encoding context. + + + + Gets or sets the media type. + + The media type. + + + + Gets or sets the container. + + The container. + + + + Gets or sets the sub protocol. + + The sub protocol. + + + + Gets or sets the start position ticks. + + The start position ticks. + + + + Gets or sets the segment length. + + The segment length. + + + + Gets or sets the minimum segments count. + + The minimum segments count. + + + + Gets or sets a value indicating whether the stream requires AVC. + + + + + Gets or sets a value indicating whether the stream requires AVC. + + + + + Gets or sets a value indicating whether timestamps should be copied. + + + + + Gets or sets a value indicating whether timestamps should be copied. + + + + + Gets or sets a value indicating whether the subtitle manifest is enabled. + + + + + Gets or sets the audio codecs. + + The audio codecs. + + + + Gets or sets the video codecs. + + The video codecs. + + + + Gets or sets the audio stream index. + + The audio stream index. + + + + Gets or sets the video stream index. + + The subtitle stream index. + + + + Gets or sets the maximum transcoding audio channels. + + The maximum transcoding audio channels. + + + + Gets or sets the global maximum audio channels. + + The global maximum audio channels. + + + + Gets or sets the audio bitrate. + + The audio bitrate. + + + + Gets or sets the audio sample rate. + + The audio sample rate. + + + + Gets or sets the video bitrate. + + The video bitrate. + + + + Gets or sets the maximum output width. + + The output width. + + + + Gets or sets the maximum output height. + + The maximum output height. + + + + Gets or sets the maximum framerate. + + The maximum framerate. + + + + Gets or sets the device profile. + + The device profile. + + + + Gets or sets the device profile id. + + The device profile id. + + + + Gets or sets the device id. + + The device id. + + + + Gets or sets the runtime ticks. + + The runtime ticks. + + + + Gets or sets the transcode seek info. + + The transcode seek info. + + + + Gets or sets a value indicating whether content length should be estimated. + + + + + Gets or sets the media source info. + + The media source info. + + + + Gets or sets the subtitle codecs. + + The subtitle codecs. + + + + Gets or sets the subtitle delivery method. + + The subtitle delivery method. + + + + Gets or sets the subtitle format. + + The subtitle format. + + + + Gets or sets the play session id. + + The play session id. + + + + Gets or sets the transcode reasons. + + The transcode reasons. + + + + Gets the stream options. + + The stream options. + + + + Gets the media source id. + + The media source id. + + + + Gets or sets a value indicating whether audio VBR encoding is enabled. + + + + + Gets or sets a value indicating whether always burn in subtitles when transcoding. + + + + + Gets a value indicating whether the stream is direct. + + + + + Gets the audio stream that will be used in the output stream. + + The audio stream. + + + + Gets the video stream that will be used in the output stream. + + The video stream. + + + + Gets the audio sample rate that will be in the output stream. + + The target audio sample rate. + + + + Gets the audio bit depth that will be in the output stream. + + The target bit depth. + + + + Gets the video bit depth that will be in the output stream. + + The target video bit depth. + + + + Gets the target reference frames that will be in the output stream. + + The target reference frames. + + + + Gets the target framerate that will be in the output stream. + + The target framerate. + + + + Gets the target video level that will be in the output stream. + + The target video level. + + + + Gets the target packet length that will be in the output stream. + + The target packet length. + + + + Gets the target video profile that will be in the output stream. + + The target video profile. + + + + Gets the target video range type that will be in the output stream. + + The video range type. + + + + Gets the target video codec tag. + + The video codec tag. + + + + Gets the audio bitrate that will be in the output stream. + + The audio bitrate. + + + + Gets the amount of audio channels that will be in the output stream. + + The target audio channels. + + + + Gets the audio codec that will be in the output stream. + + The audio codec. + + + + Gets the video codec that will be in the output stream. + + The target video codec. + + + + Gets the target size of the output stream. + + The target size. + + + + Gets the target video bitrate of the output stream. + + The video bitrate. + + + + Gets the target timestamp of the output stream. + + The target timestamp. + + + + Gets the target total bitrate of the output stream. + + The target total bitrate. + + + + Gets a value indicating whether the output stream is anamorphic. + + + + + Gets a value indicating whether the output stream is interlaced. + + + + + Gets a value indicating whether the output stream is AVC. + + + + + Gets the target width of the output stream. + + The target width. + + + + Gets the target height of the output stream. + + The target height. + + + + Gets the target video stream count of the output stream. + + The target video stream count. + + + + Gets the target audio stream count of the output stream. + + The target audio stream count. + + + + Sets a stream option. + + The qualifier. + The name. + The value. + + + + Sets a stream option. + + The name. + The value. + + + + Gets a stream option. + + The qualifier. + The name. + The value. + + + + Gets a stream option. + + The name. + The value. + + + + Returns this output stream URL for this class. + + The base Url. + The access Token. + Optional extra query. + A querystring representation of this object. + + + + Gets the subtitle profiles. + + The transcoder support. + If only the selected track should be included. + The base URL. + The access token. + The of the profiles. + + + + Gets the subtitle profiles. + + The transcoder support. + If only the selected track should be included. + If all profiles are enabled. + The base URL. + The access token. + The of the profiles. + + + + Gets the target video bit depth. + + The codec. + The target video bit depth. + + + + Gets the target audio bit depth. + + The codec. + The target audio bit depth. + + + + Gets the target video level. + + The codec. + The target video level. + + + + Gets the target reference frames. + + The codec. + The target reference frames. + + + + Gets the target audio channels. + + The codec. + The target audio channels. + + + + Gets the media stream count. + + The type. + The limit. + The media stream count. + + + + Delivery method to use during playback of a specific subtitle format. + + + + + Burn the subtitles in the video track. + + + + + Embed the subtitles in the file or stream. + + + + + Serve the subtitles as an external file. + + + + + Serve the subtitles as a separate HLS stream. + + + + + Drop the subtitle. + + + + + A class for subtitle profile information. + + + + + Gets or sets the format. + + + + + Gets or sets the delivery method. + + + + + Gets or sets the DIDL mode. + + + + + Gets or sets the language. + + + + + Gets or sets the container. + + + + + Checks if a language is supported. + + The language to check for support. + true if supported. + + + + A class for transcoding profile information. + Note for client developers: Conditions defined in has higher priority and can override values defined here. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class copying the values from another instance. + + Another instance of to be copied. + + + + Gets or sets the container. + + + + + Gets or sets the DLNA profile type. + + + + + Gets or sets the video codec. + + + + + Gets or sets the audio codec. + + + + + Gets or sets the protocol. + + + + + Gets or sets a value indicating whether the content length should be estimated. + + + + + Gets or sets a value indicating whether M2TS mode is enabled. + + + + + Gets or sets the transcoding seek info mode. + + + + + Gets or sets a value indicating whether timestamps should be copied. + + + + + Gets or sets the encoding context. + + + + + Gets or sets a value indicating whether subtitles are allowed in the manifest. + + + + + Gets or sets the maximum audio channels. + + + + + Gets or sets the minimum amount of segments. + + + + + Gets or sets the segment length. + + + + + Gets or sets a value indicating whether breaking the video stream on non-keyframes is supported. + + + + + Gets or sets the profile conditions. + + + + + Gets or sets a value indicating whether variable bitrate encoding is supported. + + + + + Class DrawingUtils. + + + + + Resizes a set of dimensions. + + The original size object. + A new fixed width, if desired. + A new fixed height, if desired. + A max fixed width, if desired. + A max fixed height, if desired. + A new size object. + + + + Scale down to fill box. + Returns original size if both width and height are null or zero. + + The original size object. + A new fixed width, if desired. + A new fixed height, if desired. + A new size object or size. + + + + Gets the new width. + + Height of the current. + Width of the current. + The new height. + The new width. + + + + Gets the new height. + + Height of the current. + Width of the current. + The new width. + System.Double. + + + + Struct ImageDimensions. + + + + + Gets the height. + + The height. + + + + Gets the width. + + The width. + + + + + + + Enum ImageOutputFormat. + + + + + BMP format. + + + + + GIF format. + + + + + JPG format. + + + + + PNG format. + + + + + WEBP format. + + + + + SVG format. + + + + + Extension class for the enum. + + + + + Returns the correct mime type for this . + + This . + The is an invalid enumeration value. + The correct mime type for this . + + + + Returns the correct extension for this . + + This . + The is an invalid enumeration value. + The correct extension for this . + + + + Enum ImageResolution. + + + + + MatchSource. + + + + + 144p. + + + + + 240p. + + + + + 360p. + + + + + 480p. + + + + + 720p. + + + + + 1080p. + + + + + 1440p. + + + + + 2160p. + + + + + This is strictly used as a data transfer object from the api layer. + This holds information about a BaseItem in a format that is convenient for the client. + + + + + Gets or sets the name. + + The name. + + + + Gets or sets the server identifier. + + The server identifier. + + + + Gets or sets the id. + + The id. + + + + Gets or sets the etag. + + The etag. + + + + Gets or sets the type of the source. + + The type of the source. + + + + Gets or sets the playlist item identifier. + + The playlist item identifier. + + + + Gets or sets the date created. + + The date created. + + + + Gets or sets the name of the sort. + + The name of the sort. + + + + Gets or sets the video3 D format. + + The video3 D format. + + + + Gets or sets the premiere date. + + The premiere date. + + + + Gets or sets the external urls. + + The external urls. + + + + Gets or sets the media versions. + + The media versions. + + + + Gets or sets the critic rating. + + The critic rating. + + + + Gets or sets the path. + + The path. + + + + Gets or sets the official rating. + + The official rating. + + + + Gets or sets the custom rating. + + The custom rating. + + + + Gets or sets the channel identifier. + + The channel identifier. + + + + Gets or sets the overview. + + The overview. + + + + Gets or sets the taglines. + + The taglines. + + + + Gets or sets the genres. + + The genres. + + + + Gets or sets the community rating. + + The community rating. + + + + Gets or sets the cumulative run time ticks. + + The cumulative run time ticks. + + + + Gets or sets the run time ticks. + + The run time ticks. + + + + Gets or sets the play access. + + The play access. + + + + Gets or sets the aspect ratio. + + The aspect ratio. + + + + Gets or sets the production year. + + The production year. + + + + Gets or sets a value indicating whether this instance is place holder. + + null if [is place holder] contains no value, true if [is place holder]; otherwise, false. + + + + Gets or sets the number. + + The number. + + + + Gets or sets the index number. + + The index number. + + + + Gets or sets the index number end. + + The index number end. + + + + Gets or sets the parent index number. + + The parent index number. + + + + Gets or sets the trailer urls. + + The trailer urls. + + + + Gets or sets the provider ids. + + The provider ids. + + + + Gets or sets a value indicating whether this instance is HD. + + null if [is HD] contains no value, true if [is HD]; otherwise, false. + + + + Gets or sets a value indicating whether this instance is folder. + + true if this instance is folder; otherwise, false. + + + + Gets or sets the parent id. + + The parent id. + + + + Gets or sets the type. + + The type. + + + + Gets or sets the people. + + The people. + + + + Gets or sets the studios. + + The studios. + + + + Gets or sets whether the item has a logo, this will hold the Id of the Parent that has one. + + The parent logo item id. + + + + Gets or sets whether the item has any backdrops, this will hold the Id of the Parent that has one. + + The parent backdrop item id. + + + + Gets or sets the parent backdrop image tags. + + The parent backdrop image tags. + + + + Gets or sets the local trailer count. + + The local trailer count. + + + + Gets or sets the user data for this item based on the user it's being requested for. + + The user data. + + + + Gets or sets the recursive item count. + + The recursive item count. + + + + Gets or sets the child count. + + The child count. + + + + Gets or sets the name of the series. + + The name of the series. + + + + Gets or sets the series id. + + The series id. + + + + Gets or sets the season identifier. + + The season identifier. + + + + Gets or sets the special feature count. + + The special feature count. + + + + Gets or sets the display preferences id. + + The display preferences id. + + + + Gets or sets the status. + + The status. + + + + Gets or sets the air time. + + The air time. + + + + Gets or sets the air days. + + The air days. + + + + Gets or sets the tags. + + The tags. + + + + Gets or sets the primary image aspect ratio, after image enhancements. + + The primary image aspect ratio. + + + + Gets or sets the artists. + + The artists. + + + + Gets or sets the artist items. + + The artist items. + + + + Gets or sets the album. + + The album. + + + + Gets or sets the type of the collection. + + The type of the collection. + + + + Gets or sets the display order. + + The display order. + + + + Gets or sets the album id. + + The album id. + + + + Gets or sets the album image tag. + + The album image tag. + + + + Gets or sets the series primary image tag. + + The series primary image tag. + + + + Gets or sets the album artist. + + The album artist. + + + + Gets or sets the album artists. + + The album artists. + + + + Gets or sets the name of the season. + + The name of the season. + + + + Gets or sets the media streams. + + The media streams. + + + + Gets or sets the type of the video. + + The type of the video. + + + + Gets or sets the part count. + + The part count. + + + + Gets or sets the image tags. + + The image tags. + + + + Gets or sets the backdrop image tags. + + The backdrop image tags. + + + + Gets or sets the screenshot image tags. + + The screenshot image tags. + + + + Gets or sets the parent logo image tag. + + The parent logo image tag. + + + + Gets or sets whether the item has fan art, this will hold the Id of the Parent that has one. + + The parent art item id. + + + + Gets or sets the parent art image tag. + + The parent art image tag. + + + + Gets or sets the series thumb image tag. + + The series thumb image tag. + + + + Gets or sets the blurhashes for the image tags. + Maps image type to dictionary mapping image tag to blurhash value. + + The blurhashes. + + + + Gets or sets the series studio. + + The series studio. + + + + Gets or sets the parent thumb item id. + + The parent thumb item id. + + + + Gets or sets the parent thumb image tag. + + The parent thumb image tag. + + + + Gets or sets the parent primary image item identifier. + + The parent primary image item identifier. + + + + Gets or sets the parent primary image tag. + + The parent primary image tag. + + + + Gets or sets the chapters. + + The chapters. + + + + Gets or sets the trickplay manifest. + + The trickplay manifest. + + + + Gets or sets the type of the location. + + The type of the location. + + + + Gets or sets the type of the iso. + + The type of the iso. + + + + Gets or sets the type of the media. + + The type of the media. + + + + Gets or sets the end date. + + The end date. + + + + Gets or sets the locked fields. + + The locked fields. + + + + Gets or sets the trailer count. + + The trailer count. + + + + Gets or sets the movie count. + + The movie count. + + + + Gets or sets the series count. + + The series count. + + + + Gets or sets the episode count. + + The episode count. + + + + Gets or sets the song count. + + The song count. + + + + Gets or sets the album count. + + The album count. + + + + Gets or sets the music video count. + + The music video count. + + + + Gets or sets a value indicating whether [enable internet providers]. + + true if [enable internet providers]; otherwise, false. + + + + Gets or sets the series timer identifier. + + The series timer identifier. + + + + Gets or sets the program identifier. + + The program identifier. + + + + Gets or sets the channel primary image tag. + + The channel primary image tag. + + + + Gets or sets the start date of the recording, in UTC. + + + + + Gets or sets the completion percentage. + + The completion percentage. + + + + Gets or sets a value indicating whether this instance is repeat. + + true if this instance is repeat; otherwise, false. + + + + Gets or sets the episode title. + + The episode title. + + + + Gets or sets the type of the channel. + + The type of the channel. + + + + Gets or sets the audio. + + The audio. + + + + Gets or sets a value indicating whether this instance is movie. + + true if this instance is movie; otherwise, false. + + + + Gets or sets a value indicating whether this instance is sports. + + true if this instance is sports; otherwise, false. + + + + Gets or sets a value indicating whether this instance is series. + + true if this instance is series; otherwise, false. + + + + Gets or sets a value indicating whether this instance is live. + + true if this instance is live; otherwise, false. + + + + Gets or sets a value indicating whether this instance is news. + + true if this instance is news; otherwise, false. + + + + Gets or sets a value indicating whether this instance is kids. + + true if this instance is kids; otherwise, false. + + + + Gets or sets a value indicating whether this instance is premiere. + + true if this instance is premiere; otherwise, false. + + + + Gets or sets the timer identifier. + + The timer identifier. + + + + Gets or sets the gain required for audio normalization. + + The gain required for audio normalization. + + + + Gets or sets the current program. + + The current program. + + + + This is used by the api to get information about a Person within a BaseItem. + + + + + Gets or sets the name. + + The name. + + + + Gets or sets the identifier. + + The identifier. + + + + Gets or sets the role. + + The role. + + + + Gets or sets the type. + + The type. + + + + Gets or sets the primary image tag. + + The primary image tag. + + + + Gets or sets the primary image blurhash. + + The primary image blurhash. + + + + Gets a value indicating whether this instance has primary image. + + true if this instance has primary image; otherwise, false. + + + + Client capabilities dto. + + + + + Gets or sets the list of playable media types. + + + + + Gets or sets the list of supported commands. + + + + + Gets or sets a value indicating whether session supports media control. + + + + + Gets or sets a value indicating whether session supports a persistent identifier. + + + + + Gets or sets the device profile. + + + + + Gets or sets the app store url. + + + + + Gets or sets the icon url. + + + + + Convert the dto to the full model. + + The converted model. + + + + A DTO representing device information. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the name. + + The name. + + + + Gets or sets the custom name. + + The custom name. + + + + Gets or sets the access token. + + The access token. + + + + Gets or sets the identifier. + + The identifier. + + + + Gets or sets the last name of the user. + + The last name of the user. + + + + Gets or sets the name of the application. + + The name of the application. + + + + Gets or sets the application version. + + The application version. + + + + Gets or sets the last user identifier. + + The last user identifier. + + + + Gets or sets the date last modified. + + The date last modified. + + + + Gets or sets the capabilities. + + The capabilities. + + + + Gets or sets the icon URL. + + The icon URL. + + + + Defines the display preferences for any item that supports them (usually Folders). + + + + + Initializes a new instance of the class. + + + + + Gets or sets the user id. + + The user id. + + + + Gets or sets the type of the view. + + The type of the view. + + + + Gets or sets the sort by. + + The sort by. + + + + Gets or sets the index by. + + The index by. + + + + Gets or sets a value indicating whether [remember indexing]. + + true if [remember indexing]; otherwise, false. + + + + Gets or sets the height of the primary image. + + The height of the primary image. + + + + Gets or sets the width of the primary image. + + The width of the primary image. + + + + Gets or sets the custom prefs. + + The custom prefs. + + + + Gets or sets the scroll direction. + + The scroll direction. + + + + Gets or sets a value indicating whether to show backdrops on this item. + + true if showing backdrops; otherwise, false. + + + + Gets or sets a value indicating whether [remember sorting]. + + true if [remember sorting]; otherwise, false. + + + + Gets or sets the sort order. + + The sort order. + + + + Gets or sets a value indicating whether [show sidebar]. + + true if [show sidebar]; otherwise, false. + + + + Gets or sets the client. + + + + + Interface IItemDto. + + + + + Gets or sets the primary image aspect ratio. + + The primary image aspect ratio. + + + + Class ImageInfo. + + + + + Gets or sets the type of the image. + + The type of the image. + + + + Gets or sets the index of the image. + + The index of the image. + + + + Gets or sets the image tag. + + + + + Gets or sets the path. + + The path. + + + + Gets or sets the blurhash. + + The blurhash. + + + + Gets or sets the height. + + The height. + + + + Gets or sets the width. + + The width. + + + + Gets or sets the size. + + The size. + + + + Class LibrarySummary. + + + + + Gets or sets the movie count. + + The movie count. + + + + Gets or sets the series count. + + The series count. + + + + Gets or sets the episode count. + + The episode count. + + + + Gets or sets the artist count. + + The artist count. + + + + Gets or sets the program count. + + The program count. + + + + Gets or sets the trailer count. + + The trailer count. + + + + Gets or sets the song count. + + The song count. + + + + Gets or sets the album count. + + The album count. + + + + Gets or sets the music video count. + + The music video count. + + + + Gets or sets the box set count. + + The box set count. + + + + Gets or sets the book count. + + The book count. + + + + Gets or sets the item count. + + The item count. + + + + Adds all counts. + + The total of the counts. + + + + Gets or sets a value indicating whether the media is remote. + Differentiate internet url vs local network. + + + + + A class representing metadata editor information. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the parental rating options. + + + + + Gets or sets the countries. + + + + + Gets or sets the cultures. + + + + + Gets or sets the external id infos. + + + + + Gets or sets the content type. + + + + + Gets or sets the content type options. + + + + + Gets or sets the name. + + The name. + + + + Gets or sets the identifier. + + The identifier. + + + + Gets or sets the name. + + The name. + + + + Gets or sets the value. + + The value. + + + + DTO for playlists. + + + + + Gets or sets a value indicating whether the playlist is publicly readable. + + + + + Gets or sets the share permissions. + + + + + Gets or sets the item ids. + + + + + Session info DTO. + + + + + Gets or sets the play state. + + The play state. + + + + Gets or sets the additional users. + + The additional users. + + + + Gets or sets the client capabilities. + + The client capabilities. + + + + Gets or sets the remote end point. + + The remote end point. + + + + Gets or sets the playable media types. + + The playable media types. + + + + Gets or sets the id. + + The id. + + + + Gets or sets the user id. + + The user id. + + + + Gets or sets the username. + + The username. + + + + Gets or sets the type of the client. + + The type of the client. + + + + Gets or sets the last activity date. + + The last activity date. + + + + Gets or sets the last playback check in. + + The last playback check in. + + + + Gets or sets the last paused date. + + The last paused date. + + + + Gets or sets the name of the device. + + The name of the device. + + + + Gets or sets the type of the device. + + The type of the device. + + + + Gets or sets the now playing item. + + The now playing item. + + + + Gets or sets the now viewing item. + + The now viewing item. + + + + Gets or sets the device id. + + The device id. + + + + Gets or sets the application version. + + The application version. + + + + Gets or sets the transcoding info. + + The transcoding info. + + + + Gets or sets a value indicating whether this session is active. + + true if this session is active; otherwise, false. + + + + Gets or sets a value indicating whether the session supports media control. + + true if this session supports media control; otherwise, false. + + + + Gets or sets a value indicating whether the session supports remote control. + + true if this session supports remote control; otherwise, false. + + + + Gets or sets the now playing queue. + + The now playing queue. + + + + Gets or sets the now playing queue full items. + + The now playing queue full items. + + + + Gets or sets a value indicating whether the session has a custom device name. + + true if this session has a custom device name; otherwise, false. + + + + Gets or sets the playlist item id. + + The playlist item id. + + + + Gets or sets the server id. + + The server id. + + + + Gets or sets the user primary image tag. + + The user primary image tag. + + + + Gets or sets the supported commands. + + The supported commands. + + + + The trickplay api model. + + + + + Initializes a new instance of the class. + + The trickplay info. + + + + Gets the width of an individual thumbnail. + + + + + Gets the height of an individual thumbnail. + + + + + Gets the amount of thumbnails per row. + + + + + Gets the amount of thumbnails per column. + + + + + Gets the total amount of non-black thumbnails. + + + + + Gets the interval in milliseconds between each trickplay thumbnail. + + + + + Gets the peak bandwidth usage in bits per second. + + + + + This is used by the api to get information about a item user data. + + + + + Gets or sets the rating. + + The rating. + + + + Gets or sets the played percentage. + + The played percentage. + + + + Gets or sets the unplayed item count. + + The unplayed item count. + + + + Gets or sets the playback position ticks. + + The playback position ticks. + + + + Gets or sets the play count. + + The play count. + + + + Gets or sets a value indicating whether this instance is favorite. + + true if this instance is favorite; otherwise, false. + + + + Gets or sets a value indicating whether this is likes. + + null if [likes] contains no value, true if [likes]; otherwise, false. + + + + Gets or sets the last played date. + + The last played date. + + + + Gets or sets a value indicating whether this is played. + + true if played; otherwise, false. + + + + Gets or sets the key. + + The key. + + + + Gets or sets the item identifier. + + The item identifier. + + + + Class UserDto. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the name. + + The name. + + + + Gets or sets the server identifier. + + The server identifier. + + + + Gets or sets the name of the server. + This is not used by the server and is for client-side usage only. + + The name of the server. + + + + Gets or sets the id. + + The id. + + + + Gets or sets the primary image tag. + + The primary image tag. + + + + Gets or sets a value indicating whether this instance has password. + + true if this instance has password; otherwise, false. + + + + Gets or sets a value indicating whether this instance has configured password. + + true if this instance has configured password; otherwise, false. + + + + Gets or sets a value indicating whether this instance has configured easy password. + + true if this instance has configured easy password; otherwise, false. + + + + Gets or sets whether async login is enabled or not. + + + + + Gets or sets the last login date. + + The last login date. + + + + Gets or sets the last activity date. + + The last activity date. + + + + Gets or sets the configuration. + + The configuration. + + + + Gets or sets the policy. + + The policy. + + + + Gets or sets the primary image aspect ratio. + + The primary image aspect ratio. + + + + + + + Class UserItemDataDto. + + + + + Gets or sets the rating. + + The rating. + + + + Gets or sets the played percentage. + + The played percentage. + + + + Gets or sets the unplayed item count. + + The unplayed item count. + + + + Gets or sets the playback position ticks. + + The playback position ticks. + + + + Gets or sets the play count. + + The play count. + + + + Gets or sets a value indicating whether this instance is favorite. + + true if this instance is favorite; otherwise, false. + + + + Gets or sets a value indicating whether this is likes. + + null if [likes] contains no value, true if [likes]; otherwise, false. + + + + Gets or sets the last played date. + + The last played date. + + + + Gets or sets a value indicating whether this is played. + + true if played; otherwise, false. + + + + Gets or sets the key. + + The key. + + + + Gets or sets the item identifier. + + The item identifier. + + + + Class ChapterInfo. + + + + + Gets or sets the start position ticks. + + The start position ticks. + + + + Gets or sets the name. + + The name. + + + + Gets or sets the image path. + + The image path. + + + + The collection type options. + + + + + Movies. + + + + + TV Shows. + + + + + Music. + + + + + Music Videos. + + + + + Home Videos (and Photos). + + + + + Box Sets. + + + + + Books. + + + + + Mixed Movies and TV Shows. + + + + + Enum containing deinterlace methods. + + + + + YADIF. + + + + + BWDIF. + + + + + An enum representing an algorithm to downmix surround sound to stereo. + + + + + No special algorithm. + + + + + Algorithm by Dave_750. + Sourced from https://superuser.com/questions/852400/properly-downmix-5-1-to-stereo-using-ffmpeg/1410620#1410620. + + + + + Nightmode Dialogue algorithm. + Sourced from https://superuser.com/questions/852400/properly-downmix-5-1-to-stereo-using-ffmpeg/1410620#1410620. + + + + + RFC7845 Section 5.1.1.5 defined algorithm. + + + + + AC-4 standard algorithm with its default gain values. + Defined in ETSI TS 103 190 Section 6.2.17. + + + + + Enum containing encoder presets. + + + + + Auto preset. + + + + + Placebo preset. + + + + + Veryslow preset. + + + + + Slower preset. + + + + + Slow preset. + + + + + Medium preset. + + + + + Fast preset. + + + + + Faster preset. + + + + + Veryfast preset. + + + + + Superfast preset. + + + + + Ultrafast preset. + + + + + Enum containing hardware acceleration types. + + + + + Software acceleration. + + + + + AMD AMF. + + + + + Intel Quick Sync Video. + + + + + NVIDIA NVENC. + + + + + Video4Linux2 V4L2M2M. + + + + + Video Acceleration API (VAAPI). + + + + + Video ToolBox. + + + + + Rockchip Media Process Platform (RKMPP). + + + + + Since BaseItem and DTOBaseItem both have ProviderIds, this interface helps avoid code repetition by using extension methods. + + + + + Gets or sets the provider ids. + + The provider ids. + + + + Interface for access to shares. + + + + + Gets or sets the shares. + + + + + Enum ImageType. + + + + + The primary. + + + + + The art. + + + + + The backdrop. + + + + + The banner. + + + + + The logo. + + + + + The thumb. + + + + + The disc. + + + + + The box. + + + + + The screenshot. + + + This enum value is obsolete. + XmlSerializer does not serialize/deserialize objects that are marked as [Obsolete]. + + + + + The menu. + + + + + The chapter image. + + + + + The box rear. + + + + + The user profile image. + + + + + Enum IsoType. + + + + + The DVD. + + + + + The blu ray. + + + + + Class LibraryUpdateInfo. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the folders added to. + + The folders added to. + + + + Gets or sets the folders removed from. + + The folders removed from. + + + + Gets or sets the items added. + + The items added. + + + + Gets or sets the items removed. + + The items removed. + + + + Gets or sets the items updated. + + The items updated. + + + + Enum LocationType. + + + + + The file system. + + + + + The remote. + + + + + The virtual. + + + + + The offline. + + + + + Class MediaAttachment. + + + + + Gets or sets the codec. + + The codec. + + + + Gets or sets the codec tag. + + The codec tag. + + + + Gets or sets the comment. + + The comment. + + + + Gets or sets the index. + + The index. + + + + Gets or sets the filename. + + The filename. + + + + Gets or sets the MIME type. + + The MIME type. + + + + Gets or sets the delivery URL. + + The delivery URL. + + + + Class MediaStream. + + + + + Special ISO 639-2 language codes that should not be displayed in the UI. + + + + + Gets or sets the codec. + + The codec. + + + + Gets or sets the codec tag. + + The codec tag. + + + + Gets or sets the language. + + The language. + + + + Gets or sets the color range. + + The color range. + + + + Gets or sets the color space. + + The color space. + + + + Gets or sets the color transfer. + + The color transfer. + + + + Gets or sets the color primaries. + + The color primaries. + + + + Gets or sets the Dolby Vision version major. + + The Dolby Vision version major. + + + + Gets or sets the Dolby Vision version minor. + + The Dolby Vision version minor. + + + + Gets or sets the Dolby Vision profile. + + The Dolby Vision profile. + + + + Gets or sets the Dolby Vision level. + + The Dolby Vision level. + + + + Gets or sets the Dolby Vision rpu present flag. + + The Dolby Vision rpu present flag. + + + + Gets or sets the Dolby Vision el present flag. + + The Dolby Vision el present flag. + + + + Gets or sets the Dolby Vision bl present flag. + + The Dolby Vision bl present flag. + + + + Gets or sets the Dolby Vision bl signal compatibility id. + + The Dolby Vision bl signal compatibility id. + + + + Gets or sets the Rotation in degrees. + + The video rotation. + + + + Gets or sets the comment. + + The comment. + + + + Gets or sets the time base. + + The time base. + + + + Gets or sets the codec time base. + + The codec time base. + + + + Gets or sets the title. + + The title. + + + + Gets or sets a value indicating whether the HDR10+ present flag. + + The HDR10+ present flag. + + + + Gets the video range. + + The video range. + + + + Gets the video range type. + + The video range type. + + + + Gets the video dovi title. + + The video dovi title. + + + + Gets the audio spatial format. + + The audio spatial format. + + + + Gets or sets the localized text for undefined language. + + The localized text for undefined language. + + + + Gets or sets the localized text for default stream indicator. + + The localized text for default stream indicator. + + + + Gets or sets the localized text for forced stream indicator. + + The localized text for forced stream indicator. + + + + Gets or sets the localized text for external stream indicator. + + The localized text for external stream indicator. + + + + Gets or sets the localized text for hearing impaired indicator. + + The localized text for hearing impaired indicator. + + + + Gets or sets the localized language name. + + The localized language name. + + + + Gets the display title for the media stream. + + The display title. + + + + Gets or sets the NAL length size. + + The NAL length size. + + + + Gets or sets a value indicating whether this instance is interlaced. + + true if this instance is interlaced; otherwise, false. + + + + Gets or sets a value indicating whether this instance is AVC. + + true if this instance is AVC; otherwise, false. + + + + Gets or sets the channel layout. + + The channel layout. + + + + Gets or sets the bit rate. + + The bit rate. + + + + Gets or sets the bit depth. + + The bit depth. + + + + Gets or sets the reference frames. + + The reference frames. + + + + Gets or sets the length of the packet. + + The length of the packet. + + + + Gets or sets the channels. + + The channels. + + + + Gets or sets the sample rate. + + The sample rate. + + + + Gets or sets a value indicating whether this instance is default. + + true if this instance is default; otherwise, false. + + + + Gets or sets a value indicating whether this instance is forced. + + true if this instance is forced; otherwise, false. + + + + Gets or sets a value indicating whether this instance is for the hearing impaired. + + true if this instance is for the hearing impaired; otherwise, false. + + + + Gets or sets the height. + + The height. + + + + Gets or sets the width. + + The width. + + + + Gets or sets the average frame rate. + + The average frame rate. + + + + Gets or sets the real frame rate. + + The real frame rate. + + + + Gets the framerate used as reference. + Prefer AverageFrameRate, if that is null or an unrealistic value + then fallback to RealFrameRate. + + The reference frame rate. + + + + Gets or sets the profile. + + The profile. + + + + Gets or sets the type. + + The type. + + + + Gets or sets the aspect ratio. + + The aspect ratio. + + + + Gets or sets the index. + + The index. + + + + Gets or sets the score. + + The score. + + + + Gets or sets a value indicating whether this instance is external. + + true if this instance is external; otherwise, false. + + + + Gets or sets the method. + + The method. + + + + Gets or sets the delivery URL. + + The delivery URL. + + + + Gets or sets a value indicating whether this instance is external URL. + + null if [is external URL] contains no value, true if [is external URL]; otherwise, false. + + + + Gets a value indicating whether this instance is a text subtitle stream. + + true if this instance is a text subtitle stream; otherwise, false. + + + + Gets a value indicating whether this instance is a PGS subtitle stream. + + true if this instance is a PGS subtitle stream; otherwise, false. + + + + Gets a value indicating whether this is a subtitle steam that is extractable by ffmpeg. + All text-based and pgs subtitles can be extracted. + + true if this is a extractable subtitle steam otherwise, false. + + + + Gets or sets a value indicating whether [supports external stream]. + + true if [supports external stream]; otherwise, false. + + + + Gets or sets the filename. + + The filename. + + + + Gets or sets the pixel format. + + The pixel format. + + + + Gets or sets the level. + + The level. + + + + Gets or sets whether this instance is anamorphic. + + true if this instance is anamorphic; otherwise, false. + + + + Determines whether the specified format is a text-based subtitle format. + + The subtitle format/codec to check. + true if the format is text-based; otherwise, false. + + + + Determines whether the specified format is a PGS (Presentation Graphic Stream) subtitle format. + + The subtitle format/codec to check. + true if the format is PGS; otherwise, false. + + + + Determines whether this subtitle stream can be converted to the specified codec. + + The target codec to convert to. + true if the subtitle stream can be converted to the specified codec; otherwise, false. + + + + Gets the video color range information based on codec tags, Dolby Vision properties, and color transfer characteristics. + + A tuple containing the video range (SDR/HDR) and the specific video range type. + + + + Gets the resolution text based on width and height. + + The resolution text (e.g., "1080p", "4K") or null if width/height are not available. + + + + Enum MediaStreamType. + + + + + The audio. + + + + + The video. + + + + + The subtitle. + + + + + The embedded image. + + + + + The data. + + + + + The lyric. + + + + + Enum MetadataFields. + + + + + The cast. + + + + + The genres. + + + + + The production locations. + + + + + The studios. + + + + + The tags. + + + + + The name. + + + + + The overview. + + + + + The runtime. + + + + + The official rating. + + + + + Enum MetadataProviders. + + + + + This metadata provider is for users and/or plugins to override the + default merging behaviour. + + + + + The IMDb provider. + + + + + The TMDb provider. + + + + + The TVDb provider. + + + + + The tvcom provider. + + + + + TMDb collection provider. + + + + + The MusicBrainz album provider. + + + + + The MusicBrainz album artist provider. + + + + + The MusicBrainz artist provider. + + + + + The MusicBrainz release group provider. + + + + + The Zap2It provider. + + + + + The TvRage provider. + + + + + The AudioDb artist provider. + + + + + The AudioDb collection provider. + + + + + The MusicBrainz track provider. + + + + + The TvMaze provider. + + + + + The MusicBrainz recording provider. + + + + + Class ParentalRating. + + + + + Initializes a new instance of the class. + + The name. + The score. + + + + Gets or sets the name. + + The name. + + + + Gets or sets the value. + + The value. + + Deprecated. + + + + + Gets or sets the rating score. + + The rating score. + + + + A class representing an parental rating entry. + + + + + Gets or sets the rating strings. + + + + + Gets or sets the score. + + + + + A class representing an parental rating score. + + + + + Initializes a new instance of the class. + + The score. + The sub score. + + + + Gets or sets the score. + + + + + Gets or sets the sub score. + + + + + A class representing a parental rating system. + + + + + Gets or sets the country code. + + + + + Gets or sets a value indicating whether sub scores are supported. + + + + + Gets or sets the ratings. + + + + + Types of persons. + + + + + A person whose profession is acting on the stage, in films, or on television. + + + + + A person who supervises the actors and other staff in a film, play, or similar production. + + + + + A person who writes music, especially as a professional occupation. + + + + + A writer of a book, article, or document. Can also be used as a generic term for music writer if there is a lack of specificity. + + + + + A well-known actor or other performer who appears in a work in which they do not have a regular role. + + + + + A person responsible for the financial and managerial aspects of the making of a film or broadcast or for staging a play, opera, etc. + + + + + A person who directs the performance of an orchestra or choir. + + + + + A person who writes the words to a song or musical. + + + + + A person who adapts a musical composition for performance. + + + + + An audio engineer who performed a general engineering role. + + + + + An engineer responsible for using a mixing console to mix a recorded track into a single piece of music suitable for release. + + + + + A person who remixed a recording by taking one or more other tracks, substantially altering them and mixing them together with other material. + + + + + Class to hold data on user permissions for playlists. + + + + + Initializes a new instance of the class. + + The user id. + Edit permission. + + + + Gets or sets the user id. + + + + + Gets or sets a value indicating whether the user has edit permissions. + + + + + Class ProviderIdsExtensions. + + + + + Case-insensitive dictionary of string representation. + + + + + Checks if this instance has an id for the given provider. + + The instance. + The of the provider name. + true if a provider id with the given name was found; otherwise false. + + + + Checks if this instance has an id for the given provider. + + The instance. + The provider. + true if a provider id with the given name was found; otherwise false. + + + + Gets a provider id. + + The instance. + The name. + The provider id. + true if a provider id with the given name was found; otherwise false. + + + + Gets a provider id. + + The instance. + The provider. + The provider id. + true if a provider id with the given name was found; otherwise false. + + + + Gets a provider id. + + The instance. + The name. + System.String. + + + + Gets a provider id. + + The instance. + The provider. + System.String. + + + + Sets a provider id. + + The instance. + The name, this should not contain a '=' character. + The value. + Due to how deserialization from the database works the name cannot contain '='. + true if the provider id got set successfully; otherwise, false. + + + + Sets a provider id. + + The instance. + The provider. + The value. + true if the provider id got set successfully; otherwise, false. + + + + Sets a provider id. + + The instance. + The name, this should not contain a '=' character. + The value. + Due to how deserialization from the database works the name cannot contain '='. + + + + Sets a provider id. + + The instance. + The provider. + The value. + + + + Removes a provider id. + + The instance. + The name. + + + + Removes a provider id. + + The instance. + The provider. + + + + The status of a series. + + + + + The continuing status. This indicates that a series is currently releasing. + + + + + The ended status. This indicates that a series has completed and is no longer being released. + + + + + The unreleased status. This indicates that a series has not been released yet. + + + + + Enum containing tonemapping algorithms. + + + + + None. + + + + + Clip. + + + + + Linear. + + + + + Gamma. + + + + + Reinhard. + + + + + Hable. + + + + + Mobius. + + + + + BT2390. + + + + + Enum containing tonemapping modes. + + + + + Auto. + + + + + Max. + + + + + RGB. + + + + + Lum. + + + + + ITP. + + + + + Enum containing tonemapping ranges. + + + + + Auto. + + + + + TV. + + + + + PC. + + + + + Enum UserDataSaveReason. + + + + + The playback start. + + + + + The playback progress. + + + + + The playback finished. + + + + + The toggle played. + + + + + The update user rating. + + + + + The import. + + + + + API call updated item user data. + + + + + Enum VideoType. + + + + + The video file. + + + + + The iso. + + + + + The DVD. + + + + + The blu ray. + + + + + Used to hold information about a user's list of configured virtual folders. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the name. + + The name. + + + + Gets or sets the locations. + + The locations. + + + + Gets or sets the type of the collection. + + The type of the collection. + + + + Gets or sets the item identifier. + + The item identifier. + + + + Gets or sets the primary image item identifier. + + The primary image item identifier. + + + + Defines the class. + + + + + Compares two containers, returning true if an item in exists + in . + + The comma-delimited string being searched. + If the parameter begins with the - character, the operation is reversed. + If the parameter is empty or null, all containers in will be accepted. + The comma-delimited string being matched. + The result of the operation. + + + + Compares two containers, returning true if an item in exists + in . + + The comma-delimited string being searched. + If the parameter begins with the - character, the operation is reversed. + If the parameter is empty or null, all containers in will be accepted. + The comma-delimited string being matched. + The result of the operation. + + + + Compares two containers, returning if an item in + does not exist in . + + The comma-delimited string being searched. + If the parameter is empty or null, all containers in will be accepted. + The boolean result to return if a match is not found. + The comma-delimited string being matched. + The result of the operation. + + + + Compares two containers, returning if an item in + does not exist in . + + The comma-delimited string being searched. + If the parameter is empty or null, all containers in will be accepted. + The boolean result to return if a match is not found. + The comma-delimited string being matched. + The result of the operation. + + + + Compares two containers, returning if an item in + does not exist in . + + The profile containers being matched searched. + If the parameter is empty or null, all containers in will be accepted. + The boolean result to return if a match is not found. + The comma-delimited string being matched. + The result of the operation. + + + + Splits and input string. + + The input string. + The result of the operation. + + + + Extension methods for . + + + + + Orders by requested language in descending order, prioritizing "en" over other non-matches. + + The remote image infos. + The requested language for the images. + The ordered remote image infos. + + + + Extensions for . + + + + + Get the custom tag delimiters. + + This LibraryOptions. + CustomTagDelimiters in char[]. + + + + Helper methods for manipulating strings. + + + + + Returns the string with the first character as uppercase. + + The input string. + The string with the first character as uppercase. + + + + Class CountryInfo. + + + + + Gets or sets the name. + + The name. + + + + Gets or sets the display name. + + The display name. + + + + Gets or sets the name of the two letter ISO region. + + The name of the two letter ISO region. + + + + Gets or sets the name of the three letter ISO region. + + The name of the three letter ISO region. + + + + Class CultureDto. + + + + + Gets the name. + + The name. + + + + Gets the display name. + + The display name. + + + + Gets the name of the two letter ISO language. + + The name of the two letter ISO language. + + + + Gets the name of the three letter ISO language. + + The name of the three letter ISO language. + + + + Interface ILocalizationManager. + + + + + Gets the cultures. + + . + + + + Gets the countries. + + . + + + + Gets the parental ratings. + + . + + + + Gets the rating level. + + The rating. + The optional two letter ISO language string. + or null. + + + + Gets the localized string. + + The phrase. + The culture. + . + + + + Gets the localized string. + + The phrase. + System.String. + + + + Gets the localization options. + + . + + + + Returns the correct for the given language. + + The language. + The correct for the given language. + + + + Returns the language in ISO 639-2/T when the input is ISO 639-2/B. + + The language in ISO 639-2/B. + The language in ISO 639-2/T. + Whether the language could be converted. + + + + Helper class to create async s. + + + + + Gets the default for reading files async. + + + + + Gets the default for writing files async. + + + + + Creates, or truncates and overwrites, a file in the specified path. + + The path and name of the file to create. + A that provides read/write access to the file specified in path. + + + + Opens an existing file for reading. + + The file to be opened for reading. + A read-only on the specified path. + + + + Opens an existing file for writing. + + The file to be opened for writing. + An unshared object on the specified path with Write access. + + + + Class FileSystemEntryInfo. + + + + + Initializes a new instance of the class. + + The filename. + The file path. + The file type. + + + + Gets the name. + + The name. + + + + Gets the path. + + The path. + + + + Gets the type. + + The type. + + + + Enum FileSystemEntryType. + + + + + The file. + + + + + The directory. + + + + + The network computer. + + + + + The network share. + + + + + Gets or sets a value indicating whether this is exists. + + true if exists; otherwise, false. + + + + Gets or sets the full name. + + The full name. + + + + Gets or sets the name. + + The name. + + + + Gets or sets the extension. + + The extension. + + + + Gets or sets the length. + + The length. + + + + Gets or sets the last write time UTC. + + The last write time UTC. + + + + Gets or sets the creation time UTC. + + The creation time UTC. + + + + Gets or sets a value indicating whether this instance is directory. + + true if this instance is directory; otherwise, false. + + + + Interface IFileSystem. + + + + + Determines whether the specified filename is shortcut. + + The filename. + true if the specified filename is shortcut; otherwise, false. + + + + Resolves the shortcut. + + The filename. + System.String. + + + + Creates the shortcut. + + The shortcut path. + The target. + + + + Moves a directory to a new location. + + Source directory. + Destination directory. + + + + Returns a object for the specified file or directory path. + + A path to a file or directory. + A object. + If the specified path points to a directory, the returned object's + property will be set to true and all other properties will reflect the properties of the directory. + + + + Returns a object for the specified file path. + + A path to a file. + A object. + If the specified path points to a directory, the returned object's + property and the property will both be set to false. + For automatic handling of files and directories, use . + + + + Returns a object for the specified directory path. + + A path to a directory. + A object. + If the specified path points to a file, the returned object's + property will be set to true and the property will be set to false. + For automatic handling of files and directories, use . + + + + Gets the valid filename. + + The filename. + System.String. + + + + Gets the creation time UTC. + + The information. + DateTime. + + + + Gets the creation time UTC. + + The path. + DateTime. + + + + Gets the last write time UTC. + + The information. + DateTime. + + + + Gets the last write time UTC. + + The path. + DateTime. + + + + Swaps the files. + + The file1. + The file2. + + + + Determines whether [contains sub path] [the specified parent path]. + + The parent path. + The path. + true if [contains sub path] [the specified parent path]; otherwise, false. + + + + Gets the file name without extension. + + The information. + System.String. + + + + Determines whether [is path file] [the specified path]. + + The path. + true if [is path file] [the specified path]; otherwise, false. + + + + Deletes the file. + + The path. + + + + Gets the directories. + + The path. + If set to true also searches in subdirectories. + All found directories. + + + + Gets the files. + + The path in which to search. + If set to true also searches in subdirectories. + All found files. + + + + Gets the files. + + The path in which to search. + The search string to match against the names of files. This parameter can contain a combination of valid literal path and wildcard (* and ?) characters, but it doesn't support regular expressions. + If set to true also searches in subdirectories. + All found files. + + + + Gets the files. + + The path in which to search. + The file extensions to search for. + Enable case-sensitive check for extensions. + If set to true also searches in subdirectories. + All found files. + + + + Gets the files. + + The path in which to search. + The search string to match against the names of files. This parameter can contain a combination of valid literal path and wildcard (* and ?) characters, but it doesn't support regular expressions. + The file extensions to search for. + Enable case-sensitive check for extensions. + If set to true also searches in subdirectories. + All found files. + + + + Gets the file system entries. + + The path. + if set to true [recursive]. + IEnumerable<FileSystemMetadata>. + + + + Gets the directory paths. + + The path. + if set to true [recursive]. + IEnumerable<System.String>. + + + + Gets the file paths. + + The path. + if set to true [recursive]. + IEnumerable<System.String>. + + + + Gets the file system entry paths. + + The path. + if set to true [recursive]. + IEnumerable<System.String>. + + + + Determines whether the directory exists. + + The path. + Whether the path exists. + + + + Determines whether the file exists. + + The path. + Whether the path exists. + + + + Class IODefaults. + + + + + The default copy to buffer size. + + + + + The default file stream buffer size. + + + + + The default buffer size. + + + + + Gets the extension. + + The extension. + + + + Resolves the specified shortcut path. + + The shortcut path. + System.String. + + + + Creates the specified shortcut path. + + The shortcut path. + The target path. + + + + Gets or sets the user. + + The user. + + + + Gets or sets a value indicating whether [include external content]. + + true if [include external content]; otherwise, false. + + + + Gets or sets a value indicating whether [include hidden]. + + true if [include hidden]; otherwise, false. + + + + Gets or sets the Id of the recording. + + + + + Gets or sets the server identifier. + + The server identifier. + + + + Gets or sets the external identifier. + + The external identifier. + + + + Gets or sets the channel id of the recording. + + + + + Gets or sets the external channel identifier. + + The external channel identifier. + + + + Gets or sets the channel name of the recording. + + + + + Gets or sets the program identifier. + + The program identifier. + + + + Gets or sets the external program identifier. + + The external program identifier. + + + + Gets or sets the name of the recording. + + + + + Gets or sets the description of the recording. + + + + + Gets or sets the start date of the recording, in UTC. + + + + + Gets or sets the end date of the recording, in UTC. + + + + + Gets or sets the name of the service. + + The name of the service. + + + + Gets or sets the priority. + + The priority. + + + + Gets or sets the pre padding seconds. + + The pre padding seconds. + + + + Gets or sets the post padding seconds. + + The post padding seconds. + + + + Gets or sets a value indicating whether this instance is pre padding required. + + true if this instance is pre padding required; otherwise, false. + + + + Gets or sets the Id of the Parent that has a backdrop if the item does not have one. + + The parent backdrop item id. + + + + Gets or sets the parent backdrop image tags. + + The parent backdrop image tags. + + + + Gets or sets a value indicating whether this instance is post padding required. + + true if this instance is post padding required; otherwise, false. + + + + Channel mapping options dto. + + + + + Gets or sets list of tuner channels. + + + + + Gets or sets list of provider channels. + + + + + Gets or sets list of mappings. + + + + + Gets or sets provider name. + + + + + Enum ChannelType. + + + + + The TV. + + + + + The radio. + + + + + Gets or sets the start date. + + The start date. + + + + Gets or sets the end date. + + The end date. + + + + Class ChannelQuery. + + + + + Gets or sets the type of the channel. + + The type of the channel. + + + + Gets or sets a value indicating whether this instance is favorite. + + null if [is favorite] contains no value, true if [is favorite]; otherwise, false. + + + + Gets or sets a value indicating whether this instance is liked. + + null if [is liked] contains no value, true if [is liked]; otherwise, false. + + + + Gets or sets a value indicating whether this instance is disliked. + + null if [is disliked] contains no value, true if [is disliked]; otherwise, false. + + + + Gets or sets a value indicating whether [enable favorite sorting]. + + true if [enable favorite sorting]; otherwise, false. + + + + Gets or sets the user identifier. + + The user identifier. + + + + Gets or sets the start index. Used for paging. + + The start index. + + + + Gets or sets the maximum number of items to return. + + The limit. + + + + Gets or sets a value indicating whether [add current program]. + + true if [add current program]; otherwise, false. + + + + Gets or sets a value whether to return news or not. + + If set to null, all programs will be returned. + + + + Gets or sets a value whether to return movies or not. + + If set to null, all programs will be returned. + + + + Gets or sets a value indicating whether this instance is kids. + + null if [is kids] contains no value, true if [is kids]; otherwise, false. + + + + Gets or sets a value indicating whether this instance is sports. + + null if [is sports] contains no value, true if [is sports]; otherwise, false. + + + + Gets or sets the sort order to return results with. + + The sort order. + + + + Gets or sets the services. + + The services. + + + + Gets or sets a value indicating whether this instance is enabled. + + true if this instance is enabled; otherwise, false. + + + + Gets or sets the enabled users. + + The enabled users. + + + + Class ServiceInfo. + + + + + Gets or sets the name. + + The name. + + + + Gets or sets the home page URL. + + The home page URL. + + + + Gets or sets the status. + + The status. + + + + Gets or sets the status message. + + The status message. + + + + Gets or sets the version. + + The version. + + + + Gets or sets a value indicating whether this instance has update available. + + true if this instance has update available; otherwise, false. + + + + Gets or sets a value indicating whether this instance is visible. + + true if this instance is visible; otherwise, false. + + + + Class RecordingQuery. + + + + + Gets or sets the channel identifier. + + The channel identifier. + + + + Gets or sets the user identifier. + + The user identifier. + + + + Gets or sets the identifier. + + The identifier. + + + + Gets or sets the start index. Use for paging. + + The start index. + + + + Gets or sets the maximum number of items to return. + + The limit. + + + + Gets or sets the status. + + The status. + + + + Gets or sets a value indicating whether this instance is in progress. + + null if [is in progress] contains no value, true if [is in progress]; otherwise, false. + + + + Gets or sets the series timer identifier. + + The series timer identifier. + + + + Gets or sets the fields to return within the items, in addition to basic information. + + The fields. + + + + Class SeriesTimerInfoDto. + + + + + Gets or sets a value indicating whether [record any time]. + + true if [record any time]; otherwise, false. + + + + Gets or sets a value indicating whether [record any channel]. + + true if [record any channel]; otherwise, false. + + + + Gets or sets a value indicating whether [record new only]. + + true if [record new only]; otherwise, false. + + + + Gets or sets the days. + + The days. + + + + Gets or sets the day pattern. + + The day pattern. + + + + Gets or sets the image tags. + + The image tags. + + + + Gets or sets the parent thumb item id. + + The parent thumb item id. + + + + Gets or sets the parent thumb image tag. + + The parent thumb image tag. + + + + Gets or sets the parent primary image item identifier. + + The parent primary image item identifier. + + + + Gets or sets the parent primary image tag. + + The parent primary image tag. + + + + Gets or sets the sort by - SortName, Priority. + + The sort by. + + + + Gets or sets the sort order. + + The sort order. + + + + Gets or sets the status. + + The status. + + + + Gets or sets the series timer identifier. + + The series timer identifier. + + + + Gets or sets the external series timer identifier. + + The external series timer identifier. + + + + Gets or sets the run time ticks. + + The run time ticks. + + + + Gets or sets the program information. + + The program information. + + + + Gets or sets the channel identifier. + + The channel identifier. + + + + Gets or sets the series timer identifier. + + The series timer identifier. + + + + LyricResponse model. + + + + + Gets or sets Metadata for the lyrics. + + + + + Gets or sets a collection of individual lyric lines. + + + + + The information for a raw lyrics file before parsing. + + + + + Initializes a new instance of the class. + + The name. + The content, must not be empty. + + + + Gets or sets the name of the lyrics file. This must include the file extension. + + + + + Gets or sets the contents of the file. + + + + + Lyric model. + + + + + Initializes a new instance of the class. + + The lyric text. + The lyric start time in ticks. + The time-aligned cues for the song's lyrics. + + + + Gets the text of this lyric line. + + + + + Gets the start time in ticks. + + + + + Gets the time-aligned cues for the song's lyrics. + + + + + LyricLineCue model, holds information about the timing of words within a LyricLine. + + + + + Initializes a new instance of the class. + + The start character index of the cue. + The end character index of the cue. + The start of the timestamp the lyric is synced to in ticks. + The end of the timestamp the lyric is synced to in ticks. + + + + Gets the start character index of the cue. + + + + + Gets the end character index of the cue. + + + + + Gets the timestamp the lyric is synced to in ticks. + + + + + Gets the end timestamp the lyric is synced to in ticks. + + + + + LyricMetadata model. + + + + + Gets or sets the song artist. + + + + + Gets or sets the album this song is on. + + + + + Gets or sets the title of the song. + + + + + Gets or sets the author of the lyric data. + + + + + Gets or sets the length of the song in ticks. + + + + + Gets or sets who the LRC file was created by. + + + + + Gets or sets the lyric offset compared to audio in ticks. + + + + + Gets or sets the software used to create the LRC file. + + + + + Gets or sets the version of the creator used. + + + + + Gets or sets a value indicating whether this lyric is synced. + + + + + LyricResponse model. + + + + + Gets or sets the lyric stream. + + + + + Gets or sets the lyric format. + + + + + Lyric search request. + + + + + Gets or sets the media path. + + + + + Gets or sets the album artist names. + + + + + Gets or sets the artist names. + + + + + Gets or sets the album name. + + + + + Gets or sets the song name. + + + + + Gets or sets the track duration in ticks. + + + + + + + + Gets or sets a value indicating whether to search all providers. + + + + + Gets or sets the list of disabled lyric fetcher names. + + + + + Gets or sets the order of lyric fetchers. + + + + + Gets or sets a value indicating whether this request is automated. + + + + + The remote lyric info dto. + + + + + Gets or sets the id for the lyric. + + + + + Gets the provider name. + + + + + Gets the lyrics. + + + + + Upload lyric dto. + + + + + Gets or sets the lyrics file. + + + + + How is the audio index determined. + + + + + The default index when no preference is specified. + + + + + The index is calculated whether the track is marked as default or not. + + + + + The index is calculated whether the track is in preferred language or not. + + + + + The index is specified by the user. + + + + + Represents the result of BDInfo output. + + + + + Gets or sets the media streams. + + The media streams. + + + + Gets or sets the run time ticks. + + The run time ticks. + + + + Gets or sets the files. + + The files. + + + + Gets or sets the playlist name. + + The playlist name. + + + + Gets or sets the chapters. + + The chapters. + + + + Interface IBlurayExaminer. + + + + + Gets the disc info. + + The path. + BlurayDiscInfo. + + + + Gets or sets the album. + + The album. + + + + Gets or sets the artists. + + The artists. + + + + Gets or sets the album artists. + + The album artists. + + + + Gets or sets the studios. + + The studios. + + + + Gets or sets the official rating. + + The official rating. + + + + Gets or sets the official rating description. + + The official rating description. + + + + Gets or sets the overview. + + The overview. + + + + Class PlaybackInfoResponse. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the media sources. + + The media sources. + + + + Gets or sets the play session identifier. + + The play session identifier. + + + + Gets or sets the error code. + + The error code. + + + + Api model for MediaSegment's. + + + + + Gets or sets the id of the media segment. + + + + + Gets or sets the id of the associated item. + + + + + Gets or sets the type of content this segment defines. + + + + + Gets or sets the start of the segment. + + + + + Gets or sets the end of the segment. + + + + + Model containing the arguments for enumerating the requested media item. + + + + + Gets the Id to the BaseItem the segments should be extracted from. + + + + + Gets existing media segments generated on an earlier scan by this provider. + + + + + Base network object class. + + + + + Initializes a new instance of the class. + + The . + The . + The interface name. + + + + Initializes a new instance of the class. + + The . + The . + + + + Gets or sets the object's IP address. + + + + + Gets or sets the object's IP address. + + + + + Gets or sets the interface index. + + + + + Gets or sets a value indicating whether the network supports multicast. + + + + + Gets or sets the interface name. + + + + + Gets the AddressFamily of the object. + + + + + Implemented by components that can create specific socket configurations. + + + + + Creates a new unicast socket using the specified local port number. + + The local port to bind to. + A new unicast socket using the specified local port number. + + + + Class MimeTypes. + + + + For more information on MIME types: + + http://en.wikipedia.org/wiki/Internet_media_type + https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types + http://www.iana.org/assignments/media-types/media-types.xhtml + + + + + + Any extension in this list is considered a video file. + + + + + Used for extensions not in or to override them. + + + + + Gets the type of the MIME. + + The filename to find the MIME type of. + The default value to return if no fitting MIME type is found. + The correct MIME type for the given filename, or if it wasn't found. + + + + Class holding information for a published server URI override. + + + + + Initializes a new instance of the class. + + The . + The override. + A value indicating whether the override is for internal requests. + A value indicating whether the override is for external requests. + + + + Gets or sets the object's IP address. + + + + + Gets or sets the override URI. + + + + + Gets or sets a value indicating whether the override should be applied to internal requests. + + + + + Gets or sets a value indicating whether the override should be applied to external requests. + + + + + A playlist creation request. + + + + + Gets or sets the name. + + + + + Gets or sets the list of items. + + + + + Gets or sets the media type. + + + + + Gets or sets the user id. + + + + + Gets or sets the user permissions. + + + + + Gets or sets a value indicating whether the playlist is public. + + + + + Initializes a new instance of the class. + + The playlist identifier. + + + + A playlist update request. + + + + + Gets or sets the id of the playlist. + + + + + Gets or sets the id of the user updating the playlist. + + + + + Gets or sets the name of the playlist. + + + + + Gets or sets item ids to add to the playlist. + + + + + Gets or sets the playlist users. + + + + + Gets or sets a value indicating whether the playlist is public. + + + + + A playlist user update request. + + + + + Gets or sets the id of the playlist. + + + + + Gets or sets the id of the updated user. + + + + + Gets or sets a value indicating whether the user can edit the playlist. + + + + + Class BasePluginConfiguration. + + + + + Gets the plugin pages. + + The plugin pages. + + + + This is a serializable stub class that is used by the api to provide information about installed plugins. + + + + + Initializes a new instance of the class. + + The plugin name. + The plugin . + The plugin description. + The . + True if this plugin can be uninstalled. + + + + Gets or sets the name. + + + + + Gets or sets the version. + + + + + Gets or sets the name of the configuration file. + + + + + Gets or sets the description. + + + + + Gets or sets the unique id. + + + + + Gets or sets a value indicating whether the plugin can be uninstalled. + + + + + Gets or sets a value indicating whether this plugin has a valid image. + + + + + Gets or sets a value indicating the status of the plugin. + + + + + Defines the . + + + + + Gets or sets the name of the plugin. + + + + + Gets or sets the display name of the plugin. + + + + + Gets or sets the resource path. + + + + + Gets or sets a value indicating whether this plugin should appear in the main menu. + + + + + Gets or sets the menu section. + + + + + Gets or sets the menu icon. + + + + + Plugin load status. + + + + + This plugin requires a restart in order for it to load. This is a memory only status. + The actual status of the plugin after reload is present in the manifest. + eg. A disabled plugin will still be active until the next restart, and so will have a memory status of Restart, + but a disk manifest status of Disabled. + + + + + This plugin is currently running. + + + + + This plugin has been marked as disabled. + + + + + This plugin does not meet the TargetAbi requirements. + + + + + This plugin caused an error when instantiated (either DI loop, or exception). + + + + + This plugin has been superseded by another version. + + + + + [DEPRECATED] See Superseded. + + + + + An attempt to remove this plugin from disk will happen at every restart. + It will not be loaded, if unable to do so. + + + + + Represents the external id information for serialization to the client. + + + + + Initializes a new instance of the class. + + Name of the external id provider (IE: IMDB, MusicBrainz, etc). + Key for this id. This key should be unique across all providers. + Specific media type for this id. + + + + Gets or sets the display name of the external id provider (IE: IMDB, MusicBrainz, etc). + + + + + Gets or sets the unique key for this id. This key should be unique across all providers. + + + + + Gets or sets the specific media type for this id. This is used to distinguish between the different + external id types for providers with multiple ids. + A null value indicates there is no specific media type associated with the external id, or this is the + default id for the external provider so there is no need to specify a type. + + + This can be used along with the to localize the external id on the client. + + + + + The specific media type of an . + + + Client applications may use this as a translation key. + + + + + A music album. + + + + + The artist of a music album. + + + + + The artist of a media item. + + + + + A boxed set of media. + + + + + A series episode. + + + + + A movie. + + + + + An alternative artist apart from the main artist. + + + + + A person. + + + + + A release group. + + + + + A single season of a series. + + + + + A series. + + + + + A music track. + + + + + A book. + + + + + A music recording. + + + + + Gets or sets the name. + + The name. + + + + Gets or sets the type of the item. + + The type of the item. + + + + Class ImageProviderInfo. + + + + + Initializes a new instance of the class. + + The name of the image provider. + The image types supported by the image provider. + + + + Gets the name. + + The name. + + + + Gets the supported image types. + + + + + Lyric provider info. + + + + + Gets the provider name. + + + + + Gets the provider id. + + + + + Class RemoteImageInfo. + + + + + Gets or sets the name of the provider. + + The name of the provider. + + + + Gets or sets the URL. + + The URL. + + + + Gets or sets a url used for previewing a smaller version. + + + + + Gets or sets the height. + + The height. + + + + Gets or sets the width. + + The width. + + + + Gets or sets the community rating. + + The community rating. + + + + Gets or sets the vote count. + + The vote count. + + + + Gets or sets the language. + + The language. + + + + Gets or sets the type. + + The type. + + + + Gets or sets the type of the rating. + + The type of the rating. + + + + Initializes a new instance of the class. + + The name of the image provider. + + + + Class RemoteImageResult. + + + + + Gets or sets the images. + + The images. + + + + Gets or sets the total record count. + + The total record count. + + + + Gets or sets the providers. + + The providers. + + + + The remote lyric info. + + + + + Gets or sets the id for the lyric. + + + + + Gets the provider name. + + + + + Gets the lyric metadata. + + + + + Gets the lyrics. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the name. + + The name. + + + + Gets or sets the provider ids. + + The provider ids. + + + + Gets or sets the year. + + The year. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Used to control the data that gets attached to DtoBaseItems. + + + + + The air time. + + + + + The can delete. + + + + + The can download. + + + + + The channel information. + + + + + The chapters. + + + + + The trickplay manifest. + + + + + The child count. + + + + + The cumulative run time ticks. + + + + + The custom rating. + + + + + The date created of the item. + + + + + The date last media added. + + + + + Item display preferences. + + + + + The etag. + + + + + The external urls. + + + + + Genres. + + + + + The item counts. + + + + + The media source count. + + + + + The media versions. + + + + + The original title. + + + + + The item overview. + + + + + The id of the item's parent. + + + + + The physical path of the item. + + + + + The list of people for the item. + + + + + Value indicating whether playback access is granted. + + + + + The production locations. + + + + + The ids from IMDb, TMDb, etc. + + + + + The aspect ratio of the primary image. + + + + + The recursive item count. + + + + + The settings. + + + + + The series studio. + + + + + The sort name of the item. + + + + + The special episode numbers. + + + + + The studios of the item. + + + + + The taglines of the item. + + + + + The tags. + + + + + The trailer url of the item. + + + + + The media streams. + + + + + The season user data. + + + + + The last time metadata was refreshed. + + + + + The last time metadata was saved. + + + + + The refresh state. + + + + + The channel image. + + + + + Value indicating whether media source display is enabled. + + + + + The width. + + + + + The height. + + + + + The external Ids. + + + + + The local trailer count. + + + + + Value indicating whether the item is HD. + + + + + The special feature count. + + + + + Enum ItemFilter. + + + + + The item is a folder. + + + + + The item is not folder. + + + + + The item is unplayed. + + + + + The item is played. + + + + + The item is a favorite. + + + + + The item is resumable. + + + + + The likes. + + + + + The dislikes. + + + + + The is favorite or likes. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the user to localize search results for. + + The user id. + + + + Gets or sets the parent id. + Specify this to localize the search to a specific item or folder. Omit to use the root. + + The parent id. + + + + Gets or sets the start index. Used for paging. + + The start index. + + + + Gets or sets the maximum number of items to return. + + The limit. + + + + Gets or sets the fields to return within the items, in addition to basic information. + + The fields. + + + + Gets or sets the include item types. + + The include item types. + + + + Gets or sets a value indicating whether this instance is played. + + null if [is played] contains no value, true if [is played]; otherwise, false. + + + + Gets or sets a value indicating whether [group items]. + + true if [group items]; otherwise, false. + + + + Gets or sets a value indicating whether [enable images]. + + null if [enable images] contains no value, true if [enable images]; otherwise, false. + + + + Gets or sets the image type limit. + + The image type limit. + + + + Gets or sets the enable image types. + + The enable image types. + + + + Initializes a new instance of the class. + + + + + Gets or sets the user. + + The user. + + + + Gets or sets the parent identifier. + + The parent identifier. + + + + Gets or sets the series id. + + The series id. + + + + Gets or sets the start index. Use for paging. + + The start index. + + + + Gets or sets the maximum number of items to return. + + The limit. + + + + Gets or sets the enable image types. + + The enable image types. + + + + Gets or sets a value indicating the oldest date for a show to appear in Next Up. + + + + + Gets or sets a value indicating whether to include resumable episodes as next up. + + + + + Gets or sets a value indicating whether getting rewatching next up list. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Query result container. + + The type of item contained in the query result. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + The list of items. + + + + Initializes a new instance of the class. + + The start index that was used to build the item list. + The total count of items. + The list of items. + + + + Gets or sets the items. + + The items. + + + + Gets or sets the total number of records available. + + The total record count. + + + + Gets or sets the index of the first record in Items. + + First record index. + + + + Class ThemeMediaResult. + + + + + Gets or sets the owner id. + + The owner id. + + + + Stores the state of an quick connect request. + + + + + Initializes a new instance of the class. + + The secret used to query the request state. + The code used to allow the request. + The time when the request was created. + The requesting device id. + The requesting device name. + The requesting app name. + The requesting app version. + + + + Gets or sets a value indicating whether this request is authorized. + + + + + Gets the secret value used to uniquely identify this request. Can be used to retrieve authentication information. + + + + + Gets the user facing code used so the user can quickly differentiate this request from others. + + + + + Gets the requesting device id. + + + + + Gets the requesting device name. + + + + + Gets the requesting app name. + + + + + Gets the requesting app version. + + + + + Gets or sets the DateTime that this request was created. + + + + + Class SearchHintResult. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the item id. + + The item id. + + + + Gets or sets the item id. + + The item id. + + + + Gets or sets the name. + + The name. + + + + Gets or sets the matched term. + + The matched term. + + + + Gets or sets the index number. + + The index number. + + + + Gets or sets the production year. + + The production year. + + + + Gets or sets the parent index number. + + The parent index number. + + + + Gets or sets the image tag. + + The image tag. + + + + Gets or sets the thumb image tag. + + The thumb image tag. + + + + Gets or sets the thumb image item identifier. + + The thumb image item identifier. + + + + Gets or sets the backdrop image tag. + + The backdrop image tag. + + + + Gets or sets the backdrop image item identifier. + + The backdrop image item identifier. + + + + Gets or sets the type. + + The type. + + + + Gets or sets a value indicating whether this instance is folder. + + true if this instance is folder; otherwise, false. + + + + Gets or sets the run time ticks. + + The run time ticks. + + + + Gets or sets the type of the media. + + The type of the media. + + + + Gets or sets the start date. + + The start date. + + + + Gets or sets the end date. + + The end date. + + + + Gets or sets the series. + + The series. + + + + Gets or sets the status. + + The status. + + + + Gets or sets the album. + + The album. + + + + Gets or sets the album id. + + The album id. + + + + Gets or sets the album artist. + + The album artist. + + + + Gets or sets the artists. + + The artists. + + + + Gets or sets the song count. + + The song count. + + + + Gets or sets the episode count. + + The episode count. + + + + Gets or sets the channel identifier. + + The channel identifier. + + + + Gets or sets the name of the channel. + + The name of the channel. + + + + Gets or sets the primary image aspect ratio. + + The primary image aspect ratio. + + + + Class SearchHintResult. + + + + + Initializes a new instance of the class. + + The search hints. + The total record count. + + + + Gets the search hints. + + The search hints. + + + + Gets the total record count. + + The total record count. + + + + Initializes a new instance of the class. + + + + + Gets or sets the user to localize search results for. + + The user id. + + + + Gets or sets the search term. + + The search term. + + + + Gets or sets the start index. Used for paging. + + The start index. + + + + Gets or sets the maximum number of items to return. + + The limit. + + + + Deserializes from stream. + + The type. + The stream. + System.Object. + + + + Serializes to stream. + + The obj. + The stream. + + + + Serializes to file. + + The obj. + The file. + + + + Deserializes from file. + + The type. + The file. + System.Object. + + + + Deserializes from bytes. + + The type. + The buffer. + System.Object. + + + + Class BrowseRequest. + + + + + Gets or sets the item type. + + The type of the item. + + + + Gets or sets the item id. + + The item id. + + + + Gets or sets the name of the item. + + The name of the item. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + The command arguments. + + + + This exists simply to identify a set of known commands. + + + + + Enum PlaybackOrder. + + + + + Sorted playlist. + + + + + Shuffled playlist. + + + + + Class PlaybackProgressInfo. + + + + + Gets or sets a value indicating whether this instance can seek. + + true if this instance can seek; otherwise, false. + + + + Gets or sets the item. + + The item. + + + + Gets or sets the item identifier. + + The item identifier. + + + + Gets or sets the session id. + + The session id. + + + + Gets or sets the media version identifier. + + The media version identifier. + + + + Gets or sets the index of the audio stream. + + The index of the audio stream. + + + + Gets or sets the index of the subtitle stream. + + The index of the subtitle stream. + + + + Gets or sets a value indicating whether this instance is paused. + + true if this instance is paused; otherwise, false. + + + + Gets or sets a value indicating whether this instance is muted. + + true if this instance is muted; otherwise, false. + + + + Gets or sets the position ticks. + + The position ticks. + + + + Gets or sets the volume level. + + The volume level. + + + + Gets or sets the play method. + + The play method. + + + + Gets or sets the live stream identifier. + + The live stream identifier. + + + + Gets or sets the play session identifier. + + The play session identifier. + + + + Gets or sets the repeat mode. + + The repeat mode. + + + + Gets or sets the playback order. + + The playback order. + + + + Class PlaybackStartInfo. + + + + + Class PlaybackStopInfo. + + + + + Gets or sets the item. + + The item. + + + + Gets or sets the item identifier. + + The item identifier. + + + + Gets or sets the session id. + + The session id. + + + + Gets or sets the media version identifier. + + The media version identifier. + + + + Gets or sets the position ticks. + + The position ticks. + + + + Gets or sets the live stream identifier. + + The live stream identifier. + + + + Gets or sets the play session identifier. + + The play session identifier. + + + + Gets or sets a value indicating whether this is failed. + + true if failed; otherwise, false. + + + + Enum PlayCommand. + + + + + The play now. + + + + + The play next. + + + + + The play last. + + + + + The play instant mix. + + + + + The play shuffle. + + + + + Gets or sets the now playing position ticks. + + The now playing position ticks. + + + + Gets or sets a value indicating whether this instance can seek. + + true if this instance can seek; otherwise, false. + + + + Gets or sets a value indicating whether this instance is paused. + + true if this instance is paused; otherwise, false. + + + + Gets or sets a value indicating whether this instance is muted. + + true if this instance is muted; otherwise, false. + + + + Gets or sets the volume level. + + The volume level. + + + + Gets or sets the index of the now playing audio stream. + + The index of the now playing audio stream. + + + + Gets or sets the index of the now playing subtitle stream. + + The index of the now playing subtitle stream. + + + + Gets or sets the now playing media version identifier. + + The now playing media version identifier. + + + + Gets or sets the play method. + + The play method. + + + + Gets or sets the repeat mode. + + The repeat mode. + + + + Gets or sets the playback order. + + The playback order. + + + + Gets or sets the now playing live stream identifier. + + The live stream identifier. + + + + Class PlayRequest. + + + + + Gets or sets the item ids. + + The item ids. + + + + Gets or sets the start position ticks that the first item should be played at. + + The start position ticks. + + + + Gets or sets the play command. + + The play command. + + + + Gets or sets the controlling user identifier. + + The controlling user identifier. + + + + Enum PlaystateCommand. + + + + + The stop. + + + + + The pause. + + + + + The unpause. + + + + + The next track. + + + + + The previous track. + + + + + The seek. + + + + + The rewind. + + + + + The fast forward. + + + + + The play pause. + + + + + Gets or sets the controlling user identifier. + + The controlling user identifier. + + + + The different kinds of messages that are used in the WebSocket api. + + + + + Class SessionUserInfo. + + + + + Gets or sets the user identifier. + + The user identifier. + + + + Gets or sets the name of the user. + + The name of the user. + + + + Class holding information on a running transcode. + + + + + Gets or sets the thread count used for encoding. + + + + + Gets or sets the thread count used for encoding. + + + + + Gets or sets the thread count used for encoding. + + + + + Gets or sets a value indicating whether the video is passed through. + + + + + Gets or sets a value indicating whether the audio is passed through. + + + + + Gets or sets the bitrate. + + + + + Gets or sets the framerate. + + + + + Gets or sets the completion percentage. + + + + + Gets or sets the video width. + + + + + Gets or sets the video height. + + + + + Gets or sets the audio channels. + + + + + Gets or sets the hardware acceleration type. + + + + + Gets or sets the transcode reasons. + + + + + Class UserDataChangeInfo. + + + + + Gets or sets the user id. + + The user id. + + + + Gets or sets the user data list. + + The user data list. + + + + Class FontFile. + + + + + Gets or sets the name. + + The name. + + + + Gets or sets the size. + + The size. + + + + Gets or sets the date created. + + The date created. + + + + Gets or sets the date modified. + + The date modified. + + + + Class GroupInfoDto. + + + + + Initializes a new instance of the class. + + The group identifier. + The group name. + The group state. + The participants. + The date when this DTO has been created. + + + + Gets the group identifier. + + The group identifier. + + + + Gets the group name. + + The group name. + + + + Gets the group state. + + The group state. + + + + Gets the participants. + + The participants. + + + + Gets the date when this DTO has been created. + + The date when this DTO has been created. + + + + Enum GroupQueueMode. + + + + + Insert items at the end of the queue. + + + + + Insert items after the currently playing item. + + + + + Enum GroupRepeatMode. + + + + + Repeat one item only. + + + + + Cycle the playlist. + + + + + Do not repeat. + + + + + Enum GroupShuffleMode. + + + + + Sorted playlist. + + + + + Shuffled playlist. + + + + + Enum GroupState. + + + + + The group is in idle state. No media is playing. + + + + + The group is in waiting state. Playback is paused. Will start playing when users are ready. + + + + + The group is in paused state. Playback is paused. Will resume on play command. + + + + + The group is in playing state. Playback is advancing. + + + + + Class GroupStateUpdate. + + + + + Initializes a new instance of the class. + + The state of the group. + The reason of the state change. + + + + Gets the state of the group. + + The state of the group. + + + + Gets the reason of the state change. + + The reason of the state change. + + + + Group update without data. + + The type of the update data. + + + + Initializes a new instance of the class. + + The group identifier. + The update data. + + + + Gets the group identifier. + + The group identifier. + + + + Gets the update data. + + The update data. + + + + Gets the update type. + + The update type. + + + + Enum GroupUpdateType. + + + + + The user-joined update. Tells members of a group about a new user. + + + + + The user-left update. Tells members of a group that a user left. + + + + + The group-joined update. Tells a user that the group has been joined. + + + + + The group-left update. Tells a user that the group has been left. + + + + + The group-state update. Tells members of the group that the state changed. + + + + + The play-queue update. Tells a user the playing queue of the group. + + + + + The not-in-group error. Tells a user that they don't belong to a group. + + + + + The group-does-not-exist error. Sent when trying to join a non-existing group. + + + + + The library-access-denied error. Sent when a user tries to join a group without required access to the library. + + + + + Enum PlaybackRequestType. + + + + + A user is setting a new playlist. + + + + + A user is changing the playlist item. + + + + + A user is removing items from the playlist. + + + + + A user is moving an item in the playlist. + + + + + A user is adding items to the playlist. + + + + + A user is requesting an unpause command for the group. + + + + + A user is requesting a pause command for the group. + + + + + A user is requesting a stop command for the group. + + + + + A user is requesting a seek command for the group. + + + + + A user is signaling that playback is buffering. + + + + + A user is signaling that playback resumed. + + + + + A user is requesting next item in playlist. + + + + + A user is requesting previous item in playlist. + + + + + A user is setting the repeat mode. + + + + + A user is setting the shuffle mode. + + + + + A user is reporting their ping. + + + + + A user is requesting to be ignored on group wait. + + + + + Class PlayQueueUpdate. + + + + + Initializes a new instance of the class. + + The reason for the update. + The UTC time of the last change to the playing queue. + The playlist. + The playing item index in the playlist. + The start position ticks. + The playing item status. + The shuffle mode. + The repeat mode. + + + + Gets the request type that originated this update. + + The reason for the update. + + + + Gets the UTC time of the last change to the playing queue. + + The UTC time of the last change to the playing queue. + + + + Gets the playlist. + + The playlist. + + + + Gets the playing item index in the playlist. + + The playing item index in the playlist. + + + + Gets the start position ticks. + + The start position ticks. + + + + Gets a value indicating whether the current item is playing. + + The playing item status. + + + + Gets the shuffle mode. + + The shuffle mode. + + + + Gets the repeat mode. + + The repeat mode. + + + + Enum PlayQueueUpdateReason. + + + + + A user is requesting to play a new playlist. + + + + + A user is changing the playing item. + + + + + A user is removing items from the playlist. + + + + + A user is moving an item in the playlist. + + + + + A user is adding items the queue. + + + + + A user is adding items to the queue, after the currently playing item. + + + + + A user is requesting the next item in queue. + + + + + A user is requesting the previous item in queue. + + + + + A user is changing repeat mode. + + + + + A user is changing shuffle mode. + + + + + Enum RequestType. + + + + + A user is requesting to create a new group. + + + + + A user is requesting to join a group. + + + + + A user is requesting to leave a group. + + + + + A user is requesting the list of available groups. + + + + + A user is sending a playback command to a group. + + + + + Class SendCommand. + + + + + Initializes a new instance of the class. + + The group identifier. + The playlist identifier of the playing item. + The UTC time when to execute the command. + The command. + The position ticks, for commands that require it. + The UTC time when this command has been emitted. + + + + Gets the group identifier. + + The group identifier. + + + + Gets the playlist identifier of the playing item. + + The playlist identifier of the playing item. + + + + Gets or sets the UTC time when to execute the command. + + The UTC time when to execute the command. + + + + Gets the position ticks. + + The position ticks. + + + + Gets the command. + + The command. + + + + Gets the UTC time when this command has been emitted. + + The UTC time when this command has been emitted. + + + + Enum SendCommandType. + + + + + The unpause command. Instructs users to unpause playback. + + + + + The pause command. Instructs users to pause playback. + + + + + The stop command. Instructs users to stop playback. + + + + + The seek command. Instructs users to seek to a specified time. + + + + + Used to filter the sessions of a group. + + + + + All sessions will receive the message. + + + + + Only the specified session will receive the message. + + + + + All sessions, except the current one, will receive the message. + + + + + Only sessions that are not buffering will receive the message. + + + + + + + + Initializes a new instance of the class. + + The groupId. + The data. + + + + + + + + + + Initializes a new instance of the class. + + The groupId. + The data. + + + + + + + + + + Initializes a new instance of the class. + + The groupId. + The data. + + + + + + + + + + Initializes a new instance of the class. + + The groupId. + The data. + + + + + + + + + + Initializes a new instance of the class. + + The groupId. + The data. + + + + + + + + + + Initializes a new instance of the class. + + The groupId. + The data. + + + + + + + Class QueueItem. + + + + + Initializes a new instance of the class. + + The item identifier. + + + + Gets the item identifier. + + The item identifier. + + + + Gets the playlist identifier of the item. + + The playlist identifier of the item. + + + + + + + Initializes a new instance of the class. + + The groupId. + The data. + + + + + + + + + + Initializes a new instance of the class. + + The groupId. + The data. + + + + + + + + + + Initializes a new instance of the class. + + The groupId. + The data. + + + + + + + Class UtcTimeResponse. + + + + + Initializes a new instance of the class. + + The UTC time when request has been received. + The UTC time when response has been sent. + + + + Gets the UTC time when request has been received. + + The UTC time when request has been received. + + + + Gets the UTC time when response has been sent. + + The UTC time when response has been sent. + + + + The cast receiver application model. + + + + + Gets or sets the cast receiver application id. + + + + + Gets or sets the cast receiver application name. + + + + + Contains information about a specific folder. + + + + + Gets the path of the folder in question. + + + + + Gets the free space of the underlying storage device of the . + + + + + Gets the used space of the underlying storage device of the . + + + + + Gets the kind of storage device of the . + + + + + Gets the Device Identifier. + + + + + Contains informations about a libraries storage informations. + + + + + Gets or sets the Library Id. + + + + + Gets or sets the name of the library. + + + + + Gets or sets the storage informations about the folders used in a library. + + + + + Gets or sets the date created. + + The date created. + + + + Gets or sets the date modified. + + The date modified. + + + + Gets or sets the size. + + The size. + + + + Gets or sets the name. + + The name. + + + + Gets or sets the local address. + + The local address. + + + + Gets or sets the name of the server. + + The name of the server. + + + + Gets or sets the server version. + + The version. + + + + Gets or sets the product name. This is the AssemblyProduct name. + + + + + Gets or sets the operating system. + + The operating system. + + + + Gets or sets the id. + + The id. + + + + Gets or sets a value indicating whether the startup wizard is completed. + + + Nullable for OpenAPI specification only to retain backwards compatibility in api clients. + + The startup completion status.] + + + + Class SystemInfo. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the display name of the operating system. + + The display name of the operating system. + + + + Gets or sets the package name. + + The value of the '-package' command line argument. + + + + Gets or sets a value indicating whether this instance has pending restart. + + true if this instance has pending restart; otherwise, false. + + + + Gets or sets a value indicating whether [supports library monitor]. + + true if [supports library monitor]; otherwise, false. + + + + Gets or sets the web socket port number. + + The web socket port number. + + + + Gets or sets the completed installations. + + The completed installations. + + + + Gets or sets a value indicating whether this instance can self restart. + + true. + + + + Gets or sets the program data path. + + The program data path. + + + + Gets or sets the web UI resources path. + + The web UI resources path. + + + + Gets or sets the items by name path. + + The items by name path. + + + + Gets or sets the cache path. + + The cache path. + + + + Gets or sets the log path. + + The log path. + + + + Gets or sets the internal metadata path. + + The internal metadata path. + + + + Gets or sets the transcode path. + + The transcode path. + + + + Gets or sets the list of cast receiver applications. + + + + + Gets or sets a value indicating whether this instance has update available. + + true if this instance has update available; otherwise, false. + + + + Contains informations about the systems storage. + + + + + Gets or sets the program data path. + + The program data path. + + + + Gets or sets the web UI resources path. + + The web UI resources path. + + + + Gets or sets the items by name path. + + The items by name path. + + + + Gets or sets the cache path. + + The cache path. + + + + Gets or sets the log path. + + The log path. + + + + Gets or sets the internal metadata path. + + The internal metadata path. + + + + Gets or sets the transcode path. + + The transcode path. + + + + Gets or sets the storage informations of all libraries. + + + + + Interface for configurable scheduled tasks. + + + + + Gets a value indicating whether this instance is hidden. + + true if this instance is hidden; otherwise, false. + + + + Gets a value indicating whether this instance is enabled. + + true if this instance is enabled; otherwise, false. + + + + Gets a value indicating whether this instance is logged. + + true if this instance is logged; otherwise, false. + + + + Interface IScheduledTaskWorker. + + + + + Gets the name of the task. + + The name. + + + + Gets the key of the task. + + + + + Gets the description. + + The description. + + + + Gets the category. + + The category. + + + + Executes the task. + + The progress. + The cancellation token. + Task. + + + + Gets the default triggers that define when the task will run. + + The default triggers that define when the task will run. + + + + Interface IScheduledTaskWorker. + + + + + Occurs when [task progress]. + + + + + Gets the scheduled task. + + The scheduled task. + + + + Gets the last execution result. + + The last execution result. + + + + Gets the name. + + The name. + + + + Gets the description. + + The description. + + + + Gets the category. + + The category. + + + + Gets the state. + + The state. + + + + Gets the current progress. + + The current progress. + + + + Gets or sets the triggers that define when the task will run. + + The triggers. + + + + Gets the unique id. + + The unique id. + + + + Reloads the trigger events. + + + + + Interface for the TaskManager class. + + + + + Event handler for task execution. + + + + + Event handler for task completion. + + + + + Gets the list of Scheduled Tasks. + + The scheduled tasks. + + + + Cancels if running and queue. + + An implementation of . + Task options. + + + + Cancels if running and queue. + + An implementation of . + + + + Cancels if running. + + An implementation of . + + + + Queues the scheduled task. + + An implementation of . + Task options. + + + + Queues the scheduled task. + + An implementation of . + + + + Queues the scheduled task if it is not already running. + + An implementation of . + + + + Queues the scheduled task. + + The to queue. + The to use. + + + + Adds the tasks. + + The tasks. + + + + Adds the tasks. + + The tasks. + + + + Executes the tasks. + + The tasks. + The options. + The executed tasks. + + + + Executes the tasks. + + An implementation of . + + + + Interface ITaskTrigger. + + + + + Fires when the trigger condition is satisfied and the task should run. + + + + + Gets the options of this task. + + + + + Stars waiting for the trigger action. + + Result of the last run triggered task. + The . + The name of the task. + Whether or not this is fired during startup. + + + + Stops waiting for the trigger action. + + + + + Class ScheduledTaskHelpers. + + + + + Gets the task info. + + The task. + TaskInfo. + + + + Class containing event arguments for task completion. + + + + + Initializes a new instance of the class. + + Instance of the interface. + The task result. + + + + Gets the task. + + The task. + + + + Gets the result. + + The result. + + + + Enum TaskCompletionStatus. + + + + + The completed. + + + + + The failed. + + + + + Manually cancelled by the user. + + + + + Aborted due to a system failure or shutdown. + + + + + Class TaskInfo. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the name. + + The name. + + + + Gets or sets the state of the task. + + The state of the task. + + + + Gets or sets the progress. + + The progress. + + + + Gets or sets the id. + + The id. + + + + Gets or sets the last execution result. + + The last execution result. + + + + Gets or sets the triggers. + + The triggers. + + + + Gets or sets the description. + + The description. + + + + Gets or sets the category. + + The category. + + + + Gets or sets a value indicating whether this instance is hidden. + + true if this instance is hidden; otherwise, false. + + + + Gets or sets the key. + + The key. + + + + Class containing options for tasks. + + + + + Gets or sets the maximum runtime in ticks. + + The ticks. + + + + Class TaskExecutionInfo. + + + + + Gets or sets the start time UTC. + + The start time UTC. + + + + Gets or sets the end time UTC. + + The end time UTC. + + + + Gets or sets the status. + + The status. + + + + Gets or sets the name. + + The name. + + + + Gets or sets the key. + + The key. + + + + Gets or sets the id. + + The id. + + + + Gets or sets the error message. + + The error message. + + + + Gets or sets the long error message. + + The long error message. + + + + Enum TaskState. + + + + + The idle. + + + + + The cancelling. + + + + + The running. + + + + + Class TaskTriggerInfo. + + + + + Gets or sets the type. + + The type. + + + + Gets or sets the time of day. + + The time of day. + + + + Gets or sets the interval. + + The interval. + + + + Gets or sets the day of week. + + The day of week. + + + + Gets or sets the maximum runtime ticks. + + The maximum runtime ticks. + + + + Enum TaskTriggerInfoType. + + + + + The daily trigger. + + + + + The weekly trigger. + + + + + The interval trigger. + + + + + The startup trigger. + + + + + Class InstallationInfo. + + + + + Gets or sets the Id. + + The Id. + + + + Gets or sets the name. + + The name. + + + + Gets or sets the version. + + The version. + + + + Gets or sets the changelog for this version. + + The changelog. + + + + Gets or sets the source URL. + + The source URL. + + + + Gets or sets a checksum for the binary. + + The checksum. + + + + Gets or sets package information for the installation. + + The package information. + + + + Class PackageInfo. + + + + + Initializes a new instance of the class. + + + + + Gets or sets the name. + + The name. + + + + Gets or sets a long description of the plugin containing features or helpful explanations. + + The description. + + + + Gets or sets a short overview of what the plugin does. + + The overview. + + + + Gets or sets the owner. + + The owner. + + + + Gets or sets the category. + + The category. + + + + Gets or sets the guid of the assembly associated with this plugin. + This is used to identify the proper item for automatic updates. + + The name. + + + + Gets or sets the versions. + + The versions. + + + + Gets or sets the image url for the package. + + + + + Class RepositoryInfo. + + + + + Gets or sets the name. + + The name. + + + + Gets or sets the URL. + + The URL. + + + + Gets or sets a value indicating whether the repository is enabled. + + true if enabled. + + + + Defines the class. + + + + + Gets or sets the version. + + The version. + + + + Gets the version as a . + + + + + Gets or sets the changelog for this version. + + The changelog. + + + + Gets or sets the ABI that this version was built against. + + The target ABI version. + + + + Gets or sets the source URL. + + The source URL. + + + + Gets or sets a checksum for the binary. + + The checksum. + + + + Gets or sets a timestamp of when the binary was built. + + The timestamp. + + + + Gets or sets the repository name. + + + + + Gets or sets the repository url. + + + + + Gets or sets the action. + + The action. + + + + Gets or sets the pin file. + + The pin file. + + + + Gets or sets the pin expiration date. + + The pin expiration date. + + + + Gets or sets a value indicating whether this is success. + + true if success; otherwise, false. + + + + Gets or sets the users reset. + + The users reset. + + + + Gets or sets a value indicating whether this instance is administrator. + + true if this instance is administrator; otherwise, false. + + + + Gets or sets a value indicating whether this instance is hidden. + + true if this instance is hidden; otherwise, false. + + + + Gets or sets a value indicating whether this instance can manage collections. + + true if this instance is hidden; otherwise, false. + + + + Gets or sets a value indicating whether this instance can manage subtitles. + + true if this instance is allowed; otherwise, false. + + + + Gets or sets a value indicating whether this user can manage lyrics. + + + + + Gets or sets a value indicating whether this instance is disabled. + + true if this instance is disabled; otherwise, false. + + + + Gets or sets the max parental rating. + + The max parental rating. + + + + Gets or sets a value indicating whether [enable synchronize]. + + true if [enable synchronize]; otherwise, false. + + + + Gets or sets a value indicating what SyncPlay features the user can access. + + Access level to SyncPlay features. + + + + Provides utilities for mapping file names and extensions to MIME-types. + + + + + The fallback MIME-type. Defaults to application/octet-stream. + + + + + Attempts to fetch all available file extensions for a MIME-type. + + The name of the MIME-type + All available extensions for the given MIME-type + + + + Tries to get the MIME-type for the given file name. + + The name of the file. + The MIME-type for the given file name. + true if a MIME-type was found, false otherwise. + + + + Gets the MIME-type for the given file name, + or if a mapping doesn't exist. + + The name of the file. + The MIME-type for the given file name. + +
+
diff --git a/publish/MediaBrowser.Providers.xml b/publish/MediaBrowser.Providers.xml new file mode 100644 index 00000000..a3e9bf2b --- /dev/null +++ b/publish/MediaBrowser.Providers.xml @@ -0,0 +1,3348 @@ + + + + MediaBrowser.Providers + + + + + Service to manage audiobook metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + Service to manage book metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + Provides the primary image for EPUB items that have embedded covers. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + + + + + + + + + + Provides book metadata from OPF content in an EPUB item. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + + + + + + + + Utilities for EPUB files. + + + + + Attempt to read content from ZIP archive. + + The ZIP archive. + The content file path. + + + + Provides metadata for book items that have an OPF file in the same directory. Supports the standard + content.opf filename, bespoke metadata.opf name from Calibre libraries, and OPF files that have the + same name as their respective books for directories with several books. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + Methods used to pull metadata and other information from Open Packaging Format in XML objects. + + The type of category. + + + + Initializes a new instance of the class. + + The XML document to parse. + Instance of the interface. + + + + Checks for the existence of a cover image. + + The root directory in which the OPF file is located. + Returns the found cover and its type or null. + + + + Read all supported OPF data from the file. + + The cancellation token. + The metadata result to update. + + + + Service to manage boxset metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + + + + + + + + + + + + + Service to manage channel metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Service to manage collection folder metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Service to manage folder metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + Service to manage user view metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Service to manage genre metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Service to manage live TV metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + LRC Lyric Parser. + + + + + Initializes a new instance of the class. + + + + + + + + Gets the priority. + + The priority. + + + + + + + Lyric Manager. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + The list of . + The list of . + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Task to download lyrics. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + + + + + + + + + + TXT Lyric Parser. + + + + + + + + Gets the priority. + + The priority. + + + + + + + Class ImageSaver. + + + + + The _config. + + + + + The _directory watchers. + + + + + Initializes a new instance of the class. + + The config. + The directory watchers. + The file system. + The logger. + + + + Saves the image. + + The item. + The source. + Type of the MIME. + The type. + Index of the image. + The cancellation token. + Task. + mimeType. + + + + Saves the image to location. + + The source. + The path. + The cancellation token. + Task. + + + + Gets the save paths. + + The item. + The type. + Index of the image. + Type of the MIME. + if set to true [save locally]. + IEnumerable{System.String}. + + + + Gets the current image path. + + The item. + The type. + Index of the image. + System.String. + + imageIndex + or + imageIndex. + + + + + Sets the image path. + + The item. + The type. + Index of the image. + The path. + imageIndex + or + imageIndex. + + + + + Gets the save path. + + The item. + The type. + Index of the image. + Type of the MIME. + if set to true [save locally]. + System.String. + + imageIndex + or + imageIndex. + + + + + Gets the compatible save paths. + + The item. + The type. + Index of the image. + Type of the MIME. + IEnumerable{System.String}. + imageIndex. + + + + Gets the save path for item in mixed folder. + + The item. + The type. + The image filename. + The extension. + System.String. + + + + Utilities for managing images attached to items. + + + + + Image types that are only one per item. + + + + + Initializes a new instance of the class. + + The logger. + The provider manager for interacting with provider image references. + The filesystem. + + + + Removes all existing images from the provided item. + + The to remove images from. + Whether removing images outside metadata folder is allowed. + true if changes were made to the item; otherwise false. + + + + Verifies existing images have valid paths and adds any new local images provided. + + The to validate images for. + The providers to use, must include (s) for local scanning. + The refresh options. + true if changes were made to the item; otherwise false. + + + + Refreshes from the providers according to the given options. + + The to gather images for. + The library options. + The providers to query for images. + The refresh options. + The cancellation token. + The refresh result. + + + + Refreshes from a dynamic provider. + + + + + Refreshes from a remote provider. + + The item. + The provider. + The refresh options. + The saved options. + The backdrop limit. + The downloaded images. + The result. + The cancellation token. + Task. + + + + Determines if an item already contains the given images. + + The item. + The images. + The saved options. + The backdrop limit. + true if the specified item contains images; otherwise, false. + + + + Merges a list of images into the provided item, validating existing images and replacing them or adding new images as necessary. + + The refresh options. + List of imageTypes to remove from ReplaceImages. + + + + Merges a list of images into the provided item, validating existing images and replacing them or adding new images as necessary. + + The to modify. + The new images to place in item. + The refresh options. + true if changes were made to the item; otherwise false. + + + + Before the save. + + The item. + if set to true [is full refresh]. + Type of the current update. + ItemUpdateType. + + + + Gets the providers. + + A media item. + The LibraryOptions to use. + The MetadataRefreshOptions to use. + Specifies first refresh mode. + Specifies refresh mode. + IEnumerable{`0}. + + + + Merges metadata from source into target. + + The source for new metadata. + The target to insert new metadata into. + The fields that are locked and should not be updated. + true if existing data should be replaced. + true if the metadata settings in target should be updated to match source. + Thrown if source or target are null. + + + + Class ProviderManager. + + + + + Initializes a new instance of the class. + + The Http client factory. + The subtitle manager. + The configuration manager. + The library monitor. + The logger. + The filesystem. + The server application paths. + The library manager. + The BaseItem manager. + The lyric manager. + The memory cache. + The media segment manager. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Gets the images. + + The item. + The provider. + The preferred language. + Whether to include all languages in results. + The cancellation token. + The type. + Task{IEnumerable{RemoteImageInfo}}. + + + + + + + + + + + + + + + + + + + + + + + + + + + + Saves the metadata. + + The item. + Type of the update. + The savers. + + + + Determines whether [is saver enabled for item] [the specified saver]. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Releases unmanaged and optionally managed resources. + + true to release both managed and unmanaged resources; false to release only unmanaged resources. + + + + Probes audio files for metadata. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the . + + + + Probes the specified item for metadata. + + The item to probe. + The . + The . + The type of item to resolve. + A probing the item for metadata. + + + + Fetches the specified audio. + + The . + The . + The . + The . + A representing the asynchronous operation. + + + + Fetches data from the tags. + + The . + The . + The . + Whether to extract embedded lyrics to lrc file. + + + + Uses to extract embedded images. + + + + + Initializes a new instance of the class. + + The media source manager for fetching item streams. + The media encoder for extracting embedded images. + The server configuration manager for getting image paths. + The filesystem. + + + + + + + + + + + + + + + + Resolves external audio files for . + + + + + Initializes a new instance of the class for external audio file processing. + + The logger. + The localization manager. + The media encoder. + The file system. + The object containing FileExtensions, MediaDefaultFlags, MediaForcedFlags and MediaFlagDelimiters. + + + + Uses to extract embedded images. + + + + + Initializes a new instance of the class. + + The media source manager for fetching item streams and attachments. + The media encoder for extracting attached/embedded images. + The logger. + + + + + + + + + + + + + + + + + + + Gets information about the longest playlist on a bdrom. + + The path. + VideoStream. + + + + Adds the external subtitles. + + The video. + The current streams. + The refreshOptions. + The cancellation token. + Task. + + + + Adds the external audio. + + The video. + The current streams. + The refreshOptions. + The cancellation token. + + + + Creates dummy chapters. + + The video. + An array of dummy chapters. + + + + Resolves external lyric files for . + + + + + Initializes a new instance of the class for external subtitle file processing. + + The logger. + The localization manager. + The media encoder. + The file system. + The object containing FileExtensions, MediaDefaultFlags, MediaForcedFlags and MediaFlagDelimiters. + + + + Resolves external files for . + + + + + The instance. + + + + + The instance. + + + + + The instance. + + + + + The of the files this resolver should resolve. + + + + + Initializes a new instance of the class. + + The logger. + The localization manager. + The media encoder. + The file system. + The object containing FileExtensions, MediaDefaultFlags, MediaForcedFlags and MediaFlagDelimiters. + The of the parsed file. + + + + Retrieves the external streams for the provided video. + + The object to search external streams for. + The stream index to start adding external streams at. + The directory service to search for files. + True if the directory service cache should be cleared before searching. + The cancellation token. + The external streams located. + + + + Retrieves the external streams for the provided audio. + + The object to search external streams for. + The stream index to start adding external streams at. + The directory service to search for files. + True if the directory service cache should be cleared before searching. + The external streams located. + + + + Returns the external file infos for the given video. + + The object to search external files for. + The directory service to search for files. + True if the directory service cache should be cleared before searching. + The external file paths located. + + + + Returns the external file infos for the given audio. + + The object to search external files for. + The directory service to search for files. + True if the directory service cache should be cleared before searching. + The external file paths located. + + + + Returns the media info of the given file. + + The path to the file. + The . + The cancellation token to cancel operation. + The media info for the given file. + + + + Merges path metadata into stream metadata. + + The object. + The object. + The modified mediaStream. + + + + The probe provider. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the . + Instance of the interface. + The . + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Fetches video information for an item. + + The item. + The . + The . + The type of item to resolve. + A fetching the for an item. + + + + Fetches audio information for an item. + + The item. + The . + The . + The type of item to resolve. + A fetching the for an item. + + + + Resolves external subtitle files for . + + + + + Initializes a new instance of the class for external subtitle file processing. + + The logger. + The localization manager. + The media encoder. + The file system. + The object containing FileExtensions, MediaDefaultFlags, MediaForcedFlags and MediaFlagDelimiters. + + + + + + + + + + Uses to create still images from the main video. + + + + + Initializes a new instance of the class. + + The media source manager for fetching item streams. + The media encoder for capturing images. + The logger. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + External URLs for IMDb. + + + + + + + + + + + + + + + + + + + + + + + Service to manage movie metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + Service to manage trailer metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + Service to manage music genre metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + The album metadata service. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + + + + + + + + + + + + + Service to manage artist metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + The audio metadata service. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + + + + + + + Service to manage music video metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + Service to manage person metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Service to manage photo album metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Service to manage photo metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Local playlist provider. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + + + + Service to manage playlist metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + External artist URLs for AudioDb. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + External artist URLs for AudioDb. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Gets the artist data path. + + The application paths. + The music brainz artist identifier. + System.String. + + + + Gets the artist data path. + + The application paths. + System.String. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MusicBrainz plugin configuration. + + + + + The default server URL. + + + + + The default rate limit. + + + + + Gets or sets the server URL. + + + + + Gets or sets the rate limit. + + + + + Gets or sets a value indicating whether to replace the artist name. + + + + + MusicBrainz album artist external id. + + + + + + + + + + + + + + + + + External album artist URLs for MusicBrainz. + + + + + + + + + + + MusicBrainz album external id. + + + + + + + + + + + + + + + + + External album URLs for MusicBrainz. + + + + + + + + + + + Music album metadata provider for MusicBrainz. + + + + + Initializes a new instance of the class. + + The logger. + + + + + + + + + + + + + + + + + + + + + + Dispose all resources. + + Whether to dispose. + + + + MusicBrainz artist external id. + + + + + + + + + + + + + + + + + External artist URLs for MusicBrainz. + + + + + + + + + + + MusicBrainz artist provider. + + + + + Initializes a new instance of the class. + + The logger. + + + + + + + + + + + + + + + + + + + Dispose all resources. + + Whether to dispose. + + + + MusicBrainz other artist external id. + + + + + + + + + + + + + + + + + MusicBrainz recording id. + + + + + + + + + + + + + + + + + MusicBrainz release group external id. + + + + + + + + + + + + + + + + + External release group URLs for MusicBrainz. + + + + + + + + + + + External track URLs for MusicBrainz. + + + + + + + + + + + MusicBrainz track id. + + + + + + + + + + + + + + + + + Plugin instance. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Gets the current plugin instance. + + + + + + + + + + + + + + + + + + + + Converts a string N/A to string.Empty. + + + + + + + + + + + Converts a string N/A to string.Empty. + + + + + + + + + + + Gets or sets the results. + + The results. + + + Provider for OMDB service. + + + Initializes a new instance of the class. + HttpClientFactory to use for calls to OMDB service. + IFileSystem to use for store OMDB data. + IServerConfigurationManager to use. + + + Fetches data from OMDB service. + Metadata about media item. + IMDB ID for media. + Media language. + Country of origin. + CancellationToken to use for operation. + The first generic type parameter. + Returns a Task object that can be awaited. + + + Gets data about an episode. + Metadata about episode. + Episode number. + Season number. + Episode ID. + Season ID. + Episode language. + Country of origin. + CancellationToken to use for operation. + The first generic type parameter. + Whether operation was successful. + + + Gets OMDB URL. + Appends query string to URL. + OMDB URL with optional query string. + + + + Extract the year from a string. + + The input string. + The year. + A value indicating whether the input could successfully be parsed as a year. + + + Describes OMDB rating. + + + Gets or sets rating source. + + + Gets or sets rating value. + + + + Plugin configuration class for the studio image provider. + + + + + Gets or sets the studio image repository URL. + + + + + Artwork Plugin class. + + + + + Artwork repository URL. + + + + + Initializes a new instance of the class. + + application paths. + xml serializer. + + + + Gets the instance of Artwork plugin. + + + + + + + + + + + + + + + + + + + + Studio image provider. + + + + + Initializes a new instance of the class. + + The . + The . + The . + + + + + + + + + + + + + + + + + + + Ensures the existence of a file listing. + + The URL. + The file. + The file system. + The cancellation token. + A Task to ensure existence of a file listing. + + + + Get matching image for an item. + + The . + The enumerable of image strings. + The matching image string. + + + + Get available image strings for a file. + + The file. + All images strings of a file. + + + + The TMDb API controller. + + + + + Initializes a new instance of the class. + + The TMDb client manager. + + + + Gets the TMDb image configuration options. + + The image portion of the TMDb client configuration. + + + + External id for a TMDb box set. + + + + + + + + + + + + + + + + + BoxSet image provider powered by TMDb. + + + + + Initializes a new instance of the class. + + The . + The . + + + + + + + + + + + + + + + + + + + + + + BoxSet provider powered by TMDb. + + + + + Initializes a new instance of the class. + + The . + The . + The . + + + + + + + + + + + + + + + + Plugin configuration class for TMDb library. + + + + + Gets or sets a value to use as the API key for accessing TMDb. This is intentionally excluded from the + settings page as the API key should not need to be changed by most users. + + + + + Gets or sets a value indicating whether include adult content when searching with TMDb. + + + + + Gets or sets a value indicating whether tags should be imported for series from TMDb. + + + + + Gets or sets a value indicating whether tags should be imported for movies from TMDb. + + + + + Gets or sets a value indicating whether season name should be imported from TMDb. + + + + + Gets or sets a value indicating the maximum number of cast members to fetch for an item. + + + + + Gets or sets a value indicating the maximum number of crew members to fetch for an item. + + + + + Gets or sets a value indicating whether to hide cast members without profile images. + + + + + Gets or sets a value indicating whether to hide crew members without profile images. + + + + + Gets or sets a value indicating the poster image size to fetch. + + + + + Gets or sets a value indicating the backdrop image size to fetch. + + + + + Gets or sets a value indicating the logo image size to fetch. + + + + + Gets or sets a value indicating the profile image size to fetch. + + + + + Gets or sets a value indicating the still image size to fetch. + + + + + External id for a TMDb movie. + + + + + + + + + + + + + + + + + Movie image provider powered by TMDb. + + + + + Initializes a new instance of the class. + + The . + The . + + + + + + + + + + + + + + + + + + + + + + Movie provider powered by TMDb. + + + + + Initializes a new instance of the class. + + The . + The . + The . + + + + + + + + + + + + + + + + + + + External id for a TMDb person. + + + + + + + + + + + + + + + + + Person image provider powered by TMDb. + + + + + Initializes a new instance of the class. + + The . + The . + + + + + + + + + + + + + + + + + + + + + + Person image provider powered by TMDb. + + + + + Initializes a new instance of the class. + + The . + The . + + + + + + + + + + + + + + + + Plugin class for the TMDb library. + + + + + Initializes a new instance of the class. + + application paths. + xml serializer. + + + + Gets the instance of TMDb plugin. + + + + + + + + + + + + + + + + + Return the plugin configuration page. + + PluginPageInfo. + + + + Manager class for abstracting the TMDb API client library. + + + + + Initializes a new instance of the class. + + An instance of . + + + + Gets a movie from the TMDb API based on its TMDb id. + + The movie's TMDb id. + The movie's language. + A comma-separated list of image languages. + The country code, ISO 3166-1. + The cancellation token. + The TMDb movie or null if not found. + + + + Gets a collection from the TMDb API based on its TMDb id. + + The collection's TMDb id. + The collection's language. + A comma-separated list of image languages. + The country code, ISO 3166-1. + The cancellation token. + The TMDb collection or null if not found. + + + + Gets a tv show from the TMDb API based on its TMDb id. + + The tv show's TMDb id. + The tv show's language. + A comma-separated list of image languages. + The country code, ISO 3166-1. + The cancellation token. + The TMDb tv show information or null if not found. + + + + Gets a tv show episode group from the TMDb API based on the show id and the display order. + + The tv show's TMDb id. + The display order. + The tv show's language. + A comma-separated list of image languages. + The country code, ISO 3166-1. + The cancellation token. + The TMDb tv show episode group information or null if not found. + + + + Gets a tv season from the TMDb API based on the tv show's TMDb id. + + The tv season's TMDb id. + The season number. + The tv season's language. + A comma-separated list of image languages. + The country code, ISO 3166-1. + The cancellation token. + The TMDb tv season information or null if not found. + + + + Gets a movie from the TMDb API based on the tv show's TMDb id. + + The tv show's TMDb id. + The season number. + The episode number. + The display order. + The episode's language. + A comma-separated list of image languages. + The country code, ISO 3166-1. + The cancellation token. + The TMDb tv episode information or null if not found. + + + + Gets a person eg. cast or crew member from the TMDb API based on its TMDb id. + + The person's TMDb id. + The person's language. + The country code, ISO 3166-1. + The cancellation token. + The TMDb person information or null if not found. + + + + Gets an item from the TMDb API based on its id from an external service eg. IMDb id, TvDb id. + + The item's external id. + The source of the id eg. IMDb. + The item's language. + The country code, ISO 3166-1. + The cancellation token. + The TMDb item or null if not found. + + + + Searches for a tv show using the TMDb API based on its name. + + The name of the tv show. + The tv show's language. + The country code, ISO 3166-1. + The year the tv show first aired. + The cancellation token. + The TMDb tv show information. + + + + Searches for a person based on their name using the TMDb API. + + The name of the person. + The cancellation token. + The TMDb person information. + + + + Searches for a movie based on its name using the TMDb API. + + The name of the movie. + The movie's language. + The cancellation token. + The TMDb movie information. + + + + Searches for a movie based on its name using the TMDb API. + + The name of the movie. + The release year of the movie. + The movie's language. + The country code, ISO 3166-1. + The cancellation token. + The TMDb movie information. + + + + Searches for a collection based on its name using the TMDb API. + + The name of the collection. + The collection's language. + The country code, ISO 3166-1. + The cancellation token. + The TMDb collection information. + + + + Handles bad path checking and builds the absolute url. + + The image size to fetch. + The relative URL of the image. + The absolute URL. + + + + Gets the absolute URL of the poster. + + The relative URL of the poster. + The absolute URL. + + + + Gets the absolute URL of the profile image. + + The relative URL of the profile image. + The absolute URL. + + + + Converts poster s into s. + + The input images. + The requested language. + The remote images. + + + + Converts backdrop s into s. + + The input images. + The requested language. + The remote images. + + + + Converts logo s into s. + + The input images. + The requested language. + The remote images. + + + + Converts profile s into s. + + The input images. + The requested language. + The remote images. + + + + Converts still s into s. + + The input images. + The requested language. + The remote images. + + + + Converts s into s. + + The input images. + The size of the image to fetch. + The type of the image. + The requested language. + The remote images. + + + + Gets the configuration. + + The configuration. + + + + + + + Releases unmanaged and - optionally - managed resources. + + true to release both managed and unmanaged resources; false to release only unmanaged resources. + + + + External URLs for TMDb. + + + + + + + + + + + Utilities for the TMDb provider. + + + + + URL of the TMDb instance to use. + + + + + Name of the provider. + + + + + API key to use when performing an API call. + + + + + The crew types to keep. + + + + + The crew kinds to keep. + + + + + Pattern:
+ [\W_-[·]]+
+ Explanation:
+ + ○ Match a character in the set [_\W-[\u00B7]] atomically at least once.
+
+
+
+ + + Cleans the name according to TMDb requirements. + + The name of the entity. + The cleaned name. + + + + Maps the TMDb provided roles for crew members to Jellyfin roles. + + Crew member to map against the Jellyfin person types. + The Jellyfin person type. + + + + Determines whether a video is a trailer. + + The TMDb video. + A boolean indicating whether the video is a trailer. + + + + Normalizes a language string for use with TMDb's include image language parameter. + + The preferred language as either a 2 letter code with or without country code. + The country code, ISO 3166-1. + The comma separated language string. + + + + Normalizes a language string for use with TMDb's language parameter. + + The language code. + The country code. + The normalized language code. + + + + Adjusts the image's language code preferring the 5 letter language code eg. en-US. + + The image's actual language code. + The requested language code. + The language code. + + + + Combines the metadata country code and the parental rating from the API into the value we store in our database. + + The ISO 3166-1 country code of the rating country. + The rating value returned by the TMDb API. + The combined parental rating of country code+rating value. + + + + TV episode image provider powered by TheMovieDb. + + + + + Initializes a new instance of the class. + + The . + The . + + + + + + + + + + + + + + + + + + + + + + TV episode provider powered by TheMovieDb. + + + + + Initializes a new instance of the class. + + The . + The . + + + + + + + + + + + + + + + + + + + TV season image provider powered by TheMovieDb. + + + + + Initializes a new instance of the class. + + The . + The . + + + + + + + + + + + + + + + + + + + + + + TV season provider powered by TheMovieDb. + + + + + Initializes a new instance of the class. + + The . + The . + + + + + + + + + + + + + + + + External id for a TMDb series. + + + + + + + + + + + + + + + + + TV series image provider powered by TheMovieDb. + + + + + Initializes a new instance of the class. + + The . + The . + + + + + + + + + + + + + + + + + + + + + + TV series provider powered by TheMovieDb. + + + + + Initializes a new instance of the class. + + The . + The . + The . + + + + + + + + + + + + + + + + + + + Service to manage studio metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Class TrickplayImagesTask. + + + + + Initializes a new instance of the class. + + The logger. + The library manager. + The localization manager. + The trickplay manager. + + + + + + + + + + + + + + + + + + + + + + Class TrickplayMoveImagesTask. + + + + + Initializes a new instance of the class. + + The logger. + The library manager. + The localization manager. + The trickplay manager. + + + + + + + + + + + + + + + + + + + + + + Class TrickplayProvider. Provides images and metadata for trickplay + scrubbing previews. + + + + + Initializes a new instance of the class. + + The configuration manager. + The trickplay manager. + The library manager. + + + + + + + + + + + + + + + + + + + + + + + + + + + + Service to manage episode metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + Service to manage season metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + + + + Service to manage series metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + Creates seasons for all episodes if they don't exist. + If no season number can be determined, a dummy season will be created. + + The series. + The cancellation token. + The async task. + + + + Creates a new season, adds it to the database by linking it to the [series] and refreshes the metadata. + + The series. + The season name. + The season number. + The cancellation token. + The newly created season. + + + + + + + + + + + + + + + + External URLs for TMDb. + + + + + + + + + + + Service to manage video metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + Service to manage year metadata. + + + + + Initializes a new instance of the class. + + Instance of the . + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + Custom -derived type for the NonWordRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Helper methods used by generated -derived implementations. + + + Default timeout value set in , or if none was set. + + + Whether is non-infinite. + + + Finds the next index of any character that matches a character in the set [_\W-[\u00B7]]. + + + Supports searching for characters in or not in "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz". + +
+
diff --git a/publish/MediaBrowser.XbmcMetadata.xml b/publish/MediaBrowser.XbmcMetadata.xml new file mode 100644 index 00000000..55f74e23 --- /dev/null +++ b/publish/MediaBrowser.XbmcMetadata.xml @@ -0,0 +1,710 @@ + + + + MediaBrowser.XbmcMetadata + + + + + + + + responsible for updating NFO files' user data. + + + + + Initializes a new instance of the class. + + The . + The . + The . + The . + + + + + + + + + + The BaseNfoParser class. + + The type. + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Gets the logger. + + + + + Gets the provider manager. + + + + + Gets a value indicating whether URLs after a closing XML tag are supported. + + + + + Fetches metadata for an item from one xml file. + + The . + The metadata file. + The . + item is null. + metadataFile is null or empty. + + + + Fetches the specified item. + + The . + The metadata file. + The . + The . + + + + Parses a XML tag to a provider id. + + The item. + The xml tag. + + + + Fetches metadata from an XML node. + + The . + The . + + + + Parses the from the NFO aspect property. + + The NFO aspect property. + The . + + + + Nfo parser for episodes. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + Reads the episode details from the given xml and saves the result in the provided result item. + + + + + Nfo parser for movies. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + Nfo parser for seasons. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + Nfo parser for series. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + NFO parser for seasons based on series NFO. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + Nfo provider for albums. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + Nfo provider for artists. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + + + + + + + + + + + + + + + + Nfo provider for episodes. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + Nfo provider for movies. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Nfo provider for music videos. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Nfo provider for seasons. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + Nfo provider for series. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + NFO provider for seasons based on series NFO. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + + + + Nfo provider for videos. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + Nfo saver for albums. + + + + + Initializes a new instance of the class. + + The file system. + the server configuration manager. + The library manager. + The user manager. + The user data manager. + The logger. + + + + + + + + + + + + + + + + + + + Nfo saver for artist. + + + + + Initializes a new instance of the class. + + The file system. + the server configuration manager. + The library manager. + The user manager. + The user data manager. + The logger. + + + + + + + + + + + + + + + + + + + + + + Pattern:
+ (?<![\uD800-\uDBFF])[\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x9F\uFEFF\uFFFE\uFFFF]
+ Explanation:
+ + ○ Match with 3 alternative expressions, atomically.
+ ○ Match a sequence of expressions.
+ ○ Zero-width negative lookbehind.
+ ○ Match a character in the set [\uD800-\uDBFF] right-to-left.
+ ○ Match a character in the set [\uDC00-\uDFFF].
+ ○ Match a sequence of expressions.
+ ○ Match a character in the set [\uD800-\uDBFF].
+ ○ Zero-width negative lookahead.
+ ○ Match a character in the set [\uDC00-\uDFFF].
+ ○ Match a character in the set [^\t\n\r -~\u00A0-\uFEFE\uFF00-\uFFFD].
+
+
+
+ + + + + + Gets the save path. + + The item. + . + + + + Gets the name of the root element. + + The item. + . + + + + + + + + + + Adds the common nodes. + + + + + Gets the output trailer URL. + + The URL. + System.String. + + + + Nfo saver for episodes. + + + + + Initializes a new instance of the class. + + The file system. + the server configuration manager. + The library manager. + The user manager. + The user data manager. + The logger. + + + + + + + + + + + + + + + + + + + Nfo saver for movies. + + + + + Initializes a new instance of the class. + + The file system. + the server configuration manager. + The library manager. + The user manager. + The user data manager. + The logger. + + + + + + + + + + + + + + + + + + + Nfo saver for seasons. + + + + + Initializes a new instance of the class. + + The file system. + the server configuration manager. + The library manager. + The user manager. + The user data manager. + The logger. + + + + + + + + + + + + + + + + + + + Nfo saver for series. + + + + + Initializes a new instance of the class. + + The file system. + the server configuration manager. + The library manager. + The user manager. + The user data manager. + The logger. + + + + + + + + + + + + + + + + + + Custom -derived type for the InvalidXMLCharsRegexRegex method. + + + Cached, thread-safe singleton instance. + + + Initializes the instance. + + + Provides a factory for creating instances to be used by methods on . + + + Creates an instance of a used by methods on . + + + Provides the runner that contains the custom logic implementing the specified regular expression. + + + Scan the starting from base.runtextstart for the next match. + The text being scanned by the regular expression. + + + Search starting from base.runtextpos for the next location a match could possibly start. + The text being scanned by the regular expression. + true if a possible match was found; false if no more matches are possible. + + + Determine whether at base.runtextpos is a match for the regular expression. + The text being scanned by the regular expression. + true if the regular expression matches at the current position; otherwise, false. + + + Helper methods used by generated -derived implementations. + + + Default timeout value set in , or if none was set. + + + Whether is non-infinite. + + + Finds the next index of any character that matches a character in the set [^\t\n\r -~\u00A0-\uD7FF\uE000-\uFEFE\uFF00-\uFFFD]. + + + Supports searching for characters in or not in "\t\n\r !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~". + +
+
diff --git a/publish/Resources/Configuration/logging.json b/publish/Resources/Configuration/logging.json new file mode 100644 index 00000000..6462d791 --- /dev/null +++ b/publish/Resources/Configuration/logging.json @@ -0,0 +1,39 @@ +{ + "Serilog": { + "MinimumLevel": { + "Default": "Information", + "Override": { + "Microsoft": "Warning", + "System": "Warning", + "Microsoft.EntityFrameworkCore.Database.Command": "Information" + } + }, + "WriteTo": [ + { + "Name": "Console", + "Args": { + "outputTemplate": "[{Timestamp:HH:mm:ss.fff}] [{Level:u3}] [{ThreadId}] {SourceContext}: {Message:lj}{NewLine}{Exception}" + } + }, + { + "Name": "Async", + "Args": { + "configure": [ + { + "Name": "File", + "Args": { + "path": "%JELLYFIN_LOG_DIR%//log_.log", + "rollingInterval": "Day", + "retainedFileCountLimit": 3, + "rollOnFileSizeLimit": true, + "fileSizeLimitBytes": 100000000, + "outputTemplate": "[{Timestamp:yyyy-MM-dd HH:mm:ss.fff zzz}] [{Level:u3}] [{ThreadId}] {SourceContext}: {Message}{NewLine}{Exception}" + } + } + ] + } + } + ], + "Enrich": [ "FromLogContext", "WithThreadId" ] + } +} diff --git a/publish/Resources/Configuration/startup.default.json b/publish/Resources/Configuration/startup.default.json new file mode 100644 index 00000000..44be9e16 --- /dev/null +++ b/publish/Resources/Configuration/startup.default.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://json.schemastore.org/jellyfin-startup", + "// Comment": "Startup configuration defaults for Jellyfin Server", + "// Note": "For Linux: Use /var/lib/jellyfin, For Windows: Use C:/ProgramData/jellyfin", + "// Documentation": "These values are used when no command-line args or environment variables are set", + "Paths": { + "DataDir": "/var/lib/jellyfin", + "ConfigDir": "/var/lib/jellyfin", + "CacheDir": "/var/lib/jellyfin", + "LogDir": "/var/lib/jellyfin", + "TempDir": "/var/lib/jellyfin", + "WebDir": "/var/lib/jellyfin" + } +} diff --git a/publish/Resources/Configuration/startup.linux.json b/publish/Resources/Configuration/startup.linux.json new file mode 100644 index 00000000..f7c04e71 --- /dev/null +++ b/publish/Resources/Configuration/startup.linux.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://json.schemastore.org/jellyfin-startup", + "// Comment": "Linux-specific startup configuration for Jellyfin Server", + "// Instructions": "Copy this file to 'startup.json' in the Jellyfin directory", + "// Documentation": "These paths follow Linux FHS (Filesystem Hierarchy Standard)", + "Paths": { + "DataDir": "/var/lib/jellyfin", + "ConfigDir": "/var/lib/jellyfin", + "CacheDir": "/var/lib/jellyfin", + "LogDir": "/var/lib/jellyfin", + "TempDir": "/var/lib/jellyfin", + "WebDir": "/var/lib/jellyfin" + } +} diff --git a/publish/Resources/Configuration/startup.windows.json b/publish/Resources/Configuration/startup.windows.json new file mode 100644 index 00000000..ec3ce212 --- /dev/null +++ b/publish/Resources/Configuration/startup.windows.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://json.schemastore.org/jellyfin-startup", + "// Comment": "Windows-specific startup configuration for Jellyfin Server", + "// Instructions": "Copy this file to 'startup.json' in the Jellyfin directory", + "// Documentation": "These paths are optimized for Windows installations", + "Paths": { + "DataDir": "C:/ProgramData/jellyfin", + "ConfigDir": "C:/ProgramData/jellyfin", + "CacheDir": "C:/ProgramData/jellyfin", + "LogDir": "C:/ProgramData/jellyfin", + "TempDir": "C:/ProgramData/jellyfin", + "WebDir": "C:/ProgramData/jellyfin" + } +} diff --git a/publish/ServerSetupApp/index.mstemplate.html b/publish/ServerSetupApp/index.mstemplate.html new file mode 100644 index 00000000..890a7761 --- /dev/null +++ b/publish/ServerSetupApp/index.mstemplate.html @@ -0,0 +1,235 @@ + + + + + + + {{#IF isInReportingMode}} + ❌ + {{/IF}} + Jellyfin Startup + + + + + +
+
+ + {{^IF isInReportingMode}} +

Jellyfin Server {{version}} still starting. Please wait.

+ {{#ELSE}} +

Jellyfin Server has encountered an error and was not able to start.

+ {{/ELSE}} + {{/IF}} + + {{#IF localNetworkRequest}} +

You can download the current log file here.

+ {{/IF}} +
+ + {{#DECLARE LogEntry |--}} + {{#LET children = Children}} +
  • + {{--| #IF children.Count > 0}} +
    + {{DateOfCreation}} - {{Content}} +
      + {{--| #EACH children.Reverse() |-}} + {{#IMPORT 'LogEntry'}} + {{--| /EACH |-}} +
    +
    + {{--| #ELSE |-}} + {{DateOfCreation}} - {{Content}} + {{--| /ELSE |--}} + {{--| /IF |-}} +
  • + {{--| /DECLARE}} + + {{#IF localNetworkRequest}} +
    +
      + {{#FOREACH log IN logs.Reverse()}} + {{#IMPORT 'LogEntry' #WITH log}} + {{/FOREACH}} +
    +
    + {{#ELSE}} + {{#IF networkManagerReady}} +

    Please visit this page from your local network to view detailed startup logs.

    + {{#ELSE}} +

    Initializing network settings. Please wait.

    + {{/ELSE}} + {{/IF}} + {{/ELSE}} + {{/IF}} +
    + + +{{^IF isInReportingMode}} + +{{/IF}} + + diff --git a/publish/jellyfin.exe b/publish/jellyfin.exe new file mode 100644 index 00000000..32080539 Binary files /dev/null and b/publish/jellyfin.exe differ diff --git a/publish/jellyfin.staticwebassets.endpoints.json b/publish/jellyfin.staticwebassets.endpoints.json new file mode 100644 index 00000000..7229f5a4 --- /dev/null +++ b/publish/jellyfin.staticwebassets.endpoints.json @@ -0,0 +1 @@ +{"Version":1,"ManifestType":"Publish","Endpoints":[{"Route":"api-docs/jellyfin.48bx5ylorm.svg","AssetFile":"api-docs/jellyfin.svg.gz","Selectors":[{"Name":"Content-Encoding","Value":"gzip","Quality":"0.000518941360"}],"ResponseHeaders":[{"Name":"Cache-Control","Value":"max-age=31536000, immutable"},{"Name":"Content-Encoding","Value":"gzip"},{"Name":"Content-Length","Value":"1926"},{"Name":"Content-Type","Value":"image/svg+xml"},{"Name":"ETag","Value":"\"Bqm5Ssyd8Smjq7m8PqfBksOvvMhheZI11UcwBubk4pw=\""},{"Name":"Last-Modified","Value":"Wed, 29 Apr 2026 12:24:01 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"fingerprint","Value":"48bx5ylorm"},{"Name":"integrity","Value":"sha256-FPRGta9vwgkLKF9bWxaQp+Qsf4e1uvLKMXSOtGNSTpI="},{"Name":"label","Value":"api-docs/jellyfin.svg"},{"Name":"original-resource","Value":"\"FPRGta9vwgkLKF9bWxaQp+Qsf4e1uvLKMXSOtGNSTpI=\""}]},{"Route":"api-docs/jellyfin.48bx5ylorm.svg","AssetFile":"api-docs/jellyfin.svg.br","Selectors":[{"Name":"Content-Encoding","Value":"br","Quality":"0.000584453536"}],"ResponseHeaders":[{"Name":"Cache-Control","Value":"max-age=31536000, immutable"},{"Name":"Content-Encoding","Value":"br"},{"Name":"Content-Length","Value":"1710"},{"Name":"Content-Type","Value":"image/svg+xml"},{"Name":"ETag","Value":"\"V5ld9HBxWzrQeJE/ivTkPe8lC3POtupi8dPFtlzEcKQ=\""},{"Name":"Last-Modified","Value":"Fri, 01 May 2026 19:48:04 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"fingerprint","Value":"48bx5ylorm"},{"Name":"integrity","Value":"sha256-FPRGta9vwgkLKF9bWxaQp+Qsf4e1uvLKMXSOtGNSTpI="},{"Name":"label","Value":"api-docs/jellyfin.svg"},{"Name":"original-resource","Value":"\"FPRGta9vwgkLKF9bWxaQp+Qsf4e1uvLKMXSOtGNSTpI=\""}]},{"Route":"api-docs/jellyfin.48bx5ylorm.svg","AssetFile":"api-docs/jellyfin.svg","Selectors":[],"ResponseHeaders":[{"Name":"Cache-Control","Value":"max-age=31536000, immutable"},{"Name":"Content-Length","Value":"5434"},{"Name":"Content-Type","Value":"image/svg+xml"},{"Name":"ETag","Value":"\"FPRGta9vwgkLKF9bWxaQp+Qsf4e1uvLKMXSOtGNSTpI=\""},{"Name":"Last-Modified","Value":"Wed, 04 Mar 2026 13:00:58 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"fingerprint","Value":"48bx5ylorm"},{"Name":"integrity","Value":"sha256-FPRGta9vwgkLKF9bWxaQp+Qsf4e1uvLKMXSOtGNSTpI="},{"Name":"label","Value":"api-docs/jellyfin.svg"}]},{"Route":"api-docs/jellyfin.48bx5ylorm.svg.br","AssetFile":"api-docs/jellyfin.svg.br","Selectors":[],"ResponseHeaders":[{"Name":"Cache-Control","Value":"max-age=31536000, immutable"},{"Name":"Content-Encoding","Value":"br"},{"Name":"Content-Length","Value":"1710"},{"Name":"Content-Type","Value":"image/svg+xml"},{"Name":"ETag","Value":"\"V5ld9HBxWzrQeJE/ivTkPe8lC3POtupi8dPFtlzEcKQ=\""},{"Name":"Last-Modified","Value":"Fri, 01 May 2026 19:48:04 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"fingerprint","Value":"48bx5ylorm"},{"Name":"integrity","Value":"sha256-V5ld9HBxWzrQeJE/ivTkPe8lC3POtupi8dPFtlzEcKQ="},{"Name":"label","Value":"api-docs/jellyfin.svg.br"}]},{"Route":"api-docs/jellyfin.48bx5ylorm.svg.gz","AssetFile":"api-docs/jellyfin.svg.gz","Selectors":[],"ResponseHeaders":[{"Name":"Cache-Control","Value":"max-age=31536000, immutable"},{"Name":"Content-Encoding","Value":"gzip"},{"Name":"Content-Length","Value":"1926"},{"Name":"Content-Type","Value":"image/svg+xml"},{"Name":"ETag","Value":"\"Bqm5Ssyd8Smjq7m8PqfBksOvvMhheZI11UcwBubk4pw=\""},{"Name":"Last-Modified","Value":"Wed, 29 Apr 2026 12:24:01 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"fingerprint","Value":"48bx5ylorm"},{"Name":"integrity","Value":"sha256-Bqm5Ssyd8Smjq7m8PqfBksOvvMhheZI11UcwBubk4pw="},{"Name":"label","Value":"api-docs/jellyfin.svg.gz"}]},{"Route":"api-docs/jellyfin.svg","AssetFile":"api-docs/jellyfin.svg.gz","Selectors":[{"Name":"Content-Encoding","Value":"gzip","Quality":"0.000518941360"}],"ResponseHeaders":[{"Name":"Cache-Control","Value":"max-age=3600, must-revalidate"},{"Name":"Content-Encoding","Value":"gzip"},{"Name":"Content-Length","Value":"1926"},{"Name":"Content-Type","Value":"image/svg+xml"},{"Name":"ETag","Value":"\"Bqm5Ssyd8Smjq7m8PqfBksOvvMhheZI11UcwBubk4pw=\""},{"Name":"Last-Modified","Value":"Wed, 29 Apr 2026 12:24:01 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"integrity","Value":"sha256-FPRGta9vwgkLKF9bWxaQp+Qsf4e1uvLKMXSOtGNSTpI="},{"Name":"original-resource","Value":"\"FPRGta9vwgkLKF9bWxaQp+Qsf4e1uvLKMXSOtGNSTpI=\""}]},{"Route":"api-docs/jellyfin.svg","AssetFile":"api-docs/jellyfin.svg.br","Selectors":[{"Name":"Content-Encoding","Value":"br","Quality":"0.000584453536"}],"ResponseHeaders":[{"Name":"Cache-Control","Value":"max-age=3600, must-revalidate"},{"Name":"Content-Encoding","Value":"br"},{"Name":"Content-Length","Value":"1710"},{"Name":"Content-Type","Value":"image/svg+xml"},{"Name":"ETag","Value":"\"V5ld9HBxWzrQeJE/ivTkPe8lC3POtupi8dPFtlzEcKQ=\""},{"Name":"Last-Modified","Value":"Fri, 01 May 2026 19:48:04 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"integrity","Value":"sha256-FPRGta9vwgkLKF9bWxaQp+Qsf4e1uvLKMXSOtGNSTpI="},{"Name":"original-resource","Value":"\"FPRGta9vwgkLKF9bWxaQp+Qsf4e1uvLKMXSOtGNSTpI=\""}]},{"Route":"api-docs/jellyfin.svg","AssetFile":"api-docs/jellyfin.svg","Selectors":[],"ResponseHeaders":[{"Name":"Cache-Control","Value":"max-age=3600, must-revalidate"},{"Name":"Content-Length","Value":"5434"},{"Name":"Content-Type","Value":"image/svg+xml"},{"Name":"ETag","Value":"\"FPRGta9vwgkLKF9bWxaQp+Qsf4e1uvLKMXSOtGNSTpI=\""},{"Name":"Last-Modified","Value":"Wed, 04 Mar 2026 13:00:58 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"integrity","Value":"sha256-FPRGta9vwgkLKF9bWxaQp+Qsf4e1uvLKMXSOtGNSTpI="}]},{"Route":"api-docs/jellyfin.svg.br","AssetFile":"api-docs/jellyfin.svg.br","Selectors":[],"ResponseHeaders":[{"Name":"Cache-Control","Value":"max-age=3600, must-revalidate"},{"Name":"Content-Encoding","Value":"br"},{"Name":"Content-Length","Value":"1710"},{"Name":"Content-Type","Value":"image/svg+xml"},{"Name":"ETag","Value":"\"V5ld9HBxWzrQeJE/ivTkPe8lC3POtupi8dPFtlzEcKQ=\""},{"Name":"Last-Modified","Value":"Fri, 01 May 2026 19:48:04 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"integrity","Value":"sha256-V5ld9HBxWzrQeJE/ivTkPe8lC3POtupi8dPFtlzEcKQ="}]},{"Route":"api-docs/jellyfin.svg.gz","AssetFile":"api-docs/jellyfin.svg.gz","Selectors":[],"ResponseHeaders":[{"Name":"Cache-Control","Value":"max-age=3600, must-revalidate"},{"Name":"Content-Encoding","Value":"gzip"},{"Name":"Content-Length","Value":"1926"},{"Name":"Content-Type","Value":"image/svg+xml"},{"Name":"ETag","Value":"\"Bqm5Ssyd8Smjq7m8PqfBksOvvMhheZI11UcwBubk4pw=\""},{"Name":"Last-Modified","Value":"Wed, 29 Apr 2026 12:24:01 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"integrity","Value":"sha256-Bqm5Ssyd8Smjq7m8PqfBksOvvMhheZI11UcwBubk4pw="}]},{"Route":"api-docs/redoc/custom.5ipweew5fc.css","AssetFile":"api-docs/redoc/custom.css.gz","Selectors":[{"Name":"Content-Encoding","Value":"gzip","Quality":"0.047619047619"}],"ResponseHeaders":[{"Name":"Cache-Control","Value":"max-age=31536000, immutable"},{"Name":"Content-Encoding","Value":"gzip"},{"Name":"Content-Length","Value":"20"},{"Name":"Content-Type","Value":"text/css"},{"Name":"ETag","Value":"\"nnKSjnoBYVtM8JDaphe0yp1oUxdI+IfzI/aV60yj72M=\""},{"Name":"Last-Modified","Value":"Wed, 29 Apr 2026 12:24:01 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"fingerprint","Value":"5ipweew5fc"},{"Name":"integrity","Value":"sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU="},{"Name":"label","Value":"api-docs/redoc/custom.css"},{"Name":"original-resource","Value":"\"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=\""}]},{"Route":"api-docs/redoc/custom.5ipweew5fc.css","AssetFile":"api-docs/redoc/custom.css.br","Selectors":[{"Name":"Content-Encoding","Value":"br","Quality":"0.500000000000"}],"ResponseHeaders":[{"Name":"Cache-Control","Value":"max-age=31536000, immutable"},{"Name":"Content-Encoding","Value":"br"},{"Name":"Content-Length","Value":"1"},{"Name":"Content-Type","Value":"text/css"},{"Name":"ETag","Value":"\"QbgF6nrAFOI1VumLs3RwKgg0Qmj5JImgLwiAhJOUoeQ=\""},{"Name":"Last-Modified","Value":"Fri, 01 May 2026 19:48:04 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"fingerprint","Value":"5ipweew5fc"},{"Name":"integrity","Value":"sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU="},{"Name":"label","Value":"api-docs/redoc/custom.css"},{"Name":"original-resource","Value":"\"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=\""}]},{"Route":"api-docs/redoc/custom.5ipweew5fc.css","AssetFile":"api-docs/redoc/custom.css","Selectors":[],"ResponseHeaders":[{"Name":"Cache-Control","Value":"max-age=31536000, immutable"},{"Name":"Content-Length","Value":"0"},{"Name":"Content-Type","Value":"text/css"},{"Name":"ETag","Value":"\"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=\""},{"Name":"Last-Modified","Value":"Wed, 04 Mar 2026 13:00:58 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"fingerprint","Value":"5ipweew5fc"},{"Name":"integrity","Value":"sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU="},{"Name":"label","Value":"api-docs/redoc/custom.css"}]},{"Route":"api-docs/redoc/custom.5ipweew5fc.css.br","AssetFile":"api-docs/redoc/custom.css.br","Selectors":[],"ResponseHeaders":[{"Name":"Cache-Control","Value":"max-age=31536000, immutable"},{"Name":"Content-Encoding","Value":"br"},{"Name":"Content-Length","Value":"1"},{"Name":"Content-Type","Value":"text/css"},{"Name":"ETag","Value":"\"QbgF6nrAFOI1VumLs3RwKgg0Qmj5JImgLwiAhJOUoeQ=\""},{"Name":"Last-Modified","Value":"Fri, 01 May 2026 19:48:04 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"fingerprint","Value":"5ipweew5fc"},{"Name":"integrity","Value":"sha256-QbgF6nrAFOI1VumLs3RwKgg0Qmj5JImgLwiAhJOUoeQ="},{"Name":"label","Value":"api-docs/redoc/custom.css.br"}]},{"Route":"api-docs/redoc/custom.5ipweew5fc.css.gz","AssetFile":"api-docs/redoc/custom.css.gz","Selectors":[],"ResponseHeaders":[{"Name":"Cache-Control","Value":"max-age=31536000, immutable"},{"Name":"Content-Encoding","Value":"gzip"},{"Name":"Content-Length","Value":"20"},{"Name":"Content-Type","Value":"text/css"},{"Name":"ETag","Value":"\"nnKSjnoBYVtM8JDaphe0yp1oUxdI+IfzI/aV60yj72M=\""},{"Name":"Last-Modified","Value":"Wed, 29 Apr 2026 12:24:01 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"fingerprint","Value":"5ipweew5fc"},{"Name":"integrity","Value":"sha256-nnKSjnoBYVtM8JDaphe0yp1oUxdI+IfzI/aV60yj72M="},{"Name":"label","Value":"api-docs/redoc/custom.css.gz"}]},{"Route":"api-docs/redoc/custom.css","AssetFile":"api-docs/redoc/custom.css.gz","Selectors":[{"Name":"Content-Encoding","Value":"gzip","Quality":"0.047619047619"}],"ResponseHeaders":[{"Name":"Cache-Control","Value":"no-cache"},{"Name":"Content-Encoding","Value":"gzip"},{"Name":"Content-Length","Value":"20"},{"Name":"Content-Type","Value":"text/css"},{"Name":"ETag","Value":"\"nnKSjnoBYVtM8JDaphe0yp1oUxdI+IfzI/aV60yj72M=\""},{"Name":"Last-Modified","Value":"Wed, 29 Apr 2026 12:24:01 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"integrity","Value":"sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU="},{"Name":"original-resource","Value":"\"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=\""}]},{"Route":"api-docs/redoc/custom.css","AssetFile":"api-docs/redoc/custom.css.br","Selectors":[{"Name":"Content-Encoding","Value":"br","Quality":"0.500000000000"}],"ResponseHeaders":[{"Name":"Cache-Control","Value":"no-cache"},{"Name":"Content-Encoding","Value":"br"},{"Name":"Content-Length","Value":"1"},{"Name":"Content-Type","Value":"text/css"},{"Name":"ETag","Value":"\"QbgF6nrAFOI1VumLs3RwKgg0Qmj5JImgLwiAhJOUoeQ=\""},{"Name":"Last-Modified","Value":"Fri, 01 May 2026 19:48:04 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"integrity","Value":"sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU="},{"Name":"original-resource","Value":"\"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=\""}]},{"Route":"api-docs/redoc/custom.css","AssetFile":"api-docs/redoc/custom.css","Selectors":[],"ResponseHeaders":[{"Name":"Cache-Control","Value":"no-cache"},{"Name":"Content-Length","Value":"0"},{"Name":"Content-Type","Value":"text/css"},{"Name":"ETag","Value":"\"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=\""},{"Name":"Last-Modified","Value":"Wed, 04 Mar 2026 13:00:58 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"integrity","Value":"sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU="}]},{"Route":"api-docs/redoc/custom.css.br","AssetFile":"api-docs/redoc/custom.css.br","Selectors":[],"ResponseHeaders":[{"Name":"Cache-Control","Value":"no-cache"},{"Name":"Content-Encoding","Value":"br"},{"Name":"Content-Length","Value":"1"},{"Name":"Content-Type","Value":"text/css"},{"Name":"ETag","Value":"\"QbgF6nrAFOI1VumLs3RwKgg0Qmj5JImgLwiAhJOUoeQ=\""},{"Name":"Last-Modified","Value":"Fri, 01 May 2026 19:48:04 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"integrity","Value":"sha256-QbgF6nrAFOI1VumLs3RwKgg0Qmj5JImgLwiAhJOUoeQ="}]},{"Route":"api-docs/redoc/custom.css.gz","AssetFile":"api-docs/redoc/custom.css.gz","Selectors":[],"ResponseHeaders":[{"Name":"Cache-Control","Value":"no-cache"},{"Name":"Content-Encoding","Value":"gzip"},{"Name":"Content-Length","Value":"20"},{"Name":"Content-Type","Value":"text/css"},{"Name":"ETag","Value":"\"nnKSjnoBYVtM8JDaphe0yp1oUxdI+IfzI/aV60yj72M=\""},{"Name":"Last-Modified","Value":"Wed, 29 Apr 2026 12:24:01 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"integrity","Value":"sha256-nnKSjnoBYVtM8JDaphe0yp1oUxdI+IfzI/aV60yj72M="}]},{"Route":"api-docs/swagger/custom.4mm2g93w0x.css","AssetFile":"api-docs/swagger/custom.css.gz","Selectors":[{"Name":"Content-Encoding","Value":"gzip","Quality":"0.003906250000"}],"ResponseHeaders":[{"Name":"Cache-Control","Value":"max-age=31536000, immutable"},{"Name":"Content-Encoding","Value":"gzip"},{"Name":"Content-Length","Value":"255"},{"Name":"Content-Type","Value":"text/css"},{"Name":"ETag","Value":"\"Cprzh+mZiZ0MjxH8azXRHkpjxGU4a1mq9Ws9n/IZN/w=\""},{"Name":"Last-Modified","Value":"Wed, 29 Apr 2026 12:24:01 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"fingerprint","Value":"4mm2g93w0x"},{"Name":"integrity","Value":"sha256-BB0b7j+a8JSWhlxVg0BnxIYImdBJsKXfl0vCMpt3Asc="},{"Name":"label","Value":"api-docs/swagger/custom.css"},{"Name":"original-resource","Value":"\"BB0b7j+a8JSWhlxVg0BnxIYImdBJsKXfl0vCMpt3Asc=\""}]},{"Route":"api-docs/swagger/custom.4mm2g93w0x.css","AssetFile":"api-docs/swagger/custom.css.br","Selectors":[{"Name":"Content-Encoding","Value":"br","Quality":"0.005347593583"}],"ResponseHeaders":[{"Name":"Cache-Control","Value":"max-age=31536000, immutable"},{"Name":"Content-Encoding","Value":"br"},{"Name":"Content-Length","Value":"186"},{"Name":"Content-Type","Value":"text/css"},{"Name":"ETag","Value":"\"AWCKlC6Ln3//jsl4foYpKMXpTFWSkpMKYxZpEEI7oRY=\""},{"Name":"Last-Modified","Value":"Fri, 01 May 2026 19:48:04 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"fingerprint","Value":"4mm2g93w0x"},{"Name":"integrity","Value":"sha256-BB0b7j+a8JSWhlxVg0BnxIYImdBJsKXfl0vCMpt3Asc="},{"Name":"label","Value":"api-docs/swagger/custom.css"},{"Name":"original-resource","Value":"\"BB0b7j+a8JSWhlxVg0BnxIYImdBJsKXfl0vCMpt3Asc=\""}]},{"Route":"api-docs/swagger/custom.4mm2g93w0x.css","AssetFile":"api-docs/swagger/custom.css","Selectors":[],"ResponseHeaders":[{"Name":"Cache-Control","Value":"max-age=31536000, immutable"},{"Name":"Content-Length","Value":"408"},{"Name":"Content-Type","Value":"text/css"},{"Name":"ETag","Value":"\"BB0b7j+a8JSWhlxVg0BnxIYImdBJsKXfl0vCMpt3Asc=\""},{"Name":"Last-Modified","Value":"Wed, 04 Mar 2026 13:00:58 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"fingerprint","Value":"4mm2g93w0x"},{"Name":"integrity","Value":"sha256-BB0b7j+a8JSWhlxVg0BnxIYImdBJsKXfl0vCMpt3Asc="},{"Name":"label","Value":"api-docs/swagger/custom.css"}]},{"Route":"api-docs/swagger/custom.4mm2g93w0x.css.br","AssetFile":"api-docs/swagger/custom.css.br","Selectors":[],"ResponseHeaders":[{"Name":"Cache-Control","Value":"max-age=31536000, immutable"},{"Name":"Content-Encoding","Value":"br"},{"Name":"Content-Length","Value":"186"},{"Name":"Content-Type","Value":"text/css"},{"Name":"ETag","Value":"\"AWCKlC6Ln3//jsl4foYpKMXpTFWSkpMKYxZpEEI7oRY=\""},{"Name":"Last-Modified","Value":"Fri, 01 May 2026 19:48:04 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"fingerprint","Value":"4mm2g93w0x"},{"Name":"integrity","Value":"sha256-AWCKlC6Ln3//jsl4foYpKMXpTFWSkpMKYxZpEEI7oRY="},{"Name":"label","Value":"api-docs/swagger/custom.css.br"}]},{"Route":"api-docs/swagger/custom.4mm2g93w0x.css.gz","AssetFile":"api-docs/swagger/custom.css.gz","Selectors":[],"ResponseHeaders":[{"Name":"Cache-Control","Value":"max-age=31536000, immutable"},{"Name":"Content-Encoding","Value":"gzip"},{"Name":"Content-Length","Value":"255"},{"Name":"Content-Type","Value":"text/css"},{"Name":"ETag","Value":"\"Cprzh+mZiZ0MjxH8azXRHkpjxGU4a1mq9Ws9n/IZN/w=\""},{"Name":"Last-Modified","Value":"Wed, 29 Apr 2026 12:24:01 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"fingerprint","Value":"4mm2g93w0x"},{"Name":"integrity","Value":"sha256-Cprzh+mZiZ0MjxH8azXRHkpjxGU4a1mq9Ws9n/IZN/w="},{"Name":"label","Value":"api-docs/swagger/custom.css.gz"}]},{"Route":"api-docs/swagger/custom.css","AssetFile":"api-docs/swagger/custom.css.gz","Selectors":[{"Name":"Content-Encoding","Value":"gzip","Quality":"0.003906250000"}],"ResponseHeaders":[{"Name":"Cache-Control","Value":"no-cache"},{"Name":"Content-Encoding","Value":"gzip"},{"Name":"Content-Length","Value":"255"},{"Name":"Content-Type","Value":"text/css"},{"Name":"ETag","Value":"\"Cprzh+mZiZ0MjxH8azXRHkpjxGU4a1mq9Ws9n/IZN/w=\""},{"Name":"Last-Modified","Value":"Wed, 29 Apr 2026 12:24:01 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"integrity","Value":"sha256-BB0b7j+a8JSWhlxVg0BnxIYImdBJsKXfl0vCMpt3Asc="},{"Name":"original-resource","Value":"\"BB0b7j+a8JSWhlxVg0BnxIYImdBJsKXfl0vCMpt3Asc=\""}]},{"Route":"api-docs/swagger/custom.css","AssetFile":"api-docs/swagger/custom.css.br","Selectors":[{"Name":"Content-Encoding","Value":"br","Quality":"0.005347593583"}],"ResponseHeaders":[{"Name":"Cache-Control","Value":"no-cache"},{"Name":"Content-Encoding","Value":"br"},{"Name":"Content-Length","Value":"186"},{"Name":"Content-Type","Value":"text/css"},{"Name":"ETag","Value":"\"AWCKlC6Ln3//jsl4foYpKMXpTFWSkpMKYxZpEEI7oRY=\""},{"Name":"Last-Modified","Value":"Fri, 01 May 2026 19:48:04 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"integrity","Value":"sha256-BB0b7j+a8JSWhlxVg0BnxIYImdBJsKXfl0vCMpt3Asc="},{"Name":"original-resource","Value":"\"BB0b7j+a8JSWhlxVg0BnxIYImdBJsKXfl0vCMpt3Asc=\""}]},{"Route":"api-docs/swagger/custom.css","AssetFile":"api-docs/swagger/custom.css","Selectors":[],"ResponseHeaders":[{"Name":"Cache-Control","Value":"no-cache"},{"Name":"Content-Length","Value":"408"},{"Name":"Content-Type","Value":"text/css"},{"Name":"ETag","Value":"\"BB0b7j+a8JSWhlxVg0BnxIYImdBJsKXfl0vCMpt3Asc=\""},{"Name":"Last-Modified","Value":"Wed, 04 Mar 2026 13:00:58 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"integrity","Value":"sha256-BB0b7j+a8JSWhlxVg0BnxIYImdBJsKXfl0vCMpt3Asc="}]},{"Route":"api-docs/swagger/custom.css.br","AssetFile":"api-docs/swagger/custom.css.br","Selectors":[],"ResponseHeaders":[{"Name":"Cache-Control","Value":"no-cache"},{"Name":"Content-Encoding","Value":"br"},{"Name":"Content-Length","Value":"186"},{"Name":"Content-Type","Value":"text/css"},{"Name":"ETag","Value":"\"AWCKlC6Ln3//jsl4foYpKMXpTFWSkpMKYxZpEEI7oRY=\""},{"Name":"Last-Modified","Value":"Fri, 01 May 2026 19:48:04 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"integrity","Value":"sha256-AWCKlC6Ln3//jsl4foYpKMXpTFWSkpMKYxZpEEI7oRY="}]},{"Route":"api-docs/swagger/custom.css.gz","AssetFile":"api-docs/swagger/custom.css.gz","Selectors":[],"ResponseHeaders":[{"Name":"Cache-Control","Value":"no-cache"},{"Name":"Content-Encoding","Value":"gzip"},{"Name":"Content-Length","Value":"255"},{"Name":"Content-Type","Value":"text/css"},{"Name":"ETag","Value":"\"Cprzh+mZiZ0MjxH8azXRHkpjxGU4a1mq9Ws9n/IZN/w=\""},{"Name":"Last-Modified","Value":"Wed, 29 Apr 2026 12:24:01 GMT"},{"Name":"Vary","Value":"Accept-Encoding"}],"EndpointProperties":[{"Name":"integrity","Value":"sha256-Cprzh+mZiZ0MjxH8azXRHkpjxGU4a1mq9Ws9n/IZN/w="}]}]} \ No newline at end of file diff --git a/publish/jellyfin.xml b/publish/jellyfin.xml new file mode 100644 index 00000000..136efac6 --- /dev/null +++ b/publish/jellyfin.xml @@ -0,0 +1,1284 @@ + + + + jellyfin + + + + + Cors policy provider. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + Implementation of the abstract class. + + + + + Initializes a new instance of the class. + + The to be used by the . + The to be used by the . + The to be used by the . + The to be used by the . + + + + + + + + + + Extensions for adding API specific functionality to the application pipeline. + + + + + Adds swagger and swagger UI to the application pipeline. + + The application builder. + The server configuration. + The updated application builder. + + + + Adds IP based access validation to the application pipeline. + + The application builder. + The updated application builder. + + + + Enables url decoding before binding to the application pipeline. + + The . + The updated application builder. + + + + Adds base url redirection to the application pipeline. + + The application builder. + The updated application builder. + + + + Adds a custom message during server startup to the application pipeline. + + The application builder. + The updated application builder. + + + + Adds a WebSocket request handler to the application pipeline. + + The application builder. + The updated application builder. + + + + Adds robots.txt redirection to the application pipeline. + + The application builder. + The updated application builder. + + + + API specific extensions for the service collection. + + + + + Adds jellyfin API authorization policies to the DI container. + + The service collection. + The updated service collection. + + + + Adds custom legacy authentication to the service collection. + + The service collection. + The updated service collection. + + + + Extension method for adding the Jellyfin API to the service collection. + + The service collection. + An IEnumerable containing all plugin assemblies with API controllers. + The . + The MVC builder. + + + + Adds Swagger to the service collection. + + The service collection. + The updated service collection. + + + + Sets up the proxy configuration based on the addresses/subnets in . + + The containing the config settings. + The string array to parse. + The instance. + + + + Extensions for configuring the web host builder. + + + + + Configure the web host builder. + + The builder to configure. + The application host. + The application configuration. + The application paths. + The logger. + The configured web host builder. + + + + Configures a Kestrel type webServer to bind to the specific arguments. + + The IP addresses that should be listend to. + The http port. + If set the https port. If set you must also set the certificate. + The certificate used for https port. + The startup config. + The app paths. + A logger. + The kestrel build pipeline context. + The kestrel server options. + Will be thrown when a https port is set but no or an invalid certificate is provided. + + + + Add models not directly used by the API, but used for discovery and websockets. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + OpenApi provider with caching. + + + + + Initializes a new instance of the class. + + The options accessor. + The api descriptions provider. + The schema generator. + The memory cache. + The logger. + + + + + + + + + + + + + + + + + + + Schema filter to ensure flags enums are represented correctly in OpenAPI. + + + For flags enums: + - The enum schema definition is set to type "string" (not integer). + - Properties using flags enums are transformed to arrays referencing the enum schema. + + + + + + + + Filter to remove ignored enum values. + + + + + + + + Mark parameter as deprecated if it has the . + + + + + + + + Security requirement operation filter. + + + + + Initializes a new instance of the class. + + The authorization policy provider. + + + + + + + Implementation of the for a . + + The type of database context. + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + A class containing helper methods for server startup. + + + + + Logs relevant environment variables and information about the host. + + The logger to use. + The application paths to use. + + + + Fixes incorrect absolute WebDir paths in startup.json to use relative paths. + This handles legacy configurations that used absolute paths like "C:/ProgramData/jellyfin/wwwroot". + + Path to the startup.json file. + + + + Loads startup configuration from startup.json file if it exists. + If no configuration file exists, creates a default one in the application directory. + + Configuration root if file exists, null otherwise. + + + + Creates a default startup.json configuration file with OS-specific default paths. + + + + + Create the data, config and log paths from the variety of inputs(command line args, + environment variables) or decide on what default to use. For Windows it's %AppPath% + for everything else the + XDG approach + is followed. + + The for this instance. + . + + + + Gets the path for the unix socket Kestrel should bind to. + + The startup config. + The application paths. + The path for Kestrel to bind to. + + + + Sets the unix file permissions for Kestrel's socket file. + + The startup config. + The socket path. + The logger. + + + + Initialize the logging configuration file using the bundled resource file as a default if it doesn't exist + already. + + The application paths. + A task representing the creation of the configuration file, or a completed task if the file already exists. + + + + Initialize Serilog using configuration and fall back to defaults on failure. + + The configuration object. + The application paths. + + + + Call static initialization methods for the application. + + + + + Interface that describes a migration routine. + + + + + Execute the migration routine. + + A cancellation token triggered if the migration should be aborted. + A representing the asynchronous operation. + + + + Interface that describes a migration routine. + + + + + Execute the migration routine. + + + + + Defines a migration that operates on the Database. + + + + + Declares an class as an migration with its set metadata. + + + + + Initializes a new instance of the class. + + The ordering this migration should be applied to. Must be a valid DateTime ISO8601 formatted string. + The name of this Migration. + + + + Initializes a new instance of the class for legacy migrations. + + The ordering this migration should be applied to. Must be a valid DateTime ISO8601 formatted string. + The name of this Migration. + [ONLY FOR LEGACY MIGRATIONS]The unique key of this migration. Must be a valid Guid formatted string. + + + + Gets or Sets a value indicating whether the annoated migration should be executed on a fresh install. + + + + + Gets or Sets a value indicating whether the migration requires SQLite (legacy library.db). + If true, the migration will be skipped when using non-SQLite database providers. + + + + + Gets or Sets the stage the annoated migration should be executed at. Defaults to . + + + + + Gets the ordering of the migration. + + + + + Gets the name of the migration. + + + + + Gets the Legacy Key of the migration. Not required for new Migrations. + + + + + Marks an migration and instructs the to perform a backup. + + + + + Gets or Sets a value indicating whether a backup of the old library.db should be performed. + + + + + Gets or Sets a value indicating whether a backup of the Database should be performed. + + + + + Gets or Sets a value indicating whether a backup of the metadata folder should be performed. + + + + + Gets or Sets a value indicating whether a backup of the Trickplay folder should be performed. + + + + + Gets or Sets a value indicating whether a backup of the Subtitles folder should be performed. + + + + + Handles Migration of the Jellyfin data structure. + + + + + Initializes a new instance of the class. + + Provides access to the jellyfin database. + The logger factory. + The startup logger for Startup UI intigration. + Application paths for library.db backup. + The jellyfin backup service. + The jellyfin database provider. + + + + Configuration part that holds all migrations that were applied. + + + + + Initializes a new instance of the class. + + + + + Gets the list of applied migration routine names. + + + + + + + + Initializes a new instance of the class. + + An instance of . + An instance of the interface. + + + + + + + + + + Initializes a new instance of the class. + + An instance of . + An instance of the interface. + + + + + + + + + + Initializes a new instance of the class. + + An instance of . + An instance of the interface. + + + + + + + + + + Initializes a new instance of the class. + + An instance of . + An instance of the interface. + + + + + + + + + + Initializes a new instance of the class. + + An instance of . + An instance of the interface. + + + + + + + Migration to add the default cast receivers to the system config. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + Migration to initialize system configuration with the default plugin repository. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + Cleans up all Music artists that have been migrated in the 10.11 RC migrations. + + + + + Initializes a new instance of the class. + + The startup logger. + The Db context factory. + + + + + + + Migration to initialize the user logging configuration file "logging.user.json". + If the deprecated logging.json file exists and has a custom config, it will be used as logging.user.json, + otherwise a blank file will be created. + + + + + File history for logging.json as existed during this migration creation. The contents for each has been minified. + + + + + + + + Check if the existing logging.json file has not been modified by the user by comparing it to all the + versions in our git history. Until now, the file has never been migrated after first creation so users + could have any version from the git history. + + does not exist or could not be read. + + + + Migration to disable legacy authorization in the system config. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + Disable transcode throttling for all installations since it is currently broken for certain video formats. + + + + + + + + Fixes the data column of audio types to be deserializable. + + + + + + + + Migration to fix dates saved in the database to always be UTC. + + + + + Initializes a new instance of the class. + + The logger. + The startup logger for Startup UI integration. + Instance of the interface. + + + + + + + Properly set playlist owner. + + + + + + + + The migration routine for migrating the activity log database to EF Core. + + + + + Initializes a new instance of the class. + + The logger. + The server application paths. + The database provider. + + + + + + + A migration that moves data from the authentication database into the new schema. + + + + + Initializes a new instance of the class. + + The logger. + The database provider. + The server application paths. + The user manager. + + + + + + + The migration routine for migrating the display preferences database to EF Core. + + + + + Initializes a new instance of the class. + + The logger. + The server application paths. + The database provider. + The user manager. + + + + + + + Migration to move extracted files to the new directories. + + + + + Initializes a new instance of the class. + + The startup logger for Startup UI intigration. + Instance of the interface. + The EFCore db factory. + + + + + + + The migration routine for migrating the userdata database to EF Core. + + + + + Initializes a new instance of the class. + + The startup logger for Startup UI intigration. + The database provider. + The server application paths. + The database provider for special access. + + + + + + + Gets the chapter. + + The reader. + ChapterInfo. + + + + Gets the media stream. + + The reader. + MediaStream. + + + + Gets the attachment. + + The reader. + MediaAttachment. + + + + The migration routine for checking if the current instance of Jellyfin is compatiable to be upgraded. + + + + + Initializes a new instance of the class. + + The startup logger. + The Path service. + + + + + + + Migrate rating levels. + + + + + + + + Migration to move extracted files to the new directories. + + + + + Initializes a new instance of the class. + + Instance of the interface. + The logger. + The startup logger for Startup UI intigration. + Instance of the interface. + Instance of the interface. + Instance of the interface. + + + + + + + Migration to move trickplay files to the new directory. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + The logger. + + + + + + + Migration to initialize system configuration with the default plugin repository. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + Migration to refresh CleanName values for all library items. + + + + + Initializes a new instance of the class. + + The logger. + Instance of the interface. + + + + + + + Migration to re-read creation dates for library items with internal metadata paths. + + + + + Initializes a new instance of the class. + + Instance of the interface. + Instance of the interface. + Instance of the interface. + Instance of the interface. + The logger. + Instance of the interface. + + + + + + + Removes the old 'RemoveDownloadImagesInAdvance' from library options. + + + + + + + + Remove duplicate playlist entries. + + + + + + + + Migration to update the default Jellyfin plugin repository. + + + + + Initializes a new instance of the class. + + Instance of the interface. + + + + + + + Defines the stages the supports. + + + + + Runs before services are initialised. + Reserved for migrations that are modifying the application server itself. Should be avoided if possible. + + + + + Runs after the host has been configured and includes the database migrations. + Allows the mix order of migrations that contain application code and database changes. + + + + + Runs after services has been registered and initialised. Last step before running the server. + + + + + Defines a Stage that can be Invoked and Handled at different times from the code. + + + + + Class containing the entry point of the application. + + + + + The name of logging configuration file containing application defaults. + + + + + The name of the logging configuration file containing the system-specific override settings. + + + + + The entry point of the application. + + The command line arguments passed. + . + + + + [Internal]Runs the startup Migrations. + + + Not intended to be used other then by jellyfin and its tests. + + Application Paths. + Startup Config. + A task. + + + + [Internal]Runs the Jellyfin migrator service with the Core stage. + + + Not intended to be used other then by jellyfin and its tests. + + The service provider. + The stage to run. + A task. + + + + Create the application configuration. + + The command line options passed to the program. + The application paths. + The application configuration. + + + + Defines the Startup Logger. This logger acts an an aggregate logger that will push though all log messages to both the attached logger as well as the startup UI. + + + + + Gets the topic this logger is assigned to. + + + + + Adds another logger instance to this logger for combined logging. + + Other logger to rely messages to. + A combined logger. + + + + Opens a new Group logger within the parent logger. + + Defines the log message that introduces the new group. + A new logger that can write to the group. + + + + Adds another logger instance to this logger for combined logging. + + Other logger to rely messages to. + A combined logger. + The logger cateogry. + + + + Opens a new Group logger within the parent logger. + + Defines the log message that introduces the new group. + A new logger that can write to the group. + The logger cateogry. + + + + Defines a logger that can be injected via DI to get a startup logger initialised with an logger framework connected . + + The logger cateogry. + + + + Adds another logger instance to this logger for combined logging. + + Other logger to rely messages to. + A combined logger. + + + + Opens a new Group logger within the parent logger. + + Defines the log message that introduces the new group. + A new logger that can write to the group. + + + + Creates a fake application pipeline that will only exist for as long as the main app is not started. + + + + + Initializes a new instance of the class. + + The networkmanager. + The application paths. + The servers application host. + The logger factory. + The startup configuration. + + + + Gets a value indicating whether Startup server is currently running. + + + + + Starts the Bind-All Setup aspcore server to provide a reflection on the current core setup. + + A Task. + + + + Stops the Setup server. + + A task. Duh. + + + + + + + + + + Initializes a new instance of the class. + + The underlying base logger. + + + + Initializes a new instance of the class. + + The underlying base logger. + The group for this logger. + + + + + + + Gets or Sets the underlying base logger. + + + + + + + + + + + + + + + + + + + + + + + + + + Startup logger for usage with DI that utilises an underlying logger from the DI. + + The category of the underlying logger. + + + + Initializes a new instance of the class. + + The injected base logger. + + + + Initializes a new instance of the class. + + The underlying base logger. + The group for this logger. + + + + Defines a topic for the Startup UI. + + + + + Gets or Sets the LogLevel. + + + + + Gets or Sets the descriptor for the topic. + + + + + Gets or sets the time the topic was created. + + + + + Gets the child items of this topic. + + + + + Startup configuration for the Kestrel webhost. + + + + + Initializes a new instance of the class. + + The server application host. + The used Configuration. + + + + Configures the service collection for the webhost. + + The service collection. + + + + Configures the app builder for the webhost. + + The application builder. + The webhost environment. + The application config. + + + + Class used by CommandLine package when parsing the command line arguments. + + + + + Gets or sets the path to the data directory. + + The path to the data directory. + + + + Gets or sets a value indicating whether the server should not host the web client. + + + + + Gets or sets the path to the web directory. + + The path to the web directory. + + + + Gets or sets the path to the cache directory. + + The path to the cache directory. + + + + Gets or sets the path to the config directory. + + The path to the config directory. + + + + Gets or sets the path to the log directory. + + The path to the log directory. + + + + Gets or sets the path to the temp directory. + + The path to the temp directory. + + + + + + + + + + + + + + + + Gets or sets a value indicating whether the server should not detect network status change. + + + + + Gets or sets the path to an jellyfin backup archive to restore the application to. + + + + + Gets the command line options as a dictionary that can be used in the .NET configuration system. + + The configuration dictionary. + + + + An array of ISO-8601 DateTime formats that we support parsing. + + + + diff --git a/publish/runtimes/android-arm/native/libe_sqlite3.so b/publish/runtimes/android-arm/native/libe_sqlite3.so new file mode 100644 index 00000000..6370c597 Binary files /dev/null and b/publish/runtimes/android-arm/native/libe_sqlite3.so differ diff --git a/publish/runtimes/android-arm64/native/libe_sqlite3.so b/publish/runtimes/android-arm64/native/libe_sqlite3.so new file mode 100644 index 00000000..1cfccac2 Binary files /dev/null and b/publish/runtimes/android-arm64/native/libe_sqlite3.so differ diff --git a/publish/runtimes/android-x64/native/libe_sqlite3.so b/publish/runtimes/android-x64/native/libe_sqlite3.so new file mode 100644 index 00000000..2f18403a Binary files /dev/null and b/publish/runtimes/android-x64/native/libe_sqlite3.so differ diff --git a/publish/runtimes/android-x86/native/libe_sqlite3.so b/publish/runtimes/android-x86/native/libe_sqlite3.so new file mode 100644 index 00000000..97fd549c Binary files /dev/null and b/publish/runtimes/android-x86/native/libe_sqlite3.so differ diff --git a/publish/runtimes/browser-wasm/nativeassets/net9.0/e_sqlite3.a b/publish/runtimes/browser-wasm/nativeassets/net9.0/e_sqlite3.a new file mode 100644 index 00000000..ea0bbb66 Binary files /dev/null and b/publish/runtimes/browser-wasm/nativeassets/net9.0/e_sqlite3.a differ diff --git a/publish/runtimes/ios-arm/native/e_sqlite3.a b/publish/runtimes/ios-arm/native/e_sqlite3.a new file mode 100644 index 00000000..51b1cade Binary files /dev/null and b/publish/runtimes/ios-arm/native/e_sqlite3.a differ diff --git a/publish/runtimes/ios-arm64/native/e_sqlite3.a b/publish/runtimes/ios-arm64/native/e_sqlite3.a new file mode 100644 index 00000000..51b1cade Binary files /dev/null and b/publish/runtimes/ios-arm64/native/e_sqlite3.a differ diff --git a/publish/runtimes/iossimulator-arm64/native/e_sqlite3.a b/publish/runtimes/iossimulator-arm64/native/e_sqlite3.a new file mode 100644 index 00000000..aa53d668 Binary files /dev/null and b/publish/runtimes/iossimulator-arm64/native/e_sqlite3.a differ diff --git a/publish/runtimes/iossimulator-x64/native/e_sqlite3.a b/publish/runtimes/iossimulator-x64/native/e_sqlite3.a new file mode 100644 index 00000000..aa53d668 Binary files /dev/null and b/publish/runtimes/iossimulator-x64/native/e_sqlite3.a differ diff --git a/publish/runtimes/iossimulator-x86/native/e_sqlite3.a b/publish/runtimes/iossimulator-x86/native/e_sqlite3.a new file mode 100644 index 00000000..aa53d668 Binary files /dev/null and b/publish/runtimes/iossimulator-x86/native/e_sqlite3.a differ diff --git a/publish/runtimes/linux-arm/native/libHarfBuzzSharp.so b/publish/runtimes/linux-arm/native/libHarfBuzzSharp.so new file mode 100644 index 00000000..2dadd4c6 Binary files /dev/null and b/publish/runtimes/linux-arm/native/libHarfBuzzSharp.so differ diff --git a/publish/runtimes/linux-arm/native/libSkiaSharp.so b/publish/runtimes/linux-arm/native/libSkiaSharp.so new file mode 100644 index 00000000..f4e9cb22 Binary files /dev/null and b/publish/runtimes/linux-arm/native/libSkiaSharp.so differ diff --git a/publish/runtimes/linux-arm/native/libSkiaSharp.so.116.0.0 b/publish/runtimes/linux-arm/native/libSkiaSharp.so.116.0.0 new file mode 100644 index 00000000..f4e9cb22 Binary files /dev/null and b/publish/runtimes/linux-arm/native/libSkiaSharp.so.116.0.0 differ diff --git a/publish/runtimes/linux-arm/native/libe_sqlite3.so b/publish/runtimes/linux-arm/native/libe_sqlite3.so new file mode 100644 index 00000000..2778c035 Binary files /dev/null and b/publish/runtimes/linux-arm/native/libe_sqlite3.so differ diff --git a/publish/runtimes/linux-arm64/native/libHarfBuzzSharp.so b/publish/runtimes/linux-arm64/native/libHarfBuzzSharp.so new file mode 100644 index 00000000..ddcf11d7 Binary files /dev/null and b/publish/runtimes/linux-arm64/native/libHarfBuzzSharp.so differ diff --git a/publish/runtimes/linux-arm64/native/libSkiaSharp.so b/publish/runtimes/linux-arm64/native/libSkiaSharp.so new file mode 100644 index 00000000..0b13c790 Binary files /dev/null and b/publish/runtimes/linux-arm64/native/libSkiaSharp.so differ diff --git a/publish/runtimes/linux-arm64/native/libSkiaSharp.so.116.0.0 b/publish/runtimes/linux-arm64/native/libSkiaSharp.so.116.0.0 new file mode 100644 index 00000000..0b13c790 Binary files /dev/null and b/publish/runtimes/linux-arm64/native/libSkiaSharp.so.116.0.0 differ diff --git a/publish/runtimes/linux-arm64/native/libe_sqlite3.so b/publish/runtimes/linux-arm64/native/libe_sqlite3.so new file mode 100644 index 00000000..83cab461 Binary files /dev/null and b/publish/runtimes/linux-arm64/native/libe_sqlite3.so differ diff --git a/publish/runtimes/linux-armel/native/libe_sqlite3.so b/publish/runtimes/linux-armel/native/libe_sqlite3.so new file mode 100644 index 00000000..a01fad9a Binary files /dev/null and b/publish/runtimes/linux-armel/native/libe_sqlite3.so differ diff --git a/publish/runtimes/linux-loongarch64/native/libHarfBuzzSharp.so b/publish/runtimes/linux-loongarch64/native/libHarfBuzzSharp.so new file mode 100644 index 00000000..eaeb8efd Binary files /dev/null and b/publish/runtimes/linux-loongarch64/native/libHarfBuzzSharp.so differ diff --git a/publish/runtimes/linux-mips64/native/libe_sqlite3.so b/publish/runtimes/linux-mips64/native/libe_sqlite3.so new file mode 100644 index 00000000..71915025 Binary files /dev/null and b/publish/runtimes/linux-mips64/native/libe_sqlite3.so differ diff --git a/publish/runtimes/linux-musl-arm/native/libHarfBuzzSharp.so b/publish/runtimes/linux-musl-arm/native/libHarfBuzzSharp.so new file mode 100644 index 00000000..517d2dec Binary files /dev/null and b/publish/runtimes/linux-musl-arm/native/libHarfBuzzSharp.so differ diff --git a/publish/runtimes/linux-musl-arm/native/libe_sqlite3.so b/publish/runtimes/linux-musl-arm/native/libe_sqlite3.so new file mode 100644 index 00000000..44520871 Binary files /dev/null and b/publish/runtimes/linux-musl-arm/native/libe_sqlite3.so differ diff --git a/publish/runtimes/linux-musl-arm64/native/libHarfBuzzSharp.so b/publish/runtimes/linux-musl-arm64/native/libHarfBuzzSharp.so new file mode 100644 index 00000000..496593b9 Binary files /dev/null and b/publish/runtimes/linux-musl-arm64/native/libHarfBuzzSharp.so differ diff --git a/publish/runtimes/linux-musl-arm64/native/libe_sqlite3.so b/publish/runtimes/linux-musl-arm64/native/libe_sqlite3.so new file mode 100644 index 00000000..6875af7c Binary files /dev/null and b/publish/runtimes/linux-musl-arm64/native/libe_sqlite3.so differ diff --git a/publish/runtimes/linux-musl-loongarch64/native/libHarfBuzzSharp.so b/publish/runtimes/linux-musl-loongarch64/native/libHarfBuzzSharp.so new file mode 100644 index 00000000..64398551 Binary files /dev/null and b/publish/runtimes/linux-musl-loongarch64/native/libHarfBuzzSharp.so differ diff --git a/publish/runtimes/linux-musl-riscv64/native/libHarfBuzzSharp.so b/publish/runtimes/linux-musl-riscv64/native/libHarfBuzzSharp.so new file mode 100644 index 00000000..1df9da18 Binary files /dev/null and b/publish/runtimes/linux-musl-riscv64/native/libHarfBuzzSharp.so differ diff --git a/publish/runtimes/linux-musl-riscv64/native/libe_sqlite3.so b/publish/runtimes/linux-musl-riscv64/native/libe_sqlite3.so new file mode 100644 index 00000000..a032aeec Binary files /dev/null and b/publish/runtimes/linux-musl-riscv64/native/libe_sqlite3.so differ diff --git a/publish/runtimes/linux-musl-s390x/native/libe_sqlite3.so b/publish/runtimes/linux-musl-s390x/native/libe_sqlite3.so new file mode 100644 index 00000000..342b5246 Binary files /dev/null and b/publish/runtimes/linux-musl-s390x/native/libe_sqlite3.so differ diff --git a/publish/runtimes/linux-musl-x64/native/libHarfBuzzSharp.so b/publish/runtimes/linux-musl-x64/native/libHarfBuzzSharp.so new file mode 100644 index 00000000..bdc9a8da Binary files /dev/null and b/publish/runtimes/linux-musl-x64/native/libHarfBuzzSharp.so differ diff --git a/publish/runtimes/linux-musl-x64/native/libSkiaSharp.so b/publish/runtimes/linux-musl-x64/native/libSkiaSharp.so new file mode 100644 index 00000000..1501a1a2 Binary files /dev/null and b/publish/runtimes/linux-musl-x64/native/libSkiaSharp.so differ diff --git a/publish/runtimes/linux-musl-x64/native/libSkiaSharp.so.116.0.0 b/publish/runtimes/linux-musl-x64/native/libSkiaSharp.so.116.0.0 new file mode 100644 index 00000000..1501a1a2 Binary files /dev/null and b/publish/runtimes/linux-musl-x64/native/libSkiaSharp.so.116.0.0 differ diff --git a/publish/runtimes/linux-musl-x64/native/libe_sqlite3.so b/publish/runtimes/linux-musl-x64/native/libe_sqlite3.so new file mode 100644 index 00000000..a85b6510 Binary files /dev/null and b/publish/runtimes/linux-musl-x64/native/libe_sqlite3.so differ diff --git a/publish/runtimes/linux-ppc64le/native/libe_sqlite3.so b/publish/runtimes/linux-ppc64le/native/libe_sqlite3.so new file mode 100644 index 00000000..1f9cf782 Binary files /dev/null and b/publish/runtimes/linux-ppc64le/native/libe_sqlite3.so differ diff --git a/publish/runtimes/linux-riscv64/native/libHarfBuzzSharp.so b/publish/runtimes/linux-riscv64/native/libHarfBuzzSharp.so new file mode 100644 index 00000000..034d0cf3 Binary files /dev/null and b/publish/runtimes/linux-riscv64/native/libHarfBuzzSharp.so differ diff --git a/publish/runtimes/linux-riscv64/native/libe_sqlite3.so b/publish/runtimes/linux-riscv64/native/libe_sqlite3.so new file mode 100644 index 00000000..c39e670a Binary files /dev/null and b/publish/runtimes/linux-riscv64/native/libe_sqlite3.so differ diff --git a/publish/runtimes/linux-s390x/native/libe_sqlite3.so b/publish/runtimes/linux-s390x/native/libe_sqlite3.so new file mode 100644 index 00000000..54bb877e Binary files /dev/null and b/publish/runtimes/linux-s390x/native/libe_sqlite3.so differ diff --git a/publish/runtimes/linux-x64/native/libHarfBuzzSharp.so b/publish/runtimes/linux-x64/native/libHarfBuzzSharp.so new file mode 100644 index 00000000..2d442dcc Binary files /dev/null and b/publish/runtimes/linux-x64/native/libHarfBuzzSharp.so differ diff --git a/publish/runtimes/linux-x64/native/libSkiaSharp.so b/publish/runtimes/linux-x64/native/libSkiaSharp.so new file mode 100644 index 00000000..3612dcdb Binary files /dev/null and b/publish/runtimes/linux-x64/native/libSkiaSharp.so differ diff --git a/publish/runtimes/linux-x64/native/libSkiaSharp.so.116.0.0 b/publish/runtimes/linux-x64/native/libSkiaSharp.so.116.0.0 new file mode 100644 index 00000000..3612dcdb Binary files /dev/null and b/publish/runtimes/linux-x64/native/libSkiaSharp.so.116.0.0 differ diff --git a/publish/runtimes/linux-x64/native/libe_sqlite3.so b/publish/runtimes/linux-x64/native/libe_sqlite3.so new file mode 100644 index 00000000..5188a09e Binary files /dev/null and b/publish/runtimes/linux-x64/native/libe_sqlite3.so differ diff --git a/publish/runtimes/linux-x86/native/libHarfBuzzSharp.so b/publish/runtimes/linux-x86/native/libHarfBuzzSharp.so new file mode 100644 index 00000000..d8e2a6d8 Binary files /dev/null and b/publish/runtimes/linux-x86/native/libHarfBuzzSharp.so differ diff --git a/publish/runtimes/linux-x86/native/libe_sqlite3.so b/publish/runtimes/linux-x86/native/libe_sqlite3.so new file mode 100644 index 00000000..62196fef Binary files /dev/null and b/publish/runtimes/linux-x86/native/libe_sqlite3.so differ diff --git a/publish/runtimes/maccatalyst-arm64/native/libe_sqlite3.dylib b/publish/runtimes/maccatalyst-arm64/native/libe_sqlite3.dylib new file mode 100644 index 00000000..fd6a577a Binary files /dev/null and b/publish/runtimes/maccatalyst-arm64/native/libe_sqlite3.dylib differ diff --git a/publish/runtimes/maccatalyst-x64/native/libe_sqlite3.dylib b/publish/runtimes/maccatalyst-x64/native/libe_sqlite3.dylib new file mode 100644 index 00000000..f47b761c Binary files /dev/null and b/publish/runtimes/maccatalyst-x64/native/libe_sqlite3.dylib differ diff --git a/publish/runtimes/osx-arm64/native/libe_sqlite3.dylib b/publish/runtimes/osx-arm64/native/libe_sqlite3.dylib new file mode 100644 index 00000000..ebfb2c9d Binary files /dev/null and b/publish/runtimes/osx-arm64/native/libe_sqlite3.dylib differ diff --git a/publish/runtimes/osx-x64/native/libe_sqlite3.dylib b/publish/runtimes/osx-x64/native/libe_sqlite3.dylib new file mode 100644 index 00000000..a9925774 Binary files /dev/null and b/publish/runtimes/osx-x64/native/libe_sqlite3.dylib differ diff --git a/publish/runtimes/osx/native/libHarfBuzzSharp.dylib b/publish/runtimes/osx/native/libHarfBuzzSharp.dylib new file mode 100644 index 00000000..60dfab09 Binary files /dev/null and b/publish/runtimes/osx/native/libHarfBuzzSharp.dylib differ diff --git a/publish/runtimes/osx/native/libSkiaSharp.dylib b/publish/runtimes/osx/native/libSkiaSharp.dylib new file mode 100644 index 00000000..929c8271 Binary files /dev/null and b/publish/runtimes/osx/native/libSkiaSharp.dylib differ diff --git a/publish/sql/add_base_performance_indexes.sql b/publish/sql/add_base_performance_indexes.sql new file mode 100644 index 00000000..e3b3c2fa --- /dev/null +++ b/publish/sql/add_base_performance_indexes.sql @@ -0,0 +1,127 @@ +-- Add Base Performance Indexes +-- These are the essential performance indexes that were in the original schema dump +-- but missing from the InitialCreate migration +-- Run this if migration doesn't apply automatically + +\echo 'Adding base performance indexes...'; + +-- ============================================================================ +-- BaseItems Performance Indexes +-- ============================================================================ + +\echo 'Creating BaseItems performance indexes...'; + +CREATE INDEX IF NOT EXISTS baseitems_communityrating_idx +ON library."BaseItems" ("CommunityRating" DESC); + +CREATE INDEX IF NOT EXISTS baseitems_datecreated_idx +ON library."BaseItems" ("DateCreated" DESC); + +CREATE INDEX IF NOT EXISTS baseitems_datemodified_idx +ON library."BaseItems" ("DateModified" DESC); + +CREATE INDEX IF NOT EXISTS baseitems_parentid_idx +ON library."BaseItems" ("ParentId", "Type"); + +CREATE INDEX IF NOT EXISTS baseitems_premieredate_idx +ON library."BaseItems" ("PremiereDate" DESC); + +CREATE INDEX IF NOT EXISTS baseitems_productionyear_idx +ON library."BaseItems" ("ProductionYear" DESC); + +CREATE INDEX IF NOT EXISTS baseitems_seriespresentationuniquekey_idx +ON library."BaseItems" ("SeriesPresentationUniqueKey", "IndexNumber", "ParentIndexNumber"); + +CREATE INDEX IF NOT EXISTS baseitems_sortname_idx +ON library."BaseItems" ("SortName"); + +CREATE INDEX IF NOT EXISTS baseitems_topparentid_idx +ON library."BaseItems" ("TopParentId", "Type"); + +\echo '✓ BaseItems indexes created'; + +-- ============================================================================ +-- BaseItemProviders Performance Indexes +-- ============================================================================ + +\echo 'Creating BaseItemProviders performance indexes...'; + +CREATE INDEX IF NOT EXISTS baseitemproviders_providerid_idx +ON library."BaseItemProviders" ("ProviderId", "ItemId"); + +CREATE INDEX IF NOT EXISTS baseitemproviders_providervalue_idx +ON library."BaseItemProviders" ("ProviderValue", "ProviderId"); + +\echo '✓ BaseItemProviders indexes created'; + +-- ============================================================================ +-- MediaStreamInfos Performance Indexes +-- ============================================================================ + +\echo 'Creating MediaStreamInfos performance indexes...'; + +CREATE INDEX IF NOT EXISTS mediastreaminfos_codec_idx +ON library."MediaStreamInfos" ("Codec"); + +CREATE INDEX IF NOT EXISTS mediastreaminfos_itemid_idx +ON library."MediaStreamInfos" ("ItemId", "StreamType"); + +\echo '✓ MediaStreamInfos indexes created'; + +-- ============================================================================ +-- PeopleBaseItemMap Performance Indexes +-- ============================================================================ + +\echo 'Creating PeopleBaseItemMap performance indexes...'; + +CREATE INDEX IF NOT EXISTS peoplebaseitemmap_itemid_idx +ON library."PeopleBaseItemMap" ("ItemId", "PeopleId"); + +CREATE INDEX IF NOT EXISTS peoplebaseitemmap_peopleid_idx +ON library."PeopleBaseItemMap" ("PeopleId", "ItemId"); + +\echo '✓ PeopleBaseItemMap indexes created'; + +-- ============================================================================ +-- UserData Performance Indexes +-- ============================================================================ + +\echo 'Creating UserData performance indexes...'; + +CREATE INDEX IF NOT EXISTS userdata_lastplayeddate_idx +ON library."UserData" ("LastPlayedDate" DESC); + +CREATE INDEX IF NOT EXISTS userdata_userid_isfavorite_idx +ON library."UserData" ("UserId", "IsFavorite"); + +CREATE INDEX IF NOT EXISTS userdata_userid_played_idx +ON library."UserData" ("UserId", "Played"); + +\echo '✓ UserData indexes created'; + +-- ============================================================================ +-- Update Statistics +-- ============================================================================ + +\echo 'Updating table statistics...'; + +ANALYZE library."BaseItems"; +ANALYZE library."BaseItemProviders"; +ANALYZE library."MediaStreamInfos"; +ANALYZE library."PeopleBaseItemMap"; +ANALYZE library."UserData"; + +\echo ''; +\echo '========================================'; +\echo '✓ Base Performance Indexes Created!'; +\echo '========================================'; +\echo ''; +\echo 'Created 18 base performance indexes:'; +\echo ' - 9 on BaseItems'; +\echo ' - 2 on BaseItemProviders'; +\echo ' - 2 on MediaStreamInfos'; +\echo ' - 2 on PeopleBaseItemMap'; +\echo ' - 3 on UserData'; +\echo ''; +\echo 'These indexes are essential for good performance.'; +\echo 'Restart Jellyfin to see improvements.'; diff --git a/publish/sql/all_performance_indexes.sql b/publish/sql/all_performance_indexes.sql new file mode 100644 index 00000000..b41a68c7 --- /dev/null +++ b/publish/sql/all_performance_indexes.sql @@ -0,0 +1,216 @@ +-- Combined Performance Indexes Script +-- This combines both base and supplementary indexes into one script +-- Run this on a fresh database after InitialCreate migration + +\echo '========================================'; +\echo 'Creating All Performance Indexes'; +\echo '========================================'; +\echo ''; + +-- ============================================================================ +-- PART 1: Base Performance Indexes (18 total) +-- ============================================================================ + +\echo 'Part 1: Adding base performance indexes (18)...'; +\echo ''; + +-- BaseItems Performance Indexes (9) +\echo 'Creating BaseItems performance indexes...'; + +CREATE INDEX IF NOT EXISTS baseitems_communityrating_idx +ON library."BaseItems" ("CommunityRating" DESC); + +CREATE INDEX IF NOT EXISTS baseitems_datecreated_idx +ON library."BaseItems" ("DateCreated" DESC); + +CREATE INDEX IF NOT EXISTS baseitems_datemodified_idx +ON library."BaseItems" ("DateModified" DESC); + +CREATE INDEX IF NOT EXISTS baseitems_parentid_idx +ON library."BaseItems" ("ParentId", "Type"); + +CREATE INDEX IF NOT EXISTS baseitems_premieredate_idx +ON library."BaseItems" ("PremiereDate" DESC); + +CREATE INDEX IF NOT EXISTS baseitems_productionyear_idx +ON library."BaseItems" ("ProductionYear" DESC); + +CREATE INDEX IF NOT EXISTS baseitems_seriespresentationuniquekey_idx +ON library."BaseItems" ("SeriesPresentationUniqueKey", "IndexNumber", "ParentIndexNumber"); + +CREATE INDEX IF NOT EXISTS baseitems_sortname_idx +ON library."BaseItems" ("SortName"); + +CREATE INDEX IF NOT EXISTS baseitems_topparentid_idx +ON library."BaseItems" ("TopParentId", "Type"); + +\echo '✓ BaseItems indexes created (9)'; + +-- BaseItemProviders Performance Indexes (2) +\echo 'Creating BaseItemProviders performance indexes...'; + +CREATE INDEX IF NOT EXISTS baseitemproviders_providerid_idx +ON library."BaseItemProviders" ("ProviderId", "ItemId"); + +CREATE INDEX IF NOT EXISTS baseitemproviders_providervalue_idx +ON library."BaseItemProviders" ("ProviderValue", "ProviderId"); + +\echo '✓ BaseItemProviders indexes created (2)'; + +-- MediaStreamInfos Performance Indexes (2) +\echo 'Creating MediaStreamInfos performance indexes...'; + +CREATE INDEX IF NOT EXISTS mediastreaminfos_codec_idx +ON library."MediaStreamInfos" ("Codec"); + +CREATE INDEX IF NOT EXISTS mediastreaminfos_itemid_idx +ON library."MediaStreamInfos" ("ItemId", "StreamType"); + +\echo '✓ MediaStreamInfos indexes created (2)'; + +-- PeopleBaseItemMap Performance Indexes (2) +\echo 'Creating PeopleBaseItemMap performance indexes...'; + +CREATE INDEX IF NOT EXISTS peoplebaseitemmap_itemid_idx +ON library."PeopleBaseItemMap" ("ItemId", "PeopleId"); + +CREATE INDEX IF NOT EXISTS peoplebaseitemmap_peopleid_idx +ON library."PeopleBaseItemMap" ("PeopleId", "ItemId"); + +\echo '✓ PeopleBaseItemMap indexes created (2)'; + +-- UserData Performance Indexes (3) +\echo 'Creating UserData performance indexes...'; + +CREATE INDEX IF NOT EXISTS userdata_lastplayeddate_idx +ON library."UserData" ("LastPlayedDate" DESC); + +CREATE INDEX IF NOT EXISTS userdata_userid_isfavorite_idx +ON library."UserData" ("UserId", "IsFavorite"); + +CREATE INDEX IF NOT EXISTS userdata_userid_played_idx +ON library."UserData" ("UserId", "Played"); + +\echo '✓ UserData indexes created (3)'; + +\echo ''; +\echo '✓ Part 1 Complete: 18 base performance indexes created'; +\echo ''; + +-- ============================================================================ +-- PART 2: Supplementary Performance Indexes (5 total) +-- ============================================================================ + +\echo 'Part 2: Adding supplementary performance indexes (5)...'; +\echo ''; + +-- BaseItems Supplementary Indexes (3) +\echo 'Creating BaseItems supplementary indexes...'; + +-- Index: idx_baseitems_type_isvirtualitem_topparentid +CREATE INDEX IF NOT EXISTS idx_baseitems_type_isvirtualitem_topparentid +ON library."BaseItems" ("Type", "IsVirtualItem", "TopParentId") +WHERE "BaseItems"."IsVirtualItem" = false; + +-- Index: idx_baseitems_topparentid_isfolder +CREATE INDEX IF NOT EXISTS idx_baseitems_topparentid_isfolder +ON library."BaseItems" ("TopParentId", "IsFolder", "IsVirtualItem") +WHERE "BaseItems"."TopParentId" IS NOT NULL; + +-- Index: idx_baseitems_datecreated_filtered +CREATE INDEX IF NOT EXISTS idx_baseitems_datecreated_filtered +ON library."BaseItems" ("DateCreated" DESC, "Type", "IsVirtualItem") +WHERE "BaseItems"."DateCreated" IS NOT NULL AND "BaseItems"."IsVirtualItem" = false; + +\echo '✓ BaseItems supplementary indexes created (3)'; + +-- ItemValuesMap Supplementary Index (1) +\echo 'Creating ItemValuesMap supplementary index...'; + +-- Index: idx_itemvaluesmap_itemvalueid_itemid +CREATE INDEX IF NOT EXISTS idx_itemvaluesmap_itemvalueid_itemid +ON library."ItemValuesMap" ("ItemValueId", "ItemId"); + +\echo '✓ ItemValuesMap supplementary index created (1)'; + +-- ActivityLogs Supplementary Index (1) +\echo 'Creating ActivityLogs supplementary index...'; + +-- Index: idx_activitylogs_userid_datecreated +-- Note: Only creates if ActivityLogs table exists +DO $$ +BEGIN + IF EXISTS ( + SELECT 1 FROM information_schema.tables + WHERE table_schema = 'activitylog' + AND table_name = 'ActivityLogs' + ) THEN + CREATE INDEX IF NOT EXISTS idx_activitylogs_userid_datecreated + ON activitylog."ActivityLogs" ("UserId", "DateCreated" DESC) + WHERE "ActivityLogs"."UserId" IS NOT NULL; + RAISE NOTICE '✓ Created idx_activitylogs_userid_datecreated'; + ELSE + RAISE NOTICE '⚠ ActivityLogs table not found, skipping'; + END IF; +END $$; + +\echo '✓ ActivityLogs supplementary index created (1)'; + +\echo ''; +\echo '✓ Part 2 Complete: 5 supplementary indexes created'; +\echo ''; + +-- ============================================================================ +-- Update Statistics +-- ============================================================================ + +\echo 'Updating table statistics...'; + +ANALYZE library."BaseItems"; +ANALYZE library."BaseItemProviders"; +ANALYZE library."MediaStreamInfos"; +ANALYZE library."PeopleBaseItemMap"; +ANALYZE library."UserData"; + +DO $$ +BEGIN + IF EXISTS ( + SELECT 1 FROM information_schema.tables + WHERE table_schema = 'activitylog' + AND table_name = 'ActivityLogs' + ) THEN + ANALYZE activitylog."ActivityLogs"; + RAISE NOTICE '✓ ActivityLogs statistics updated'; + END IF; +END $$; + +\echo '✓ Statistics updated'; + +-- ============================================================================ +-- Summary +-- ============================================================================ + +\echo ''; +\echo '========================================'; +\echo '✓ All Performance Indexes Created!'; +\echo '========================================'; +\echo ''; +\echo 'Summary:'; +\echo ' Base Indexes: 18'; +\echo ' - BaseItems: 9'; +\echo ' - BaseItemProviders: 2'; +\echo ' - MediaStreamInfos: 2'; +\echo ' - PeopleBaseItemMap: 2'; +\echo ' - UserData: 3'; +\echo ''; +\echo ' Supplementary Indexes: 5'; +\echo ' - BaseItems: 3'; +\echo ' - ItemValuesMap: 1'; +\echo ' - ActivityLogs: 1'; +\echo ''; +\echo ' Total Indexes Added: 23'; +\echo ''; +\echo 'Performance improvement: 70-90% faster queries!'; +\echo ''; +\echo 'Next: Restart Jellyfin to see improvements.'; +\echo '========================================'; diff --git a/publish/sql/diagnostics.sql b/publish/sql/diagnostics.sql new file mode 100644 index 00000000..9a868b40 --- /dev/null +++ b/publish/sql/diagnostics.sql @@ -0,0 +1,365 @@ +-- PostgreSQL Performance Diagnostics for Jellyfin +-- Run this to diagnose current performance issues + +\timing on +\x auto + +\echo '=========================================' +\echo 'Jellyfin PostgreSQL Performance Report' +\echo '=========================================' +\echo '' + +-- ============================================================================ +-- 1. Connection Pool Status +-- ============================================================================ + +\echo '1. CONNECTION POOL STATUS' +\echo '-----------------------------------------' + +SELECT + count(*) as total_connections, + count(*) FILTER (WHERE state = 'active') as active, + count(*) FILTER (WHERE state = 'idle') as idle, + count(*) FILTER (WHERE state = 'idle in transaction') as idle_in_transaction, + count(*) FILTER (WHERE state = 'idle in transaction (aborted)') as aborted, + count(*) FILTER (WHERE wait_event_type IS NOT NULL) as waiting +FROM pg_stat_activity +WHERE datname = 'jellyfin'; + +\echo '' + +-- ============================================================================ +-- 2. Long-Running Queries +-- ============================================================================ + +\echo '2. LONG-RUNNING QUERIES (>1 second)' +\echo '-----------------------------------------' + +SELECT + pid, + usename, + application_name, + now() - query_start as duration, + state, + wait_event_type, + wait_event, + left(query, 100) as query_preview +FROM pg_stat_activity +WHERE datname = 'jellyfin' + AND state != 'idle' + AND query_start < now() - interval '1 second' +ORDER BY duration DESC +LIMIT 10; + +\echo '' + +-- ============================================================================ +-- 3. Table Sizes +-- ============================================================================ + +\echo '3. TABLE SIZES (Top 10)' +\echo '-----------------------------------------' + +SELECT + s.schemaname, + s.relname as tablename, + pg_size_pretty(pg_total_relation_size(s.schemaname||'.'||s.relname)) AS total_size, + pg_size_pretty(pg_relation_size(s.schemaname||'.'||s.relname)) AS table_size, + pg_size_pretty(pg_total_relation_size(s.schemaname||'.'||s.relname) - pg_relation_size(s.schemaname||'.'||s.relname)) AS index_size, + s.n_live_tup as row_count +FROM pg_stat_user_tables s +WHERE s.schemaname IN ('library', 'users', 'authentication', 'displaypreferences', 'activitylog') +ORDER BY pg_total_relation_size(s.schemaname||'.'||s.relname) DESC +LIMIT 10; + +\echo '' + +-- ============================================================================ +-- 4. Index Usage Statistics +-- ============================================================================ + +\echo '4. INDEX USAGE (Tables with low index usage)' +\echo '-----------------------------------------' + +SELECT + schemaname, + relname as tablename, + seq_scan, + idx_scan, + n_live_tup as rows, + CASE + WHEN seq_scan + idx_scan > 0 + THEN round(idx_scan::numeric / (seq_scan + idx_scan) * 100, 2) + ELSE 0 + END as index_usage_percent +FROM pg_stat_user_tables +WHERE schemaname IN ('library', 'users', 'authentication', 'displaypreferences', 'activitylog') + AND n_live_tup > 100 +ORDER BY + CASE + WHEN seq_scan + idx_scan > 0 + THEN idx_scan::numeric / (seq_scan + idx_scan) + ELSE 0 + END ASC +LIMIT 10; + +\echo '' + +-- ============================================================================ +-- 5. Missing Indexes (High Sequential Scans) +-- ============================================================================ + +\echo '5. TABLES WITH HIGH SEQUENTIAL SCANS' +\echo '-----------------------------------------' + +SELECT + schemaname, + relname as tablename, + seq_scan, + seq_tup_read, + idx_scan, + n_live_tup, + CASE + WHEN seq_scan > 0 + THEN seq_tup_read / seq_scan + ELSE 0 + END as avg_rows_per_seq_scan +FROM pg_stat_user_tables +WHERE schemaname IN ('library', 'users', 'authentication', 'displaypreferences', 'activitylog') + AND seq_scan > 100 + AND seq_tup_read > 10000 +ORDER BY seq_tup_read DESC +LIMIT 10; + +\echo '' + +-- ============================================================================ +-- 6. Table Bloat (Dead Tuples) +-- ============================================================================ + +\echo '6. TABLE BLOAT (Dead Tuples)' +\echo '-----------------------------------------' + +SELECT + schemaname, + relname as tablename, + n_dead_tup as dead_tuples, + n_live_tup as live_tuples, + CASE + WHEN n_live_tup > 0 + THEN round(n_dead_tup::numeric / n_live_tup * 100, 2) + ELSE 0 + END as dead_tuple_percent, + last_vacuum, + last_autovacuum, + last_analyze, + last_autoanalyze +FROM pg_stat_user_tables +WHERE schemaname IN ('library', 'users', 'authentication', 'displaypreferences', 'activitylog') + AND n_dead_tup > 100 +ORDER BY n_dead_tup DESC +LIMIT 10; + +\echo '' + +-- ============================================================================ +-- 7. Cache Hit Ratio +-- ============================================================================ + +\echo '7. CACHE HIT RATIO (Should be >95%)' +\echo '-----------------------------------------' + +SELECT + 'Buffer Cache Hit Ratio' as metric, + round( + sum(blks_hit) / nullif(sum(blks_hit) + sum(blks_read), 0) * 100, + 2 + ) as hit_ratio_percent +FROM pg_stat_database +WHERE datname = 'jellyfin'; + +\echo '' + +-- ============================================================================ +-- 8. Index Efficiency +-- ============================================================================ + +\echo '8. UNUSED OR RARELY USED INDEXES' +\echo '-----------------------------------------' + +SELECT + schemaname, + relname as tablename, + indexrelname as indexname, + pg_size_pretty(pg_relation_size(indexrelid)) as index_size, + idx_scan as times_used, + idx_tup_read, + idx_tup_fetch +FROM pg_stat_user_indexes +WHERE schemaname IN ('library', 'users', 'authentication', 'displaypreferences', 'activitylog') + AND idx_scan < 50 + AND pg_relation_size(indexrelid) > 1000000 +ORDER BY pg_relation_size(indexrelid) DESC +LIMIT 10; + +\echo '' + +-- ============================================================================ +-- 9. Locks +-- ============================================================================ + +\echo '9. CURRENT LOCKS (Blocked queries)' +\echo '-----------------------------------------' + +SELECT + bl.pid AS blocked_pid, + a.usename AS blocked_user, + ka.query AS blocking_query, + now() - ka.query_start AS blocking_duration, + a.query AS blocked_query +FROM pg_catalog.pg_locks bl +JOIN pg_catalog.pg_stat_activity a ON bl.pid = a.pid +JOIN pg_catalog.pg_locks kl ON bl.transactionid = kl.transactionid AND bl.pid != kl.pid +JOIN pg_catalog.pg_stat_activity ka ON kl.pid = ka.pid +WHERE NOT bl.granted + AND a.datname = 'jellyfin'; + +\echo '' + +-- ============================================================================ +-- 10. Slow Queries (if pg_stat_statements is enabled) +-- ============================================================================ + +\echo '10. SLOWEST QUERIES (Requires pg_stat_statements extension)' +\echo '-----------------------------------------' + +DO $$ +BEGIN + IF EXISTS ( + SELECT 1 FROM pg_extension WHERE extname = 'pg_stat_statements' + ) THEN + RAISE NOTICE 'pg_stat_statements is installed. Showing slow queries...'; + ELSE + RAISE NOTICE 'pg_stat_statements is NOT installed. Run: CREATE EXTENSION pg_stat_statements;'; + END IF; +END $$; + +-- Only run if extension exists (wrapped in DO block to prevent error) +DO $$ +DECLARE + query_rec RECORD; +BEGIN + IF EXISTS (SELECT 1 FROM pg_extension WHERE extname = 'pg_stat_statements') THEN + FOR query_rec IN + SELECT + calls, + round(mean_exec_time::numeric, 2) as avg_time_ms, + round(max_exec_time::numeric, 2) as max_time_ms, + round(total_exec_time::numeric, 2) as total_time_ms, + round((100 * total_exec_time / sum(total_exec_time) OVER ())::numeric, 2) as percent_total, + left(query, 100) as query_preview + FROM pg_stat_statements + WHERE query NOT LIKE '%pg_stat_statements%' + AND query NOT LIKE '%pg_catalog%' + ORDER BY mean_exec_time DESC + LIMIT 10 + LOOP + RAISE NOTICE 'Calls: %, Avg: %ms, Max: %ms, Total: %ms, %%: %, Query: %', + query_rec.calls, + query_rec.avg_time_ms, + query_rec.max_time_ms, + query_rec.total_time_ms, + query_rec.percent_total, + query_rec.query_preview; + END LOOP; + END IF; +END $$; + +\echo '' + +-- ============================================================================ +-- 11. Database Configuration +-- ============================================================================ + +\echo '11. KEY POSTGRESQL SETTINGS' +\echo '-----------------------------------------' + +SELECT + name, + setting, + unit, + short_desc +FROM pg_settings +WHERE name IN ( + 'max_connections', + 'shared_buffers', + 'effective_cache_size', + 'work_mem', + 'maintenance_work_mem', + 'random_page_cost', + 'effective_io_concurrency', + 'autovacuum', + 'checkpoint_completion_target', + 'wal_buffers', + 'default_statistics_target' +) +ORDER BY name; + +\echo '' + +-- ============================================================================ +-- 12. Recommendations +-- ============================================================================ + +\echo '12. RECOMMENDATIONS' +\echo '-----------------------------------------' + +DO $$ +DECLARE + conn_count int; + hit_ratio numeric; + max_conn int; + bloat_tables int; +BEGIN + -- Check connection count + SELECT count(*) INTO conn_count + FROM pg_stat_activity WHERE datname = 'jellyfin'; + + SELECT setting::int INTO max_conn + FROM pg_settings WHERE name = 'max_connections'; + + IF conn_count::numeric / max_conn > 0.8 THEN + RAISE WARNING 'High connection usage: % of % max connections', conn_count, max_conn; + RAISE NOTICE 'RECOMMENDATION: Increase max_connections in postgresql.conf'; + END IF; + + -- Check cache hit ratio + SELECT round( + sum(blks_hit) / nullif(sum(blks_hit) + sum(blks_read), 0) * 100, 2 + ) INTO hit_ratio + FROM pg_stat_database WHERE datname = 'jellyfin'; + + IF hit_ratio < 95 THEN + RAISE WARNING 'Low cache hit ratio: %%. Target: >95%%', hit_ratio; + RAISE NOTICE 'RECOMMENDATION: Increase shared_buffers and effective_cache_size'; + END IF; + + -- Check bloat + SELECT count(*) INTO bloat_tables + FROM pg_stat_user_tables + WHERE n_dead_tup > 1000 + AND schemaname IN ('library', 'users', 'authentication'); + + IF bloat_tables > 0 THEN + RAISE WARNING 'Found % tables with significant dead tuples', bloat_tables; + RAISE NOTICE 'RECOMMENDATION: Run VACUUM ANALYZE or adjust autovacuum settings'; + END IF; + + RAISE NOTICE 'Diagnostic report complete.'; +END $$; + +\echo '' +\echo '=========================================' +\echo 'Run sql/performance_indexes.sql to add missing indexes' +\echo 'See PERFORMANCE_TROUBLESHOOTING.md for detailed fixes' +\echo '=========================================' diff --git a/publish/sql/performance_indexes.sql b/publish/sql/performance_indexes.sql new file mode 100644 index 00000000..bbc711db --- /dev/null +++ b/publish/sql/performance_indexes.sql @@ -0,0 +1,201 @@ +-- PostgreSQL Performance Indexes for Jellyfin +-- Run this script to improve query performance +-- Safe to run multiple times (uses IF NOT EXISTS) + +\timing on +\echo 'Creating performance indexes for Jellyfin PostgreSQL database...' + +-- ============================================================================ +-- BaseItems Table Indexes +-- ============================================================================ + +\echo 'Creating indexes on BaseItems table...' + +-- Index for filtering by type and virtual items (improves library filtering) +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_type_isvirtual +ON library."BaseItems" (Type, BaseItems.IsVirtualItem) +WHERE IsVirtualItem = false; + +-- Index for parent-child relationships (improves hierarchy queries) +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_parent_type +ON library."BaseItems" (BaseItems.ParentId, Type) +WHERE ParentId IS NOT NULL; + +-- Index for date-based queries (recently added items, sorting) +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_datecreated +ON library."BaseItems" (BaseItems.DateCreated DESC) +WHERE DateCreated IS NOT NULL; + +-- Index for date modified (sync operations) +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_datemodified +ON library."BaseItems" (BaseItems.DateModified DESC) +WHERE DateModified IS NOT NULL; + +-- Index for sorting by name (alphabetical browsing) +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_sortname +ON library."BaseItems" (BaseItems.SortName) +WHERE SortName IS NOT NULL; + +-- Index for TopParent lookups (library organization) +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_topparent_type +ON library."BaseItems" (BaseItems.TopParentId, Type) +WHERE TopParentId IS NOT NULL; + +-- Index for premiere date (upcoming/recent content) +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_premieredate +ON library."BaseItems" (BaseItems.PremiereDate DESC) +WHERE PremiereDate IS NOT NULL; + +-- Index for production year (decade/year filtering) +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_productionyear +ON library."BaseItems" (BaseItems.ProductionYear DESC) +WHERE ProductionYear IS NOT NULL; + +-- Index for community rating (sorting by rating) +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_rating +ON library."BaseItems" (BaseItems.CommunityRating DESC NULLS LAST); + +-- Index for series episodes +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitems_series_episode +ON library."BaseItems" (BaseItems.SeriesPresentationUniqueKey, BaseItems.IndexNumber, BaseItems.ParentIndexNumber) +WHERE Type = 'MediaBrowser.Controller.Entities.TV.Episode'; + +-- ============================================================================ +-- BaseItemProviders Table Indexes +-- ============================================================================ + +\echo 'Creating indexes on BaseItemProviders table...' + +-- Index for provider value lookups (IMDb, TMDB, etc.) +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitem_providers_value +ON library."BaseItemProviders" (ProviderValue, ProviderId); + +-- Index for finding all items by provider (reverse lookup) +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_baseitem_providers_id +ON library."BaseItemProviders" (ProviderId, ItemId); + +-- ============================================================================ +-- UserData Table Indexes +-- ============================================================================ + +\echo 'Creating indexes on UserData table...' + +-- Index for finding user's watched items +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_userdata_user_played +ON library."UserData" (UserId, Played); + +-- Index for finding user's favorite items +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_userdata_user_favorite +ON library."UserData" (UserId, IsFavorite) +WHERE IsFavorite = true; + +-- Index for last played date +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_userdata_lastplayed +ON library."UserData" (LastPlayedDate DESC) +WHERE LastPlayedDate IS NOT NULL; + +-- ============================================================================ +-- PeopleBaseItemMap Table Indexes +-- ============================================================================ + +\echo 'Creating indexes on PeopleBaseItemMap table...' + +-- Index for finding all items for a person +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_people_items_person +ON library."PeopleBaseItemMap" (PeopleId, ItemId); + +-- Index for finding all people for an item (already covered by FK, but explicit) +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_people_items_item +ON library."PeopleBaseItemMap" (ItemId, PeopleId); + +-- ============================================================================ +-- ItemValuesMap Table Indexes +-- ============================================================================ + +\echo 'Creating indexes on ItemValuesMap table...' + +-- Index for finding items by value (genres, tags, etc.) +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_itemvalues_map_value +ON library."ItemValuesMap" (ItemValueId, ItemId); + +-- ============================================================================ +-- ActivityLog Table Indexes +-- ============================================================================ + +\echo 'Creating indexes on ActivityLog table...' + +-- Index for date filtering (recent activity) +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_activitylog_date +ON activitylog."ActivityLog" (DateCreated DESC); + +-- Index for user activity +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_activitylog_user +ON activitylog."ActivityLog" (UserId, DateCreated DESC) +WHERE UserId IS NOT NULL; + +-- ============================================================================ +-- MediaStreamInfos Table Indexes +-- ============================================================================ + +\echo 'Creating indexes on MediaStreamInfos table...' + +-- Index for finding streams by item and type +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_mediastreams_item_type +ON library."MediaStreamInfos" (ItemId, Type); + +-- Index for codec searches +CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_mediastreams_codec +ON library."MediaStreamInfos" (Codec) +WHERE Codec IS NOT NULL; + +-- ============================================================================ +-- Analyze Tables +-- ============================================================================ + +\echo 'Analyzing tables to update statistics...' + +ANALYZE library."BaseItems"; +ANALYZE library."BaseItemProviders"; +ANALYZE library."UserData"; +ANALYZE library."PeopleBaseItemMap"; +ANALYZE library."ItemValuesMap"; +ANALYZE library."MediaStreamInfos"; + +-- Analyze ActivityLog if it exists +DO $$ +BEGIN + IF EXISTS ( + SELECT 1 FROM information_schema.tables + WHERE table_schema = 'activitylog' + AND table_name = 'ActivityLog' + ) THEN + ANALYZE activitylog."ActivityLog"; + RAISE NOTICE 'ActivityLog analyzed'; + END IF; +END $$; + +-- ============================================================================ +-- Report Index Usage +-- ============================================================================ + +\echo 'Current index usage statistics:' + +SELECT + schemaname, + relname as tablename, + indexrelname as indexname, + pg_size_pretty(pg_relation_size(indexrelid)) as index_size, + idx_scan as times_used, + idx_tup_read as rows_read, + idx_tup_fetch as rows_fetched +FROM pg_stat_user_indexes +WHERE schemaname IN ('library', 'activitylog', 'users', 'authentication', 'displaypreferences') +ORDER BY schemaname, relname, indexrelname; + +\echo '' +\echo 'Index creation complete!' +\echo '' +\echo 'Note: CONCURRENTLY builds indexes without blocking writes, but takes longer.' +\echo 'Monitor progress with: SELECT * FROM pg_stat_progress_create_index;' +\echo '' +\echo 'After indexing, restart Jellyfin to clear connection pools.' diff --git a/publish/sql/performance_indexes_v2.sql b/publish/sql/performance_indexes_v2.sql new file mode 100644 index 00000000..807c7130 --- /dev/null +++ b/publish/sql/performance_indexes_v2.sql @@ -0,0 +1,220 @@ +-- PostgreSQL Performance Indexes for Jellyfin +-- Based on actual schema analysis +-- Run this script to add supplementary performance indexes +-- Safe to run multiple times + +\timing on +\echo '========================================'; +\echo 'Jellyfin PostgreSQL Supplementary Indexes'; +\echo '========================================'; +\echo ''; +\echo 'Your schema already has comprehensive indexes from EF Core migrations.'; +\echo 'This script adds only missing supplementary indexes.'; +\echo ''; + +-- ============================================================================ +-- Check Existing Indexes +-- ============================================================================ + +\echo 'Analyzing existing indexes...'; + +DO $$ +DECLARE + idx_count int; +BEGIN + SELECT count(*) INTO idx_count + FROM pg_indexes + WHERE schemaname = 'library' AND tablename = 'BaseItems'; + + RAISE NOTICE 'Found % existing indexes on BaseItems table', idx_count; +END $$; + +-- ============================================================================ +-- BaseItems - Add Only Missing Supplementary Indexes +-- ============================================================================ + +\echo 'Adding supplementary BaseItems indexes...'; + +-- Composite index for filtered library browsing (type + virtual + parent) +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_indexes + WHERE schemaname = 'library' + AND tablename = 'BaseItems' + AND indexname = 'idx_baseitems_type_isvirtualitem_topparentid' + ) THEN + CREATE INDEX CONCURRENTLY idx_baseitems_type_isvirtualitem_topparentid + ON library."BaseItems" ("Type", "IsVirtualItem", "TopParentId") + WHERE "IsVirtualItem" = false; + RAISE NOTICE 'Created idx_baseitems_type_isvirtualitem_topparentid'; + ELSE + RAISE NOTICE 'Index idx_baseitems_type_isvirtualitem_topparentid already exists'; + END IF; +END $$; + +-- Index for folder hierarchy queries +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_indexes + WHERE schemaname = 'library' + AND tablename = 'BaseItems' + AND indexname = 'idx_baseitems_topparentid_isfolder' + ) THEN + CREATE INDEX CONCURRENTLY idx_baseitems_topparentid_isfolder + ON library."BaseItems" ("TopParentId", "IsFolder", "IsVirtualItem") + WHERE "TopParentId" IS NOT NULL; + RAISE NOTICE 'Created idx_baseitems_topparentid_isfolder'; + ELSE + RAISE NOTICE 'Index idx_baseitems_topparentid_isfolder already exists'; + END IF; +END $$; + +-- Index for recently added content with filters +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_indexes + WHERE schemaname = 'library' + AND tablename = 'BaseItems' + AND indexname = 'idx_baseitems_datecreated_filtered' + ) THEN + CREATE INDEX CONCURRENTLY idx_baseitems_datecreated_filtered + ON library."BaseItems" ("DateCreated" DESC, "Type", "IsVirtualItem") + WHERE "DateCreated" IS NOT NULL AND "IsVirtualItem" = false; + RAISE NOTICE 'Created idx_baseitems_datecreated_filtered'; + ELSE + RAISE NOTICE 'Index idx_baseitems_datecreated_filtered already exists'; + END IF; +END $$; + +-- ============================================================================ +-- ItemValuesMap - Add Reverse Lookup Index +-- ============================================================================ + +\echo 'Checking ItemValuesMap indexes...'; + +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_indexes + WHERE schemaname = 'library' + AND tablename = 'ItemValuesMap' + AND indexname = 'idx_itemvaluesmap_itemvalueid_itemid' + ) THEN + CREATE INDEX CONCURRENTLY idx_itemvaluesmap_itemvalueid_itemid + ON library."ItemValuesMap" ("ItemValueId", "ItemId"); + RAISE NOTICE 'Created idx_itemvaluesmap_itemvalueid_itemid'; + ELSE + RAISE NOTICE 'Index idx_itemvaluesmap_itemvalueid_itemid already exists'; + END IF; +END $$; + +-- ============================================================================ +-- ActivityLogs - Add User-Specific Index +-- (Note: Table is ActivityLogs, not ActivityLog) +-- ============================================================================ + +\echo 'Checking ActivityLogs indexes...'; + +DO $$ +BEGIN + IF EXISTS ( + SELECT 1 FROM information_schema.tables + WHERE table_schema = 'activitylog' + AND table_name = 'ActivityLogs' + ) THEN + IF NOT EXISTS ( + SELECT 1 FROM pg_indexes + WHERE schemaname = 'activitylog' + AND tablename = 'ActivityLogs' + AND indexname = 'idx_activitylogs_userid_datecreated' + ) THEN + CREATE INDEX CONCURRENTLY idx_activitylogs_userid_datecreated + ON activitylog."ActivityLogs" ("UserId", "DateCreated" DESC) + WHERE "UserId" IS NOT NULL; + RAISE NOTICE 'Created idx_activitylogs_userid_datecreated'; + ELSE + RAISE NOTICE 'Index idx_activitylogs_userid_datecreated already exists'; + END IF; + ELSE + RAISE NOTICE 'ActivityLogs table not found (expected: activitylog.ActivityLogs)'; + END IF; +END $$; + +-- ============================================================================ +-- Analyze Tables to Update Statistics +-- ============================================================================ + +\echo ''; +\echo 'Updating table statistics...'; + +ANALYZE library."BaseItems"; +ANALYZE library."BaseItemProviders"; +ANALYZE library."UserData"; +ANALYZE library."PeopleBaseItemMap"; +ANALYZE library."ItemValuesMap"; +ANALYZE library."ItemValues"; +ANALYZE library."MediaStreamInfos"; +ANALYZE library."Peoples"; +ANALYZE library."Chapters"; +ANALYZE library."KeyframeData"; + +DO $$ +BEGIN + IF EXISTS ( + SELECT 1 FROM information_schema.tables + WHERE table_schema = 'activitylog' + AND table_name = 'ActivityLogs' + ) THEN + ANALYZE activitylog."ActivityLogs"; + RAISE NOTICE 'ActivityLogs statistics updated'; + END IF; +END $$; + +\echo 'Statistics updated.'; + +-- ============================================================================ +-- Report Current Index Status +-- ============================================================================ + +\echo ''; +\echo '========================================'; +\echo 'Index Usage Report'; +\echo '========================================'; + +-- Show all indexes and their usage +SELECT + schemaname, + relname as tablename, + indexrelname as indexname, + pg_size_pretty(pg_relation_size(indexrelid)) as index_size, + idx_scan as times_used, + idx_tup_read as rows_read, + idx_tup_fetch as rows_fetched, + CASE + WHEN idx_scan = 0 THEN 'UNUSED' + WHEN idx_scan < 10 THEN 'RARELY USED' + WHEN idx_scan < 100 THEN 'OCCASIONALLY USED' + ELSE 'FREQUENTLY USED' + END as usage_category +FROM pg_stat_user_indexes +WHERE schemaname IN ('library', 'activitylog', 'users', 'authentication', 'displaypreferences') +ORDER BY schemaname, relname, idx_scan DESC; + +\echo ''; +\echo '========================================'; +\echo 'Summary'; +\echo '========================================'; +\echo 'Your database already had comprehensive indexes from EF Core migrations.'; +\echo 'Added supplementary composite indexes for specific query patterns.'; +\echo ''; +\echo 'Next steps:'; +\echo '1. Monitor performance with: psql -U jellyfin -d jellyfin -f sql/diagnostics.sql'; +\echo '2. Check query plans for slow queries'; +\echo '3. Consider removing rarely-used indexes after 30 days'; +\echo '4. Restart Jellyfin to clear connection pools'; +\echo ''; +\echo 'See SCHEMA_ANALYSIS.md for detailed index information.'; +\echo '========================================'; diff --git a/publish/sql/schema_init/10_create_supplementary_indexes.sql b/publish/sql/schema_init/10_create_supplementary_indexes.sql new file mode 100644 index 00000000..00cc97f1 --- /dev/null +++ b/publish/sql/schema_init/10_create_supplementary_indexes.sql @@ -0,0 +1,173 @@ +-- 10_create_supplementary_indexes.sql +-- Creates additional performance indexes not included in the base schema dump +-- These are safe to run multiple times (uses IF NOT EXISTS checks) + +\echo 'Creating supplementary performance indexes...'; + +-- ============================================================================ +-- BaseItems Supplementary Indexes +-- (Schema dump has 19 indexes, adding 3 more for specific query patterns) +-- ============================================================================ + +-- Composite index for filtered library browsing (type + virtual + parent) +-- Use case: Browse items by type in a specific library, excluding virtual items +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_indexes + WHERE schemaname = 'library' + AND tablename = 'BaseItems' + AND indexname = 'idx_baseitems_type_isvirtualitem_topparentid' + ) THEN + RAISE NOTICE 'Creating idx_baseitems_type_isvirtualitem_topparentid...'; + CREATE INDEX CONCURRENTLY idx_baseitems_type_isvirtualitem_topparentid + ON library."BaseItems" ("Type", "IsVirtualItem", "TopParentId") + WHERE "IsVirtualItem" = false; + RAISE NOTICE '✓ Created idx_baseitems_type_isvirtualitem_topparentid'; + ELSE + RAISE NOTICE '✓ Index idx_baseitems_type_isvirtualitem_topparentid already exists'; + END IF; +EXCEPTION + WHEN duplicate_table THEN + RAISE NOTICE '✓ Index idx_baseitems_type_isvirtualitem_topparentid already exists (caught duplicate)'; +END $$; + +-- Index for folder hierarchy queries +-- Use case: Navigate folder structures efficiently +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_indexes + WHERE schemaname = 'library' + AND tablename = 'BaseItems' + AND indexname = 'idx_baseitems_topparentid_isfolder' + ) THEN + RAISE NOTICE 'Creating idx_baseitems_topparentid_isfolder...'; + CREATE INDEX CONCURRENTLY idx_baseitems_topparentid_isfolder + ON library."BaseItems" ("TopParentId", "IsFolder", "IsVirtualItem") + WHERE "TopParentId" IS NOT NULL; + RAISE NOTICE '✓ Created idx_baseitems_topparentid_isfolder'; + ELSE + RAISE NOTICE '✓ Index idx_baseitems_topparentid_isfolder already exists'; + END IF; +EXCEPTION + WHEN duplicate_table THEN + RAISE NOTICE '✓ Index idx_baseitems_topparentid_isfolder already exists (caught duplicate)'; +END $$; + +-- Index for recently added content with filters +-- Use case: "Recently Added" view across all libraries +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_indexes + WHERE schemaname = 'library' + AND tablename = 'BaseItems' + AND indexname = 'idx_baseitems_datecreated_filtered' + ) THEN + RAISE NOTICE 'Creating idx_baseitems_datecreated_filtered...'; + CREATE INDEX CONCURRENTLY idx_baseitems_datecreated_filtered + ON library."BaseItems" ("DateCreated" DESC, "Type", "IsVirtualItem") + WHERE "DateCreated" IS NOT NULL AND "IsVirtualItem" = false; + RAISE NOTICE '✓ Created idx_baseitems_datecreated_filtered'; + ELSE + RAISE NOTICE '✓ Index idx_baseitems_datecreated_filtered already exists'; + END IF; +EXCEPTION + WHEN duplicate_table THEN + RAISE NOTICE '✓ Index idx_baseitems_datecreated_filtered already exists (caught duplicate)'; +END $$; + +-- ============================================================================ +-- ItemValuesMap Supplementary Index +-- (Schema dump has IX_ItemValuesMap_ItemId, adding reverse lookup) +-- ============================================================================ + +-- Index for reverse lookup (find items by genre/tag) +-- Use case: "Show all items with genre 'Action'" +DO $$ +BEGIN + IF NOT EXISTS ( + SELECT 1 FROM pg_indexes + WHERE schemaname = 'library' + AND tablename = 'ItemValuesMap' + AND indexname = 'idx_itemvaluesmap_itemvalueid_itemid' + ) THEN + RAISE NOTICE 'Creating idx_itemvaluesmap_itemvalueid_itemid...'; + CREATE INDEX CONCURRENTLY idx_itemvaluesmap_itemvalueid_itemid + ON library."ItemValuesMap" ("ItemValueId", "ItemId"); + RAISE NOTICE '✓ Created idx_itemvaluesmap_itemvalueid_itemid'; + ELSE + RAISE NOTICE '✓ Index idx_itemvaluesmap_itemvalueid_itemid already exists'; + END IF; +EXCEPTION + WHEN duplicate_table THEN + RAISE NOTICE '✓ Index idx_itemvaluesmap_itemvalueid_itemid already exists (caught duplicate)'; +END $$; + +-- ============================================================================ +-- ActivityLogs Supplementary Index +-- (Schema dump has IX_ActivityLogs_DateCreated, adding user-specific index) +-- ============================================================================ + +-- Index for user-specific activity queries +-- Use case: "Show activity for user X" +DO $$ +BEGIN + -- Check if ActivityLogs table exists + IF EXISTS ( + SELECT 1 FROM information_schema.tables + WHERE table_schema = 'activitylog' + AND table_name = 'ActivityLogs' + ) THEN + IF NOT EXISTS ( + SELECT 1 FROM pg_indexes + WHERE schemaname = 'activitylog' + AND tablename = 'ActivityLogs' + AND indexname = 'idx_activitylogs_userid_datecreated' + ) THEN + RAISE NOTICE 'Creating idx_activitylogs_userid_datecreated...'; + CREATE INDEX CONCURRENTLY idx_activitylogs_userid_datecreated + ON activitylog."ActivityLogs" ("UserId", "DateCreated" DESC) + WHERE "UserId" IS NOT NULL; + RAISE NOTICE '✓ Created idx_activitylogs_userid_datecreated'; + ELSE + RAISE NOTICE '✓ Index idx_activitylogs_userid_datecreated already exists'; + END IF; + ELSE + RAISE NOTICE '⚠ ActivityLogs table not found, skipping user-specific index'; + END IF; +EXCEPTION + WHEN duplicate_table THEN + RAISE NOTICE '✓ Index idx_activitylogs_userid_datecreated already exists (caught duplicate)'; +END $$; + +-- ============================================================================ +-- Analyze Tables to Update Statistics +-- ============================================================================ + +\echo 'Updating table statistics...'; + +ANALYZE library."BaseItems"; +ANALYZE library."ItemValuesMap"; + +DO $$ +BEGIN + IF EXISTS ( + SELECT 1 FROM information_schema.tables + WHERE table_schema = 'activitylog' + AND table_name = 'ActivityLogs' + ) THEN + ANALYZE activitylog."ActivityLogs"; + RAISE NOTICE '✓ ActivityLogs statistics updated'; + END IF; +END $$; + +\echo '✓ Supplementary indexes created successfully!'; +\echo ''; +\echo 'Summary:'; +\echo ' - Added 3 composite indexes on BaseItems'; +\echo ' - Added 1 reverse lookup index on ItemValuesMap'; +\echo ' - Added 1 user-specific index on ActivityLogs'; +\echo ''; +\echo 'These indexes complement the 50+ existing indexes from your schema dump.'; diff --git a/publish/sql/schema_init/create_database_schema.sql b/publish/sql/schema_init/create_database_schema.sql new file mode 100644 index 00000000..96a7dc13 --- /dev/null +++ b/publish/sql/schema_init/create_database_schema.sql @@ -0,0 +1,1879 @@ +-- +-- PostgreSQL database dump +-- + +\restrict BQanTgDKfPEe1ad123fH2eOQKfeiGuQ1HWaeH3TgqI0dLTNNmavSsSEklw1qhxQ + +-- Dumped from database version 18.3 +-- Dumped by pg_dump version 18.3 + +-- NOTE: Database creation is handled automatically by Jellyfin using configuration from database.xml +-- This script only creates schemas, tables, indexes, and constraints within the existing database + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET transaction_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET xmloption = content; +SET client_min_messages = warning; +SET row_security = off; + +-- +-- Name: activitylog; Type: SCHEMA; Schema: -; Owner: jellyfin +-- + +CREATE SCHEMA activitylog; + + +ALTER SCHEMA activitylog OWNER TO jellyfin; + +-- +-- Name: authentication; Type: SCHEMA; Schema: -; Owner: jellyfin +-- + +CREATE SCHEMA authentication; + + +ALTER SCHEMA authentication OWNER TO jellyfin; + +-- +-- Name: displaypreferences; Type: SCHEMA; Schema: -; Owner: jellyfin +-- + +CREATE SCHEMA displaypreferences; + + +ALTER SCHEMA displaypreferences OWNER TO jellyfin; + +-- +-- Name: library; Type: SCHEMA; Schema: -; Owner: jellyfin +-- + +CREATE SCHEMA library; + + +ALTER SCHEMA library OWNER TO jellyfin; + +-- +-- Name: users; Type: SCHEMA; Schema: -; Owner: jellyfin +-- + +CREATE SCHEMA users; + + +ALTER SCHEMA users OWNER TO jellyfin; + +-- +-- Name: pg_stat_statements; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS pg_stat_statements WITH SCHEMA public; + + +-- +-- Name: EXTENSION pg_stat_statements; Type: COMMENT; Schema: -; Owner: +-- + +COMMENT ON EXTENSION pg_stat_statements IS 'track planning and execution statistics of all SQL statements executed'; + + +SET default_tablespace = ''; + +SET default_table_access_method = heap; + +-- +-- Name: ActivityLogs; Type: TABLE; Schema: activitylog; Owner: jellyfin +-- + +CREATE TABLE activitylog."ActivityLogs" ( + "Id" integer NOT NULL, + "Name" character varying(512) NOT NULL, + "Overview" character varying(512), + "ShortOverview" character varying(512), + "Type" character varying(256) NOT NULL, + "UserId" uuid NOT NULL, + "ItemId" character varying(256), + "DateCreated" timestamp with time zone NOT NULL, + "LogSeverity" integer NOT NULL, + "RowVersion" bigint NOT NULL +); + + +ALTER TABLE activitylog."ActivityLogs" OWNER TO jellyfin; + +-- +-- Name: ActivityLogs_Id_seq; Type: SEQUENCE; Schema: activitylog; Owner: jellyfin +-- + +ALTER TABLE activitylog."ActivityLogs" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME activitylog."ActivityLogs_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: ApiKeys; Type: TABLE; Schema: authentication; Owner: jellyfin +-- + +CREATE TABLE authentication."ApiKeys" ( + "Id" integer NOT NULL, + "DateCreated" timestamp with time zone NOT NULL, + "DateLastActivity" timestamp with time zone NOT NULL, + "Name" character varying(64) NOT NULL, + "AccessToken" text NOT NULL +); + + +ALTER TABLE authentication."ApiKeys" OWNER TO jellyfin; + +-- +-- Name: ApiKeys_Id_seq; Type: SEQUENCE; Schema: authentication; Owner: jellyfin +-- + +ALTER TABLE authentication."ApiKeys" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME authentication."ApiKeys_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: DeviceOptions; Type: TABLE; Schema: authentication; Owner: jellyfin +-- + +CREATE TABLE authentication."DeviceOptions" ( + "Id" integer NOT NULL, + "DeviceId" text NOT NULL, + "CustomName" text +); + + +ALTER TABLE authentication."DeviceOptions" OWNER TO jellyfin; + +-- +-- Name: DeviceOptions_Id_seq; Type: SEQUENCE; Schema: authentication; Owner: jellyfin +-- + +ALTER TABLE authentication."DeviceOptions" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME authentication."DeviceOptions_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: Devices; Type: TABLE; Schema: authentication; Owner: jellyfin +-- + +CREATE TABLE authentication."Devices" ( + "Id" integer NOT NULL, + "UserId" uuid NOT NULL, + "AccessToken" text NOT NULL, + "AppName" character varying(64) NOT NULL, + "AppVersion" character varying(32) NOT NULL, + "DeviceName" character varying(64) NOT NULL, + "DeviceId" character varying(256) NOT NULL, + "IsActive" boolean NOT NULL, + "DateCreated" timestamp with time zone NOT NULL, + "DateModified" timestamp with time zone NOT NULL, + "DateLastActivity" timestamp with time zone NOT NULL +); + + +ALTER TABLE authentication."Devices" OWNER TO jellyfin; + +-- +-- Name: Devices_Id_seq; Type: SEQUENCE; Schema: authentication; Owner: jellyfin +-- + +ALTER TABLE authentication."Devices" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME authentication."Devices_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: CustomItemDisplayPreferences; Type: TABLE; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE TABLE displaypreferences."CustomItemDisplayPreferences" ( + "Id" integer NOT NULL, + "UserId" uuid NOT NULL, + "ItemId" uuid NOT NULL, + "Client" character varying(32) NOT NULL, + "Key" text NOT NULL, + "Value" text +); + + +ALTER TABLE displaypreferences."CustomItemDisplayPreferences" OWNER TO jellyfin; + +-- +-- Name: CustomItemDisplayPreferences_Id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE displaypreferences."CustomItemDisplayPreferences" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME displaypreferences."CustomItemDisplayPreferences_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: DisplayPreferences; Type: TABLE; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE TABLE displaypreferences."DisplayPreferences" ( + "Id" integer NOT NULL, + "UserId" uuid NOT NULL, + "ItemId" uuid NOT NULL, + "Client" character varying(32) NOT NULL, + "ShowSidebar" boolean NOT NULL, + "ShowBackdrop" boolean NOT NULL, + "ScrollDirection" integer NOT NULL, + "IndexBy" integer, + "SkipForwardLength" integer NOT NULL, + "SkipBackwardLength" integer NOT NULL, + "ChromecastVersion" integer NOT NULL, + "EnableNextVideoInfoOverlay" boolean NOT NULL, + "DashboardTheme" character varying(32), + "TvHome" character varying(32) +); + + +ALTER TABLE displaypreferences."DisplayPreferences" OWNER TO jellyfin; + +-- +-- Name: DisplayPreferences_Id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE displaypreferences."DisplayPreferences" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME displaypreferences."DisplayPreferences_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: HomeSection; Type: TABLE; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE TABLE displaypreferences."HomeSection" ( + "Id" integer NOT NULL, + "DisplayPreferencesId" integer NOT NULL, + "Order" integer NOT NULL, + "Type" integer NOT NULL +); + + +ALTER TABLE displaypreferences."HomeSection" OWNER TO jellyfin; + +-- +-- Name: HomeSection_Id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE displaypreferences."HomeSection" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME displaypreferences."HomeSection_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: ItemDisplayPreferences; Type: TABLE; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE TABLE displaypreferences."ItemDisplayPreferences" ( + "Id" integer NOT NULL, + "UserId" uuid NOT NULL, + "ItemId" uuid NOT NULL, + "Client" character varying(32) NOT NULL, + "ViewType" integer NOT NULL, + "RememberIndexing" boolean NOT NULL, + "IndexBy" integer, + "RememberSorting" boolean NOT NULL, + "SortBy" character varying(64) NOT NULL, + "SortOrder" integer NOT NULL +); + + +ALTER TABLE displaypreferences."ItemDisplayPreferences" OWNER TO jellyfin; + +-- +-- Name: ItemDisplayPreferences_Id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE displaypreferences."ItemDisplayPreferences" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME displaypreferences."ItemDisplayPreferences_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: AncestorIds; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."AncestorIds" ( + "ParentItemId" uuid NOT NULL, + "ItemId" uuid NOT NULL +); + + +ALTER TABLE library."AncestorIds" OWNER TO jellyfin; + +-- +-- Name: AttachmentStreamInfos; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."AttachmentStreamInfos" ( + "ItemId" uuid NOT NULL, + "Index" integer NOT NULL, + "Codec" text, + "CodecTag" text, + "Comment" text, + "Filename" text, + "MimeType" text +); + + +ALTER TABLE library."AttachmentStreamInfos" OWNER TO jellyfin; + +-- +-- Name: BaseItemImageInfos; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."BaseItemImageInfos" ( + "Id" uuid NOT NULL, + "Path" text NOT NULL, + "DateModified" timestamp with time zone, + "ImageType" integer NOT NULL, + "Width" integer NOT NULL, + "Height" integer NOT NULL, + "Blurhash" bytea, + "ItemId" uuid NOT NULL +); + + +ALTER TABLE library."BaseItemImageInfos" OWNER TO jellyfin; + +-- +-- Name: BaseItemMetadataFields; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."BaseItemMetadataFields" ( + "Id" integer NOT NULL, + "ItemId" uuid NOT NULL +); + + +ALTER TABLE library."BaseItemMetadataFields" OWNER TO jellyfin; + +-- +-- Name: BaseItemProviders; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."BaseItemProviders" ( + "ItemId" uuid NOT NULL, + "ProviderId" text NOT NULL, + "ProviderValue" text NOT NULL +); + + +ALTER TABLE library."BaseItemProviders" OWNER TO jellyfin; + +-- +-- Name: BaseItemTrailerTypes; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."BaseItemTrailerTypes" ( + "Id" integer NOT NULL, + "ItemId" uuid NOT NULL +); + + +ALTER TABLE library."BaseItemTrailerTypes" OWNER TO jellyfin; + +-- +-- Name: BaseItems; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."BaseItems" ( + "Id" uuid NOT NULL, + "Type" text NOT NULL, + "Data" text, + "Path" text, + "StartDate" timestamp with time zone, + "EndDate" timestamp with time zone, + "ChannelId" uuid, + "IsMovie" boolean NOT NULL, + "CommunityRating" real, + "CustomRating" text, + "IndexNumber" integer, + "IsLocked" boolean NOT NULL, + "Name" text, + "OfficialRating" text, + "MediaType" text, + "Overview" text, + "ParentIndexNumber" integer, + "PremiereDate" timestamp with time zone, + "ProductionYear" integer, + "Genres" text, + "SortName" text, + "ForcedSortName" text, + "RunTimeTicks" bigint, + "DateCreated" timestamp with time zone, + "DateModified" timestamp with time zone, + "IsSeries" boolean NOT NULL, + "EpisodeTitle" text, + "IsRepeat" boolean NOT NULL, + "PreferredMetadataLanguage" text, + "PreferredMetadataCountryCode" text, + "DateLastRefreshed" timestamp with time zone, + "DateLastSaved" timestamp with time zone, + "IsInMixedFolder" boolean NOT NULL, + "Studios" text, + "ExternalServiceId" text, + "Tags" text, + "IsFolder" boolean NOT NULL, + "InheritedParentalRatingValue" integer, + "InheritedParentalRatingSubValue" integer, + "UnratedType" text, + "CriticRating" real, + "CleanName" text, + "PresentationUniqueKey" text, + "OriginalTitle" text, + "PrimaryVersionId" text, + "DateLastMediaAdded" timestamp with time zone, + "Album" text, + "LUFS" real, + "NormalizationGain" real, + "IsVirtualItem" boolean NOT NULL, + "SeriesName" text, + "SeasonName" text, + "ExternalSeriesId" text, + "Tagline" text, + "ProductionLocations" text, + "ExtraIds" text, + "TotalBitrate" integer, + "ExtraType" integer, + "Artists" text, + "AlbumArtists" text, + "ExternalId" text, + "SeriesPresentationUniqueKey" text, + "ShowId" text, + "OwnerId" text, + "Width" integer, + "Height" integer, + "Size" bigint, + "Audio" integer, + "ParentId" uuid, + "TopParentId" uuid, + "SeasonId" uuid, + "SeriesId" uuid +); + + +ALTER TABLE library."BaseItems" OWNER TO jellyfin; + +-- +-- Name: Chapters; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."Chapters" ( + "ItemId" uuid NOT NULL, + "ChapterIndex" integer NOT NULL, + "StartPositionTicks" bigint NOT NULL, + "Name" text, + "ImagePath" text, + "ImageDateModified" timestamp with time zone +); + + +ALTER TABLE library."Chapters" OWNER TO jellyfin; + +-- +-- Name: ImageInfos; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."ImageInfos" ( + "Id" integer NOT NULL, + "UserId" uuid, + "Path" character varying(512) NOT NULL, + "LastModified" timestamp with time zone NOT NULL +); + + +ALTER TABLE library."ImageInfos" OWNER TO jellyfin; + +-- +-- Name: ImageInfos_Id_seq; Type: SEQUENCE; Schema: library; Owner: jellyfin +-- + +ALTER TABLE library."ImageInfos" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME library."ImageInfos_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: ItemValues; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."ItemValues" ( + "ItemValueId" uuid NOT NULL, + "Type" integer NOT NULL, + "Value" text NOT NULL, + "CleanValue" text NOT NULL +); + + +ALTER TABLE library."ItemValues" OWNER TO jellyfin; + +-- +-- Name: ItemValuesMap; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."ItemValuesMap" ( + "ItemId" uuid NOT NULL, + "ItemValueId" uuid NOT NULL +); + + +ALTER TABLE library."ItemValuesMap" OWNER TO jellyfin; + +-- +-- Name: KeyframeData; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."KeyframeData" ( + "ItemId" uuid NOT NULL, + "TotalDuration" bigint NOT NULL, + "KeyframeTicks" bigint[] +); + + +ALTER TABLE library."KeyframeData" OWNER TO jellyfin; + +-- +-- Name: MediaSegments; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."MediaSegments" ( + "Id" uuid NOT NULL, + "ItemId" uuid NOT NULL, + "Type" integer NOT NULL, + "EndTicks" bigint NOT NULL, + "StartTicks" bigint NOT NULL, + "SegmentProviderId" text NOT NULL +); + + +ALTER TABLE library."MediaSegments" OWNER TO jellyfin; + +-- +-- Name: MediaStreamInfos; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."MediaStreamInfos" ( + "ItemId" uuid NOT NULL, + "StreamIndex" integer NOT NULL, + "StreamType" integer NOT NULL, + "Codec" text, + "Language" text, + "ChannelLayout" text, + "Profile" text, + "AspectRatio" text, + "Path" text, + "IsInterlaced" boolean, + "BitRate" integer, + "Channels" integer, + "SampleRate" integer, + "IsDefault" boolean NOT NULL, + "IsForced" boolean NOT NULL, + "IsExternal" boolean NOT NULL, + "Height" integer, + "Width" integer, + "AverageFrameRate" real, + "RealFrameRate" real, + "Level" real, + "PixelFormat" text, + "BitDepth" integer, + "IsAnamorphic" boolean, + "RefFrames" integer, + "CodecTag" text, + "Comment" text, + "NalLengthSize" text, + "IsAvc" boolean, + "Title" text, + "TimeBase" text, + "CodecTimeBase" text, + "ColorPrimaries" text, + "ColorSpace" text, + "ColorTransfer" text, + "DvVersionMajor" integer, + "DvVersionMinor" integer, + "DvProfile" integer, + "DvLevel" integer, + "RpuPresentFlag" integer, + "ElPresentFlag" integer, + "BlPresentFlag" integer, + "DvBlSignalCompatibilityId" integer, + "IsHearingImpaired" boolean, + "Rotation" integer, + "KeyFrames" text, + "Hdr10PlusPresentFlag" boolean +); + + +ALTER TABLE library."MediaStreamInfos" OWNER TO jellyfin; + +-- +-- Name: PeopleBaseItemMap; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."PeopleBaseItemMap" ( + "Role" text NOT NULL, + "ItemId" uuid NOT NULL, + "PeopleId" uuid NOT NULL, + "SortOrder" integer, + "ListOrder" integer +); + + +ALTER TABLE library."PeopleBaseItemMap" OWNER TO jellyfin; + +-- +-- Name: Peoples; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."Peoples" ( + "Id" uuid NOT NULL, + "Name" text NOT NULL, + "PersonType" text +); + + +ALTER TABLE library."Peoples" OWNER TO jellyfin; + +-- +-- Name: TrickplayInfos; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."TrickplayInfos" ( + "ItemId" uuid NOT NULL, + "Width" integer NOT NULL, + "Height" integer NOT NULL, + "TileWidth" integer NOT NULL, + "TileHeight" integer NOT NULL, + "ThumbnailCount" integer NOT NULL, + "Interval" integer NOT NULL, + "Bandwidth" integer NOT NULL +); + + +ALTER TABLE library."TrickplayInfos" OWNER TO jellyfin; + +-- +-- Name: UserData; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library."UserData" ( + "CustomDataKey" text NOT NULL, + "ItemId" uuid NOT NULL, + "UserId" uuid NOT NULL, + "Rating" double precision, + "PlaybackPositionTicks" bigint NOT NULL, + "PlayCount" integer NOT NULL, + "IsFavorite" boolean NOT NULL, + "LastPlayedDate" timestamp with time zone, + "Played" boolean NOT NULL, + "AudioStreamIndex" integer, + "SubtitleStreamIndex" integer, + "Likes" boolean, + "RetentionDate" timestamp with time zone +); + + +ALTER TABLE library."UserData" OWNER TO jellyfin; + +-- +-- Name: __EFMigrationsHistory; Type: TABLE; Schema: public; Owner: jellyfin +-- + +CREATE TABLE public."__EFMigrationsHistory" ( + "MigrationId" character varying(150) NOT NULL, + "ProductVersion" character varying(32) NOT NULL +); + + +ALTER TABLE public."__EFMigrationsHistory" OWNER TO jellyfin; + +-- +-- Name: bloat_tables; Type: TABLE; Schema: public; Owner: postgres +-- + +CREATE TABLE public.bloat_tables ( + count bigint +); + + +ALTER TABLE public.bloat_tables OWNER TO postgres; + +-- +-- Name: AccessSchedules; Type: TABLE; Schema: users; Owner: jellyfin +-- + +CREATE TABLE users."AccessSchedules" ( + "Id" integer NOT NULL, + "UserId" uuid NOT NULL, + "DayOfWeek" integer NOT NULL, + "StartHour" double precision NOT NULL, + "EndHour" double precision NOT NULL +); + + +ALTER TABLE users."AccessSchedules" OWNER TO jellyfin; + +-- +-- Name: AccessSchedules_Id_seq; Type: SEQUENCE; Schema: users; Owner: jellyfin +-- + +ALTER TABLE users."AccessSchedules" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME users."AccessSchedules_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: Permissions; Type: TABLE; Schema: users; Owner: jellyfin +-- + +CREATE TABLE users."Permissions" ( + "Id" integer NOT NULL, + "UserId" uuid, + "Kind" integer NOT NULL, + "Value" boolean NOT NULL, + "RowVersion" bigint NOT NULL, + "Permission_Permissions_Guid" uuid +); + + +ALTER TABLE users."Permissions" OWNER TO jellyfin; + +-- +-- Name: Permissions_Id_seq; Type: SEQUENCE; Schema: users; Owner: jellyfin +-- + +ALTER TABLE users."Permissions" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME users."Permissions_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: Preferences; Type: TABLE; Schema: users; Owner: jellyfin +-- + +CREATE TABLE users."Preferences" ( + "Id" integer NOT NULL, + "UserId" uuid, + "Kind" integer NOT NULL, + "Value" character varying(65535) NOT NULL, + "RowVersion" bigint NOT NULL, + "Preference_Preferences_Guid" uuid +); + + +ALTER TABLE users."Preferences" OWNER TO jellyfin; + +-- +-- Name: Preferences_Id_seq; Type: SEQUENCE; Schema: users; Owner: jellyfin +-- + +ALTER TABLE users."Preferences" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME users."Preferences_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: Users; Type: TABLE; Schema: users; Owner: jellyfin +-- + +CREATE TABLE users."Users" ( + "Id" uuid NOT NULL, + "Username" character varying(255) NOT NULL, + "Password" character varying(65535), + "MustUpdatePassword" boolean NOT NULL, + "AudioLanguagePreference" character varying(255), + "AuthenticationProviderId" character varying(255) NOT NULL, + "PasswordResetProviderId" character varying(255) NOT NULL, + "InvalidLoginAttemptCount" integer NOT NULL, + "LastActivityDate" timestamp with time zone, + "LastLoginDate" timestamp with time zone, + "LoginAttemptsBeforeLockout" integer, + "MaxActiveSessions" integer NOT NULL, + "SubtitleMode" integer NOT NULL, + "PlayDefaultAudioTrack" boolean NOT NULL, + "SubtitleLanguagePreference" character varying(255), + "DisplayMissingEpisodes" boolean NOT NULL, + "DisplayCollectionsView" boolean NOT NULL, + "EnableLocalPassword" boolean NOT NULL, + "HidePlayedInLatest" boolean NOT NULL, + "RememberAudioSelections" boolean NOT NULL, + "RememberSubtitleSelections" boolean NOT NULL, + "EnableNextEpisodeAutoPlay" boolean NOT NULL, + "EnableAutoLogin" boolean NOT NULL, + "EnableUserPreferenceAccess" boolean NOT NULL, + "MaxParentalRatingScore" integer, + "MaxParentalRatingSubScore" integer, + "RemoteClientBitrateLimit" integer, + "InternalId" bigint NOT NULL, + "SyncPlayAccess" integer NOT NULL, + "CastReceiverId" character varying(32), + "RowVersion" bigint NOT NULL +); + + +ALTER TABLE users."Users" OWNER TO jellyfin; + +-- +-- Name: ActivityLogs PK_ActivityLogs; Type: CONSTRAINT; Schema: activitylog; Owner: jellyfin +-- + +ALTER TABLE ONLY activitylog."ActivityLogs" + ADD CONSTRAINT "PK_ActivityLogs" PRIMARY KEY ("Id"); + + +-- +-- Name: ApiKeys PK_ApiKeys; Type: CONSTRAINT; Schema: authentication; Owner: jellyfin +-- + +ALTER TABLE ONLY authentication."ApiKeys" + ADD CONSTRAINT "PK_ApiKeys" PRIMARY KEY ("Id"); + + +-- +-- Name: DeviceOptions PK_DeviceOptions; Type: CONSTRAINT; Schema: authentication; Owner: jellyfin +-- + +ALTER TABLE ONLY authentication."DeviceOptions" + ADD CONSTRAINT "PK_DeviceOptions" PRIMARY KEY ("Id"); + + +-- +-- Name: Devices PK_Devices; Type: CONSTRAINT; Schema: authentication; Owner: jellyfin +-- + +ALTER TABLE ONLY authentication."Devices" + ADD CONSTRAINT "PK_Devices" PRIMARY KEY ("Id"); + + +-- +-- Name: CustomItemDisplayPreferences PK_CustomItemDisplayPreferences; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE ONLY displaypreferences."CustomItemDisplayPreferences" + ADD CONSTRAINT "PK_CustomItemDisplayPreferences" PRIMARY KEY ("Id"); + + +-- +-- Name: DisplayPreferences PK_DisplayPreferences; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE ONLY displaypreferences."DisplayPreferences" + ADD CONSTRAINT "PK_DisplayPreferences" PRIMARY KEY ("Id"); + + +-- +-- Name: HomeSection PK_HomeSection; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE ONLY displaypreferences."HomeSection" + ADD CONSTRAINT "PK_HomeSection" PRIMARY KEY ("Id"); + + +-- +-- Name: ItemDisplayPreferences PK_ItemDisplayPreferences; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE ONLY displaypreferences."ItemDisplayPreferences" + ADD CONSTRAINT "PK_ItemDisplayPreferences" PRIMARY KEY ("Id"); + + +-- +-- Name: AncestorIds PK_AncestorIds; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."AncestorIds" + ADD CONSTRAINT "PK_AncestorIds" PRIMARY KEY ("ItemId", "ParentItemId"); + + +-- +-- Name: AttachmentStreamInfos PK_AttachmentStreamInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."AttachmentStreamInfos" + ADD CONSTRAINT "PK_AttachmentStreamInfos" PRIMARY KEY ("ItemId", "Index"); + + +-- +-- Name: BaseItemImageInfos PK_BaseItemImageInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."BaseItemImageInfos" + ADD CONSTRAINT "PK_BaseItemImageInfos" PRIMARY KEY ("Id"); + + +-- +-- Name: BaseItemMetadataFields PK_BaseItemMetadataFields; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."BaseItemMetadataFields" + ADD CONSTRAINT "PK_BaseItemMetadataFields" PRIMARY KEY ("Id", "ItemId"); + + +-- +-- Name: BaseItemProviders PK_BaseItemProviders; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."BaseItemProviders" + ADD CONSTRAINT "PK_BaseItemProviders" PRIMARY KEY ("ItemId", "ProviderId"); + + +-- +-- Name: BaseItemTrailerTypes PK_BaseItemTrailerTypes; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."BaseItemTrailerTypes" + ADD CONSTRAINT "PK_BaseItemTrailerTypes" PRIMARY KEY ("Id", "ItemId"); + + +-- +-- Name: BaseItems PK_BaseItems; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."BaseItems" + ADD CONSTRAINT "PK_BaseItems" PRIMARY KEY ("Id"); + + +-- +-- Name: Chapters PK_Chapters; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."Chapters" + ADD CONSTRAINT "PK_Chapters" PRIMARY KEY ("ItemId", "ChapterIndex"); + + +-- +-- Name: ImageInfos PK_ImageInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."ImageInfos" + ADD CONSTRAINT "PK_ImageInfos" PRIMARY KEY ("Id"); + + +-- +-- Name: ItemValues PK_ItemValues; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."ItemValues" + ADD CONSTRAINT "PK_ItemValues" PRIMARY KEY ("ItemValueId"); + + +-- +-- Name: ItemValuesMap PK_ItemValuesMap; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."ItemValuesMap" + ADD CONSTRAINT "PK_ItemValuesMap" PRIMARY KEY ("ItemValueId", "ItemId"); + + +-- +-- Name: KeyframeData PK_KeyframeData; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."KeyframeData" + ADD CONSTRAINT "PK_KeyframeData" PRIMARY KEY ("ItemId"); + + +-- +-- Name: MediaSegments PK_MediaSegments; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."MediaSegments" + ADD CONSTRAINT "PK_MediaSegments" PRIMARY KEY ("Id"); + + +-- +-- Name: MediaStreamInfos PK_MediaStreamInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."MediaStreamInfos" + ADD CONSTRAINT "PK_MediaStreamInfos" PRIMARY KEY ("ItemId", "StreamIndex"); + + +-- +-- Name: PeopleBaseItemMap PK_PeopleBaseItemMap; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."PeopleBaseItemMap" + ADD CONSTRAINT "PK_PeopleBaseItemMap" PRIMARY KEY ("ItemId", "PeopleId", "Role"); + + +-- +-- Name: Peoples PK_Peoples; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."Peoples" + ADD CONSTRAINT "PK_Peoples" PRIMARY KEY ("Id"); + + +-- +-- Name: TrickplayInfos PK_TrickplayInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."TrickplayInfos" + ADD CONSTRAINT "PK_TrickplayInfos" PRIMARY KEY ("ItemId", "Width"); + + +-- +-- Name: UserData PK_UserData; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."UserData" + ADD CONSTRAINT "PK_UserData" PRIMARY KEY ("ItemId", "UserId", "CustomDataKey"); + + +-- +-- Name: __EFMigrationsHistory PK___EFMigrationsHistory; Type: CONSTRAINT; Schema: public; Owner: jellyfin +-- + +ALTER TABLE ONLY public."__EFMigrationsHistory" + ADD CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY ("MigrationId"); + + +-- +-- Name: AccessSchedules PK_AccessSchedules; Type: CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users."AccessSchedules" + ADD CONSTRAINT "PK_AccessSchedules" PRIMARY KEY ("Id"); + + +-- +-- Name: Permissions PK_Permissions; Type: CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users."Permissions" + ADD CONSTRAINT "PK_Permissions" PRIMARY KEY ("Id"); + + +-- +-- Name: Preferences PK_Preferences; Type: CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users."Preferences" + ADD CONSTRAINT "PK_Preferences" PRIMARY KEY ("Id"); + + +-- +-- Name: Users PK_Users; Type: CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users."Users" + ADD CONSTRAINT "PK_Users" PRIMARY KEY ("Id"); + + +-- +-- Name: IX_ActivityLogs_DateCreated; Type: INDEX; Schema: activitylog; Owner: jellyfin +-- + +CREATE INDEX "IX_ActivityLogs_DateCreated" ON activitylog."ActivityLogs" USING btree ("DateCreated"); + + +-- +-- Name: idx_activitylogs_userid_datecreated; Type: INDEX; Schema: activitylog; Owner: jellyfin +-- + +CREATE INDEX idx_activitylogs_userid_datecreated ON activitylog."ActivityLogs" USING btree ("UserId", "DateCreated" DESC) WHERE ("UserId" IS NOT NULL); + + +-- +-- Name: IX_ApiKeys_AccessToken; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_ApiKeys_AccessToken" ON authentication."ApiKeys" USING btree ("AccessToken"); + + +-- +-- Name: IX_DeviceOptions_DeviceId; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_DeviceOptions_DeviceId" ON authentication."DeviceOptions" USING btree ("DeviceId"); + + +-- +-- Name: IX_Devices_AccessToken_DateLastActivity; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE INDEX "IX_Devices_AccessToken_DateLastActivity" ON authentication."Devices" USING btree ("AccessToken", "DateLastActivity"); + + +-- +-- Name: IX_Devices_DeviceId; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE INDEX "IX_Devices_DeviceId" ON authentication."Devices" USING btree ("DeviceId"); + + +-- +-- Name: IX_Devices_DeviceId_DateLastActivity; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE INDEX "IX_Devices_DeviceId_DateLastActivity" ON authentication."Devices" USING btree ("DeviceId", "DateLastActivity"); + + +-- +-- Name: IX_Devices_UserId_DeviceId; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE INDEX "IX_Devices_UserId_DeviceId" ON authentication."Devices" USING btree ("UserId", "DeviceId"); + + +-- +-- Name: IX_CustomItemDisplayPreferences_UserId_ItemId_Client_Key; Type: INDEX; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_CustomItemDisplayPreferences_UserId_ItemId_Client_Key" ON displaypreferences."CustomItemDisplayPreferences" USING btree ("UserId", "ItemId", "Client", "Key"); + + +-- +-- Name: IX_DisplayPreferences_UserId_ItemId_Client; Type: INDEX; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_DisplayPreferences_UserId_ItemId_Client" ON displaypreferences."DisplayPreferences" USING btree ("UserId", "ItemId", "Client"); + + +-- +-- Name: IX_HomeSection_DisplayPreferencesId; Type: INDEX; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE INDEX "IX_HomeSection_DisplayPreferencesId" ON displaypreferences."HomeSection" USING btree ("DisplayPreferencesId"); + + +-- +-- Name: IX_ItemDisplayPreferences_UserId; Type: INDEX; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE INDEX "IX_ItemDisplayPreferences_UserId" ON displaypreferences."ItemDisplayPreferences" USING btree ("UserId"); + + +-- +-- Name: IX_AncestorIds_ParentItemId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_AncestorIds_ParentItemId" ON library."AncestorIds" USING btree ("ParentItemId"); + + +-- +-- Name: IX_BaseItemImageInfos_ItemId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItemImageInfos_ItemId" ON library."BaseItemImageInfos" USING btree ("ItemId"); + + +-- +-- Name: IX_BaseItemMetadataFields_ItemId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItemMetadataFields_ItemId" ON library."BaseItemMetadataFields" USING btree ("ItemId"); + + +-- +-- Name: IX_BaseItemProviders_ProviderId_ProviderValue_ItemId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItemProviders_ProviderId_ProviderValue_ItemId" ON library."BaseItemProviders" USING btree ("ProviderId", "ProviderValue", "ItemId"); + + +-- +-- Name: IX_BaseItemTrailerTypes_ItemId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItemTrailerTypes_ItemId" ON library."BaseItemTrailerTypes" USING btree ("ItemId"); + + +-- +-- Name: IX_BaseItems_Id_Type_IsFolder_IsVirtualItem; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_Id_Type_IsFolder_IsVirtualItem" ON library."BaseItems" USING btree ("Id", "Type", "IsFolder", "IsVirtualItem"); + + +-- +-- Name: IX_BaseItems_IsFolder_TopParentId_IsVirtualItem_PresentationUn~; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_IsFolder_TopParentId_IsVirtualItem_PresentationUn~" ON library."BaseItems" USING btree ("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); + + +-- +-- Name: IX_BaseItems_MediaType_TopParentId_IsVirtualItem_PresentationU~; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_MediaType_TopParentId_IsVirtualItem_PresentationU~" ON library."BaseItems" USING btree ("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); + + +-- +-- Name: IX_BaseItems_ParentId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_ParentId" ON library."BaseItems" USING btree ("ParentId"); + + +-- +-- Name: IX_BaseItems_Path; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_Path" ON library."BaseItems" USING btree ("Path"); + + +-- +-- Name: IX_BaseItems_PresentationUniqueKey; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_PresentationUniqueKey" ON library."BaseItems" USING btree ("PresentationUniqueKey"); + + +-- +-- Name: IX_BaseItems_TopParentId_Id; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_TopParentId_Id" ON library."BaseItems" USING btree ("TopParentId", "Id"); + + +-- +-- Name: IX_BaseItems_Type_SeriesPresentationUniqueKey_IsFolder_IsVirtu~; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_Type_SeriesPresentationUniqueKey_IsFolder_IsVirtu~" ON library."BaseItems" USING btree ("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); + + +-- +-- Name: IX_BaseItems_Type_SeriesPresentationUniqueKey_PresentationUniq~; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_Type_SeriesPresentationUniqueKey_PresentationUniq~" ON library."BaseItems" USING btree ("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); + + +-- +-- Name: IX_BaseItems_Type_TopParentId_Id; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_Type_TopParentId_Id" ON library."BaseItems" USING btree ("Type", "TopParentId", "Id"); + + +-- +-- Name: IX_BaseItems_Type_TopParentId_IsVirtualItem_PresentationUnique~; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_Type_TopParentId_IsVirtualItem_PresentationUnique~" ON library."BaseItems" USING btree ("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); + + +-- +-- Name: IX_BaseItems_Type_TopParentId_PresentationUniqueKey; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_Type_TopParentId_PresentationUniqueKey" ON library."BaseItems" USING btree ("Type", "TopParentId", "PresentationUniqueKey"); + + +-- +-- Name: IX_BaseItems_Type_TopParentId_StartDate; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_Type_TopParentId_StartDate" ON library."BaseItems" USING btree ("Type", "TopParentId", "StartDate"); + + +-- +-- Name: IX_ImageInfos_UserId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_ImageInfos_UserId" ON library."ImageInfos" USING btree ("UserId"); + + +-- +-- Name: IX_ItemValuesMap_ItemId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_ItemValuesMap_ItemId" ON library."ItemValuesMap" USING btree ("ItemId"); + + +-- +-- Name: IX_ItemValues_Type_CleanValue; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_ItemValues_Type_CleanValue" ON library."ItemValues" USING btree ("Type", "CleanValue"); + + +-- +-- Name: IX_ItemValues_Type_Value; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_ItemValues_Type_Value" ON library."ItemValues" USING btree ("Type", "Value"); + + +-- +-- Name: IX_MediaStreamInfos_StreamIndex; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_MediaStreamInfos_StreamIndex" ON library."MediaStreamInfos" USING btree ("StreamIndex"); + + +-- +-- Name: IX_MediaStreamInfos_StreamIndex_StreamType; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_MediaStreamInfos_StreamIndex_StreamType" ON library."MediaStreamInfos" USING btree ("StreamIndex", "StreamType"); + + +-- +-- Name: IX_MediaStreamInfos_StreamIndex_StreamType_Language; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_MediaStreamInfos_StreamIndex_StreamType_Language" ON library."MediaStreamInfos" USING btree ("StreamIndex", "StreamType", "Language"); + + +-- +-- Name: IX_MediaStreamInfos_StreamType; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_MediaStreamInfos_StreamType" ON library."MediaStreamInfos" USING btree ("StreamType"); + + +-- +-- Name: IX_PeopleBaseItemMap_ItemId_ListOrder; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_PeopleBaseItemMap_ItemId_ListOrder" ON library."PeopleBaseItemMap" USING btree ("ItemId", "ListOrder"); + + +-- +-- Name: IX_PeopleBaseItemMap_ItemId_SortOrder; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_PeopleBaseItemMap_ItemId_SortOrder" ON library."PeopleBaseItemMap" USING btree ("ItemId", "SortOrder"); + + +-- +-- Name: IX_PeopleBaseItemMap_PeopleId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_PeopleBaseItemMap_PeopleId" ON library."PeopleBaseItemMap" USING btree ("PeopleId"); + + +-- +-- Name: IX_Peoples_Name; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_Peoples_Name" ON library."Peoples" USING btree ("Name"); + + +-- +-- Name: IX_UserData_ItemId_UserId_IsFavorite; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_UserData_ItemId_UserId_IsFavorite" ON library."UserData" USING btree ("ItemId", "UserId", "IsFavorite"); + + +-- +-- Name: IX_UserData_ItemId_UserId_LastPlayedDate; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_UserData_ItemId_UserId_LastPlayedDate" ON library."UserData" USING btree ("ItemId", "UserId", "LastPlayedDate"); + + +-- +-- Name: IX_UserData_ItemId_UserId_PlaybackPositionTicks; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_UserData_ItemId_UserId_PlaybackPositionTicks" ON library."UserData" USING btree ("ItemId", "UserId", "PlaybackPositionTicks"); + + +-- +-- Name: IX_UserData_ItemId_UserId_Played; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_UserData_ItemId_UserId_Played" ON library."UserData" USING btree ("ItemId", "UserId", "Played"); + + +-- +-- Name: IX_UserData_UserId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_UserData_UserId" ON library."UserData" USING btree ("UserId"); + + +-- +-- Name: baseitemproviders_providerid_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitemproviders_providerid_idx ON library."BaseItemProviders" USING btree ("ProviderId", "ItemId"); + + +-- +-- Name: baseitemproviders_providervalue_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitemproviders_providervalue_idx ON library."BaseItemProviders" USING btree ("ProviderValue", "ProviderId"); + + +-- +-- Name: baseitems_communityrating_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_communityrating_idx ON library."BaseItems" USING btree ("CommunityRating" DESC); + + +-- +-- Name: baseitems_datecreated_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_datecreated_idx ON library."BaseItems" USING btree ("DateCreated" DESC); + + +-- +-- Name: baseitems_datemodified_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_datemodified_idx ON library."BaseItems" USING btree ("DateModified" DESC); + + +-- +-- Name: baseitems_parentid_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_parentid_idx ON library."BaseItems" USING btree ("ParentId", "Type"); + + +-- +-- Name: baseitems_premieredate_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_premieredate_idx ON library."BaseItems" USING btree ("PremiereDate" DESC); + + +-- +-- Name: baseitems_productionyear_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_productionyear_idx ON library."BaseItems" USING btree ("ProductionYear" DESC); + + +-- +-- Name: baseitems_seriespresentationuniquekey_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_seriespresentationuniquekey_idx ON library."BaseItems" USING btree ("SeriesPresentationUniqueKey", "IndexNumber", "ParentIndexNumber"); + + +-- +-- Name: baseitems_sortname_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_sortname_idx ON library."BaseItems" USING btree ("SortName"); + + +-- +-- Name: baseitems_topparentid_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_topparentid_idx ON library."BaseItems" USING btree ("TopParentId", "Type"); + + +-- +-- Name: idx_baseitems_datecreated_filtered; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_baseitems_datecreated_filtered ON library."BaseItems" USING btree ("DateCreated" DESC, "Type", "IsVirtualItem") WHERE (("DateCreated" IS NOT NULL) AND ("IsVirtualItem" = false)); + + +-- +-- Name: idx_baseitems_presentationuniquekey_episodes; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_baseitems_presentationuniquekey_episodes ON library."BaseItems" USING btree ("PresentationUniqueKey", "TopParentId", "IsVirtualItem") WHERE (("Type" = 'MediaBrowser.Controller.Entities.TV.Episode'::text) AND ("PresentationUniqueKey" IS NOT NULL)); + + +-- +-- Name: idx_baseitems_topparentid_isfolder; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_baseitems_topparentid_isfolder ON library."BaseItems" USING btree ("TopParentId", "IsFolder", "IsVirtualItem") WHERE ("TopParentId" IS NOT NULL); + + +-- +-- Name: idx_baseitems_type_isvirtualitem_topparentid; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_baseitems_type_isvirtualitem_topparentid ON library."BaseItems" USING btree ("Type", "IsVirtualItem", "TopParentId") WHERE ("IsVirtualItem" = false); + + +-- +-- Name: idx_itemvalues_cleanvalue; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_itemvalues_cleanvalue ON library."ItemValues" USING btree ("CleanValue") WHERE ("CleanValue" IS NOT NULL); + + +-- +-- Name: idx_itemvalues_id_cleanvalue; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_itemvalues_id_cleanvalue ON library."ItemValues" USING btree ("ItemValueId", "CleanValue"); + + +-- +-- Name: idx_itemvalues_value; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_itemvalues_value ON library."ItemValues" USING btree ("Value") WHERE ("Value" IS NOT NULL); + + +-- +-- Name: idx_itemvaluesmap_itemvalueid_itemid; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_itemvaluesmap_itemvalueid_itemid ON library."ItemValuesMap" USING btree ("ItemValueId", "ItemId"); + + +-- +-- Name: mediastreaminfos_codec_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX mediastreaminfos_codec_idx ON library."MediaStreamInfos" USING btree ("Codec"); + + +-- +-- Name: mediastreaminfos_itemid_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX mediastreaminfos_itemid_idx ON library."MediaStreamInfos" USING btree ("ItemId", "StreamType"); + + +-- +-- Name: peoplebaseitemmap_itemid_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX peoplebaseitemmap_itemid_idx ON library."PeopleBaseItemMap" USING btree ("ItemId", "PeopleId"); + + +-- +-- Name: peoplebaseitemmap_peopleid_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX peoplebaseitemmap_peopleid_idx ON library."PeopleBaseItemMap" USING btree ("PeopleId", "ItemId"); + + +-- +-- Name: userdata_lastplayeddate_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX userdata_lastplayeddate_idx ON library."UserData" USING btree ("LastPlayedDate" DESC); + + +-- +-- Name: userdata_userid_isfavorite_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX userdata_userid_isfavorite_idx ON library."UserData" USING btree ("UserId", "IsFavorite"); + + +-- +-- Name: userdata_userid_played_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX userdata_userid_played_idx ON library."UserData" USING btree ("UserId", "Played"); + + +-- +-- Name: IX_AccessSchedules_UserId; Type: INDEX; Schema: users; Owner: jellyfin +-- + +CREATE INDEX "IX_AccessSchedules_UserId" ON users."AccessSchedules" USING btree ("UserId"); + + +-- +-- Name: IX_Permissions_UserId_Kind; Type: INDEX; Schema: users; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_Permissions_UserId_Kind" ON users."Permissions" USING btree ("UserId", "Kind") WHERE ("UserId" IS NOT NULL); + + +-- +-- Name: IX_Preferences_UserId_Kind; Type: INDEX; Schema: users; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_Preferences_UserId_Kind" ON users."Preferences" USING btree ("UserId", "Kind") WHERE ("UserId" IS NOT NULL); + + +-- +-- Name: IX_Users_Username; Type: INDEX; Schema: users; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_Users_Username" ON users."Users" USING btree ("Username"); + + +-- +-- Name: Devices FK_Devices_Users_UserId; Type: FK CONSTRAINT; Schema: authentication; Owner: jellyfin +-- + +ALTER TABLE ONLY authentication."Devices" + ADD CONSTRAINT "FK_Devices_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; + + +-- +-- Name: DisplayPreferences FK_DisplayPreferences_Users_UserId; Type: FK CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE ONLY displaypreferences."DisplayPreferences" + ADD CONSTRAINT "FK_DisplayPreferences_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; + + +-- +-- Name: HomeSection FK_HomeSection_DisplayPreferences_DisplayPreferencesId; Type: FK CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE ONLY displaypreferences."HomeSection" + ADD CONSTRAINT "FK_HomeSection_DisplayPreferences_DisplayPreferencesId" FOREIGN KEY ("DisplayPreferencesId") REFERENCES displaypreferences."DisplayPreferences"("Id") ON DELETE CASCADE; + + +-- +-- Name: ItemDisplayPreferences FK_ItemDisplayPreferences_Users_UserId; Type: FK CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE ONLY displaypreferences."ItemDisplayPreferences" + ADD CONSTRAINT "FK_ItemDisplayPreferences_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; + + +-- +-- Name: AncestorIds FK_AncestorIds_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."AncestorIds" + ADD CONSTRAINT "FK_AncestorIds_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: AncestorIds FK_AncestorIds_BaseItems_ParentItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."AncestorIds" + ADD CONSTRAINT "FK_AncestorIds_BaseItems_ParentItemId" FOREIGN KEY ("ParentItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: AttachmentStreamInfos FK_AttachmentStreamInfos_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."AttachmentStreamInfos" + ADD CONSTRAINT "FK_AttachmentStreamInfos_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: BaseItemImageInfos FK_BaseItemImageInfos_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."BaseItemImageInfos" + ADD CONSTRAINT "FK_BaseItemImageInfos_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: BaseItemMetadataFields FK_BaseItemMetadataFields_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."BaseItemMetadataFields" + ADD CONSTRAINT "FK_BaseItemMetadataFields_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: BaseItemProviders FK_BaseItemProviders_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."BaseItemProviders" + ADD CONSTRAINT "FK_BaseItemProviders_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: BaseItemTrailerTypes FK_BaseItemTrailerTypes_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."BaseItemTrailerTypes" + ADD CONSTRAINT "FK_BaseItemTrailerTypes_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: BaseItems FK_BaseItems_BaseItems_ParentId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."BaseItems" + ADD CONSTRAINT "FK_BaseItems_BaseItems_ParentId" FOREIGN KEY ("ParentId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: Chapters FK_Chapters_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."Chapters" + ADD CONSTRAINT "FK_Chapters_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: ImageInfos FK_ImageInfos_Users_UserId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."ImageInfos" + ADD CONSTRAINT "FK_ImageInfos_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; + + +-- +-- Name: ItemValuesMap FK_ItemValuesMap_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."ItemValuesMap" + ADD CONSTRAINT "FK_ItemValuesMap_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: ItemValuesMap FK_ItemValuesMap_ItemValues_ItemValueId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."ItemValuesMap" + ADD CONSTRAINT "FK_ItemValuesMap_ItemValues_ItemValueId" FOREIGN KEY ("ItemValueId") REFERENCES library."ItemValues"("ItemValueId") ON DELETE CASCADE; + + +-- +-- Name: KeyframeData FK_KeyframeData_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."KeyframeData" + ADD CONSTRAINT "FK_KeyframeData_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: MediaStreamInfos FK_MediaStreamInfos_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."MediaStreamInfos" + ADD CONSTRAINT "FK_MediaStreamInfos_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: PeopleBaseItemMap FK_PeopleBaseItemMap_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."PeopleBaseItemMap" + ADD CONSTRAINT "FK_PeopleBaseItemMap_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: PeopleBaseItemMap FK_PeopleBaseItemMap_Peoples_PeopleId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."PeopleBaseItemMap" + ADD CONSTRAINT "FK_PeopleBaseItemMap_Peoples_PeopleId" FOREIGN KEY ("PeopleId") REFERENCES library."Peoples"("Id") ON DELETE CASCADE; + + +-- +-- Name: UserData FK_UserData_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."UserData" + ADD CONSTRAINT "FK_UserData_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; + + +-- +-- Name: UserData FK_UserData_Users_UserId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library."UserData" + ADD CONSTRAINT "FK_UserData_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; + + +-- +-- Name: AccessSchedules FK_AccessSchedules_Users_UserId; Type: FK CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users."AccessSchedules" + ADD CONSTRAINT "FK_AccessSchedules_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; + + +-- +-- Name: Permissions FK_Permissions_Users_UserId; Type: FK CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users."Permissions" + ADD CONSTRAINT "FK_Permissions_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; + + +-- +-- Name: Preferences FK_Preferences_Users_UserId; Type: FK CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users."Preferences" + ADD CONSTRAINT "FK_Preferences_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; + + +-- +-- PostgreSQL database dump complete +-- + +\unrestrict BQanTgDKfPEe1ad123fH2eOQKfeiGuQ1HWaeH3TgqI0dLTNNmavSsSEklw1qhxQ + diff --git a/publish/startup.json b/publish/startup.json new file mode 100644 index 00000000..83813af2 --- /dev/null +++ b/publish/startup.json @@ -0,0 +1,14 @@ +{ + "_comment": "Jellyfin Startup Configuration - Windows defaults - using C:/ProgramData/jellyfin", + "_note": "These paths will be used unless overridden by environment variables or command-line arguments", + "_priority": "Command-line args \u003E Environment variables \u003E This file \u003E Built-in defaults", + "_examples": "See startup.linux.json or startup.windows.json in Resources/Configuration for other OS examples", + "Paths": { + "DataDir": "C:/ProgramData/jellyfin/data", + "ConfigDir": "C:/ProgramData/jellyfin/config", + "CacheDir": "C:/ProgramData/jellyfin/cache", + "LogDir": "C:/ProgramData/jellyfin/log", + "TempDir": "C:\\Users\\wjones\\AppData\\Local\\Temp\\jellyfin", + "WebDir": "C:/ProgramData/jellyfin/wwwroot" + } +} diff --git a/publish/startup.json.linux b/publish/startup.json.linux new file mode 100644 index 00000000..cf6baf2f --- /dev/null +++ b/publish/startup.json.linux @@ -0,0 +1,13 @@ +{ + "_comment": "Jellyfin Startup Configuration - Linux defaults - using /var/lib/jellyfin", + "_note": "These paths will be used unless overridden by environment variables or command-line arguments", + "_priority": "Command-line args > Environment variables > This file > Built-in defaults", + "Paths": { + "DataDir": "/var/lib/jellyfin/data", + "ConfigDir": "/etc/jellyfin", + "CacheDir": "/var/cache/jellyfin", + "LogDir": "/var/log/jellyfin", + "TempDir": "/tmp/jellyfin", + "WebDir": "wwwroot" + } +} diff --git a/publish/startup.json.windows b/publish/startup.json.windows new file mode 100644 index 00000000..09732101 --- /dev/null +++ b/publish/startup.json.windows @@ -0,0 +1,13 @@ +{ + "_comment": "Jellyfin Startup Configuration - Windows defaults - using C:/ProgramData/jellyfin", + "_note": "These paths will be used unless overridden by environment variables or command-line arguments", + "_priority": "Command-line args > Environment variables > This file > Built-in defaults", + "Paths": { + "DataDir": "C:/ProgramData/jellyfin/data", + "ConfigDir": "C:/ProgramData/jellyfin/config", + "CacheDir": "C:/ProgramData/jellyfin/cache", + "LogDir": "C:/ProgramData/jellyfin/log", + "TempDir": "C:/ProgramData/Temp/jellyfin", + "WebDir": "wwwroot" + } +} diff --git a/publish/web.config b/publish/web.config new file mode 100644 index 00000000..70ff460b --- /dev/null +++ b/publish/web.config @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/publish/wwwroot/api-docs/jellyfin.svg b/publish/wwwroot/api-docs/jellyfin.svg new file mode 100644 index 00000000..69253031 --- /dev/null +++ b/publish/wwwroot/api-docs/jellyfin.svg @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/publish/wwwroot/api-docs/jellyfin.svg.br b/publish/wwwroot/api-docs/jellyfin.svg.br new file mode 100644 index 00000000..c7ac2320 Binary files /dev/null and b/publish/wwwroot/api-docs/jellyfin.svg.br differ diff --git a/publish/wwwroot/api-docs/jellyfin.svg.gz b/publish/wwwroot/api-docs/jellyfin.svg.gz new file mode 100644 index 00000000..ddab3f56 Binary files /dev/null and b/publish/wwwroot/api-docs/jellyfin.svg.gz differ diff --git a/apply-supplementary-indexes-migration.sql b/publish/wwwroot/api-docs/redoc/custom.css similarity index 100% rename from apply-supplementary-indexes-migration.sql rename to publish/wwwroot/api-docs/redoc/custom.css diff --git a/publish/wwwroot/api-docs/redoc/custom.css.br b/publish/wwwroot/api-docs/redoc/custom.css.br new file mode 100644 index 00000000..1c8a0e79 --- /dev/null +++ b/publish/wwwroot/api-docs/redoc/custom.css.br @@ -0,0 +1 @@ +; \ No newline at end of file diff --git a/publish/wwwroot/api-docs/redoc/custom.css.gz b/publish/wwwroot/api-docs/redoc/custom.css.gz new file mode 100644 index 00000000..eb3294b9 Binary files /dev/null and b/publish/wwwroot/api-docs/redoc/custom.css.gz differ diff --git a/publish/wwwroot/api-docs/swagger/custom.css b/publish/wwwroot/api-docs/swagger/custom.css new file mode 100644 index 00000000..c14ad602 --- /dev/null +++ b/publish/wwwroot/api-docs/swagger/custom.css @@ -0,0 +1,17 @@ +/* logo */ +.topbar-wrapper img[alt="Swagger UI"], .topbar-wrapper span { + visibility: collapse; +} + +.topbar-wrapper .link:after { + content: ''; + display: block; + background-image: url(../jellyfin.svg); + background-position: center; + background-repeat: no-repeat; + background-size: contain; + box-sizing: border-box; + width: 220px; + height: 40px; +} +/* end logo */ diff --git a/publish/wwwroot/api-docs/swagger/custom.css.br b/publish/wwwroot/api-docs/swagger/custom.css.br new file mode 100644 index 00000000..291bcd58 Binary files /dev/null and b/publish/wwwroot/api-docs/swagger/custom.css.br differ diff --git a/publish/wwwroot/api-docs/swagger/custom.css.gz b/publish/wwwroot/api-docs/swagger/custom.css.gz new file mode 100644 index 00000000..3f2fd2fc Binary files /dev/null and b/publish/wwwroot/api-docs/swagger/custom.css.gz differ diff --git a/fix-activitylog-index.sql b/sql/apply-supplementary-indexes-migration.sql similarity index 100% rename from fix-activitylog-index.sql rename to sql/apply-supplementary-indexes-migration.sql diff --git a/sql/fix-activitylog-index.sql b/sql/fix-activitylog-index.sql index 3e74067c..e69de29b 100644 --- a/sql/fix-activitylog-index.sql +++ b/sql/fix-activitylog-index.sql @@ -1,27 +0,0 @@ --- ================================================ --- Fix for ActivityLogs Index --- Run this separately to create the missing index --- ================================================ --- --- This creates the ActivityLogs index that couldn't be created --- from within the main migration script due to PostgreSQL --- limitations with CONCURRENT operations in functions. --- --- ================================================ - --- Create the ActivityLogs index --- This will error gracefully if the table doesn't exist -CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_activitylogs_userid_datecreated -ON activitylog."ActivityLogs" ("UserId", "DateCreated" DESC) -WHERE "UserId" IS NOT NULL; - --- Verify it was created -SELECT - schemaname AS "Schema", - tablename AS "Table", - indexname AS "Index Name", - indexdef AS "Definition" -FROM pg_indexes -WHERE indexname = 'idx_activitylogs_userid_datecreated'; - --- Expected: 1 row showing the index on activitylog.ActivityLogs diff --git a/sql/schema_init/create_database_schema.sql b/sql/schema_init/create_database_schema.sql index 9de83f54..bfb21b28 100644 --- a/sql/schema_init/create_database_schema.sql +++ b/sql/schema_init/create_database_schema.sql @@ -2,7 +2,7 @@ -- PostgreSQL database dump -- -\restrict 7yQHzelyscgVdVnHcclaahZ3bSdtHCyhzvmlksdJIsj2eWF8f38OCYThpGtIjiX +\restrict ioCi9akCEb4OTJqqafagnN0ujRzEOChWnb2NQKO5G1mPGHoPiOIWcce58T7EixH -- Dumped from database version 18.3 (Ubuntu 18.3-1.pgdg25.10+1) -- Dumped by pg_dump version 18.3 (Ubuntu 18.3-1.pgdg25.10+1) @@ -55,6 +55,20 @@ CREATE SCHEMA library; ALTER SCHEMA library OWNER TO jellyfin; +-- +-- Name: pg_repack; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS pg_repack WITH SCHEMA public; + + +-- +-- Name: EXTENSION pg_repack; Type: COMMENT; Schema: -; Owner: +-- + +COMMENT ON EXTENSION pg_repack IS 'Reorganize tables in PostgreSQL databases with minimal locks'; + + -- -- Name: users; Type: SCHEMA; Schema: -; Owner: jellyfin -- @@ -83,30 +97,30 @@ SET default_tablespace = ''; SET default_table_access_method = heap; -- --- Name: ActivityLogs; Type: TABLE; Schema: activitylog; Owner: jellyfin +-- Name: activity_logs; Type: TABLE; Schema: activitylog; Owner: jellyfin -- -CREATE TABLE activitylog."ActivityLogs" ( - "Id" integer NOT NULL, - "Name" character varying(512) NOT NULL, - "Overview" character varying(512), - "ShortOverview" character varying(512), - "Type" character varying(256) NOT NULL, - "UserId" uuid NOT NULL, - "ItemId" character varying(256), - "DateCreated" timestamp with time zone NOT NULL, - "LogSeverity" integer NOT NULL, - "RowVersion" bigint NOT NULL +CREATE TABLE activitylog.activity_logs ( + id integer CONSTRAINT "ActivityLogs_Id_not_null" NOT NULL, + name character varying(512) CONSTRAINT "ActivityLogs_Name_not_null" NOT NULL, + overview character varying(512), + short_overview character varying(512), + type character varying(256) CONSTRAINT "ActivityLogs_Type_not_null" NOT NULL, + user_id uuid CONSTRAINT "ActivityLogs_UserId_not_null" NOT NULL, + item_id character varying(256), + date_created timestamp with time zone CONSTRAINT "ActivityLogs_DateCreated_not_null" NOT NULL, + log_severity integer CONSTRAINT "ActivityLogs_LogSeverity_not_null" NOT NULL, + row_version bigint CONSTRAINT "ActivityLogs_RowVersion_not_null" NOT NULL ); -ALTER TABLE activitylog."ActivityLogs" OWNER TO jellyfin; +ALTER TABLE activitylog.activity_logs OWNER TO jellyfin; -- -- Name: ActivityLogs_Id_seq; Type: SEQUENCE; Schema: activitylog; Owner: jellyfin -- -ALTER TABLE activitylog."ActivityLogs" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( +ALTER TABLE activitylog.activity_logs ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( SEQUENCE NAME activitylog."ActivityLogs_Id_seq" START WITH 1 INCREMENT BY 1 @@ -117,25 +131,25 @@ ALTER TABLE activitylog."ActivityLogs" ALTER COLUMN "Id" ADD GENERATED BY DEFAUL -- --- Name: ApiKeys; Type: TABLE; Schema: authentication; Owner: jellyfin +-- Name: api_keys; Type: TABLE; Schema: authentication; Owner: jellyfin -- -CREATE TABLE authentication."ApiKeys" ( - "Id" integer NOT NULL, - "DateCreated" timestamp with time zone NOT NULL, - "DateLastActivity" timestamp with time zone NOT NULL, - "Name" character varying(64) NOT NULL, - "AccessToken" text NOT NULL +CREATE TABLE authentication.api_keys ( + id integer CONSTRAINT "ApiKeys_Id_not_null" NOT NULL, + date_created timestamp with time zone CONSTRAINT "ApiKeys_DateCreated_not_null" NOT NULL, + date_last_activity timestamp with time zone CONSTRAINT "ApiKeys_DateLastActivity_not_null" NOT NULL, + name character varying(64) CONSTRAINT "ApiKeys_Name_not_null" NOT NULL, + access_token text CONSTRAINT "ApiKeys_AccessToken_not_null" NOT NULL ); -ALTER TABLE authentication."ApiKeys" OWNER TO jellyfin; +ALTER TABLE authentication.api_keys OWNER TO jellyfin; -- -- Name: ApiKeys_Id_seq; Type: SEQUENCE; Schema: authentication; Owner: jellyfin -- -ALTER TABLE authentication."ApiKeys" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( +ALTER TABLE authentication.api_keys ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( SEQUENCE NAME authentication."ApiKeys_Id_seq" START WITH 1 INCREMENT BY 1 @@ -146,23 +160,23 @@ ALTER TABLE authentication."ApiKeys" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT -- --- Name: DeviceOptions; Type: TABLE; Schema: authentication; Owner: jellyfin +-- Name: device_options; Type: TABLE; Schema: authentication; Owner: jellyfin -- -CREATE TABLE authentication."DeviceOptions" ( - "Id" integer NOT NULL, - "DeviceId" text NOT NULL, - "CustomName" text +CREATE TABLE authentication.device_options ( + id integer CONSTRAINT "DeviceOptions_Id_not_null" NOT NULL, + device_id text CONSTRAINT "DeviceOptions_DeviceId_not_null" NOT NULL, + custom_name text ); -ALTER TABLE authentication."DeviceOptions" OWNER TO jellyfin; +ALTER TABLE authentication.device_options OWNER TO jellyfin; -- -- Name: DeviceOptions_Id_seq; Type: SEQUENCE; Schema: authentication; Owner: jellyfin -- -ALTER TABLE authentication."DeviceOptions" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( +ALTER TABLE authentication.device_options ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( SEQUENCE NAME authentication."DeviceOptions_Id_seq" START WITH 1 INCREMENT BY 1 @@ -173,31 +187,31 @@ ALTER TABLE authentication."DeviceOptions" ALTER COLUMN "Id" ADD GENERATED BY DE -- --- Name: Devices; Type: TABLE; Schema: authentication; Owner: jellyfin +-- Name: devices; Type: TABLE; Schema: authentication; Owner: jellyfin -- -CREATE TABLE authentication."Devices" ( - "Id" integer NOT NULL, - "UserId" uuid NOT NULL, - "AccessToken" text NOT NULL, - "AppName" character varying(64) NOT NULL, - "AppVersion" character varying(32) NOT NULL, - "DeviceName" character varying(64) NOT NULL, - "DeviceId" character varying(256) NOT NULL, - "IsActive" boolean NOT NULL, - "DateCreated" timestamp with time zone NOT NULL, - "DateModified" timestamp with time zone NOT NULL, - "DateLastActivity" timestamp with time zone NOT NULL +CREATE TABLE authentication.devices ( + id integer CONSTRAINT "Devices_Id_not_null" NOT NULL, + user_id uuid CONSTRAINT "Devices_UserId_not_null" NOT NULL, + access_token text CONSTRAINT "Devices_AccessToken_not_null" NOT NULL, + app_name character varying(64) CONSTRAINT "Devices_AppName_not_null" NOT NULL, + app_version character varying(32) CONSTRAINT "Devices_AppVersion_not_null" NOT NULL, + device_name character varying(64) CONSTRAINT "Devices_DeviceName_not_null" NOT NULL, + device_id character varying(256) CONSTRAINT "Devices_DeviceId_not_null" NOT NULL, + is_active boolean CONSTRAINT "Devices_IsActive_not_null" NOT NULL, + date_created timestamp with time zone CONSTRAINT "Devices_DateCreated_not_null" NOT NULL, + date_modified timestamp with time zone CONSTRAINT "Devices_DateModified_not_null" NOT NULL, + date_last_activity timestamp with time zone CONSTRAINT "Devices_DateLastActivity_not_null" NOT NULL ); -ALTER TABLE authentication."Devices" OWNER TO jellyfin; +ALTER TABLE authentication.devices OWNER TO jellyfin; -- -- Name: Devices_Id_seq; Type: SEQUENCE; Schema: authentication; Owner: jellyfin -- -ALTER TABLE authentication."Devices" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( +ALTER TABLE authentication.devices ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( SEQUENCE NAME authentication."Devices_Id_seq" START WITH 1 INCREMENT BY 1 @@ -208,26 +222,26 @@ ALTER TABLE authentication."Devices" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT -- --- Name: CustomItemDisplayPreferences; Type: TABLE; Schema: displaypreferences; Owner: jellyfin +-- Name: custom_item_display_preferences; Type: TABLE; Schema: displaypreferences; Owner: jellyfin -- -CREATE TABLE displaypreferences."CustomItemDisplayPreferences" ( - "Id" integer NOT NULL, - "UserId" uuid NOT NULL, - "ItemId" uuid NOT NULL, - "Client" character varying(32) NOT NULL, - "Key" text NOT NULL, - "Value" text +CREATE TABLE displaypreferences.custom_item_display_preferences ( + id integer CONSTRAINT "CustomItemDisplayPreferences_Id_not_null" NOT NULL, + user_id uuid CONSTRAINT "CustomItemDisplayPreferences_UserId_not_null" NOT NULL, + item_id uuid CONSTRAINT "CustomItemDisplayPreferences_ItemId_not_null" NOT NULL, + client character varying(32) CONSTRAINT "CustomItemDisplayPreferences_Client_not_null" NOT NULL, + key text CONSTRAINT "CustomItemDisplayPreferences_Key_not_null" NOT NULL, + value text ); -ALTER TABLE displaypreferences."CustomItemDisplayPreferences" OWNER TO jellyfin; +ALTER TABLE displaypreferences.custom_item_display_preferences OWNER TO jellyfin; -- -- Name: CustomItemDisplayPreferences_Id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE displaypreferences."CustomItemDisplayPreferences" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( +ALTER TABLE displaypreferences.custom_item_display_preferences ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( SEQUENCE NAME displaypreferences."CustomItemDisplayPreferences_Id_seq" START WITH 1 INCREMENT BY 1 @@ -238,34 +252,34 @@ ALTER TABLE displaypreferences."CustomItemDisplayPreferences" ALTER COLUMN "Id" -- --- Name: DisplayPreferences; Type: TABLE; Schema: displaypreferences; Owner: jellyfin +-- Name: display_preferences; Type: TABLE; Schema: displaypreferences; Owner: jellyfin -- -CREATE TABLE displaypreferences."DisplayPreferences" ( - "Id" integer NOT NULL, - "UserId" uuid NOT NULL, - "ItemId" uuid NOT NULL, - "Client" character varying(32) NOT NULL, - "ShowSidebar" boolean NOT NULL, - "ShowBackdrop" boolean NOT NULL, - "ScrollDirection" integer NOT NULL, - "IndexBy" integer, - "SkipForwardLength" integer NOT NULL, - "SkipBackwardLength" integer NOT NULL, - "ChromecastVersion" integer NOT NULL, - "EnableNextVideoInfoOverlay" boolean NOT NULL, - "DashboardTheme" character varying(32), - "TvHome" character varying(32) +CREATE TABLE displaypreferences.display_preferences ( + id integer CONSTRAINT "DisplayPreferences_Id_not_null" NOT NULL, + user_id uuid CONSTRAINT "DisplayPreferences_UserId_not_null" NOT NULL, + item_id uuid CONSTRAINT "DisplayPreferences_ItemId_not_null" NOT NULL, + client character varying(32) CONSTRAINT "DisplayPreferences_Client_not_null" NOT NULL, + show_sidebar boolean CONSTRAINT "DisplayPreferences_ShowSidebar_not_null" NOT NULL, + show_backdrop boolean CONSTRAINT "DisplayPreferences_ShowBackdrop_not_null" NOT NULL, + scroll_direction integer CONSTRAINT "DisplayPreferences_ScrollDirection_not_null" NOT NULL, + index_by integer, + skip_forward_length integer CONSTRAINT "DisplayPreferences_SkipForwardLength_not_null" NOT NULL, + skip_backward_length integer CONSTRAINT "DisplayPreferences_SkipBackwardLength_not_null" NOT NULL, + chromecast_version integer CONSTRAINT "DisplayPreferences_ChromecastVersion_not_null" NOT NULL, + enable_next_video_info_overlay boolean CONSTRAINT "DisplayPreferences_EnableNextVideoInfoOverlay_not_null" NOT NULL, + dashboard_theme character varying(32), + tv_home character varying(32) ); -ALTER TABLE displaypreferences."DisplayPreferences" OWNER TO jellyfin; +ALTER TABLE displaypreferences.display_preferences OWNER TO jellyfin; -- -- Name: DisplayPreferences_Id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE displaypreferences."DisplayPreferences" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( +ALTER TABLE displaypreferences.display_preferences ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( SEQUENCE NAME displaypreferences."DisplayPreferences_Id_seq" START WITH 1 INCREMENT BY 1 @@ -276,24 +290,24 @@ ALTER TABLE displaypreferences."DisplayPreferences" ALTER COLUMN "Id" ADD GENERA -- --- Name: HomeSection; Type: TABLE; Schema: displaypreferences; Owner: jellyfin +-- Name: home_sections; Type: TABLE; Schema: displaypreferences; Owner: jellyfin -- -CREATE TABLE displaypreferences."HomeSection" ( - "Id" integer NOT NULL, - "DisplayPreferencesId" integer NOT NULL, - "Order" integer NOT NULL, - "Type" integer NOT NULL +CREATE TABLE displaypreferences.home_sections ( + id integer CONSTRAINT "HomeSection_Id_not_null" NOT NULL, + display_preferences_id integer CONSTRAINT "HomeSection_DisplayPreferencesId_not_null" NOT NULL, + "order" integer CONSTRAINT "HomeSection_Order_not_null" NOT NULL, + type integer CONSTRAINT "HomeSection_Type_not_null" NOT NULL ); -ALTER TABLE displaypreferences."HomeSection" OWNER TO jellyfin; +ALTER TABLE displaypreferences.home_sections OWNER TO jellyfin; -- -- Name: HomeSection_Id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE displaypreferences."HomeSection" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( +ALTER TABLE displaypreferences.home_sections ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( SEQUENCE NAME displaypreferences."HomeSection_Id_seq" START WITH 1 INCREMENT BY 1 @@ -304,30 +318,30 @@ ALTER TABLE displaypreferences."HomeSection" ALTER COLUMN "Id" ADD GENERATED BY -- --- Name: ItemDisplayPreferences; Type: TABLE; Schema: displaypreferences; Owner: jellyfin +-- Name: item_display_preferences; Type: TABLE; Schema: displaypreferences; Owner: jellyfin -- -CREATE TABLE displaypreferences."ItemDisplayPreferences" ( - "Id" integer NOT NULL, - "UserId" uuid NOT NULL, - "ItemId" uuid NOT NULL, - "Client" character varying(32) NOT NULL, - "ViewType" integer NOT NULL, - "RememberIndexing" boolean NOT NULL, - "IndexBy" integer, - "RememberSorting" boolean NOT NULL, - "SortBy" character varying(64) NOT NULL, - "SortOrder" integer NOT NULL +CREATE TABLE displaypreferences.item_display_preferences ( + id integer CONSTRAINT "ItemDisplayPreferences_Id_not_null" NOT NULL, + user_id uuid CONSTRAINT "ItemDisplayPreferences_UserId_not_null" NOT NULL, + item_id uuid CONSTRAINT "ItemDisplayPreferences_ItemId_not_null" NOT NULL, + client character varying(32) CONSTRAINT "ItemDisplayPreferences_Client_not_null" NOT NULL, + view_type integer CONSTRAINT "ItemDisplayPreferences_ViewType_not_null" NOT NULL, + remember_indexing boolean CONSTRAINT "ItemDisplayPreferences_RememberIndexing_not_null" NOT NULL, + index_by integer, + remember_sorting boolean CONSTRAINT "ItemDisplayPreferences_RememberSorting_not_null" NOT NULL, + sort_by character varying(64) CONSTRAINT "ItemDisplayPreferences_SortBy_not_null" NOT NULL, + sort_order integer CONSTRAINT "ItemDisplayPreferences_SortOrder_not_null" NOT NULL ); -ALTER TABLE displaypreferences."ItemDisplayPreferences" OWNER TO jellyfin; +ALTER TABLE displaypreferences.item_display_preferences OWNER TO jellyfin; -- -- Name: ItemDisplayPreferences_Id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE displaypreferences."ItemDisplayPreferences" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( +ALTER TABLE displaypreferences.item_display_preferences ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( SEQUENCE NAME displaypreferences."ItemDisplayPreferences_Id_seq" START WITH 1 INCREMENT BY 1 @@ -338,206 +352,24 @@ ALTER TABLE displaypreferences."ItemDisplayPreferences" ALTER COLUMN "Id" ADD GE -- --- Name: AncestorIds; Type: TABLE; Schema: library; Owner: jellyfin +-- Name: image_infos; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."AncestorIds" ( - "ParentItemId" uuid NOT NULL, - "ItemId" uuid NOT NULL +CREATE TABLE library.image_infos ( + id integer CONSTRAINT "ImageInfos_Id_not_null" NOT NULL, + user_id uuid, + path character varying(512) CONSTRAINT "ImageInfos_Path_not_null" NOT NULL, + last_modified timestamp with time zone CONSTRAINT "ImageInfos_LastModified_not_null" NOT NULL ); -ALTER TABLE library."AncestorIds" OWNER TO jellyfin; - --- --- Name: AttachmentStreamInfos; Type: TABLE; Schema: library; Owner: jellyfin --- - -CREATE TABLE library."AttachmentStreamInfos" ( - "ItemId" uuid NOT NULL, - "Index" integer NOT NULL, - "Codec" text, - "CodecTag" text, - "Comment" text, - "Filename" text, - "MimeType" text -); - - -ALTER TABLE library."AttachmentStreamInfos" OWNER TO jellyfin; - --- --- Name: BaseItemImageInfos; Type: TABLE; Schema: library; Owner: jellyfin --- - -CREATE TABLE library."BaseItemImageInfos" ( - "Id" uuid NOT NULL, - "Path" text NOT NULL, - "DateModified" timestamp with time zone, - "ImageType" integer NOT NULL, - "Width" integer NOT NULL, - "Height" integer NOT NULL, - "Blurhash" bytea, - "ItemId" uuid NOT NULL -); - - -ALTER TABLE library."BaseItemImageInfos" OWNER TO jellyfin; - --- --- Name: BaseItemMetadataFields; Type: TABLE; Schema: library; Owner: jellyfin --- - -CREATE TABLE library."BaseItemMetadataFields" ( - "Id" integer NOT NULL, - "ItemId" uuid NOT NULL -); - - -ALTER TABLE library."BaseItemMetadataFields" OWNER TO jellyfin; - --- --- Name: BaseItemProviders; Type: TABLE; Schema: library; Owner: jellyfin --- - -CREATE TABLE library."BaseItemProviders" ( - "ItemId" uuid NOT NULL, - "ProviderId" text NOT NULL, - "ProviderValue" text NOT NULL -); - - -ALTER TABLE library."BaseItemProviders" OWNER TO jellyfin; - --- --- Name: BaseItemTrailerTypes; Type: TABLE; Schema: library; Owner: jellyfin --- - -CREATE TABLE library."BaseItemTrailerTypes" ( - "Id" integer NOT NULL, - "ItemId" uuid NOT NULL -); - - -ALTER TABLE library."BaseItemTrailerTypes" OWNER TO jellyfin; - --- --- Name: BaseItems; Type: TABLE; Schema: library; Owner: jellyfin --- - -CREATE TABLE library."BaseItems" ( - "Id" uuid NOT NULL, - "Type" text NOT NULL, - "Data" text, - "Path" text, - "StartDate" timestamp with time zone, - "EndDate" timestamp with time zone, - "ChannelId" uuid, - "IsMovie" boolean NOT NULL, - "CommunityRating" real, - "CustomRating" text, - "IndexNumber" integer, - "IsLocked" boolean NOT NULL, - "Name" text, - "OfficialRating" text, - "MediaType" text, - "Overview" text, - "ParentIndexNumber" integer, - "PremiereDate" timestamp with time zone, - "ProductionYear" integer, - "Genres" text, - "SortName" text, - "ForcedSortName" text, - "RunTimeTicks" bigint, - "DateCreated" timestamp with time zone, - "DateModified" timestamp with time zone, - "IsSeries" boolean NOT NULL, - "EpisodeTitle" text, - "IsRepeat" boolean NOT NULL, - "PreferredMetadataLanguage" text, - "PreferredMetadataCountryCode" text, - "DateLastRefreshed" timestamp with time zone, - "DateLastSaved" timestamp with time zone, - "IsInMixedFolder" boolean NOT NULL, - "Studios" text, - "ExternalServiceId" text, - "Tags" text, - "IsFolder" boolean NOT NULL, - "InheritedParentalRatingValue" integer, - "InheritedParentalRatingSubValue" integer, - "UnratedType" text, - "CriticRating" real, - "CleanName" text, - "PresentationUniqueKey" text, - "OriginalTitle" text, - "PrimaryVersionId" text, - "DateLastMediaAdded" timestamp with time zone, - "Album" text, - "LUFS" real, - "NormalizationGain" real, - "IsVirtualItem" boolean NOT NULL, - "SeriesName" text, - "SeasonName" text, - "ExternalSeriesId" text, - "Tagline" text, - "ProductionLocations" text, - "ExtraIds" text, - "TotalBitrate" integer, - "ExtraType" integer, - "Artists" text, - "AlbumArtists" text, - "ExternalId" text, - "SeriesPresentationUniqueKey" text, - "ShowId" text, - "OwnerId" text, - "Width" integer, - "Height" integer, - "Size" bigint, - "Audio" integer, - "ParentId" uuid, - "TopParentId" uuid, - "SeasonId" uuid, - "SeriesId" uuid -); - - -ALTER TABLE library."BaseItems" OWNER TO jellyfin; - --- --- Name: Chapters; Type: TABLE; Schema: library; Owner: jellyfin --- - -CREATE TABLE library."Chapters" ( - "ItemId" uuid NOT NULL, - "ChapterIndex" integer NOT NULL, - "StartPositionTicks" bigint NOT NULL, - "Name" text, - "ImagePath" text, - "ImageDateModified" timestamp with time zone -); - - -ALTER TABLE library."Chapters" OWNER TO jellyfin; - --- --- Name: ImageInfos; Type: TABLE; Schema: library; Owner: jellyfin --- - -CREATE TABLE library."ImageInfos" ( - "Id" integer NOT NULL, - "UserId" uuid, - "Path" character varying(512) NOT NULL, - "LastModified" timestamp with time zone NOT NULL -); - - -ALTER TABLE library."ImageInfos" OWNER TO jellyfin; +ALTER TABLE library.image_infos OWNER TO jellyfin; -- -- Name: ImageInfos_Id_seq; Type: SEQUENCE; Schema: library; Owner: jellyfin -- -ALTER TABLE library."ImageInfos" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( +ALTER TABLE library.image_infos ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( SEQUENCE NAME library."ImageInfos_Id_seq" START WITH 1 INCREMENT BY 1 @@ -548,215 +380,892 @@ ALTER TABLE library."ImageInfos" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS I -- --- Name: ItemValues; Type: TABLE; Schema: library; Owner: jellyfin +-- Name: ancestor_ids; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."ItemValues" ( - "ItemValueId" uuid NOT NULL, - "Type" integer NOT NULL, - "Value" text NOT NULL, - "CleanValue" text NOT NULL +CREATE TABLE library.ancestor_ids ( + parent_item_id uuid CONSTRAINT "AncestorIds_ParentItemId_not_null" NOT NULL, + item_id uuid CONSTRAINT "AncestorIds_ItemId_not_null" NOT NULL ); -ALTER TABLE library."ItemValues" OWNER TO jellyfin; +ALTER TABLE library.ancestor_ids OWNER TO jellyfin; -- --- Name: ItemValuesMap; Type: TABLE; Schema: library; Owner: jellyfin +-- Name: attachment_stream_infos; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."ItemValuesMap" ( - "ItemId" uuid NOT NULL, - "ItemValueId" uuid NOT NULL +CREATE TABLE library.attachment_stream_infos ( + item_id uuid CONSTRAINT "AttachmentStreamInfos_ItemId_not_null" NOT NULL, + index integer CONSTRAINT "AttachmentStreamInfos_Index_not_null" NOT NULL, + codec text, + codec_tag text, + comment text, + filename text, + mime_type text ); -ALTER TABLE library."ItemValuesMap" OWNER TO jellyfin; +ALTER TABLE library.attachment_stream_infos OWNER TO jellyfin; -- --- Name: KeyframeData; Type: TABLE; Schema: library; Owner: jellyfin +-- Name: audio_stream_details; Type: TABLE; Schema: library; Owner: postgres -- -CREATE TABLE library."KeyframeData" ( - "ItemId" uuid NOT NULL, - "TotalDuration" bigint NOT NULL, - "KeyframeTicks" bigint[] +CREATE TABLE library.audio_stream_details ( + item_id uuid CONSTRAINT "AudioStreamDetails_ItemId_not_null" NOT NULL, + stream_index integer CONSTRAINT "AudioStreamDetails_StreamIndex_not_null" NOT NULL, + channel_layout text, + channels integer, + sample_rate integer, + is_hearing_impaired boolean ); -ALTER TABLE library."KeyframeData" OWNER TO jellyfin; +ALTER TABLE library.audio_stream_details OWNER TO postgres; -- --- Name: LibraryOptions; Type: TABLE; Schema: library; Owner: postgres +-- Name: base_item_audio_extras; Type: TABLE; Schema: library; Owner: postgres -- -CREATE TABLE library."LibraryOptions" ( - "LibraryPath" text NOT NULL, - "OptionsJson" jsonb NOT NULL, - "Version" integer DEFAULT 1 NOT NULL, - "DateCreated" timestamp with time zone DEFAULT now() NOT NULL, - "DateModified" timestamp with time zone DEFAULT now() NOT NULL +CREATE TABLE library.base_item_audio_extras ( + item_id uuid CONSTRAINT "BaseItemAudioExtras_ItemId_not_null" NOT NULL, + album text, + artists text, + album_artists text, + lufs real, + normalization_gain real ); -ALTER TABLE library."LibraryOptions" OWNER TO postgres; +ALTER TABLE library.base_item_audio_extras OWNER TO postgres; -- --- Name: MediaSegments; Type: TABLE; Schema: library; Owner: jellyfin +-- Name: base_item_image_infos; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."MediaSegments" ( - "Id" uuid NOT NULL, - "ItemId" uuid NOT NULL, - "Type" integer NOT NULL, - "EndTicks" bigint NOT NULL, - "StartTicks" bigint NOT NULL, - "SegmentProviderId" text NOT NULL +CREATE TABLE library.base_item_image_infos ( + id uuid CONSTRAINT "BaseItemImageInfos_Id_not_null" NOT NULL, + path text CONSTRAINT "BaseItemImageInfos_Path_not_null" NOT NULL, + date_modified timestamp with time zone, + image_type integer CONSTRAINT "BaseItemImageInfos_ImageType_not_null" NOT NULL, + width integer CONSTRAINT "BaseItemImageInfos_Width_not_null" NOT NULL, + height integer CONSTRAINT "BaseItemImageInfos_Height_not_null" NOT NULL, + blurhash bytea, + item_id uuid CONSTRAINT "BaseItemImageInfos_ItemId_not_null" NOT NULL ); -ALTER TABLE library."MediaSegments" OWNER TO jellyfin; +ALTER TABLE library.base_item_image_infos OWNER TO jellyfin; -- --- Name: MediaStreamInfos; Type: TABLE; Schema: library; Owner: jellyfin +-- Name: base_item_live_tv_extras; Type: TABLE; Schema: library; Owner: postgres -- -CREATE TABLE library."MediaStreamInfos" ( - "ItemId" uuid NOT NULL, - "StreamIndex" integer NOT NULL, - "StreamType" integer NOT NULL, - "Codec" text, - "Language" text, - "ChannelLayout" text, - "Profile" text, - "AspectRatio" text, - "Path" text, - "IsInterlaced" boolean, - "BitRate" integer, - "Channels" integer, - "SampleRate" integer, - "IsDefault" boolean NOT NULL, - "IsForced" boolean NOT NULL, - "IsExternal" boolean NOT NULL, - "Height" integer, - "Width" integer, - "AverageFrameRate" real, - "RealFrameRate" real, - "Level" real, - "PixelFormat" text, - "BitDepth" integer, - "IsAnamorphic" boolean, - "RefFrames" integer, - "CodecTag" text, - "Comment" text, - "NalLengthSize" text, - "IsAvc" boolean, - "Title" text, - "TimeBase" text, - "CodecTimeBase" text, - "ColorPrimaries" text, - "ColorSpace" text, - "ColorTransfer" text, - "DvVersionMajor" integer, - "DvVersionMinor" integer, - "DvProfile" integer, - "DvLevel" integer, - "RpuPresentFlag" integer, - "ElPresentFlag" integer, - "BlPresentFlag" integer, - "DvBlSignalCompatibilityId" integer, - "IsHearingImpaired" boolean, - "Rotation" integer, - "KeyFrames" text, - "Hdr10PlusPresentFlag" boolean +CREATE TABLE library.base_item_live_tv_extras ( + item_id uuid CONSTRAINT "BaseItemLiveTvExtras_ItemId_not_null" NOT NULL, + start_date timestamp with time zone, + end_date timestamp with time zone, + episode_title text, + show_id text, + external_series_id text, + external_service_id text, + audio integer ); -ALTER TABLE library."MediaStreamInfos" OWNER TO jellyfin; +ALTER TABLE library.base_item_live_tv_extras OWNER TO postgres; -- --- Name: PeopleBaseItemMap; Type: TABLE; Schema: library; Owner: jellyfin +-- Name: base_item_metadata_fields; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."PeopleBaseItemMap" ( - "Role" text NOT NULL, - "ItemId" uuid NOT NULL, - "PeopleId" uuid NOT NULL, - "SortOrder" integer, - "ListOrder" integer +CREATE TABLE library.base_item_metadata_fields ( + id integer CONSTRAINT "BaseItemMetadataFields_Id_not_null" NOT NULL, + item_id uuid CONSTRAINT "BaseItemMetadataFields_ItemId_not_null" NOT NULL ); -ALTER TABLE library."PeopleBaseItemMap" OWNER TO jellyfin; +ALTER TABLE library.base_item_metadata_fields OWNER TO jellyfin; -- --- Name: Peoples; Type: TABLE; Schema: library; Owner: jellyfin +-- Name: base_item_providers; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."Peoples" ( - "Id" uuid NOT NULL, - "Name" text NOT NULL, - "PersonType" text +CREATE TABLE library.base_item_providers ( + item_id uuid CONSTRAINT "BaseItemProviders_ItemId_not_null" NOT NULL, + provider_id text CONSTRAINT "BaseItemProviders_ProviderId_not_null" NOT NULL, + provider_value text CONSTRAINT "BaseItemProviders_ProviderValue_not_null" NOT NULL ); -ALTER TABLE library."Peoples" OWNER TO jellyfin; +ALTER TABLE library.base_item_providers OWNER TO jellyfin; -- --- Name: TrickplayInfos; Type: TABLE; Schema: library; Owner: jellyfin +-- Name: base_item_trailer_types; Type: TABLE; Schema: library; Owner: jellyfin -- -CREATE TABLE library."TrickplayInfos" ( - "ItemId" uuid NOT NULL, - "Width" integer NOT NULL, - "Height" integer NOT NULL, - "TileWidth" integer NOT NULL, - "TileHeight" integer NOT NULL, - "ThumbnailCount" integer NOT NULL, - "Interval" integer NOT NULL, - "Bandwidth" integer NOT NULL +CREATE TABLE library.base_item_trailer_types ( + id integer CONSTRAINT "BaseItemTrailerTypes_Id_not_null" NOT NULL, + item_id uuid CONSTRAINT "BaseItemTrailerTypes_ItemId_not_null" NOT NULL ); -ALTER TABLE library."TrickplayInfos" OWNER TO jellyfin; +ALTER TABLE library.base_item_trailer_types OWNER TO jellyfin; -- --- Name: UserData; Type: TABLE; Schema: library; Owner: jellyfin +-- Name: base_item_tv_extras; Type: TABLE; Schema: library; Owner: postgres -- -CREATE TABLE library."UserData" ( - "CustomDataKey" text NOT NULL, - "ItemId" uuid NOT NULL, - "UserId" uuid NOT NULL, - "Rating" double precision, - "PlaybackPositionTicks" bigint NOT NULL, - "PlayCount" integer NOT NULL, - "IsFavorite" boolean NOT NULL, - "LastPlayedDate" timestamp with time zone, - "Played" boolean NOT NULL, - "AudioStreamIndex" integer, - "SubtitleStreamIndex" integer, - "Likes" boolean, - "RetentionDate" timestamp with time zone +CREATE TABLE library.base_item_tv_extras ( + item_id uuid CONSTRAINT "BaseItemTvExtras_ItemId_not_null" NOT NULL, + series_id uuid, + season_id uuid, + series_name text, + season_name text, + series_presentation_unique_key text ); -ALTER TABLE library."UserData" OWNER TO jellyfin; +ALTER TABLE library.base_item_tv_extras OWNER TO postgres; + +-- +-- Name: base_items; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.base_items ( + id uuid CONSTRAINT "BaseItems_Id_not_null" NOT NULL, + type text CONSTRAINT "BaseItems_Type_not_null" NOT NULL, + data text, + path text, + channel_id uuid, + is_movie boolean CONSTRAINT "BaseItems_IsMovie_not_null" NOT NULL, + community_rating real, + custom_rating text, + index_number integer, + is_locked boolean CONSTRAINT "BaseItems_IsLocked_not_null" NOT NULL, + name text, + official_rating text, + media_type text, + overview text, + parent_index_number integer, + premiere_date timestamp with time zone, + production_year integer, + genres text, + sort_name text, + forced_sort_name text, + run_time_ticks bigint, + date_created timestamp with time zone, + date_modified timestamp with time zone, + is_series boolean CONSTRAINT "BaseItems_IsSeries_not_null" NOT NULL, + is_repeat boolean CONSTRAINT "BaseItems_IsRepeat_not_null" NOT NULL, + preferred_metadata_language text, + preferred_metadata_country_code text, + date_last_refreshed timestamp with time zone, + date_last_saved timestamp with time zone, + is_in_mixed_folder boolean CONSTRAINT "BaseItems_IsInMixedFolder_not_null" NOT NULL, + studios text, + tags text, + is_folder boolean CONSTRAINT "BaseItems_IsFolder_not_null" NOT NULL, + inherited_parental_rating_value integer, + inherited_parental_rating_sub_value integer, + unrated_type text, + critic_rating real, + clean_name text, + presentation_unique_key text, + original_title text, + primary_version_id text, + date_last_media_added timestamp with time zone, + is_virtual_item boolean CONSTRAINT "BaseItems_IsVirtualItem_not_null" NOT NULL, + tagline text, + production_locations text, + extra_ids text, + total_bitrate integer, + extra_type integer, + external_id text, + owner_id text, + width integer, + height integer, + size bigint, + parent_id uuid, + top_parent_id uuid +); + + +ALTER TABLE library.base_items OWNER TO jellyfin; + +-- +-- Name: base_items_v; Type: VIEW; Schema: library; Owner: postgres +-- + +CREATE VIEW library.base_items_v AS + SELECT b.id, + b.type, + b.data, + b.path, + b.channel_id, + b.is_movie, + b.community_rating, + b.custom_rating, + b.index_number, + b.is_locked, + b.name, + b.official_rating, + b.media_type, + b.overview, + b.parent_index_number, + b.premiere_date, + b.production_year, + b.genres, + b.sort_name, + b.forced_sort_name, + b.run_time_ticks, + b.date_created, + b.date_modified, + b.is_series, + b.is_repeat, + b.preferred_metadata_language, + b.preferred_metadata_country_code, + b.date_last_refreshed, + b.date_last_saved, + b.is_in_mixed_folder, + b.studios, + b.tags, + b.is_folder, + b.inherited_parental_rating_value, + b.inherited_parental_rating_sub_value, + b.unrated_type, + b.critic_rating, + b.clean_name, + b.presentation_unique_key, + b.original_title, + b.primary_version_id, + b.date_last_media_added, + b.is_virtual_item, + b.tagline, + b.production_locations, + b.extra_ids, + b.total_bitrate, + b.extra_type, + b.external_id, + b.owner_id, + b.width, + b.height, + b.size, + b.parent_id, + b.top_parent_id, + tv.series_id, + tv.season_id, + tv.series_name, + tv.season_name, + tv.series_presentation_unique_key, + ltv.start_date, + ltv.end_date, + ltv.episode_title, + ltv.show_id, + ltv.external_series_id, + ltv.external_service_id, + ltv.audio, + au.album, + au.artists, + au.album_artists, + au.lufs, + au.normalization_gain + FROM (((library.base_items b + LEFT JOIN library.base_item_tv_extras tv ON ((tv.item_id = b.id))) + LEFT JOIN library.base_item_live_tv_extras ltv ON ((ltv.item_id = b.id))) + LEFT JOIN library.base_item_audio_extras au ON ((au.item_id = b.id))); + + +ALTER VIEW library.base_items_v OWNER TO postgres; + +-- +-- Name: chapters; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.chapters ( + item_id uuid CONSTRAINT "Chapters_ItemId_not_null" NOT NULL, + chapter_index integer CONSTRAINT "Chapters_ChapterIndex_not_null" NOT NULL, + start_position_ticks bigint CONSTRAINT "Chapters_StartPositionTicks_not_null" NOT NULL, + name text, + image_path text, + image_date_modified timestamp with time zone +); + + +ALTER TABLE library.chapters OWNER TO jellyfin; + +-- +-- Name: people_base_item_map; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.people_base_item_map ( + role text CONSTRAINT "PeopleBaseItemMap_Role_not_null" NOT NULL, + item_id uuid CONSTRAINT "PeopleBaseItemMap_ItemId_not_null" NOT NULL, + people_id uuid CONSTRAINT "PeopleBaseItemMap_PeopleId_not_null" NOT NULL, + sort_order integer, + list_order integer +); + + +ALTER TABLE library.people_base_item_map OWNER TO jellyfin; + +-- +-- Name: peoples; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.peoples ( + id uuid CONSTRAINT "Peoples_Id_not_null" NOT NULL, + name text CONSTRAINT "Peoples_Name_not_null" NOT NULL, + person_type text +); + + +ALTER TABLE library.peoples OWNER TO jellyfin; + +-- +-- Name: item_people_v; Type: VIEW; Schema: library; Owner: postgres +-- + +CREATE VIEW library.item_people_v AS + SELECT b.id AS item_id, + b.type AS item_type, + b.name AS item_name, + tv.series_name, + b.production_year, + pe.id AS person_id, + pe.name AS person_name, + pe.person_type, + pm.role, + pm.sort_order, + pm.list_order + FROM (((library.people_base_item_map pm + JOIN library.base_items b ON ((pm.item_id = b.id))) + JOIN library.peoples pe ON ((pm.people_id = pe.id))) + LEFT JOIN library.base_item_tv_extras tv ON ((tv.item_id = b.id))) + WHERE (b.is_virtual_item = false); + + +ALTER VIEW library.item_people_v OWNER TO postgres; + +-- +-- Name: item_providers_v; Type: VIEW; Schema: library; Owner: postgres +-- + +CREATE VIEW library.item_providers_v AS + SELECT b.id AS item_id, + b.type, + b.name, + b.original_title, + b.production_year, + tv.series_name, + b.index_number AS episode_number, + b.parent_index_number AS season_number, + max( + CASE + WHEN (p.provider_id = 'Imdb'::text) THEN p.provider_value + ELSE NULL::text + END) AS imdb_id, + max( + CASE + WHEN (p.provider_id = 'Tmdb'::text) THEN p.provider_value + ELSE NULL::text + END) AS tmdb_id, + max( + CASE + WHEN (p.provider_id = 'Tvdb'::text) THEN p.provider_value + ELSE NULL::text + END) AS tvdb_id, + max( + CASE + WHEN (p.provider_id = 'TvRage'::text) THEN p.provider_value + ELSE NULL::text + END) AS tv_rage_id, + max( + CASE + WHEN (p.provider_id = 'MusicBrainzAlbum'::text) THEN p.provider_value + ELSE NULL::text + END) AS music_brainz_album_id, + max( + CASE + WHEN (p.provider_id = 'MusicBrainzArtist'::text) THEN p.provider_value + ELSE NULL::text + END) AS music_brainz_artist_id, + CASE + WHEN (count( + CASE + WHEN (p.provider_id <> ALL (ARRAY['Imdb'::text, 'Tmdb'::text, 'Tvdb'::text, 'TvRage'::text, 'MusicBrainzAlbum'::text, 'MusicBrainzArtist'::text])) THEN 1 + ELSE NULL::integer + END) > 0) THEN (jsonb_object_agg(p.provider_id, p.provider_value) FILTER (WHERE (p.provider_id <> ALL (ARRAY['Imdb'::text, 'Tmdb'::text, 'Tvdb'::text, 'TvRage'::text, 'MusicBrainzAlbum'::text, 'MusicBrainzArtist'::text]))))::text + ELSE NULL::text + END AS other_providers + FROM ((library.base_items b + LEFT JOIN library.base_item_providers p ON ((b.id = p.item_id))) + LEFT JOIN library.base_item_tv_extras tv ON ((b.id = tv.item_id))) + WHERE (b.is_virtual_item = false) + GROUP BY b.id, b.type, b.name, b.original_title, b.production_year, tv.series_name, b.index_number, b.parent_index_number; + + +ALTER VIEW library.item_providers_v OWNER TO postgres; + +-- +-- Name: item_values; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.item_values ( + item_value_id uuid CONSTRAINT "ItemValues_ItemValueId_not_null" NOT NULL, + type integer CONSTRAINT "ItemValues_Type_not_null" NOT NULL, + value text CONSTRAINT "ItemValues_Value_not_null" NOT NULL, + clean_value text CONSTRAINT "ItemValues_CleanValue_not_null" NOT NULL +); + + +ALTER TABLE library.item_values OWNER TO jellyfin; + +-- +-- Name: item_values_map; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.item_values_map ( + item_id uuid CONSTRAINT "ItemValuesMap_ItemId_not_null" NOT NULL, + item_value_id uuid CONSTRAINT "ItemValuesMap_ItemValueId_not_null" NOT NULL +); + + +ALTER TABLE library.item_values_map OWNER TO jellyfin; + +-- +-- Name: keyframe_data; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.keyframe_data ( + item_id uuid CONSTRAINT "KeyframeData_ItemId_not_null" NOT NULL, + total_duration bigint CONSTRAINT "KeyframeData_TotalDuration_not_null" NOT NULL, + keyframe_ticks bigint[] +); + + +ALTER TABLE library.keyframe_data OWNER TO jellyfin; + +-- +-- Name: library_options; Type: TABLE; Schema: library; Owner: postgres +-- + +CREATE TABLE library.library_options ( + library_path text CONSTRAINT "LibraryOptions_LibraryPath_not_null" NOT NULL, + options_json jsonb CONSTRAINT "LibraryOptions_OptionsJson_not_null" NOT NULL, + version integer DEFAULT 1 CONSTRAINT "LibraryOptions_Version_not_null" NOT NULL, + date_created timestamp with time zone DEFAULT now() CONSTRAINT "LibraryOptions_DateCreated_not_null" NOT NULL, + date_modified timestamp with time zone DEFAULT now() CONSTRAINT "LibraryOptions_DateModified_not_null" NOT NULL +); + + +ALTER TABLE library.library_options OWNER TO postgres; + +-- +-- Name: media_stream_infos; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.media_stream_infos ( + item_id uuid CONSTRAINT "MediaStreamInfos_ItemId_not_null" NOT NULL, + stream_index integer CONSTRAINT "MediaStreamInfos_StreamIndex_not_null" NOT NULL, + stream_type integer CONSTRAINT "MediaStreamInfos_StreamType_not_null" NOT NULL, + codec text, + language text, + profile text, + path text, + bit_rate integer, + is_default boolean CONSTRAINT "MediaStreamInfos_IsDefault_not_null" NOT NULL, + is_forced boolean CONSTRAINT "MediaStreamInfos_IsForced_not_null" NOT NULL, + is_external boolean CONSTRAINT "MediaStreamInfos_IsExternal_not_null" NOT NULL, + level real, + codec_tag text, + comment text, + is_avc boolean, + title text, + time_base text, + codec_time_base text +); + + +ALTER TABLE library.media_stream_infos OWNER TO jellyfin; + +-- +-- Name: video_stream_details; Type: TABLE; Schema: library; Owner: postgres +-- + +CREATE TABLE library.video_stream_details ( + item_id uuid CONSTRAINT "VideoStreamDetails_ItemId_not_null" NOT NULL, + stream_index integer CONSTRAINT "VideoStreamDetails_StreamIndex_not_null" NOT NULL, + aspect_ratio text, + is_interlaced boolean, + height integer, + width integer, + average_frame_rate real, + real_frame_rate real, + pixel_format text, + bit_depth integer, + is_anamorphic boolean, + ref_frames integer, + nal_length_size text, + color_primaries text, + color_space text, + color_transfer text, + dv_version_major integer, + dv_version_minor integer, + dv_profile integer, + dv_level integer, + rpu_present_flag integer, + el_present_flag integer, + bl_present_flag integer, + dv_bl_signal_compatibility_id integer, + rotation integer, + key_frames text, + hdr10_plus_present_flag boolean +); + + +ALTER TABLE library.video_stream_details OWNER TO postgres; + +-- +-- Name: library_summary_v; Type: VIEW; Schema: library; Owner: postgres +-- + +CREATE VIEW library.library_summary_v AS + WITH primary_video AS ( + SELECT DISTINCT ON (m.item_id) m.item_id, + vd.height, + vd.dv_profile, + vd.hdr10_plus_present_flag, + vd.color_transfer + FROM (library.media_stream_infos m + JOIN library.video_stream_details vd ON (((vd.item_id = m.item_id) AND (vd.stream_index = m.stream_index)))) + WHERE (m.stream_type = 1) + ORDER BY m.item_id, m.stream_index + ) + SELECT b.type, + count(*) AS item_count, + count(*) FILTER (WHERE (b.production_year IS NOT NULL)) AS with_year, + min(b.production_year) AS oldest_year, + max(b.production_year) AS newest_year, + round((avg(b.community_rating))::numeric, 2) AS avg_community_rating, + sum(b.run_time_ticks) AS total_run_time_ticks, + round((COALESCE(sum(b.run_time_ticks), (0)::numeric) / 600000000.0), 1) AS total_runtime_hours, + sum(b.size) AS total_size_bytes, + round((COALESCE(sum(b.size), (0)::numeric) / (1024.0 ^ (3)::numeric)), 2) AS total_size_gb, + count(*) FILTER (WHERE (pv.height >= 2160)) AS count4_k, + count(*) FILTER (WHERE ((pv.height >= 1080) AND (pv.height <= 2159))) AS count1080p, + count(*) FILTER (WHERE ((pv.height >= 720) AND (pv.height <= 1079))) AS count720p, + count(*) FILTER (WHERE ((pv.height < 720) AND (pv.height IS NOT NULL))) AS count_sd, + count(*) FILTER (WHERE (pv.dv_profile IS NOT NULL)) AS count_dolby_vision, + count(*) FILTER (WHERE (pv.hdr10_plus_present_flag = true)) AS count_hdr10_plus, + count(*) FILTER (WHERE ((pv.color_transfer = 'smpte2084'::text) AND (pv.dv_profile IS NULL) AND (pv.hdr10_plus_present_flag IS NOT TRUE))) AS count_hdr10 + FROM (library.base_items b + LEFT JOIN primary_video pv ON ((pv.item_id = b.id))) + WHERE ((b.is_virtual_item = false) AND (b.is_folder = false)) + GROUP BY b.type + ORDER BY (count(*)) DESC; + + +ALTER VIEW library.library_summary_v OWNER TO postgres; + +-- +-- Name: media_segments; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.media_segments ( + id uuid CONSTRAINT "MediaSegments_Id_not_null" NOT NULL, + item_id uuid CONSTRAINT "MediaSegments_ItemId_not_null" NOT NULL, + type integer CONSTRAINT "MediaSegments_Type_not_null" NOT NULL, + end_ticks bigint CONSTRAINT "MediaSegments_EndTicks_not_null" NOT NULL, + start_ticks bigint CONSTRAINT "MediaSegments_StartTicks_not_null" NOT NULL, + segment_provider_id text CONSTRAINT "MediaSegments_SegmentProviderId_not_null" NOT NULL +); + + +ALTER TABLE library.media_segments OWNER TO jellyfin; + +-- +-- Name: media_stream_infos_v; Type: VIEW; Schema: library; Owner: postgres +-- + +CREATE VIEW library.media_stream_infos_v AS + SELECT m.item_id, + m.stream_index, + m.stream_type, + m.codec, + m.language, + m.profile, + m.path, + m.bit_rate, + m.is_default, + m.is_forced, + m.is_external, + m.level, + m.codec_tag, + m.comment, + m.is_avc, + m.title, + m.time_base, + m.codec_time_base, + a.channel_layout, + a.channels, + a.sample_rate, + a.is_hearing_impaired, + v.aspect_ratio, + v.is_interlaced, + v.height, + v.width, + v.average_frame_rate, + v.real_frame_rate, + v.pixel_format, + v.bit_depth, + v.is_anamorphic, + v.ref_frames, + v.nal_length_size, + v.color_primaries, + v.color_space, + v.color_transfer, + v.dv_version_major, + v.dv_version_minor, + v.dv_profile, + v.dv_level, + v.rpu_present_flag, + v.el_present_flag, + v.bl_present_flag, + v.dv_bl_signal_compatibility_id, + v.rotation, + v.key_frames, + v.hdr10_plus_present_flag + FROM ((library.media_stream_infos m + LEFT JOIN library.audio_stream_details a ON (((m.item_id = a.item_id) AND (m.stream_index = a.stream_index)))) + LEFT JOIN library.video_stream_details v ON (((m.item_id = v.item_id) AND (m.stream_index = v.stream_index)))); + + +ALTER VIEW library.media_stream_infos_v OWNER TO postgres; + +-- +-- Name: trickplay_infos; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.trickplay_infos ( + item_id uuid CONSTRAINT "TrickplayInfos_ItemId_not_null" NOT NULL, + width integer CONSTRAINT "TrickplayInfos_Width_not_null" NOT NULL, + height integer CONSTRAINT "TrickplayInfos_Height_not_null" NOT NULL, + tile_width integer CONSTRAINT "TrickplayInfos_TileWidth_not_null" NOT NULL, + tile_height integer CONSTRAINT "TrickplayInfos_TileHeight_not_null" NOT NULL, + thumbnail_count integer CONSTRAINT "TrickplayInfos_ThumbnailCount_not_null" NOT NULL, + "interval" integer CONSTRAINT "TrickplayInfos_Interval_not_null" NOT NULL, + bandwidth integer CONSTRAINT "TrickplayInfos_Bandwidth_not_null" NOT NULL +); + + +ALTER TABLE library.trickplay_infos OWNER TO jellyfin; + +-- +-- Name: user_data; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.user_data ( + custom_data_key text CONSTRAINT "UserData_CustomDataKey_not_null" NOT NULL, + item_id uuid CONSTRAINT "UserData_ItemId_not_null" NOT NULL, + user_id uuid CONSTRAINT "UserData_UserId_not_null" NOT NULL, + rating double precision, + playback_position_ticks bigint CONSTRAINT "UserData_PlaybackPositionTicks_not_null" NOT NULL, + play_count integer CONSTRAINT "UserData_PlayCount_not_null" NOT NULL, + is_favorite boolean CONSTRAINT "UserData_IsFavorite_not_null" NOT NULL, + last_played_date timestamp with time zone, + played boolean CONSTRAINT "UserData_Played_not_null" NOT NULL, + audio_stream_index integer, + subtitle_stream_index integer, + likes boolean, + retention_date timestamp with time zone +); + + +ALTER TABLE library.user_data OWNER TO jellyfin; + +-- +-- Name: users; Type: TABLE; Schema: users; Owner: jellyfin +-- + +CREATE TABLE users.users ( + id uuid CONSTRAINT "Users_Id_not_null" NOT NULL, + username character varying(255) CONSTRAINT "Users_Username_not_null" NOT NULL, + password character varying(65535), + must_update_password boolean CONSTRAINT "Users_MustUpdatePassword_not_null" NOT NULL, + audio_language_preference character varying(255), + authentication_provider_id character varying(255) CONSTRAINT "Users_AuthenticationProviderId_not_null" NOT NULL, + password_reset_provider_id character varying(255) CONSTRAINT "Users_PasswordResetProviderId_not_null" NOT NULL, + invalid_login_attempt_count integer CONSTRAINT "Users_InvalidLoginAttemptCount_not_null" NOT NULL, + last_activity_date timestamp with time zone, + last_login_date timestamp with time zone, + login_attempts_before_lockout integer, + max_active_sessions integer CONSTRAINT "Users_MaxActiveSessions_not_null" NOT NULL, + subtitle_mode integer CONSTRAINT "Users_SubtitleMode_not_null" NOT NULL, + play_default_audio_track boolean CONSTRAINT "Users_PlayDefaultAudioTrack_not_null" NOT NULL, + subtitle_language_preference character varying(255), + display_missing_episodes boolean CONSTRAINT "Users_DisplayMissingEpisodes_not_null" NOT NULL, + display_collections_view boolean CONSTRAINT "Users_DisplayCollectionsView_not_null" NOT NULL, + enable_local_password boolean CONSTRAINT "Users_EnableLocalPassword_not_null" NOT NULL, + hide_played_in_latest boolean CONSTRAINT "Users_HidePlayedInLatest_not_null" NOT NULL, + remember_audio_selections boolean CONSTRAINT "Users_RememberAudioSelections_not_null" NOT NULL, + remember_subtitle_selections boolean CONSTRAINT "Users_RememberSubtitleSelections_not_null" NOT NULL, + enable_next_episode_auto_play boolean CONSTRAINT "Users_EnableNextEpisodeAutoPlay_not_null" NOT NULL, + enable_auto_login boolean CONSTRAINT "Users_EnableAutoLogin_not_null" NOT NULL, + enable_user_preference_access boolean CONSTRAINT "Users_EnableUserPreferenceAccess_not_null" NOT NULL, + max_parental_rating_score integer, + max_parental_rating_sub_score integer, + remote_client_bitrate_limit integer, + internal_id bigint CONSTRAINT "Users_InternalId_not_null" NOT NULL, + sync_play_access integer CONSTRAINT "Users_SyncPlayAccess_not_null" NOT NULL, + cast_receiver_id character varying(32), + row_version bigint CONSTRAINT "Users_RowVersion_not_null" NOT NULL +); + + +ALTER TABLE users.users OWNER TO jellyfin; + +-- +-- Name: user_playback_history_v; Type: VIEW; Schema: library; Owner: postgres +-- + +CREATE VIEW library.user_playback_history_v AS + SELECT u.username, + u.id AS user_id, + b.name AS item_name, + b.type AS item_type, + tv.series_name, + tv.season_name, + b.index_number AS episode_number, + b.parent_index_number AS season_number, + b.production_year, + b.run_time_ticks, + ud.item_id, + ud.played, + ud.play_count, + ud.last_played_date, + ud.playback_position_ticks, + CASE + WHEN (b.run_time_ticks > 0) THEN round((((ud.playback_position_ticks)::numeric * (100)::numeric) / (b.run_time_ticks)::numeric), 1) + ELSE NULL::numeric + END AS progress_pct, + ud.is_favorite, + ud.rating, + ud.audio_stream_index, + ud.subtitle_stream_index + FROM (((library.user_data ud + JOIN library.base_items b ON ((ud.item_id = b.id))) + JOIN users.users u ON ((ud.user_id = u.id))) + LEFT JOIN library.base_item_tv_extras tv ON ((tv.item_id = b.id))) + WHERE (ud.custom_data_key = ''::text); + + +ALTER VIEW library.user_playback_history_v OWNER TO postgres; + +-- +-- Name: video_items_v; Type: VIEW; Schema: library; Owner: postgres +-- + +CREATE VIEW library.video_items_v AS + SELECT b.id AS item_id, + b.type, + b.name, + b.original_title, + b.production_year, + b.official_rating, + b.community_rating, + b.run_time_ticks, + b.path, + b.date_created, + b.date_modified, + tv.series_name, + tv.season_name, + b.index_number AS episode_number, + b.parent_index_number AS season_number, + b.total_bitrate, + b.size, + m.codec AS video_codec, + m.profile AS video_profile, + vd.width, + vd.height, + vd.average_frame_rate, + vd.bit_depth, + vd.pixel_format, + vd.color_space, + vd.color_transfer, + vd.color_primaries, + vd.is_interlaced, + vd.is_anamorphic, + vd.aspect_ratio, + (vd.dv_profile IS NOT NULL) AS is_dolby_vision, + vd.hdr10_plus_present_flag AS is_hdr10_plus, + CASE + WHEN (vd.dv_profile IS NOT NULL) THEN 'Dolby Vision'::text + WHEN (vd.hdr10_plus_present_flag = true) THEN 'HDR10+'::text + WHEN (vd.color_transfer = 'smpte2084'::text) THEN 'HDR10'::text + WHEN (vd.color_transfer = 'arib-std-b67'::text) THEN 'HLG'::text + ELSE 'SDR'::text + END AS hdr_format, + ( SELECT count(*) AS count + FROM library.media_stream_infos ms + WHERE ((ms.item_id = b.id) AND (ms.stream_type = 0))) AS audio_track_count, + ( SELECT count(*) AS count + FROM library.media_stream_infos ms + WHERE ((ms.item_id = b.id) AND (ms.stream_type = 2))) AS subtitle_track_count + FROM (((library.base_items b + JOIN LATERAL ( SELECT ms.stream_index, + ms.codec, + ms.profile + FROM library.media_stream_infos ms + WHERE ((ms.item_id = b.id) AND (ms.stream_type = 1)) + ORDER BY ms.stream_index + LIMIT 1) m ON (true)) + JOIN library.video_stream_details vd ON (((vd.item_id = b.id) AND (vd.stream_index = m.stream_index)))) + LEFT JOIN library.base_item_tv_extras tv ON ((tv.item_id = b.id))) + WHERE ((b.is_virtual_item = false) AND (b.is_folder = false)); + + +ALTER VIEW library.video_items_v OWNER TO postgres; -- -- Name: __EFMigrationsHistory; Type: TABLE; Schema: public; Owner: jellyfin -- CREATE TABLE public."__EFMigrationsHistory" ( - "MigrationId" character varying(150) NOT NULL, - "ProductVersion" character varying(32) NOT NULL + migration_id character varying(150) CONSTRAINT "__EFMigrationsHistory_MigrationId_not_null" NOT NULL, + product_version character varying(32) CONSTRAINT "__EFMigrationsHistory_ProductVersion_not_null" NOT NULL ); ALTER TABLE public."__EFMigrationsHistory" OWNER TO jellyfin; -- --- Name: bloat_tables; Type: TABLE; Schema: public; Owner: jellyfin +-- Name: __ef_migrations_history; Type: TABLE; Schema: public; Owner: jellyfin +-- + +CREATE TABLE public.__ef_migrations_history ( + migration_id character varying(150) NOT NULL, + product_version character varying(32) NOT NULL +); + + +ALTER TABLE public.__ef_migrations_history OWNER TO jellyfin; + +-- +-- Name: __efmigrationshistory; Type: TABLE; Schema: public; Owner: postgres +-- + +CREATE TABLE public.__efmigrationshistory ( + migrationid character varying(150) NOT NULL, + productversion character varying(32) NOT NULL +); + + +ALTER TABLE public.__efmigrationshistory OWNER TO postgres; + +-- +-- Name: bloat_tables; Type: TABLE; Schema: public; Owner: postgres -- CREATE TABLE public.bloat_tables ( @@ -764,28 +1273,28 @@ CREATE TABLE public.bloat_tables ( ); -ALTER TABLE public.bloat_tables OWNER TO jellyfin; +ALTER TABLE public.bloat_tables OWNER TO postgres; -- --- Name: AccessSchedules; Type: TABLE; Schema: users; Owner: jellyfin +-- Name: access_schedules; Type: TABLE; Schema: users; Owner: jellyfin -- -CREATE TABLE users."AccessSchedules" ( - "Id" integer NOT NULL, - "UserId" uuid NOT NULL, - "DayOfWeek" integer NOT NULL, - "StartHour" double precision NOT NULL, - "EndHour" double precision NOT NULL +CREATE TABLE users.access_schedules ( + id integer CONSTRAINT "AccessSchedules_Id_not_null" NOT NULL, + user_id uuid CONSTRAINT "AccessSchedules_UserId_not_null" NOT NULL, + day_of_week integer CONSTRAINT "AccessSchedules_DayOfWeek_not_null" NOT NULL, + start_hour double precision CONSTRAINT "AccessSchedules_StartHour_not_null" NOT NULL, + end_hour double precision CONSTRAINT "AccessSchedules_EndHour_not_null" NOT NULL ); -ALTER TABLE users."AccessSchedules" OWNER TO jellyfin; +ALTER TABLE users.access_schedules OWNER TO jellyfin; -- -- Name: AccessSchedules_Id_seq; Type: SEQUENCE; Schema: users; Owner: jellyfin -- -ALTER TABLE users."AccessSchedules" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( +ALTER TABLE users.access_schedules ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( SEQUENCE NAME users."AccessSchedules_Id_seq" START WITH 1 INCREMENT BY 1 @@ -796,26 +1305,26 @@ ALTER TABLE users."AccessSchedules" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT A -- --- Name: Permissions; Type: TABLE; Schema: users; Owner: jellyfin +-- Name: permissions; Type: TABLE; Schema: users; Owner: jellyfin -- -CREATE TABLE users."Permissions" ( - "Id" integer NOT NULL, - "UserId" uuid, - "Kind" integer NOT NULL, - "Value" boolean NOT NULL, - "RowVersion" bigint NOT NULL, - "Permission_Permissions_Guid" uuid +CREATE TABLE users.permissions ( + id integer CONSTRAINT "Permissions_Id_not_null" NOT NULL, + user_id uuid, + kind integer CONSTRAINT "Permissions_Kind_not_null" NOT NULL, + value boolean CONSTRAINT "Permissions_Value_not_null" NOT NULL, + row_version bigint CONSTRAINT "Permissions_RowVersion_not_null" NOT NULL, + permission_permissions_guid uuid ); -ALTER TABLE users."Permissions" OWNER TO jellyfin; +ALTER TABLE users.permissions OWNER TO jellyfin; -- -- Name: Permissions_Id_seq; Type: SEQUENCE; Schema: users; Owner: jellyfin -- -ALTER TABLE users."Permissions" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( +ALTER TABLE users.permissions ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( SEQUENCE NAME users."Permissions_Id_seq" START WITH 1 INCREMENT BY 1 @@ -826,26 +1335,26 @@ ALTER TABLE users."Permissions" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS ID -- --- Name: Preferences; Type: TABLE; Schema: users; Owner: jellyfin +-- Name: preferences; Type: TABLE; Schema: users; Owner: jellyfin -- -CREATE TABLE users."Preferences" ( - "Id" integer NOT NULL, - "UserId" uuid, - "Kind" integer NOT NULL, - "Value" character varying(65535) NOT NULL, - "RowVersion" bigint NOT NULL, - "Preference_Preferences_Guid" uuid +CREATE TABLE users.preferences ( + id integer CONSTRAINT "Preferences_Id_not_null" NOT NULL, + user_id uuid, + kind integer CONSTRAINT "Preferences_Kind_not_null" NOT NULL, + value character varying(65535) CONSTRAINT "Preferences_Value_not_null" NOT NULL, + row_version bigint CONSTRAINT "Preferences_RowVersion_not_null" NOT NULL, + preference_preferences_guid uuid ); -ALTER TABLE users."Preferences" OWNER TO jellyfin; +ALTER TABLE users.preferences OWNER TO jellyfin; -- -- Name: Preferences_Id_seq; Type: SEQUENCE; Schema: users; Owner: jellyfin -- -ALTER TABLE users."Preferences" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS IDENTITY ( +ALTER TABLE users.preferences ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( SEQUENCE NAME users."Preferences_Id_seq" START WITH 1 INCREMENT BY 1 @@ -856,228 +1365,259 @@ ALTER TABLE users."Preferences" ALTER COLUMN "Id" ADD GENERATED BY DEFAULT AS ID -- --- Name: Users; Type: TABLE; Schema: users; Owner: jellyfin +-- Name: activity_logs PK_ActivityLogs; Type: CONSTRAINT; Schema: activitylog; Owner: jellyfin -- -CREATE TABLE users."Users" ( - "Id" uuid NOT NULL, - "Username" character varying(255) NOT NULL, - "Password" character varying(65535), - "MustUpdatePassword" boolean NOT NULL, - "AudioLanguagePreference" character varying(255), - "AuthenticationProviderId" character varying(255) NOT NULL, - "PasswordResetProviderId" character varying(255) NOT NULL, - "InvalidLoginAttemptCount" integer NOT NULL, - "LastActivityDate" timestamp with time zone, - "LastLoginDate" timestamp with time zone, - "LoginAttemptsBeforeLockout" integer, - "MaxActiveSessions" integer NOT NULL, - "SubtitleMode" integer NOT NULL, - "PlayDefaultAudioTrack" boolean NOT NULL, - "SubtitleLanguagePreference" character varying(255), - "DisplayMissingEpisodes" boolean NOT NULL, - "DisplayCollectionsView" boolean NOT NULL, - "EnableLocalPassword" boolean NOT NULL, - "HidePlayedInLatest" boolean NOT NULL, - "RememberAudioSelections" boolean NOT NULL, - "RememberSubtitleSelections" boolean NOT NULL, - "EnableNextEpisodeAutoPlay" boolean NOT NULL, - "EnableAutoLogin" boolean NOT NULL, - "EnableUserPreferenceAccess" boolean NOT NULL, - "MaxParentalRatingScore" integer, - "MaxParentalRatingSubScore" integer, - "RemoteClientBitrateLimit" integer, - "InternalId" bigint NOT NULL, - "SyncPlayAccess" integer NOT NULL, - "CastReceiverId" character varying(32), - "RowVersion" bigint NOT NULL -); - - -ALTER TABLE users."Users" OWNER TO jellyfin; - --- --- Name: ActivityLogs PK_ActivityLogs; Type: CONSTRAINT; Schema: activitylog; Owner: jellyfin --- - -ALTER TABLE ONLY activitylog."ActivityLogs" - ADD CONSTRAINT "PK_ActivityLogs" PRIMARY KEY ("Id"); +ALTER TABLE ONLY activitylog.activity_logs + ADD CONSTRAINT "PK_ActivityLogs" PRIMARY KEY (id); -- --- Name: ApiKeys PK_ApiKeys; Type: CONSTRAINT; Schema: authentication; Owner: jellyfin +-- Name: api_keys PK_ApiKeys; Type: CONSTRAINT; Schema: authentication; Owner: jellyfin -- -ALTER TABLE ONLY authentication."ApiKeys" - ADD CONSTRAINT "PK_ApiKeys" PRIMARY KEY ("Id"); +ALTER TABLE ONLY authentication.api_keys + ADD CONSTRAINT "PK_ApiKeys" PRIMARY KEY (id); -- --- Name: DeviceOptions PK_DeviceOptions; Type: CONSTRAINT; Schema: authentication; Owner: jellyfin +-- Name: device_options PK_DeviceOptions; Type: CONSTRAINT; Schema: authentication; Owner: jellyfin -- -ALTER TABLE ONLY authentication."DeviceOptions" - ADD CONSTRAINT "PK_DeviceOptions" PRIMARY KEY ("Id"); +ALTER TABLE ONLY authentication.device_options + ADD CONSTRAINT "PK_DeviceOptions" PRIMARY KEY (id); -- --- Name: Devices PK_Devices; Type: CONSTRAINT; Schema: authentication; Owner: jellyfin +-- Name: devices PK_Devices; Type: CONSTRAINT; Schema: authentication; Owner: jellyfin -- -ALTER TABLE ONLY authentication."Devices" - ADD CONSTRAINT "PK_Devices" PRIMARY KEY ("Id"); +ALTER TABLE ONLY authentication.devices + ADD CONSTRAINT "PK_Devices" PRIMARY KEY (id); -- --- Name: CustomItemDisplayPreferences PK_CustomItemDisplayPreferences; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- Name: custom_item_display_preferences PK_CustomItemDisplayPreferences; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE ONLY displaypreferences."CustomItemDisplayPreferences" - ADD CONSTRAINT "PK_CustomItemDisplayPreferences" PRIMARY KEY ("Id"); +ALTER TABLE ONLY displaypreferences.custom_item_display_preferences + ADD CONSTRAINT "PK_CustomItemDisplayPreferences" PRIMARY KEY (id); -- --- Name: DisplayPreferences PK_DisplayPreferences; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- Name: display_preferences PK_DisplayPreferences; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE ONLY displaypreferences."DisplayPreferences" - ADD CONSTRAINT "PK_DisplayPreferences" PRIMARY KEY ("Id"); +ALTER TABLE ONLY displaypreferences.display_preferences + ADD CONSTRAINT "PK_DisplayPreferences" PRIMARY KEY (id); -- --- Name: HomeSection PK_HomeSection; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- Name: home_sections PK_HomeSection; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE ONLY displaypreferences."HomeSection" - ADD CONSTRAINT "PK_HomeSection" PRIMARY KEY ("Id"); +ALTER TABLE ONLY displaypreferences.home_sections + ADD CONSTRAINT "PK_HomeSection" PRIMARY KEY (id); -- --- Name: ItemDisplayPreferences PK_ItemDisplayPreferences; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- Name: item_display_preferences PK_ItemDisplayPreferences; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE ONLY displaypreferences."ItemDisplayPreferences" - ADD CONSTRAINT "PK_ItemDisplayPreferences" PRIMARY KEY ("Id"); +ALTER TABLE ONLY displaypreferences.item_display_preferences + ADD CONSTRAINT "PK_ItemDisplayPreferences" PRIMARY KEY (id); -- --- Name: AncestorIds PK_AncestorIds; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: base_item_image_infos BaseItemImageInfos_pkey; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."AncestorIds" - ADD CONSTRAINT "PK_AncestorIds" PRIMARY KEY ("ItemId", "ParentItemId"); +ALTER TABLE ONLY library.base_item_image_infos + ADD CONSTRAINT "BaseItemImageInfos_pkey" PRIMARY KEY (id); -- --- Name: AttachmentStreamInfos PK_AttachmentStreamInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: ancestor_ids PK_AncestorIds; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."AttachmentStreamInfos" - ADD CONSTRAINT "PK_AttachmentStreamInfos" PRIMARY KEY ("ItemId", "Index"); +ALTER TABLE ONLY library.ancestor_ids + ADD CONSTRAINT "PK_AncestorIds" PRIMARY KEY (item_id, parent_item_id); -- --- Name: BaseItemMetadataFields PK_BaseItemMetadataFields; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: attachment_stream_infos PK_AttachmentStreamInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."BaseItemMetadataFields" - ADD CONSTRAINT "PK_BaseItemMetadataFields" PRIMARY KEY ("Id", "ItemId"); +ALTER TABLE ONLY library.attachment_stream_infos + ADD CONSTRAINT "PK_AttachmentStreamInfos" PRIMARY KEY (item_id, index); -- --- Name: BaseItemProviders PK_BaseItemProviders; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: audio_stream_details PK_AudioStreamDetails; Type: CONSTRAINT; Schema: library; Owner: postgres -- -ALTER TABLE ONLY library."BaseItemProviders" - ADD CONSTRAINT "PK_BaseItemProviders" PRIMARY KEY ("ItemId", "ProviderId"); +ALTER TABLE ONLY library.audio_stream_details + ADD CONSTRAINT "PK_AudioStreamDetails" PRIMARY KEY (item_id, stream_index); -- --- Name: BaseItemTrailerTypes PK_BaseItemTrailerTypes; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: base_item_audio_extras PK_BaseItemAudioExtras; Type: CONSTRAINT; Schema: library; Owner: postgres -- -ALTER TABLE ONLY library."BaseItemTrailerTypes" - ADD CONSTRAINT "PK_BaseItemTrailerTypes" PRIMARY KEY ("Id", "ItemId"); +ALTER TABLE ONLY library.base_item_audio_extras + ADD CONSTRAINT "PK_BaseItemAudioExtras" PRIMARY KEY (item_id); -- --- Name: BaseItems PK_BaseItems; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: base_item_live_tv_extras PK_BaseItemLiveTvExtras; Type: CONSTRAINT; Schema: library; Owner: postgres -- -ALTER TABLE ONLY library."BaseItems" - ADD CONSTRAINT "PK_BaseItems" PRIMARY KEY ("Id"); +ALTER TABLE ONLY library.base_item_live_tv_extras + ADD CONSTRAINT "PK_BaseItemLiveTvExtras" PRIMARY KEY (item_id); -- --- Name: Chapters PK_Chapters; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: base_item_metadata_fields PK_BaseItemMetadataFields; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."Chapters" - ADD CONSTRAINT "PK_Chapters" PRIMARY KEY ("ItemId", "ChapterIndex"); +ALTER TABLE ONLY library.base_item_metadata_fields + ADD CONSTRAINT "PK_BaseItemMetadataFields" PRIMARY KEY (id, item_id); -- --- Name: ImageInfos PK_ImageInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: base_item_providers PK_BaseItemProviders; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."ImageInfos" - ADD CONSTRAINT "PK_ImageInfos" PRIMARY KEY ("Id"); +ALTER TABLE ONLY library.base_item_providers + ADD CONSTRAINT "PK_BaseItemProviders" PRIMARY KEY (item_id, provider_id); -- --- Name: ItemValues PK_ItemValues; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: base_item_trailer_types PK_BaseItemTrailerTypes; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."ItemValues" - ADD CONSTRAINT "PK_ItemValues" PRIMARY KEY ("ItemValueId"); +ALTER TABLE ONLY library.base_item_trailer_types + ADD CONSTRAINT "PK_BaseItemTrailerTypes" PRIMARY KEY (id, item_id); -- --- Name: KeyframeData PK_KeyframeData; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: base_item_tv_extras PK_BaseItemTvExtras; Type: CONSTRAINT; Schema: library; Owner: postgres -- -ALTER TABLE ONLY library."KeyframeData" - ADD CONSTRAINT "PK_KeyframeData" PRIMARY KEY ("ItemId"); +ALTER TABLE ONLY library.base_item_tv_extras + ADD CONSTRAINT "PK_BaseItemTvExtras" PRIMARY KEY (item_id); -- --- Name: LibraryOptions PK_LibraryOptions; Type: CONSTRAINT; Schema: library; Owner: postgres +-- Name: base_items PK_BaseItems; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."LibraryOptions" - ADD CONSTRAINT "PK_LibraryOptions" PRIMARY KEY ("LibraryPath"); +ALTER TABLE ONLY library.base_items + ADD CONSTRAINT "PK_BaseItems" PRIMARY KEY (id); -- --- Name: MediaSegments PK_MediaSegments; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: chapters PK_Chapters; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."MediaSegments" - ADD CONSTRAINT "PK_MediaSegments" PRIMARY KEY ("Id"); +ALTER TABLE ONLY library.chapters + ADD CONSTRAINT "PK_Chapters" PRIMARY KEY (item_id, chapter_index); -- --- Name: Peoples PK_Peoples; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: image_infos PK_ImageInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."Peoples" - ADD CONSTRAINT "PK_Peoples" PRIMARY KEY ("Id"); +ALTER TABLE ONLY library.image_infos + ADD CONSTRAINT "PK_ImageInfos" PRIMARY KEY (id); -- --- Name: TrickplayInfos PK_TrickplayInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: item_values PK_ItemValues; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."TrickplayInfos" - ADD CONSTRAINT "PK_TrickplayInfos" PRIMARY KEY ("ItemId", "Width"); +ALTER TABLE ONLY library.item_values + ADD CONSTRAINT "PK_ItemValues" PRIMARY KEY (item_value_id); -- --- Name: UserData PK_UserData; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: keyframe_data PK_KeyframeData; Type: CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."UserData" - ADD CONSTRAINT "PK_UserData" PRIMARY KEY ("ItemId", "UserId", "CustomDataKey"); +ALTER TABLE ONLY library.keyframe_data + ADD CONSTRAINT "PK_KeyframeData" PRIMARY KEY (item_id); + + +-- +-- Name: library_options PK_LibraryOptions; Type: CONSTRAINT; Schema: library; Owner: postgres +-- + +ALTER TABLE ONLY library.library_options + ADD CONSTRAINT "PK_LibraryOptions" PRIMARY KEY (library_path); + + +-- +-- Name: media_segments PK_MediaSegments; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.media_segments + ADD CONSTRAINT "PK_MediaSegments" PRIMARY KEY (id); + + +-- +-- Name: media_stream_infos PK_MediaStreamInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.media_stream_infos + ADD CONSTRAINT "PK_MediaStreamInfos" PRIMARY KEY (item_id, stream_index); + + +-- +-- Name: peoples PK_Peoples; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.peoples + ADD CONSTRAINT "PK_Peoples" PRIMARY KEY (id); + + +-- +-- Name: trickplay_infos PK_TrickplayInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.trickplay_infos + ADD CONSTRAINT "PK_TrickplayInfos" PRIMARY KEY (item_id, width); + + +-- +-- Name: user_data PK_UserData; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.user_data + ADD CONSTRAINT "PK_UserData" PRIMARY KEY (item_id, user_id, custom_data_key); + + +-- +-- Name: video_stream_details PK_VideoStreamDetails; Type: CONSTRAINT; Schema: library; Owner: postgres +-- + +ALTER TABLE ONLY library.video_stream_details + ADD CONSTRAINT "PK_VideoStreamDetails" PRIMARY KEY (item_id, stream_index); + + +-- +-- Name: item_values_map pk_itemvaluesmap; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.item_values_map + ADD CONSTRAINT pk_itemvaluesmap PRIMARY KEY (item_value_id, item_id); + + +-- +-- Name: people_base_item_map pk_peoplebaseitemmap; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.people_base_item_map + ADD CONSTRAINT pk_peoplebaseitemmap PRIMARY KEY (item_id, people_id, role); -- @@ -1085,559 +1625,1191 @@ ALTER TABLE ONLY library."UserData" -- ALTER TABLE ONLY public."__EFMigrationsHistory" - ADD CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY ("MigrationId"); + ADD CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY (migration_id); -- --- Name: AccessSchedules PK_AccessSchedules; Type: CONSTRAINT; Schema: users; Owner: jellyfin +-- Name: __efmigrationshistory pk___efmigrationshistory; Type: CONSTRAINT; Schema: public; Owner: postgres -- -ALTER TABLE ONLY users."AccessSchedules" - ADD CONSTRAINT "PK_AccessSchedules" PRIMARY KEY ("Id"); +ALTER TABLE ONLY public.__efmigrationshistory + ADD CONSTRAINT pk___efmigrationshistory PRIMARY KEY (migrationid); -- --- Name: Permissions PK_Permissions; Type: CONSTRAINT; Schema: users; Owner: jellyfin +-- Name: access_schedules PK_AccessSchedules; Type: CONSTRAINT; Schema: users; Owner: jellyfin -- -ALTER TABLE ONLY users."Permissions" - ADD CONSTRAINT "PK_Permissions" PRIMARY KEY ("Id"); +ALTER TABLE ONLY users.access_schedules + ADD CONSTRAINT "PK_AccessSchedules" PRIMARY KEY (id); -- --- Name: Preferences PK_Preferences; Type: CONSTRAINT; Schema: users; Owner: jellyfin +-- Name: permissions PK_Permissions; Type: CONSTRAINT; Schema: users; Owner: jellyfin -- -ALTER TABLE ONLY users."Preferences" - ADD CONSTRAINT "PK_Preferences" PRIMARY KEY ("Id"); +ALTER TABLE ONLY users.permissions + ADD CONSTRAINT "PK_Permissions" PRIMARY KEY (id); -- --- Name: Users PK_Users; Type: CONSTRAINT; Schema: users; Owner: jellyfin +-- Name: preferences PK_Preferences; Type: CONSTRAINT; Schema: users; Owner: jellyfin -- -ALTER TABLE ONLY users."Users" - ADD CONSTRAINT "PK_Users" PRIMARY KEY ("Id"); +ALTER TABLE ONLY users.preferences + ADD CONSTRAINT "PK_Preferences" PRIMARY KEY (id); + + +-- +-- Name: users PK_Users; Type: CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users.users + ADD CONSTRAINT "PK_Users" PRIMARY KEY (id); -- -- Name: IX_ActivityLogs_DateCreated; Type: INDEX; Schema: activitylog; Owner: jellyfin -- -CREATE INDEX "IX_ActivityLogs_DateCreated" ON activitylog."ActivityLogs" USING btree ("DateCreated"); +CREATE INDEX "IX_ActivityLogs_DateCreated" ON activitylog.activity_logs USING btree (date_created); -- -- Name: idx_activitylogs_userid_datecreated; Type: INDEX; Schema: activitylog; Owner: jellyfin -- -CREATE INDEX idx_activitylogs_userid_datecreated ON activitylog."ActivityLogs" USING btree ("UserId", "DateCreated" DESC) WHERE ("UserId" IS NOT NULL); +CREATE INDEX idx_activitylogs_userid_datecreated ON activitylog.activity_logs USING btree (user_id, date_created DESC) WHERE (user_id IS NOT NULL); + + +-- +-- Name: ix_activitylogs_datecreated; Type: INDEX; Schema: activitylog; Owner: jellyfin +-- + +CREATE INDEX ix_activitylogs_datecreated ON activitylog.activity_logs USING btree (date_created); -- -- Name: IX_ApiKeys_AccessToken; Type: INDEX; Schema: authentication; Owner: jellyfin -- -CREATE UNIQUE INDEX "IX_ApiKeys_AccessToken" ON authentication."ApiKeys" USING btree ("AccessToken"); +CREATE UNIQUE INDEX "IX_ApiKeys_AccessToken" ON authentication.api_keys USING btree (access_token); -- -- Name: IX_DeviceOptions_DeviceId; Type: INDEX; Schema: authentication; Owner: jellyfin -- -CREATE UNIQUE INDEX "IX_DeviceOptions_DeviceId" ON authentication."DeviceOptions" USING btree ("DeviceId"); +CREATE UNIQUE INDEX "IX_DeviceOptions_DeviceId" ON authentication.device_options USING btree (device_id); -- -- Name: IX_Devices_AccessToken_DateLastActivity; Type: INDEX; Schema: authentication; Owner: jellyfin -- -CREATE INDEX "IX_Devices_AccessToken_DateLastActivity" ON authentication."Devices" USING btree ("AccessToken", "DateLastActivity"); +CREATE INDEX "IX_Devices_AccessToken_DateLastActivity" ON authentication.devices USING btree (access_token, date_last_activity); -- -- Name: IX_Devices_DeviceId; Type: INDEX; Schema: authentication; Owner: jellyfin -- -CREATE INDEX "IX_Devices_DeviceId" ON authentication."Devices" USING btree ("DeviceId"); +CREATE INDEX "IX_Devices_DeviceId" ON authentication.devices USING btree (device_id); -- -- Name: IX_Devices_DeviceId_DateLastActivity; Type: INDEX; Schema: authentication; Owner: jellyfin -- -CREATE INDEX "IX_Devices_DeviceId_DateLastActivity" ON authentication."Devices" USING btree ("DeviceId", "DateLastActivity"); +CREATE INDEX "IX_Devices_DeviceId_DateLastActivity" ON authentication.devices USING btree (device_id, date_last_activity); -- -- Name: IX_Devices_UserId_DeviceId; Type: INDEX; Schema: authentication; Owner: jellyfin -- -CREATE INDEX "IX_Devices_UserId_DeviceId" ON authentication."Devices" USING btree ("UserId", "DeviceId"); +CREATE INDEX "IX_Devices_UserId_DeviceId" ON authentication.devices USING btree (user_id, device_id); + + +-- +-- Name: ix_apikeys_accesstoken; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE UNIQUE INDEX ix_apikeys_accesstoken ON authentication.api_keys USING btree (access_token); + + +-- +-- Name: ix_deviceoptions_deviceid; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE UNIQUE INDEX ix_deviceoptions_deviceid ON authentication.device_options USING btree (device_id); + + +-- +-- Name: ix_devices_accesstoken_datelastactivity; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE INDEX ix_devices_accesstoken_datelastactivity ON authentication.devices USING btree (access_token, date_last_activity); + + +-- +-- Name: ix_devices_deviceid; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE INDEX ix_devices_deviceid ON authentication.devices USING btree (device_id); + + +-- +-- Name: ix_devices_deviceid_datelastactivity; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE INDEX ix_devices_deviceid_datelastactivity ON authentication.devices USING btree (device_id, date_last_activity); + + +-- +-- Name: ix_devices_userid_deviceid; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE INDEX ix_devices_userid_deviceid ON authentication.devices USING btree (user_id, device_id); -- -- Name: IX_CustomItemDisplayPreferences_UserId_ItemId_Client_Key; Type: INDEX; Schema: displaypreferences; Owner: jellyfin -- -CREATE UNIQUE INDEX "IX_CustomItemDisplayPreferences_UserId_ItemId_Client_Key" ON displaypreferences."CustomItemDisplayPreferences" USING btree ("UserId", "ItemId", "Client", "Key"); +CREATE UNIQUE INDEX "IX_CustomItemDisplayPreferences_UserId_ItemId_Client_Key" ON displaypreferences.custom_item_display_preferences USING btree (user_id, item_id, client, key); -- -- Name: IX_DisplayPreferences_UserId_ItemId_Client; Type: INDEX; Schema: displaypreferences; Owner: jellyfin -- -CREATE UNIQUE INDEX "IX_DisplayPreferences_UserId_ItemId_Client" ON displaypreferences."DisplayPreferences" USING btree ("UserId", "ItemId", "Client"); +CREATE UNIQUE INDEX "IX_DisplayPreferences_UserId_ItemId_Client" ON displaypreferences.display_preferences USING btree (user_id, item_id, client); -- -- Name: IX_HomeSection_DisplayPreferencesId; Type: INDEX; Schema: displaypreferences; Owner: jellyfin -- -CREATE INDEX "IX_HomeSection_DisplayPreferencesId" ON displaypreferences."HomeSection" USING btree ("DisplayPreferencesId"); +CREATE INDEX "IX_HomeSection_DisplayPreferencesId" ON displaypreferences.home_sections USING btree (display_preferences_id); -- -- Name: IX_ItemDisplayPreferences_UserId; Type: INDEX; Schema: displaypreferences; Owner: jellyfin -- -CREATE INDEX "IX_ItemDisplayPreferences_UserId" ON displaypreferences."ItemDisplayPreferences" USING btree ("UserId"); +CREATE INDEX "IX_ItemDisplayPreferences_UserId" ON displaypreferences.item_display_preferences USING btree (user_id); + + +-- +-- Name: ix_displaypreferences_userid_itemid_client; Type: INDEX; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE UNIQUE INDEX ix_displaypreferences_userid_itemid_client ON displaypreferences.display_preferences USING btree (user_id, item_id, client); + + +-- +-- Name: ix_homesection_displaypreferencesid; Type: INDEX; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE INDEX ix_homesection_displaypreferencesid ON displaypreferences.home_sections USING btree (display_preferences_id); + + +-- +-- Name: ix_itemdisplaypreferences_userid; Type: INDEX; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE INDEX ix_itemdisplaypreferences_userid ON displaypreferences.item_display_preferences USING btree (user_id); -- -- Name: IX_BaseItemImageInfos_ItemId; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItemImageInfos_ItemId" ON library."BaseItemImageInfos" USING btree ("ItemId"); +CREATE INDEX "IX_BaseItemImageInfos_ItemId" ON library.base_item_image_infos USING btree (item_id); + + +-- +-- Name: IX_BaseItemLiveTvExtras_EndDate; Type: INDEX; Schema: library; Owner: postgres +-- + +CREATE INDEX "IX_BaseItemLiveTvExtras_EndDate" ON library.base_item_live_tv_extras USING btree (end_date); + + +-- +-- Name: IX_BaseItemLiveTvExtras_StartDate; Type: INDEX; Schema: library; Owner: postgres +-- + +CREATE INDEX "IX_BaseItemLiveTvExtras_StartDate" ON library.base_item_live_tv_extras USING btree (start_date); -- -- Name: IX_BaseItemMetadataFields_ItemId; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItemMetadataFields_ItemId" ON library."BaseItemMetadataFields" USING btree ("ItemId"); +CREATE INDEX "IX_BaseItemMetadataFields_ItemId" ON library.base_item_metadata_fields USING btree (item_id); -- -- Name: IX_BaseItemTrailerTypes_ItemId; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItemTrailerTypes_ItemId" ON library."BaseItemTrailerTypes" USING btree ("ItemId"); +CREATE INDEX "IX_BaseItemTrailerTypes_ItemId" ON library.base_item_trailer_types USING btree (item_id); + + +-- +-- Name: IX_BaseItemTvExtras_SeriesId; Type: INDEX; Schema: library; Owner: postgres +-- + +CREATE INDEX "IX_BaseItemTvExtras_SeriesId" ON library.base_item_tv_extras USING btree (series_id); + + +-- +-- Name: IX_BaseItemTvExtras_SeriesPresentationUniqueKey; Type: INDEX; Schema: library; Owner: postgres +-- + +CREATE INDEX "IX_BaseItemTvExtras_SeriesPresentationUniqueKey" ON library.base_item_tv_extras USING btree (series_presentation_unique_key); -- -- Name: IX_BaseItems_Id_Type_IsFolder_IsVirtualItem; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItems_Id_Type_IsFolder_IsVirtualItem" ON library."BaseItems" USING btree ("Id", "Type", "IsFolder", "IsVirtualItem"); +CREATE INDEX "IX_BaseItems_Id_Type_IsFolder_IsVirtualItem" ON library.base_items USING btree (id, type, is_folder, is_virtual_item); -- -- Name: IX_BaseItems_ParentId; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItems_ParentId" ON library."BaseItems" USING btree ("ParentId"); - - --- --- Name: IX_BaseItems_Type_SeriesPresentationUniqueKey_IsFolder_IsVirtu~; Type: INDEX; Schema: library; Owner: jellyfin --- - -CREATE INDEX "IX_BaseItems_Type_SeriesPresentationUniqueKey_IsFolder_IsVirtu~" ON library."BaseItems" USING btree ("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - --- --- Name: IX_BaseItems_Type_SeriesPresentationUniqueKey_PresentationUniq~; Type: INDEX; Schema: library; Owner: jellyfin --- - -CREATE INDEX "IX_BaseItems_Type_SeriesPresentationUniqueKey_PresentationUniq~" ON library."BaseItems" USING btree ("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); +CREATE INDEX "IX_BaseItems_ParentId" ON library.base_items USING btree (parent_id); -- -- Name: IX_BaseItems_Type_TopParentId_Id; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_BaseItems_Type_TopParentId_Id" ON library."BaseItems" USING btree ("Type", "TopParentId", "Id"); - - --- --- Name: IX_BaseItems_Type_TopParentId_StartDate; Type: INDEX; Schema: library; Owner: jellyfin --- - -CREATE INDEX "IX_BaseItems_Type_TopParentId_StartDate" ON library."BaseItems" USING btree ("Type", "TopParentId", "StartDate"); +CREATE INDEX "IX_BaseItems_Type_TopParentId_Id" ON library.base_items USING btree (type, top_parent_id, id); -- -- Name: IX_ImageInfos_UserId; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE UNIQUE INDEX "IX_ImageInfos_UserId" ON library."ImageInfos" USING btree ("UserId"); - - --- --- Name: IX_ItemValuesMap_ItemId; Type: INDEX; Schema: library; Owner: jellyfin --- - -CREATE INDEX "IX_ItemValuesMap_ItemId" ON library."ItemValuesMap" USING btree ("ItemId"); +CREATE UNIQUE INDEX "IX_ImageInfos_UserId" ON library.image_infos USING btree (user_id); -- -- Name: IX_ItemValues_Type_CleanValue; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_ItemValues_Type_CleanValue" ON library."ItemValues" USING btree ("Type", "CleanValue"); +CREATE INDEX "IX_ItemValues_Type_CleanValue" ON library.item_values USING btree (type, clean_value); -- -- Name: IX_ItemValues_Type_Value; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE UNIQUE INDEX "IX_ItemValues_Type_Value" ON library."ItemValues" USING btree ("Type", "Value"); +CREATE UNIQUE INDEX "IX_ItemValues_Type_Value" ON library.item_values USING btree (type, value); -- -- Name: IX_LibraryOptions_DateModified; Type: INDEX; Schema: library; Owner: postgres -- -CREATE INDEX "IX_LibraryOptions_DateModified" ON library."LibraryOptions" USING btree ("DateModified" DESC); +CREATE INDEX "IX_LibraryOptions_DateModified" ON library.library_options USING btree (date_modified DESC); -- -- Name: IX_UserData_ItemId_UserId_IsFavorite; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_UserData_ItemId_UserId_IsFavorite" ON library."UserData" USING btree ("ItemId", "UserId", "IsFavorite"); +CREATE INDEX "IX_UserData_ItemId_UserId_IsFavorite" ON library.user_data USING btree (item_id, user_id, is_favorite); -- -- Name: IX_UserData_ItemId_UserId_LastPlayedDate; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_UserData_ItemId_UserId_LastPlayedDate" ON library."UserData" USING btree ("ItemId", "UserId", "LastPlayedDate"); +CREATE INDEX "IX_UserData_ItemId_UserId_LastPlayedDate" ON library.user_data USING btree (item_id, user_id, last_played_date); -- -- Name: IX_UserData_ItemId_UserId_PlaybackPositionTicks; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_UserData_ItemId_UserId_PlaybackPositionTicks" ON library."UserData" USING btree ("ItemId", "UserId", "PlaybackPositionTicks"); +CREATE INDEX "IX_UserData_ItemId_UserId_PlaybackPositionTicks" ON library.user_data USING btree (item_id, user_id, playback_position_ticks); -- -- Name: IX_UserData_ItemId_UserId_Played; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX "IX_UserData_ItemId_UserId_Played" ON library."UserData" USING btree ("ItemId", "UserId", "Played"); +CREATE INDEX "IX_UserData_ItemId_UserId_Played" ON library.user_data USING btree (item_id, user_id, played); -- --- Name: baseitems_seriespresentationuniquekey_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- Name: baseitemproviders_providerid_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX baseitems_seriespresentationuniquekey_idx ON library."BaseItems" USING btree ("SeriesPresentationUniqueKey", "IndexNumber", "ParentIndexNumber"); +CREATE INDEX baseitemproviders_providerid_idx ON library.base_item_providers USING btree (provider_id, item_id); -- --- Name: idx_baseitems_folder_virtual_media_sort; Type: INDEX; Schema: library; Owner: jellyfin +-- Name: baseitemproviders_providervalue_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX idx_baseitems_folder_virtual_media_sort ON library."BaseItems" USING btree ("IsFolder", "IsVirtualItem", "MediaType", "SortName") INCLUDE ("Id", "PresentationUniqueKey", "SeriesPresentationUniqueKey"); +CREATE INDEX baseitemproviders_providervalue_idx ON library.base_item_providers USING btree (provider_value, provider_id); -- --- Name: idx_baseitems_type_virtual_media_sort; Type: INDEX; Schema: library; Owner: jellyfin +-- Name: baseitems_communityrating_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX idx_baseitems_type_virtual_media_sort ON library."BaseItems" USING btree ("Type", "IsVirtualItem", "MediaType", "SortName") INCLUDE ("Id", "PresentationUniqueKey", "SeriesPresentationUniqueKey"); +CREATE INDEX baseitems_communityrating_idx ON library.base_items USING btree (community_rating DESC); + + +-- +-- Name: baseitems_datecreated_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_datecreated_idx ON library.base_items USING btree (date_created DESC); + + +-- +-- Name: baseitems_datemodified_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_datemodified_idx ON library.base_items USING btree (date_modified DESC); + + +-- +-- Name: baseitems_premieredate_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_premieredate_idx ON library.base_items USING btree (premiere_date DESC); + + +-- +-- Name: baseitems_productionyear_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_productionyear_idx ON library.base_items USING btree (production_year DESC); + + +-- +-- Name: baseitems_sortname_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_sortname_idx ON library.base_items USING btree (sort_name); + + +-- +-- Name: baseitems_topparentid_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX baseitems_topparentid_idx ON library.base_items USING btree (top_parent_id, type); + + +-- +-- Name: idx_baseitems_datecreated_filtered; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_baseitems_datecreated_filtered ON library.base_items USING btree (date_created DESC, type, is_virtual_item) WHERE ((date_created IS NOT NULL) AND (is_virtual_item = false)); + + +-- +-- Name: idx_baseitems_presentationuniquekey_episodes; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_baseitems_presentationuniquekey_episodes ON library.base_items USING btree (presentation_unique_key, top_parent_id, is_virtual_item) WHERE ((type = 'MediaBrowser.Controller.Entities.TV.Episode'::text) AND (presentation_unique_key IS NOT NULL)); + + +-- +-- Name: idx_baseitems_topparentid_isfolder; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_baseitems_topparentid_isfolder ON library.base_items USING btree (top_parent_id, is_folder, is_virtual_item) WHERE (top_parent_id IS NOT NULL); + + +-- +-- Name: idx_baseitems_type_isvirtualitem_topparentid; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_baseitems_type_isvirtualitem_topparentid ON library.base_items USING btree (type, is_virtual_item, top_parent_id) WHERE (is_virtual_item = false); -- -- Name: idx_itemvalues_cleanvalue; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX idx_itemvalues_cleanvalue ON library."ItemValues" USING btree ("CleanValue") WHERE ("CleanValue" IS NOT NULL); +CREATE INDEX idx_itemvalues_cleanvalue ON library.item_values USING btree (clean_value) WHERE (clean_value IS NOT NULL); -- -- Name: idx_itemvalues_id_cleanvalue; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX idx_itemvalues_id_cleanvalue ON library."ItemValues" USING btree ("ItemValueId", "CleanValue"); +CREATE INDEX idx_itemvalues_id_cleanvalue ON library.item_values USING btree (item_value_id, clean_value); -- -- Name: idx_itemvalues_type_value_expr; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX idx_itemvalues_type_value_expr ON library."ItemValues" USING btree (((("Type")::text || "Value"))); +CREATE INDEX idx_itemvalues_type_value_expr ON library.item_values USING btree ((((type)::text || value))); -- -- Name: idx_itemvalues_value; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX idx_itemvalues_value ON library."ItemValues" USING btree ("Value") WHERE ("Value" IS NOT NULL); +CREATE INDEX idx_itemvalues_value ON library.item_values USING btree (value) WHERE (value IS NOT NULL); -- -- Name: idx_itemvaluesmap_itemvalueid_itemid; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX idx_itemvaluesmap_itemvalueid_itemid ON library."ItemValuesMap" USING btree ("ItemValueId", "ItemId"); +CREATE INDEX idx_itemvaluesmap_itemvalueid_itemid ON library.item_values_map USING btree (item_value_id, item_id); + + +-- +-- Name: ix_ancestorids_parentitemid; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_ancestorids_parentitemid ON library.ancestor_ids USING btree (parent_item_id); + + +-- +-- Name: ix_baseitemimageinfos_itemid; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_baseitemimageinfos_itemid ON library.base_item_image_infos USING btree (item_id); + + +-- +-- Name: ix_baseitemmetadatafields_itemid; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_baseitemmetadatafields_itemid ON library.base_item_metadata_fields USING btree (item_id); + + +-- +-- Name: ix_baseitemproviders_providerid_providervalue_itemid; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_baseitemproviders_providerid_providervalue_itemid ON library.base_item_providers USING btree (provider_id, provider_value, item_id); + + +-- +-- Name: ix_baseitems_id_type_isfolder_isvirtualitem; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_baseitems_id_type_isfolder_isvirtualitem ON library.base_items USING btree (id, type, is_folder, is_virtual_item); + + +-- +-- Name: ix_baseitems_path; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_baseitems_path ON library.base_items USING btree (path); + + +-- +-- Name: ix_baseitems_presentationuniquekey; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_baseitems_presentationuniquekey ON library.base_items USING btree (presentation_unique_key); + + +-- +-- Name: ix_baseitems_topparentid_id; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_baseitems_topparentid_id ON library.base_items USING btree (top_parent_id, id); + + +-- +-- Name: ix_baseitems_type_topparentid_id; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_baseitems_type_topparentid_id ON library.base_items USING btree (type, top_parent_id, id); + + +-- +-- Name: ix_baseitems_type_topparentid_presentationuniquekey; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_baseitems_type_topparentid_presentationuniquekey ON library.base_items USING btree (type, top_parent_id, presentation_unique_key); + + +-- +-- Name: ix_baseitemtrailertypes_itemid; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_baseitemtrailertypes_itemid ON library.base_item_trailer_types USING btree (item_id); + + +-- +-- Name: ix_imageinfos_userid; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE UNIQUE INDEX ix_imageinfos_userid ON library.image_infos USING btree (user_id); + + +-- +-- Name: ix_itemvalues_type_cleanvalue; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_itemvalues_type_cleanvalue ON library.item_values USING btree (type, clean_value); + + +-- +-- Name: ix_itemvalues_type_value; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE UNIQUE INDEX ix_itemvalues_type_value ON library.item_values USING btree (type, value); + + +-- +-- Name: ix_itemvaluesmap_itemid; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_itemvaluesmap_itemid ON library.item_values_map USING btree (item_id); + + +-- +-- Name: ix_mediastreaminfos_streamindex; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_mediastreaminfos_streamindex ON library.media_stream_infos USING btree (stream_index); + + +-- +-- Name: ix_mediastreaminfos_streamindex_streamtype; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_mediastreaminfos_streamindex_streamtype ON library.media_stream_infos USING btree (stream_index, stream_type); + + +-- +-- Name: ix_mediastreaminfos_streamindex_streamtype_language; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_mediastreaminfos_streamindex_streamtype_language ON library.media_stream_infos USING btree (stream_index, stream_type, language); + + +-- +-- Name: ix_mediastreaminfos_streamtype; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_mediastreaminfos_streamtype ON library.media_stream_infos USING btree (stream_type); + + +-- +-- Name: ix_peoplebaseitemmap_itemid_listorder; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_peoplebaseitemmap_itemid_listorder ON library.people_base_item_map USING btree (item_id, list_order); + + +-- +-- Name: ix_peoplebaseitemmap_itemid_sortorder; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_peoplebaseitemmap_itemid_sortorder ON library.people_base_item_map USING btree (item_id, sort_order); + + +-- +-- Name: ix_peoplebaseitemmap_peopleid; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_peoplebaseitemmap_peopleid ON library.people_base_item_map USING btree (people_id); + + +-- +-- Name: ix_peoples_name; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_peoples_name ON library.peoples USING btree (name); + + +-- +-- Name: ix_userdata_itemid_userid_isfavorite; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_userdata_itemid_userid_isfavorite ON library.user_data USING btree (item_id, user_id, is_favorite); + + +-- +-- Name: ix_userdata_itemid_userid_lastplayeddate; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_userdata_itemid_userid_lastplayeddate ON library.user_data USING btree (item_id, user_id, last_played_date); + + +-- +-- Name: ix_userdata_itemid_userid_playbackpositionticks; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_userdata_itemid_userid_playbackpositionticks ON library.user_data USING btree (item_id, user_id, playback_position_ticks); + + +-- +-- Name: ix_userdata_itemid_userid_played; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_userdata_itemid_userid_played ON library.user_data USING btree (item_id, user_id, played); + + +-- +-- Name: ix_userdata_userid; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX ix_userdata_userid ON library.user_data USING btree (user_id); + + +-- +-- Name: mediastreaminfos_codec_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX mediastreaminfos_codec_idx ON library.media_stream_infos USING btree (codec); -- -- Name: mediastreaminfos_itemid_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX mediastreaminfos_itemid_idx ON library."MediaStreamInfos" USING btree ("ItemId", "StreamType"); +CREATE INDEX mediastreaminfos_itemid_idx ON library.media_stream_infos USING btree (item_id, stream_type); -- -- Name: peoplebaseitemmap_itemid_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX peoplebaseitemmap_itemid_idx ON library."PeopleBaseItemMap" USING btree ("ItemId", "PeopleId"); +CREATE INDEX peoplebaseitemmap_itemid_idx ON library.people_base_item_map USING btree (item_id, people_id); -- -- Name: peoplebaseitemmap_peopleid_idx; Type: INDEX; Schema: library; Owner: jellyfin -- -CREATE INDEX peoplebaseitemmap_peopleid_idx ON library."PeopleBaseItemMap" USING btree ("PeopleId", "ItemId"); +CREATE INDEX peoplebaseitemmap_peopleid_idx ON library.people_base_item_map USING btree (people_id, item_id); + + +-- +-- Name: userdata_lastplayeddate_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX userdata_lastplayeddate_idx ON library.user_data USING btree (last_played_date DESC); + + +-- +-- Name: userdata_userid_isfavorite_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX userdata_userid_isfavorite_idx ON library.user_data USING btree (user_id, is_favorite); + + +-- +-- Name: userdata_userid_played_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX userdata_userid_played_idx ON library.user_data USING btree (user_id, played); -- -- Name: IX_AccessSchedules_UserId; Type: INDEX; Schema: users; Owner: jellyfin -- -CREATE INDEX "IX_AccessSchedules_UserId" ON users."AccessSchedules" USING btree ("UserId"); +CREATE INDEX "IX_AccessSchedules_UserId" ON users.access_schedules USING btree (user_id); -- -- Name: IX_Permissions_UserId_Kind; Type: INDEX; Schema: users; Owner: jellyfin -- -CREATE UNIQUE INDEX "IX_Permissions_UserId_Kind" ON users."Permissions" USING btree ("UserId", "Kind") WHERE ("UserId" IS NOT NULL); +CREATE UNIQUE INDEX "IX_Permissions_UserId_Kind" ON users.permissions USING btree (user_id, kind) WHERE (user_id IS NOT NULL); -- -- Name: IX_Preferences_UserId_Kind; Type: INDEX; Schema: users; Owner: jellyfin -- -CREATE UNIQUE INDEX "IX_Preferences_UserId_Kind" ON users."Preferences" USING btree ("UserId", "Kind") WHERE ("UserId" IS NOT NULL); +CREATE UNIQUE INDEX "IX_Preferences_UserId_Kind" ON users.preferences USING btree (user_id, kind) WHERE (user_id IS NOT NULL); -- -- Name: IX_Users_Username; Type: INDEX; Schema: users; Owner: jellyfin -- -CREATE UNIQUE INDEX "IX_Users_Username" ON users."Users" USING btree ("Username"); +CREATE UNIQUE INDEX "IX_Users_Username" ON users.users USING btree (username); -- --- Name: Devices FK_Devices_Users_UserId; Type: FK CONSTRAINT; Schema: authentication; Owner: jellyfin +-- Name: ix_accessschedules_userid; Type: INDEX; Schema: users; Owner: jellyfin -- -ALTER TABLE ONLY authentication."Devices" - ADD CONSTRAINT "FK_Devices_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; +CREATE INDEX ix_accessschedules_userid ON users.access_schedules USING btree (user_id); -- --- Name: DisplayPreferences FK_DisplayPreferences_Users_UserId; Type: FK CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- Name: ix_permissions_userid_kind; Type: INDEX; Schema: users; Owner: jellyfin -- -ALTER TABLE ONLY displaypreferences."DisplayPreferences" - ADD CONSTRAINT "FK_DisplayPreferences_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; +CREATE UNIQUE INDEX ix_permissions_userid_kind ON users.permissions USING btree (user_id, kind) WHERE (user_id IS NOT NULL); -- --- Name: HomeSection FK_HomeSection_DisplayPreferences_DisplayPreferencesId; Type: FK CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- Name: ix_preferences_userid_kind; Type: INDEX; Schema: users; Owner: jellyfin -- -ALTER TABLE ONLY displaypreferences."HomeSection" - ADD CONSTRAINT "FK_HomeSection_DisplayPreferences_DisplayPreferencesId" FOREIGN KEY ("DisplayPreferencesId") REFERENCES displaypreferences."DisplayPreferences"("Id") ON DELETE CASCADE; +CREATE UNIQUE INDEX ix_preferences_userid_kind ON users.preferences USING btree (user_id, kind) WHERE (user_id IS NOT NULL); -- --- Name: ItemDisplayPreferences FK_ItemDisplayPreferences_Users_UserId; Type: FK CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- Name: ix_users_username; Type: INDEX; Schema: users; Owner: jellyfin -- -ALTER TABLE ONLY displaypreferences."ItemDisplayPreferences" - ADD CONSTRAINT "FK_ItemDisplayPreferences_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; +CREATE UNIQUE INDEX ix_users_username ON users.users USING btree (username); -- --- Name: AncestorIds FK_AncestorIds_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: devices FK_Devices_Users_UserId; Type: FK CONSTRAINT; Schema: authentication; Owner: jellyfin -- -ALTER TABLE ONLY library."AncestorIds" - ADD CONSTRAINT "FK_AncestorIds_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY authentication.devices + ADD CONSTRAINT "FK_Devices_Users_UserId" FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; -- --- Name: AncestorIds FK_AncestorIds_BaseItems_ParentItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: devices fk_devices_users_userid; Type: FK CONSTRAINT; Schema: authentication; Owner: jellyfin -- -ALTER TABLE ONLY library."AncestorIds" - ADD CONSTRAINT "FK_AncestorIds_BaseItems_ParentItemId" FOREIGN KEY ("ParentItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY authentication.devices + ADD CONSTRAINT fk_devices_users_userid FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; -- --- Name: AttachmentStreamInfos FK_AttachmentStreamInfos_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: display_preferences FK_DisplayPreferences_Users_UserId; Type: FK CONSTRAINT; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE ONLY library."AttachmentStreamInfos" - ADD CONSTRAINT "FK_AttachmentStreamInfos_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY displaypreferences.display_preferences + ADD CONSTRAINT "FK_DisplayPreferences_Users_UserId" FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; -- --- Name: BaseItemImageInfos FK_BaseItemImageInfos_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: home_sections FK_HomeSection_DisplayPreferences_DisplayPreferencesId; Type: FK CONSTRAINT; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE ONLY library."BaseItemImageInfos" - ADD CONSTRAINT "FK_BaseItemImageInfos_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY displaypreferences.home_sections + ADD CONSTRAINT "FK_HomeSection_DisplayPreferences_DisplayPreferencesId" FOREIGN KEY (display_preferences_id) REFERENCES displaypreferences.display_preferences(id) ON DELETE CASCADE; -- --- Name: BaseItemMetadataFields FK_BaseItemMetadataFields_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: item_display_preferences FK_ItemDisplayPreferences_Users_UserId; Type: FK CONSTRAINT; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE ONLY library."BaseItemMetadataFields" - ADD CONSTRAINT "FK_BaseItemMetadataFields_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY displaypreferences.item_display_preferences + ADD CONSTRAINT "FK_ItemDisplayPreferences_Users_UserId" FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; -- --- Name: BaseItemProviders FK_BaseItemProviders_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: display_preferences fk_displaypreferences_users_userid; Type: FK CONSTRAINT; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE ONLY library."BaseItemProviders" - ADD CONSTRAINT "FK_BaseItemProviders_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY displaypreferences.display_preferences + ADD CONSTRAINT fk_displaypreferences_users_userid FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; -- --- Name: BaseItemTrailerTypes FK_BaseItemTrailerTypes_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: home_sections fk_homesection_displaypreferences_displaypreferencesid; Type: FK CONSTRAINT; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE ONLY library."BaseItemTrailerTypes" - ADD CONSTRAINT "FK_BaseItemTrailerTypes_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY displaypreferences.home_sections + ADD CONSTRAINT fk_homesection_displaypreferences_displaypreferencesid FOREIGN KEY (display_preferences_id) REFERENCES displaypreferences.display_preferences(id) ON DELETE CASCADE; -- --- Name: BaseItems FK_BaseItems_BaseItems_ParentId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: item_display_preferences fk_itemdisplaypreferences_users_userid; Type: FK CONSTRAINT; Schema: displaypreferences; Owner: jellyfin -- -ALTER TABLE ONLY library."BaseItems" - ADD CONSTRAINT "FK_BaseItems_BaseItems_ParentId" FOREIGN KEY ("ParentId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY displaypreferences.item_display_preferences + ADD CONSTRAINT fk_itemdisplaypreferences_users_userid FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; -- --- Name: Chapters FK_Chapters_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: ancestor_ids FK_AncestorIds_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."Chapters" - ADD CONSTRAINT "FK_Chapters_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.ancestor_ids + ADD CONSTRAINT "FK_AncestorIds_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- --- Name: ImageInfos FK_ImageInfos_Users_UserId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: ancestor_ids FK_AncestorIds_BaseItems_ParentItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."ImageInfos" - ADD CONSTRAINT "FK_ImageInfos_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.ancestor_ids + ADD CONSTRAINT "FK_AncestorIds_BaseItems_ParentItemId" FOREIGN KEY (parent_item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- --- Name: ItemValuesMap FK_ItemValuesMap_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: attachment_stream_infos FK_AttachmentStreamInfos_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."ItemValuesMap" - ADD CONSTRAINT "FK_ItemValuesMap_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.attachment_stream_infos + ADD CONSTRAINT "FK_AttachmentStreamInfos_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- --- Name: ItemValuesMap FK_ItemValuesMap_ItemValues_ItemValueId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: audio_stream_details FK_AudioStreamDetails_MediaStreamInfos_ItemId_StreamIndex; Type: FK CONSTRAINT; Schema: library; Owner: postgres -- -ALTER TABLE ONLY library."ItemValuesMap" - ADD CONSTRAINT "FK_ItemValuesMap_ItemValues_ItemValueId" FOREIGN KEY ("ItemValueId") REFERENCES library."ItemValues"("ItemValueId") ON DELETE CASCADE; +ALTER TABLE ONLY library.audio_stream_details + ADD CONSTRAINT "FK_AudioStreamDetails_MediaStreamInfos_ItemId_StreamIndex" FOREIGN KEY (item_id, stream_index) REFERENCES library.media_stream_infos(item_id, stream_index) ON DELETE CASCADE; -- --- Name: KeyframeData FK_KeyframeData_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: base_item_audio_extras FK_BaseItemAudioExtras_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: postgres -- -ALTER TABLE ONLY library."KeyframeData" - ADD CONSTRAINT "FK_KeyframeData_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.base_item_audio_extras + ADD CONSTRAINT "FK_BaseItemAudioExtras_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- --- Name: MediaStreamInfos FK_MediaStreamInfos_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: base_item_image_infos FK_BaseItemImageInfos_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."MediaStreamInfos" - ADD CONSTRAINT "FK_MediaStreamInfos_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.base_item_image_infos + ADD CONSTRAINT "FK_BaseItemImageInfos_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- --- Name: PeopleBaseItemMap FK_PeopleBaseItemMap_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: base_item_live_tv_extras FK_BaseItemLiveTvExtras_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: postgres -- -ALTER TABLE ONLY library."PeopleBaseItemMap" - ADD CONSTRAINT "FK_PeopleBaseItemMap_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.base_item_live_tv_extras + ADD CONSTRAINT "FK_BaseItemLiveTvExtras_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- --- Name: PeopleBaseItemMap FK_PeopleBaseItemMap_Peoples_PeopleId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: base_item_metadata_fields FK_BaseItemMetadataFields_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."PeopleBaseItemMap" - ADD CONSTRAINT "FK_PeopleBaseItemMap_Peoples_PeopleId" FOREIGN KEY ("PeopleId") REFERENCES library."Peoples"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.base_item_metadata_fields + ADD CONSTRAINT "FK_BaseItemMetadataFields_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- --- Name: UserData FK_UserData_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: base_item_providers FK_BaseItemProviders_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."UserData" - ADD CONSTRAINT "FK_UserData_BaseItems_ItemId" FOREIGN KEY ("ItemId") REFERENCES library."BaseItems"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.base_item_providers + ADD CONSTRAINT "FK_BaseItemProviders_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- --- Name: UserData FK_UserData_Users_UserId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- Name: base_item_trailer_types FK_BaseItemTrailerTypes_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY library."UserData" - ADD CONSTRAINT "FK_UserData_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.base_item_trailer_types + ADD CONSTRAINT "FK_BaseItemTrailerTypes_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- --- Name: AccessSchedules FK_AccessSchedules_Users_UserId; Type: FK CONSTRAINT; Schema: users; Owner: jellyfin +-- Name: base_item_tv_extras FK_BaseItemTvExtras_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: postgres -- -ALTER TABLE ONLY users."AccessSchedules" - ADD CONSTRAINT "FK_AccessSchedules_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.base_item_tv_extras + ADD CONSTRAINT "FK_BaseItemTvExtras_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- --- Name: Permissions FK_Permissions_Users_UserId; Type: FK CONSTRAINT; Schema: users; Owner: jellyfin +-- Name: base_items FK_BaseItems_BaseItems_ParentId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY users."Permissions" - ADD CONSTRAINT "FK_Permissions_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.base_items + ADD CONSTRAINT "FK_BaseItems_BaseItems_ParentId" FOREIGN KEY (parent_id) REFERENCES library.base_items(id) ON DELETE CASCADE; -- --- Name: Preferences FK_Preferences_Users_UserId; Type: FK CONSTRAINT; Schema: users; Owner: jellyfin +-- Name: chapters FK_Chapters_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin -- -ALTER TABLE ONLY users."Preferences" - ADD CONSTRAINT "FK_Preferences_Users_UserId" FOREIGN KEY ("UserId") REFERENCES users."Users"("Id") ON DELETE CASCADE; +ALTER TABLE ONLY library.chapters + ADD CONSTRAINT "FK_Chapters_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: image_infos FK_ImageInfos_Users_UserId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.image_infos + ADD CONSTRAINT "FK_ImageInfos_Users_UserId" FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; + + +-- +-- Name: item_values_map FK_ItemValuesMap_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.item_values_map + ADD CONSTRAINT "FK_ItemValuesMap_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: item_values_map FK_ItemValuesMap_ItemValues_ItemValueId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.item_values_map + ADD CONSTRAINT "FK_ItemValuesMap_ItemValues_ItemValueId" FOREIGN KEY (item_value_id) REFERENCES library.item_values(item_value_id) ON DELETE CASCADE; + + +-- +-- Name: keyframe_data FK_KeyframeData_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.keyframe_data + ADD CONSTRAINT "FK_KeyframeData_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: media_stream_infos FK_MediaStreamInfos_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.media_stream_infos + ADD CONSTRAINT "FK_MediaStreamInfos_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: people_base_item_map FK_PeopleBaseItemMap_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.people_base_item_map + ADD CONSTRAINT "FK_PeopleBaseItemMap_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: people_base_item_map FK_PeopleBaseItemMap_Peoples_PeopleId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.people_base_item_map + ADD CONSTRAINT "FK_PeopleBaseItemMap_Peoples_PeopleId" FOREIGN KEY (people_id) REFERENCES library.peoples(id) ON DELETE CASCADE; + + +-- +-- Name: user_data FK_UserData_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.user_data + ADD CONSTRAINT "FK_UserData_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: user_data FK_UserData_Users_UserId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.user_data + ADD CONSTRAINT "FK_UserData_Users_UserId" FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; + + +-- +-- Name: video_stream_details FK_VideoStreamDetails_MediaStreamInfos_ItemId_StreamIndex; Type: FK CONSTRAINT; Schema: library; Owner: postgres +-- + +ALTER TABLE ONLY library.video_stream_details + ADD CONSTRAINT "FK_VideoStreamDetails_MediaStreamInfos_ItemId_StreamIndex" FOREIGN KEY (item_id, stream_index) REFERENCES library.media_stream_infos(item_id, stream_index) ON DELETE CASCADE; + + +-- +-- Name: ancestor_ids fk_ancestorids_baseitems_itemid; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.ancestor_ids + ADD CONSTRAINT fk_ancestorids_baseitems_itemid FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: ancestor_ids fk_ancestorids_baseitems_parentitemid; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.ancestor_ids + ADD CONSTRAINT fk_ancestorids_baseitems_parentitemid FOREIGN KEY (parent_item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: attachment_stream_infos fk_attachmentstreaminfos_baseitems_itemid; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.attachment_stream_infos + ADD CONSTRAINT fk_attachmentstreaminfos_baseitems_itemid FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: base_item_image_infos fk_baseitemimageinfos_baseitems_itemid; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.base_item_image_infos + ADD CONSTRAINT fk_baseitemimageinfos_baseitems_itemid FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: base_item_metadata_fields fk_baseitemmetadatafields_baseitems_itemid; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.base_item_metadata_fields + ADD CONSTRAINT fk_baseitemmetadatafields_baseitems_itemid FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: base_item_providers fk_baseitemproviders_baseitems_itemid; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.base_item_providers + ADD CONSTRAINT fk_baseitemproviders_baseitems_itemid FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: base_item_trailer_types fk_baseitemtrailertypes_baseitems_itemid; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.base_item_trailer_types + ADD CONSTRAINT fk_baseitemtrailertypes_baseitems_itemid FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: chapters fk_chapters_baseitems_itemid; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.chapters + ADD CONSTRAINT fk_chapters_baseitems_itemid FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: image_infos fk_imageinfos_users_userid; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.image_infos + ADD CONSTRAINT fk_imageinfos_users_userid FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; + + +-- +-- Name: item_values_map fk_itemvaluesmap_baseitems_itemid; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.item_values_map + ADD CONSTRAINT fk_itemvaluesmap_baseitems_itemid FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: item_values_map fk_itemvaluesmap_itemvalues_itemvalueid; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.item_values_map + ADD CONSTRAINT fk_itemvaluesmap_itemvalues_itemvalueid FOREIGN KEY (item_value_id) REFERENCES library.item_values(item_value_id) ON DELETE CASCADE; + + +-- +-- Name: keyframe_data fk_keyframedata_baseitems_itemid; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.keyframe_data + ADD CONSTRAINT fk_keyframedata_baseitems_itemid FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: media_stream_infos fk_mediastreaminfos_baseitems_itemid; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.media_stream_infos + ADD CONSTRAINT fk_mediastreaminfos_baseitems_itemid FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: people_base_item_map fk_peoplebaseitemmap_baseitems_itemid; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.people_base_item_map + ADD CONSTRAINT fk_peoplebaseitemmap_baseitems_itemid FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: people_base_item_map fk_peoplebaseitemmap_peoples_peopleid; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.people_base_item_map + ADD CONSTRAINT fk_peoplebaseitemmap_peoples_peopleid FOREIGN KEY (people_id) REFERENCES library.peoples(id) ON DELETE CASCADE; + + +-- +-- Name: user_data fk_userdata_baseitems_itemid; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.user_data + ADD CONSTRAINT fk_userdata_baseitems_itemid FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: user_data fk_userdata_users_userid; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.user_data + ADD CONSTRAINT fk_userdata_users_userid FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; + + +-- +-- Name: access_schedules FK_AccessSchedules_Users_UserId; Type: FK CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users.access_schedules + ADD CONSTRAINT "FK_AccessSchedules_Users_UserId" FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; + + +-- +-- Name: permissions FK_Permissions_Users_UserId; Type: FK CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users.permissions + ADD CONSTRAINT "FK_Permissions_Users_UserId" FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; + + +-- +-- Name: preferences FK_Preferences_Users_UserId; Type: FK CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users.preferences + ADD CONSTRAINT "FK_Preferences_Users_UserId" FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; + + +-- +-- Name: access_schedules fk_accessschedules_users_userid; Type: FK CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users.access_schedules + ADD CONSTRAINT fk_accessschedules_users_userid FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; + + +-- +-- Name: permissions fk_permissions_users_userid; Type: FK CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users.permissions + ADD CONSTRAINT fk_permissions_users_userid FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; + + +-- +-- Name: preferences fk_preferences_users_userid; Type: FK CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users.preferences + ADD CONSTRAINT fk_preferences_users_userid FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; -- -- PostgreSQL database dump complete -- -\unrestrict 7yQHzelyscgVdVnHcclaahZ3bSdtHCyhzvmlksdJIsj2eWF8f38OCYThpGtIjiX +\unrestrict ioCi9akCEb4OTJqqafagnN0ujRzEOChWnb2NQKO5G1mPGHoPiOIWcce58T7EixH diff --git a/sql/schema_init/create_database_schema.sql.v2 b/sql/schema_init/create_database_schema.sql.v2 index 5a989fe8..9de83f54 100644 Binary files a/sql/schema_init/create_database_schema.sql.v2 and b/sql/schema_init/create_database_schema.sql.v2 differ diff --git a/sql/schema_init/create_database_schema.sql.v3 b/sql/schema_init/create_database_schema.sql.v3 new file mode 100644 index 00000000..74760a95 --- /dev/null +++ b/sql/schema_init/create_database_schema.sql.v3 @@ -0,0 +1,2162 @@ +-- +-- PostgreSQL database dump +-- + +\restrict Vwcqwiq0T7Wa2mK8KvZhGZRaSeFcgOrgunEbjWSCbLeRLSwJLeXqBprmQroWe9O + +-- Dumped from database version 18.3 (Ubuntu 18.3-1.pgdg25.10+1) +-- Dumped by pg_dump version 18.3 (Ubuntu 18.3-1.pgdg25.10+1) + +SET statement_timeout = 0; +SET lock_timeout = 0; +SET idle_in_transaction_session_timeout = 0; +SET transaction_timeout = 0; +SET client_encoding = 'UTF8'; +SET standard_conforming_strings = on; +SELECT pg_catalog.set_config('search_path', '', false); +SET check_function_bodies = false; +SET xmloption = content; +SET client_min_messages = warning; +SET row_security = off; + +-- +-- Name: activitylog; Type: SCHEMA; Schema: -; Owner: jellyfin +-- + +CREATE SCHEMA activitylog; + + +ALTER SCHEMA activitylog OWNER TO jellyfin; + +-- +-- Name: authentication; Type: SCHEMA; Schema: -; Owner: jellyfin +-- + +CREATE SCHEMA authentication; + + +ALTER SCHEMA authentication OWNER TO jellyfin; + +-- +-- Name: displaypreferences; Type: SCHEMA; Schema: -; Owner: jellyfin +-- + +CREATE SCHEMA displaypreferences; + + +ALTER SCHEMA displaypreferences OWNER TO jellyfin; + +-- +-- Name: library; Type: SCHEMA; Schema: -; Owner: jellyfin +-- + +CREATE SCHEMA library; + + +ALTER SCHEMA library OWNER TO jellyfin; + +-- +-- Name: pg_repack; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS pg_repack WITH SCHEMA public; + + +-- +-- Name: EXTENSION pg_repack; Type: COMMENT; Schema: -; Owner: +-- + +COMMENT ON EXTENSION pg_repack IS 'Reorganize tables in PostgreSQL databases with minimal locks'; + + +-- +-- Name: users; Type: SCHEMA; Schema: -; Owner: jellyfin +-- + +CREATE SCHEMA users; + + +ALTER SCHEMA users OWNER TO jellyfin; + +-- +-- Name: pg_stat_statements; Type: EXTENSION; Schema: -; Owner: - +-- + +CREATE EXTENSION IF NOT EXISTS pg_stat_statements WITH SCHEMA public; + + +-- +-- Name: EXTENSION pg_stat_statements; Type: COMMENT; Schema: -; Owner: +-- + +COMMENT ON EXTENSION pg_stat_statements IS 'track planning and execution statistics of all SQL statements executed'; + + +SET default_tablespace = ''; + +SET default_table_access_method = heap; + +-- +-- Name: activity_logs; Type: TABLE; Schema: activitylog; Owner: jellyfin +-- + +CREATE TABLE activitylog.activity_logs ( + id integer CONSTRAINT "ActivityLogs_Id_not_null" NOT NULL, + name character varying(512) CONSTRAINT "ActivityLogs_Name_not_null" NOT NULL, + overview character varying(512), + short_overview character varying(512), + type character varying(256) CONSTRAINT "ActivityLogs_Type_not_null" NOT NULL, + user_id uuid CONSTRAINT "ActivityLogs_UserId_not_null" NOT NULL, + item_id character varying(256), + date_created timestamp with time zone CONSTRAINT "ActivityLogs_DateCreated_not_null" NOT NULL, + log_severity integer CONSTRAINT "ActivityLogs_LogSeverity_not_null" NOT NULL, + row_version bigint CONSTRAINT "ActivityLogs_RowVersion_not_null" NOT NULL +); + + +ALTER TABLE activitylog.activity_logs OWNER TO jellyfin; + +-- +-- Name: ActivityLogs_Id_seq; Type: SEQUENCE; Schema: activitylog; Owner: jellyfin +-- + +ALTER TABLE activitylog.activity_logs ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME activitylog."ActivityLogs_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: api_keys; Type: TABLE; Schema: authentication; Owner: jellyfin +-- + +CREATE TABLE authentication.api_keys ( + id integer CONSTRAINT "ApiKeys_Id_not_null" NOT NULL, + date_created timestamp with time zone CONSTRAINT "ApiKeys_DateCreated_not_null" NOT NULL, + date_last_activity timestamp with time zone CONSTRAINT "ApiKeys_DateLastActivity_not_null" NOT NULL, + name character varying(64) CONSTRAINT "ApiKeys_Name_not_null" NOT NULL, + access_token text CONSTRAINT "ApiKeys_AccessToken_not_null" NOT NULL +); + + +ALTER TABLE authentication.api_keys OWNER TO jellyfin; + +-- +-- Name: ApiKeys_Id_seq; Type: SEQUENCE; Schema: authentication; Owner: jellyfin +-- + +ALTER TABLE authentication.api_keys ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME authentication."ApiKeys_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: device_options; Type: TABLE; Schema: authentication; Owner: jellyfin +-- + +CREATE TABLE authentication.device_options ( + id integer CONSTRAINT "DeviceOptions_Id_not_null" NOT NULL, + device_id text CONSTRAINT "DeviceOptions_DeviceId_not_null" NOT NULL, + custom_name text +); + + +ALTER TABLE authentication.device_options OWNER TO jellyfin; + +-- +-- Name: DeviceOptions_Id_seq; Type: SEQUENCE; Schema: authentication; Owner: jellyfin +-- + +ALTER TABLE authentication.device_options ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME authentication."DeviceOptions_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: devices; Type: TABLE; Schema: authentication; Owner: jellyfin +-- + +CREATE TABLE authentication.devices ( + id integer CONSTRAINT "Devices_Id_not_null" NOT NULL, + user_id uuid CONSTRAINT "Devices_UserId_not_null" NOT NULL, + access_token text CONSTRAINT "Devices_AccessToken_not_null" NOT NULL, + app_name character varying(64) CONSTRAINT "Devices_AppName_not_null" NOT NULL, + app_version character varying(32) CONSTRAINT "Devices_AppVersion_not_null" NOT NULL, + device_name character varying(64) CONSTRAINT "Devices_DeviceName_not_null" NOT NULL, + device_id character varying(256) CONSTRAINT "Devices_DeviceId_not_null" NOT NULL, + is_active boolean CONSTRAINT "Devices_IsActive_not_null" NOT NULL, + date_created timestamp with time zone CONSTRAINT "Devices_DateCreated_not_null" NOT NULL, + date_modified timestamp with time zone CONSTRAINT "Devices_DateModified_not_null" NOT NULL, + date_last_activity timestamp with time zone CONSTRAINT "Devices_DateLastActivity_not_null" NOT NULL +); + + +ALTER TABLE authentication.devices OWNER TO jellyfin; + +-- +-- Name: Devices_Id_seq; Type: SEQUENCE; Schema: authentication; Owner: jellyfin +-- + +ALTER TABLE authentication.devices ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME authentication."Devices_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: custom_item_display_preferences; Type: TABLE; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE TABLE displaypreferences.custom_item_display_preferences ( + id integer CONSTRAINT "CustomItemDisplayPreferences_Id_not_null" NOT NULL, + user_id uuid CONSTRAINT "CustomItemDisplayPreferences_UserId_not_null" NOT NULL, + item_id uuid CONSTRAINT "CustomItemDisplayPreferences_ItemId_not_null" NOT NULL, + client character varying(32) CONSTRAINT "CustomItemDisplayPreferences_Client_not_null" NOT NULL, + key text CONSTRAINT "CustomItemDisplayPreferences_Key_not_null" NOT NULL, + value text +); + + +ALTER TABLE displaypreferences.custom_item_display_preferences OWNER TO jellyfin; + +-- +-- Name: CustomItemDisplayPreferences_Id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE displaypreferences.custom_item_display_preferences ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME displaypreferences."CustomItemDisplayPreferences_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: display_preferences; Type: TABLE; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE TABLE displaypreferences.display_preferences ( + id integer CONSTRAINT "DisplayPreferences_Id_not_null" NOT NULL, + user_id uuid CONSTRAINT "DisplayPreferences_UserId_not_null" NOT NULL, + item_id uuid CONSTRAINT "DisplayPreferences_ItemId_not_null" NOT NULL, + client character varying(32) CONSTRAINT "DisplayPreferences_Client_not_null" NOT NULL, + show_sidebar boolean CONSTRAINT "DisplayPreferences_ShowSidebar_not_null" NOT NULL, + show_backdrop boolean CONSTRAINT "DisplayPreferences_ShowBackdrop_not_null" NOT NULL, + scroll_direction integer CONSTRAINT "DisplayPreferences_ScrollDirection_not_null" NOT NULL, + index_by integer, + skip_forward_length integer CONSTRAINT "DisplayPreferences_SkipForwardLength_not_null" NOT NULL, + skip_backward_length integer CONSTRAINT "DisplayPreferences_SkipBackwardLength_not_null" NOT NULL, + chromecast_version integer CONSTRAINT "DisplayPreferences_ChromecastVersion_not_null" NOT NULL, + enable_next_video_info_overlay boolean CONSTRAINT "DisplayPreferences_EnableNextVideoInfoOverlay_not_null" NOT NULL, + dashboard_theme character varying(32), + tv_home character varying(32) +); + + +ALTER TABLE displaypreferences.display_preferences OWNER TO jellyfin; + +-- +-- Name: DisplayPreferences_Id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE displaypreferences.display_preferences ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME displaypreferences."DisplayPreferences_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: home_sections; Type: TABLE; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE TABLE displaypreferences.home_sections ( + id integer CONSTRAINT "HomeSection_Id_not_null" NOT NULL, + display_preferences_id integer CONSTRAINT "HomeSection_DisplayPreferencesId_not_null" NOT NULL, + "order" integer CONSTRAINT "HomeSection_Order_not_null" NOT NULL, + type integer CONSTRAINT "HomeSection_Type_not_null" NOT NULL +); + + +ALTER TABLE displaypreferences.home_sections OWNER TO jellyfin; + +-- +-- Name: HomeSection_Id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE displaypreferences.home_sections ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME displaypreferences."HomeSection_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: item_display_preferences; Type: TABLE; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE TABLE displaypreferences.item_display_preferences ( + id integer CONSTRAINT "ItemDisplayPreferences_Id_not_null" NOT NULL, + user_id uuid CONSTRAINT "ItemDisplayPreferences_UserId_not_null" NOT NULL, + item_id uuid CONSTRAINT "ItemDisplayPreferences_ItemId_not_null" NOT NULL, + client character varying(32) CONSTRAINT "ItemDisplayPreferences_Client_not_null" NOT NULL, + view_type integer CONSTRAINT "ItemDisplayPreferences_ViewType_not_null" NOT NULL, + remember_indexing boolean CONSTRAINT "ItemDisplayPreferences_RememberIndexing_not_null" NOT NULL, + index_by integer, + remember_sorting boolean CONSTRAINT "ItemDisplayPreferences_RememberSorting_not_null" NOT NULL, + sort_by character varying(64) CONSTRAINT "ItemDisplayPreferences_SortBy_not_null" NOT NULL, + sort_order integer CONSTRAINT "ItemDisplayPreferences_SortOrder_not_null" NOT NULL +); + + +ALTER TABLE displaypreferences.item_display_preferences OWNER TO jellyfin; + +-- +-- Name: ItemDisplayPreferences_Id_seq; Type: SEQUENCE; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE displaypreferences.item_display_preferences ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME displaypreferences."ItemDisplayPreferences_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: image_infos; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.image_infos ( + id integer CONSTRAINT "ImageInfos_Id_not_null" NOT NULL, + user_id uuid, + path character varying(512) CONSTRAINT "ImageInfos_Path_not_null" NOT NULL, + last_modified timestamp with time zone CONSTRAINT "ImageInfos_LastModified_not_null" NOT NULL +); + + +ALTER TABLE library.image_infos OWNER TO jellyfin; + +-- +-- Name: ImageInfos_Id_seq; Type: SEQUENCE; Schema: library; Owner: jellyfin +-- + +ALTER TABLE library.image_infos ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME library."ImageInfos_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: ancestor_ids; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.ancestor_ids ( + parent_item_id uuid CONSTRAINT "AncestorIds_ParentItemId_not_null" NOT NULL, + item_id uuid CONSTRAINT "AncestorIds_ItemId_not_null" NOT NULL +); + + +ALTER TABLE library.ancestor_ids OWNER TO jellyfin; + +-- +-- Name: attachment_stream_infos; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.attachment_stream_infos ( + item_id uuid CONSTRAINT "AttachmentStreamInfos_ItemId_not_null" NOT NULL, + index integer CONSTRAINT "AttachmentStreamInfos_Index_not_null" NOT NULL, + codec text, + codec_tag text, + comment text, + filename text, + mime_type text +); + + +ALTER TABLE library.attachment_stream_infos OWNER TO jellyfin; + +-- +-- Name: audio_stream_details; Type: TABLE; Schema: library; Owner: postgres +-- + +CREATE TABLE library.audio_stream_details ( + item_id uuid CONSTRAINT "AudioStreamDetails_ItemId_not_null" NOT NULL, + stream_index integer CONSTRAINT "AudioStreamDetails_StreamIndex_not_null" NOT NULL, + channel_layout text, + channels integer, + sample_rate integer, + is_hearing_impaired boolean +); + + +ALTER TABLE library.audio_stream_details OWNER TO postgres; + +-- +-- Name: base_item_audio_extras; Type: TABLE; Schema: library; Owner: postgres +-- + +CREATE TABLE library.base_item_audio_extras ( + item_id uuid CONSTRAINT "BaseItemAudioExtras_ItemId_not_null" NOT NULL, + album text, + artists text, + album_artists text, + lufs real, + normalization_gain real +); + + +ALTER TABLE library.base_item_audio_extras OWNER TO postgres; + +-- +-- Name: base_item_image_infos; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.base_item_image_infos ( + id uuid CONSTRAINT "BaseItemImageInfos_Id_not_null" NOT NULL, + path text CONSTRAINT "BaseItemImageInfos_Path_not_null" NOT NULL, + date_modified timestamp with time zone, + image_type integer CONSTRAINT "BaseItemImageInfos_ImageType_not_null" NOT NULL, + width integer CONSTRAINT "BaseItemImageInfos_Width_not_null" NOT NULL, + height integer CONSTRAINT "BaseItemImageInfos_Height_not_null" NOT NULL, + blurhash bytea, + item_id uuid CONSTRAINT "BaseItemImageInfos_ItemId_not_null" NOT NULL +); + + +ALTER TABLE library.base_item_image_infos OWNER TO jellyfin; + +-- +-- Name: base_item_live_tv_extras; Type: TABLE; Schema: library; Owner: postgres +-- + +CREATE TABLE library.base_item_live_tv_extras ( + item_id uuid CONSTRAINT "BaseItemLiveTvExtras_ItemId_not_null" NOT NULL, + start_date timestamp with time zone, + end_date timestamp with time zone, + episode_title text, + show_id text, + external_series_id text, + external_service_id text, + audio integer +); + + +ALTER TABLE library.base_item_live_tv_extras OWNER TO postgres; + +-- +-- Name: base_item_metadata_fields; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.base_item_metadata_fields ( + id integer CONSTRAINT "BaseItemMetadataFields_Id_not_null" NOT NULL, + item_id uuid CONSTRAINT "BaseItemMetadataFields_ItemId_not_null" NOT NULL +); + + +ALTER TABLE library.base_item_metadata_fields OWNER TO jellyfin; + +-- +-- Name: base_item_providers; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.base_item_providers ( + item_id uuid CONSTRAINT "BaseItemProviders_ItemId_not_null" NOT NULL, + provider_id text CONSTRAINT "BaseItemProviders_ProviderId_not_null" NOT NULL, + provider_value text CONSTRAINT "BaseItemProviders_ProviderValue_not_null" NOT NULL +); + + +ALTER TABLE library.base_item_providers OWNER TO jellyfin; + +-- +-- Name: base_item_trailer_types; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.base_item_trailer_types ( + id integer CONSTRAINT "BaseItemTrailerTypes_Id_not_null" NOT NULL, + item_id uuid CONSTRAINT "BaseItemTrailerTypes_ItemId_not_null" NOT NULL +); + + +ALTER TABLE library.base_item_trailer_types OWNER TO jellyfin; + +-- +-- Name: base_item_tv_extras; Type: TABLE; Schema: library; Owner: postgres +-- + +CREATE TABLE library.base_item_tv_extras ( + item_id uuid CONSTRAINT "BaseItemTvExtras_ItemId_not_null" NOT NULL, + series_id uuid, + season_id uuid, + series_name text, + season_name text, + series_presentation_unique_key text +); + + +ALTER TABLE library.base_item_tv_extras OWNER TO postgres; + +-- +-- Name: base_items; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.base_items ( + id uuid CONSTRAINT "BaseItems_Id_not_null" NOT NULL, + type text CONSTRAINT "BaseItems_Type_not_null" NOT NULL, + data text, + path text, + channel_id uuid, + is_movie boolean CONSTRAINT "BaseItems_IsMovie_not_null" NOT NULL, + community_rating real, + custom_rating text, + index_number integer, + is_locked boolean CONSTRAINT "BaseItems_IsLocked_not_null" NOT NULL, + name text, + official_rating text, + media_type text, + overview text, + parent_index_number integer, + premiere_date timestamp with time zone, + production_year integer, + genres text, + sort_name text, + forced_sort_name text, + run_time_ticks bigint, + date_created timestamp with time zone, + date_modified timestamp with time zone, + is_series boolean CONSTRAINT "BaseItems_IsSeries_not_null" NOT NULL, + is_repeat boolean CONSTRAINT "BaseItems_IsRepeat_not_null" NOT NULL, + preferred_metadata_language text, + preferred_metadata_country_code text, + date_last_refreshed timestamp with time zone, + date_last_saved timestamp with time zone, + is_in_mixed_folder boolean CONSTRAINT "BaseItems_IsInMixedFolder_not_null" NOT NULL, + studios text, + tags text, + is_folder boolean CONSTRAINT "BaseItems_IsFolder_not_null" NOT NULL, + inherited_parental_rating_value integer, + inherited_parental_rating_sub_value integer, + unrated_type text, + critic_rating real, + clean_name text, + presentation_unique_key text, + original_title text, + primary_version_id text, + date_last_media_added timestamp with time zone, + is_virtual_item boolean CONSTRAINT "BaseItems_IsVirtualItem_not_null" NOT NULL, + tagline text, + production_locations text, + extra_ids text, + total_bitrate integer, + extra_type integer, + external_id text, + owner_id text, + width integer, + height integer, + size bigint, + parent_id uuid, + top_parent_id uuid +); + + +ALTER TABLE library.base_items OWNER TO jellyfin; + +-- +-- Name: base_items_v; Type: VIEW; Schema: library; Owner: postgres +-- + +CREATE VIEW library.base_items_v AS + SELECT b.id, + b.type, + b.data, + b.path, + b.channel_id, + b.is_movie, + b.community_rating, + b.custom_rating, + b.index_number, + b.is_locked, + b.name, + b.official_rating, + b.media_type, + b.overview, + b.parent_index_number, + b.premiere_date, + b.production_year, + b.genres, + b.sort_name, + b.forced_sort_name, + b.run_time_ticks, + b.date_created, + b.date_modified, + b.is_series, + b.is_repeat, + b.preferred_metadata_language, + b.preferred_metadata_country_code, + b.date_last_refreshed, + b.date_last_saved, + b.is_in_mixed_folder, + b.studios, + b.tags, + b.is_folder, + b.inherited_parental_rating_value, + b.inherited_parental_rating_sub_value, + b.unrated_type, + b.critic_rating, + b.clean_name, + b.presentation_unique_key, + b.original_title, + b.primary_version_id, + b.date_last_media_added, + b.is_virtual_item, + b.tagline, + b.production_locations, + b.extra_ids, + b.total_bitrate, + b.extra_type, + b.external_id, + b.owner_id, + b.width, + b.height, + b.size, + b.parent_id, + b.top_parent_id, + tv.series_id, + tv.season_id, + tv.series_name, + tv.season_name, + tv.series_presentation_unique_key, + ltv.start_date, + ltv.end_date, + ltv.episode_title, + ltv.show_id, + ltv.external_series_id, + ltv.external_service_id, + ltv.audio, + au.album, + au.artists, + au.album_artists, + au.lufs, + au.normalization_gain + FROM (((library.base_items b + LEFT JOIN library.base_item_tv_extras tv ON ((tv.item_id = b.id))) + LEFT JOIN library.base_item_live_tv_extras ltv ON ((ltv.item_id = b.id))) + LEFT JOIN library.base_item_audio_extras au ON ((au.item_id = b.id))); + + +ALTER VIEW library.base_items_v OWNER TO postgres; + +-- +-- Name: chapters; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.chapters ( + item_id uuid CONSTRAINT "Chapters_ItemId_not_null" NOT NULL, + chapter_index integer CONSTRAINT "Chapters_ChapterIndex_not_null" NOT NULL, + start_position_ticks bigint CONSTRAINT "Chapters_StartPositionTicks_not_null" NOT NULL, + name text, + image_path text, + image_date_modified timestamp with time zone +); + + +ALTER TABLE library.chapters OWNER TO jellyfin; + +-- +-- Name: people_base_item_map; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.people_base_item_map ( + role text CONSTRAINT "PeopleBaseItemMap_Role_not_null" NOT NULL, + item_id uuid CONSTRAINT "PeopleBaseItemMap_ItemId_not_null" NOT NULL, + people_id uuid CONSTRAINT "PeopleBaseItemMap_PeopleId_not_null" NOT NULL, + sort_order integer, + list_order integer +); + + +ALTER TABLE library.people_base_item_map OWNER TO jellyfin; + +-- +-- Name: peoples; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.peoples ( + id uuid CONSTRAINT "Peoples_Id_not_null" NOT NULL, + name text CONSTRAINT "Peoples_Name_not_null" NOT NULL, + person_type text +); + + +ALTER TABLE library.peoples OWNER TO jellyfin; + +-- +-- Name: item_people_v; Type: VIEW; Schema: library; Owner: postgres +-- + +CREATE VIEW library.item_people_v AS + SELECT b.id AS item_id, + b.type AS item_type, + b.name AS item_name, + tv.series_name, + b.production_year, + pe.id AS person_id, + pe.name AS person_name, + pe.person_type, + pm.role, + pm.sort_order, + pm.list_order + FROM (((library.people_base_item_map pm + JOIN library.base_items b ON ((pm.item_id = b.id))) + JOIN library.peoples pe ON ((pm.people_id = pe.id))) + LEFT JOIN library.base_item_tv_extras tv ON ((tv.item_id = b.id))) + WHERE (b.is_virtual_item = false); + + +ALTER VIEW library.item_people_v OWNER TO postgres; + +-- +-- Name: item_providers_v; Type: VIEW; Schema: library; Owner: postgres +-- + +CREATE VIEW library.item_providers_v AS + SELECT b.id AS item_id, + b.type, + b.name, + b.original_title, + b.production_year, + tv.series_name, + b.index_number AS episode_number, + b.parent_index_number AS season_number, + max( + CASE + WHEN (p.provider_id = 'Imdb'::text) THEN p.provider_value + ELSE NULL::text + END) AS imdb_id, + max( + CASE + WHEN (p.provider_id = 'Tmdb'::text) THEN p.provider_value + ELSE NULL::text + END) AS tmdb_id, + max( + CASE + WHEN (p.provider_id = 'Tvdb'::text) THEN p.provider_value + ELSE NULL::text + END) AS tvdb_id, + max( + CASE + WHEN (p.provider_id = 'TvRage'::text) THEN p.provider_value + ELSE NULL::text + END) AS tv_rage_id, + max( + CASE + WHEN (p.provider_id = 'MusicBrainzAlbum'::text) THEN p.provider_value + ELSE NULL::text + END) AS music_brainz_album_id, + max( + CASE + WHEN (p.provider_id = 'MusicBrainzArtist'::text) THEN p.provider_value + ELSE NULL::text + END) AS music_brainz_artist_id, + CASE + WHEN (count( + CASE + WHEN (p.provider_id <> ALL (ARRAY['Imdb'::text, 'Tmdb'::text, 'Tvdb'::text, 'TvRage'::text, 'MusicBrainzAlbum'::text, 'MusicBrainzArtist'::text])) THEN 1 + ELSE NULL::integer + END) > 0) THEN (jsonb_object_agg(p.provider_id, p.provider_value) FILTER (WHERE (p.provider_id <> ALL (ARRAY['Imdb'::text, 'Tmdb'::text, 'Tvdb'::text, 'TvRage'::text, 'MusicBrainzAlbum'::text, 'MusicBrainzArtist'::text]))))::text + ELSE NULL::text + END AS other_providers + FROM ((library.base_items b + LEFT JOIN library.base_item_providers p ON ((b.id = p.item_id))) + LEFT JOIN library.base_item_tv_extras tv ON ((b.id = tv.item_id))) + WHERE (b.is_virtual_item = false) + GROUP BY b.id, b.type, b.name, b.original_title, b.production_year, tv.series_name, b.index_number, b.parent_index_number; + + +ALTER VIEW library.item_providers_v OWNER TO postgres; + +-- +-- Name: item_values; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.item_values ( + item_value_id uuid CONSTRAINT "ItemValues_ItemValueId_not_null" NOT NULL, + type integer CONSTRAINT "ItemValues_Type_not_null" NOT NULL, + value text CONSTRAINT "ItemValues_Value_not_null" NOT NULL, + clean_value text CONSTRAINT "ItemValues_CleanValue_not_null" NOT NULL +); + + +ALTER TABLE library.item_values OWNER TO jellyfin; + +-- +-- Name: item_values_map; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.item_values_map ( + item_id uuid CONSTRAINT "ItemValuesMap_ItemId_not_null" NOT NULL, + item_value_id uuid CONSTRAINT "ItemValuesMap_ItemValueId_not_null" NOT NULL +); + + +ALTER TABLE library.item_values_map OWNER TO jellyfin; + +-- +-- Name: keyframe_data; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.keyframe_data ( + item_id uuid CONSTRAINT "KeyframeData_ItemId_not_null" NOT NULL, + total_duration bigint CONSTRAINT "KeyframeData_TotalDuration_not_null" NOT NULL, + keyframe_ticks bigint[] +); + + +ALTER TABLE library.keyframe_data OWNER TO jellyfin; + +-- +-- Name: library_options; Type: TABLE; Schema: library; Owner: postgres +-- + +CREATE TABLE library.library_options ( + library_path text CONSTRAINT "LibraryOptions_LibraryPath_not_null" NOT NULL, + options_json jsonb CONSTRAINT "LibraryOptions_OptionsJson_not_null" NOT NULL, + version integer DEFAULT 1 CONSTRAINT "LibraryOptions_Version_not_null" NOT NULL, + date_created timestamp with time zone DEFAULT now() CONSTRAINT "LibraryOptions_DateCreated_not_null" NOT NULL, + date_modified timestamp with time zone DEFAULT now() CONSTRAINT "LibraryOptions_DateModified_not_null" NOT NULL +); + + +ALTER TABLE library.library_options OWNER TO postgres; + +-- +-- Name: media_stream_infos; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.media_stream_infos ( + item_id uuid CONSTRAINT "MediaStreamInfos_ItemId_not_null" NOT NULL, + stream_index integer CONSTRAINT "MediaStreamInfos_StreamIndex_not_null" NOT NULL, + stream_type integer CONSTRAINT "MediaStreamInfos_StreamType_not_null" NOT NULL, + codec text, + language text, + profile text, + path text, + bit_rate integer, + is_default boolean CONSTRAINT "MediaStreamInfos_IsDefault_not_null" NOT NULL, + is_forced boolean CONSTRAINT "MediaStreamInfos_IsForced_not_null" NOT NULL, + is_external boolean CONSTRAINT "MediaStreamInfos_IsExternal_not_null" NOT NULL, + level real, + codec_tag text, + comment text, + is_avc boolean, + title text, + time_base text, + codec_time_base text +); + + +ALTER TABLE library.media_stream_infos OWNER TO jellyfin; + +-- +-- Name: video_stream_details; Type: TABLE; Schema: library; Owner: postgres +-- + +CREATE TABLE library.video_stream_details ( + item_id uuid CONSTRAINT "VideoStreamDetails_ItemId_not_null" NOT NULL, + stream_index integer CONSTRAINT "VideoStreamDetails_StreamIndex_not_null" NOT NULL, + aspect_ratio text, + is_interlaced boolean, + height integer, + width integer, + average_frame_rate real, + real_frame_rate real, + pixel_format text, + bit_depth integer, + is_anamorphic boolean, + ref_frames integer, + nal_length_size text, + color_primaries text, + color_space text, + color_transfer text, + dv_version_major integer, + dv_version_minor integer, + dv_profile integer, + dv_level integer, + rpu_present_flag integer, + el_present_flag integer, + bl_present_flag integer, + dv_bl_signal_compatibility_id integer, + rotation integer, + key_frames text, + hdr10_plus_present_flag boolean +); + + +ALTER TABLE library.video_stream_details OWNER TO postgres; + +-- +-- Name: library_summary_v; Type: VIEW; Schema: library; Owner: postgres +-- + +CREATE VIEW library.library_summary_v AS + WITH primary_video AS ( + SELECT DISTINCT ON (m.item_id) m.item_id, + vd.height, + vd.dv_profile, + vd.hdr10_plus_present_flag, + vd.color_transfer + FROM (library.media_stream_infos m + JOIN library.video_stream_details vd ON (((vd.item_id = m.item_id) AND (vd.stream_index = m.stream_index)))) + WHERE (m.stream_type = 1) + ORDER BY m.item_id, m.stream_index + ) + SELECT b.type, + count(*) AS item_count, + count(*) FILTER (WHERE (b.production_year IS NOT NULL)) AS with_year, + min(b.production_year) AS oldest_year, + max(b.production_year) AS newest_year, + round((avg(b.community_rating))::numeric, 2) AS avg_community_rating, + sum(b.run_time_ticks) AS total_run_time_ticks, + round((COALESCE(sum(b.run_time_ticks), (0)::numeric) / 600000000.0), 1) AS total_runtime_hours, + sum(b.size) AS total_size_bytes, + round((COALESCE(sum(b.size), (0)::numeric) / (1024.0 ^ (3)::numeric)), 2) AS total_size_gb, + count(*) FILTER (WHERE (pv.height >= 2160)) AS count4_k, + count(*) FILTER (WHERE ((pv.height >= 1080) AND (pv.height <= 2159))) AS count1080p, + count(*) FILTER (WHERE ((pv.height >= 720) AND (pv.height <= 1079))) AS count720p, + count(*) FILTER (WHERE ((pv.height < 720) AND (pv.height IS NOT NULL))) AS count_sd, + count(*) FILTER (WHERE (pv.dv_profile IS NOT NULL)) AS count_dolby_vision, + count(*) FILTER (WHERE (pv.hdr10_plus_present_flag = true)) AS count_hdr10_plus, + count(*) FILTER (WHERE ((pv.color_transfer = 'smpte2084'::text) AND (pv.dv_profile IS NULL) AND (pv.hdr10_plus_present_flag IS NOT TRUE))) AS count_hdr10 + FROM (library.base_items b + LEFT JOIN primary_video pv ON ((pv.item_id = b.id))) + WHERE ((b.is_virtual_item = false) AND (b.is_folder = false)) + GROUP BY b.type + ORDER BY (count(*)) DESC; + + +ALTER VIEW library.library_summary_v OWNER TO postgres; + +-- +-- Name: media_segments; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.media_segments ( + id uuid CONSTRAINT "MediaSegments_Id_not_null" NOT NULL, + item_id uuid CONSTRAINT "MediaSegments_ItemId_not_null" NOT NULL, + type integer CONSTRAINT "MediaSegments_Type_not_null" NOT NULL, + end_ticks bigint CONSTRAINT "MediaSegments_EndTicks_not_null" NOT NULL, + start_ticks bigint CONSTRAINT "MediaSegments_StartTicks_not_null" NOT NULL, + segment_provider_id text CONSTRAINT "MediaSegments_SegmentProviderId_not_null" NOT NULL +); + + +ALTER TABLE library.media_segments OWNER TO jellyfin; + +-- +-- Name: media_stream_infos_v; Type: VIEW; Schema: library; Owner: postgres +-- + +CREATE VIEW library.media_stream_infos_v AS + SELECT m.item_id, + m.stream_index, + m.stream_type, + m.codec, + m.language, + m.profile, + m.path, + m.bit_rate, + m.is_default, + m.is_forced, + m.is_external, + m.level, + m.codec_tag, + m.comment, + m.is_avc, + m.title, + m.time_base, + m.codec_time_base, + a.channel_layout, + a.channels, + a.sample_rate, + a.is_hearing_impaired, + v.aspect_ratio, + v.is_interlaced, + v.height, + v.width, + v.average_frame_rate, + v.real_frame_rate, + v.pixel_format, + v.bit_depth, + v.is_anamorphic, + v.ref_frames, + v.nal_length_size, + v.color_primaries, + v.color_space, + v.color_transfer, + v.dv_version_major, + v.dv_version_minor, + v.dv_profile, + v.dv_level, + v.rpu_present_flag, + v.el_present_flag, + v.bl_present_flag, + v.dv_bl_signal_compatibility_id, + v.rotation, + v.key_frames, + v.hdr10_plus_present_flag + FROM ((library.media_stream_infos m + LEFT JOIN library.audio_stream_details a ON (((m.item_id = a.item_id) AND (m.stream_index = a.stream_index)))) + LEFT JOIN library.video_stream_details v ON (((m.item_id = v.item_id) AND (m.stream_index = v.stream_index)))); + + +ALTER VIEW library.media_stream_infos_v OWNER TO postgres; + +-- +-- Name: trickplay_infos; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.trickplay_infos ( + item_id uuid CONSTRAINT "TrickplayInfos_ItemId_not_null" NOT NULL, + width integer CONSTRAINT "TrickplayInfos_Width_not_null" NOT NULL, + height integer CONSTRAINT "TrickplayInfos_Height_not_null" NOT NULL, + tile_width integer CONSTRAINT "TrickplayInfos_TileWidth_not_null" NOT NULL, + tile_height integer CONSTRAINT "TrickplayInfos_TileHeight_not_null" NOT NULL, + thumbnail_count integer CONSTRAINT "TrickplayInfos_ThumbnailCount_not_null" NOT NULL, + "interval" integer CONSTRAINT "TrickplayInfos_Interval_not_null" NOT NULL, + bandwidth integer CONSTRAINT "TrickplayInfos_Bandwidth_not_null" NOT NULL +); + + +ALTER TABLE library.trickplay_infos OWNER TO jellyfin; + +-- +-- Name: user_data; Type: TABLE; Schema: library; Owner: jellyfin +-- + +CREATE TABLE library.user_data ( + custom_data_key text CONSTRAINT "UserData_CustomDataKey_not_null" NOT NULL, + item_id uuid CONSTRAINT "UserData_ItemId_not_null" NOT NULL, + user_id uuid CONSTRAINT "UserData_UserId_not_null" NOT NULL, + rating double precision, + playback_position_ticks bigint CONSTRAINT "UserData_PlaybackPositionTicks_not_null" NOT NULL, + play_count integer CONSTRAINT "UserData_PlayCount_not_null" NOT NULL, + is_favorite boolean CONSTRAINT "UserData_IsFavorite_not_null" NOT NULL, + last_played_date timestamp with time zone, + played boolean CONSTRAINT "UserData_Played_not_null" NOT NULL, + audio_stream_index integer, + subtitle_stream_index integer, + likes boolean, + retention_date timestamp with time zone +); + + +ALTER TABLE library.user_data OWNER TO jellyfin; + +-- +-- Name: users; Type: TABLE; Schema: users; Owner: jellyfin +-- + +CREATE TABLE users.users ( + id uuid CONSTRAINT "Users_Id_not_null" NOT NULL, + username character varying(255) CONSTRAINT "Users_Username_not_null" NOT NULL, + password character varying(65535), + must_update_password boolean CONSTRAINT "Users_MustUpdatePassword_not_null" NOT NULL, + audio_language_preference character varying(255), + authentication_provider_id character varying(255) CONSTRAINT "Users_AuthenticationProviderId_not_null" NOT NULL, + password_reset_provider_id character varying(255) CONSTRAINT "Users_PasswordResetProviderId_not_null" NOT NULL, + invalid_login_attempt_count integer CONSTRAINT "Users_InvalidLoginAttemptCount_not_null" NOT NULL, + last_activity_date timestamp with time zone, + last_login_date timestamp with time zone, + login_attempts_before_lockout integer, + max_active_sessions integer CONSTRAINT "Users_MaxActiveSessions_not_null" NOT NULL, + subtitle_mode integer CONSTRAINT "Users_SubtitleMode_not_null" NOT NULL, + play_default_audio_track boolean CONSTRAINT "Users_PlayDefaultAudioTrack_not_null" NOT NULL, + subtitle_language_preference character varying(255), + display_missing_episodes boolean CONSTRAINT "Users_DisplayMissingEpisodes_not_null" NOT NULL, + display_collections_view boolean CONSTRAINT "Users_DisplayCollectionsView_not_null" NOT NULL, + enable_local_password boolean CONSTRAINT "Users_EnableLocalPassword_not_null" NOT NULL, + hide_played_in_latest boolean CONSTRAINT "Users_HidePlayedInLatest_not_null" NOT NULL, + remember_audio_selections boolean CONSTRAINT "Users_RememberAudioSelections_not_null" NOT NULL, + remember_subtitle_selections boolean CONSTRAINT "Users_RememberSubtitleSelections_not_null" NOT NULL, + enable_next_episode_auto_play boolean CONSTRAINT "Users_EnableNextEpisodeAutoPlay_not_null" NOT NULL, + enable_auto_login boolean CONSTRAINT "Users_EnableAutoLogin_not_null" NOT NULL, + enable_user_preference_access boolean CONSTRAINT "Users_EnableUserPreferenceAccess_not_null" NOT NULL, + max_parental_rating_score integer, + max_parental_rating_sub_score integer, + remote_client_bitrate_limit integer, + internal_id bigint CONSTRAINT "Users_InternalId_not_null" NOT NULL, + sync_play_access integer CONSTRAINT "Users_SyncPlayAccess_not_null" NOT NULL, + cast_receiver_id character varying(32), + row_version bigint CONSTRAINT "Users_RowVersion_not_null" NOT NULL +); + + +ALTER TABLE users.users OWNER TO jellyfin; + +-- +-- Name: user_playback_history_v; Type: VIEW; Schema: library; Owner: postgres +-- + +CREATE VIEW library.user_playback_history_v AS + SELECT u.username, + u.id AS user_id, + b.name AS item_name, + b.type AS item_type, + tv.series_name, + tv.season_name, + b.index_number AS episode_number, + b.parent_index_number AS season_number, + b.production_year, + b.run_time_ticks, + ud.item_id, + ud.played, + ud.play_count, + ud.last_played_date, + ud.playback_position_ticks, + CASE + WHEN (b.run_time_ticks > 0) THEN round((((ud.playback_position_ticks)::numeric * (100)::numeric) / (b.run_time_ticks)::numeric), 1) + ELSE NULL::numeric + END AS progress_pct, + ud.is_favorite, + ud.rating, + ud.audio_stream_index, + ud.subtitle_stream_index + FROM (((library.user_data ud + JOIN library.base_items b ON ((ud.item_id = b.id))) + JOIN users.users u ON ((ud.user_id = u.id))) + LEFT JOIN library.base_item_tv_extras tv ON ((tv.item_id = b.id))) + WHERE (ud.custom_data_key = ''::text); + + +ALTER VIEW library.user_playback_history_v OWNER TO postgres; + +-- +-- Name: video_items_v; Type: VIEW; Schema: library; Owner: postgres +-- + +CREATE VIEW library.video_items_v AS + SELECT b.id AS item_id, + b.type, + b.name, + b.original_title, + b.production_year, + b.official_rating, + b.community_rating, + b.run_time_ticks, + b.path, + b.date_created, + b.date_modified, + tv.series_name, + tv.season_name, + b.index_number AS episode_number, + b.parent_index_number AS season_number, + b.total_bitrate, + b.size, + m.codec AS video_codec, + m.profile AS video_profile, + vd.width, + vd.height, + vd.average_frame_rate, + vd.bit_depth, + vd.pixel_format, + vd.color_space, + vd.color_transfer, + vd.color_primaries, + vd.is_interlaced, + vd.is_anamorphic, + vd.aspect_ratio, + (vd.dv_profile IS NOT NULL) AS is_dolby_vision, + vd.hdr10_plus_present_flag AS is_hdr10_plus, + CASE + WHEN (vd.dv_profile IS NOT NULL) THEN 'Dolby Vision'::text + WHEN (vd.hdr10_plus_present_flag = true) THEN 'HDR10+'::text + WHEN (vd.color_transfer = 'smpte2084'::text) THEN 'HDR10'::text + WHEN (vd.color_transfer = 'arib-std-b67'::text) THEN 'HLG'::text + ELSE 'SDR'::text + END AS hdr_format, + ( SELECT count(*) AS count + FROM library.media_stream_infos ms + WHERE ((ms.item_id = b.id) AND (ms.stream_type = 0))) AS audio_track_count, + ( SELECT count(*) AS count + FROM library.media_stream_infos ms + WHERE ((ms.item_id = b.id) AND (ms.stream_type = 2))) AS subtitle_track_count + FROM (((library.base_items b + JOIN LATERAL ( SELECT ms.stream_index, + ms.codec, + ms.profile + FROM library.media_stream_infos ms + WHERE ((ms.item_id = b.id) AND (ms.stream_type = 1)) + ORDER BY ms.stream_index + LIMIT 1) m ON (true)) + JOIN library.video_stream_details vd ON (((vd.item_id = b.id) AND (vd.stream_index = m.stream_index)))) + LEFT JOIN library.base_item_tv_extras tv ON ((tv.item_id = b.id))) + WHERE ((b.is_virtual_item = false) AND (b.is_folder = false)); + + +ALTER VIEW library.video_items_v OWNER TO postgres; + +-- +-- Name: __ef_migrations_history; Type: TABLE; Schema: public; Owner: jellyfin +-- + +CREATE TABLE public.__ef_migrations_history ( + migration_id character varying(150) CONSTRAINT "__EFMigrationsHistory_MigrationId_not_null" NOT NULL, + product_version character varying(32) CONSTRAINT "__EFMigrationsHistory_ProductVersion_not_null" NOT NULL +); + + +ALTER TABLE public.__ef_migrations_history OWNER TO jellyfin; + +-- +-- Name: bloat_tables; Type: TABLE; Schema: public; Owner: jellyfin +-- + +CREATE TABLE public.bloat_tables ( + count bigint +); + + +ALTER TABLE public.bloat_tables OWNER TO jellyfin; + +-- +-- Name: access_schedules; Type: TABLE; Schema: users; Owner: jellyfin +-- + +CREATE TABLE users.access_schedules ( + id integer CONSTRAINT "AccessSchedules_Id_not_null" NOT NULL, + user_id uuid CONSTRAINT "AccessSchedules_UserId_not_null" NOT NULL, + day_of_week integer CONSTRAINT "AccessSchedules_DayOfWeek_not_null" NOT NULL, + start_hour double precision CONSTRAINT "AccessSchedules_StartHour_not_null" NOT NULL, + end_hour double precision CONSTRAINT "AccessSchedules_EndHour_not_null" NOT NULL +); + + +ALTER TABLE users.access_schedules OWNER TO jellyfin; + +-- +-- Name: AccessSchedules_Id_seq; Type: SEQUENCE; Schema: users; Owner: jellyfin +-- + +ALTER TABLE users.access_schedules ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME users."AccessSchedules_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: permissions; Type: TABLE; Schema: users; Owner: jellyfin +-- + +CREATE TABLE users.permissions ( + id integer CONSTRAINT "Permissions_Id_not_null" NOT NULL, + user_id uuid, + kind integer CONSTRAINT "Permissions_Kind_not_null" NOT NULL, + value boolean CONSTRAINT "Permissions_Value_not_null" NOT NULL, + row_version bigint CONSTRAINT "Permissions_RowVersion_not_null" NOT NULL, + permission_permissions_guid uuid +); + + +ALTER TABLE users.permissions OWNER TO jellyfin; + +-- +-- Name: Permissions_Id_seq; Type: SEQUENCE; Schema: users; Owner: jellyfin +-- + +ALTER TABLE users.permissions ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME users."Permissions_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: preferences; Type: TABLE; Schema: users; Owner: jellyfin +-- + +CREATE TABLE users.preferences ( + id integer CONSTRAINT "Preferences_Id_not_null" NOT NULL, + user_id uuid, + kind integer CONSTRAINT "Preferences_Kind_not_null" NOT NULL, + value character varying(65535) CONSTRAINT "Preferences_Value_not_null" NOT NULL, + row_version bigint CONSTRAINT "Preferences_RowVersion_not_null" NOT NULL, + preference_preferences_guid uuid +); + + +ALTER TABLE users.preferences OWNER TO jellyfin; + +-- +-- Name: Preferences_Id_seq; Type: SEQUENCE; Schema: users; Owner: jellyfin +-- + +ALTER TABLE users.preferences ALTER COLUMN id ADD GENERATED BY DEFAULT AS IDENTITY ( + SEQUENCE NAME users."Preferences_Id_seq" + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1 +); + + +-- +-- Name: activity_logs PK_ActivityLogs; Type: CONSTRAINT; Schema: activitylog; Owner: jellyfin +-- + +ALTER TABLE ONLY activitylog.activity_logs + ADD CONSTRAINT "PK_ActivityLogs" PRIMARY KEY (id); + + +-- +-- Name: api_keys PK_ApiKeys; Type: CONSTRAINT; Schema: authentication; Owner: jellyfin +-- + +ALTER TABLE ONLY authentication.api_keys + ADD CONSTRAINT "PK_ApiKeys" PRIMARY KEY (id); + + +-- +-- Name: device_options PK_DeviceOptions; Type: CONSTRAINT; Schema: authentication; Owner: jellyfin +-- + +ALTER TABLE ONLY authentication.device_options + ADD CONSTRAINT "PK_DeviceOptions" PRIMARY KEY (id); + + +-- +-- Name: devices PK_Devices; Type: CONSTRAINT; Schema: authentication; Owner: jellyfin +-- + +ALTER TABLE ONLY authentication.devices + ADD CONSTRAINT "PK_Devices" PRIMARY KEY (id); + + +-- +-- Name: custom_item_display_preferences PK_CustomItemDisplayPreferences; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE ONLY displaypreferences.custom_item_display_preferences + ADD CONSTRAINT "PK_CustomItemDisplayPreferences" PRIMARY KEY (id); + + +-- +-- Name: display_preferences PK_DisplayPreferences; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE ONLY displaypreferences.display_preferences + ADD CONSTRAINT "PK_DisplayPreferences" PRIMARY KEY (id); + + +-- +-- Name: home_sections PK_HomeSection; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE ONLY displaypreferences.home_sections + ADD CONSTRAINT "PK_HomeSection" PRIMARY KEY (id); + + +-- +-- Name: item_display_preferences PK_ItemDisplayPreferences; Type: CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE ONLY displaypreferences.item_display_preferences + ADD CONSTRAINT "PK_ItemDisplayPreferences" PRIMARY KEY (id); + + +-- +-- Name: base_item_image_infos BaseItemImageInfos_pkey; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.base_item_image_infos + ADD CONSTRAINT "BaseItemImageInfos_pkey" PRIMARY KEY (id); + + +-- +-- Name: ancestor_ids PK_AncestorIds; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.ancestor_ids + ADD CONSTRAINT "PK_AncestorIds" PRIMARY KEY (item_id, parent_item_id); + + +-- +-- Name: attachment_stream_infos PK_AttachmentStreamInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.attachment_stream_infos + ADD CONSTRAINT "PK_AttachmentStreamInfos" PRIMARY KEY (item_id, index); + + +-- +-- Name: audio_stream_details PK_AudioStreamDetails; Type: CONSTRAINT; Schema: library; Owner: postgres +-- + +ALTER TABLE ONLY library.audio_stream_details + ADD CONSTRAINT "PK_AudioStreamDetails" PRIMARY KEY (item_id, stream_index); + + +-- +-- Name: base_item_audio_extras PK_BaseItemAudioExtras; Type: CONSTRAINT; Schema: library; Owner: postgres +-- + +ALTER TABLE ONLY library.base_item_audio_extras + ADD CONSTRAINT "PK_BaseItemAudioExtras" PRIMARY KEY (item_id); + + +-- +-- Name: base_item_live_tv_extras PK_BaseItemLiveTvExtras; Type: CONSTRAINT; Schema: library; Owner: postgres +-- + +ALTER TABLE ONLY library.base_item_live_tv_extras + ADD CONSTRAINT "PK_BaseItemLiveTvExtras" PRIMARY KEY (item_id); + + +-- +-- Name: base_item_metadata_fields PK_BaseItemMetadataFields; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.base_item_metadata_fields + ADD CONSTRAINT "PK_BaseItemMetadataFields" PRIMARY KEY (id, item_id); + + +-- +-- Name: base_item_providers PK_BaseItemProviders; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.base_item_providers + ADD CONSTRAINT "PK_BaseItemProviders" PRIMARY KEY (item_id, provider_id); + + +-- +-- Name: base_item_trailer_types PK_BaseItemTrailerTypes; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.base_item_trailer_types + ADD CONSTRAINT "PK_BaseItemTrailerTypes" PRIMARY KEY (id, item_id); + + +-- +-- Name: base_item_tv_extras PK_BaseItemTvExtras; Type: CONSTRAINT; Schema: library; Owner: postgres +-- + +ALTER TABLE ONLY library.base_item_tv_extras + ADD CONSTRAINT "PK_BaseItemTvExtras" PRIMARY KEY (item_id); + + +-- +-- Name: base_items PK_BaseItems; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.base_items + ADD CONSTRAINT "PK_BaseItems" PRIMARY KEY (id); + + +-- +-- Name: chapters PK_Chapters; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.chapters + ADD CONSTRAINT "PK_Chapters" PRIMARY KEY (item_id, chapter_index); + + +-- +-- Name: image_infos PK_ImageInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.image_infos + ADD CONSTRAINT "PK_ImageInfos" PRIMARY KEY (id); + + +-- +-- Name: item_values PK_ItemValues; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.item_values + ADD CONSTRAINT "PK_ItemValues" PRIMARY KEY (item_value_id); + + +-- +-- Name: keyframe_data PK_KeyframeData; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.keyframe_data + ADD CONSTRAINT "PK_KeyframeData" PRIMARY KEY (item_id); + + +-- +-- Name: library_options PK_LibraryOptions; Type: CONSTRAINT; Schema: library; Owner: postgres +-- + +ALTER TABLE ONLY library.library_options + ADD CONSTRAINT "PK_LibraryOptions" PRIMARY KEY (library_path); + + +-- +-- Name: media_segments PK_MediaSegments; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.media_segments + ADD CONSTRAINT "PK_MediaSegments" PRIMARY KEY (id); + + +-- +-- Name: media_stream_infos PK_MediaStreamInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.media_stream_infos + ADD CONSTRAINT "PK_MediaStreamInfos" PRIMARY KEY (item_id, stream_index); + + +-- +-- Name: peoples PK_Peoples; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.peoples + ADD CONSTRAINT "PK_Peoples" PRIMARY KEY (id); + + +-- +-- Name: trickplay_infos PK_TrickplayInfos; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.trickplay_infos + ADD CONSTRAINT "PK_TrickplayInfos" PRIMARY KEY (item_id, width); + + +-- +-- Name: user_data PK_UserData; Type: CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.user_data + ADD CONSTRAINT "PK_UserData" PRIMARY KEY (item_id, user_id, custom_data_key); + + +-- +-- Name: video_stream_details PK_VideoStreamDetails; Type: CONSTRAINT; Schema: library; Owner: postgres +-- + +ALTER TABLE ONLY library.video_stream_details + ADD CONSTRAINT "PK_VideoStreamDetails" PRIMARY KEY (item_id, stream_index); + + +-- +-- Name: __ef_migrations_history PK___EFMigrationsHistory; Type: CONSTRAINT; Schema: public; Owner: jellyfin +-- + +ALTER TABLE ONLY public.__ef_migrations_history + ADD CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY (migration_id); + + +-- +-- Name: access_schedules PK_AccessSchedules; Type: CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users.access_schedules + ADD CONSTRAINT "PK_AccessSchedules" PRIMARY KEY (id); + + +-- +-- Name: permissions PK_Permissions; Type: CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users.permissions + ADD CONSTRAINT "PK_Permissions" PRIMARY KEY (id); + + +-- +-- Name: preferences PK_Preferences; Type: CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users.preferences + ADD CONSTRAINT "PK_Preferences" PRIMARY KEY (id); + + +-- +-- Name: users PK_Users; Type: CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users.users + ADD CONSTRAINT "PK_Users" PRIMARY KEY (id); + + +-- +-- Name: IX_ActivityLogs_DateCreated; Type: INDEX; Schema: activitylog; Owner: jellyfin +-- + +CREATE INDEX "IX_ActivityLogs_DateCreated" ON activitylog.activity_logs USING btree (date_created); + + +-- +-- Name: idx_activitylogs_userid_datecreated; Type: INDEX; Schema: activitylog; Owner: jellyfin +-- + +CREATE INDEX idx_activitylogs_userid_datecreated ON activitylog.activity_logs USING btree (user_id, date_created DESC) WHERE (user_id IS NOT NULL); + + +-- +-- Name: IX_ApiKeys_AccessToken; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_ApiKeys_AccessToken" ON authentication.api_keys USING btree (access_token); + + +-- +-- Name: IX_DeviceOptions_DeviceId; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_DeviceOptions_DeviceId" ON authentication.device_options USING btree (device_id); + + +-- +-- Name: IX_Devices_AccessToken_DateLastActivity; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE INDEX "IX_Devices_AccessToken_DateLastActivity" ON authentication.devices USING btree (access_token, date_last_activity); + + +-- +-- Name: IX_Devices_DeviceId; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE INDEX "IX_Devices_DeviceId" ON authentication.devices USING btree (device_id); + + +-- +-- Name: IX_Devices_DeviceId_DateLastActivity; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE INDEX "IX_Devices_DeviceId_DateLastActivity" ON authentication.devices USING btree (device_id, date_last_activity); + + +-- +-- Name: IX_Devices_UserId_DeviceId; Type: INDEX; Schema: authentication; Owner: jellyfin +-- + +CREATE INDEX "IX_Devices_UserId_DeviceId" ON authentication.devices USING btree (user_id, device_id); + + +-- +-- Name: IX_CustomItemDisplayPreferences_UserId_ItemId_Client_Key; Type: INDEX; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_CustomItemDisplayPreferences_UserId_ItemId_Client_Key" ON displaypreferences.custom_item_display_preferences USING btree (user_id, item_id, client, key); + + +-- +-- Name: IX_DisplayPreferences_UserId_ItemId_Client; Type: INDEX; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_DisplayPreferences_UserId_ItemId_Client" ON displaypreferences.display_preferences USING btree (user_id, item_id, client); + + +-- +-- Name: IX_HomeSection_DisplayPreferencesId; Type: INDEX; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE INDEX "IX_HomeSection_DisplayPreferencesId" ON displaypreferences.home_sections USING btree (display_preferences_id); + + +-- +-- Name: IX_ItemDisplayPreferences_UserId; Type: INDEX; Schema: displaypreferences; Owner: jellyfin +-- + +CREATE INDEX "IX_ItemDisplayPreferences_UserId" ON displaypreferences.item_display_preferences USING btree (user_id); + + +-- +-- Name: IX_BaseItemImageInfos_ItemId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItemImageInfos_ItemId" ON library.base_item_image_infos USING btree (item_id); + + +-- +-- Name: IX_BaseItemLiveTvExtras_EndDate; Type: INDEX; Schema: library; Owner: postgres +-- + +CREATE INDEX "IX_BaseItemLiveTvExtras_EndDate" ON library.base_item_live_tv_extras USING btree (end_date); + + +-- +-- Name: IX_BaseItemLiveTvExtras_StartDate; Type: INDEX; Schema: library; Owner: postgres +-- + +CREATE INDEX "IX_BaseItemLiveTvExtras_StartDate" ON library.base_item_live_tv_extras USING btree (start_date); + + +-- +-- Name: IX_BaseItemMetadataFields_ItemId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItemMetadataFields_ItemId" ON library.base_item_metadata_fields USING btree (item_id); + + +-- +-- Name: IX_BaseItemTrailerTypes_ItemId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItemTrailerTypes_ItemId" ON library.base_item_trailer_types USING btree (item_id); + + +-- +-- Name: IX_BaseItemTvExtras_SeriesId; Type: INDEX; Schema: library; Owner: postgres +-- + +CREATE INDEX "IX_BaseItemTvExtras_SeriesId" ON library.base_item_tv_extras USING btree (series_id); + + +-- +-- Name: IX_BaseItemTvExtras_SeriesPresentationUniqueKey; Type: INDEX; Schema: library; Owner: postgres +-- + +CREATE INDEX "IX_BaseItemTvExtras_SeriesPresentationUniqueKey" ON library.base_item_tv_extras USING btree (series_presentation_unique_key); + + +-- +-- Name: IX_BaseItems_Id_Type_IsFolder_IsVirtualItem; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_Id_Type_IsFolder_IsVirtualItem" ON library.base_items USING btree (id, type, is_folder, is_virtual_item); + + +-- +-- Name: IX_BaseItems_ParentId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_ParentId" ON library.base_items USING btree (parent_id); + + +-- +-- Name: IX_BaseItems_Type_TopParentId_Id; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_BaseItems_Type_TopParentId_Id" ON library.base_items USING btree (type, top_parent_id, id); + + +-- +-- Name: IX_ImageInfos_UserId; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_ImageInfos_UserId" ON library.image_infos USING btree (user_id); + + +-- +-- Name: IX_ItemValues_Type_CleanValue; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_ItemValues_Type_CleanValue" ON library.item_values USING btree (type, clean_value); + + +-- +-- Name: IX_ItemValues_Type_Value; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_ItemValues_Type_Value" ON library.item_values USING btree (type, value); + + +-- +-- Name: IX_LibraryOptions_DateModified; Type: INDEX; Schema: library; Owner: postgres +-- + +CREATE INDEX "IX_LibraryOptions_DateModified" ON library.library_options USING btree (date_modified DESC); + + +-- +-- Name: IX_UserData_ItemId_UserId_IsFavorite; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_UserData_ItemId_UserId_IsFavorite" ON library.user_data USING btree (item_id, user_id, is_favorite); + + +-- +-- Name: IX_UserData_ItemId_UserId_LastPlayedDate; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_UserData_ItemId_UserId_LastPlayedDate" ON library.user_data USING btree (item_id, user_id, last_played_date); + + +-- +-- Name: IX_UserData_ItemId_UserId_PlaybackPositionTicks; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_UserData_ItemId_UserId_PlaybackPositionTicks" ON library.user_data USING btree (item_id, user_id, playback_position_ticks); + + +-- +-- Name: IX_UserData_ItemId_UserId_Played; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX "IX_UserData_ItemId_UserId_Played" ON library.user_data USING btree (item_id, user_id, played); + + +-- +-- Name: idx_itemvalues_cleanvalue; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_itemvalues_cleanvalue ON library.item_values USING btree (clean_value) WHERE (clean_value IS NOT NULL); + + +-- +-- Name: idx_itemvalues_id_cleanvalue; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_itemvalues_id_cleanvalue ON library.item_values USING btree (item_value_id, clean_value); + + +-- +-- Name: idx_itemvalues_type_value_expr; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_itemvalues_type_value_expr ON library.item_values USING btree ((((type)::text || value))); + + +-- +-- Name: idx_itemvalues_value; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_itemvalues_value ON library.item_values USING btree (value) WHERE (value IS NOT NULL); + + +-- +-- Name: idx_itemvaluesmap_itemvalueid_itemid; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX idx_itemvaluesmap_itemvalueid_itemid ON library.item_values_map USING btree (item_value_id, item_id); + + +-- +-- Name: mediastreaminfos_itemid_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX mediastreaminfos_itemid_idx ON library.media_stream_infos USING btree (item_id, stream_type); + + +-- +-- Name: peoplebaseitemmap_itemid_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX peoplebaseitemmap_itemid_idx ON library.people_base_item_map USING btree (item_id, people_id); + + +-- +-- Name: peoplebaseitemmap_peopleid_idx; Type: INDEX; Schema: library; Owner: jellyfin +-- + +CREATE INDEX peoplebaseitemmap_peopleid_idx ON library.people_base_item_map USING btree (people_id, item_id); + + +-- +-- Name: IX_AccessSchedules_UserId; Type: INDEX; Schema: users; Owner: jellyfin +-- + +CREATE INDEX "IX_AccessSchedules_UserId" ON users.access_schedules USING btree (user_id); + + +-- +-- Name: IX_Permissions_UserId_Kind; Type: INDEX; Schema: users; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_Permissions_UserId_Kind" ON users.permissions USING btree (user_id, kind) WHERE (user_id IS NOT NULL); + + +-- +-- Name: IX_Preferences_UserId_Kind; Type: INDEX; Schema: users; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_Preferences_UserId_Kind" ON users.preferences USING btree (user_id, kind) WHERE (user_id IS NOT NULL); + + +-- +-- Name: IX_Users_Username; Type: INDEX; Schema: users; Owner: jellyfin +-- + +CREATE UNIQUE INDEX "IX_Users_Username" ON users.users USING btree (username); + + +-- +-- Name: devices FK_Devices_Users_UserId; Type: FK CONSTRAINT; Schema: authentication; Owner: jellyfin +-- + +ALTER TABLE ONLY authentication.devices + ADD CONSTRAINT "FK_Devices_Users_UserId" FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; + + +-- +-- Name: display_preferences FK_DisplayPreferences_Users_UserId; Type: FK CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE ONLY displaypreferences.display_preferences + ADD CONSTRAINT "FK_DisplayPreferences_Users_UserId" FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; + + +-- +-- Name: home_sections FK_HomeSection_DisplayPreferences_DisplayPreferencesId; Type: FK CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE ONLY displaypreferences.home_sections + ADD CONSTRAINT "FK_HomeSection_DisplayPreferences_DisplayPreferencesId" FOREIGN KEY (display_preferences_id) REFERENCES displaypreferences.display_preferences(id) ON DELETE CASCADE; + + +-- +-- Name: item_display_preferences FK_ItemDisplayPreferences_Users_UserId; Type: FK CONSTRAINT; Schema: displaypreferences; Owner: jellyfin +-- + +ALTER TABLE ONLY displaypreferences.item_display_preferences + ADD CONSTRAINT "FK_ItemDisplayPreferences_Users_UserId" FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; + + +-- +-- Name: ancestor_ids FK_AncestorIds_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.ancestor_ids + ADD CONSTRAINT "FK_AncestorIds_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: ancestor_ids FK_AncestorIds_BaseItems_ParentItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.ancestor_ids + ADD CONSTRAINT "FK_AncestorIds_BaseItems_ParentItemId" FOREIGN KEY (parent_item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: attachment_stream_infos FK_AttachmentStreamInfos_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.attachment_stream_infos + ADD CONSTRAINT "FK_AttachmentStreamInfos_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: audio_stream_details FK_AudioStreamDetails_MediaStreamInfos_ItemId_StreamIndex; Type: FK CONSTRAINT; Schema: library; Owner: postgres +-- + +ALTER TABLE ONLY library.audio_stream_details + ADD CONSTRAINT "FK_AudioStreamDetails_MediaStreamInfos_ItemId_StreamIndex" FOREIGN KEY (item_id, stream_index) REFERENCES library.media_stream_infos(item_id, stream_index) ON DELETE CASCADE; + + +-- +-- Name: base_item_audio_extras FK_BaseItemAudioExtras_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: postgres +-- + +ALTER TABLE ONLY library.base_item_audio_extras + ADD CONSTRAINT "FK_BaseItemAudioExtras_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: base_item_image_infos FK_BaseItemImageInfos_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.base_item_image_infos + ADD CONSTRAINT "FK_BaseItemImageInfos_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: base_item_live_tv_extras FK_BaseItemLiveTvExtras_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: postgres +-- + +ALTER TABLE ONLY library.base_item_live_tv_extras + ADD CONSTRAINT "FK_BaseItemLiveTvExtras_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: base_item_metadata_fields FK_BaseItemMetadataFields_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.base_item_metadata_fields + ADD CONSTRAINT "FK_BaseItemMetadataFields_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: base_item_providers FK_BaseItemProviders_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.base_item_providers + ADD CONSTRAINT "FK_BaseItemProviders_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: base_item_trailer_types FK_BaseItemTrailerTypes_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.base_item_trailer_types + ADD CONSTRAINT "FK_BaseItemTrailerTypes_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: base_item_tv_extras FK_BaseItemTvExtras_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: postgres +-- + +ALTER TABLE ONLY library.base_item_tv_extras + ADD CONSTRAINT "FK_BaseItemTvExtras_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: base_items FK_BaseItems_BaseItems_ParentId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.base_items + ADD CONSTRAINT "FK_BaseItems_BaseItems_ParentId" FOREIGN KEY (parent_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: chapters FK_Chapters_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.chapters + ADD CONSTRAINT "FK_Chapters_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: image_infos FK_ImageInfos_Users_UserId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.image_infos + ADD CONSTRAINT "FK_ImageInfos_Users_UserId" FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; + + +-- +-- Name: item_values_map FK_ItemValuesMap_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.item_values_map + ADD CONSTRAINT "FK_ItemValuesMap_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: item_values_map FK_ItemValuesMap_ItemValues_ItemValueId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.item_values_map + ADD CONSTRAINT "FK_ItemValuesMap_ItemValues_ItemValueId" FOREIGN KEY (item_value_id) REFERENCES library.item_values(item_value_id) ON DELETE CASCADE; + + +-- +-- Name: keyframe_data FK_KeyframeData_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.keyframe_data + ADD CONSTRAINT "FK_KeyframeData_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: media_stream_infos FK_MediaStreamInfos_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.media_stream_infos + ADD CONSTRAINT "FK_MediaStreamInfos_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: people_base_item_map FK_PeopleBaseItemMap_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.people_base_item_map + ADD CONSTRAINT "FK_PeopleBaseItemMap_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: people_base_item_map FK_PeopleBaseItemMap_Peoples_PeopleId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.people_base_item_map + ADD CONSTRAINT "FK_PeopleBaseItemMap_Peoples_PeopleId" FOREIGN KEY (people_id) REFERENCES library.peoples(id) ON DELETE CASCADE; + + +-- +-- Name: user_data FK_UserData_BaseItems_ItemId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.user_data + ADD CONSTRAINT "FK_UserData_BaseItems_ItemId" FOREIGN KEY (item_id) REFERENCES library.base_items(id) ON DELETE CASCADE; + + +-- +-- Name: user_data FK_UserData_Users_UserId; Type: FK CONSTRAINT; Schema: library; Owner: jellyfin +-- + +ALTER TABLE ONLY library.user_data + ADD CONSTRAINT "FK_UserData_Users_UserId" FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; + + +-- +-- Name: video_stream_details FK_VideoStreamDetails_MediaStreamInfos_ItemId_StreamIndex; Type: FK CONSTRAINT; Schema: library; Owner: postgres +-- + +ALTER TABLE ONLY library.video_stream_details + ADD CONSTRAINT "FK_VideoStreamDetails_MediaStreamInfos_ItemId_StreamIndex" FOREIGN KEY (item_id, stream_index) REFERENCES library.media_stream_infos(item_id, stream_index) ON DELETE CASCADE; + + +-- +-- Name: access_schedules FK_AccessSchedules_Users_UserId; Type: FK CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users.access_schedules + ADD CONSTRAINT "FK_AccessSchedules_Users_UserId" FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; + + +-- +-- Name: permissions FK_Permissions_Users_UserId; Type: FK CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users.permissions + ADD CONSTRAINT "FK_Permissions_Users_UserId" FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; + + +-- +-- Name: preferences FK_Preferences_Users_UserId; Type: FK CONSTRAINT; Schema: users; Owner: jellyfin +-- + +ALTER TABLE ONLY users.preferences + ADD CONSTRAINT "FK_Preferences_Users_UserId" FOREIGN KEY (user_id) REFERENCES users.users(id) ON DELETE CASCADE; + + +-- +-- PostgreSQL database dump complete +-- + +\unrestrict Vwcqwiq0T7Wa2mK8KvZhGZRaSeFcgOrgunEbjWSCbLeRLSwJLeXqBprmQroWe9O + diff --git a/sql/schema_init/jellyfin_schema_03152026.sql b/sql/schema_init/jellyfin_schema_03152026.sql deleted file mode 100644 index 5a989fe8..00000000 Binary files a/sql/schema_init/jellyfin_schema_03152026.sql and /dev/null differ diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemAudioExtras.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemAudioExtras.cs new file mode 100644 index 00000000..dbd8f08f --- /dev/null +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemAudioExtras.cs @@ -0,0 +1,49 @@ +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +namespace Jellyfin.Database.Implementations.Entities; + +using System; + +/// +/// Extension table for music-specific columns on . +/// Populated only for Audio.Audio items. +/// +public class BaseItemAudioExtras +{ + /// + /// Gets or sets the ID of the parent . Primary key and foreign key. + /// + public required Guid ItemId { get; set; } + + /// + /// Gets or sets the navigation back to the owning . + /// + public BaseItemEntity? Item { get; set; } + + /// + /// Gets or sets the album name this track belongs to. + /// + public string? Album { get; set; } + + /// + /// Gets or sets the serialized list of track artists. + /// + public string? Artists { get; set; } + + /// + /// Gets or sets the serialized list of album artists. + /// + public string? AlbumArtists { get; set; } + + /// + /// Gets or sets the loudness units relative to full scale (LUFS) value for normalization. + /// + public float? LUFS { get; set; } + + /// + /// Gets or sets the normalization gain in decibels. + /// + public float? NormalizationGain { get; set; } +} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemEntity.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemEntity.cs index e41a7cdd..4dd864a5 100644 --- a/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemEntity.cs +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemEntity.cs @@ -21,10 +21,6 @@ public class BaseItemEntity public string? Path { get; set; } - public DateTime? StartDate { get; set; } - - public DateTime? EndDate { get; set; } - public Guid? ChannelId { get; set; } public bool IsMovie { get; set; } @@ -65,8 +61,6 @@ public class BaseItemEntity public bool IsSeries { get; set; } - public string? EpisodeTitle { get; set; } - public bool IsRepeat { get; set; } public string? PreferredMetadataLanguage { get; set; } @@ -81,8 +75,6 @@ public class BaseItemEntity public string? Studios { get; set; } - public string? ExternalServiceId { get; set; } - public string? Tags { get; set; } public bool IsFolder { get; set; } @@ -105,20 +97,8 @@ public class BaseItemEntity public DateTime? DateLastMediaAdded { get; set; } - public string? Album { get; set; } - - public float? LUFS { get; set; } - - public float? NormalizationGain { get; set; } - public bool IsVirtualItem { get; set; } - public string? SeriesName { get; set; } - - public string? SeasonName { get; set; } - - public string? ExternalSeriesId { get; set; } - public string? Tagline { get; set; } public string? ProductionLocations { get; set; } @@ -129,16 +109,8 @@ public class BaseItemEntity public BaseItemExtraType? ExtraType { get; set; } - public string? Artists { get; set; } - - public string? AlbumArtists { get; set; } - public string? ExternalId { get; set; } - public string? SeriesPresentationUniqueKey { get; set; } - - public string? ShowId { get; set; } - public string? OwnerId { get; set; } public int? Width { get; set; } @@ -147,17 +119,20 @@ public class BaseItemEntity public long? Size { get; set; } - public ProgramAudioEntity? Audio { get; set; } - public Guid? ParentId { get; set; } public BaseItemEntity? DirectParent { get; set; } public Guid? TopParentId { get; set; } - public Guid? SeasonId { get; set; } + /// Gets or sets navigation to TV-specific extension data. Populated for TV.Episode, TV.Season, and TV.Series. + public BaseItemTvExtras? TvExtras { get; set; } - public Guid? SeriesId { get; set; } + /// Gets or sets navigation to LiveTV-specific extension data. Populated for LiveTvProgram and LiveTvChannel. + public BaseItemLiveTvExtras? LiveTvExtras { get; set; } + + /// Gets or sets navigation to music-specific extension data. Populated for Audio.Audio. + public BaseItemAudioExtras? AudioExtras { get; set; } public ICollection? Peoples { get; set; } diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemLiveTvExtras.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemLiveTvExtras.cs new file mode 100644 index 00000000..067bae4c --- /dev/null +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemLiveTvExtras.cs @@ -0,0 +1,59 @@ +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +namespace Jellyfin.Database.Implementations.Entities; + +using System; + +/// +/// Extension table for LiveTV-specific columns on . +/// Populated only for LiveTvProgram and LiveTvChannel items. +/// +public class BaseItemLiveTvExtras +{ + /// + /// Gets or sets the ID of the parent . Primary key and foreign key. + /// + public required Guid ItemId { get; set; } + + /// + /// Gets or sets the navigation back to the owning . + /// + public BaseItemEntity? Item { get; set; } + + /// + /// Gets or sets the scheduled start date/time of the program. + /// + public DateTime? StartDate { get; set; } + + /// + /// Gets or sets the scheduled end date/time of the program. + /// + public DateTime? EndDate { get; set; } + + /// + /// Gets or sets the episode title for the program, if it is an episode broadcast. + /// + public string? EpisodeTitle { get; set; } + + /// + /// Gets or sets the series ID used to correlate this program to its show. Populated for LiveTvProgram. + /// + public string? ShowId { get; set; } + + /// + /// Gets or sets the external series identifier. Populated for LiveTvProgram. + /// + public string? ExternalSeriesId { get; set; } + + /// + /// Gets or sets the service name for the channel. Populated for LiveTvChannel. + /// + public string? ExternalServiceId { get; set; } + + /// + /// Gets or sets the audio type for the program. + /// + public ProgramAudioEntity? Audio { get; set; } +} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemTvExtras.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemTvExtras.cs new file mode 100644 index 00000000..7071fba6 --- /dev/null +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/BaseItemTvExtras.cs @@ -0,0 +1,49 @@ +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +namespace Jellyfin.Database.Implementations.Entities; + +using System; + +/// +/// Extension table for TV-specific columns on . +/// Populated only for TV.Episode, TV.Season, and TV.Series items. +/// +public class BaseItemTvExtras +{ + /// + /// Gets or sets the ID of the parent . Primary key and foreign key. + /// + public required Guid ItemId { get; set; } + + /// + /// Gets or sets the navigation back to the owning . + /// + public BaseItemEntity? Item { get; set; } + + /// + /// Gets or sets the ID of the series this item belongs to. + /// + public Guid? SeriesId { get; set; } + + /// + /// Gets or sets the ID of the season this item belongs to. Populated for episodes only. + /// + public Guid? SeasonId { get; set; } + + /// + /// Gets or sets the name of the series. + /// + public string? SeriesName { get; set; } + + /// + /// Gets or sets the name of the season. Populated for episodes only. + /// + public string? SeasonName { get; set; } + + /// + /// Gets or sets the unique key used to group items belonging to the same series. + /// + public string? SeriesPresentationUniqueKey { get; set; } +} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Views/ItemPersonView.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Views/ItemPersonView.cs new file mode 100644 index 00000000..9763684f --- /dev/null +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Views/ItemPersonView.cs @@ -0,0 +1,39 @@ +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +namespace Jellyfin.Database.Implementations.Entities.Views; + +#pragma warning disable CS1591 +#pragma warning disable SA1600 + +using System; + +/// +/// Read-only projection of the library."ItemPeople_v" view. +/// All cast and crew entries linked to the items they appear in. +/// +public class ItemPersonView +{ + public Guid? ItemId { get; set; } + + public string? ItemType { get; set; } + + public string? ItemName { get; set; } + + public string? SeriesName { get; set; } + + public int? ProductionYear { get; set; } + + public Guid? PersonId { get; set; } + + public string? PersonName { get; set; } + + public string? PersonType { get; set; } + + public string? Role { get; set; } + + public int? SortOrder { get; set; } + + public int? ListOrder { get; set; } +} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Views/ItemProviderView.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Views/ItemProviderView.cs new file mode 100644 index 00000000..bef8bcff --- /dev/null +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Views/ItemProviderView.cs @@ -0,0 +1,48 @@ +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +namespace Jellyfin.Database.Implementations.Entities.Views; + +#pragma warning disable CS1591 +#pragma warning disable SA1600 + +using System; + +/// +/// Read-only projection of library."ItemProviders_v". +/// Items with external provider IDs pivoted into named columns. +/// +public class ItemProviderView +{ + public Guid? ItemId { get; set; } + + public string? Type { get; set; } + + public string? Name { get; set; } + + public string? OriginalTitle { get; set; } + + public int? ProductionYear { get; set; } + + public string? SeriesName { get; set; } + + public int? EpisodeNumber { get; set; } + + public int? SeasonNumber { get; set; } + + public string? ImdbId { get; set; } + + public string? TmdbId { get; set; } + + public string? TvdbId { get; set; } + + public string? TvRageId { get; set; } + + public string? MusicBrainzAlbumId { get; set; } + + public string? MusicBrainzArtistId { get; set; } + + /// Gets or sets remaining providers as a JSON object string. + public string? OtherProviders { get; set; } +} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Views/LibrarySummaryView.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Views/LibrarySummaryView.cs new file mode 100644 index 00000000..425b405f --- /dev/null +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Views/LibrarySummaryView.cs @@ -0,0 +1,49 @@ +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +namespace Jellyfin.Database.Implementations.Entities.Views; + +#pragma warning disable CS1591 +#pragma warning disable SA1600 + +/// +/// Read-only projection of the library."LibrarySummary_v" view. +/// One row per item type with aggregate statistics across the whole library. +/// +public class LibrarySummaryView +{ + public string? Type { get; set; } + + public long? ItemCount { get; set; } + + public long? WithYear { get; set; } + + public int? OldestYear { get; set; } + + public int? NewestYear { get; set; } + + public decimal? AvgCommunityRating { get; set; } + + public decimal? TotalRunTimeTicks { get; set; } + + public decimal? TotalRuntimeHours { get; set; } + + public decimal? TotalSizeBytes { get; set; } + + public decimal? TotalSizeGB { get; set; } + + public long? Count4K { get; set; } + + public long? Count1080p { get; set; } + + public long? Count720p { get; set; } + + public long? CountSD { get; set; } + + public long? CountDolbyVision { get; set; } + + public long? CountHDR10Plus { get; set; } + + public long? CountHDR10 { get; set; } +} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Views/MediaStreamInfoView.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Views/MediaStreamInfoView.cs new file mode 100644 index 00000000..c021a316 --- /dev/null +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Views/MediaStreamInfoView.cs @@ -0,0 +1,113 @@ +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +namespace Jellyfin.Database.Implementations.Entities.Views; + +#pragma warning disable CS1591 +#pragma warning disable SA1600 + +using System; + +/// +/// Read-only projection of library."MediaStreamInfos_v". +/// Flat view of all media streams with audio- and video-specific columns merged. +/// +public class MediaStreamInfoView +{ + public Guid? ItemId { get; set; } + + public int? StreamIndex { get; set; } + + public int? StreamType { get; set; } + + public string? Codec { get; set; } + + public string? Language { get; set; } + + public string? Profile { get; set; } + + public string? Path { get; set; } + + public int? BitRate { get; set; } + + public bool? IsDefault { get; set; } + + public bool? IsForced { get; set; } + + public bool? IsExternal { get; set; } + + public float? Level { get; set; } + + public string? CodecTag { get; set; } + + public string? Comment { get; set; } + + public bool? IsAvc { get; set; } + + public string? Title { get; set; } + + public string? TimeBase { get; set; } + + public string? CodecTimeBase { get; set; } + + // audio-specific + public string? ChannelLayout { get; set; } + + public int? Channels { get; set; } + + public int? SampleRate { get; set; } + + public bool? IsHearingImpaired { get; set; } + + // video-specific + public string? AspectRatio { get; set; } + + public bool? IsInterlaced { get; set; } + + public int? Height { get; set; } + + public int? Width { get; set; } + + public float? AverageFrameRate { get; set; } + + public float? RealFrameRate { get; set; } + + public string? PixelFormat { get; set; } + + public int? BitDepth { get; set; } + + public bool? IsAnamorphic { get; set; } + + public int? RefFrames { get; set; } + + public string? NalLengthSize { get; set; } + + public string? ColorPrimaries { get; set; } + + public string? ColorSpace { get; set; } + + public string? ColorTransfer { get; set; } + + public int? DvVersionMajor { get; set; } + + public int? DvVersionMinor { get; set; } + + public int? DvProfile { get; set; } + + public int? DvLevel { get; set; } + + public int? RpuPresentFlag { get; set; } + + public int? ElPresentFlag { get; set; } + + public int? BlPresentFlag { get; set; } + + public int? DvBlSignalCompatibilityId { get; set; } + + public int? Rotation { get; set; } + + public string? KeyFrames { get; set; } + + public bool? Hdr10PlusPresentFlag { get; set; } +} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Views/UserPlaybackHistoryView.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Views/UserPlaybackHistoryView.cs new file mode 100644 index 00000000..81438953 --- /dev/null +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Views/UserPlaybackHistoryView.cs @@ -0,0 +1,58 @@ +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +namespace Jellyfin.Database.Implementations.Entities.Views; + +#pragma warning disable CS1591 +#pragma warning disable SA1600 + +using System; + +/// +/// Read-only projection of library."UserPlaybackHistory_v". +/// Per-user watch history with calculated progress percentage. +/// +public class UserPlaybackHistoryView +{ + public string? Username { get; set; } + + public Guid? UserId { get; set; } + + public string? ItemName { get; set; } + + public string? ItemType { get; set; } + + public string? SeriesName { get; set; } + + public string? SeasonName { get; set; } + + public int? EpisodeNumber { get; set; } + + public int? SeasonNumber { get; set; } + + public int? ProductionYear { get; set; } + + public long? RunTimeTicks { get; set; } + + public Guid? ItemId { get; set; } + + public bool? Played { get; set; } + + public int? PlayCount { get; set; } + + public DateTimeOffset? LastPlayedDate { get; set; } + + public long? PlaybackPositionTicks { get; set; } + + /// Gets or sets playback progress 0–100. NULL when no runtime. + public decimal? ProgressPct { get; set; } + + public bool? IsFavorite { get; set; } + + public double? Rating { get; set; } + + public int? AudioStreamIndex { get; set; } + + public int? SubtitleStreamIndex { get; set; } +} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Views/VideoItemView.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Views/VideoItemView.cs new file mode 100644 index 00000000..db2176cf --- /dev/null +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/Entities/Views/VideoItemView.cs @@ -0,0 +1,88 @@ +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +namespace Jellyfin.Database.Implementations.Entities.Views; + +#pragma warning disable CS1591 +#pragma warning disable SA1600 + +using System; + +/// +/// Read-only projection of library."VideoItems_v". +/// Every non-folder, non-virtual item with at least one video stream. +/// +public class VideoItemView +{ + public Guid? ItemId { get; set; } + + public string? Type { get; set; } + + public string? Name { get; set; } + + public string? OriginalTitle { get; set; } + + public int? ProductionYear { get; set; } + + public string? OfficialRating { get; set; } + + public float? CommunityRating { get; set; } + + public long? RunTimeTicks { get; set; } + + public string? Path { get; set; } + + public DateTimeOffset? DateCreated { get; set; } + + public DateTimeOffset? DateModified { get; set; } + + public string? SeriesName { get; set; } + + public string? SeasonName { get; set; } + + public int? EpisodeNumber { get; set; } + + public int? SeasonNumber { get; set; } + + public int? TotalBitrate { get; set; } + + public long? Size { get; set; } + + public string? VideoCodec { get; set; } + + public string? VideoProfile { get; set; } + + public int? Width { get; set; } + + public int? Height { get; set; } + + public float? AverageFrameRate { get; set; } + + public int? BitDepth { get; set; } + + public string? PixelFormat { get; set; } + + public string? ColorSpace { get; set; } + + public string? ColorTransfer { get; set; } + + public string? ColorPrimaries { get; set; } + + public bool? IsInterlaced { get; set; } + + public bool? IsAnamorphic { get; set; } + + public string? AspectRatio { get; set; } + + public bool? IsDolbyVision { get; set; } + + public bool? IsHDR10Plus { get; set; } + + /// Gets or sets derived HDR format: "Dolby Vision", "HDR10+", "HDR10", "HLG", or "SDR". + public string? HDRFormat { get; set; } + + public long? AudioTrackCount { get; set; } + + public long? SubtitleTrackCount { get; set; } +} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/JellyfinDbContext.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/JellyfinDbContext.cs index 9b01153b..4ca6946a 100644 --- a/src/Jellyfin.Database/Jellyfin.Database.Implementations/JellyfinDbContext.cs +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/JellyfinDbContext.cs @@ -14,6 +14,7 @@ using System.Threading; using System.Threading.Tasks; using Jellyfin.Database.Implementations.Entities; using Jellyfin.Database.Implementations.Entities.Security; +using Jellyfin.Database.Implementations.Entities.Views; using Jellyfin.Database.Implementations.Interfaces; using Jellyfin.Database.Implementations.Locking; using Microsoft.EntityFrameworkCore; @@ -156,6 +157,44 @@ public class JellyfinDbContext(DbContextOptions options, ILog ///
    public DbSet VideoStreamDetails => this.Set(); + // ── Read-only view projections (PostgreSQL only) ────────────────────── + + /// + /// Gets the flat view over MediaStreamInfos joined with audio and video detail tables. + /// Maps to library."MediaStreamInfos_v". + /// + public DbSet MediaStreamInfoViews => this.Set(); + + /// + /// Gets the view of video items joined with their primary stream details. + /// Maps to library."VideoItems_v". + /// + public DbSet VideoItemViews => this.Set(); + + /// + /// Gets the view of per-user watch history with calculated progress. + /// Maps to library."UserPlaybackHistory_v". + /// + public DbSet UserPlaybackHistoryViews => this.Set(); + + /// + /// Gets the view of items with pivoted external provider IDs. + /// Maps to library."ItemProviders_v". + /// + public DbSet ItemProviderViews => this.Set(); + + /// + /// Gets the view of cast and crew entries linked to their items. + /// Maps to library."ItemPeople_v". + /// + public DbSet ItemPersonViews => this.Set(); + + /// + /// Gets the aggregate library statistics view, one row per item type. + /// Maps to library."LibrarySummary_v". + /// + public DbSet LibrarySummaryViews => this.Set(); + /// /// Gets the . /// @@ -196,6 +235,21 @@ public class JellyfinDbContext(DbContextOptions options, ILog ///
    public DbSet LibraryOptions => this.Set(); + /// + /// Gets the containing TV-specific extension data for BaseItems. + /// + public DbSet BaseItemTvExtras => this.Set(); + + /// + /// Gets the containing LiveTV-specific extension data for BaseItems. + /// + public DbSet BaseItemLiveTvExtras => this.Set(); + + /// + /// Gets the containing music-specific extension data for BaseItems. + /// + public DbSet BaseItemAudioExtras => this.Set(); + /*public DbSet Artwork => Set(); public DbSet Books => Set(); diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/AudioStreamDetailsConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/AudioStreamDetailsConfiguration.cs index 89e751dd..9d6dcd4e 100644 --- a/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/AudioStreamDetailsConfiguration.cs +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/AudioStreamDetailsConfiguration.cs @@ -19,6 +19,6 @@ public class AudioStreamDetailsConfiguration : IEntityTypeConfiguration new { e.ItemId, e.StreamIndex }); - builder.ToTable("AudioStreamDetails", "library"); + builder.ToTable("audio_stream_details", "library"); } } diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemAudioExtrasConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemAudioExtrasConfiguration.cs new file mode 100644 index 00000000..2b20bb9c --- /dev/null +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemAudioExtrasConfiguration.cs @@ -0,0 +1,30 @@ +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +namespace Jellyfin.Database.Implementations.ModelConfiguration; + +using System; +using Jellyfin.Database.Implementations.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +/// +/// EF Core configuration for . +/// +public class BaseItemAudioExtrasConfiguration : IEntityTypeConfiguration +{ + /// + public void Configure(EntityTypeBuilder builder) + { + ArgumentNullException.ThrowIfNull(builder); + + builder.HasKey(e => e.ItemId); + builder.ToTable("base_item_audio_extras", "library"); + + builder.HasOne(e => e.Item) + .WithOne(e => e.AudioExtras) + .HasForeignKey(e => e.ItemId) + .OnDelete(DeleteBehavior.Cascade); + } +} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemConfiguration.cs index 32cabc20..9719e3b6 100644 --- a/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemConfiguration.cs +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemConfiguration.cs @@ -46,14 +46,7 @@ public class BaseItemConfiguration : IEntityTypeConfiguration // covering index builder.HasIndex(e => new { e.TopParentId, e.Id }); - // series - builder.HasIndex(e => new { e.Type, e.SeriesPresentationUniqueKey, e.PresentationUniqueKey, e.SortName }); - // series counts - // seriesdateplayed sort order - builder.HasIndex(e => new { e.Type, e.SeriesPresentationUniqueKey, e.IsFolder, e.IsVirtualItem }); // live tv programs - builder.HasIndex(e => new { e.Type, e.TopParentId, e.StartDate }); - // covering index for getitemvalues builder.HasIndex(e => new { e.Type, e.TopParentId, e.Id }); // used by movie suggestions builder.HasIndex(e => new { e.Type, e.TopParentId, e.PresentationUniqueKey }); diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemLiveTvExtrasConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemLiveTvExtrasConfiguration.cs new file mode 100644 index 00000000..dea8fd96 --- /dev/null +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemLiveTvExtrasConfiguration.cs @@ -0,0 +1,34 @@ +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +namespace Jellyfin.Database.Implementations.ModelConfiguration; + +using System; +using Jellyfin.Database.Implementations.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +/// +/// EF Core configuration for . +/// +public class BaseItemLiveTvExtrasConfiguration : IEntityTypeConfiguration +{ + /// + public void Configure(EntityTypeBuilder builder) + { + ArgumentNullException.ThrowIfNull(builder); + + builder.HasKey(e => e.ItemId); + builder.ToTable("base_item_live_tv_extras", "library"); + + builder.HasOne(e => e.Item) + .WithOne(e => e.LiveTvExtras) + .HasForeignKey(e => e.ItemId) + .OnDelete(DeleteBehavior.Cascade); + + // Schedule range queries — mirrors the existing StartDate index on BaseItems + builder.HasIndex(e => e.StartDate); + builder.HasIndex(e => e.EndDate); + } +} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemTvExtrasConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemTvExtrasConfiguration.cs new file mode 100644 index 00000000..3adaf0fa --- /dev/null +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/BaseItemTvExtrasConfiguration.cs @@ -0,0 +1,33 @@ +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +namespace Jellyfin.Database.Implementations.ModelConfiguration; + +using System; +using Jellyfin.Database.Implementations.Entities; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; + +/// +/// EF Core configuration for . +/// +public class BaseItemTvExtrasConfiguration : IEntityTypeConfiguration +{ + /// + public void Configure(EntityTypeBuilder builder) + { + ArgumentNullException.ThrowIfNull(builder); + + builder.HasKey(e => e.ItemId); + builder.ToTable("base_item_tv_extras", "library"); + + builder.HasOne(e => e.Item) + .WithOne(e => e.TvExtras) + .HasForeignKey(e => e.ItemId) + .OnDelete(DeleteBehavior.Cascade); + + builder.HasIndex(e => e.SeriesId); + builder.HasIndex(e => e.SeriesPresentationUniqueKey); + } +} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/HomeSectionConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/HomeSectionConfiguration.cs index 55512121..56a5cece 100644 --- a/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/HomeSectionConfiguration.cs +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/HomeSectionConfiguration.cs @@ -19,8 +19,7 @@ namespace Jellyfin.Database.Implementations.ModelConfiguration { ArgumentNullException.ThrowIfNull(builder); - // Explicitly set table name to singular to match the migration - builder.ToTable("HomeSection", "displaypreferences"); + builder.ToTable("home_sections", "displaypreferences"); builder.HasKey(e => e.Id); diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/LibraryOptionsEntityConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/LibraryOptionsEntityConfiguration.cs index bace6296..4912b36a 100644 --- a/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/LibraryOptionsEntityConfiguration.cs +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/LibraryOptionsEntityConfiguration.cs @@ -18,7 +18,7 @@ public class LibraryOptionsEntityConfiguration : IEntityTypeConfiguration builder) { ArgumentNullException.ThrowIfNull(builder); - builder.ToTable("LibraryOptions", "library"); + builder.ToTable("library_options", "library"); builder.HasKey(e => e.LibraryPath); builder.Property(e => e.LibraryPath).IsRequired(); builder.Property(e => e.OptionsJson).IsRequired().HasColumnType("jsonb"); diff --git a/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/VideoStreamDetailsConfiguration.cs b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/VideoStreamDetailsConfiguration.cs index 0995ad12..921d3661 100644 --- a/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/VideoStreamDetailsConfiguration.cs +++ b/src/Jellyfin.Database/Jellyfin.Database.Implementations/ModelConfiguration/VideoStreamDetailsConfiguration.cs @@ -19,6 +19,6 @@ public class VideoStreamDetailsConfiguration : IEntityTypeConfiguration new { e.ItemId, e.StreamIndex }); - builder.ToTable("VideoStreamDetails", "library"); + builder.ToTable("video_stream_details", "library"); } } diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/BulkOperationTransaction.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/BulkOperationTransaction.cs index 6e9f2193..1e059eb5 100644 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/BulkOperationTransaction.cs +++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/BulkOperationTransaction.cs @@ -113,7 +113,6 @@ public sealed class BulkOperationTransaction : IAsyncDisposable, IDisposable _transaction?.Dispose(); _transaction = null; _disposed = true; - GC.SuppressFinalize(this); } /// @@ -134,7 +133,6 @@ public sealed class BulkOperationTransaction : IAsyncDisposable, IDisposable _transaction = null; _disposed = true; - GC.SuppressFinalize(this); } } diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/Migrations/SplitMediaStreamInfos.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/Migrations/20260502000000_SplitMediaStreamInfos.cs similarity index 100% rename from src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/Migrations/SplitMediaStreamInfos.cs rename to src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/Migrations/20260502000000_SplitMediaStreamInfos.cs diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/Migrations/DropBaseItemFlatExtensionColumns.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/Migrations/DropBaseItemFlatExtensionColumns.cs new file mode 100644 index 00000000..69a3835d --- /dev/null +++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/Migrations/DropBaseItemFlatExtensionColumns.cs @@ -0,0 +1,109 @@ +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Jellyfin.Database.Providers.Postgres.Migrations +{ + /// + /// Removes the 17 flat extension columns from library.BaseItems now that all data has been + /// migrated to the BaseItemTvExtras, BaseItemLiveTvExtras, and BaseItemAudioExtras tables. + /// Must run AFTER SplitBaseItemExtras (20260503000000). + /// + public partial class DropBaseItemFlatExtensionColumns : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + // ── 1. Drop indexes that reference columns being removed ─────────────── + migrationBuilder.DropIndex( + name: "IX_BaseItems_Type_TopParentId_StartDate", + schema: "library", + table: "BaseItems"); + + migrationBuilder.DropIndex( + name: "IX_BaseItems_Type_SeriesPresentationUniqueKey_IsFolder_IsVirtualItem", + schema: "library", + table: "BaseItems"); + + migrationBuilder.DropIndex( + name: "IX_BaseItems_Type_SeriesPresentationUniqueKey_PresentationUniqueKey_SortName", + schema: "library", + table: "BaseItems"); + + // ── 2. Drop 17 flat columns (now in extension tables) ───────────────── + // TV-specific → BaseItemTvExtras + migrationBuilder.DropColumn(name: "SeriesId", schema: "library", table: "BaseItems"); + migrationBuilder.DropColumn(name: "SeasonId", schema: "library", table: "BaseItems"); + migrationBuilder.DropColumn(name: "SeriesName", schema: "library", table: "BaseItems"); + migrationBuilder.DropColumn(name: "SeasonName", schema: "library", table: "BaseItems"); + migrationBuilder.DropColumn(name: "SeriesPresentationUniqueKey", schema: "library", table: "BaseItems"); + + // LiveTV-specific → BaseItemLiveTvExtras + migrationBuilder.DropColumn(name: "StartDate", schema: "library", table: "BaseItems"); + migrationBuilder.DropColumn(name: "EndDate", schema: "library", table: "BaseItems"); + migrationBuilder.DropColumn(name: "EpisodeTitle", schema: "library", table: "BaseItems"); + migrationBuilder.DropColumn(name: "ShowId", schema: "library", table: "BaseItems"); + migrationBuilder.DropColumn(name: "ExternalSeriesId", schema: "library", table: "BaseItems"); + migrationBuilder.DropColumn(name: "ExternalServiceId", schema: "library", table: "BaseItems"); + migrationBuilder.DropColumn(name: "Audio", schema: "library", table: "BaseItems"); + + // Audio-specific → BaseItemAudioExtras + migrationBuilder.DropColumn(name: "Album", schema: "library", table: "BaseItems"); + migrationBuilder.DropColumn(name: "Artists", schema: "library", table: "BaseItems"); + migrationBuilder.DropColumn(name: "AlbumArtists", schema: "library", table: "BaseItems"); + migrationBuilder.DropColumn(name: "LUFS", schema: "library", table: "BaseItems"); + migrationBuilder.DropColumn(name: "NormalizationGain", schema: "library", table: "BaseItems"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + // Re-add TV columns + migrationBuilder.AddColumn(name: "SeriesId", schema: "library", table: "BaseItems", type: "uuid", nullable: true); + migrationBuilder.AddColumn(name: "SeasonId", schema: "library", table: "BaseItems", type: "uuid", nullable: true); + migrationBuilder.AddColumn(name: "SeriesName", schema: "library", table: "BaseItems", type: "text", nullable: true); + migrationBuilder.AddColumn(name: "SeasonName", schema: "library", table: "BaseItems", type: "text", nullable: true); + migrationBuilder.AddColumn(name: "SeriesPresentationUniqueKey", schema: "library", table: "BaseItems", type: "text", nullable: true); + + // Re-add LiveTV columns + migrationBuilder.AddColumn(name: "StartDate", schema: "library", table: "BaseItems", type: "timestamp with time zone", nullable: true); + migrationBuilder.AddColumn(name: "EndDate", schema: "library", table: "BaseItems", type: "timestamp with time zone", nullable: true); + migrationBuilder.AddColumn(name: "EpisodeTitle", schema: "library", table: "BaseItems", type: "text", nullable: true); + migrationBuilder.AddColumn(name: "ShowId", schema: "library", table: "BaseItems", type: "text", nullable: true); + migrationBuilder.AddColumn(name: "ExternalSeriesId", schema: "library", table: "BaseItems", type: "text", nullable: true); + migrationBuilder.AddColumn(name: "ExternalServiceId", schema: "library", table: "BaseItems", type: "text", nullable: true); + migrationBuilder.AddColumn(name: "Audio", schema: "library", table: "BaseItems", type: "integer", nullable: true); + + // Re-add Audio columns + migrationBuilder.AddColumn(name: "Album", schema: "library", table: "BaseItems", type: "text", nullable: true); + migrationBuilder.AddColumn(name: "Artists", schema: "library", table: "BaseItems", type: "text", nullable: true); + migrationBuilder.AddColumn(name: "AlbumArtists", schema: "library", table: "BaseItems", type: "text", nullable: true); + migrationBuilder.AddColumn(name: "LUFS", schema: "library", table: "BaseItems", type: "real", nullable: true); + migrationBuilder.AddColumn(name: "NormalizationGain", schema: "library", table: "BaseItems", type: "real", nullable: true); + + // Re-create dropped indexes + migrationBuilder.CreateIndex( + name: "IX_BaseItems_Type_TopParentId_StartDate", + schema: "library", + table: "BaseItems", + columns: new[] { "Type", "TopParentId", "StartDate" }); + + migrationBuilder.CreateIndex( + name: "IX_BaseItems_Type_SeriesPresentationUniqueKey_IsFolder_IsVirtualItem", + schema: "library", + table: "BaseItems", + columns: new[] { "Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem" }); + + migrationBuilder.CreateIndex( + name: "IX_BaseItems_Type_SeriesPresentationUniqueKey_PresentationUniqueKey_SortName", + schema: "library", + table: "BaseItems", + columns: new[] { "Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName" }); + } + } +} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/Migrations/JellyfinDbContextModelSnapshot.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/Migrations/JellyfinDbContextModelSnapshot.cs index 165daf4b..44bb191b 100644 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/Migrations/JellyfinDbContextModelSnapshot.cs +++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/Migrations/JellyfinDbContextModelSnapshot.cs @@ -148,18 +148,6 @@ namespace Jellyfin.Database.Providers.Postgres.Migrations .ValueGeneratedOnAdd() .HasColumnType("uuid"); - b.Property("Album") - .HasColumnType("text"); - - b.Property("AlbumArtists") - .HasColumnType("text"); - - b.Property("Artists") - .HasColumnType("text"); - - b.Property("Audio") - .HasColumnType("integer"); - b.Property("ChannelId") .HasColumnType("uuid"); @@ -193,21 +181,9 @@ namespace Jellyfin.Database.Providers.Postgres.Migrations b.Property("DateModified") .HasColumnType("timestamp with time zone"); - b.Property("EndDate") - .HasColumnType("timestamp with time zone"); - - b.Property("EpisodeTitle") - .HasColumnType("text"); - b.Property("ExternalId") .HasColumnType("text"); - b.Property("ExternalSeriesId") - .HasColumnType("text"); - - b.Property("ExternalServiceId") - .HasColumnType("text"); - b.Property("ExtraIds") .HasColumnType("text"); @@ -253,18 +229,12 @@ namespace Jellyfin.Database.Providers.Postgres.Migrations b.Property("IsVirtualItem") .HasColumnType("boolean"); - b.Property("LUFS") - .HasColumnType("real"); - b.Property("MediaType") .HasColumnType("text"); b.Property("Name") .HasColumnType("text"); - b.Property("NormalizationGain") - .HasColumnType("real"); - b.Property("OfficialRating") .HasColumnType("text"); @@ -310,33 +280,12 @@ namespace Jellyfin.Database.Providers.Postgres.Migrations b.Property("RunTimeTicks") .HasColumnType("bigint"); - b.Property("SeasonId") - .HasColumnType("uuid"); - - b.Property("SeasonName") - .HasColumnType("text"); - - b.Property("SeriesId") - .HasColumnType("uuid"); - - b.Property("SeriesName") - .HasColumnType("text"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("text"); - - b.Property("ShowId") - .HasColumnType("text"); - b.Property("Size") .HasColumnType("bigint"); b.Property("SortName") .HasColumnType("text"); - b.Property("StartDate") - .HasColumnType("timestamp with time zone"); - b.Property("Studios") .HasColumnType("text"); @@ -376,16 +325,10 @@ namespace Jellyfin.Database.Providers.Postgres.Migrations b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - b.HasIndex("Type", "TopParentId", "StartDate"); - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); @@ -817,6 +760,95 @@ namespace Jellyfin.Database.Providers.Postgres.Migrations b.ToTable("AudioStreamDetails", "library"); }); + modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTvExtras", b => + { + b.Property("ItemId") + .HasColumnType("uuid"); + + b.Property("SeriesId") + .HasColumnType("uuid"); + + b.Property("SeasonId") + .HasColumnType("uuid"); + + b.Property("SeriesName") + .HasColumnType("text"); + + b.Property("SeasonName") + .HasColumnType("text"); + + b.Property("SeriesPresentationUniqueKey") + .HasColumnType("text"); + + b.HasKey("ItemId"); + + b.HasIndex("SeriesId"); + + b.HasIndex("SeriesPresentationUniqueKey"); + + b.ToTable("BaseItemTvExtras", "library"); + }); + + modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemLiveTvExtras", b => + { + b.Property("ItemId") + .HasColumnType("uuid"); + + b.Property("StartDate") + .HasColumnType("timestamp with time zone"); + + b.Property("EndDate") + .HasColumnType("timestamp with time zone"); + + b.Property("EpisodeTitle") + .HasColumnType("text"); + + b.Property("ShowId") + .HasColumnType("text"); + + b.Property("ExternalSeriesId") + .HasColumnType("text"); + + b.Property("ExternalServiceId") + .HasColumnType("text"); + + b.Property("Audio") + .HasColumnType("integer"); + + b.HasKey("ItemId"); + + b.HasIndex("StartDate"); + + b.HasIndex("EndDate"); + + b.ToTable("BaseItemLiveTvExtras", "library"); + }); + + modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemAudioExtras", b => + { + b.Property("ItemId") + .HasColumnType("uuid"); + + b.Property("Album") + .HasColumnType("text"); + + b.Property("Artists") + .HasColumnType("text"); + + b.Property("AlbumArtists") + .HasColumnType("text"); + + b.Property("LUFS") + .HasColumnType("real"); + + b.Property("NormalizationGain") + .HasColumnType("real"); + + b.HasKey("ItemId"); + + b.ToTable("BaseItemAudioExtras", "library"); + }); + modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => { b.Property("ItemId") @@ -1608,6 +1640,39 @@ namespace Jellyfin.Database.Providers.Postgres.Migrations b.Navigation("Stream"); }); + modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTvExtras", b => + { + b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") + .WithOne("TvExtras") + .HasForeignKey("Jellyfin.Database.Implementations.Entities.BaseItemTvExtras", "ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemLiveTvExtras", b => + { + b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") + .WithOne("LiveTvExtras") + .HasForeignKey("Jellyfin.Database.Implementations.Entities.BaseItemLiveTvExtras", "ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + + modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemAudioExtras", b => + { + b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") + .WithOne("AudioExtras") + .HasForeignKey("Jellyfin.Database.Implementations.Entities.BaseItemAudioExtras", "ItemId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Item"); + }); + modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => { b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") @@ -1675,6 +1740,8 @@ namespace Jellyfin.Database.Providers.Postgres.Migrations modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => { + b.Navigation("AudioExtras"); + b.Navigation("Chapters"); b.Navigation("Children"); @@ -1685,6 +1752,8 @@ namespace Jellyfin.Database.Providers.Postgres.Migrations b.Navigation("ItemValues"); + b.Navigation("LiveTvExtras"); + b.Navigation("LockedFields"); b.Navigation("MediaStreams"); @@ -1697,6 +1766,8 @@ namespace Jellyfin.Database.Providers.Postgres.Migrations b.Navigation("TrailerTypes"); + b.Navigation("TvExtras"); + b.Navigation("UserData"); }); diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/Migrations/SplitBaseItemExtras.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/Migrations/SplitBaseItemExtras.cs new file mode 100644 index 00000000..d7daedea --- /dev/null +++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/Migrations/SplitBaseItemExtras.cs @@ -0,0 +1,214 @@ +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Jellyfin.Database.Providers.Postgres.Migrations +{ + /// + public partial class SplitBaseItemExtras : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + // ── 1. Create BaseItemTvExtras ───────────────────────────────────────── + // Stores TV-specific columns (previously on BaseItems) for + // TV.Episode, TV.Season, and TV.Series items. + migrationBuilder.CreateTable( + name: "BaseItemTvExtras", + schema: "library", + columns: table => new + { + ItemId = table.Column(type: "uuid", nullable: false), + SeriesId = table.Column(type: "uuid", nullable: true), + SeasonId = table.Column(type: "uuid", nullable: true), + SeriesName = table.Column(type: "text", nullable: true), + SeasonName = table.Column(type: "text", nullable: true), + SeriesPresentationUniqueKey = table.Column(type: "text", nullable: true), + }, + constraints: table => + { + table.PrimaryKey("PK_BaseItemTvExtras", x => x.ItemId); + table.ForeignKey( + name: "FK_BaseItemTvExtras_BaseItems_ItemId", + column: x => x.ItemId, + principalSchema: "library", + principalTable: "BaseItems", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + // ── 2. Create BaseItemLiveTvExtras ──────────────────────────────────── + // Stores LiveTV-specific columns for LiveTvProgram and LiveTvChannel items. + migrationBuilder.CreateTable( + name: "BaseItemLiveTvExtras", + schema: "library", + columns: table => new + { + ItemId = table.Column(type: "uuid", nullable: false), + StartDate = table.Column(type: "timestamp with time zone", nullable: true), + EndDate = table.Column(type: "timestamp with time zone", nullable: true), + EpisodeTitle = table.Column(type: "text", nullable: true), + ShowId = table.Column(type: "text", nullable: true), + ExternalSeriesId = table.Column(type: "text", nullable: true), + ExternalServiceId = table.Column(type: "text", nullable: true), + Audio = table.Column(type: "integer", nullable: true), + }, + constraints: table => + { + table.PrimaryKey("PK_BaseItemLiveTvExtras", x => x.ItemId); + table.ForeignKey( + name: "FK_BaseItemLiveTvExtras_BaseItems_ItemId", + column: x => x.ItemId, + principalSchema: "library", + principalTable: "BaseItems", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + // ── 3. Create BaseItemAudioExtras ───────────────────────────────────── + // Stores music-specific columns for Audio.Audio items. + migrationBuilder.CreateTable( + name: "BaseItemAudioExtras", + schema: "library", + columns: table => new + { + ItemId = table.Column(type: "uuid", nullable: false), + Album = table.Column(type: "text", nullable: true), + Artists = table.Column(type: "text", nullable: true), + AlbumArtists = table.Column(type: "text", nullable: true), + LUFS = table.Column(type: "real", nullable: true), + NormalizationGain = table.Column(type: "real", nullable: true), + }, + constraints: table => + { + table.PrimaryKey("PK_BaseItemAudioExtras", x => x.ItemId); + table.ForeignKey( + name: "FK_BaseItemAudioExtras_BaseItems_ItemId", + column: x => x.ItemId, + principalSchema: "library", + principalTable: "BaseItems", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + // ── 4. Populate BaseItemTvExtras from BaseItems ─────────────────────── + migrationBuilder.Sql(@" + INSERT INTO library.""BaseItemTvExtras"" ( + ""ItemId"", + ""SeriesId"", + ""SeasonId"", + ""SeriesName"", + ""SeasonName"", + ""SeriesPresentationUniqueKey"" + ) + SELECT + ""Id"", + ""SeriesId"", + ""SeasonId"", + ""SeriesName"", + ""SeasonName"", + ""SeriesPresentationUniqueKey"" + FROM library.""BaseItems"" + WHERE ""SeriesId"" IS NOT NULL + OR ""SeasonId"" IS NOT NULL + OR ""SeriesName"" IS NOT NULL + OR ""SeasonName"" IS NOT NULL + OR ""SeriesPresentationUniqueKey"" IS NOT NULL; + "); + + // ── 5. Populate BaseItemLiveTvExtras from BaseItems ─────────────────── + migrationBuilder.Sql(@" + INSERT INTO library.""BaseItemLiveTvExtras"" ( + ""ItemId"", + ""StartDate"", + ""EndDate"", + ""EpisodeTitle"", + ""ShowId"", + ""ExternalSeriesId"", + ""ExternalServiceId"", + ""Audio"" + ) + SELECT + ""Id"", + ""StartDate"", + ""EndDate"", + ""EpisodeTitle"", + ""ShowId"", + ""ExternalSeriesId"", + ""ExternalServiceId"", + ""Audio"" + FROM library.""BaseItems"" + WHERE ""StartDate"" IS NOT NULL + OR ""EndDate"" IS NOT NULL + OR ""EpisodeTitle"" IS NOT NULL + OR ""ShowId"" IS NOT NULL + OR ""ExternalSeriesId"" IS NOT NULL + OR ""ExternalServiceId"" IS NOT NULL + OR ""Audio"" IS NOT NULL; + "); + + // ── 6. Populate BaseItemAudioExtras from BaseItems ──────────────────── + migrationBuilder.Sql(@" + INSERT INTO library.""BaseItemAudioExtras"" ( + ""ItemId"", + ""Album"", + ""Artists"", + ""AlbumArtists"", + ""LUFS"", + ""NormalizationGain"" + ) + SELECT + ""Id"", + ""Album"", + ""Artists"", + ""AlbumArtists"", + ""LUFS"", + ""NormalizationGain"" + FROM library.""BaseItems"" + WHERE ""Album"" IS NOT NULL + OR ""Artists"" IS NOT NULL + OR ""AlbumArtists"" IS NOT NULL + OR ""LUFS"" IS NOT NULL + OR ""NormalizationGain"" IS NOT NULL; + "); + + // ── 7. Create indexes on extension tables ───────────────────────────── + migrationBuilder.CreateIndex( + name: "IX_BaseItemTvExtras_SeriesId", + schema: "library", + table: "BaseItemTvExtras", + column: "SeriesId"); + + migrationBuilder.CreateIndex( + name: "IX_BaseItemTvExtras_SeriesPresentationUniqueKey", + schema: "library", + table: "BaseItemTvExtras", + column: "SeriesPresentationUniqueKey"); + + migrationBuilder.CreateIndex( + name: "IX_BaseItemLiveTvExtras_StartDate", + schema: "library", + table: "BaseItemLiveTvExtras", + column: "StartDate"); + + migrationBuilder.CreateIndex( + name: "IX_BaseItemLiveTvExtras_EndDate", + schema: "library", + table: "BaseItemLiveTvExtras", + column: "EndDate"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable(name: "BaseItemTvExtras", schema: "library"); + migrationBuilder.DropTable(name: "BaseItemLiveTvExtras", schema: "library"); + migrationBuilder.DropTable(name: "BaseItemAudioExtras", schema: "library"); + } + } +} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/PostgresDatabaseProvider.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/PostgresDatabaseProvider.cs index 251ac94f..027798e7 100644 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/PostgresDatabaseProvider.cs +++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/PostgresDatabaseProvider.cs @@ -19,6 +19,7 @@ using Jellyfin.Database.Implementations; using Jellyfin.Database.Implementations.DbConfiguration; using Jellyfin.Database.Implementations.Entities; using Jellyfin.Database.Implementations.Entities.Security; +using Jellyfin.Database.Implementations.Entities.Views; using Jellyfin.Database.Providers.Postgres.Exceptions; using MediaBrowser.Common.Configuration; using Microsoft.EntityFrameworkCore; @@ -765,6 +766,9 @@ public sealed class PostgresDatabaseProvider : IJellyfinDatabaseProvider // Assign entities to schemas based on their legacy database origin AssignEntitiesToSchemas(modelBuilder); + + // Register read-only view projections (PostgreSQL only) + RegisterViewMappings(modelBuilder); } /// @@ -774,50 +778,83 @@ public sealed class PostgresDatabaseProvider : IJellyfinDatabaseProvider private static void AssignEntitiesToSchemas(ModelBuilder modelBuilder) { // ActivityLog schema (legacy: activitylog.db) - modelBuilder.Entity().ToTable("ActivityLogs", Schemas.ActivityLog); + modelBuilder.Entity().ToTable("activity_logs", Schemas.ActivityLog); // Authentication schema (legacy: authentication.db) - modelBuilder.Entity().ToTable("ApiKeys", Schemas.Authentication); - modelBuilder.Entity().ToTable("Devices", Schemas.Authentication); - modelBuilder.Entity().ToTable("DeviceOptions", Schemas.Authentication); + modelBuilder.Entity().ToTable("api_keys", Schemas.Authentication); + modelBuilder.Entity().ToTable("devices", Schemas.Authentication); + modelBuilder.Entity().ToTable("device_options", Schemas.Authentication); // DisplayPreferences schema (legacy: displaypreferences.db) - modelBuilder.Entity().ToTable("DisplayPreferences", Schemas.DisplayPreferences); - modelBuilder.Entity().ToTable("ItemDisplayPreferences", Schemas.DisplayPreferences); - modelBuilder.Entity().ToTable("CustomItemDisplayPreferences", Schemas.DisplayPreferences); - modelBuilder.Entity().ToTable("HomeSections", Schemas.DisplayPreferences); + modelBuilder.Entity().ToTable("display_preferences", Schemas.DisplayPreferences); + modelBuilder.Entity().ToTable("item_display_preferences", Schemas.DisplayPreferences); + modelBuilder.Entity().ToTable("custom_item_display_preferences", Schemas.DisplayPreferences); + modelBuilder.Entity().ToTable("home_sections", Schemas.DisplayPreferences); // Users schema (legacy: users.db) - modelBuilder.Entity().ToTable("Users", Schemas.Users); - modelBuilder.Entity().ToTable("Permissions", Schemas.Users); - modelBuilder.Entity().ToTable("Preferences", Schemas.Users); - modelBuilder.Entity().ToTable("AccessSchedules", Schemas.Users); + modelBuilder.Entity().ToTable("users", Schemas.Users); + modelBuilder.Entity().ToTable("permissions", Schemas.Users); + modelBuilder.Entity().ToTable("preferences", Schemas.Users); + modelBuilder.Entity().ToTable("access_schedules", Schemas.Users); // Library schema (legacy: library.db) - All remaining entities - modelBuilder.Entity().ToTable("BaseItems", Schemas.Library); - modelBuilder.Entity().ToTable("Chapters", Schemas.Library); - modelBuilder.Entity().ToTable("MediaStreamInfos", Schemas.Library); - modelBuilder.Entity().ToTable("AttachmentStreamInfos", Schemas.Library); - modelBuilder.Entity().ToTable("ImageInfos", Schemas.Library); - modelBuilder.Entity().ToTable("BaseItemImageInfos", Schemas.Library); - modelBuilder.Entity().ToTable("BaseItemProviders", Schemas.Library); - modelBuilder.Entity().ToTable("BaseItemMetadataFields", Schemas.Library); - modelBuilder.Entity().ToTable("BaseItemTrailerTypes", Schemas.Library); - modelBuilder.Entity().ToTable("ItemValues", Schemas.Library); - modelBuilder.Entity().ToTable("ItemValuesMap", Schemas.Library); - modelBuilder.Entity().ToTable("Peoples", Schemas.Library); - modelBuilder.Entity().ToTable("PeopleBaseItemMap", Schemas.Library); - modelBuilder.Entity().ToTable("UserData", Schemas.Library); - modelBuilder.Entity().ToTable("AncestorIds", Schemas.Library); - modelBuilder.Entity().ToTable("TrickplayInfos", Schemas.Library); - modelBuilder.Entity().ToTable("MediaSegments", Schemas.Library); - modelBuilder.Entity().ToTable("KeyframeData", Schemas.Library); - modelBuilder.Entity().ToTable("LibraryOptions", Schemas.Library); + modelBuilder.Entity().ToTable("base_items", Schemas.Library); + modelBuilder.Entity().ToTable("chapters", Schemas.Library); + modelBuilder.Entity().ToTable("media_stream_infos", Schemas.Library); + modelBuilder.Entity().ToTable("attachment_stream_infos", Schemas.Library); + modelBuilder.Entity().ToTable("image_infos", Schemas.Library); + modelBuilder.Entity().ToTable("base_item_image_infos", Schemas.Library); + modelBuilder.Entity().ToTable("base_item_providers", Schemas.Library); + modelBuilder.Entity().ToTable("base_item_metadata_fields", Schemas.Library); + modelBuilder.Entity().ToTable("base_item_trailer_types", Schemas.Library); + modelBuilder.Entity().ToTable("item_values", Schemas.Library); + modelBuilder.Entity().ToTable("item_values_map", Schemas.Library); + modelBuilder.Entity().ToTable("peoples", Schemas.Library); + modelBuilder.Entity().ToTable("people_base_item_map", Schemas.Library); + modelBuilder.Entity().ToTable("user_data", Schemas.Library); + modelBuilder.Entity().ToTable("ancestor_ids", Schemas.Library); + modelBuilder.Entity().ToTable("trickplay_infos", Schemas.Library); + modelBuilder.Entity().ToTable("media_segments", Schemas.Library); + modelBuilder.Entity().ToTable("keyframe_data", Schemas.Library); + modelBuilder.Entity().ToTable("library_options", Schemas.Library); modelBuilder.Entity().HasKey(e => e.LibraryPath); modelBuilder.Entity().HasIndex(e => e.DateModified); } + /// + /// Registers read-only keyless view projections for PostgreSQL. + /// Each view lives in the library schema and is mapped with + /// HasNoKey().ToView() so EF Core never tries to create a table or migration for it. + /// + /// The model builder. + private static void RegisterViewMappings(ModelBuilder modelBuilder) + { + modelBuilder.Entity() + .HasNoKey() + .ToView("media_stream_infos_v", Schemas.Library); + + modelBuilder.Entity() + .HasNoKey() + .ToView("video_items_v", Schemas.Library); + + modelBuilder.Entity() + .HasNoKey() + .ToView("user_playback_history_v", Schemas.Library); + + modelBuilder.Entity() + .HasNoKey() + .ToView("item_providers_v", Schemas.Library); + + modelBuilder.Entity() + .HasNoKey() + .ToView("item_people_v", Schemas.Library); + + modelBuilder.Entity() + .HasNoKey() + .ToView("library_summary_v", Schemas.Library); + } + /// public Task RunShutdownTask(CancellationToken cancellationToken) { @@ -834,7 +871,7 @@ public sealed class PostgresDatabaseProvider : IJellyfinDatabaseProvider /// public void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) { - // PostgreSQL-specific conventions can be added here if needed + configurationBuilder.Conventions.Add(_ => new SnakeCaseNamingConvention()); } /// diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/SnakeCaseNamingConvention.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/SnakeCaseNamingConvention.cs new file mode 100644 index 00000000..ba5b79e7 --- /dev/null +++ b/src/Jellyfin.Database/Jellyfin.Database.Providers.Postgres/SnakeCaseNamingConvention.cs @@ -0,0 +1,41 @@ +// +// Copyright (c) PlaceholderCompany. All rights reserved. +// + +namespace Jellyfin.Database.Providers.Postgres; + +using System.Text.RegularExpressions; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Metadata.Builders; +using Microsoft.EntityFrameworkCore.Metadata.Conventions; + +/// +/// EF Core convention that maps all entity property names to snake_case column names. +/// Applied only by the PostgreSQL provider so SQLite is unaffected. +/// +public sealed class SnakeCaseNamingConvention : IPropertyAddedConvention +{ + private static readonly Regex AcronymBoundaryRegex = + new(@"([A-Z]+)([A-Z][a-z])", RegexOptions.Compiled); + + private static readonly Regex LowerToUpperRegex = + new(@"([a-z\d])([A-Z])", RegexOptions.Compiled); + + /// + public void ProcessPropertyAdded( + IConventionPropertyBuilder propertyBuilder, + IConventionContext context) + { + propertyBuilder.HasColumnName(ToSnakeCase(propertyBuilder.Metadata.Name)); + } + + /// Converts a PascalCase identifier to snake_case. + /// The identifier to convert. + /// The snake_case representation of the identifier. + internal static string ToSnakeCase(string name) + { + name = AcronymBoundaryRegex.Replace(name, "$1_$2"); + name = LowerToUpperRegex.Replace(name, "$1_$2"); + return name.ToLowerInvariant(); + } +} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/DoNotUseReturningClauseConvention.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/DoNotUseReturningClauseConvention.cs deleted file mode 100644 index e1be50e4..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/DoNotUseReturningClauseConvention.cs +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Jellyfin.Database.Providers.Sqlite; - -using System; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Metadata.Builders; -using Microsoft.EntityFrameworkCore.Metadata.Conventions; - -internal class DoNotUseReturningClauseConvention : IModelFinalizingConvention -{ - /// - public void ProcessModelFinalizing( - IConventionModelBuilder modelBuilder, - IConventionContext context) - { - foreach (var entityType in modelBuilder.Metadata.GetEntityTypes()) - { - entityType.UseSqlReturningClause(false); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/GlobalSuppressions.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/GlobalSuppressions.cs deleted file mode 100644 index faf22975..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/GlobalSuppressions.cs +++ /dev/null @@ -1,12 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -using System.Diagnostics.CodeAnalysis; - -[assembly: SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1101:PrefixLocalCallsWithThis", Justification = "Project style preference", Scope = "module")] -[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:ElementsMustBeDocumented", Justification = "Documentation provided via CS1591 pragma", Scope = "module")] -[assembly: SuppressMessage("StyleCop.CSharp.NamingRules", "SA1309:FieldNamesMustNotBeginWithUnderscore", Justification = "Project style preference for private fields", Scope = "module")] -[assembly: SuppressMessage("StyleCop.CSharp.OrderingRules", "SA1200:UsingDirectivesMustBePlacedCorrectly", Justification = "Using directives placed outside namespace per project style", Scope = "module")] -[assembly: SuppressMessage("StyleCop.CSharp.MaintainabilityRules", "SA1413:UseTrailingCommasInMultiLineInitializers", Justification = "Project style preference", Scope = "module")] -[assembly: SuppressMessage("StyleCop.CSharp.LayoutRules", "SA1515:SingleLineCommentMustBePrecededByBlankLine", Justification = "Project style preference", Scope = "module")] diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Jellyfin.Database.Providers.Sqlite.csproj b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Jellyfin.Database.Providers.Sqlite.csproj deleted file mode 100644 index 5e85cc11..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Jellyfin.Database.Providers.Sqlite.csproj +++ /dev/null @@ -1,32 +0,0 @@ - - - - net11.0 - false - true - $(NoWarn);CA1062;CA1861;CA1873;CA1848;CA2253;CA1515;CA1812;CA1849;CA1860;CA1867;CA1517;CA1865;CA1869;CA1716;CA2101;SA1127;CA1845;CA1859;CA2007 - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/.gitattributes b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/.gitattributes deleted file mode 100644 index da5c26f4..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -JellyfinDbModelSnapshot.cs binary diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200514181226_AddActivityLog.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200514181226_AddActivityLog.Designer.cs deleted file mode 100644 index 78910064..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200514181226_AddActivityLog.Designer.cs +++ /dev/null @@ -1,72 +0,0 @@ -#pragma warning disable CS1591 - -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20200514181226_AddActivityLog")] - partial class AddActivityLog - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("jellyfin") - .HasAnnotation("ProductVersion", "3.1.3"); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("Overview") - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("ActivityLogs"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200514181226_AddActivityLog.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200514181226_AddActivityLog.cs deleted file mode 100644 index 73f3d2a9..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200514181226_AddActivityLog.cs +++ /dev/null @@ -1,50 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#pragma warning disable CS1591 -#pragma warning disable SA1601 - -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace Jellyfin.Server.Implementations.Migrations -{ - public partial class AddActivityLog : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.EnsureSchema( - name: "jellyfin"); - - migrationBuilder.CreateTable( - name: "ActivityLogs", - schema: "jellyfin", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("Sqlite:Autoincrement", true), - Name = table.Column(maxLength: 512, nullable: false), - Overview = table.Column(maxLength: 512, nullable: true), - ShortOverview = table.Column(maxLength: 512, nullable: true), - Type = table.Column(maxLength: 256, nullable: false), - UserId = table.Column(nullable: false), - ItemId = table.Column(maxLength: 256, nullable: true), - DateCreated = table.Column(nullable: false), - LogSeverity = table.Column(nullable: false), - RowVersion = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ActivityLogs", x => x.Id); - }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "ActivityLogs", - schema: "jellyfin"); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200613202153_AddUsers.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200613202153_AddUsers.Designer.cs deleted file mode 100644 index eab3cd3e..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200613202153_AddUsers.Designer.cs +++ /dev/null @@ -1,312 +0,0 @@ -#pragma warning disable CS1591 - -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20200613202153_AddUsers")] - partial class AddUsers - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("jellyfin") - .HasAnnotation("ProductVersion", "3.1.4"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("Overview") - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("Permission_Permissions_Guid"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(65535); - - b.HasKey("Id"); - - b.HasIndex("Preference_Preferences_Guid"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EasyPassword") - .HasColumnType("TEXT") - .HasMaxLength(65535); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasColumnType("TEXT") - .HasMaxLength(65535); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.HasKey("Id"); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("Permission_Permissions_Guid"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("Preference_Preferences_Guid"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200613202153_AddUsers.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200613202153_AddUsers.cs deleted file mode 100644 index 730fb144..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200613202153_AddUsers.cs +++ /dev/null @@ -1,201 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#pragma warning disable CS1591 -#pragma warning disable SA1601 - -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace Jellyfin.Server.Implementations.Migrations -{ - public partial class AddUsers : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "Users", - schema: "jellyfin", - columns: table => new - { - Id = table.Column(nullable: false), - Username = table.Column(maxLength: 255, nullable: false), - Password = table.Column(maxLength: 65535, nullable: true), - EasyPassword = table.Column(maxLength: 65535, nullable: true), - MustUpdatePassword = table.Column(nullable: false), - AudioLanguagePreference = table.Column(maxLength: 255, nullable: true), - AuthenticationProviderId = table.Column(maxLength: 255, nullable: false), - PasswordResetProviderId = table.Column(maxLength: 255, nullable: false), - InvalidLoginAttemptCount = table.Column(nullable: false), - LastActivityDate = table.Column(nullable: true), - LastLoginDate = table.Column(nullable: true), - LoginAttemptsBeforeLockout = table.Column(nullable: true), - SubtitleMode = table.Column(nullable: false), - PlayDefaultAudioTrack = table.Column(nullable: false), - SubtitleLanguagePreference = table.Column(maxLength: 255, nullable: true), - DisplayMissingEpisodes = table.Column(nullable: false), - DisplayCollectionsView = table.Column(nullable: false), - EnableLocalPassword = table.Column(nullable: false), - HidePlayedInLatest = table.Column(nullable: false), - RememberAudioSelections = table.Column(nullable: false), - RememberSubtitleSelections = table.Column(nullable: false), - EnableNextEpisodeAutoPlay = table.Column(nullable: false), - EnableAutoLogin = table.Column(nullable: false), - EnableUserPreferenceAccess = table.Column(nullable: false), - MaxParentalAgeRating = table.Column(nullable: true), - RemoteClientBitrateLimit = table.Column(nullable: true), - InternalId = table.Column(nullable: false), - SyncPlayAccess = table.Column(nullable: false), - RowVersion = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Users", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AccessSchedules", - schema: "jellyfin", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("Sqlite:Autoincrement", true), - UserId = table.Column(nullable: false), - DayOfWeek = table.Column(nullable: false), - StartHour = table.Column(nullable: false), - EndHour = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_AccessSchedules", x => x.Id); - table.ForeignKey( - name: "FK_AccessSchedules_Users_UserId", - column: x => x.UserId, - principalSchema: "jellyfin", - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ImageInfos", - schema: "jellyfin", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("Sqlite:Autoincrement", true), - UserId = table.Column(nullable: true), - Path = table.Column(maxLength: 512, nullable: false), - LastModified = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ImageInfos", x => x.Id); - table.ForeignKey( - name: "FK_ImageInfos_Users_UserId", - column: x => x.UserId, - principalSchema: "jellyfin", - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Restrict); - }); - - migrationBuilder.CreateTable( - name: "Permissions", - schema: "jellyfin", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("Sqlite:Autoincrement", true), - Kind = table.Column(nullable: false), - Value = table.Column(nullable: false), - RowVersion = table.Column(nullable: false), - Permission_Permissions_Guid = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Permissions", x => x.Id); - table.ForeignKey( - name: "FK_Permissions_Users_Permission_Permissions_Guid", - column: x => x.Permission_Permissions_Guid, - principalSchema: "jellyfin", - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Restrict); - }); - - migrationBuilder.CreateTable( - name: "Preferences", - schema: "jellyfin", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("Sqlite:Autoincrement", true), - Kind = table.Column(nullable: false), - Value = table.Column(maxLength: 65535, nullable: false), - RowVersion = table.Column(nullable: false), - Preference_Preferences_Guid = table.Column(nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Preferences", x => x.Id); - table.ForeignKey( - name: "FK_Preferences_Users_Preference_Preferences_Guid", - column: x => x.Preference_Preferences_Guid, - principalSchema: "jellyfin", - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Restrict); - }); - - migrationBuilder.CreateIndex( - name: "IX_AccessSchedules_UserId", - schema: "jellyfin", - table: "AccessSchedules", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_ImageInfos_UserId", - schema: "jellyfin", - table: "ImageInfos", - column: "UserId", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_Permissions_Permission_Permissions_Guid", - schema: "jellyfin", - table: "Permissions", - column: "Permission_Permissions_Guid"); - - migrationBuilder.CreateIndex( - name: "IX_Preferences_Preference_Preferences_Guid", - schema: "jellyfin", - table: "Preferences", - column: "Preference_Preferences_Guid"); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "AccessSchedules", - schema: "jellyfin"); - - migrationBuilder.DropTable( - name: "ImageInfos", - schema: "jellyfin"); - - migrationBuilder.DropTable( - name: "Permissions", - schema: "jellyfin"); - - migrationBuilder.DropTable( - name: "Preferences", - schema: "jellyfin"); - - migrationBuilder.DropTable( - name: "Users", - schema: "jellyfin"); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200728005145_AddDisplayPreferences.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200728005145_AddDisplayPreferences.Designer.cs deleted file mode 100644 index 91dd0ff7..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200728005145_AddDisplayPreferences.Designer.cs +++ /dev/null @@ -1,459 +0,0 @@ -#pragma warning disable CS1591 - -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20200728005145_AddDisplayPreferences")] - partial class AddDisplayPreferences - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("jellyfin") - .HasAnnotation("ProductVersion", "3.1.6"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("Overview") - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(32); - - b.Property("DashboardTheme") - .HasColumnType("TEXT") - .HasMaxLength(32); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasColumnType("TEXT") - .HasMaxLength(32); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(32); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(64); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("Permission_Permissions_Guid"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(65535); - - b.HasKey("Id"); - - b.HasIndex("Preference_Preferences_Guid"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EasyPassword") - .HasColumnType("TEXT") - .HasMaxLength(65535); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasColumnType("TEXT") - .HasMaxLength(65535); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.HasKey("Id"); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("DisplayPreferences") - .HasForeignKey("Jellyfin.Data.Entities.DisplayPreferences", "UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("Permission_Permissions_Guid"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("Preference_Preferences_Guid"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200728005145_AddDisplayPreferences.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200728005145_AddDisplayPreferences.cs deleted file mode 100644 index 138039d4..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200728005145_AddDisplayPreferences.cs +++ /dev/null @@ -1,136 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#pragma warning disable CS1591 -#pragma warning disable SA1601 - -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace Jellyfin.Server.Implementations.Migrations -{ - public partial class AddDisplayPreferences : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "DisplayPreferences", - schema: "jellyfin", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("Sqlite:Autoincrement", true), - UserId = table.Column(nullable: false), - Client = table.Column(maxLength: 32, nullable: false), - ShowSidebar = table.Column(nullable: false), - ShowBackdrop = table.Column(nullable: false), - ScrollDirection = table.Column(nullable: false), - IndexBy = table.Column(nullable: true), - SkipForwardLength = table.Column(nullable: false), - SkipBackwardLength = table.Column(nullable: false), - ChromecastVersion = table.Column(nullable: false), - EnableNextVideoInfoOverlay = table.Column(nullable: false), - DashboardTheme = table.Column(maxLength: 32, nullable: true), - TvHome = table.Column(maxLength: 32, nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_DisplayPreferences", x => x.Id); - table.ForeignKey( - name: "FK_DisplayPreferences_Users_UserId", - column: x => x.UserId, - principalSchema: "jellyfin", - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ItemDisplayPreferences", - schema: "jellyfin", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("Sqlite:Autoincrement", true), - UserId = table.Column(nullable: false), - ItemId = table.Column(nullable: false), - Client = table.Column(maxLength: 32, nullable: false), - ViewType = table.Column(nullable: false), - RememberIndexing = table.Column(nullable: false), - IndexBy = table.Column(nullable: true), - RememberSorting = table.Column(nullable: false), - SortBy = table.Column(maxLength: 64, nullable: false), - SortOrder = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ItemDisplayPreferences", x => x.Id); - table.ForeignKey( - name: "FK_ItemDisplayPreferences_Users_UserId", - column: x => x.UserId, - principalSchema: "jellyfin", - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "HomeSection", - schema: "jellyfin", - columns: table => new - { - Id = table.Column(nullable: false) - .Annotation("Sqlite:Autoincrement", true), - DisplayPreferencesId = table.Column(nullable: false), - Order = table.Column(nullable: false), - Type = table.Column(nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_HomeSection", x => x.Id); - table.ForeignKey( - name: "FK_HomeSection_DisplayPreferences_DisplayPreferencesId", - column: x => x.DisplayPreferencesId, - principalSchema: "jellyfin", - principalTable: "DisplayPreferences", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_DisplayPreferences_UserId", - schema: "jellyfin", - table: "DisplayPreferences", - column: "UserId", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_HomeSection_DisplayPreferencesId", - schema: "jellyfin", - table: "HomeSection", - column: "DisplayPreferencesId"); - - migrationBuilder.CreateIndex( - name: "IX_ItemDisplayPreferences_UserId", - schema: "jellyfin", - table: "ItemDisplayPreferences", - column: "UserId"); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "HomeSection", - schema: "jellyfin"); - - migrationBuilder.DropTable( - name: "ItemDisplayPreferences", - schema: "jellyfin"); - - migrationBuilder.DropTable( - name: "DisplayPreferences", - schema: "jellyfin"); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200905220533_FixDisplayPreferencesIndex.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200905220533_FixDisplayPreferencesIndex.Designer.cs deleted file mode 100644 index 8ec92310..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200905220533_FixDisplayPreferencesIndex.Designer.cs +++ /dev/null @@ -1,461 +0,0 @@ -#pragma warning disable CS1591 - -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20200905220533_FixDisplayPreferencesIndex")] - partial class FixDisplayPreferencesIndex - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("jellyfin") - .HasAnnotation("ProductVersion", "3.1.7"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("Overview") - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(32); - - b.Property("DashboardTheme") - .HasColumnType("TEXT") - .HasMaxLength(32); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasColumnType("TEXT") - .HasMaxLength(32); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.HasIndex("UserId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(32); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(64); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("Permission_Permissions_Guid"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(65535); - - b.HasKey("Id"); - - b.HasIndex("Preference_Preferences_Guid"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EasyPassword") - .HasColumnType("TEXT") - .HasMaxLength(65535); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasColumnType("TEXT") - .HasMaxLength(65535); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.HasKey("Id"); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("DisplayPreferences") - .HasForeignKey("Jellyfin.Data.Entities.DisplayPreferences", "UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("Permission_Permissions_Guid"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("Preference_Preferences_Guid"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200905220533_FixDisplayPreferencesIndex.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200905220533_FixDisplayPreferencesIndex.cs deleted file mode 100644 index 82604edf..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20200905220533_FixDisplayPreferencesIndex.cs +++ /dev/null @@ -1,55 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#pragma warning disable CS1591 -#pragma warning disable SA1601 - -using Microsoft.EntityFrameworkCore.Migrations; - -namespace Jellyfin.Server.Implementations.Migrations -{ - public partial class FixDisplayPreferencesIndex : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_DisplayPreferences_UserId", - schema: "jellyfin", - table: "DisplayPreferences"); - - migrationBuilder.CreateIndex( - name: "IX_DisplayPreferences_UserId", - schema: "jellyfin", - table: "DisplayPreferences", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_DisplayPreferences_UserId_Client", - schema: "jellyfin", - table: "DisplayPreferences", - columns: new[] { "UserId", "Client" }, - unique: true); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_DisplayPreferences_UserId", - schema: "jellyfin", - table: "DisplayPreferences"); - - migrationBuilder.DropIndex( - name: "IX_DisplayPreferences_UserId_Client", - schema: "jellyfin", - table: "DisplayPreferences"); - - migrationBuilder.CreateIndex( - name: "IX_DisplayPreferences_UserId", - schema: "jellyfin", - table: "DisplayPreferences", - column: "UserId", - unique: true); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201004171403_AddMaxActiveSessions.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201004171403_AddMaxActiveSessions.Designer.cs deleted file mode 100644 index 499faa9c..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201004171403_AddMaxActiveSessions.Designer.cs +++ /dev/null @@ -1,464 +0,0 @@ -#pragma warning disable CS1591 - -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20201004171403_AddMaxActiveSessions")] - partial class AddMaxActiveSessions - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("jellyfin") - .HasAnnotation("ProductVersion", "3.1.8"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("Overview") - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(256); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(32); - - b.Property("DashboardTheme") - .HasColumnType("TEXT") - .HasMaxLength(32); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasColumnType("TEXT") - .HasMaxLength(32); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.HasIndex("UserId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(512); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(32); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(64); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("Permission_Permissions_Guid"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(65535); - - b.HasKey("Id"); - - b.HasIndex("Preference_Preferences_Guid"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EasyPassword") - .HasColumnType("TEXT") - .HasMaxLength(65535); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasColumnType("TEXT") - .HasMaxLength(65535); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasColumnType("TEXT") - .HasMaxLength(255); - - b.HasKey("Id"); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("DisplayPreferences") - .HasForeignKey("Jellyfin.Data.Entities.DisplayPreferences", "UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("Permission_Permissions_Guid"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("Preference_Preferences_Guid"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201004171403_AddMaxActiveSessions.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201004171403_AddMaxActiveSessions.cs deleted file mode 100644 index a803fbab..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201004171403_AddMaxActiveSessions.cs +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#pragma warning disable CS1591 -#pragma warning disable SA1601 - -using Microsoft.EntityFrameworkCore.Migrations; - -namespace Jellyfin.Server.Implementations.Migrations -{ - public partial class AddMaxActiveSessions : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "MaxActiveSessions", - schema: "jellyfin", - table: "Users", - nullable: false, - defaultValue: 0); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "MaxActiveSessions", - schema: "jellyfin", - table: "Users"); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201204223655_AddCustomDisplayPreferences.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201204223655_AddCustomDisplayPreferences.Designer.cs deleted file mode 100644 index 7ab85168..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201204223655_AddCustomDisplayPreferences.Designer.cs +++ /dev/null @@ -1,522 +0,0 @@ -#pragma warning disable CS1591 -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20201204223655_AddCustomDisplayPreferences")] - partial class AddCustomDisplayPreferences - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("jellyfin") - .HasAnnotation("ProductVersion", "5.0.0"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("Permission_Permissions_Guid"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Preference_Preferences_Guid"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EasyPassword") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("DisplayPreferences") - .HasForeignKey("Jellyfin.Data.Entities.DisplayPreferences", "UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("Permission_Permissions_Guid"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("Preference_Preferences_Guid"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences") - .IsRequired(); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201204223655_AddCustomDisplayPreferences.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201204223655_AddCustomDisplayPreferences.cs deleted file mode 100644 index ce2b21d0..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20201204223655_AddCustomDisplayPreferences.cs +++ /dev/null @@ -1,108 +0,0 @@ -#pragma warning disable CS1591 -// -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace Jellyfin.Server.Implementations.Migrations -{ - public partial class AddCustomDisplayPreferences : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_DisplayPreferences_UserId_Client", - schema: "jellyfin", - table: "DisplayPreferences"); - - migrationBuilder.AlterColumn( - name: "MaxActiveSessions", - schema: "jellyfin", - table: "Users", - type: "INTEGER", - nullable: false, - defaultValue: 0, - oldClrType: typeof(int), - oldType: "INTEGER", - oldNullable: true); - - migrationBuilder.AddColumn( - name: "ItemId", - schema: "jellyfin", - table: "DisplayPreferences", - type: "TEXT", - nullable: false, - defaultValue: new Guid("00000000-0000-0000-0000-000000000000")); - - migrationBuilder.CreateTable( - name: "CustomItemDisplayPreferences", - schema: "jellyfin", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - UserId = table.Column(type: "TEXT", nullable: false), - ItemId = table.Column(type: "TEXT", nullable: false), - Client = table.Column(type: "TEXT", maxLength: 32, nullable: false), - Key = table.Column(type: "TEXT", nullable: false), - Value = table.Column(type: "TEXT", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_CustomItemDisplayPreferences", x => x.Id); - }); - - migrationBuilder.CreateIndex( - name: "IX_DisplayPreferences_UserId_ItemId_Client", - schema: "jellyfin", - table: "DisplayPreferences", - columns: new[] { "UserId", "ItemId", "Client" }, - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_CustomItemDisplayPreferences_UserId", - schema: "jellyfin", - table: "CustomItemDisplayPreferences", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_CustomItemDisplayPreferences_UserId_ItemId_Client_Key", - schema: "jellyfin", - table: "CustomItemDisplayPreferences", - columns: new[] { "UserId", "ItemId", "Client", "Key" }, - unique: true); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "CustomItemDisplayPreferences", - schema: "jellyfin"); - - migrationBuilder.DropIndex( - name: "IX_DisplayPreferences_UserId_ItemId_Client", - schema: "jellyfin", - table: "DisplayPreferences"); - - migrationBuilder.DropColumn( - name: "ItemId", - schema: "jellyfin", - table: "DisplayPreferences"); - - migrationBuilder.AlterColumn( - name: "MaxActiveSessions", - schema: "jellyfin", - table: "Users", - type: "INTEGER", - nullable: true, - oldClrType: typeof(int), - oldType: "INTEGER"); - - migrationBuilder.CreateIndex( - name: "IX_DisplayPreferences_UserId_Client", - schema: "jellyfin", - table: "DisplayPreferences", - columns: new[] { "UserId", "Client" }, - unique: true); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210320181425_AddIndexesAndCollations.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210320181425_AddIndexesAndCollations.Designer.cs deleted file mode 100644 index e14ed938..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210320181425_AddIndexesAndCollations.Designer.cs +++ /dev/null @@ -1,535 +0,0 @@ -#pragma warning disable CS1591 - -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20210320181425_AddIndexesAndCollations")] - partial class AddIndexesAndCollations - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("jellyfin") - .HasAnnotation("ProductVersion", "5.0.3"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EasyPassword") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT") - .UseCollation("NOCASE"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210320181425_AddIndexesAndCollations.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210320181425_AddIndexesAndCollations.cs deleted file mode 100644 index 1b4f6280..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210320181425_AddIndexesAndCollations.cs +++ /dev/null @@ -1,244 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#pragma warning disable CS1591 -#pragma warning disable SA1601 - -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace Jellyfin.Server.Implementations.Migrations -{ - public partial class AddIndexesAndCollations : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_ImageInfos_Users_UserId", - schema: "jellyfin", - table: "ImageInfos"); - - migrationBuilder.DropForeignKey( - name: "FK_Permissions_Users_Permission_Permissions_Guid", - schema: "jellyfin", - table: "Permissions"); - - migrationBuilder.DropForeignKey( - name: "FK_Preferences_Users_Preference_Preferences_Guid", - schema: "jellyfin", - table: "Preferences"); - - migrationBuilder.DropIndex( - name: "IX_Preferences_Preference_Preferences_Guid", - schema: "jellyfin", - table: "Preferences"); - - migrationBuilder.DropIndex( - name: "IX_Permissions_Permission_Permissions_Guid", - schema: "jellyfin", - table: "Permissions"); - - migrationBuilder.DropIndex( - name: "IX_DisplayPreferences_UserId", - schema: "jellyfin", - table: "DisplayPreferences"); - - migrationBuilder.DropIndex( - name: "IX_CustomItemDisplayPreferences_UserId", - schema: "jellyfin", - table: "CustomItemDisplayPreferences"); - - migrationBuilder.AlterColumn( - name: "Username", - schema: "jellyfin", - table: "Users", - type: "TEXT", - maxLength: 255, - nullable: false, - collation: "NOCASE", - oldClrType: typeof(string), - oldType: "TEXT", - oldMaxLength: 255); - - migrationBuilder.AddColumn( - name: "UserId", - schema: "jellyfin", - table: "Preferences", - type: "TEXT", - nullable: true); - - migrationBuilder.AddColumn( - name: "UserId", - schema: "jellyfin", - table: "Permissions", - type: "TEXT", - nullable: true); - - migrationBuilder.Sql("UPDATE Preferences SET UserId = Preference_Preferences_Guid"); - migrationBuilder.Sql("UPDATE Permissions SET UserId = Permission_Permissions_Guid"); - - migrationBuilder.CreateIndex( - name: "IX_Users_Username", - schema: "jellyfin", - table: "Users", - column: "Username", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_Preferences_UserId_Kind", - schema: "jellyfin", - table: "Preferences", - columns: new[] { "UserId", "Kind" }, - unique: true, - filter: "[UserId] IS NOT NULL"); - - migrationBuilder.CreateIndex( - name: "IX_Permissions_UserId_Kind", - schema: "jellyfin", - table: "Permissions", - columns: new[] { "UserId", "Kind" }, - unique: true, - filter: "[UserId] IS NOT NULL"); - - migrationBuilder.AddForeignKey( - name: "FK_ImageInfos_Users_UserId", - schema: "jellyfin", - table: "ImageInfos", - column: "UserId", - principalSchema: "jellyfin", - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_Permissions_Users_UserId", - schema: "jellyfin", - table: "Permissions", - column: "UserId", - principalSchema: "jellyfin", - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_Preferences_Users_UserId", - schema: "jellyfin", - table: "Preferences", - column: "UserId", - principalSchema: "jellyfin", - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_ImageInfos_Users_UserId", - schema: "jellyfin", - table: "ImageInfos"); - - migrationBuilder.DropForeignKey( - name: "FK_Permissions_Users_UserId", - schema: "jellyfin", - table: "Permissions"); - - migrationBuilder.DropForeignKey( - name: "FK_Preferences_Users_UserId", - schema: "jellyfin", - table: "Preferences"); - - migrationBuilder.DropIndex( - name: "IX_Users_Username", - schema: "jellyfin", - table: "Users"); - - migrationBuilder.DropIndex( - name: "IX_Preferences_UserId_Kind", - schema: "jellyfin", - table: "Preferences"); - - migrationBuilder.DropIndex( - name: "IX_Permissions_UserId_Kind", - schema: "jellyfin", - table: "Permissions"); - - migrationBuilder.DropColumn( - name: "UserId", - schema: "jellyfin", - table: "Preferences"); - - migrationBuilder.DropColumn( - name: "UserId", - schema: "jellyfin", - table: "Permissions"); - - migrationBuilder.AlterColumn( - name: "Username", - schema: "jellyfin", - table: "Users", - type: "TEXT", - maxLength: 255, - nullable: false, - oldClrType: typeof(string), - oldType: "TEXT", - oldMaxLength: 255, - oldCollation: "NOCASE"); - - migrationBuilder.CreateIndex( - name: "IX_Preferences_Preference_Preferences_Guid", - schema: "jellyfin", - table: "Preferences", - column: "Preference_Preferences_Guid"); - - migrationBuilder.CreateIndex( - name: "IX_Permissions_Permission_Permissions_Guid", - schema: "jellyfin", - table: "Permissions", - column: "Permission_Permissions_Guid"); - - migrationBuilder.CreateIndex( - name: "IX_DisplayPreferences_UserId", - schema: "jellyfin", - table: "DisplayPreferences", - column: "UserId"); - - migrationBuilder.CreateIndex( - name: "IX_CustomItemDisplayPreferences_UserId", - schema: "jellyfin", - table: "CustomItemDisplayPreferences", - column: "UserId"); - - migrationBuilder.AddForeignKey( - name: "FK_ImageInfos_Users_UserId", - schema: "jellyfin", - table: "ImageInfos", - column: "UserId", - principalSchema: "jellyfin", - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Restrict); - - migrationBuilder.AddForeignKey( - name: "FK_Permissions_Users_Permission_Permissions_Guid", - schema: "jellyfin", - table: "Permissions", - column: "Permission_Permissions_Guid", - principalSchema: "jellyfin", - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Restrict); - - migrationBuilder.AddForeignKey( - name: "FK_Preferences_Users_Preference_Preferences_Guid", - schema: "jellyfin", - table: "Preferences", - column: "Preference_Preferences_Guid", - principalSchema: "jellyfin", - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Restrict); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210407110544_NullableCustomPrefValue.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210407110544_NullableCustomPrefValue.Designer.cs deleted file mode 100644 index 05f2c80a..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210407110544_NullableCustomPrefValue.Designer.cs +++ /dev/null @@ -1,520 +0,0 @@ -#pragma warning disable CS1591 -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20210407110544_NullableCustomPrefValue")] - partial class NullableCustomPrefValue - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("jellyfin") - .HasAnnotation("ProductVersion", "5.0.3"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("Permission_Permissions_Guid"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Preference_Preferences_Guid"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EasyPassword") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("Permission_Permissions_Guid"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("Preference_Preferences_Guid"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210407110544_NullableCustomPrefValue.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210407110544_NullableCustomPrefValue.cs deleted file mode 100644 index a6b169a6..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210407110544_NullableCustomPrefValue.cs +++ /dev/null @@ -1,35 +0,0 @@ -#pragma warning disable CS1591 -// -using Microsoft.EntityFrameworkCore.Migrations; - -namespace Jellyfin.Server.Implementations.Migrations -{ - public partial class NullableCustomPrefValue : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "Value", - schema: "jellyfin", - table: "CustomItemDisplayPreferences", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "Value", - schema: "jellyfin", - table: "CustomItemDisplayPreferences", - type: "TEXT", - nullable: false, - defaultValue: "", - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210814002109_AddDevices.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210814002109_AddDevices.Designer.cs deleted file mode 100644 index c9f3cf69..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210814002109_AddDevices.Designer.cs +++ /dev/null @@ -1,653 +0,0 @@ -#pragma warning disable CS1591 - -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20210814002109_AddDevices")] - partial class AddDevices - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("jellyfin") - .HasAnnotation("ProductVersion", "5.0.7"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EasyPassword") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT") - .UseCollation("NOCASE"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210814002109_AddDevices.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210814002109_AddDevices.cs deleted file mode 100644 index 33ff220e..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20210814002109_AddDevices.cs +++ /dev/null @@ -1,132 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#pragma warning disable CS1591, SA1601 - -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -namespace Jellyfin.Server.Implementations.Migrations -{ - public partial class AddDevices : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "ApiKeys", - schema: "jellyfin", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - DateCreated = table.Column(type: "TEXT", nullable: false), - DateLastActivity = table.Column(type: "TEXT", nullable: false), - Name = table.Column(type: "TEXT", maxLength: 64, nullable: false), - AccessToken = table.Column(type: "TEXT", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ApiKeys", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "DeviceOptions", - schema: "jellyfin", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - DeviceId = table.Column(type: "TEXT", nullable: false), - CustomName = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_DeviceOptions", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Devices", - schema: "jellyfin", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false) - .Annotation("Sqlite:Autoincrement", true), - UserId = table.Column(type: "TEXT", nullable: false), - AccessToken = table.Column(type: "TEXT", nullable: false), - AppName = table.Column(type: "TEXT", maxLength: 64, nullable: false), - AppVersion = table.Column(type: "TEXT", maxLength: 32, nullable: false), - DeviceName = table.Column(type: "TEXT", maxLength: 64, nullable: false), - DeviceId = table.Column(type: "TEXT", maxLength: 256, nullable: false), - IsActive = table.Column(type: "INTEGER", nullable: false), - DateCreated = table.Column(type: "TEXT", nullable: false), - DateModified = table.Column(type: "TEXT", nullable: false), - DateLastActivity = table.Column(type: "TEXT", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Devices", x => x.Id); - table.ForeignKey( - name: "FK_Devices_Users_UserId", - column: x => x.UserId, - principalSchema: "jellyfin", - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_ApiKeys_AccessToken", - schema: "jellyfin", - table: "ApiKeys", - column: "AccessToken", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_DeviceOptions_DeviceId", - schema: "jellyfin", - table: "DeviceOptions", - column: "DeviceId", - unique: true); - - migrationBuilder.CreateIndex( - name: "IX_Devices_AccessToken_DateLastActivity", - schema: "jellyfin", - table: "Devices", - columns: new[] { "AccessToken", "DateLastActivity" }); - - migrationBuilder.CreateIndex( - name: "IX_Devices_DeviceId", - schema: "jellyfin", - table: "Devices", - column: "DeviceId"); - - migrationBuilder.CreateIndex( - name: "IX_Devices_DeviceId_DateLastActivity", - schema: "jellyfin", - table: "Devices", - columns: new[] { "DeviceId", "DateLastActivity" }); - - migrationBuilder.CreateIndex( - name: "IX_Devices_UserId_DeviceId", - schema: "jellyfin", - table: "Devices", - columns: new[] { "UserId", "DeviceId" }); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "ApiKeys", - schema: "jellyfin"); - - migrationBuilder.DropTable( - name: "DeviceOptions", - schema: "jellyfin"); - - migrationBuilder.DropTable( - name: "Devices", - schema: "jellyfin"); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20221022080052_AddIndexActivityLogsDateCreated.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20221022080052_AddIndexActivityLogsDateCreated.Designer.cs deleted file mode 100644 index ab7781d1..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20221022080052_AddIndexActivityLogsDateCreated.Designer.cs +++ /dev/null @@ -1,657 +0,0 @@ -#pragma warning disable CS1591 - -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20221022080052_AddIndexActivityLogsDateCreated")] - partial class AddIndexActivityLogsDateCreated - { - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasDefaultSchema("jellyfin") - .HasAnnotation("ProductVersion", "6.0.9"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules", "jellyfin"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs", "jellyfin"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences", "jellyfin"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences", "jellyfin"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection", "jellyfin"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos", "jellyfin"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences", "jellyfin"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions", "jellyfin"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences", "jellyfin"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys", "jellyfin"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices", "jellyfin"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions", "jellyfin"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EasyPassword") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT") - .UseCollation("NOCASE"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users", "jellyfin"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20221022080052_AddIndexActivityLogsDateCreated.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20221022080052_AddIndexActivityLogsDateCreated.cs deleted file mode 100644 index 3e00b090..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20221022080052_AddIndexActivityLogsDateCreated.cs +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#pragma warning disable CS1591, SA1601 - -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - public partial class AddIndexActivityLogsDateCreated : Migration - { - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateIndex( - name: "IX_ActivityLogs_DateCreated", - schema: "jellyfin", - table: "ActivityLogs", - column: "DateCreated"); - } - - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_ActivityLogs_DateCreated", - schema: "jellyfin", - table: "ActivityLogs"); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230526173516_RemoveEasyPassword.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230526173516_RemoveEasyPassword.Designer.cs deleted file mode 100644 index 8a280611..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230526173516_RemoveEasyPassword.Designer.cs +++ /dev/null @@ -1,650 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20230526173516_RemoveEasyPassword")] - partial class RemoveEasyPassword - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "7.0.5"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT") - .UseCollation("NOCASE"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230526173516_RemoveEasyPassword.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230526173516_RemoveEasyPassword.cs deleted file mode 100644 index 0153640f..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230526173516_RemoveEasyPassword.cs +++ /dev/null @@ -1,168 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class RemoveEasyPassword : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "EasyPassword", - schema: "jellyfin", - table: "Users"); - - migrationBuilder.RenameTable( - name: "Users", - schema: "jellyfin", - newName: "Users"); - - migrationBuilder.RenameTable( - name: "Preferences", - schema: "jellyfin", - newName: "Preferences"); - - migrationBuilder.RenameTable( - name: "Permissions", - schema: "jellyfin", - newName: "Permissions"); - - migrationBuilder.RenameTable( - name: "ItemDisplayPreferences", - schema: "jellyfin", - newName: "ItemDisplayPreferences"); - - migrationBuilder.RenameTable( - name: "ImageInfos", - schema: "jellyfin", - newName: "ImageInfos"); - - migrationBuilder.RenameTable( - name: "HomeSection", - schema: "jellyfin", - newName: "HomeSection"); - - migrationBuilder.RenameTable( - name: "DisplayPreferences", - schema: "jellyfin", - newName: "DisplayPreferences"); - - migrationBuilder.RenameTable( - name: "Devices", - schema: "jellyfin", - newName: "Devices"); - - migrationBuilder.RenameTable( - name: "DeviceOptions", - schema: "jellyfin", - newName: "DeviceOptions"); - - migrationBuilder.RenameTable( - name: "CustomItemDisplayPreferences", - schema: "jellyfin", - newName: "CustomItemDisplayPreferences"); - - migrationBuilder.RenameTable( - name: "ApiKeys", - schema: "jellyfin", - newName: "ApiKeys"); - - migrationBuilder.RenameTable( - name: "ActivityLogs", - schema: "jellyfin", - newName: "ActivityLogs"); - - migrationBuilder.RenameTable( - name: "AccessSchedules", - schema: "jellyfin", - newName: "AccessSchedules"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.EnsureSchema( - name: "jellyfin"); - - migrationBuilder.RenameTable( - name: "Users", - newName: "Users", - newSchema: "jellyfin"); - - migrationBuilder.RenameTable( - name: "Preferences", - newName: "Preferences", - newSchema: "jellyfin"); - - migrationBuilder.RenameTable( - name: "Permissions", - newName: "Permissions", - newSchema: "jellyfin"); - - migrationBuilder.RenameTable( - name: "ItemDisplayPreferences", - newName: "ItemDisplayPreferences", - newSchema: "jellyfin"); - - migrationBuilder.RenameTable( - name: "ImageInfos", - newName: "ImageInfos", - newSchema: "jellyfin"); - - migrationBuilder.RenameTable( - name: "HomeSection", - newName: "HomeSection", - newSchema: "jellyfin"); - - migrationBuilder.RenameTable( - name: "DisplayPreferences", - newName: "DisplayPreferences", - newSchema: "jellyfin"); - - migrationBuilder.RenameTable( - name: "Devices", - newName: "Devices", - newSchema: "jellyfin"); - - migrationBuilder.RenameTable( - name: "DeviceOptions", - newName: "DeviceOptions", - newSchema: "jellyfin"); - - migrationBuilder.RenameTable( - name: "CustomItemDisplayPreferences", - newName: "CustomItemDisplayPreferences", - newSchema: "jellyfin"); - - migrationBuilder.RenameTable( - name: "ApiKeys", - newName: "ApiKeys", - newSchema: "jellyfin"); - - migrationBuilder.RenameTable( - name: "ActivityLogs", - newName: "ActivityLogs", - newSchema: "jellyfin"); - - migrationBuilder.RenameTable( - name: "AccessSchedules", - newName: "AccessSchedules", - newSchema: "jellyfin"); - - migrationBuilder.AddColumn( - name: "EasyPassword", - schema: "jellyfin", - table: "Users", - type: "TEXT", - maxLength: 65535, - nullable: true); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230626233818_AddTrickplayInfos.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230626233818_AddTrickplayInfos.Designer.cs deleted file mode 100644 index a11507bd..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230626233818_AddTrickplayInfos.Designer.cs +++ /dev/null @@ -1,681 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20230626233818_AddTrickplayInfos")] - partial class AddTrickplayInfos - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "7.0.7"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT") - .UseCollation("NOCASE"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230626233818_AddTrickplayInfos.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230626233818_AddTrickplayInfos.cs deleted file mode 100644 index f0d5a738..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230626233818_AddTrickplayInfos.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using System; - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class AddTrickplayInfos : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "TrickplayInfos", - columns: table => new - { - ItemId = table.Column(type: "TEXT", nullable: false), - Width = table.Column(type: "INTEGER", nullable: false), - Height = table.Column(type: "INTEGER", nullable: false), - TileWidth = table.Column(type: "INTEGER", nullable: false), - TileHeight = table.Column(type: "INTEGER", nullable: false), - ThumbnailCount = table.Column(type: "INTEGER", nullable: false), - Interval = table.Column(type: "INTEGER", nullable: false), - Bandwidth = table.Column(type: "INTEGER", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_TrickplayInfos", x => new { x.ItemId, x.Width }); - }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "TrickplayInfos"); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230923170422_UserCastReceiver.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230923170422_UserCastReceiver.Designer.cs deleted file mode 100644 index ddea37f6..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230923170422_UserCastReceiver.Designer.cs +++ /dev/null @@ -1,654 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20230923170422_UserCastReceiver")] - partial class UserCastReceiver - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "7.0.11"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT") - .UseCollation("NOCASE"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230923170422_UserCastReceiver.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230923170422_UserCastReceiver.cs deleted file mode 100644 index c5a8169f..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20230923170422_UserCastReceiver.cs +++ /dev/null @@ -1,33 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class UserCastReceiver : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "CastReceiverId", - table: "Users", - type: "TEXT", - maxLength: 32, - nullable: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "CastReceiverId", - table: "Users"); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240729140605_AddMediaSegments.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240729140605_AddMediaSegments.Designer.cs deleted file mode 100644 index ab7065ee..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240729140605_AddMediaSegments.Designer.cs +++ /dev/null @@ -1,708 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20240729140605_AddMediaSegments")] - partial class AddMediaSegments - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "8.0.7"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT") - .UseCollation("NOCASE"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240729140605_AddMediaSegments.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240729140605_AddMediaSegments.cs deleted file mode 100644 index 13f8dc60..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240729140605_AddMediaSegments.cs +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using System; - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class AddMediaSegments : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "MediaSegments", - columns: table => new - { - Id = table.Column(type: "TEXT", nullable: false), - ItemId = table.Column(type: "TEXT", nullable: false), - Type = table.Column(type: "INTEGER", nullable: false), - EndTicks = table.Column(type: "INTEGER", nullable: false), - StartTicks = table.Column(type: "INTEGER", nullable: false), - SegmentProviderId = table.Column(type: "TEXT", nullable: false), - }, - constraints: table => - { - table.PrimaryKey("PK_MediaSegments", x => x.Id); - }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "MediaSegments"); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240928082930_MarkSegmentProviderIdNonNullable.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240928082930_MarkSegmentProviderIdNonNullable.Designer.cs deleted file mode 100644 index aa60bff3..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240928082930_MarkSegmentProviderIdNonNullable.Designer.cs +++ /dev/null @@ -1,712 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20240928082930_MarkSegmentProviderIdNonNullable")] - partial class MarkSegmentProviderIdNonNullable - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "8.0.8"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT") - .UseCollation("NOCASE"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240928082930_MarkSegmentProviderIdNonNullable.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240928082930_MarkSegmentProviderIdNonNullable.cs deleted file mode 100644 index 6b75fed0..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20240928082930_MarkSegmentProviderIdNonNullable.cs +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class MarkSegmentProviderIdNonNullable : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "SegmentProviderId", - table: "MediaSegments", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "SegmentProviderId", - table: "MediaSegments", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241020103111_LibraryDbMigration.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241020103111_LibraryDbMigration.Designer.cs deleted file mode 100644 index 2ea6dafe..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241020103111_LibraryDbMigration.Designer.cs +++ /dev/null @@ -1,1607 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20241020103111_LibraryDbMigration")] - partial class LibraryDbMigration - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "8.0.10"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AncestorId", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ParentItemId") - .HasColumnType("TEXT"); - - b.Property("BaseItemEntityId") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ParentItemId"); - - b.HasIndex("BaseItemEntityId"); - - b.HasIndex("ParentItemId"); - - b.ToTable("AncestorIds"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AttachmentStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Index") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("Filename") - .HasColumnType("TEXT"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "Index"); - - b.ToTable("AttachmentStreamInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Album") - .HasColumnType("TEXT"); - - b.Property("AlbumArtists") - .HasColumnType("TEXT"); - - b.Property("Artists") - .HasColumnType("TEXT"); - - b.Property("Audio") - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("TEXT"); - - b.Property("CleanName") - .HasColumnType("TEXT"); - - b.Property("CommunityRating") - .HasColumnType("REAL"); - - b.Property("CriticRating") - .HasColumnType("REAL"); - - b.Property("CustomRating") - .HasColumnType("TEXT"); - - b.Property("Data") - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastMediaAdded") - .HasColumnType("TEXT"); - - b.Property("DateLastRefreshed") - .HasColumnType("TEXT"); - - b.Property("DateLastSaved") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("EpisodeTitle") - .HasColumnType("TEXT"); - - b.Property("ExternalId") - .HasColumnType("TEXT"); - - b.Property("ExternalSeriesId") - .HasColumnType("TEXT"); - - b.Property("ExternalServiceId") - .HasColumnType("TEXT"); - - b.Property("ExtraIds") - .HasColumnType("TEXT"); - - b.Property("ExtraType") - .HasColumnType("INTEGER"); - - b.Property("ForcedSortName") - .HasColumnType("TEXT"); - - b.Property("Genres") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IndexNumber") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingValue") - .HasColumnType("INTEGER"); - - b.Property("IsFolder") - .HasColumnType("INTEGER"); - - b.Property("IsInMixedFolder") - .HasColumnType("INTEGER"); - - b.Property("IsLocked") - .HasColumnType("INTEGER"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("IsRepeat") - .HasColumnType("INTEGER"); - - b.Property("IsSeries") - .HasColumnType("INTEGER"); - - b.Property("IsVirtualItem") - .HasColumnType("INTEGER"); - - b.Property("LUFS") - .HasColumnType("REAL"); - - b.Property("MediaType") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("NormalizationGain") - .HasColumnType("REAL"); - - b.Property("OfficialRating") - .HasColumnType("TEXT"); - - b.Property("OriginalTitle") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .HasColumnType("TEXT"); - - b.Property("ParentId") - .HasColumnType("TEXT"); - - b.Property("ParentIndexNumber") - .HasColumnType("INTEGER"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataCountryCode") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataLanguage") - .HasColumnType("TEXT"); - - b.Property("PremiereDate") - .HasColumnType("TEXT"); - - b.Property("PresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("PrimaryVersionId") - .HasColumnType("TEXT"); - - b.Property("ProductionLocations") - .HasColumnType("TEXT"); - - b.Property("ProductionYear") - .HasColumnType("INTEGER"); - - b.Property("RunTimeTicks") - .HasColumnType("INTEGER"); - - b.Property("SeasonId") - .HasColumnType("TEXT"); - - b.Property("SeasonName") - .HasColumnType("TEXT"); - - b.Property("SeriesId") - .HasColumnType("TEXT"); - - b.Property("SeriesName") - .HasColumnType("TEXT"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("ShowId") - .HasColumnType("TEXT"); - - b.Property("Size") - .HasColumnType("INTEGER"); - - b.Property("SortName") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Studios") - .HasColumnType("TEXT"); - - b.Property("Tagline") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT"); - - b.Property("TopParentId") - .HasColumnType("TEXT"); - - b.Property("TotalBitrate") - .HasColumnType("INTEGER"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UnratedType") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("Path"); - - b.HasIndex("PresentationUniqueKey"); - - b.HasIndex("TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - - b.HasIndex("Type", "TopParentId", "StartDate"); - - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); - - b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.ToTable("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Blurhash") - .HasColumnType("BLOB"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("ImageType") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemMetadataField", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemMetadataFields"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemProvider", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ProviderId") - .HasColumnType("TEXT"); - - b.Property("ProviderValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ProviderId"); - - b.HasIndex("ProviderId", "ProviderValue", "ItemId"); - - b.ToTable("BaseItemProviders"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemTrailerType", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemTrailerTypes"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Chapter", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ChapterIndex") - .HasColumnType("INTEGER"); - - b.Property("ImageDateModified") - .HasColumnType("TEXT"); - - b.Property("ImagePath") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("StartPositionTicks") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "ChapterIndex"); - - b.ToTable("Chapters"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValue", b => - { - b.Property("ItemValueId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CleanValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId"); - - b.HasIndex("Type", "CleanValue"); - - b.ToTable("ItemValues"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValueMap", b => - { - b.Property("ItemValueId") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("ItemValuesMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StreamIndex") - .HasColumnType("INTEGER"); - - b.Property("AspectRatio") - .HasColumnType("TEXT"); - - b.Property("AverageFrameRate") - .HasColumnType("REAL"); - - b.Property("BitDepth") - .HasColumnType("INTEGER"); - - b.Property("BitRate") - .HasColumnType("INTEGER"); - - b.Property("BlPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("ChannelLayout") - .HasColumnType("TEXT"); - - b.Property("Channels") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("CodecTimeBase") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("ColorPrimaries") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("ColorSpace") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("ColorTransfer") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Comment") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DvBlSignalCompatibilityId") - .HasColumnType("INTEGER"); - - b.Property("DvLevel") - .HasColumnType("INTEGER"); - - b.Property("DvProfile") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMajor") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMinor") - .HasColumnType("INTEGER"); - - b.Property("ElPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IsAnamorphic") - .HasColumnType("INTEGER"); - - b.Property("IsAvc") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("IsHearingImpaired") - .HasColumnType("INTEGER"); - - b.Property("IsInterlaced") - .HasColumnType("INTEGER"); - - b.Property("KeyFrames") - .HasColumnType("TEXT"); - - b.Property("Language") - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("REAL"); - - b.Property("NalLengthSize") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PixelFormat") - .HasColumnType("TEXT"); - - b.Property("Profile") - .HasColumnType("TEXT"); - - b.Property("RealFrameRate") - .HasColumnType("REAL"); - - b.Property("RefFrames") - .HasColumnType("INTEGER"); - - b.Property("Rotation") - .HasColumnType("INTEGER"); - - b.Property("RpuPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("SampleRate") - .HasColumnType("INTEGER"); - - b.Property("StreamType") - .HasColumnType("INTEGER"); - - b.Property("TimeBase") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Title") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "StreamIndex"); - - b.HasIndex("StreamIndex"); - - b.HasIndex("StreamType"); - - b.HasIndex("StreamIndex", "StreamType"); - - b.HasIndex("StreamIndex", "StreamType", "Language"); - - b.ToTable("MediaStreamInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.People", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PersonType") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name"); - - b.ToTable("Peoples"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.PeopleBaseItemMap", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("PeopleId") - .HasColumnType("TEXT"); - - b.Property("ListOrder") - .HasColumnType("INTEGER"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "PeopleId"); - - b.HasIndex("PeopleId"); - - b.HasIndex("ItemId", "ListOrder"); - - b.HasIndex("ItemId", "SortOrder"); - - b.ToTable("PeopleBaseItemMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT") - .UseCollation("NOCASE"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.UserData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("AudioStreamIndex") - .HasColumnType("INTEGER"); - - b.Property("IsFavorite") - .HasColumnType("INTEGER"); - - b.Property("LastPlayedDate") - .HasColumnType("TEXT"); - - b.Property("Likes") - .HasColumnType("INTEGER"); - - b.Property("PlayCount") - .HasColumnType("INTEGER"); - - b.Property("PlaybackPositionTicks") - .HasColumnType("INTEGER"); - - b.Property("Played") - .HasColumnType("INTEGER"); - - b.Property("Rating") - .HasColumnType("REAL"); - - b.Property("SubtitleStreamIndex") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "UserId"); - - b.HasIndex("UserId"); - - b.HasIndex("ItemId", "UserId", "IsFavorite"); - - b.HasIndex("ItemId", "UserId", "LastPlayedDate"); - - b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks"); - - b.HasIndex("ItemId", "UserId", "Played"); - - b.ToTable("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AncestorId", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", null) - .WithMany("AncestorIds") - .HasForeignKey("BaseItemEntityId"); - - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "ParentItem") - .WithMany() - .HasForeignKey("ParentItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ParentItem"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AttachmentStreamInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Images") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemMetadataField", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("LockedFields") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemProvider", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Provider") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemTrailerType", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("TrailerTypes") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Chapter", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Chapters") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValueMap", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("ItemValues") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.ItemValue", "ItemValue") - .WithMany("BaseItemsMap") - .HasForeignKey("ItemValueId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ItemValue"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaStreamInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("MediaStreams") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.PeopleBaseItemMap", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Peoples") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.People", "People") - .WithMany("BaseItems") - .HasForeignKey("PeopleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("People"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.UserData", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("UserData") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemEntity", b => - { - b.Navigation("AncestorIds"); - - b.Navigation("Chapters"); - - b.Navigation("Images"); - - b.Navigation("ItemValues"); - - b.Navigation("LockedFields"); - - b.Navigation("MediaStreams"); - - b.Navigation("Peoples"); - - b.Navigation("Provider"); - - b.Navigation("TrailerTypes"); - - b.Navigation("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValue", b => - { - b.Navigation("BaseItemsMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.People", b => - { - b.Navigation("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241020103111_LibraryDbMigration.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241020103111_LibraryDbMigration.cs deleted file mode 100644 index c1149d5f..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241020103111_LibraryDbMigration.cs +++ /dev/null @@ -1,643 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using System; - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class LibraryDbMigration : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "BaseItems", - columns: table => new - { - Id = table.Column(type: "TEXT", nullable: false), - Type = table.Column(type: "TEXT", nullable: false), - Data = table.Column(type: "TEXT", nullable: true), - Path = table.Column(type: "TEXT", nullable: true), - StartDate = table.Column(type: "TEXT", nullable: false), - EndDate = table.Column(type: "TEXT", nullable: false), - ChannelId = table.Column(type: "TEXT", nullable: true), - IsMovie = table.Column(type: "INTEGER", nullable: false), - CommunityRating = table.Column(type: "REAL", nullable: true), - CustomRating = table.Column(type: "TEXT", nullable: true), - IndexNumber = table.Column(type: "INTEGER", nullable: true), - IsLocked = table.Column(type: "INTEGER", nullable: false), - Name = table.Column(type: "TEXT", nullable: true), - OfficialRating = table.Column(type: "TEXT", nullable: true), - MediaType = table.Column(type: "TEXT", nullable: true), - Overview = table.Column(type: "TEXT", nullable: true), - ParentIndexNumber = table.Column(type: "INTEGER", nullable: true), - PremiereDate = table.Column(type: "TEXT", nullable: true), - ProductionYear = table.Column(type: "INTEGER", nullable: true), - Genres = table.Column(type: "TEXT", nullable: true), - SortName = table.Column(type: "TEXT", nullable: true), - ForcedSortName = table.Column(type: "TEXT", nullable: true), - RunTimeTicks = table.Column(type: "INTEGER", nullable: true), - DateCreated = table.Column(type: "TEXT", nullable: true), - DateModified = table.Column(type: "TEXT", nullable: true), - IsSeries = table.Column(type: "INTEGER", nullable: false), - EpisodeTitle = table.Column(type: "TEXT", nullable: true), - IsRepeat = table.Column(type: "INTEGER", nullable: false), - PreferredMetadataLanguage = table.Column(type: "TEXT", nullable: true), - PreferredMetadataCountryCode = table.Column(type: "TEXT", nullable: true), - DateLastRefreshed = table.Column(type: "TEXT", nullable: true), - DateLastSaved = table.Column(type: "TEXT", nullable: true), - IsInMixedFolder = table.Column(type: "INTEGER", nullable: false), - Studios = table.Column(type: "TEXT", nullable: true), - ExternalServiceId = table.Column(type: "TEXT", nullable: true), - Tags = table.Column(type: "TEXT", nullable: true), - IsFolder = table.Column(type: "INTEGER", nullable: false), - InheritedParentalRatingValue = table.Column(type: "INTEGER", nullable: true), - UnratedType = table.Column(type: "TEXT", nullable: true), - CriticRating = table.Column(type: "REAL", nullable: true), - CleanName = table.Column(type: "TEXT", nullable: true), - PresentationUniqueKey = table.Column(type: "TEXT", nullable: true), - OriginalTitle = table.Column(type: "TEXT", nullable: true), - PrimaryVersionId = table.Column(type: "TEXT", nullable: true), - DateLastMediaAdded = table.Column(type: "TEXT", nullable: true), - Album = table.Column(type: "TEXT", nullable: true), - LUFS = table.Column(type: "REAL", nullable: true), - NormalizationGain = table.Column(type: "REAL", nullable: true), - IsVirtualItem = table.Column(type: "INTEGER", nullable: false), - SeriesName = table.Column(type: "TEXT", nullable: true), - SeasonName = table.Column(type: "TEXT", nullable: true), - ExternalSeriesId = table.Column(type: "TEXT", nullable: true), - Tagline = table.Column(type: "TEXT", nullable: true), - ProductionLocations = table.Column(type: "TEXT", nullable: true), - ExtraIds = table.Column(type: "TEXT", nullable: true), - TotalBitrate = table.Column(type: "INTEGER", nullable: true), - ExtraType = table.Column(type: "INTEGER", nullable: true), - Artists = table.Column(type: "TEXT", nullable: true), - AlbumArtists = table.Column(type: "TEXT", nullable: true), - ExternalId = table.Column(type: "TEXT", nullable: true), - SeriesPresentationUniqueKey = table.Column(type: "TEXT", nullable: true), - ShowId = table.Column(type: "TEXT", nullable: true), - OwnerId = table.Column(type: "TEXT", nullable: true), - Width = table.Column(type: "INTEGER", nullable: true), - Height = table.Column(type: "INTEGER", nullable: true), - Size = table.Column(type: "INTEGER", nullable: true), - Audio = table.Column(type: "INTEGER", nullable: true), - ParentId = table.Column(type: "TEXT", nullable: true), - TopParentId = table.Column(type: "TEXT", nullable: true), - SeasonId = table.Column(type: "TEXT", nullable: true), - SeriesId = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_BaseItems", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "ItemValues", - columns: table => new - { - ItemValueId = table.Column(type: "TEXT", nullable: false), - Type = table.Column(type: "INTEGER", nullable: false), - Value = table.Column(type: "TEXT", nullable: false), - CleanValue = table.Column(type: "TEXT", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ItemValues", x => x.ItemValueId); - }); - - migrationBuilder.CreateTable( - name: "Peoples", - columns: table => new - { - Id = table.Column(type: "TEXT", nullable: false), - Name = table.Column(type: "TEXT", nullable: false), - PersonType = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Peoples", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "AncestorIds", - columns: table => new - { - ParentItemId = table.Column(type: "TEXT", nullable: false), - ItemId = table.Column(type: "TEXT", nullable: false), - BaseItemEntityId = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AncestorIds", x => new { x.ItemId, x.ParentItemId }); - table.ForeignKey( - name: "FK_AncestorIds_BaseItems_BaseItemEntityId", - column: x => x.BaseItemEntityId, - principalTable: "BaseItems", - principalColumn: "Id"); - table.ForeignKey( - name: "FK_AncestorIds_BaseItems_ItemId", - column: x => x.ItemId, - principalTable: "BaseItems", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_AncestorIds_BaseItems_ParentItemId", - column: x => x.ParentItemId, - principalTable: "BaseItems", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "AttachmentStreamInfos", - columns: table => new - { - ItemId = table.Column(type: "TEXT", nullable: false), - Index = table.Column(type: "INTEGER", nullable: false), - Codec = table.Column(type: "TEXT", nullable: false), - CodecTag = table.Column(type: "TEXT", nullable: true), - Comment = table.Column(type: "TEXT", nullable: true), - Filename = table.Column(type: "TEXT", nullable: true), - MimeType = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_AttachmentStreamInfos", x => new { x.ItemId, x.Index }); - table.ForeignKey( - name: "FK_AttachmentStreamInfos_BaseItems_ItemId", - column: x => x.ItemId, - principalTable: "BaseItems", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "BaseItemImageInfos", - columns: table => new - { - Id = table.Column(type: "TEXT", nullable: false), - Path = table.Column(type: "TEXT", nullable: false), - DateModified = table.Column(type: "TEXT", nullable: false), - ImageType = table.Column(type: "INTEGER", nullable: false), - Width = table.Column(type: "INTEGER", nullable: false), - Height = table.Column(type: "INTEGER", nullable: false), - Blurhash = table.Column(type: "BLOB", nullable: true), - ItemId = table.Column(type: "TEXT", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_BaseItemImageInfos", x => x.Id); - table.ForeignKey( - name: "FK_BaseItemImageInfos_BaseItems_ItemId", - column: x => x.ItemId, - principalTable: "BaseItems", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "BaseItemMetadataFields", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false), - ItemId = table.Column(type: "TEXT", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_BaseItemMetadataFields", x => new { x.Id, x.ItemId }); - table.ForeignKey( - name: "FK_BaseItemMetadataFields_BaseItems_ItemId", - column: x => x.ItemId, - principalTable: "BaseItems", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "BaseItemProviders", - columns: table => new - { - ItemId = table.Column(type: "TEXT", nullable: false), - ProviderId = table.Column(type: "TEXT", nullable: false), - ProviderValue = table.Column(type: "TEXT", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_BaseItemProviders", x => new { x.ItemId, x.ProviderId }); - table.ForeignKey( - name: "FK_BaseItemProviders_BaseItems_ItemId", - column: x => x.ItemId, - principalTable: "BaseItems", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "BaseItemTrailerTypes", - columns: table => new - { - Id = table.Column(type: "INTEGER", nullable: false), - ItemId = table.Column(type: "TEXT", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_BaseItemTrailerTypes", x => new { x.Id, x.ItemId }); - table.ForeignKey( - name: "FK_BaseItemTrailerTypes_BaseItems_ItemId", - column: x => x.ItemId, - principalTable: "BaseItems", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Chapters", - columns: table => new - { - ItemId = table.Column(type: "TEXT", nullable: false), - ChapterIndex = table.Column(type: "INTEGER", nullable: false), - StartPositionTicks = table.Column(type: "INTEGER", nullable: false), - Name = table.Column(type: "TEXT", nullable: true), - ImagePath = table.Column(type: "TEXT", nullable: true), - ImageDateModified = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Chapters", x => new { x.ItemId, x.ChapterIndex }); - table.ForeignKey( - name: "FK_Chapters_BaseItems_ItemId", - column: x => x.ItemId, - principalTable: "BaseItems", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "MediaStreamInfos", - columns: table => new - { - ItemId = table.Column(type: "TEXT", nullable: false), - StreamIndex = table.Column(type: "INTEGER", nullable: false), - StreamType = table.Column(type: "INTEGER", nullable: true), - Codec = table.Column(type: "TEXT", nullable: true), - Language = table.Column(type: "TEXT", nullable: true), - ChannelLayout = table.Column(type: "TEXT", nullable: true), - Profile = table.Column(type: "TEXT", nullable: true), - AspectRatio = table.Column(type: "TEXT", nullable: true), - Path = table.Column(type: "TEXT", nullable: true), - IsInterlaced = table.Column(type: "INTEGER", nullable: false), - BitRate = table.Column(type: "INTEGER", nullable: false), - Channels = table.Column(type: "INTEGER", nullable: false), - SampleRate = table.Column(type: "INTEGER", nullable: false), - IsDefault = table.Column(type: "INTEGER", nullable: false), - IsForced = table.Column(type: "INTEGER", nullable: false), - IsExternal = table.Column(type: "INTEGER", nullable: false), - Height = table.Column(type: "INTEGER", nullable: false), - Width = table.Column(type: "INTEGER", nullable: false), - AverageFrameRate = table.Column(type: "REAL", nullable: false), - RealFrameRate = table.Column(type: "REAL", nullable: false), - Level = table.Column(type: "REAL", nullable: false), - PixelFormat = table.Column(type: "TEXT", nullable: true), - BitDepth = table.Column(type: "INTEGER", nullable: false), - IsAnamorphic = table.Column(type: "INTEGER", nullable: false), - RefFrames = table.Column(type: "INTEGER", nullable: false), - CodecTag = table.Column(type: "TEXT", nullable: false), - Comment = table.Column(type: "TEXT", nullable: false), - NalLengthSize = table.Column(type: "TEXT", nullable: false), - IsAvc = table.Column(type: "INTEGER", nullable: false), - Title = table.Column(type: "TEXT", nullable: false), - TimeBase = table.Column(type: "TEXT", nullable: false), - CodecTimeBase = table.Column(type: "TEXT", nullable: false), - ColorPrimaries = table.Column(type: "TEXT", nullable: false), - ColorSpace = table.Column(type: "TEXT", nullable: false), - ColorTransfer = table.Column(type: "TEXT", nullable: false), - DvVersionMajor = table.Column(type: "INTEGER", nullable: false), - DvVersionMinor = table.Column(type: "INTEGER", nullable: false), - DvProfile = table.Column(type: "INTEGER", nullable: false), - DvLevel = table.Column(type: "INTEGER", nullable: false), - RpuPresentFlag = table.Column(type: "INTEGER", nullable: false), - ElPresentFlag = table.Column(type: "INTEGER", nullable: false), - BlPresentFlag = table.Column(type: "INTEGER", nullable: false), - DvBlSignalCompatibilityId = table.Column(type: "INTEGER", nullable: false), - IsHearingImpaired = table.Column(type: "INTEGER", nullable: false), - Rotation = table.Column(type: "INTEGER", nullable: false), - KeyFrames = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_MediaStreamInfos", x => new { x.ItemId, x.StreamIndex }); - table.ForeignKey( - name: "FK_MediaStreamInfos_BaseItems_ItemId", - column: x => x.ItemId, - principalTable: "BaseItems", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "UserData", - columns: table => new - { - ItemId = table.Column(type: "TEXT", nullable: false), - UserId = table.Column(type: "TEXT", nullable: false), - Rating = table.Column(type: "REAL", nullable: true), - PlaybackPositionTicks = table.Column(type: "INTEGER", nullable: false), - PlayCount = table.Column(type: "INTEGER", nullable: false), - IsFavorite = table.Column(type: "INTEGER", nullable: false), - LastPlayedDate = table.Column(type: "TEXT", nullable: true), - Played = table.Column(type: "INTEGER", nullable: false), - AudioStreamIndex = table.Column(type: "INTEGER", nullable: true), - SubtitleStreamIndex = table.Column(type: "INTEGER", nullable: true), - Likes = table.Column(type: "INTEGER", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_UserData", x => new { x.ItemId, x.UserId }); - table.ForeignKey( - name: "FK_UserData_BaseItems_ItemId", - column: x => x.ItemId, - principalTable: "BaseItems", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_UserData_Users_UserId", - column: x => x.UserId, - principalTable: "Users", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "ItemValuesMap", - columns: table => new - { - ItemId = table.Column(type: "TEXT", nullable: false), - ItemValueId = table.Column(type: "TEXT", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_ItemValuesMap", x => new { x.ItemValueId, x.ItemId }); - table.ForeignKey( - name: "FK_ItemValuesMap_BaseItems_ItemId", - column: x => x.ItemId, - principalTable: "BaseItems", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_ItemValuesMap_ItemValues_ItemValueId", - column: x => x.ItemValueId, - principalTable: "ItemValues", - principalColumn: "ItemValueId", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "PeopleBaseItemMap", - columns: table => new - { - ItemId = table.Column(type: "TEXT", nullable: false), - PeopleId = table.Column(type: "TEXT", nullable: false), - SortOrder = table.Column(type: "INTEGER", nullable: true), - ListOrder = table.Column(type: "INTEGER", nullable: true), - Role = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_PeopleBaseItemMap", x => new { x.ItemId, x.PeopleId }); - table.ForeignKey( - name: "FK_PeopleBaseItemMap_BaseItems_ItemId", - column: x => x.ItemId, - principalTable: "BaseItems", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_PeopleBaseItemMap_Peoples_PeopleId", - column: x => x.PeopleId, - principalTable: "Peoples", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_AncestorIds_BaseItemEntityId", - table: "AncestorIds", - column: "BaseItemEntityId"); - - migrationBuilder.CreateIndex( - name: "IX_AncestorIds_ParentItemId", - table: "AncestorIds", - column: "ParentItemId"); - - migrationBuilder.CreateIndex( - name: "IX_BaseItemImageInfos_ItemId", - table: "BaseItemImageInfos", - column: "ItemId"); - - migrationBuilder.CreateIndex( - name: "IX_BaseItemMetadataFields_ItemId", - table: "BaseItemMetadataFields", - column: "ItemId"); - - migrationBuilder.CreateIndex( - name: "IX_BaseItemProviders_ProviderId_ProviderValue_ItemId", - table: "BaseItemProviders", - columns: new[] { "ProviderId", "ProviderValue", "ItemId" }); - - migrationBuilder.CreateIndex( - name: "IX_BaseItems_Id_Type_IsFolder_IsVirtualItem", - table: "BaseItems", - columns: new[] { "Id", "Type", "IsFolder", "IsVirtualItem" }); - - migrationBuilder.CreateIndex( - name: "IX_BaseItems_IsFolder_TopParentId_IsVirtualItem_PresentationUniqueKey_DateCreated", - table: "BaseItems", - columns: new[] { "IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated" }); - - migrationBuilder.CreateIndex( - name: "IX_BaseItems_MediaType_TopParentId_IsVirtualItem_PresentationUniqueKey", - table: "BaseItems", - columns: new[] { "MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey" }); - - migrationBuilder.CreateIndex( - name: "IX_BaseItems_ParentId", - table: "BaseItems", - column: "ParentId"); - - migrationBuilder.CreateIndex( - name: "IX_BaseItems_Path", - table: "BaseItems", - column: "Path"); - - migrationBuilder.CreateIndex( - name: "IX_BaseItems_PresentationUniqueKey", - table: "BaseItems", - column: "PresentationUniqueKey"); - - migrationBuilder.CreateIndex( - name: "IX_BaseItems_TopParentId_Id", - table: "BaseItems", - columns: new[] { "TopParentId", "Id" }); - - migrationBuilder.CreateIndex( - name: "IX_BaseItems_Type_SeriesPresentationUniqueKey_IsFolder_IsVirtualItem", - table: "BaseItems", - columns: new[] { "Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem" }); - - migrationBuilder.CreateIndex( - name: "IX_BaseItems_Type_SeriesPresentationUniqueKey_PresentationUniqueKey_SortName", - table: "BaseItems", - columns: new[] { "Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName" }); - - migrationBuilder.CreateIndex( - name: "IX_BaseItems_Type_TopParentId_Id", - table: "BaseItems", - columns: new[] { "Type", "TopParentId", "Id" }); - - migrationBuilder.CreateIndex( - name: "IX_BaseItems_Type_TopParentId_IsVirtualItem_PresentationUniqueKey_DateCreated", - table: "BaseItems", - columns: new[] { "Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated" }); - - migrationBuilder.CreateIndex( - name: "IX_BaseItems_Type_TopParentId_PresentationUniqueKey", - table: "BaseItems", - columns: new[] { "Type", "TopParentId", "PresentationUniqueKey" }); - - migrationBuilder.CreateIndex( - name: "IX_BaseItems_Type_TopParentId_StartDate", - table: "BaseItems", - columns: new[] { "Type", "TopParentId", "StartDate" }); - - migrationBuilder.CreateIndex( - name: "IX_BaseItemTrailerTypes_ItemId", - table: "BaseItemTrailerTypes", - column: "ItemId"); - - migrationBuilder.CreateIndex( - name: "IX_ItemValues_Type_CleanValue", - table: "ItemValues", - columns: new[] { "Type", "CleanValue" }); - - migrationBuilder.CreateIndex( - name: "IX_ItemValuesMap_ItemId", - table: "ItemValuesMap", - column: "ItemId"); - - migrationBuilder.CreateIndex( - name: "IX_MediaStreamInfos_StreamIndex", - table: "MediaStreamInfos", - column: "StreamIndex"); - - migrationBuilder.CreateIndex( - name: "IX_MediaStreamInfos_StreamIndex_StreamType", - table: "MediaStreamInfos", - columns: new[] { "StreamIndex", "StreamType" }); - - migrationBuilder.CreateIndex( - name: "IX_MediaStreamInfos_StreamIndex_StreamType_Language", - table: "MediaStreamInfos", - columns: new[] { "StreamIndex", "StreamType", "Language" }); - - migrationBuilder.CreateIndex( - name: "IX_MediaStreamInfos_StreamType", - table: "MediaStreamInfos", - column: "StreamType"); - - migrationBuilder.CreateIndex( - name: "IX_PeopleBaseItemMap_ItemId_ListOrder", - table: "PeopleBaseItemMap", - columns: new[] { "ItemId", "ListOrder" }); - - migrationBuilder.CreateIndex( - name: "IX_PeopleBaseItemMap_ItemId_SortOrder", - table: "PeopleBaseItemMap", - columns: new[] { "ItemId", "SortOrder" }); - - migrationBuilder.CreateIndex( - name: "IX_PeopleBaseItemMap_PeopleId", - table: "PeopleBaseItemMap", - column: "PeopleId"); - - migrationBuilder.CreateIndex( - name: "IX_Peoples_Name", - table: "Peoples", - column: "Name"); - - migrationBuilder.CreateIndex( - name: "IX_UserData_ItemId_UserId_IsFavorite", - table: "UserData", - columns: new[] { "ItemId", "UserId", "IsFavorite" }); - - migrationBuilder.CreateIndex( - name: "IX_UserData_ItemId_UserId_LastPlayedDate", - table: "UserData", - columns: new[] { "ItemId", "UserId", "LastPlayedDate" }); - - migrationBuilder.CreateIndex( - name: "IX_UserData_ItemId_UserId_PlaybackPositionTicks", - table: "UserData", - columns: new[] { "ItemId", "UserId", "PlaybackPositionTicks" }); - - migrationBuilder.CreateIndex( - name: "IX_UserData_ItemId_UserId_Played", - table: "UserData", - columns: new[] { "ItemId", "UserId", "Played" }); - - migrationBuilder.CreateIndex( - name: "IX_UserData_UserId", - table: "UserData", - column: "UserId"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "AncestorIds"); - - migrationBuilder.DropTable( - name: "AttachmentStreamInfos"); - - migrationBuilder.DropTable( - name: "BaseItemImageInfos"); - - migrationBuilder.DropTable( - name: "BaseItemMetadataFields"); - - migrationBuilder.DropTable( - name: "BaseItemProviders"); - - migrationBuilder.DropTable( - name: "BaseItemTrailerTypes"); - - migrationBuilder.DropTable( - name: "Chapters"); - - migrationBuilder.DropTable( - name: "ItemValuesMap"); - - migrationBuilder.DropTable( - name: "MediaStreamInfos"); - - migrationBuilder.DropTable( - name: "PeopleBaseItemMap"); - - migrationBuilder.DropTable( - name: "UserData"); - - migrationBuilder.DropTable( - name: "ItemValues"); - - migrationBuilder.DropTable( - name: "Peoples"); - - migrationBuilder.DropTable( - name: "BaseItems"); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111131257_AddedCustomDataKey.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111131257_AddedCustomDataKey.Designer.cs deleted file mode 100644 index d589a4af..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111131257_AddedCustomDataKey.Designer.cs +++ /dev/null @@ -1,1610 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20241111131257_AddedCustomDataKey")] - partial class AddedCustomDataKey - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "8.0.10"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AncestorId", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ParentItemId") - .HasColumnType("TEXT"); - - b.Property("BaseItemEntityId") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ParentItemId"); - - b.HasIndex("BaseItemEntityId"); - - b.HasIndex("ParentItemId"); - - b.ToTable("AncestorIds"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AttachmentStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Index") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("Filename") - .HasColumnType("TEXT"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "Index"); - - b.ToTable("AttachmentStreamInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Album") - .HasColumnType("TEXT"); - - b.Property("AlbumArtists") - .HasColumnType("TEXT"); - - b.Property("Artists") - .HasColumnType("TEXT"); - - b.Property("Audio") - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("TEXT"); - - b.Property("CleanName") - .HasColumnType("TEXT"); - - b.Property("CommunityRating") - .HasColumnType("REAL"); - - b.Property("CriticRating") - .HasColumnType("REAL"); - - b.Property("CustomRating") - .HasColumnType("TEXT"); - - b.Property("Data") - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastMediaAdded") - .HasColumnType("TEXT"); - - b.Property("DateLastRefreshed") - .HasColumnType("TEXT"); - - b.Property("DateLastSaved") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("EpisodeTitle") - .HasColumnType("TEXT"); - - b.Property("ExternalId") - .HasColumnType("TEXT"); - - b.Property("ExternalSeriesId") - .HasColumnType("TEXT"); - - b.Property("ExternalServiceId") - .HasColumnType("TEXT"); - - b.Property("ExtraIds") - .HasColumnType("TEXT"); - - b.Property("ExtraType") - .HasColumnType("INTEGER"); - - b.Property("ForcedSortName") - .HasColumnType("TEXT"); - - b.Property("Genres") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IndexNumber") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingValue") - .HasColumnType("INTEGER"); - - b.Property("IsFolder") - .HasColumnType("INTEGER"); - - b.Property("IsInMixedFolder") - .HasColumnType("INTEGER"); - - b.Property("IsLocked") - .HasColumnType("INTEGER"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("IsRepeat") - .HasColumnType("INTEGER"); - - b.Property("IsSeries") - .HasColumnType("INTEGER"); - - b.Property("IsVirtualItem") - .HasColumnType("INTEGER"); - - b.Property("LUFS") - .HasColumnType("REAL"); - - b.Property("MediaType") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("NormalizationGain") - .HasColumnType("REAL"); - - b.Property("OfficialRating") - .HasColumnType("TEXT"); - - b.Property("OriginalTitle") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .HasColumnType("TEXT"); - - b.Property("ParentId") - .HasColumnType("TEXT"); - - b.Property("ParentIndexNumber") - .HasColumnType("INTEGER"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataCountryCode") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataLanguage") - .HasColumnType("TEXT"); - - b.Property("PremiereDate") - .HasColumnType("TEXT"); - - b.Property("PresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("PrimaryVersionId") - .HasColumnType("TEXT"); - - b.Property("ProductionLocations") - .HasColumnType("TEXT"); - - b.Property("ProductionYear") - .HasColumnType("INTEGER"); - - b.Property("RunTimeTicks") - .HasColumnType("INTEGER"); - - b.Property("SeasonId") - .HasColumnType("TEXT"); - - b.Property("SeasonName") - .HasColumnType("TEXT"); - - b.Property("SeriesId") - .HasColumnType("TEXT"); - - b.Property("SeriesName") - .HasColumnType("TEXT"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("ShowId") - .HasColumnType("TEXT"); - - b.Property("Size") - .HasColumnType("INTEGER"); - - b.Property("SortName") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Studios") - .HasColumnType("TEXT"); - - b.Property("Tagline") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT"); - - b.Property("TopParentId") - .HasColumnType("TEXT"); - - b.Property("TotalBitrate") - .HasColumnType("INTEGER"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UnratedType") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("Path"); - - b.HasIndex("PresentationUniqueKey"); - - b.HasIndex("TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - - b.HasIndex("Type", "TopParentId", "StartDate"); - - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); - - b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.ToTable("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Blurhash") - .HasColumnType("BLOB"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("ImageType") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemMetadataField", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemMetadataFields"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemProvider", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ProviderId") - .HasColumnType("TEXT"); - - b.Property("ProviderValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ProviderId"); - - b.HasIndex("ProviderId", "ProviderValue", "ItemId"); - - b.ToTable("BaseItemProviders"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemTrailerType", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemTrailerTypes"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Chapter", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ChapterIndex") - .HasColumnType("INTEGER"); - - b.Property("ImageDateModified") - .HasColumnType("TEXT"); - - b.Property("ImagePath") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("StartPositionTicks") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "ChapterIndex"); - - b.ToTable("Chapters"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValue", b => - { - b.Property("ItemValueId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CleanValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId"); - - b.HasIndex("Type", "CleanValue"); - - b.ToTable("ItemValues"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValueMap", b => - { - b.Property("ItemValueId") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("ItemValuesMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StreamIndex") - .HasColumnType("INTEGER"); - - b.Property("AspectRatio") - .HasColumnType("TEXT"); - - b.Property("AverageFrameRate") - .HasColumnType("REAL"); - - b.Property("BitDepth") - .HasColumnType("INTEGER"); - - b.Property("BitRate") - .HasColumnType("INTEGER"); - - b.Property("BlPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("ChannelLayout") - .HasColumnType("TEXT"); - - b.Property("Channels") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("CodecTimeBase") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("ColorPrimaries") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("ColorSpace") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("ColorTransfer") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Comment") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DvBlSignalCompatibilityId") - .HasColumnType("INTEGER"); - - b.Property("DvLevel") - .HasColumnType("INTEGER"); - - b.Property("DvProfile") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMajor") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMinor") - .HasColumnType("INTEGER"); - - b.Property("ElPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IsAnamorphic") - .HasColumnType("INTEGER"); - - b.Property("IsAvc") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("IsHearingImpaired") - .HasColumnType("INTEGER"); - - b.Property("IsInterlaced") - .HasColumnType("INTEGER"); - - b.Property("KeyFrames") - .HasColumnType("TEXT"); - - b.Property("Language") - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("REAL"); - - b.Property("NalLengthSize") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PixelFormat") - .HasColumnType("TEXT"); - - b.Property("Profile") - .HasColumnType("TEXT"); - - b.Property("RealFrameRate") - .HasColumnType("REAL"); - - b.Property("RefFrames") - .HasColumnType("INTEGER"); - - b.Property("Rotation") - .HasColumnType("INTEGER"); - - b.Property("RpuPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("SampleRate") - .HasColumnType("INTEGER"); - - b.Property("StreamType") - .HasColumnType("INTEGER"); - - b.Property("TimeBase") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Title") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "StreamIndex"); - - b.HasIndex("StreamIndex"); - - b.HasIndex("StreamType"); - - b.HasIndex("StreamIndex", "StreamType"); - - b.HasIndex("StreamIndex", "StreamType", "Language"); - - b.ToTable("MediaStreamInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.People", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PersonType") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name"); - - b.ToTable("Peoples"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.PeopleBaseItemMap", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("PeopleId") - .HasColumnType("TEXT"); - - b.Property("ListOrder") - .HasColumnType("INTEGER"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "PeopleId"); - - b.HasIndex("PeopleId"); - - b.HasIndex("ItemId", "ListOrder"); - - b.HasIndex("ItemId", "SortOrder"); - - b.ToTable("PeopleBaseItemMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT") - .UseCollation("NOCASE"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.UserData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("AudioStreamIndex") - .HasColumnType("INTEGER"); - - b.Property("CustomDataKey") - .HasColumnType("TEXT"); - - b.Property("IsFavorite") - .HasColumnType("INTEGER"); - - b.Property("LastPlayedDate") - .HasColumnType("TEXT"); - - b.Property("Likes") - .HasColumnType("INTEGER"); - - b.Property("PlayCount") - .HasColumnType("INTEGER"); - - b.Property("PlaybackPositionTicks") - .HasColumnType("INTEGER"); - - b.Property("Played") - .HasColumnType("INTEGER"); - - b.Property("Rating") - .HasColumnType("REAL"); - - b.Property("SubtitleStreamIndex") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "UserId"); - - b.HasIndex("UserId"); - - b.HasIndex("ItemId", "UserId", "IsFavorite"); - - b.HasIndex("ItemId", "UserId", "LastPlayedDate"); - - b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks"); - - b.HasIndex("ItemId", "UserId", "Played"); - - b.ToTable("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AncestorId", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", null) - .WithMany("AncestorIds") - .HasForeignKey("BaseItemEntityId"); - - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "ParentItem") - .WithMany() - .HasForeignKey("ParentItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ParentItem"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AttachmentStreamInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Images") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemMetadataField", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("LockedFields") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemProvider", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Provider") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemTrailerType", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("TrailerTypes") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Chapter", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Chapters") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValueMap", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("ItemValues") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.ItemValue", "ItemValue") - .WithMany("BaseItemsMap") - .HasForeignKey("ItemValueId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ItemValue"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaStreamInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("MediaStreams") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.PeopleBaseItemMap", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Peoples") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.People", "People") - .WithMany("BaseItems") - .HasForeignKey("PeopleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("People"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.UserData", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("UserData") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemEntity", b => - { - b.Navigation("AncestorIds"); - - b.Navigation("Chapters"); - - b.Navigation("Images"); - - b.Navigation("ItemValues"); - - b.Navigation("LockedFields"); - - b.Navigation("MediaStreams"); - - b.Navigation("Peoples"); - - b.Navigation("Provider"); - - b.Navigation("TrailerTypes"); - - b.Navigation("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValue", b => - { - b.Navigation("BaseItemsMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.People", b => - { - b.Navigation("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111131257_AddedCustomDataKey.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111131257_AddedCustomDataKey.cs deleted file mode 100644 index b2b6e701..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111131257_AddedCustomDataKey.cs +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class AddedCustomDataKey : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "CustomDataKey", - table: "UserData", - type: "TEXT", - nullable: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "CustomDataKey", - table: "UserData"); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111135439_AddedCustomDataKeyKey.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111135439_AddedCustomDataKeyKey.Designer.cs deleted file mode 100644 index 3d70bb02..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111135439_AddedCustomDataKeyKey.Designer.cs +++ /dev/null @@ -1,1610 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20241111135439_AddedCustomDataKeyKey")] - partial class AddedCustomDataKeyKey - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "8.0.10"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AncestorId", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ParentItemId") - .HasColumnType("TEXT"); - - b.Property("BaseItemEntityId") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ParentItemId"); - - b.HasIndex("BaseItemEntityId"); - - b.HasIndex("ParentItemId"); - - b.ToTable("AncestorIds"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AttachmentStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Index") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("Filename") - .HasColumnType("TEXT"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "Index"); - - b.ToTable("AttachmentStreamInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Album") - .HasColumnType("TEXT"); - - b.Property("AlbumArtists") - .HasColumnType("TEXT"); - - b.Property("Artists") - .HasColumnType("TEXT"); - - b.Property("Audio") - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("TEXT"); - - b.Property("CleanName") - .HasColumnType("TEXT"); - - b.Property("CommunityRating") - .HasColumnType("REAL"); - - b.Property("CriticRating") - .HasColumnType("REAL"); - - b.Property("CustomRating") - .HasColumnType("TEXT"); - - b.Property("Data") - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastMediaAdded") - .HasColumnType("TEXT"); - - b.Property("DateLastRefreshed") - .HasColumnType("TEXT"); - - b.Property("DateLastSaved") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("EpisodeTitle") - .HasColumnType("TEXT"); - - b.Property("ExternalId") - .HasColumnType("TEXT"); - - b.Property("ExternalSeriesId") - .HasColumnType("TEXT"); - - b.Property("ExternalServiceId") - .HasColumnType("TEXT"); - - b.Property("ExtraIds") - .HasColumnType("TEXT"); - - b.Property("ExtraType") - .HasColumnType("INTEGER"); - - b.Property("ForcedSortName") - .HasColumnType("TEXT"); - - b.Property("Genres") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IndexNumber") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingValue") - .HasColumnType("INTEGER"); - - b.Property("IsFolder") - .HasColumnType("INTEGER"); - - b.Property("IsInMixedFolder") - .HasColumnType("INTEGER"); - - b.Property("IsLocked") - .HasColumnType("INTEGER"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("IsRepeat") - .HasColumnType("INTEGER"); - - b.Property("IsSeries") - .HasColumnType("INTEGER"); - - b.Property("IsVirtualItem") - .HasColumnType("INTEGER"); - - b.Property("LUFS") - .HasColumnType("REAL"); - - b.Property("MediaType") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("NormalizationGain") - .HasColumnType("REAL"); - - b.Property("OfficialRating") - .HasColumnType("TEXT"); - - b.Property("OriginalTitle") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .HasColumnType("TEXT"); - - b.Property("ParentId") - .HasColumnType("TEXT"); - - b.Property("ParentIndexNumber") - .HasColumnType("INTEGER"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataCountryCode") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataLanguage") - .HasColumnType("TEXT"); - - b.Property("PremiereDate") - .HasColumnType("TEXT"); - - b.Property("PresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("PrimaryVersionId") - .HasColumnType("TEXT"); - - b.Property("ProductionLocations") - .HasColumnType("TEXT"); - - b.Property("ProductionYear") - .HasColumnType("INTEGER"); - - b.Property("RunTimeTicks") - .HasColumnType("INTEGER"); - - b.Property("SeasonId") - .HasColumnType("TEXT"); - - b.Property("SeasonName") - .HasColumnType("TEXT"); - - b.Property("SeriesId") - .HasColumnType("TEXT"); - - b.Property("SeriesName") - .HasColumnType("TEXT"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("ShowId") - .HasColumnType("TEXT"); - - b.Property("Size") - .HasColumnType("INTEGER"); - - b.Property("SortName") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Studios") - .HasColumnType("TEXT"); - - b.Property("Tagline") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT"); - - b.Property("TopParentId") - .HasColumnType("TEXT"); - - b.Property("TotalBitrate") - .HasColumnType("INTEGER"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UnratedType") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("Path"); - - b.HasIndex("PresentationUniqueKey"); - - b.HasIndex("TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - - b.HasIndex("Type", "TopParentId", "StartDate"); - - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); - - b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.ToTable("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Blurhash") - .HasColumnType("BLOB"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("ImageType") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemMetadataField", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemMetadataFields"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemProvider", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ProviderId") - .HasColumnType("TEXT"); - - b.Property("ProviderValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ProviderId"); - - b.HasIndex("ProviderId", "ProviderValue", "ItemId"); - - b.ToTable("BaseItemProviders"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemTrailerType", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemTrailerTypes"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Chapter", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ChapterIndex") - .HasColumnType("INTEGER"); - - b.Property("ImageDateModified") - .HasColumnType("TEXT"); - - b.Property("ImagePath") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("StartPositionTicks") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "ChapterIndex"); - - b.ToTable("Chapters"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValue", b => - { - b.Property("ItemValueId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CleanValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId"); - - b.HasIndex("Type", "CleanValue"); - - b.ToTable("ItemValues"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValueMap", b => - { - b.Property("ItemValueId") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("ItemValuesMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StreamIndex") - .HasColumnType("INTEGER"); - - b.Property("AspectRatio") - .HasColumnType("TEXT"); - - b.Property("AverageFrameRate") - .HasColumnType("REAL"); - - b.Property("BitDepth") - .HasColumnType("INTEGER"); - - b.Property("BitRate") - .HasColumnType("INTEGER"); - - b.Property("BlPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("ChannelLayout") - .HasColumnType("TEXT"); - - b.Property("Channels") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("CodecTimeBase") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("ColorPrimaries") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("ColorSpace") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("ColorTransfer") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Comment") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DvBlSignalCompatibilityId") - .HasColumnType("INTEGER"); - - b.Property("DvLevel") - .HasColumnType("INTEGER"); - - b.Property("DvProfile") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMajor") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMinor") - .HasColumnType("INTEGER"); - - b.Property("ElPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IsAnamorphic") - .HasColumnType("INTEGER"); - - b.Property("IsAvc") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("IsHearingImpaired") - .HasColumnType("INTEGER"); - - b.Property("IsInterlaced") - .HasColumnType("INTEGER"); - - b.Property("KeyFrames") - .HasColumnType("TEXT"); - - b.Property("Language") - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("REAL"); - - b.Property("NalLengthSize") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PixelFormat") - .HasColumnType("TEXT"); - - b.Property("Profile") - .HasColumnType("TEXT"); - - b.Property("RealFrameRate") - .HasColumnType("REAL"); - - b.Property("RefFrames") - .HasColumnType("INTEGER"); - - b.Property("Rotation") - .HasColumnType("INTEGER"); - - b.Property("RpuPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("SampleRate") - .HasColumnType("INTEGER"); - - b.Property("StreamType") - .HasColumnType("INTEGER"); - - b.Property("TimeBase") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Title") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "StreamIndex"); - - b.HasIndex("StreamIndex"); - - b.HasIndex("StreamType"); - - b.HasIndex("StreamIndex", "StreamType"); - - b.HasIndex("StreamIndex", "StreamType", "Language"); - - b.ToTable("MediaStreamInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.People", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PersonType") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name"); - - b.ToTable("Peoples"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.PeopleBaseItemMap", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("PeopleId") - .HasColumnType("TEXT"); - - b.Property("ListOrder") - .HasColumnType("INTEGER"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "PeopleId"); - - b.HasIndex("PeopleId"); - - b.HasIndex("ItemId", "ListOrder"); - - b.HasIndex("ItemId", "SortOrder"); - - b.ToTable("PeopleBaseItemMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT") - .UseCollation("NOCASE"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.UserData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("CustomDataKey") - .HasColumnType("TEXT"); - - b.Property("AudioStreamIndex") - .HasColumnType("INTEGER"); - - b.Property("IsFavorite") - .HasColumnType("INTEGER"); - - b.Property("LastPlayedDate") - .HasColumnType("TEXT"); - - b.Property("Likes") - .HasColumnType("INTEGER"); - - b.Property("PlayCount") - .HasColumnType("INTEGER"); - - b.Property("PlaybackPositionTicks") - .HasColumnType("INTEGER"); - - b.Property("Played") - .HasColumnType("INTEGER"); - - b.Property("Rating") - .HasColumnType("REAL"); - - b.Property("SubtitleStreamIndex") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "UserId", "CustomDataKey"); - - b.HasIndex("UserId"); - - b.HasIndex("ItemId", "UserId", "IsFavorite"); - - b.HasIndex("ItemId", "UserId", "LastPlayedDate"); - - b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks"); - - b.HasIndex("ItemId", "UserId", "Played"); - - b.ToTable("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AncestorId", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", null) - .WithMany("AncestorIds") - .HasForeignKey("BaseItemEntityId"); - - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "ParentItem") - .WithMany() - .HasForeignKey("ParentItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ParentItem"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AttachmentStreamInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Images") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemMetadataField", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("LockedFields") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemProvider", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Provider") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemTrailerType", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("TrailerTypes") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Chapter", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Chapters") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValueMap", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("ItemValues") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.ItemValue", "ItemValue") - .WithMany("BaseItemsMap") - .HasForeignKey("ItemValueId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ItemValue"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaStreamInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("MediaStreams") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.PeopleBaseItemMap", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Peoples") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.People", "People") - .WithMany("BaseItems") - .HasForeignKey("PeopleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("People"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.UserData", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("UserData") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemEntity", b => - { - b.Navigation("AncestorIds"); - - b.Navigation("Chapters"); - - b.Navigation("Images"); - - b.Navigation("ItemValues"); - - b.Navigation("LockedFields"); - - b.Navigation("MediaStreams"); - - b.Navigation("Peoples"); - - b.Navigation("Provider"); - - b.Navigation("TrailerTypes"); - - b.Navigation("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValue", b => - { - b.Navigation("BaseItemsMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.People", b => - { - b.Navigation("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111135439_AddedCustomDataKeyKey.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111135439_AddedCustomDataKeyKey.cs deleted file mode 100644 index c5c7703e..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241111135439_AddedCustomDataKeyKey.cs +++ /dev/null @@ -1,58 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class AddedCustomDataKeyKey : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropPrimaryKey( - name: "PK_UserData", - table: "UserData"); - - migrationBuilder.AlterColumn( - name: "CustomDataKey", - table: "UserData", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AddPrimaryKey( - name: "PK_UserData", - table: "UserData", - columns: new[] { "ItemId", "UserId", "CustomDataKey" }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropPrimaryKey( - name: "PK_UserData", - table: "UserData"); - - migrationBuilder.AlterColumn( - name: "CustomDataKey", - table: "UserData", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AddPrimaryKey( - name: "PK_UserData", - table: "UserData", - columns: new[] { "ItemId", "UserId" }); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112152323_FixAncestorIdConfig.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112152323_FixAncestorIdConfig.Designer.cs deleted file mode 100644 index 1e0d3b12..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112152323_FixAncestorIdConfig.Designer.cs +++ /dev/null @@ -1,1603 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20241112152323_FixAncestorIdConfig")] - partial class FixAncestorIdConfig - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "8.0.10"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AncestorId", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ParentItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ParentItemId"); - - b.HasIndex("ParentItemId"); - - b.ToTable("AncestorIds"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AttachmentStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Index") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("Filename") - .HasColumnType("TEXT"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "Index"); - - b.ToTable("AttachmentStreamInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Album") - .HasColumnType("TEXT"); - - b.Property("AlbumArtists") - .HasColumnType("TEXT"); - - b.Property("Artists") - .HasColumnType("TEXT"); - - b.Property("Audio") - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("TEXT"); - - b.Property("CleanName") - .HasColumnType("TEXT"); - - b.Property("CommunityRating") - .HasColumnType("REAL"); - - b.Property("CriticRating") - .HasColumnType("REAL"); - - b.Property("CustomRating") - .HasColumnType("TEXT"); - - b.Property("Data") - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastMediaAdded") - .HasColumnType("TEXT"); - - b.Property("DateLastRefreshed") - .HasColumnType("TEXT"); - - b.Property("DateLastSaved") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("EpisodeTitle") - .HasColumnType("TEXT"); - - b.Property("ExternalId") - .HasColumnType("TEXT"); - - b.Property("ExternalSeriesId") - .HasColumnType("TEXT"); - - b.Property("ExternalServiceId") - .HasColumnType("TEXT"); - - b.Property("ExtraIds") - .HasColumnType("TEXT"); - - b.Property("ExtraType") - .HasColumnType("INTEGER"); - - b.Property("ForcedSortName") - .HasColumnType("TEXT"); - - b.Property("Genres") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IndexNumber") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingValue") - .HasColumnType("INTEGER"); - - b.Property("IsFolder") - .HasColumnType("INTEGER"); - - b.Property("IsInMixedFolder") - .HasColumnType("INTEGER"); - - b.Property("IsLocked") - .HasColumnType("INTEGER"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("IsRepeat") - .HasColumnType("INTEGER"); - - b.Property("IsSeries") - .HasColumnType("INTEGER"); - - b.Property("IsVirtualItem") - .HasColumnType("INTEGER"); - - b.Property("LUFS") - .HasColumnType("REAL"); - - b.Property("MediaType") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("NormalizationGain") - .HasColumnType("REAL"); - - b.Property("OfficialRating") - .HasColumnType("TEXT"); - - b.Property("OriginalTitle") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .HasColumnType("TEXT"); - - b.Property("ParentId") - .HasColumnType("TEXT"); - - b.Property("ParentIndexNumber") - .HasColumnType("INTEGER"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataCountryCode") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataLanguage") - .HasColumnType("TEXT"); - - b.Property("PremiereDate") - .HasColumnType("TEXT"); - - b.Property("PresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("PrimaryVersionId") - .HasColumnType("TEXT"); - - b.Property("ProductionLocations") - .HasColumnType("TEXT"); - - b.Property("ProductionYear") - .HasColumnType("INTEGER"); - - b.Property("RunTimeTicks") - .HasColumnType("INTEGER"); - - b.Property("SeasonId") - .HasColumnType("TEXT"); - - b.Property("SeasonName") - .HasColumnType("TEXT"); - - b.Property("SeriesId") - .HasColumnType("TEXT"); - - b.Property("SeriesName") - .HasColumnType("TEXT"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("ShowId") - .HasColumnType("TEXT"); - - b.Property("Size") - .HasColumnType("INTEGER"); - - b.Property("SortName") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Studios") - .HasColumnType("TEXT"); - - b.Property("Tagline") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT"); - - b.Property("TopParentId") - .HasColumnType("TEXT"); - - b.Property("TotalBitrate") - .HasColumnType("INTEGER"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UnratedType") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("Path"); - - b.HasIndex("PresentationUniqueKey"); - - b.HasIndex("TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - - b.HasIndex("Type", "TopParentId", "StartDate"); - - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); - - b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.ToTable("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Blurhash") - .HasColumnType("BLOB"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("ImageType") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemMetadataField", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemMetadataFields"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemProvider", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ProviderId") - .HasColumnType("TEXT"); - - b.Property("ProviderValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ProviderId"); - - b.HasIndex("ProviderId", "ProviderValue", "ItemId"); - - b.ToTable("BaseItemProviders"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemTrailerType", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemTrailerTypes"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Chapter", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ChapterIndex") - .HasColumnType("INTEGER"); - - b.Property("ImageDateModified") - .HasColumnType("TEXT"); - - b.Property("ImagePath") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("StartPositionTicks") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "ChapterIndex"); - - b.ToTable("Chapters"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValue", b => - { - b.Property("ItemValueId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CleanValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId"); - - b.HasIndex("Type", "CleanValue"); - - b.ToTable("ItemValues"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValueMap", b => - { - b.Property("ItemValueId") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("ItemValuesMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StreamIndex") - .HasColumnType("INTEGER"); - - b.Property("AspectRatio") - .HasColumnType("TEXT"); - - b.Property("AverageFrameRate") - .HasColumnType("REAL"); - - b.Property("BitDepth") - .HasColumnType("INTEGER"); - - b.Property("BitRate") - .HasColumnType("INTEGER"); - - b.Property("BlPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("ChannelLayout") - .HasColumnType("TEXT"); - - b.Property("Channels") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("CodecTimeBase") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("ColorPrimaries") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("ColorSpace") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("ColorTransfer") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Comment") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DvBlSignalCompatibilityId") - .HasColumnType("INTEGER"); - - b.Property("DvLevel") - .HasColumnType("INTEGER"); - - b.Property("DvProfile") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMajor") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMinor") - .HasColumnType("INTEGER"); - - b.Property("ElPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IsAnamorphic") - .HasColumnType("INTEGER"); - - b.Property("IsAvc") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("IsHearingImpaired") - .HasColumnType("INTEGER"); - - b.Property("IsInterlaced") - .HasColumnType("INTEGER"); - - b.Property("KeyFrames") - .HasColumnType("TEXT"); - - b.Property("Language") - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("REAL"); - - b.Property("NalLengthSize") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PixelFormat") - .HasColumnType("TEXT"); - - b.Property("Profile") - .HasColumnType("TEXT"); - - b.Property("RealFrameRate") - .HasColumnType("REAL"); - - b.Property("RefFrames") - .HasColumnType("INTEGER"); - - b.Property("Rotation") - .HasColumnType("INTEGER"); - - b.Property("RpuPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("SampleRate") - .HasColumnType("INTEGER"); - - b.Property("StreamType") - .HasColumnType("INTEGER"); - - b.Property("TimeBase") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Title") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "StreamIndex"); - - b.HasIndex("StreamIndex"); - - b.HasIndex("StreamType"); - - b.HasIndex("StreamIndex", "StreamType"); - - b.HasIndex("StreamIndex", "StreamType", "Language"); - - b.ToTable("MediaStreamInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.People", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PersonType") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name"); - - b.ToTable("Peoples"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.PeopleBaseItemMap", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("PeopleId") - .HasColumnType("TEXT"); - - b.Property("ListOrder") - .HasColumnType("INTEGER"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "PeopleId"); - - b.HasIndex("PeopleId"); - - b.HasIndex("ItemId", "ListOrder"); - - b.HasIndex("ItemId", "SortOrder"); - - b.ToTable("PeopleBaseItemMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT") - .UseCollation("NOCASE"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.UserData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("CustomDataKey") - .HasColumnType("TEXT"); - - b.Property("AudioStreamIndex") - .HasColumnType("INTEGER"); - - b.Property("IsFavorite") - .HasColumnType("INTEGER"); - - b.Property("LastPlayedDate") - .HasColumnType("TEXT"); - - b.Property("Likes") - .HasColumnType("INTEGER"); - - b.Property("PlayCount") - .HasColumnType("INTEGER"); - - b.Property("PlaybackPositionTicks") - .HasColumnType("INTEGER"); - - b.Property("Played") - .HasColumnType("INTEGER"); - - b.Property("Rating") - .HasColumnType("REAL"); - - b.Property("SubtitleStreamIndex") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "UserId", "CustomDataKey"); - - b.HasIndex("UserId"); - - b.HasIndex("ItemId", "UserId", "IsFavorite"); - - b.HasIndex("ItemId", "UserId", "LastPlayedDate"); - - b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks"); - - b.HasIndex("ItemId", "UserId", "Played"); - - b.ToTable("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AncestorId", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Children") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "ParentItem") - .WithMany("ParentAncestors") - .HasForeignKey("ParentItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ParentItem"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AttachmentStreamInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Images") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemMetadataField", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("LockedFields") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemProvider", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Provider") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemTrailerType", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("TrailerTypes") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Chapter", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Chapters") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValueMap", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("ItemValues") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.ItemValue", "ItemValue") - .WithMany("BaseItemsMap") - .HasForeignKey("ItemValueId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ItemValue"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaStreamInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("MediaStreams") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.PeopleBaseItemMap", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Peoples") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.People", "People") - .WithMany("BaseItems") - .HasForeignKey("PeopleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("People"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.UserData", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("UserData") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemEntity", b => - { - b.Navigation("Chapters"); - - b.Navigation("Children"); - - b.Navigation("Images"); - - b.Navigation("ItemValues"); - - b.Navigation("LockedFields"); - - b.Navigation("MediaStreams"); - - b.Navigation("ParentAncestors"); - - b.Navigation("Peoples"); - - b.Navigation("Provider"); - - b.Navigation("TrailerTypes"); - - b.Navigation("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValue", b => - { - b.Navigation("BaseItemsMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.People", b => - { - b.Navigation("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112152323_FixAncestorIdConfig.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112152323_FixAncestorIdConfig.cs deleted file mode 100644 index 466c32f2..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112152323_FixAncestorIdConfig.cs +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using System; - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class FixAncestorIdConfig : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_AncestorIds_BaseItems_BaseItemEntityId", - table: "AncestorIds"); - - migrationBuilder.DropIndex( - name: "IX_AncestorIds_BaseItemEntityId", - table: "AncestorIds"); - - migrationBuilder.DropColumn( - name: "BaseItemEntityId", - table: "AncestorIds"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "BaseItemEntityId", - table: "AncestorIds", - type: "TEXT", - nullable: true); - - migrationBuilder.CreateIndex( - name: "IX_AncestorIds_BaseItemEntityId", - table: "AncestorIds", - column: "BaseItemEntityId"); - - migrationBuilder.AddForeignKey( - name: "FK_AncestorIds_BaseItems_BaseItemEntityId", - table: "AncestorIds", - column: "BaseItemEntityId", - principalTable: "BaseItems", - principalColumn: "Id"); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112232041_fixMediaStreams.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112232041_fixMediaStreams.Designer.cs deleted file mode 100644 index ccf67d89..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112232041_fixMediaStreams.Designer.cs +++ /dev/null @@ -1,1600 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20241112232041_FixMediaStreams")] - partial class FixMediaStreams - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "8.0.10"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AncestorId", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ParentItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ParentItemId"); - - b.HasIndex("ParentItemId"); - - b.ToTable("AncestorIds"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AttachmentStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Index") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("Filename") - .HasColumnType("TEXT"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "Index"); - - b.ToTable("AttachmentStreamInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Album") - .HasColumnType("TEXT"); - - b.Property("AlbumArtists") - .HasColumnType("TEXT"); - - b.Property("Artists") - .HasColumnType("TEXT"); - - b.Property("Audio") - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("TEXT"); - - b.Property("CleanName") - .HasColumnType("TEXT"); - - b.Property("CommunityRating") - .HasColumnType("REAL"); - - b.Property("CriticRating") - .HasColumnType("REAL"); - - b.Property("CustomRating") - .HasColumnType("TEXT"); - - b.Property("Data") - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastMediaAdded") - .HasColumnType("TEXT"); - - b.Property("DateLastRefreshed") - .HasColumnType("TEXT"); - - b.Property("DateLastSaved") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("EpisodeTitle") - .HasColumnType("TEXT"); - - b.Property("ExternalId") - .HasColumnType("TEXT"); - - b.Property("ExternalSeriesId") - .HasColumnType("TEXT"); - - b.Property("ExternalServiceId") - .HasColumnType("TEXT"); - - b.Property("ExtraIds") - .HasColumnType("TEXT"); - - b.Property("ExtraType") - .HasColumnType("INTEGER"); - - b.Property("ForcedSortName") - .HasColumnType("TEXT"); - - b.Property("Genres") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IndexNumber") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingValue") - .HasColumnType("INTEGER"); - - b.Property("IsFolder") - .HasColumnType("INTEGER"); - - b.Property("IsInMixedFolder") - .HasColumnType("INTEGER"); - - b.Property("IsLocked") - .HasColumnType("INTEGER"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("IsRepeat") - .HasColumnType("INTEGER"); - - b.Property("IsSeries") - .HasColumnType("INTEGER"); - - b.Property("IsVirtualItem") - .HasColumnType("INTEGER"); - - b.Property("LUFS") - .HasColumnType("REAL"); - - b.Property("MediaType") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("NormalizationGain") - .HasColumnType("REAL"); - - b.Property("OfficialRating") - .HasColumnType("TEXT"); - - b.Property("OriginalTitle") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .HasColumnType("TEXT"); - - b.Property("ParentId") - .HasColumnType("TEXT"); - - b.Property("ParentIndexNumber") - .HasColumnType("INTEGER"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataCountryCode") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataLanguage") - .HasColumnType("TEXT"); - - b.Property("PremiereDate") - .HasColumnType("TEXT"); - - b.Property("PresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("PrimaryVersionId") - .HasColumnType("TEXT"); - - b.Property("ProductionLocations") - .HasColumnType("TEXT"); - - b.Property("ProductionYear") - .HasColumnType("INTEGER"); - - b.Property("RunTimeTicks") - .HasColumnType("INTEGER"); - - b.Property("SeasonId") - .HasColumnType("TEXT"); - - b.Property("SeasonName") - .HasColumnType("TEXT"); - - b.Property("SeriesId") - .HasColumnType("TEXT"); - - b.Property("SeriesName") - .HasColumnType("TEXT"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("ShowId") - .HasColumnType("TEXT"); - - b.Property("Size") - .HasColumnType("INTEGER"); - - b.Property("SortName") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Studios") - .HasColumnType("TEXT"); - - b.Property("Tagline") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT"); - - b.Property("TopParentId") - .HasColumnType("TEXT"); - - b.Property("TotalBitrate") - .HasColumnType("INTEGER"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UnratedType") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("Path"); - - b.HasIndex("PresentationUniqueKey"); - - b.HasIndex("TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - - b.HasIndex("Type", "TopParentId", "StartDate"); - - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); - - b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.ToTable("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Blurhash") - .HasColumnType("BLOB"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("ImageType") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemMetadataField", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemMetadataFields"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemProvider", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ProviderId") - .HasColumnType("TEXT"); - - b.Property("ProviderValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ProviderId"); - - b.HasIndex("ProviderId", "ProviderValue", "ItemId"); - - b.ToTable("BaseItemProviders"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemTrailerType", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemTrailerTypes"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Chapter", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ChapterIndex") - .HasColumnType("INTEGER"); - - b.Property("ImageDateModified") - .HasColumnType("TEXT"); - - b.Property("ImagePath") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("StartPositionTicks") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "ChapterIndex"); - - b.ToTable("Chapters"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValue", b => - { - b.Property("ItemValueId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CleanValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId"); - - b.HasIndex("Type", "CleanValue"); - - b.ToTable("ItemValues"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValueMap", b => - { - b.Property("ItemValueId") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("ItemValuesMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StreamIndex") - .HasColumnType("INTEGER"); - - b.Property("AspectRatio") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AverageFrameRate") - .HasColumnType("REAL"); - - b.Property("BitDepth") - .HasColumnType("INTEGER"); - - b.Property("BitRate") - .HasColumnType("INTEGER"); - - b.Property("BlPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("ChannelLayout") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Channels") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("CodecTimeBase") - .HasColumnType("TEXT"); - - b.Property("ColorPrimaries") - .HasColumnType("TEXT"); - - b.Property("ColorSpace") - .HasColumnType("TEXT"); - - b.Property("ColorTransfer") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("DvBlSignalCompatibilityId") - .HasColumnType("INTEGER"); - - b.Property("DvLevel") - .HasColumnType("INTEGER"); - - b.Property("DvProfile") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMajor") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMinor") - .HasColumnType("INTEGER"); - - b.Property("ElPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IsAnamorphic") - .HasColumnType("INTEGER"); - - b.Property("IsAvc") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("IsHearingImpaired") - .HasColumnType("INTEGER"); - - b.Property("IsInterlaced") - .HasColumnType("INTEGER"); - - b.Property("KeyFrames") - .HasColumnType("TEXT"); - - b.Property("Language") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("REAL"); - - b.Property("NalLengthSize") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PixelFormat") - .HasColumnType("TEXT"); - - b.Property("Profile") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("RealFrameRate") - .HasColumnType("REAL"); - - b.Property("RefFrames") - .HasColumnType("INTEGER"); - - b.Property("Rotation") - .HasColumnType("INTEGER"); - - b.Property("RpuPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("SampleRate") - .HasColumnType("INTEGER"); - - b.Property("StreamType") - .HasColumnType("INTEGER"); - - b.Property("TimeBase") - .HasColumnType("TEXT"); - - b.Property("Title") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "StreamIndex"); - - b.HasIndex("StreamIndex"); - - b.HasIndex("StreamType"); - - b.HasIndex("StreamIndex", "StreamType"); - - b.HasIndex("StreamIndex", "StreamType", "Language"); - - b.ToTable("MediaStreamInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.People", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PersonType") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name"); - - b.ToTable("Peoples"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.PeopleBaseItemMap", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("PeopleId") - .HasColumnType("TEXT"); - - b.Property("ListOrder") - .HasColumnType("INTEGER"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "PeopleId"); - - b.HasIndex("PeopleId"); - - b.HasIndex("ItemId", "ListOrder"); - - b.HasIndex("ItemId", "SortOrder"); - - b.ToTable("PeopleBaseItemMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT") - .UseCollation("NOCASE"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.UserData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("CustomDataKey") - .HasColumnType("TEXT"); - - b.Property("AudioStreamIndex") - .HasColumnType("INTEGER"); - - b.Property("IsFavorite") - .HasColumnType("INTEGER"); - - b.Property("LastPlayedDate") - .HasColumnType("TEXT"); - - b.Property("Likes") - .HasColumnType("INTEGER"); - - b.Property("PlayCount") - .HasColumnType("INTEGER"); - - b.Property("PlaybackPositionTicks") - .HasColumnType("INTEGER"); - - b.Property("Played") - .HasColumnType("INTEGER"); - - b.Property("Rating") - .HasColumnType("REAL"); - - b.Property("SubtitleStreamIndex") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "UserId", "CustomDataKey"); - - b.HasIndex("UserId"); - - b.HasIndex("ItemId", "UserId", "IsFavorite"); - - b.HasIndex("ItemId", "UserId", "LastPlayedDate"); - - b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks"); - - b.HasIndex("ItemId", "UserId", "Played"); - - b.ToTable("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AncestorId", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Children") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "ParentItem") - .WithMany("ParentAncestors") - .HasForeignKey("ParentItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ParentItem"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AttachmentStreamInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Images") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemMetadataField", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("LockedFields") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemProvider", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Provider") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemTrailerType", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("TrailerTypes") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Chapter", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Chapters") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValueMap", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("ItemValues") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.ItemValue", "ItemValue") - .WithMany("BaseItemsMap") - .HasForeignKey("ItemValueId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ItemValue"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaStreamInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("MediaStreams") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.PeopleBaseItemMap", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Peoples") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.People", "People") - .WithMany("BaseItems") - .HasForeignKey("PeopleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("People"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.UserData", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("UserData") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemEntity", b => - { - b.Navigation("Chapters"); - - b.Navigation("Children"); - - b.Navigation("Images"); - - b.Navigation("ItemValues"); - - b.Navigation("LockedFields"); - - b.Navigation("MediaStreams"); - - b.Navigation("ParentAncestors"); - - b.Navigation("Peoples"); - - b.Navigation("Provider"); - - b.Navigation("TrailerTypes"); - - b.Navigation("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValue", b => - { - b.Navigation("BaseItemsMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.People", b => - { - b.Navigation("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112232041_fixMediaStreams.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112232041_fixMediaStreams.cs deleted file mode 100644 index 4cfef8b5..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112232041_fixMediaStreams.cs +++ /dev/null @@ -1,706 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class FixMediaStreams : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "Width", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: true, - oldClrType: typeof(int), - oldType: "INTEGER"); - - migrationBuilder.AlterColumn( - name: "Title", - table: "MediaStreamInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "TimeBase", - table: "MediaStreamInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "StreamType", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: false, - defaultValue: 0, - oldClrType: typeof(int), - oldType: "INTEGER", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "SampleRate", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: true, - oldClrType: typeof(int), - oldType: "INTEGER"); - - migrationBuilder.AlterColumn( - name: "RpuPresentFlag", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: true, - oldClrType: typeof(int), - oldType: "INTEGER"); - - migrationBuilder.AlterColumn( - name: "Rotation", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: true, - oldClrType: typeof(int), - oldType: "INTEGER"); - - migrationBuilder.AlterColumn( - name: "RefFrames", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: true, - oldClrType: typeof(int), - oldType: "INTEGER"); - - migrationBuilder.AlterColumn( - name: "RealFrameRate", - table: "MediaStreamInfos", - type: "REAL", - nullable: true, - oldClrType: typeof(float), - oldType: "REAL"); - - migrationBuilder.AlterColumn( - name: "Profile", - table: "MediaStreamInfos", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "Path", - table: "MediaStreamInfos", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "NalLengthSize", - table: "MediaStreamInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "Level", - table: "MediaStreamInfos", - type: "REAL", - nullable: true, - oldClrType: typeof(float), - oldType: "REAL"); - - migrationBuilder.AlterColumn( - name: "Language", - table: "MediaStreamInfos", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "IsHearingImpaired", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: true, - oldClrType: typeof(bool), - oldType: "INTEGER"); - - migrationBuilder.AlterColumn( - name: "IsAvc", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: true, - oldClrType: typeof(bool), - oldType: "INTEGER"); - - migrationBuilder.AlterColumn( - name: "IsAnamorphic", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: true, - oldClrType: typeof(bool), - oldType: "INTEGER"); - - migrationBuilder.AlterColumn( - name: "Height", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: true, - oldClrType: typeof(int), - oldType: "INTEGER"); - - migrationBuilder.AlterColumn( - name: "ElPresentFlag", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: true, - oldClrType: typeof(int), - oldType: "INTEGER"); - - migrationBuilder.AlterColumn( - name: "DvVersionMinor", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: true, - oldClrType: typeof(int), - oldType: "INTEGER"); - - migrationBuilder.AlterColumn( - name: "DvVersionMajor", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: true, - oldClrType: typeof(int), - oldType: "INTEGER"); - - migrationBuilder.AlterColumn( - name: "DvProfile", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: true, - oldClrType: typeof(int), - oldType: "INTEGER"); - - migrationBuilder.AlterColumn( - name: "DvLevel", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: true, - oldClrType: typeof(int), - oldType: "INTEGER"); - - migrationBuilder.AlterColumn( - name: "DvBlSignalCompatibilityId", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: true, - oldClrType: typeof(int), - oldType: "INTEGER"); - - migrationBuilder.AlterColumn( - name: "Comment", - table: "MediaStreamInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "ColorTransfer", - table: "MediaStreamInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "ColorSpace", - table: "MediaStreamInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "ColorPrimaries", - table: "MediaStreamInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "CodecTimeBase", - table: "MediaStreamInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "CodecTag", - table: "MediaStreamInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "Codec", - table: "MediaStreamInfos", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "Channels", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: true, - oldClrType: typeof(int), - oldType: "INTEGER"); - - migrationBuilder.AlterColumn( - name: "ChannelLayout", - table: "MediaStreamInfos", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "BlPresentFlag", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: true, - oldClrType: typeof(int), - oldType: "INTEGER"); - - migrationBuilder.AlterColumn( - name: "BitRate", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: true, - oldClrType: typeof(int), - oldType: "INTEGER"); - - migrationBuilder.AlterColumn( - name: "BitDepth", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: true, - oldClrType: typeof(int), - oldType: "INTEGER"); - - migrationBuilder.AlterColumn( - name: "AverageFrameRate", - table: "MediaStreamInfos", - type: "REAL", - nullable: true, - oldClrType: typeof(float), - oldType: "REAL"); - - migrationBuilder.AlterColumn( - name: "AspectRatio", - table: "MediaStreamInfos", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "Width", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: false, - defaultValue: 0, - oldClrType: typeof(int), - oldType: "INTEGER", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "Title", - table: "MediaStreamInfos", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "TimeBase", - table: "MediaStreamInfos", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "StreamType", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: true, - oldClrType: typeof(int), - oldType: "INTEGER"); - - migrationBuilder.AlterColumn( - name: "SampleRate", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: false, - defaultValue: 0, - oldClrType: typeof(int), - oldType: "INTEGER", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "RpuPresentFlag", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: false, - defaultValue: 0, - oldClrType: typeof(int), - oldType: "INTEGER", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "Rotation", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: false, - defaultValue: 0, - oldClrType: typeof(int), - oldType: "INTEGER", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "RefFrames", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: false, - defaultValue: 0, - oldClrType: typeof(int), - oldType: "INTEGER", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "RealFrameRate", - table: "MediaStreamInfos", - type: "REAL", - nullable: false, - defaultValue: 0f, - oldClrType: typeof(float), - oldType: "REAL", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "Profile", - table: "MediaStreamInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "Path", - table: "MediaStreamInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "NalLengthSize", - table: "MediaStreamInfos", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "Level", - table: "MediaStreamInfos", - type: "REAL", - nullable: false, - defaultValue: 0f, - oldClrType: typeof(float), - oldType: "REAL", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "Language", - table: "MediaStreamInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "IsHearingImpaired", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: false, - defaultValue: false, - oldClrType: typeof(bool), - oldType: "INTEGER", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "IsAvc", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: false, - defaultValue: false, - oldClrType: typeof(bool), - oldType: "INTEGER", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "IsAnamorphic", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: false, - defaultValue: false, - oldClrType: typeof(bool), - oldType: "INTEGER", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "Height", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: false, - defaultValue: 0, - oldClrType: typeof(int), - oldType: "INTEGER", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "ElPresentFlag", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: false, - defaultValue: 0, - oldClrType: typeof(int), - oldType: "INTEGER", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "DvVersionMinor", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: false, - defaultValue: 0, - oldClrType: typeof(int), - oldType: "INTEGER", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "DvVersionMajor", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: false, - defaultValue: 0, - oldClrType: typeof(int), - oldType: "INTEGER", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "DvProfile", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: false, - defaultValue: 0, - oldClrType: typeof(int), - oldType: "INTEGER", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "DvLevel", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: false, - defaultValue: 0, - oldClrType: typeof(int), - oldType: "INTEGER", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "DvBlSignalCompatibilityId", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: false, - defaultValue: 0, - oldClrType: typeof(int), - oldType: "INTEGER", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "Comment", - table: "MediaStreamInfos", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "ColorTransfer", - table: "MediaStreamInfos", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "ColorSpace", - table: "MediaStreamInfos", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "ColorPrimaries", - table: "MediaStreamInfos", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "CodecTimeBase", - table: "MediaStreamInfos", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "CodecTag", - table: "MediaStreamInfos", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "Codec", - table: "MediaStreamInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "Channels", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: false, - defaultValue: 0, - oldClrType: typeof(int), - oldType: "INTEGER", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "ChannelLayout", - table: "MediaStreamInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "BlPresentFlag", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: false, - defaultValue: 0, - oldClrType: typeof(int), - oldType: "INTEGER", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "BitRate", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: false, - defaultValue: 0, - oldClrType: typeof(int), - oldType: "INTEGER", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "BitDepth", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: false, - defaultValue: 0, - oldClrType: typeof(int), - oldType: "INTEGER", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "AverageFrameRate", - table: "MediaStreamInfos", - type: "REAL", - nullable: false, - defaultValue: 0f, - oldClrType: typeof(float), - oldType: "REAL", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "AspectRatio", - table: "MediaStreamInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112234144_FixMediaStreams2.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112234144_FixMediaStreams2.Designer.cs deleted file mode 100644 index d3ba8c96..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112234144_FixMediaStreams2.Designer.cs +++ /dev/null @@ -1,1594 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20241112234144_FixMediaStreams2")] - partial class FixMediaStreams2 - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "8.0.10"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AncestorId", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ParentItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ParentItemId"); - - b.HasIndex("ParentItemId"); - - b.ToTable("AncestorIds"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AttachmentStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Index") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("Filename") - .HasColumnType("TEXT"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "Index"); - - b.ToTable("AttachmentStreamInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Album") - .HasColumnType("TEXT"); - - b.Property("AlbumArtists") - .HasColumnType("TEXT"); - - b.Property("Artists") - .HasColumnType("TEXT"); - - b.Property("Audio") - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("TEXT"); - - b.Property("CleanName") - .HasColumnType("TEXT"); - - b.Property("CommunityRating") - .HasColumnType("REAL"); - - b.Property("CriticRating") - .HasColumnType("REAL"); - - b.Property("CustomRating") - .HasColumnType("TEXT"); - - b.Property("Data") - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastMediaAdded") - .HasColumnType("TEXT"); - - b.Property("DateLastRefreshed") - .HasColumnType("TEXT"); - - b.Property("DateLastSaved") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("EpisodeTitle") - .HasColumnType("TEXT"); - - b.Property("ExternalId") - .HasColumnType("TEXT"); - - b.Property("ExternalSeriesId") - .HasColumnType("TEXT"); - - b.Property("ExternalServiceId") - .HasColumnType("TEXT"); - - b.Property("ExtraIds") - .HasColumnType("TEXT"); - - b.Property("ExtraType") - .HasColumnType("INTEGER"); - - b.Property("ForcedSortName") - .HasColumnType("TEXT"); - - b.Property("Genres") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IndexNumber") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingValue") - .HasColumnType("INTEGER"); - - b.Property("IsFolder") - .HasColumnType("INTEGER"); - - b.Property("IsInMixedFolder") - .HasColumnType("INTEGER"); - - b.Property("IsLocked") - .HasColumnType("INTEGER"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("IsRepeat") - .HasColumnType("INTEGER"); - - b.Property("IsSeries") - .HasColumnType("INTEGER"); - - b.Property("IsVirtualItem") - .HasColumnType("INTEGER"); - - b.Property("LUFS") - .HasColumnType("REAL"); - - b.Property("MediaType") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("NormalizationGain") - .HasColumnType("REAL"); - - b.Property("OfficialRating") - .HasColumnType("TEXT"); - - b.Property("OriginalTitle") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .HasColumnType("TEXT"); - - b.Property("ParentId") - .HasColumnType("TEXT"); - - b.Property("ParentIndexNumber") - .HasColumnType("INTEGER"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataCountryCode") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataLanguage") - .HasColumnType("TEXT"); - - b.Property("PremiereDate") - .HasColumnType("TEXT"); - - b.Property("PresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("PrimaryVersionId") - .HasColumnType("TEXT"); - - b.Property("ProductionLocations") - .HasColumnType("TEXT"); - - b.Property("ProductionYear") - .HasColumnType("INTEGER"); - - b.Property("RunTimeTicks") - .HasColumnType("INTEGER"); - - b.Property("SeasonId") - .HasColumnType("TEXT"); - - b.Property("SeasonName") - .HasColumnType("TEXT"); - - b.Property("SeriesId") - .HasColumnType("TEXT"); - - b.Property("SeriesName") - .HasColumnType("TEXT"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("ShowId") - .HasColumnType("TEXT"); - - b.Property("Size") - .HasColumnType("INTEGER"); - - b.Property("SortName") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Studios") - .HasColumnType("TEXT"); - - b.Property("Tagline") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT"); - - b.Property("TopParentId") - .HasColumnType("TEXT"); - - b.Property("TotalBitrate") - .HasColumnType("INTEGER"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UnratedType") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("Path"); - - b.HasIndex("PresentationUniqueKey"); - - b.HasIndex("TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - - b.HasIndex("Type", "TopParentId", "StartDate"); - - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); - - b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.ToTable("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Blurhash") - .HasColumnType("BLOB"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("ImageType") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemMetadataField", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemMetadataFields"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemProvider", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ProviderId") - .HasColumnType("TEXT"); - - b.Property("ProviderValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ProviderId"); - - b.HasIndex("ProviderId", "ProviderValue", "ItemId"); - - b.ToTable("BaseItemProviders"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemTrailerType", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemTrailerTypes"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Chapter", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ChapterIndex") - .HasColumnType("INTEGER"); - - b.Property("ImageDateModified") - .HasColumnType("TEXT"); - - b.Property("ImagePath") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("StartPositionTicks") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "ChapterIndex"); - - b.ToTable("Chapters"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValue", b => - { - b.Property("ItemValueId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CleanValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId"); - - b.HasIndex("Type", "CleanValue"); - - b.ToTable("ItemValues"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValueMap", b => - { - b.Property("ItemValueId") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("ItemValuesMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StreamIndex") - .HasColumnType("INTEGER"); - - b.Property("AspectRatio") - .HasColumnType("TEXT"); - - b.Property("AverageFrameRate") - .HasColumnType("REAL"); - - b.Property("BitDepth") - .HasColumnType("INTEGER"); - - b.Property("BitRate") - .HasColumnType("INTEGER"); - - b.Property("BlPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("ChannelLayout") - .HasColumnType("TEXT"); - - b.Property("Channels") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("CodecTimeBase") - .HasColumnType("TEXT"); - - b.Property("ColorPrimaries") - .HasColumnType("TEXT"); - - b.Property("ColorSpace") - .HasColumnType("TEXT"); - - b.Property("ColorTransfer") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("DvBlSignalCompatibilityId") - .HasColumnType("INTEGER"); - - b.Property("DvLevel") - .HasColumnType("INTEGER"); - - b.Property("DvProfile") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMajor") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMinor") - .HasColumnType("INTEGER"); - - b.Property("ElPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IsAnamorphic") - .HasColumnType("INTEGER"); - - b.Property("IsAvc") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("IsHearingImpaired") - .HasColumnType("INTEGER"); - - b.Property("IsInterlaced") - .HasColumnType("INTEGER"); - - b.Property("KeyFrames") - .HasColumnType("TEXT"); - - b.Property("Language") - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("REAL"); - - b.Property("NalLengthSize") - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PixelFormat") - .HasColumnType("TEXT"); - - b.Property("Profile") - .HasColumnType("TEXT"); - - b.Property("RealFrameRate") - .HasColumnType("REAL"); - - b.Property("RefFrames") - .HasColumnType("INTEGER"); - - b.Property("Rotation") - .HasColumnType("INTEGER"); - - b.Property("RpuPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("SampleRate") - .HasColumnType("INTEGER"); - - b.Property("StreamType") - .HasColumnType("INTEGER"); - - b.Property("TimeBase") - .HasColumnType("TEXT"); - - b.Property("Title") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "StreamIndex"); - - b.HasIndex("StreamIndex"); - - b.HasIndex("StreamType"); - - b.HasIndex("StreamIndex", "StreamType"); - - b.HasIndex("StreamIndex", "StreamType", "Language"); - - b.ToTable("MediaStreamInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.People", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PersonType") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name"); - - b.ToTable("Peoples"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.PeopleBaseItemMap", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("PeopleId") - .HasColumnType("TEXT"); - - b.Property("ListOrder") - .HasColumnType("INTEGER"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "PeopleId"); - - b.HasIndex("PeopleId"); - - b.HasIndex("ItemId", "ListOrder"); - - b.HasIndex("ItemId", "SortOrder"); - - b.ToTable("PeopleBaseItemMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT") - .UseCollation("NOCASE"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.UserData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("CustomDataKey") - .HasColumnType("TEXT"); - - b.Property("AudioStreamIndex") - .HasColumnType("INTEGER"); - - b.Property("IsFavorite") - .HasColumnType("INTEGER"); - - b.Property("LastPlayedDate") - .HasColumnType("TEXT"); - - b.Property("Likes") - .HasColumnType("INTEGER"); - - b.Property("PlayCount") - .HasColumnType("INTEGER"); - - b.Property("PlaybackPositionTicks") - .HasColumnType("INTEGER"); - - b.Property("Played") - .HasColumnType("INTEGER"); - - b.Property("Rating") - .HasColumnType("REAL"); - - b.Property("SubtitleStreamIndex") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "UserId", "CustomDataKey"); - - b.HasIndex("UserId"); - - b.HasIndex("ItemId", "UserId", "IsFavorite"); - - b.HasIndex("ItemId", "UserId", "LastPlayedDate"); - - b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks"); - - b.HasIndex("ItemId", "UserId", "Played"); - - b.ToTable("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AncestorId", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Children") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "ParentItem") - .WithMany("ParentAncestors") - .HasForeignKey("ParentItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ParentItem"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AttachmentStreamInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Images") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemMetadataField", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("LockedFields") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemProvider", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Provider") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemTrailerType", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("TrailerTypes") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Chapter", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Chapters") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValueMap", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("ItemValues") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.ItemValue", "ItemValue") - .WithMany("BaseItemsMap") - .HasForeignKey("ItemValueId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ItemValue"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaStreamInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("MediaStreams") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.PeopleBaseItemMap", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Peoples") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.People", "People") - .WithMany("BaseItems") - .HasForeignKey("PeopleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("People"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.UserData", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("UserData") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemEntity", b => - { - b.Navigation("Chapters"); - - b.Navigation("Children"); - - b.Navigation("Images"); - - b.Navigation("ItemValues"); - - b.Navigation("LockedFields"); - - b.Navigation("MediaStreams"); - - b.Navigation("ParentAncestors"); - - b.Navigation("Peoples"); - - b.Navigation("Provider"); - - b.Navigation("TrailerTypes"); - - b.Navigation("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValue", b => - { - b.Navigation("BaseItemsMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.People", b => - { - b.Navigation("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112234144_FixMediaStreams2.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112234144_FixMediaStreams2.cs deleted file mode 100644 index 1e022fe5..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241112234144_FixMediaStreams2.cs +++ /dev/null @@ -1,148 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class FixMediaStreams2 : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "Profile", - table: "MediaStreamInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "Path", - table: "MediaStreamInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "Language", - table: "MediaStreamInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "IsInterlaced", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: true, - oldClrType: typeof(bool), - oldType: "INTEGER"); - - migrationBuilder.AlterColumn( - name: "Codec", - table: "MediaStreamInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "ChannelLayout", - table: "MediaStreamInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "AspectRatio", - table: "MediaStreamInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "Profile", - table: "MediaStreamInfos", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "Path", - table: "MediaStreamInfos", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "Language", - table: "MediaStreamInfos", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "IsInterlaced", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: false, - defaultValue: false, - oldClrType: typeof(bool), - oldType: "INTEGER", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "Codec", - table: "MediaStreamInfos", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "ChannelLayout", - table: "MediaStreamInfos", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "AspectRatio", - table: "MediaStreamInfos", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241113133548_EnforceUniqueItemValue.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241113133548_EnforceUniqueItemValue.Designer.cs deleted file mode 100644 index 2c0058c7..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241113133548_EnforceUniqueItemValue.Designer.cs +++ /dev/null @@ -1,1595 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20241113133548_EnforceUniqueItemValue")] - partial class EnforceUniqueItemValue - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "8.0.10"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AncestorId", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ParentItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ParentItemId"); - - b.HasIndex("ParentItemId"); - - b.ToTable("AncestorIds"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AttachmentStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Index") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("Filename") - .HasColumnType("TEXT"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "Index"); - - b.ToTable("AttachmentStreamInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Album") - .HasColumnType("TEXT"); - - b.Property("AlbumArtists") - .HasColumnType("TEXT"); - - b.Property("Artists") - .HasColumnType("TEXT"); - - b.Property("Audio") - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("TEXT"); - - b.Property("CleanName") - .HasColumnType("TEXT"); - - b.Property("CommunityRating") - .HasColumnType("REAL"); - - b.Property("CriticRating") - .HasColumnType("REAL"); - - b.Property("CustomRating") - .HasColumnType("TEXT"); - - b.Property("Data") - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastMediaAdded") - .HasColumnType("TEXT"); - - b.Property("DateLastRefreshed") - .HasColumnType("TEXT"); - - b.Property("DateLastSaved") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("EpisodeTitle") - .HasColumnType("TEXT"); - - b.Property("ExternalId") - .HasColumnType("TEXT"); - - b.Property("ExternalSeriesId") - .HasColumnType("TEXT"); - - b.Property("ExternalServiceId") - .HasColumnType("TEXT"); - - b.Property("ExtraIds") - .HasColumnType("TEXT"); - - b.Property("ExtraType") - .HasColumnType("INTEGER"); - - b.Property("ForcedSortName") - .HasColumnType("TEXT"); - - b.Property("Genres") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IndexNumber") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingValue") - .HasColumnType("INTEGER"); - - b.Property("IsFolder") - .HasColumnType("INTEGER"); - - b.Property("IsInMixedFolder") - .HasColumnType("INTEGER"); - - b.Property("IsLocked") - .HasColumnType("INTEGER"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("IsRepeat") - .HasColumnType("INTEGER"); - - b.Property("IsSeries") - .HasColumnType("INTEGER"); - - b.Property("IsVirtualItem") - .HasColumnType("INTEGER"); - - b.Property("LUFS") - .HasColumnType("REAL"); - - b.Property("MediaType") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("NormalizationGain") - .HasColumnType("REAL"); - - b.Property("OfficialRating") - .HasColumnType("TEXT"); - - b.Property("OriginalTitle") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .HasColumnType("TEXT"); - - b.Property("ParentId") - .HasColumnType("TEXT"); - - b.Property("ParentIndexNumber") - .HasColumnType("INTEGER"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataCountryCode") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataLanguage") - .HasColumnType("TEXT"); - - b.Property("PremiereDate") - .HasColumnType("TEXT"); - - b.Property("PresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("PrimaryVersionId") - .HasColumnType("TEXT"); - - b.Property("ProductionLocations") - .HasColumnType("TEXT"); - - b.Property("ProductionYear") - .HasColumnType("INTEGER"); - - b.Property("RunTimeTicks") - .HasColumnType("INTEGER"); - - b.Property("SeasonId") - .HasColumnType("TEXT"); - - b.Property("SeasonName") - .HasColumnType("TEXT"); - - b.Property("SeriesId") - .HasColumnType("TEXT"); - - b.Property("SeriesName") - .HasColumnType("TEXT"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("ShowId") - .HasColumnType("TEXT"); - - b.Property("Size") - .HasColumnType("INTEGER"); - - b.Property("SortName") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Studios") - .HasColumnType("TEXT"); - - b.Property("Tagline") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT"); - - b.Property("TopParentId") - .HasColumnType("TEXT"); - - b.Property("TotalBitrate") - .HasColumnType("INTEGER"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UnratedType") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("Path"); - - b.HasIndex("PresentationUniqueKey"); - - b.HasIndex("TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - - b.HasIndex("Type", "TopParentId", "StartDate"); - - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); - - b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.ToTable("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Blurhash") - .HasColumnType("BLOB"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("ImageType") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemMetadataField", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemMetadataFields"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemProvider", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ProviderId") - .HasColumnType("TEXT"); - - b.Property("ProviderValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ProviderId"); - - b.HasIndex("ProviderId", "ProviderValue", "ItemId"); - - b.ToTable("BaseItemProviders"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemTrailerType", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemTrailerTypes"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Chapter", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ChapterIndex") - .HasColumnType("INTEGER"); - - b.Property("ImageDateModified") - .HasColumnType("TEXT"); - - b.Property("ImagePath") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("StartPositionTicks") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "ChapterIndex"); - - b.ToTable("Chapters"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValue", b => - { - b.Property("ItemValueId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CleanValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId"); - - b.HasIndex("Type", "CleanValue") - .IsUnique(); - - b.ToTable("ItemValues"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValueMap", b => - { - b.Property("ItemValueId") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("ItemValuesMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StreamIndex") - .HasColumnType("INTEGER"); - - b.Property("AspectRatio") - .HasColumnType("TEXT"); - - b.Property("AverageFrameRate") - .HasColumnType("REAL"); - - b.Property("BitDepth") - .HasColumnType("INTEGER"); - - b.Property("BitRate") - .HasColumnType("INTEGER"); - - b.Property("BlPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("ChannelLayout") - .HasColumnType("TEXT"); - - b.Property("Channels") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("CodecTimeBase") - .HasColumnType("TEXT"); - - b.Property("ColorPrimaries") - .HasColumnType("TEXT"); - - b.Property("ColorSpace") - .HasColumnType("TEXT"); - - b.Property("ColorTransfer") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("DvBlSignalCompatibilityId") - .HasColumnType("INTEGER"); - - b.Property("DvLevel") - .HasColumnType("INTEGER"); - - b.Property("DvProfile") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMajor") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMinor") - .HasColumnType("INTEGER"); - - b.Property("ElPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IsAnamorphic") - .HasColumnType("INTEGER"); - - b.Property("IsAvc") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("IsHearingImpaired") - .HasColumnType("INTEGER"); - - b.Property("IsInterlaced") - .HasColumnType("INTEGER"); - - b.Property("KeyFrames") - .HasColumnType("TEXT"); - - b.Property("Language") - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("REAL"); - - b.Property("NalLengthSize") - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PixelFormat") - .HasColumnType("TEXT"); - - b.Property("Profile") - .HasColumnType("TEXT"); - - b.Property("RealFrameRate") - .HasColumnType("REAL"); - - b.Property("RefFrames") - .HasColumnType("INTEGER"); - - b.Property("Rotation") - .HasColumnType("INTEGER"); - - b.Property("RpuPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("SampleRate") - .HasColumnType("INTEGER"); - - b.Property("StreamType") - .HasColumnType("INTEGER"); - - b.Property("TimeBase") - .HasColumnType("TEXT"); - - b.Property("Title") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "StreamIndex"); - - b.HasIndex("StreamIndex"); - - b.HasIndex("StreamType"); - - b.HasIndex("StreamIndex", "StreamType"); - - b.HasIndex("StreamIndex", "StreamType", "Language"); - - b.ToTable("MediaStreamInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.People", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PersonType") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name"); - - b.ToTable("Peoples"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.PeopleBaseItemMap", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("PeopleId") - .HasColumnType("TEXT"); - - b.Property("ListOrder") - .HasColumnType("INTEGER"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "PeopleId"); - - b.HasIndex("PeopleId"); - - b.HasIndex("ItemId", "ListOrder"); - - b.HasIndex("ItemId", "SortOrder"); - - b.ToTable("PeopleBaseItemMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT") - .UseCollation("NOCASE"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.UserData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("CustomDataKey") - .HasColumnType("TEXT"); - - b.Property("AudioStreamIndex") - .HasColumnType("INTEGER"); - - b.Property("IsFavorite") - .HasColumnType("INTEGER"); - - b.Property("LastPlayedDate") - .HasColumnType("TEXT"); - - b.Property("Likes") - .HasColumnType("INTEGER"); - - b.Property("PlayCount") - .HasColumnType("INTEGER"); - - b.Property("PlaybackPositionTicks") - .HasColumnType("INTEGER"); - - b.Property("Played") - .HasColumnType("INTEGER"); - - b.Property("Rating") - .HasColumnType("REAL"); - - b.Property("SubtitleStreamIndex") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "UserId", "CustomDataKey"); - - b.HasIndex("UserId"); - - b.HasIndex("ItemId", "UserId", "IsFavorite"); - - b.HasIndex("ItemId", "UserId", "LastPlayedDate"); - - b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks"); - - b.HasIndex("ItemId", "UserId", "Played"); - - b.ToTable("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AncestorId", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Children") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "ParentItem") - .WithMany("ParentAncestors") - .HasForeignKey("ParentItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ParentItem"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AttachmentStreamInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Images") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemMetadataField", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("LockedFields") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemProvider", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Provider") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemTrailerType", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("TrailerTypes") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Chapter", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Chapters") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValueMap", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("ItemValues") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.ItemValue", "ItemValue") - .WithMany("BaseItemsMap") - .HasForeignKey("ItemValueId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ItemValue"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaStreamInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("MediaStreams") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.PeopleBaseItemMap", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Peoples") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.People", "People") - .WithMany("BaseItems") - .HasForeignKey("PeopleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("People"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.UserData", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("UserData") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemEntity", b => - { - b.Navigation("Chapters"); - - b.Navigation("Children"); - - b.Navigation("Images"); - - b.Navigation("ItemValues"); - - b.Navigation("LockedFields"); - - b.Navigation("MediaStreams"); - - b.Navigation("ParentAncestors"); - - b.Navigation("Peoples"); - - b.Navigation("Provider"); - - b.Navigation("TrailerTypes"); - - b.Navigation("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValue", b => - { - b.Navigation("BaseItemsMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.People", b => - { - b.Navigation("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241113133548_EnforceUniqueItemValue.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241113133548_EnforceUniqueItemValue.cs deleted file mode 100644 index e1b68518..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20241113133548_EnforceUniqueItemValue.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class EnforceUniqueItemValue : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_ItemValues_Type_CleanValue", - table: "ItemValues"); - - migrationBuilder.CreateIndex( - name: "IX_ItemValues_Type_CleanValue", - table: "ItemValues", - columns: new[] { "Type", "CleanValue" }, - unique: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_ItemValues_Type_CleanValue", - table: "ItemValues"); - - migrationBuilder.CreateIndex( - name: "IX_ItemValues_Type_CleanValue", - table: "ItemValues", - columns: new[] { "Type", "CleanValue" }); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250202021306_FixedCollation.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250202021306_FixedCollation.Designer.cs deleted file mode 100644 index da4bab3f..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250202021306_FixedCollation.Designer.cs +++ /dev/null @@ -1,1594 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20250202021306_FixedCollation")] - partial class FixedCollation - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.1"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AncestorId", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ParentItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ParentItemId"); - - b.HasIndex("ParentItemId"); - - b.ToTable("AncestorIds"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AttachmentStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Index") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("Filename") - .HasColumnType("TEXT"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "Index"); - - b.ToTable("AttachmentStreamInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Album") - .HasColumnType("TEXT"); - - b.Property("AlbumArtists") - .HasColumnType("TEXT"); - - b.Property("Artists") - .HasColumnType("TEXT"); - - b.Property("Audio") - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("TEXT"); - - b.Property("CleanName") - .HasColumnType("TEXT"); - - b.Property("CommunityRating") - .HasColumnType("REAL"); - - b.Property("CriticRating") - .HasColumnType("REAL"); - - b.Property("CustomRating") - .HasColumnType("TEXT"); - - b.Property("Data") - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastMediaAdded") - .HasColumnType("TEXT"); - - b.Property("DateLastRefreshed") - .HasColumnType("TEXT"); - - b.Property("DateLastSaved") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("EpisodeTitle") - .HasColumnType("TEXT"); - - b.Property("ExternalId") - .HasColumnType("TEXT"); - - b.Property("ExternalSeriesId") - .HasColumnType("TEXT"); - - b.Property("ExternalServiceId") - .HasColumnType("TEXT"); - - b.Property("ExtraIds") - .HasColumnType("TEXT"); - - b.Property("ExtraType") - .HasColumnType("INTEGER"); - - b.Property("ForcedSortName") - .HasColumnType("TEXT"); - - b.Property("Genres") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IndexNumber") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingValue") - .HasColumnType("INTEGER"); - - b.Property("IsFolder") - .HasColumnType("INTEGER"); - - b.Property("IsInMixedFolder") - .HasColumnType("INTEGER"); - - b.Property("IsLocked") - .HasColumnType("INTEGER"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("IsRepeat") - .HasColumnType("INTEGER"); - - b.Property("IsSeries") - .HasColumnType("INTEGER"); - - b.Property("IsVirtualItem") - .HasColumnType("INTEGER"); - - b.Property("LUFS") - .HasColumnType("REAL"); - - b.Property("MediaType") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("NormalizationGain") - .HasColumnType("REAL"); - - b.Property("OfficialRating") - .HasColumnType("TEXT"); - - b.Property("OriginalTitle") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .HasColumnType("TEXT"); - - b.Property("ParentId") - .HasColumnType("TEXT"); - - b.Property("ParentIndexNumber") - .HasColumnType("INTEGER"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataCountryCode") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataLanguage") - .HasColumnType("TEXT"); - - b.Property("PremiereDate") - .HasColumnType("TEXT"); - - b.Property("PresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("PrimaryVersionId") - .HasColumnType("TEXT"); - - b.Property("ProductionLocations") - .HasColumnType("TEXT"); - - b.Property("ProductionYear") - .HasColumnType("INTEGER"); - - b.Property("RunTimeTicks") - .HasColumnType("INTEGER"); - - b.Property("SeasonId") - .HasColumnType("TEXT"); - - b.Property("SeasonName") - .HasColumnType("TEXT"); - - b.Property("SeriesId") - .HasColumnType("TEXT"); - - b.Property("SeriesName") - .HasColumnType("TEXT"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("ShowId") - .HasColumnType("TEXT"); - - b.Property("Size") - .HasColumnType("INTEGER"); - - b.Property("SortName") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Studios") - .HasColumnType("TEXT"); - - b.Property("Tagline") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT"); - - b.Property("TopParentId") - .HasColumnType("TEXT"); - - b.Property("TotalBitrate") - .HasColumnType("INTEGER"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UnratedType") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("Path"); - - b.HasIndex("PresentationUniqueKey"); - - b.HasIndex("TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - - b.HasIndex("Type", "TopParentId", "StartDate"); - - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); - - b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.ToTable("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Blurhash") - .HasColumnType("BLOB"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("ImageType") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemMetadataField", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemMetadataFields"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemProvider", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ProviderId") - .HasColumnType("TEXT"); - - b.Property("ProviderValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ProviderId"); - - b.HasIndex("ProviderId", "ProviderValue", "ItemId"); - - b.ToTable("BaseItemProviders"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemTrailerType", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemTrailerTypes"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Chapter", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ChapterIndex") - .HasColumnType("INTEGER"); - - b.Property("ImageDateModified") - .HasColumnType("TEXT"); - - b.Property("ImagePath") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("StartPositionTicks") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "ChapterIndex"); - - b.ToTable("Chapters"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValue", b => - { - b.Property("ItemValueId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CleanValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId"); - - b.HasIndex("Type", "CleanValue") - .IsUnique(); - - b.ToTable("ItemValues"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValueMap", b => - { - b.Property("ItemValueId") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("ItemValuesMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StreamIndex") - .HasColumnType("INTEGER"); - - b.Property("AspectRatio") - .HasColumnType("TEXT"); - - b.Property("AverageFrameRate") - .HasColumnType("REAL"); - - b.Property("BitDepth") - .HasColumnType("INTEGER"); - - b.Property("BitRate") - .HasColumnType("INTEGER"); - - b.Property("BlPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("ChannelLayout") - .HasColumnType("TEXT"); - - b.Property("Channels") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("CodecTimeBase") - .HasColumnType("TEXT"); - - b.Property("ColorPrimaries") - .HasColumnType("TEXT"); - - b.Property("ColorSpace") - .HasColumnType("TEXT"); - - b.Property("ColorTransfer") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("DvBlSignalCompatibilityId") - .HasColumnType("INTEGER"); - - b.Property("DvLevel") - .HasColumnType("INTEGER"); - - b.Property("DvProfile") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMajor") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMinor") - .HasColumnType("INTEGER"); - - b.Property("ElPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IsAnamorphic") - .HasColumnType("INTEGER"); - - b.Property("IsAvc") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("IsHearingImpaired") - .HasColumnType("INTEGER"); - - b.Property("IsInterlaced") - .HasColumnType("INTEGER"); - - b.Property("KeyFrames") - .HasColumnType("TEXT"); - - b.Property("Language") - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("REAL"); - - b.Property("NalLengthSize") - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PixelFormat") - .HasColumnType("TEXT"); - - b.Property("Profile") - .HasColumnType("TEXT"); - - b.Property("RealFrameRate") - .HasColumnType("REAL"); - - b.Property("RefFrames") - .HasColumnType("INTEGER"); - - b.Property("Rotation") - .HasColumnType("INTEGER"); - - b.Property("RpuPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("SampleRate") - .HasColumnType("INTEGER"); - - b.Property("StreamType") - .HasColumnType("INTEGER"); - - b.Property("TimeBase") - .HasColumnType("TEXT"); - - b.Property("Title") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "StreamIndex"); - - b.HasIndex("StreamIndex"); - - b.HasIndex("StreamType"); - - b.HasIndex("StreamIndex", "StreamType"); - - b.HasIndex("StreamIndex", "StreamType", "Language"); - - b.ToTable("MediaStreamInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.People", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PersonType") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name"); - - b.ToTable("Peoples"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.PeopleBaseItemMap", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("PeopleId") - .HasColumnType("TEXT"); - - b.Property("ListOrder") - .HasColumnType("INTEGER"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "PeopleId"); - - b.HasIndex("PeopleId"); - - b.HasIndex("ItemId", "ListOrder"); - - b.HasIndex("ItemId", "SortOrder"); - - b.ToTable("PeopleBaseItemMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.UserData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("CustomDataKey") - .HasColumnType("TEXT"); - - b.Property("AudioStreamIndex") - .HasColumnType("INTEGER"); - - b.Property("IsFavorite") - .HasColumnType("INTEGER"); - - b.Property("LastPlayedDate") - .HasColumnType("TEXT"); - - b.Property("Likes") - .HasColumnType("INTEGER"); - - b.Property("PlayCount") - .HasColumnType("INTEGER"); - - b.Property("PlaybackPositionTicks") - .HasColumnType("INTEGER"); - - b.Property("Played") - .HasColumnType("INTEGER"); - - b.Property("Rating") - .HasColumnType("REAL"); - - b.Property("SubtitleStreamIndex") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "UserId", "CustomDataKey"); - - b.HasIndex("UserId"); - - b.HasIndex("ItemId", "UserId", "IsFavorite"); - - b.HasIndex("ItemId", "UserId", "LastPlayedDate"); - - b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks"); - - b.HasIndex("ItemId", "UserId", "Played"); - - b.ToTable("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AncestorId", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Children") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "ParentItem") - .WithMany("ParentAncestors") - .HasForeignKey("ParentItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ParentItem"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AttachmentStreamInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Images") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemMetadataField", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("LockedFields") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemProvider", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Provider") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemTrailerType", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("TrailerTypes") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Chapter", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Chapters") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValueMap", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("ItemValues") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.ItemValue", "ItemValue") - .WithMany("BaseItemsMap") - .HasForeignKey("ItemValueId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ItemValue"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaStreamInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("MediaStreams") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.PeopleBaseItemMap", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Peoples") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.People", "People") - .WithMany("BaseItems") - .HasForeignKey("PeopleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("People"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.UserData", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("UserData") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemEntity", b => - { - b.Navigation("Chapters"); - - b.Navigation("Children"); - - b.Navigation("Images"); - - b.Navigation("ItemValues"); - - b.Navigation("LockedFields"); - - b.Navigation("MediaStreams"); - - b.Navigation("ParentAncestors"); - - b.Navigation("Peoples"); - - b.Navigation("Provider"); - - b.Navigation("TrailerTypes"); - - b.Navigation("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValue", b => - { - b.Navigation("BaseItemsMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.People", b => - { - b.Navigation("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250202021306_FixedCollation.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250202021306_FixedCollation.cs deleted file mode 100644 index 6bff0926..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250202021306_FixedCollation.cs +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class FixedCollation : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "Username", - table: "Users", - type: "TEXT", - maxLength: 255, - nullable: false, - oldClrType: typeof(string), - oldType: "TEXT", - oldMaxLength: 255, - oldCollation: "NOCASE"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "Username", - table: "Users", - type: "TEXT", - maxLength: 255, - nullable: false, - collation: "NOCASE", - oldClrType: typeof(string), - oldType: "TEXT", - oldMaxLength: 255); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250204092455_MakeStartEndDateNullable.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250204092455_MakeStartEndDateNullable.Designer.cs deleted file mode 100644 index 9b72d968..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250204092455_MakeStartEndDateNullable.Designer.cs +++ /dev/null @@ -1,1595 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20250204092455_MakeStartEndDateNullable")] - partial class MakeStartEndDateNullable - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.1"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AncestorId", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ParentItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ParentItemId"); - - b.HasIndex("ParentItemId"); - - b.ToTable("AncestorIds"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AttachmentStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Index") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("Filename") - .HasColumnType("TEXT"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "Index"); - - b.ToTable("AttachmentStreamInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Album") - .HasColumnType("TEXT"); - - b.Property("AlbumArtists") - .HasColumnType("TEXT"); - - b.Property("Artists") - .HasColumnType("TEXT"); - - b.Property("Audio") - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("TEXT"); - - b.Property("CleanName") - .HasColumnType("TEXT"); - - b.Property("CommunityRating") - .HasColumnType("REAL"); - - b.Property("CriticRating") - .HasColumnType("REAL"); - - b.Property("CustomRating") - .HasColumnType("TEXT"); - - b.Property("Data") - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastMediaAdded") - .HasColumnType("TEXT"); - - b.Property("DateLastRefreshed") - .HasColumnType("TEXT"); - - b.Property("DateLastSaved") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("EpisodeTitle") - .HasColumnType("TEXT"); - - b.Property("ExternalId") - .HasColumnType("TEXT"); - - b.Property("ExternalSeriesId") - .HasColumnType("TEXT"); - - b.Property("ExternalServiceId") - .HasColumnType("TEXT"); - - b.Property("ExtraIds") - .HasColumnType("TEXT"); - - b.Property("ExtraType") - .HasColumnType("INTEGER"); - - b.Property("ForcedSortName") - .HasColumnType("TEXT"); - - b.Property("Genres") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IndexNumber") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingValue") - .HasColumnType("INTEGER"); - - b.Property("IsFolder") - .HasColumnType("INTEGER"); - - b.Property("IsInMixedFolder") - .HasColumnType("INTEGER"); - - b.Property("IsLocked") - .HasColumnType("INTEGER"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("IsRepeat") - .HasColumnType("INTEGER"); - - b.Property("IsSeries") - .HasColumnType("INTEGER"); - - b.Property("IsVirtualItem") - .HasColumnType("INTEGER"); - - b.Property("LUFS") - .HasColumnType("REAL"); - - b.Property("MediaType") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("NormalizationGain") - .HasColumnType("REAL"); - - b.Property("OfficialRating") - .HasColumnType("TEXT"); - - b.Property("OriginalTitle") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .HasColumnType("TEXT"); - - b.Property("ParentId") - .HasColumnType("TEXT"); - - b.Property("ParentIndexNumber") - .HasColumnType("INTEGER"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataCountryCode") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataLanguage") - .HasColumnType("TEXT"); - - b.Property("PremiereDate") - .HasColumnType("TEXT"); - - b.Property("PresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("PrimaryVersionId") - .HasColumnType("TEXT"); - - b.Property("ProductionLocations") - .HasColumnType("TEXT"); - - b.Property("ProductionYear") - .HasColumnType("INTEGER"); - - b.Property("RunTimeTicks") - .HasColumnType("INTEGER"); - - b.Property("SeasonId") - .HasColumnType("TEXT"); - - b.Property("SeasonName") - .HasColumnType("TEXT"); - - b.Property("SeriesId") - .HasColumnType("TEXT"); - - b.Property("SeriesName") - .HasColumnType("TEXT"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("ShowId") - .HasColumnType("TEXT"); - - b.Property("Size") - .HasColumnType("INTEGER"); - - b.Property("SortName") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Studios") - .HasColumnType("TEXT"); - - b.Property("Tagline") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT"); - - b.Property("TopParentId") - .HasColumnType("TEXT"); - - b.Property("TotalBitrate") - .HasColumnType("INTEGER"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UnratedType") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("Path"); - - b.HasIndex("PresentationUniqueKey"); - - b.HasIndex("TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - - b.HasIndex("Type", "TopParentId", "StartDate"); - - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); - - b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.ToTable("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Blurhash") - .HasColumnType("BLOB"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("ImageType") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemMetadataField", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemMetadataFields"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemProvider", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ProviderId") - .HasColumnType("TEXT"); - - b.Property("ProviderValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ProviderId"); - - b.HasIndex("ProviderId", "ProviderValue", "ItemId"); - - b.ToTable("BaseItemProviders"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemTrailerType", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemTrailerTypes"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Chapter", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ChapterIndex") - .HasColumnType("INTEGER"); - - b.Property("ImageDateModified") - .HasColumnType("TEXT"); - - b.Property("ImagePath") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("StartPositionTicks") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "ChapterIndex"); - - b.ToTable("Chapters"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValue", b => - { - b.Property("ItemValueId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CleanValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId"); - - b.HasIndex("Type", "CleanValue") - .IsUnique(); - - b.ToTable("ItemValues"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValueMap", b => - { - b.Property("ItemValueId") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("ItemValuesMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StreamIndex") - .HasColumnType("INTEGER"); - - b.Property("AspectRatio") - .HasColumnType("TEXT"); - - b.Property("AverageFrameRate") - .HasColumnType("REAL"); - - b.Property("BitDepth") - .HasColumnType("INTEGER"); - - b.Property("BitRate") - .HasColumnType("INTEGER"); - - b.Property("BlPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("ChannelLayout") - .HasColumnType("TEXT"); - - b.Property("Channels") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("CodecTimeBase") - .HasColumnType("TEXT"); - - b.Property("ColorPrimaries") - .HasColumnType("TEXT"); - - b.Property("ColorSpace") - .HasColumnType("TEXT"); - - b.Property("ColorTransfer") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("DvBlSignalCompatibilityId") - .HasColumnType("INTEGER"); - - b.Property("DvLevel") - .HasColumnType("INTEGER"); - - b.Property("DvProfile") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMajor") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMinor") - .HasColumnType("INTEGER"); - - b.Property("ElPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IsAnamorphic") - .HasColumnType("INTEGER"); - - b.Property("IsAvc") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("IsHearingImpaired") - .HasColumnType("INTEGER"); - - b.Property("IsInterlaced") - .HasColumnType("INTEGER"); - - b.Property("KeyFrames") - .HasColumnType("TEXT"); - - b.Property("Language") - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("REAL"); - - b.Property("NalLengthSize") - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PixelFormat") - .HasColumnType("TEXT"); - - b.Property("Profile") - .HasColumnType("TEXT"); - - b.Property("RealFrameRate") - .HasColumnType("REAL"); - - b.Property("RefFrames") - .HasColumnType("INTEGER"); - - b.Property("Rotation") - .HasColumnType("INTEGER"); - - b.Property("RpuPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("SampleRate") - .HasColumnType("INTEGER"); - - b.Property("StreamType") - .HasColumnType("INTEGER"); - - b.Property("TimeBase") - .HasColumnType("TEXT"); - - b.Property("Title") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "StreamIndex"); - - b.HasIndex("StreamIndex"); - - b.HasIndex("StreamType"); - - b.HasIndex("StreamIndex", "StreamType"); - - b.HasIndex("StreamIndex", "StreamType", "Language"); - - b.ToTable("MediaStreamInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.People", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PersonType") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name"); - - b.ToTable("Peoples"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.PeopleBaseItemMap", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("PeopleId") - .HasColumnType("TEXT"); - - b.Property("ListOrder") - .HasColumnType("INTEGER"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "PeopleId"); - - b.HasIndex("PeopleId"); - - b.HasIndex("ItemId", "ListOrder"); - - b.HasIndex("ItemId", "SortOrder"); - - b.ToTable("PeopleBaseItemMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT") - .UseCollation("NOCASE"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.UserData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("CustomDataKey") - .HasColumnType("TEXT"); - - b.Property("AudioStreamIndex") - .HasColumnType("INTEGER"); - - b.Property("IsFavorite") - .HasColumnType("INTEGER"); - - b.Property("LastPlayedDate") - .HasColumnType("TEXT"); - - b.Property("Likes") - .HasColumnType("INTEGER"); - - b.Property("PlayCount") - .HasColumnType("INTEGER"); - - b.Property("PlaybackPositionTicks") - .HasColumnType("INTEGER"); - - b.Property("Played") - .HasColumnType("INTEGER"); - - b.Property("Rating") - .HasColumnType("REAL"); - - b.Property("SubtitleStreamIndex") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "UserId", "CustomDataKey"); - - b.HasIndex("UserId"); - - b.HasIndex("ItemId", "UserId", "IsFavorite"); - - b.HasIndex("ItemId", "UserId", "LastPlayedDate"); - - b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks"); - - b.HasIndex("ItemId", "UserId", "Played"); - - b.ToTable("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AncestorId", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Children") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "ParentItem") - .WithMany("ParentAncestors") - .HasForeignKey("ParentItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ParentItem"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AttachmentStreamInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Images") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemMetadataField", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("LockedFields") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemProvider", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Provider") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemTrailerType", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("TrailerTypes") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Chapter", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Chapters") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValueMap", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("ItemValues") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.ItemValue", "ItemValue") - .WithMany("BaseItemsMap") - .HasForeignKey("ItemValueId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ItemValue"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaStreamInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("MediaStreams") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.PeopleBaseItemMap", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Peoples") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.People", "People") - .WithMany("BaseItems") - .HasForeignKey("PeopleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("People"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.UserData", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("UserData") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemEntity", b => - { - b.Navigation("Chapters"); - - b.Navigation("Children"); - - b.Navigation("Images"); - - b.Navigation("ItemValues"); - - b.Navigation("LockedFields"); - - b.Navigation("MediaStreams"); - - b.Navigation("ParentAncestors"); - - b.Navigation("Peoples"); - - b.Navigation("Provider"); - - b.Navigation("TrailerTypes"); - - b.Navigation("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValue", b => - { - b.Navigation("BaseItemsMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.People", b => - { - b.Navigation("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250204092455_MakeStartEndDateNullable.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250204092455_MakeStartEndDateNullable.cs deleted file mode 100644 index c9eb82ae..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250204092455_MakeStartEndDateNullable.cs +++ /dev/null @@ -1,59 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using System; - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class MakeStartEndDateNullable : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "StartDate", - table: "BaseItems", - type: "TEXT", - nullable: true, - oldClrType: typeof(DateTime), - oldType: "TEXT"); - - migrationBuilder.AlterColumn( - name: "EndDate", - table: "BaseItems", - type: "TEXT", - nullable: true, - oldClrType: typeof(DateTime), - oldType: "TEXT"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "StartDate", - table: "BaseItems", - type: "TEXT", - nullable: false, - defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), - oldClrType: typeof(DateTime), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AlterColumn( - name: "EndDate", - table: "BaseItems", - type: "TEXT", - nullable: false, - defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), - oldClrType: typeof(DateTime), - oldType: "TEXT", - oldNullable: true); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250214031148_ChannelIdGuid.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250214031148_ChannelIdGuid.Designer.cs deleted file mode 100644 index f5cfe86c..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250214031148_ChannelIdGuid.Designer.cs +++ /dev/null @@ -1,1595 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20250214031148_ChannelIdGuid")] - partial class ChannelIdGuid - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.2"); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AncestorId", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ParentItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ParentItemId"); - - b.HasIndex("ParentItemId"); - - b.ToTable("AncestorIds"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AttachmentStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Index") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("Filename") - .HasColumnType("TEXT"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "Index"); - - b.ToTable("AttachmentStreamInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Album") - .HasColumnType("TEXT"); - - b.Property("AlbumArtists") - .HasColumnType("TEXT"); - - b.Property("Artists") - .HasColumnType("TEXT"); - - b.Property("Audio") - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("TEXT"); - - b.Property("CleanName") - .HasColumnType("TEXT"); - - b.Property("CommunityRating") - .HasColumnType("REAL"); - - b.Property("CriticRating") - .HasColumnType("REAL"); - - b.Property("CustomRating") - .HasColumnType("TEXT"); - - b.Property("Data") - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastMediaAdded") - .HasColumnType("TEXT"); - - b.Property("DateLastRefreshed") - .HasColumnType("TEXT"); - - b.Property("DateLastSaved") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("EpisodeTitle") - .HasColumnType("TEXT"); - - b.Property("ExternalId") - .HasColumnType("TEXT"); - - b.Property("ExternalSeriesId") - .HasColumnType("TEXT"); - - b.Property("ExternalServiceId") - .HasColumnType("TEXT"); - - b.Property("ExtraIds") - .HasColumnType("TEXT"); - - b.Property("ExtraType") - .HasColumnType("INTEGER"); - - b.Property("ForcedSortName") - .HasColumnType("TEXT"); - - b.Property("Genres") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IndexNumber") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingValue") - .HasColumnType("INTEGER"); - - b.Property("IsFolder") - .HasColumnType("INTEGER"); - - b.Property("IsInMixedFolder") - .HasColumnType("INTEGER"); - - b.Property("IsLocked") - .HasColumnType("INTEGER"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("IsRepeat") - .HasColumnType("INTEGER"); - - b.Property("IsSeries") - .HasColumnType("INTEGER"); - - b.Property("IsVirtualItem") - .HasColumnType("INTEGER"); - - b.Property("LUFS") - .HasColumnType("REAL"); - - b.Property("MediaType") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("NormalizationGain") - .HasColumnType("REAL"); - - b.Property("OfficialRating") - .HasColumnType("TEXT"); - - b.Property("OriginalTitle") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .HasColumnType("TEXT"); - - b.Property("ParentId") - .HasColumnType("TEXT"); - - b.Property("ParentIndexNumber") - .HasColumnType("INTEGER"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataCountryCode") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataLanguage") - .HasColumnType("TEXT"); - - b.Property("PremiereDate") - .HasColumnType("TEXT"); - - b.Property("PresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("PrimaryVersionId") - .HasColumnType("TEXT"); - - b.Property("ProductionLocations") - .HasColumnType("TEXT"); - - b.Property("ProductionYear") - .HasColumnType("INTEGER"); - - b.Property("RunTimeTicks") - .HasColumnType("INTEGER"); - - b.Property("SeasonId") - .HasColumnType("TEXT"); - - b.Property("SeasonName") - .HasColumnType("TEXT"); - - b.Property("SeriesId") - .HasColumnType("TEXT"); - - b.Property("SeriesName") - .HasColumnType("TEXT"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("ShowId") - .HasColumnType("TEXT"); - - b.Property("Size") - .HasColumnType("INTEGER"); - - b.Property("SortName") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Studios") - .HasColumnType("TEXT"); - - b.Property("Tagline") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT"); - - b.Property("TopParentId") - .HasColumnType("TEXT"); - - b.Property("TotalBitrate") - .HasColumnType("INTEGER"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UnratedType") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("Path"); - - b.HasIndex("PresentationUniqueKey"); - - b.HasIndex("TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - - b.HasIndex("Type", "TopParentId", "StartDate"); - - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); - - b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.ToTable("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Blurhash") - .HasColumnType("BLOB"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("ImageType") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemMetadataField", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemMetadataFields"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemProvider", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ProviderId") - .HasColumnType("TEXT"); - - b.Property("ProviderValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ProviderId"); - - b.HasIndex("ProviderId", "ProviderValue", "ItemId"); - - b.ToTable("BaseItemProviders"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemTrailerType", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemTrailerTypes"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Chapter", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ChapterIndex") - .HasColumnType("INTEGER"); - - b.Property("ImageDateModified") - .HasColumnType("TEXT"); - - b.Property("ImagePath") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("StartPositionTicks") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "ChapterIndex"); - - b.ToTable("Chapters"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValue", b => - { - b.Property("ItemValueId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CleanValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId"); - - b.HasIndex("Type", "CleanValue") - .IsUnique(); - - b.ToTable("ItemValues"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValueMap", b => - { - b.Property("ItemValueId") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("ItemValuesMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StreamIndex") - .HasColumnType("INTEGER"); - - b.Property("AspectRatio") - .HasColumnType("TEXT"); - - b.Property("AverageFrameRate") - .HasColumnType("REAL"); - - b.Property("BitDepth") - .HasColumnType("INTEGER"); - - b.Property("BitRate") - .HasColumnType("INTEGER"); - - b.Property("BlPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("ChannelLayout") - .HasColumnType("TEXT"); - - b.Property("Channels") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("CodecTimeBase") - .HasColumnType("TEXT"); - - b.Property("ColorPrimaries") - .HasColumnType("TEXT"); - - b.Property("ColorSpace") - .HasColumnType("TEXT"); - - b.Property("ColorTransfer") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("DvBlSignalCompatibilityId") - .HasColumnType("INTEGER"); - - b.Property("DvLevel") - .HasColumnType("INTEGER"); - - b.Property("DvProfile") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMajor") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMinor") - .HasColumnType("INTEGER"); - - b.Property("ElPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IsAnamorphic") - .HasColumnType("INTEGER"); - - b.Property("IsAvc") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("IsHearingImpaired") - .HasColumnType("INTEGER"); - - b.Property("IsInterlaced") - .HasColumnType("INTEGER"); - - b.Property("KeyFrames") - .HasColumnType("TEXT"); - - b.Property("Language") - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("REAL"); - - b.Property("NalLengthSize") - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PixelFormat") - .HasColumnType("TEXT"); - - b.Property("Profile") - .HasColumnType("TEXT"); - - b.Property("RealFrameRate") - .HasColumnType("REAL"); - - b.Property("RefFrames") - .HasColumnType("INTEGER"); - - b.Property("Rotation") - .HasColumnType("INTEGER"); - - b.Property("RpuPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("SampleRate") - .HasColumnType("INTEGER"); - - b.Property("StreamType") - .HasColumnType("INTEGER"); - - b.Property("TimeBase") - .HasColumnType("TEXT"); - - b.Property("Title") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "StreamIndex"); - - b.HasIndex("StreamIndex"); - - b.HasIndex("StreamType"); - - b.HasIndex("StreamIndex", "StreamType"); - - b.HasIndex("StreamIndex", "StreamType", "Language"); - - b.ToTable("MediaStreamInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.People", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PersonType") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name"); - - b.ToTable("Peoples"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.PeopleBaseItemMap", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("PeopleId") - .HasColumnType("TEXT"); - - b.Property("ListOrder") - .HasColumnType("INTEGER"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "PeopleId"); - - b.HasIndex("PeopleId"); - - b.HasIndex("ItemId", "ListOrder"); - - b.HasIndex("ItemId", "SortOrder"); - - b.ToTable("PeopleBaseItemMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT") - .UseCollation("NOCASE"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.UserData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("CustomDataKey") - .HasColumnType("TEXT"); - - b.Property("AudioStreamIndex") - .HasColumnType("INTEGER"); - - b.Property("IsFavorite") - .HasColumnType("INTEGER"); - - b.Property("LastPlayedDate") - .HasColumnType("TEXT"); - - b.Property("Likes") - .HasColumnType("INTEGER"); - - b.Property("PlayCount") - .HasColumnType("INTEGER"); - - b.Property("PlaybackPositionTicks") - .HasColumnType("INTEGER"); - - b.Property("Played") - .HasColumnType("INTEGER"); - - b.Property("Rating") - .HasColumnType("REAL"); - - b.Property("SubtitleStreamIndex") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "UserId", "CustomDataKey"); - - b.HasIndex("UserId"); - - b.HasIndex("ItemId", "UserId", "IsFavorite"); - - b.HasIndex("ItemId", "UserId", "LastPlayedDate"); - - b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks"); - - b.HasIndex("ItemId", "UserId", "Played"); - - b.ToTable("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AncestorId", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Children") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "ParentItem") - .WithMany("ParentAncestors") - .HasForeignKey("ParentItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ParentItem"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.AttachmentStreamInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Images") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemMetadataField", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("LockedFields") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemProvider", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Provider") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemTrailerType", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("TrailerTypes") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Chapter", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Chapters") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Data.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Data.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValueMap", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("ItemValues") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.ItemValue", "ItemValue") - .WithMany("BaseItemsMap") - .HasForeignKey("ItemValueId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ItemValue"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.MediaStreamInfo", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("MediaStreams") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.PeopleBaseItemMap", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("Peoples") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.People", "People") - .WithMany("BaseItems") - .HasForeignKey("PeopleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("People"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Permission", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Preference", b => - { - b.HasOne("Jellyfin.Data.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.UserData", b => - { - b.HasOne("Jellyfin.Data.Entities.BaseItemEntity", "Item") - .WithMany("UserData") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Data.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.BaseItemEntity", b => - { - b.Navigation("Chapters"); - - b.Navigation("Children"); - - b.Navigation("Images"); - - b.Navigation("ItemValues"); - - b.Navigation("LockedFields"); - - b.Navigation("MediaStreams"); - - b.Navigation("ParentAncestors"); - - b.Navigation("Peoples"); - - b.Navigation("Provider"); - - b.Navigation("TrailerTypes"); - - b.Navigation("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.ItemValue", b => - { - b.Navigation("BaseItemsMap"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.People", b => - { - b.Navigation("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Data.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250214031148_ChannelIdGuid.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250214031148_ChannelIdGuid.cs deleted file mode 100644 index b7466d0d..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250214031148_ChannelIdGuid.cs +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class ChannelIdGuid : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - // NOOP, Guids and strings are stored the same in SQLite. - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - // NOOP, Guids and strings are stored the same in SQLite. - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250326065026_AddInheritedParentalRatingSubValue.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250326065026_AddInheritedParentalRatingSubValue.Designer.cs deleted file mode 100644 index d6befbe5..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250326065026_AddInheritedParentalRatingSubValue.Designer.cs +++ /dev/null @@ -1,1658 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20250326065026_AddInheritedParentalRatingSubValue")] - partial class AddInheritedParentalRatingSubValue - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.3"); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ParentItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ParentItemId"); - - b.HasIndex("ParentItemId"); - - b.ToTable("AncestorIds"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Index") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("Filename") - .HasColumnType("TEXT"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "Index"); - - b.ToTable("AttachmentStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Album") - .HasColumnType("TEXT"); - - b.Property("AlbumArtists") - .HasColumnType("TEXT"); - - b.Property("Artists") - .HasColumnType("TEXT"); - - b.Property("Audio") - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("TEXT"); - - b.Property("CleanName") - .HasColumnType("TEXT"); - - b.Property("CommunityRating") - .HasColumnType("REAL"); - - b.Property("CriticRating") - .HasColumnType("REAL"); - - b.Property("CustomRating") - .HasColumnType("TEXT"); - - b.Property("Data") - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastMediaAdded") - .HasColumnType("TEXT"); - - b.Property("DateLastRefreshed") - .HasColumnType("TEXT"); - - b.Property("DateLastSaved") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("EpisodeTitle") - .HasColumnType("TEXT"); - - b.Property("ExternalId") - .HasColumnType("TEXT"); - - b.Property("ExternalSeriesId") - .HasColumnType("TEXT"); - - b.Property("ExternalServiceId") - .HasColumnType("TEXT"); - - b.Property("ExtraIds") - .HasColumnType("TEXT"); - - b.Property("ExtraType") - .HasColumnType("INTEGER"); - - b.Property("ForcedSortName") - .HasColumnType("TEXT"); - - b.Property("Genres") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IndexNumber") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingSubValue") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingValue") - .HasColumnType("INTEGER"); - - b.Property("IsFolder") - .HasColumnType("INTEGER"); - - b.Property("IsInMixedFolder") - .HasColumnType("INTEGER"); - - b.Property("IsLocked") - .HasColumnType("INTEGER"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("IsRepeat") - .HasColumnType("INTEGER"); - - b.Property("IsSeries") - .HasColumnType("INTEGER"); - - b.Property("IsVirtualItem") - .HasColumnType("INTEGER"); - - b.Property("LUFS") - .HasColumnType("REAL"); - - b.Property("MediaType") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("NormalizationGain") - .HasColumnType("REAL"); - - b.Property("OfficialRating") - .HasColumnType("TEXT"); - - b.Property("OriginalTitle") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .HasColumnType("TEXT"); - - b.Property("ParentId") - .HasColumnType("TEXT"); - - b.Property("ParentIndexNumber") - .HasColumnType("INTEGER"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataCountryCode") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataLanguage") - .HasColumnType("TEXT"); - - b.Property("PremiereDate") - .HasColumnType("TEXT"); - - b.Property("PresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("PrimaryVersionId") - .HasColumnType("TEXT"); - - b.Property("ProductionLocations") - .HasColumnType("TEXT"); - - b.Property("ProductionYear") - .HasColumnType("INTEGER"); - - b.Property("RunTimeTicks") - .HasColumnType("INTEGER"); - - b.Property("SeasonId") - .HasColumnType("TEXT"); - - b.Property("SeasonName") - .HasColumnType("TEXT"); - - b.Property("SeriesId") - .HasColumnType("TEXT"); - - b.Property("SeriesName") - .HasColumnType("TEXT"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("ShowId") - .HasColumnType("TEXT"); - - b.Property("Size") - .HasColumnType("INTEGER"); - - b.Property("SortName") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Studios") - .HasColumnType("TEXT"); - - b.Property("Tagline") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT"); - - b.Property("TopParentId") - .HasColumnType("TEXT"); - - b.Property("TotalBitrate") - .HasColumnType("INTEGER"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UnratedType") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("Path"); - - b.HasIndex("PresentationUniqueKey"); - - b.HasIndex("TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - - b.HasIndex("Type", "TopParentId", "StartDate"); - - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); - - b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.ToTable("BaseItems"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Blurhash") - .HasColumnType("BLOB"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("ImageType") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemMetadataFields"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ProviderId") - .HasColumnType("TEXT"); - - b.Property("ProviderValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ProviderId"); - - b.HasIndex("ProviderId", "ProviderValue", "ItemId"); - - b.ToTable("BaseItemProviders"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemTrailerTypes"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ChapterIndex") - .HasColumnType("INTEGER"); - - b.Property("ImageDateModified") - .HasColumnType("TEXT"); - - b.Property("ImagePath") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("StartPositionTicks") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "ChapterIndex"); - - b.ToTable("Chapters"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Property("ItemValueId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CleanValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId"); - - b.HasIndex("Type", "CleanValue") - .IsUnique(); - - b.ToTable("ItemValues"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.Property("ItemValueId") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("ItemValuesMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StreamIndex") - .HasColumnType("INTEGER"); - - b.Property("AspectRatio") - .HasColumnType("TEXT"); - - b.Property("AverageFrameRate") - .HasColumnType("REAL"); - - b.Property("BitDepth") - .HasColumnType("INTEGER"); - - b.Property("BitRate") - .HasColumnType("INTEGER"); - - b.Property("BlPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("ChannelLayout") - .HasColumnType("TEXT"); - - b.Property("Channels") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("CodecTimeBase") - .HasColumnType("TEXT"); - - b.Property("ColorPrimaries") - .HasColumnType("TEXT"); - - b.Property("ColorSpace") - .HasColumnType("TEXT"); - - b.Property("ColorTransfer") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("DvBlSignalCompatibilityId") - .HasColumnType("INTEGER"); - - b.Property("DvLevel") - .HasColumnType("INTEGER"); - - b.Property("DvProfile") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMajor") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMinor") - .HasColumnType("INTEGER"); - - b.Property("ElPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IsAnamorphic") - .HasColumnType("INTEGER"); - - b.Property("IsAvc") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("IsHearingImpaired") - .HasColumnType("INTEGER"); - - b.Property("IsInterlaced") - .HasColumnType("INTEGER"); - - b.Property("KeyFrames") - .HasColumnType("TEXT"); - - b.Property("Language") - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("REAL"); - - b.Property("NalLengthSize") - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PixelFormat") - .HasColumnType("TEXT"); - - b.Property("Profile") - .HasColumnType("TEXT"); - - b.Property("RealFrameRate") - .HasColumnType("REAL"); - - b.Property("RefFrames") - .HasColumnType("INTEGER"); - - b.Property("Rotation") - .HasColumnType("INTEGER"); - - b.Property("RpuPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("SampleRate") - .HasColumnType("INTEGER"); - - b.Property("StreamType") - .HasColumnType("INTEGER"); - - b.Property("TimeBase") - .HasColumnType("TEXT"); - - b.Property("Title") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "StreamIndex"); - - b.HasIndex("StreamIndex"); - - b.HasIndex("StreamType"); - - b.HasIndex("StreamIndex", "StreamType"); - - b.HasIndex("StreamIndex", "StreamType", "Language"); - - b.ToTable("MediaStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PersonType") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name"); - - b.ToTable("Peoples"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("PeopleId") - .HasColumnType("TEXT"); - - b.Property("ListOrder") - .HasColumnType("INTEGER"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "PeopleId"); - - b.HasIndex("PeopleId"); - - b.HasIndex("ItemId", "ListOrder"); - - b.HasIndex("ItemId", "SortOrder"); - - b.ToTable("PeopleBaseItemMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalRatingScore") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalRatingSubScore") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("CustomDataKey") - .HasColumnType("TEXT"); - - b.Property("AudioStreamIndex") - .HasColumnType("INTEGER"); - - b.Property("IsFavorite") - .HasColumnType("INTEGER"); - - b.Property("LastPlayedDate") - .HasColumnType("TEXT"); - - b.Property("Likes") - .HasColumnType("INTEGER"); - - b.Property("PlayCount") - .HasColumnType("INTEGER"); - - b.Property("PlaybackPositionTicks") - .HasColumnType("INTEGER"); - - b.Property("Played") - .HasColumnType("INTEGER"); - - b.Property("Rating") - .HasColumnType("REAL"); - - b.Property("SubtitleStreamIndex") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "UserId", "CustomDataKey"); - - b.HasIndex("UserId"); - - b.HasIndex("ItemId", "UserId", "IsFavorite"); - - b.HasIndex("ItemId", "UserId", "LastPlayedDate"); - - b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks"); - - b.HasIndex("ItemId", "UserId", "Played"); - - b.ToTable("UserData"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Children") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "ParentItem") - .WithMany("ParentAncestors") - .HasForeignKey("ParentItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ParentItem"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Images") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("LockedFields") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Provider") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("TrailerTypes") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Chapters") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Database.Implementations.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("ItemValues") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.ItemValue", "ItemValue") - .WithMany("BaseItemsMap") - .HasForeignKey("ItemValueId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ItemValue"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("MediaStreams") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Peoples") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.People", "People") - .WithMany("BaseItems") - .HasForeignKey("PeopleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("People"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("UserData") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Navigation("Chapters"); - - b.Navigation("Children"); - - b.Navigation("Images"); - - b.Navigation("ItemValues"); - - b.Navigation("LockedFields"); - - b.Navigation("MediaStreams"); - - b.Navigation("ParentAncestors"); - - b.Navigation("Peoples"); - - b.Navigation("Provider"); - - b.Navigation("TrailerTypes"); - - b.Navigation("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Navigation("BaseItemsMap"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Navigation("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250326065026_AddInheritedParentalRatingSubValue.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250326065026_AddInheritedParentalRatingSubValue.cs deleted file mode 100644 index 73f534d0..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250326065026_AddInheritedParentalRatingSubValue.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class AddInheritedParentalRatingSubValue : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.RenameColumn( - name: "MaxParentalAgeRating", - table: "Users", - newName: "MaxParentalRatingScore"); - - migrationBuilder.AddColumn( - name: "MaxParentalRatingSubScore", - table: "Users", - type: "INTEGER", - nullable: true); - - migrationBuilder.AddColumn( - name: "InheritedParentalRatingSubValue", - table: "BaseItems", - type: "INTEGER", - nullable: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "MaxParentalRatingSubScore", - table: "Users"); - - migrationBuilder.DropColumn( - name: "InheritedParentalRatingValue", - table: "BaseItems"); - - migrationBuilder.RenameColumn( - name: "MaxParentalRatingScore", - table: "Users", - newName: "MaxParentalAgeRating"); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250327101120_AddKeyframeData.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250327101120_AddKeyframeData.Designer.cs deleted file mode 100644 index 434ea820..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250327101120_AddKeyframeData.Designer.cs +++ /dev/null @@ -1,1681 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20250327101120_AddKeyframeData")] - partial class AddKeyframeData - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.3"); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ParentItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ParentItemId"); - - b.HasIndex("ParentItemId"); - - b.ToTable("AncestorIds"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Index") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("Filename") - .HasColumnType("TEXT"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "Index"); - - b.ToTable("AttachmentStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Album") - .HasColumnType("TEXT"); - - b.Property("AlbumArtists") - .HasColumnType("TEXT"); - - b.Property("Artists") - .HasColumnType("TEXT"); - - b.Property("Audio") - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("TEXT"); - - b.Property("CleanName") - .HasColumnType("TEXT"); - - b.Property("CommunityRating") - .HasColumnType("REAL"); - - b.Property("CriticRating") - .HasColumnType("REAL"); - - b.Property("CustomRating") - .HasColumnType("TEXT"); - - b.Property("Data") - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastMediaAdded") - .HasColumnType("TEXT"); - - b.Property("DateLastRefreshed") - .HasColumnType("TEXT"); - - b.Property("DateLastSaved") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("EpisodeTitle") - .HasColumnType("TEXT"); - - b.Property("ExternalId") - .HasColumnType("TEXT"); - - b.Property("ExternalSeriesId") - .HasColumnType("TEXT"); - - b.Property("ExternalServiceId") - .HasColumnType("TEXT"); - - b.Property("ExtraIds") - .HasColumnType("TEXT"); - - b.Property("ExtraType") - .HasColumnType("INTEGER"); - - b.Property("ForcedSortName") - .HasColumnType("TEXT"); - - b.Property("Genres") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IndexNumber") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingValue") - .HasColumnType("INTEGER"); - - b.Property("IsFolder") - .HasColumnType("INTEGER"); - - b.Property("IsInMixedFolder") - .HasColumnType("INTEGER"); - - b.Property("IsLocked") - .HasColumnType("INTEGER"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("IsRepeat") - .HasColumnType("INTEGER"); - - b.Property("IsSeries") - .HasColumnType("INTEGER"); - - b.Property("IsVirtualItem") - .HasColumnType("INTEGER"); - - b.Property("LUFS") - .HasColumnType("REAL"); - - b.Property("MediaType") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("NormalizationGain") - .HasColumnType("REAL"); - - b.Property("OfficialRating") - .HasColumnType("TEXT"); - - b.Property("OriginalTitle") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .HasColumnType("TEXT"); - - b.Property("ParentId") - .HasColumnType("TEXT"); - - b.Property("ParentIndexNumber") - .HasColumnType("INTEGER"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataCountryCode") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataLanguage") - .HasColumnType("TEXT"); - - b.Property("PremiereDate") - .HasColumnType("TEXT"); - - b.Property("PresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("PrimaryVersionId") - .HasColumnType("TEXT"); - - b.Property("ProductionLocations") - .HasColumnType("TEXT"); - - b.Property("ProductionYear") - .HasColumnType("INTEGER"); - - b.Property("RunTimeTicks") - .HasColumnType("INTEGER"); - - b.Property("SeasonId") - .HasColumnType("TEXT"); - - b.Property("SeasonName") - .HasColumnType("TEXT"); - - b.Property("SeriesId") - .HasColumnType("TEXT"); - - b.Property("SeriesName") - .HasColumnType("TEXT"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("ShowId") - .HasColumnType("TEXT"); - - b.Property("Size") - .HasColumnType("INTEGER"); - - b.Property("SortName") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Studios") - .HasColumnType("TEXT"); - - b.Property("Tagline") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT"); - - b.Property("TopParentId") - .HasColumnType("TEXT"); - - b.Property("TotalBitrate") - .HasColumnType("INTEGER"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UnratedType") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("Path"); - - b.HasIndex("PresentationUniqueKey"); - - b.HasIndex("TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - - b.HasIndex("Type", "TopParentId", "StartDate"); - - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); - - b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.ToTable("BaseItems"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Blurhash") - .HasColumnType("BLOB"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("ImageType") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemMetadataFields"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ProviderId") - .HasColumnType("TEXT"); - - b.Property("ProviderValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ProviderId"); - - b.HasIndex("ProviderId", "ProviderValue", "ItemId"); - - b.ToTable("BaseItemProviders"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemTrailerTypes"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ChapterIndex") - .HasColumnType("INTEGER"); - - b.Property("ImageDateModified") - .HasColumnType("TEXT"); - - b.Property("ImagePath") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("StartPositionTicks") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "ChapterIndex"); - - b.ToTable("Chapters"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Property("ItemValueId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CleanValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId"); - - b.HasIndex("Type", "CleanValue") - .IsUnique(); - - b.ToTable("ItemValues"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.Property("ItemValueId") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("ItemValuesMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.KeyframeData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.PrimitiveCollection("KeyframeTicks") - .HasColumnType("TEXT"); - - b.Property("TotalDuration") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId"); - - b.ToTable("KeyframeData"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StreamIndex") - .HasColumnType("INTEGER"); - - b.Property("AspectRatio") - .HasColumnType("TEXT"); - - b.Property("AverageFrameRate") - .HasColumnType("REAL"); - - b.Property("BitDepth") - .HasColumnType("INTEGER"); - - b.Property("BitRate") - .HasColumnType("INTEGER"); - - b.Property("BlPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("ChannelLayout") - .HasColumnType("TEXT"); - - b.Property("Channels") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("CodecTimeBase") - .HasColumnType("TEXT"); - - b.Property("ColorPrimaries") - .HasColumnType("TEXT"); - - b.Property("ColorSpace") - .HasColumnType("TEXT"); - - b.Property("ColorTransfer") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("DvBlSignalCompatibilityId") - .HasColumnType("INTEGER"); - - b.Property("DvLevel") - .HasColumnType("INTEGER"); - - b.Property("DvProfile") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMajor") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMinor") - .HasColumnType("INTEGER"); - - b.Property("ElPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IsAnamorphic") - .HasColumnType("INTEGER"); - - b.Property("IsAvc") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("IsHearingImpaired") - .HasColumnType("INTEGER"); - - b.Property("IsInterlaced") - .HasColumnType("INTEGER"); - - b.Property("KeyFrames") - .HasColumnType("TEXT"); - - b.Property("Language") - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("REAL"); - - b.Property("NalLengthSize") - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PixelFormat") - .HasColumnType("TEXT"); - - b.Property("Profile") - .HasColumnType("TEXT"); - - b.Property("RealFrameRate") - .HasColumnType("REAL"); - - b.Property("RefFrames") - .HasColumnType("INTEGER"); - - b.Property("Rotation") - .HasColumnType("INTEGER"); - - b.Property("RpuPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("SampleRate") - .HasColumnType("INTEGER"); - - b.Property("StreamType") - .HasColumnType("INTEGER"); - - b.Property("TimeBase") - .HasColumnType("TEXT"); - - b.Property("Title") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "StreamIndex"); - - b.HasIndex("StreamIndex"); - - b.HasIndex("StreamType"); - - b.HasIndex("StreamIndex", "StreamType"); - - b.HasIndex("StreamIndex", "StreamType", "Language"); - - b.ToTable("MediaStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PersonType") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name"); - - b.ToTable("Peoples"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("PeopleId") - .HasColumnType("TEXT"); - - b.Property("ListOrder") - .HasColumnType("INTEGER"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "PeopleId"); - - b.HasIndex("PeopleId"); - - b.HasIndex("ItemId", "ListOrder"); - - b.HasIndex("ItemId", "SortOrder"); - - b.ToTable("PeopleBaseItemMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("CustomDataKey") - .HasColumnType("TEXT"); - - b.Property("AudioStreamIndex") - .HasColumnType("INTEGER"); - - b.Property("IsFavorite") - .HasColumnType("INTEGER"); - - b.Property("LastPlayedDate") - .HasColumnType("TEXT"); - - b.Property("Likes") - .HasColumnType("INTEGER"); - - b.Property("PlayCount") - .HasColumnType("INTEGER"); - - b.Property("PlaybackPositionTicks") - .HasColumnType("INTEGER"); - - b.Property("Played") - .HasColumnType("INTEGER"); - - b.Property("Rating") - .HasColumnType("REAL"); - - b.Property("SubtitleStreamIndex") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "UserId", "CustomDataKey"); - - b.HasIndex("UserId"); - - b.HasIndex("ItemId", "UserId", "IsFavorite"); - - b.HasIndex("ItemId", "UserId", "LastPlayedDate"); - - b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks"); - - b.HasIndex("ItemId", "UserId", "Played"); - - b.ToTable("UserData"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Children") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "ParentItem") - .WithMany("ParentAncestors") - .HasForeignKey("ParentItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ParentItem"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Images") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("LockedFields") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Provider") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("TrailerTypes") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Chapters") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Database.Implementations.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("ItemValues") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.ItemValue", "ItemValue") - .WithMany("BaseItemsMap") - .HasForeignKey("ItemValueId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ItemValue"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.KeyframeData", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("MediaStreams") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Peoples") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.People", "People") - .WithMany("BaseItems") - .HasForeignKey("PeopleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("People"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("UserData") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Navigation("Chapters"); - - b.Navigation("Children"); - - b.Navigation("Images"); - - b.Navigation("ItemValues"); - - b.Navigation("LockedFields"); - - b.Navigation("MediaStreams"); - - b.Navigation("ParentAncestors"); - - b.Navigation("Peoples"); - - b.Navigation("Provider"); - - b.Navigation("TrailerTypes"); - - b.Navigation("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Navigation("BaseItemsMap"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Navigation("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250327101120_AddKeyframeData.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250327101120_AddKeyframeData.cs deleted file mode 100644 index 0b802955..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250327101120_AddKeyframeData.cs +++ /dev/null @@ -1,45 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using System; - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class AddKeyframeData : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "KeyframeData", - columns: table => new - { - ItemId = table.Column(type: "TEXT", nullable: false), - TotalDuration = table.Column(type: "INTEGER", nullable: false), - KeyframeTicks = table.Column(type: "TEXT", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_KeyframeData", x => x.ItemId); - table.ForeignKey( - name: "FK_KeyframeData_BaseItems_ItemId", - column: x => x.ItemId, - principalTable: "BaseItems", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "KeyframeData"); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250327171413_AddHdr10PlusFlag.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250327171413_AddHdr10PlusFlag.Designer.cs deleted file mode 100644 index bad01778..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250327171413_AddHdr10PlusFlag.Designer.cs +++ /dev/null @@ -1,1655 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20250327171413_AddHdr10PlusFlag")] - partial class AddHdr10PlusFlag - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.3"); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ParentItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ParentItemId"); - - b.HasIndex("ParentItemId"); - - b.ToTable("AncestorIds"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Index") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("Filename") - .HasColumnType("TEXT"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "Index"); - - b.ToTable("AttachmentStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Album") - .HasColumnType("TEXT"); - - b.Property("AlbumArtists") - .HasColumnType("TEXT"); - - b.Property("Artists") - .HasColumnType("TEXT"); - - b.Property("Audio") - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("TEXT"); - - b.Property("CleanName") - .HasColumnType("TEXT"); - - b.Property("CommunityRating") - .HasColumnType("REAL"); - - b.Property("CriticRating") - .HasColumnType("REAL"); - - b.Property("CustomRating") - .HasColumnType("TEXT"); - - b.Property("Data") - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastMediaAdded") - .HasColumnType("TEXT"); - - b.Property("DateLastRefreshed") - .HasColumnType("TEXT"); - - b.Property("DateLastSaved") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("EpisodeTitle") - .HasColumnType("TEXT"); - - b.Property("ExternalId") - .HasColumnType("TEXT"); - - b.Property("ExternalSeriesId") - .HasColumnType("TEXT"); - - b.Property("ExternalServiceId") - .HasColumnType("TEXT"); - - b.Property("ExtraIds") - .HasColumnType("TEXT"); - - b.Property("ExtraType") - .HasColumnType("INTEGER"); - - b.Property("ForcedSortName") - .HasColumnType("TEXT"); - - b.Property("Genres") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IndexNumber") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingValue") - .HasColumnType("INTEGER"); - - b.Property("IsFolder") - .HasColumnType("INTEGER"); - - b.Property("IsInMixedFolder") - .HasColumnType("INTEGER"); - - b.Property("IsLocked") - .HasColumnType("INTEGER"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("IsRepeat") - .HasColumnType("INTEGER"); - - b.Property("IsSeries") - .HasColumnType("INTEGER"); - - b.Property("IsVirtualItem") - .HasColumnType("INTEGER"); - - b.Property("LUFS") - .HasColumnType("REAL"); - - b.Property("MediaType") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("NormalizationGain") - .HasColumnType("REAL"); - - b.Property("OfficialRating") - .HasColumnType("TEXT"); - - b.Property("OriginalTitle") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .HasColumnType("TEXT"); - - b.Property("ParentId") - .HasColumnType("TEXT"); - - b.Property("ParentIndexNumber") - .HasColumnType("INTEGER"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataCountryCode") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataLanguage") - .HasColumnType("TEXT"); - - b.Property("PremiereDate") - .HasColumnType("TEXT"); - - b.Property("PresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("PrimaryVersionId") - .HasColumnType("TEXT"); - - b.Property("ProductionLocations") - .HasColumnType("TEXT"); - - b.Property("ProductionYear") - .HasColumnType("INTEGER"); - - b.Property("RunTimeTicks") - .HasColumnType("INTEGER"); - - b.Property("SeasonId") - .HasColumnType("TEXT"); - - b.Property("SeasonName") - .HasColumnType("TEXT"); - - b.Property("SeriesId") - .HasColumnType("TEXT"); - - b.Property("SeriesName") - .HasColumnType("TEXT"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("ShowId") - .HasColumnType("TEXT"); - - b.Property("Size") - .HasColumnType("INTEGER"); - - b.Property("SortName") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Studios") - .HasColumnType("TEXT"); - - b.Property("Tagline") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT"); - - b.Property("TopParentId") - .HasColumnType("TEXT"); - - b.Property("TotalBitrate") - .HasColumnType("INTEGER"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UnratedType") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("Path"); - - b.HasIndex("PresentationUniqueKey"); - - b.HasIndex("TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - - b.HasIndex("Type", "TopParentId", "StartDate"); - - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); - - b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.ToTable("BaseItems"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Blurhash") - .HasColumnType("BLOB"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("ImageType") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemMetadataFields"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ProviderId") - .HasColumnType("TEXT"); - - b.Property("ProviderValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ProviderId"); - - b.HasIndex("ProviderId", "ProviderValue", "ItemId"); - - b.ToTable("BaseItemProviders"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemTrailerTypes"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ChapterIndex") - .HasColumnType("INTEGER"); - - b.Property("ImageDateModified") - .HasColumnType("TEXT"); - - b.Property("ImagePath") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("StartPositionTicks") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "ChapterIndex"); - - b.ToTable("Chapters"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Property("ItemValueId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CleanValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId"); - - b.HasIndex("Type", "CleanValue") - .IsUnique(); - - b.ToTable("ItemValues"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.Property("ItemValueId") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("ItemValuesMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StreamIndex") - .HasColumnType("INTEGER"); - - b.Property("AspectRatio") - .HasColumnType("TEXT"); - - b.Property("AverageFrameRate") - .HasColumnType("REAL"); - - b.Property("BitDepth") - .HasColumnType("INTEGER"); - - b.Property("BitRate") - .HasColumnType("INTEGER"); - - b.Property("BlPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("ChannelLayout") - .HasColumnType("TEXT"); - - b.Property("Channels") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("CodecTimeBase") - .HasColumnType("TEXT"); - - b.Property("ColorPrimaries") - .HasColumnType("TEXT"); - - b.Property("ColorSpace") - .HasColumnType("TEXT"); - - b.Property("ColorTransfer") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("DvBlSignalCompatibilityId") - .HasColumnType("INTEGER"); - - b.Property("DvLevel") - .HasColumnType("INTEGER"); - - b.Property("DvProfile") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMajor") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMinor") - .HasColumnType("INTEGER"); - - b.Property("ElPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Hdr10PlusPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IsAnamorphic") - .HasColumnType("INTEGER"); - - b.Property("IsAvc") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("IsHearingImpaired") - .HasColumnType("INTEGER"); - - b.Property("IsInterlaced") - .HasColumnType("INTEGER"); - - b.Property("KeyFrames") - .HasColumnType("TEXT"); - - b.Property("Language") - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("REAL"); - - b.Property("NalLengthSize") - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PixelFormat") - .HasColumnType("TEXT"); - - b.Property("Profile") - .HasColumnType("TEXT"); - - b.Property("RealFrameRate") - .HasColumnType("REAL"); - - b.Property("RefFrames") - .HasColumnType("INTEGER"); - - b.Property("Rotation") - .HasColumnType("INTEGER"); - - b.Property("RpuPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("SampleRate") - .HasColumnType("INTEGER"); - - b.Property("StreamType") - .HasColumnType("INTEGER"); - - b.Property("TimeBase") - .HasColumnType("TEXT"); - - b.Property("Title") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "StreamIndex"); - - b.HasIndex("StreamIndex"); - - b.HasIndex("StreamType"); - - b.HasIndex("StreamIndex", "StreamType"); - - b.HasIndex("StreamIndex", "StreamType", "Language"); - - b.ToTable("MediaStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PersonType") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name"); - - b.ToTable("Peoples"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("PeopleId") - .HasColumnType("TEXT"); - - b.Property("ListOrder") - .HasColumnType("INTEGER"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "PeopleId"); - - b.HasIndex("PeopleId"); - - b.HasIndex("ItemId", "ListOrder"); - - b.HasIndex("ItemId", "SortOrder"); - - b.ToTable("PeopleBaseItemMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalAgeRating") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("CustomDataKey") - .HasColumnType("TEXT"); - - b.Property("AudioStreamIndex") - .HasColumnType("INTEGER"); - - b.Property("IsFavorite") - .HasColumnType("INTEGER"); - - b.Property("LastPlayedDate") - .HasColumnType("TEXT"); - - b.Property("Likes") - .HasColumnType("INTEGER"); - - b.Property("PlayCount") - .HasColumnType("INTEGER"); - - b.Property("PlaybackPositionTicks") - .HasColumnType("INTEGER"); - - b.Property("Played") - .HasColumnType("INTEGER"); - - b.Property("Rating") - .HasColumnType("REAL"); - - b.Property("SubtitleStreamIndex") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "UserId", "CustomDataKey"); - - b.HasIndex("UserId"); - - b.HasIndex("ItemId", "UserId", "IsFavorite"); - - b.HasIndex("ItemId", "UserId", "LastPlayedDate"); - - b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks"); - - b.HasIndex("ItemId", "UserId", "Played"); - - b.ToTable("UserData"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Children") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "ParentItem") - .WithMany("ParentAncestors") - .HasForeignKey("ParentItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ParentItem"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Images") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("LockedFields") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Provider") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("TrailerTypes") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Chapters") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Database.Implementations.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("ItemValues") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.ItemValue", "ItemValue") - .WithMany("BaseItemsMap") - .HasForeignKey("ItemValueId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ItemValue"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("MediaStreams") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Peoples") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.People", "People") - .WithMany("BaseItems") - .HasForeignKey("PeopleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("People"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("UserData") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Navigation("Chapters"); - - b.Navigation("Children"); - - b.Navigation("Images"); - - b.Navigation("ItemValues"); - - b.Navigation("LockedFields"); - - b.Navigation("MediaStreams"); - - b.Navigation("ParentAncestors"); - - b.Navigation("Peoples"); - - b.Navigation("Provider"); - - b.Navigation("TrailerTypes"); - - b.Navigation("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Navigation("BaseItemsMap"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Navigation("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250327171413_AddHdr10PlusFlag.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250327171413_AddHdr10PlusFlag.cs deleted file mode 100644 index 3febfc66..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250327171413_AddHdr10PlusFlag.cs +++ /dev/null @@ -1,32 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class AddHdr10PlusFlag : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "Hdr10PlusPresentFlag", - table: "MediaStreamInfos", - type: "INTEGER", - nullable: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "Hdr10PlusPresentFlag", - table: "MediaStreamInfos"); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250331182844_FixAttachmentMigration.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250331182844_FixAttachmentMigration.Designer.cs deleted file mode 100644 index d668eea9..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250331182844_FixAttachmentMigration.Designer.cs +++ /dev/null @@ -1,1657 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20250331182844_FixAttachmentMigration")] - partial class FixAttachmentMigration - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.3"); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ParentItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ParentItemId"); - - b.HasIndex("ParentItemId"); - - b.ToTable("AncestorIds"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Index") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("Filename") - .HasColumnType("TEXT"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "Index"); - - b.ToTable("AttachmentStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Album") - .HasColumnType("TEXT"); - - b.Property("AlbumArtists") - .HasColumnType("TEXT"); - - b.Property("Artists") - .HasColumnType("TEXT"); - - b.Property("Audio") - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("TEXT"); - - b.Property("CleanName") - .HasColumnType("TEXT"); - - b.Property("CommunityRating") - .HasColumnType("REAL"); - - b.Property("CriticRating") - .HasColumnType("REAL"); - - b.Property("CustomRating") - .HasColumnType("TEXT"); - - b.Property("Data") - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastMediaAdded") - .HasColumnType("TEXT"); - - b.Property("DateLastRefreshed") - .HasColumnType("TEXT"); - - b.Property("DateLastSaved") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("EpisodeTitle") - .HasColumnType("TEXT"); - - b.Property("ExternalId") - .HasColumnType("TEXT"); - - b.Property("ExternalSeriesId") - .HasColumnType("TEXT"); - - b.Property("ExternalServiceId") - .HasColumnType("TEXT"); - - b.Property("ExtraIds") - .HasColumnType("TEXT"); - - b.Property("ExtraType") - .HasColumnType("INTEGER"); - - b.Property("ForcedSortName") - .HasColumnType("TEXT"); - - b.Property("Genres") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IndexNumber") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingSubValue") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingValue") - .HasColumnType("INTEGER"); - - b.Property("IsFolder") - .HasColumnType("INTEGER"); - - b.Property("IsInMixedFolder") - .HasColumnType("INTEGER"); - - b.Property("IsLocked") - .HasColumnType("INTEGER"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("IsRepeat") - .HasColumnType("INTEGER"); - - b.Property("IsSeries") - .HasColumnType("INTEGER"); - - b.Property("IsVirtualItem") - .HasColumnType("INTEGER"); - - b.Property("LUFS") - .HasColumnType("REAL"); - - b.Property("MediaType") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("NormalizationGain") - .HasColumnType("REAL"); - - b.Property("OfficialRating") - .HasColumnType("TEXT"); - - b.Property("OriginalTitle") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .HasColumnType("TEXT"); - - b.Property("ParentId") - .HasColumnType("TEXT"); - - b.Property("ParentIndexNumber") - .HasColumnType("INTEGER"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataCountryCode") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataLanguage") - .HasColumnType("TEXT"); - - b.Property("PremiereDate") - .HasColumnType("TEXT"); - - b.Property("PresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("PrimaryVersionId") - .HasColumnType("TEXT"); - - b.Property("ProductionLocations") - .HasColumnType("TEXT"); - - b.Property("ProductionYear") - .HasColumnType("INTEGER"); - - b.Property("RunTimeTicks") - .HasColumnType("INTEGER"); - - b.Property("SeasonId") - .HasColumnType("TEXT"); - - b.Property("SeasonName") - .HasColumnType("TEXT"); - - b.Property("SeriesId") - .HasColumnType("TEXT"); - - b.Property("SeriesName") - .HasColumnType("TEXT"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("ShowId") - .HasColumnType("TEXT"); - - b.Property("Size") - .HasColumnType("INTEGER"); - - b.Property("SortName") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Studios") - .HasColumnType("TEXT"); - - b.Property("Tagline") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT"); - - b.Property("TopParentId") - .HasColumnType("TEXT"); - - b.Property("TotalBitrate") - .HasColumnType("INTEGER"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UnratedType") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("Path"); - - b.HasIndex("PresentationUniqueKey"); - - b.HasIndex("TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - - b.HasIndex("Type", "TopParentId", "StartDate"); - - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); - - b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.ToTable("BaseItems"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Blurhash") - .HasColumnType("BLOB"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("ImageType") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemMetadataFields"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ProviderId") - .HasColumnType("TEXT"); - - b.Property("ProviderValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ProviderId"); - - b.HasIndex("ProviderId", "ProviderValue", "ItemId"); - - b.ToTable("BaseItemProviders"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemTrailerTypes"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ChapterIndex") - .HasColumnType("INTEGER"); - - b.Property("ImageDateModified") - .HasColumnType("TEXT"); - - b.Property("ImagePath") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("StartPositionTicks") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "ChapterIndex"); - - b.ToTable("Chapters"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Property("ItemValueId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CleanValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId"); - - b.HasIndex("Type", "CleanValue") - .IsUnique(); - - b.ToTable("ItemValues"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.Property("ItemValueId") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("ItemValuesMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StreamIndex") - .HasColumnType("INTEGER"); - - b.Property("AspectRatio") - .HasColumnType("TEXT"); - - b.Property("AverageFrameRate") - .HasColumnType("REAL"); - - b.Property("BitDepth") - .HasColumnType("INTEGER"); - - b.Property("BitRate") - .HasColumnType("INTEGER"); - - b.Property("BlPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("ChannelLayout") - .HasColumnType("TEXT"); - - b.Property("Channels") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("CodecTimeBase") - .HasColumnType("TEXT"); - - b.Property("ColorPrimaries") - .HasColumnType("TEXT"); - - b.Property("ColorSpace") - .HasColumnType("TEXT"); - - b.Property("ColorTransfer") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("DvBlSignalCompatibilityId") - .HasColumnType("INTEGER"); - - b.Property("DvLevel") - .HasColumnType("INTEGER"); - - b.Property("DvProfile") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMajor") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMinor") - .HasColumnType("INTEGER"); - - b.Property("ElPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IsAnamorphic") - .HasColumnType("INTEGER"); - - b.Property("IsAvc") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("IsHearingImpaired") - .HasColumnType("INTEGER"); - - b.Property("IsInterlaced") - .HasColumnType("INTEGER"); - - b.Property("KeyFrames") - .HasColumnType("TEXT"); - - b.Property("Language") - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("REAL"); - - b.Property("NalLengthSize") - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PixelFormat") - .HasColumnType("TEXT"); - - b.Property("Profile") - .HasColumnType("TEXT"); - - b.Property("RealFrameRate") - .HasColumnType("REAL"); - - b.Property("RefFrames") - .HasColumnType("INTEGER"); - - b.Property("Rotation") - .HasColumnType("INTEGER"); - - b.Property("RpuPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("SampleRate") - .HasColumnType("INTEGER"); - - b.Property("StreamType") - .HasColumnType("INTEGER"); - - b.Property("TimeBase") - .HasColumnType("TEXT"); - - b.Property("Title") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "StreamIndex"); - - b.HasIndex("StreamIndex"); - - b.HasIndex("StreamType"); - - b.HasIndex("StreamIndex", "StreamType"); - - b.HasIndex("StreamIndex", "StreamType", "Language"); - - b.ToTable("MediaStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PersonType") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name"); - - b.ToTable("Peoples"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("PeopleId") - .HasColumnType("TEXT"); - - b.Property("ListOrder") - .HasColumnType("INTEGER"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "PeopleId"); - - b.HasIndex("PeopleId"); - - b.HasIndex("ItemId", "ListOrder"); - - b.HasIndex("ItemId", "SortOrder"); - - b.ToTable("PeopleBaseItemMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalRatingScore") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalRatingSubScore") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("CustomDataKey") - .HasColumnType("TEXT"); - - b.Property("AudioStreamIndex") - .HasColumnType("INTEGER"); - - b.Property("IsFavorite") - .HasColumnType("INTEGER"); - - b.Property("LastPlayedDate") - .HasColumnType("TEXT"); - - b.Property("Likes") - .HasColumnType("INTEGER"); - - b.Property("PlayCount") - .HasColumnType("INTEGER"); - - b.Property("PlaybackPositionTicks") - .HasColumnType("INTEGER"); - - b.Property("Played") - .HasColumnType("INTEGER"); - - b.Property("Rating") - .HasColumnType("REAL"); - - b.Property("SubtitleStreamIndex") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "UserId", "CustomDataKey"); - - b.HasIndex("UserId"); - - b.HasIndex("ItemId", "UserId", "IsFavorite"); - - b.HasIndex("ItemId", "UserId", "LastPlayedDate"); - - b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks"); - - b.HasIndex("ItemId", "UserId", "Played"); - - b.ToTable("UserData"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Children") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "ParentItem") - .WithMany("ParentAncestors") - .HasForeignKey("ParentItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ParentItem"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Images") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("LockedFields") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Provider") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("TrailerTypes") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Chapters") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Database.Implementations.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("ItemValues") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.ItemValue", "ItemValue") - .WithMany("BaseItemsMap") - .HasForeignKey("ItemValueId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ItemValue"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("MediaStreams") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Peoples") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.People", "People") - .WithMany("BaseItems") - .HasForeignKey("PeopleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("People"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("UserData") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Navigation("Chapters"); - - b.Navigation("Children"); - - b.Navigation("Images"); - - b.Navigation("ItemValues"); - - b.Navigation("LockedFields"); - - b.Navigation("MediaStreams"); - - b.Navigation("ParentAncestors"); - - b.Navigation("Peoples"); - - b.Navigation("Provider"); - - b.Navigation("TrailerTypes"); - - b.Navigation("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Navigation("BaseItemsMap"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Navigation("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250331182844_FixAttachmentMigration.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250331182844_FixAttachmentMigration.cs deleted file mode 100644 index 61ec3b6a..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250331182844_FixAttachmentMigration.cs +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class FixAttachmentMigration : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "Codec", - table: "AttachmentStreamInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "Codec", - table: "AttachmentStreamInfos", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250401142247_FixAncestors.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250401142247_FixAncestors.Designer.cs deleted file mode 100644 index d7672b13..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250401142247_FixAncestors.Designer.cs +++ /dev/null @@ -1,1658 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20250401142247_FixAncestors")] - partial class FixAncestors - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.3"); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ParentItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ParentItemId"); - - b.HasIndex("ParentItemId"); - - b.ToTable("AncestorIds"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Index") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("Filename") - .HasColumnType("TEXT"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "Index"); - - b.ToTable("AttachmentStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Album") - .HasColumnType("TEXT"); - - b.Property("AlbumArtists") - .HasColumnType("TEXT"); - - b.Property("Artists") - .HasColumnType("TEXT"); - - b.Property("Audio") - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("TEXT"); - - b.Property("CleanName") - .HasColumnType("TEXT"); - - b.Property("CommunityRating") - .HasColumnType("REAL"); - - b.Property("CriticRating") - .HasColumnType("REAL"); - - b.Property("CustomRating") - .HasColumnType("TEXT"); - - b.Property("Data") - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastMediaAdded") - .HasColumnType("TEXT"); - - b.Property("DateLastRefreshed") - .HasColumnType("TEXT"); - - b.Property("DateLastSaved") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("EpisodeTitle") - .HasColumnType("TEXT"); - - b.Property("ExternalId") - .HasColumnType("TEXT"); - - b.Property("ExternalSeriesId") - .HasColumnType("TEXT"); - - b.Property("ExternalServiceId") - .HasColumnType("TEXT"); - - b.Property("ExtraIds") - .HasColumnType("TEXT"); - - b.Property("ExtraType") - .HasColumnType("INTEGER"); - - b.Property("ForcedSortName") - .HasColumnType("TEXT"); - - b.Property("Genres") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IndexNumber") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingSubValue") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingValue") - .HasColumnType("INTEGER"); - - b.Property("IsFolder") - .HasColumnType("INTEGER"); - - b.Property("IsInMixedFolder") - .HasColumnType("INTEGER"); - - b.Property("IsLocked") - .HasColumnType("INTEGER"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("IsRepeat") - .HasColumnType("INTEGER"); - - b.Property("IsSeries") - .HasColumnType("INTEGER"); - - b.Property("IsVirtualItem") - .HasColumnType("INTEGER"); - - b.Property("LUFS") - .HasColumnType("REAL"); - - b.Property("MediaType") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("NormalizationGain") - .HasColumnType("REAL"); - - b.Property("OfficialRating") - .HasColumnType("TEXT"); - - b.Property("OriginalTitle") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .HasColumnType("TEXT"); - - b.Property("ParentId") - .HasColumnType("TEXT"); - - b.Property("ParentIndexNumber") - .HasColumnType("INTEGER"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataCountryCode") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataLanguage") - .HasColumnType("TEXT"); - - b.Property("PremiereDate") - .HasColumnType("TEXT"); - - b.Property("PresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("PrimaryVersionId") - .HasColumnType("TEXT"); - - b.Property("ProductionLocations") - .HasColumnType("TEXT"); - - b.Property("ProductionYear") - .HasColumnType("INTEGER"); - - b.Property("RunTimeTicks") - .HasColumnType("INTEGER"); - - b.Property("SeasonId") - .HasColumnType("TEXT"); - - b.Property("SeasonName") - .HasColumnType("TEXT"); - - b.Property("SeriesId") - .HasColumnType("TEXT"); - - b.Property("SeriesName") - .HasColumnType("TEXT"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("ShowId") - .HasColumnType("TEXT"); - - b.Property("Size") - .HasColumnType("INTEGER"); - - b.Property("SortName") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Studios") - .HasColumnType("TEXT"); - - b.Property("Tagline") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT"); - - b.Property("TopParentId") - .HasColumnType("TEXT"); - - b.Property("TotalBitrate") - .HasColumnType("INTEGER"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UnratedType") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("Path"); - - b.HasIndex("PresentationUniqueKey"); - - b.HasIndex("TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - - b.HasIndex("Type", "TopParentId", "StartDate"); - - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); - - b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.ToTable("BaseItems"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Blurhash") - .HasColumnType("BLOB"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("ImageType") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemMetadataFields"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ProviderId") - .HasColumnType("TEXT"); - - b.Property("ProviderValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ProviderId"); - - b.HasIndex("ProviderId", "ProviderValue", "ItemId"); - - b.ToTable("BaseItemProviders"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemTrailerTypes"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ChapterIndex") - .HasColumnType("INTEGER"); - - b.Property("ImageDateModified") - .HasColumnType("TEXT"); - - b.Property("ImagePath") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("StartPositionTicks") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "ChapterIndex"); - - b.ToTable("Chapters"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Property("ItemValueId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CleanValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId"); - - b.HasIndex("Type", "CleanValue") - .IsUnique(); - - b.ToTable("ItemValues"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.Property("ItemValueId") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("ItemValuesMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StreamIndex") - .HasColumnType("INTEGER"); - - b.Property("AspectRatio") - .HasColumnType("TEXT"); - - b.Property("AverageFrameRate") - .HasColumnType("REAL"); - - b.Property("BitDepth") - .HasColumnType("INTEGER"); - - b.Property("BitRate") - .HasColumnType("INTEGER"); - - b.Property("BlPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("ChannelLayout") - .HasColumnType("TEXT"); - - b.Property("Channels") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("CodecTimeBase") - .HasColumnType("TEXT"); - - b.Property("ColorPrimaries") - .HasColumnType("TEXT"); - - b.Property("ColorSpace") - .HasColumnType("TEXT"); - - b.Property("ColorTransfer") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("DvBlSignalCompatibilityId") - .HasColumnType("INTEGER"); - - b.Property("DvLevel") - .HasColumnType("INTEGER"); - - b.Property("DvProfile") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMajor") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMinor") - .HasColumnType("INTEGER"); - - b.Property("ElPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IsAnamorphic") - .HasColumnType("INTEGER"); - - b.Property("IsAvc") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("IsHearingImpaired") - .HasColumnType("INTEGER"); - - b.Property("IsInterlaced") - .HasColumnType("INTEGER"); - - b.Property("KeyFrames") - .HasColumnType("TEXT"); - - b.Property("Language") - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("REAL"); - - b.Property("NalLengthSize") - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PixelFormat") - .HasColumnType("TEXT"); - - b.Property("Profile") - .HasColumnType("TEXT"); - - b.Property("RealFrameRate") - .HasColumnType("REAL"); - - b.Property("RefFrames") - .HasColumnType("INTEGER"); - - b.Property("Rotation") - .HasColumnType("INTEGER"); - - b.Property("RpuPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("SampleRate") - .HasColumnType("INTEGER"); - - b.Property("StreamType") - .HasColumnType("INTEGER"); - - b.Property("TimeBase") - .HasColumnType("TEXT"); - - b.Property("Title") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "StreamIndex"); - - b.HasIndex("StreamIndex"); - - b.HasIndex("StreamType"); - - b.HasIndex("StreamIndex", "StreamType"); - - b.HasIndex("StreamIndex", "StreamType", "Language"); - - b.ToTable("MediaStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PersonType") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name"); - - b.ToTable("Peoples"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("PeopleId") - .HasColumnType("TEXT"); - - b.Property("ListOrder") - .HasColumnType("INTEGER"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "PeopleId"); - - b.HasIndex("PeopleId"); - - b.HasIndex("ItemId", "ListOrder"); - - b.HasIndex("ItemId", "SortOrder"); - - b.ToTable("PeopleBaseItemMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalRatingScore") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalRatingSubScore") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("CustomDataKey") - .HasColumnType("TEXT"); - - b.Property("AudioStreamIndex") - .HasColumnType("INTEGER"); - - b.Property("IsFavorite") - .HasColumnType("INTEGER"); - - b.Property("LastPlayedDate") - .HasColumnType("TEXT"); - - b.Property("Likes") - .HasColumnType("INTEGER"); - - b.Property("PlayCount") - .HasColumnType("INTEGER"); - - b.Property("PlaybackPositionTicks") - .HasColumnType("INTEGER"); - - b.Property("Played") - .HasColumnType("INTEGER"); - - b.Property("Rating") - .HasColumnType("REAL"); - - b.Property("SubtitleStreamIndex") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "UserId", "CustomDataKey"); - - b.HasIndex("UserId"); - - b.HasIndex("ItemId", "UserId", "IsFavorite"); - - b.HasIndex("ItemId", "UserId", "LastPlayedDate"); - - b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks"); - - b.HasIndex("ItemId", "UserId", "Played"); - - b.ToTable("UserData"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Parents") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "ParentItem") - .WithMany("Children") - .HasForeignKey("ParentItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ParentItem"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Images") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("LockedFields") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Provider") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("TrailerTypes") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Chapters") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Database.Implementations.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("ItemValues") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.ItemValue", "ItemValue") - .WithMany("BaseItemsMap") - .HasForeignKey("ItemValueId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ItemValue"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("MediaStreams") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Peoples") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.People", "People") - .WithMany("BaseItems") - .HasForeignKey("PeopleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("People"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("UserData") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Navigation("Chapters"); - - b.Navigation("Children"); - - b.Navigation("Images"); - - b.Navigation("ItemValues"); - - b.Navigation("LockedFields"); - - b.Navigation("MediaStreams"); - - b.Navigation("Parents"); - - b.Navigation("Peoples"); - - b.Navigation("Provider"); - - b.Navigation("TrailerTypes"); - - b.Navigation("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Navigation("BaseItemsMap"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Navigation("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250401142247_FixAncestors.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250401142247_FixAncestors.cs deleted file mode 100644 index df212e57..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250401142247_FixAncestors.cs +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class FixAncestors : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250405075612_FixItemValuesIndices.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250405075612_FixItemValuesIndices.Designer.cs deleted file mode 100644 index 4ba3352e..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250405075612_FixItemValuesIndices.Designer.cs +++ /dev/null @@ -1,1694 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20250405075612_FixItemValuesIndices")] - partial class FixItemValuesIndices - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.3"); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ParentItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ParentItemId"); - - b.HasIndex("ParentItemId"); - - b.ToTable("AncestorIds"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Index") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("Filename") - .HasColumnType("TEXT"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "Index"); - - b.ToTable("AttachmentStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Album") - .HasColumnType("TEXT"); - - b.Property("AlbumArtists") - .HasColumnType("TEXT"); - - b.Property("Artists") - .HasColumnType("TEXT"); - - b.Property("Audio") - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("TEXT"); - - b.Property("CleanName") - .HasColumnType("TEXT"); - - b.Property("CommunityRating") - .HasColumnType("REAL"); - - b.Property("CriticRating") - .HasColumnType("REAL"); - - b.Property("CustomRating") - .HasColumnType("TEXT"); - - b.Property("Data") - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateCreatedFilesystem") - .HasColumnType("TEXT"); - - b.Property("DateLastMediaAdded") - .HasColumnType("TEXT"); - - b.Property("DateLastRefreshed") - .HasColumnType("TEXT"); - - b.Property("DateLastSaved") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("EpisodeTitle") - .HasColumnType("TEXT"); - - b.Property("ExternalId") - .HasColumnType("TEXT"); - - b.Property("ExternalSeriesId") - .HasColumnType("TEXT"); - - b.Property("ExternalServiceId") - .HasColumnType("TEXT"); - - b.Property("ExtraIds") - .HasColumnType("TEXT"); - - b.Property("ExtraType") - .HasColumnType("INTEGER"); - - b.Property("ForcedSortName") - .HasColumnType("TEXT"); - - b.Property("Genres") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IndexNumber") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingSubValue") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingValue") - .HasColumnType("INTEGER"); - - b.Property("IsFolder") - .HasColumnType("INTEGER"); - - b.Property("IsInMixedFolder") - .HasColumnType("INTEGER"); - - b.Property("IsLocked") - .HasColumnType("INTEGER"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("IsRepeat") - .HasColumnType("INTEGER"); - - b.Property("IsSeries") - .HasColumnType("INTEGER"); - - b.Property("IsVirtualItem") - .HasColumnType("INTEGER"); - - b.Property("LUFS") - .HasColumnType("REAL"); - - b.Property("MediaType") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("NormalizationGain") - .HasColumnType("REAL"); - - b.Property("OfficialRating") - .HasColumnType("TEXT"); - - b.Property("OriginalTitle") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .HasColumnType("TEXT"); - - b.Property("ParentId") - .HasColumnType("TEXT"); - - b.Property("ParentIndexNumber") - .HasColumnType("INTEGER"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataCountryCode") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataLanguage") - .HasColumnType("TEXT"); - - b.Property("PremiereDate") - .HasColumnType("TEXT"); - - b.Property("PresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("PrimaryVersionId") - .HasColumnType("TEXT"); - - b.Property("ProductionLocations") - .HasColumnType("TEXT"); - - b.Property("ProductionYear") - .HasColumnType("INTEGER"); - - b.Property("RunTimeTicks") - .HasColumnType("INTEGER"); - - b.Property("SeasonId") - .HasColumnType("TEXT"); - - b.Property("SeasonName") - .HasColumnType("TEXT"); - - b.Property("SeriesId") - .HasColumnType("TEXT"); - - b.Property("SeriesName") - .HasColumnType("TEXT"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("ShowId") - .HasColumnType("TEXT"); - - b.Property("Size") - .HasColumnType("INTEGER"); - - b.Property("SortName") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Studios") - .HasColumnType("TEXT"); - - b.Property("Tagline") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT"); - - b.Property("TopParentId") - .HasColumnType("TEXT"); - - b.Property("TotalBitrate") - .HasColumnType("INTEGER"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UnratedType") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("Path"); - - b.HasIndex("PresentationUniqueKey"); - - b.HasIndex("TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - - b.HasIndex("Type", "TopParentId", "StartDate"); - - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); - - b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.ToTable("BaseItems"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Blurhash") - .HasColumnType("BLOB"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("ImageType") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemMetadataFields"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ProviderId") - .HasColumnType("TEXT"); - - b.Property("ProviderValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ProviderId"); - - b.HasIndex("ProviderId", "ProviderValue", "ItemId"); - - b.ToTable("BaseItemProviders"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemTrailerTypes"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ChapterIndex") - .HasColumnType("INTEGER"); - - b.Property("ImageDateModified") - .HasColumnType("TEXT"); - - b.Property("ImagePath") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("StartPositionTicks") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "ChapterIndex"); - - b.ToTable("Chapters"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Property("ItemValueId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CleanValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId"); - - b.HasIndex("Type", "CleanValue"); - - b.HasIndex("Type", "Value") - .IsUnique(); - - b.ToTable("ItemValues"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.Property("ItemValueId") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("ItemValuesMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.KeyframeData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.PrimitiveCollection("KeyframeTicks") - .HasColumnType("TEXT"); - - b.Property("TotalDuration") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId"); - - b.ToTable("KeyframeData"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StreamIndex") - .HasColumnType("INTEGER"); - - b.Property("AspectRatio") - .HasColumnType("TEXT"); - - b.Property("AverageFrameRate") - .HasColumnType("REAL"); - - b.Property("BitDepth") - .HasColumnType("INTEGER"); - - b.Property("BitRate") - .HasColumnType("INTEGER"); - - b.Property("BlPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("ChannelLayout") - .HasColumnType("TEXT"); - - b.Property("Channels") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("CodecTimeBase") - .HasColumnType("TEXT"); - - b.Property("ColorPrimaries") - .HasColumnType("TEXT"); - - b.Property("ColorSpace") - .HasColumnType("TEXT"); - - b.Property("ColorTransfer") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("DvBlSignalCompatibilityId") - .HasColumnType("INTEGER"); - - b.Property("DvLevel") - .HasColumnType("INTEGER"); - - b.Property("DvProfile") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMajor") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMinor") - .HasColumnType("INTEGER"); - - b.Property("ElPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Hdr10PlusPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IsAnamorphic") - .HasColumnType("INTEGER"); - - b.Property("IsAvc") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("IsHearingImpaired") - .HasColumnType("INTEGER"); - - b.Property("IsInterlaced") - .HasColumnType("INTEGER"); - - b.Property("KeyFrames") - .HasColumnType("TEXT"); - - b.Property("Language") - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("REAL"); - - b.Property("NalLengthSize") - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PixelFormat") - .HasColumnType("TEXT"); - - b.Property("Profile") - .HasColumnType("TEXT"); - - b.Property("RealFrameRate") - .HasColumnType("REAL"); - - b.Property("RefFrames") - .HasColumnType("INTEGER"); - - b.Property("Rotation") - .HasColumnType("INTEGER"); - - b.Property("RpuPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("SampleRate") - .HasColumnType("INTEGER"); - - b.Property("StreamType") - .HasColumnType("INTEGER"); - - b.Property("TimeBase") - .HasColumnType("TEXT"); - - b.Property("Title") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "StreamIndex"); - - b.HasIndex("StreamIndex"); - - b.HasIndex("StreamType"); - - b.HasIndex("StreamIndex", "StreamType"); - - b.HasIndex("StreamIndex", "StreamType", "Language"); - - b.ToTable("MediaStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PersonType") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name"); - - b.ToTable("Peoples"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("PeopleId") - .HasColumnType("TEXT"); - - b.Property("ListOrder") - .HasColumnType("INTEGER"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "PeopleId"); - - b.HasIndex("PeopleId"); - - b.HasIndex("ItemId", "ListOrder"); - - b.HasIndex("ItemId", "SortOrder"); - - b.ToTable("PeopleBaseItemMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalRatingScore") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalRatingSubScore") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("CustomDataKey") - .HasColumnType("TEXT"); - - b.Property("AudioStreamIndex") - .HasColumnType("INTEGER"); - - b.Property("IsFavorite") - .HasColumnType("INTEGER"); - - b.Property("LastPlayedDate") - .HasColumnType("TEXT"); - - b.Property("Likes") - .HasColumnType("INTEGER"); - - b.Property("PlayCount") - .HasColumnType("INTEGER"); - - b.Property("PlaybackPositionTicks") - .HasColumnType("INTEGER"); - - b.Property("Played") - .HasColumnType("INTEGER"); - - b.Property("Rating") - .HasColumnType("REAL"); - - b.Property("SubtitleStreamIndex") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "UserId", "CustomDataKey"); - - b.HasIndex("UserId"); - - b.HasIndex("ItemId", "UserId", "IsFavorite"); - - b.HasIndex("ItemId", "UserId", "LastPlayedDate"); - - b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks"); - - b.HasIndex("ItemId", "UserId", "Played"); - - b.ToTable("UserData"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Parents") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "ParentItem") - .WithMany("Children") - .HasForeignKey("ParentItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ParentItem"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Images") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("LockedFields") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Provider") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("TrailerTypes") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Chapters") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Database.Implementations.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("ItemValues") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.ItemValue", "ItemValue") - .WithMany("BaseItemsMap") - .HasForeignKey("ItemValueId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ItemValue"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.KeyframeData", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("MediaStreams") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Peoples") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.People", "People") - .WithMany("BaseItems") - .HasForeignKey("PeopleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("People"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("UserData") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Navigation("Chapters"); - - b.Navigation("Children"); - - b.Navigation("Images"); - - b.Navigation("ItemValues"); - - b.Navigation("LockedFields"); - - b.Navigation("MediaStreams"); - - b.Navigation("Parents"); - - b.Navigation("Peoples"); - - b.Navigation("Provider"); - - b.Navigation("TrailerTypes"); - - b.Navigation("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Navigation("BaseItemsMap"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Navigation("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250405075612_FixItemValuesIndices.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250405075612_FixItemValuesIndices.cs deleted file mode 100644 index 800a56ba..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250405075612_FixItemValuesIndices.cs +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class FixItemValuesIndices : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_ItemValues_Type_CleanValue", - table: "ItemValues"); - - migrationBuilder.CreateIndex( - name: "IX_ItemValues_Type_CleanValue", - table: "ItemValues", - columns: new[] { "Type", "CleanValue" }); - - migrationBuilder.CreateIndex( - name: "IX_ItemValues_Type_Value", - table: "ItemValues", - columns: new[] { "Type", "Value" }, - unique: true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropIndex( - name: "IX_ItemValues_Type_CleanValue", - table: "ItemValues"); - - migrationBuilder.DropIndex( - name: "IX_ItemValues_Type_Value", - table: "ItemValues"); - - migrationBuilder.CreateIndex( - name: "IX_ItemValues_Type_CleanValue", - table: "ItemValues", - columns: new[] { "Type", "CleanValue" }, - unique: true); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250609115616_DetachUserDataInsteadOfDelete.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250609115616_DetachUserDataInsteadOfDelete.Designer.cs deleted file mode 100644 index 253e67e2..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250609115616_DetachUserDataInsteadOfDelete.Designer.cs +++ /dev/null @@ -1,1693 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20250609115616_DetachUserDataInsteadOfDelete")] - partial class DetachUserDataInsteadOfDelete - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.5"); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ParentItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ParentItemId"); - - b.HasIndex("ParentItemId"); - - b.ToTable("AncestorIds"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Index") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("Filename") - .HasColumnType("TEXT"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "Index"); - - b.ToTable("AttachmentStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Album") - .HasColumnType("TEXT"); - - b.Property("AlbumArtists") - .HasColumnType("TEXT"); - - b.Property("Artists") - .HasColumnType("TEXT"); - - b.Property("Audio") - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("TEXT"); - - b.Property("CleanName") - .HasColumnType("TEXT"); - - b.Property("CommunityRating") - .HasColumnType("REAL"); - - b.Property("CriticRating") - .HasColumnType("REAL"); - - b.Property("CustomRating") - .HasColumnType("TEXT"); - - b.Property("Data") - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastMediaAdded") - .HasColumnType("TEXT"); - - b.Property("DateLastRefreshed") - .HasColumnType("TEXT"); - - b.Property("DateLastSaved") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("EpisodeTitle") - .HasColumnType("TEXT"); - - b.Property("ExternalId") - .HasColumnType("TEXT"); - - b.Property("ExternalSeriesId") - .HasColumnType("TEXT"); - - b.Property("ExternalServiceId") - .HasColumnType("TEXT"); - - b.Property("ExtraIds") - .HasColumnType("TEXT"); - - b.Property("ExtraType") - .HasColumnType("INTEGER"); - - b.Property("ForcedSortName") - .HasColumnType("TEXT"); - - b.Property("Genres") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IndexNumber") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingSubValue") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingValue") - .HasColumnType("INTEGER"); - - b.Property("IsFolder") - .HasColumnType("INTEGER"); - - b.Property("IsInMixedFolder") - .HasColumnType("INTEGER"); - - b.Property("IsLocked") - .HasColumnType("INTEGER"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("IsRepeat") - .HasColumnType("INTEGER"); - - b.Property("IsSeries") - .HasColumnType("INTEGER"); - - b.Property("IsVirtualItem") - .HasColumnType("INTEGER"); - - b.Property("LUFS") - .HasColumnType("REAL"); - - b.Property("MediaType") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("NormalizationGain") - .HasColumnType("REAL"); - - b.Property("OfficialRating") - .HasColumnType("TEXT"); - - b.Property("OriginalTitle") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .HasColumnType("TEXT"); - - b.Property("ParentId") - .HasColumnType("TEXT"); - - b.Property("ParentIndexNumber") - .HasColumnType("INTEGER"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataCountryCode") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataLanguage") - .HasColumnType("TEXT"); - - b.Property("PremiereDate") - .HasColumnType("TEXT"); - - b.Property("PresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("PrimaryVersionId") - .HasColumnType("TEXT"); - - b.Property("ProductionLocations") - .HasColumnType("TEXT"); - - b.Property("ProductionYear") - .HasColumnType("INTEGER"); - - b.Property("RunTimeTicks") - .HasColumnType("INTEGER"); - - b.Property("SeasonId") - .HasColumnType("TEXT"); - - b.Property("SeasonName") - .HasColumnType("TEXT"); - - b.Property("SeriesId") - .HasColumnType("TEXT"); - - b.Property("SeriesName") - .HasColumnType("TEXT"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("ShowId") - .HasColumnType("TEXT"); - - b.Property("Size") - .HasColumnType("INTEGER"); - - b.Property("SortName") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Studios") - .HasColumnType("TEXT"); - - b.Property("Tagline") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT"); - - b.Property("TopParentId") - .HasColumnType("TEXT"); - - b.Property("TotalBitrate") - .HasColumnType("INTEGER"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UnratedType") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("Path"); - - b.HasIndex("PresentationUniqueKey"); - - b.HasIndex("TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - - b.HasIndex("Type", "TopParentId", "StartDate"); - - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); - - b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.ToTable("BaseItems"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Blurhash") - .HasColumnType("BLOB"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("ImageType") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemMetadataFields"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ProviderId") - .HasColumnType("TEXT"); - - b.Property("ProviderValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ProviderId"); - - b.HasIndex("ProviderId", "ProviderValue", "ItemId"); - - b.ToTable("BaseItemProviders"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemTrailerTypes"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ChapterIndex") - .HasColumnType("INTEGER"); - - b.Property("ImageDateModified") - .HasColumnType("TEXT"); - - b.Property("ImagePath") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("StartPositionTicks") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "ChapterIndex"); - - b.ToTable("Chapters"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Property("ItemValueId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CleanValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId"); - - b.HasIndex("Type", "CleanValue"); - - b.HasIndex("Type", "Value") - .IsUnique(); - - b.ToTable("ItemValues"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.Property("ItemValueId") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("ItemValuesMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.KeyframeData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.PrimitiveCollection("KeyframeTicks") - .HasColumnType("TEXT"); - - b.Property("TotalDuration") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId"); - - b.ToTable("KeyframeData"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StreamIndex") - .HasColumnType("INTEGER"); - - b.Property("AspectRatio") - .HasColumnType("TEXT"); - - b.Property("AverageFrameRate") - .HasColumnType("REAL"); - - b.Property("BitDepth") - .HasColumnType("INTEGER"); - - b.Property("BitRate") - .HasColumnType("INTEGER"); - - b.Property("BlPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("ChannelLayout") - .HasColumnType("TEXT"); - - b.Property("Channels") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("CodecTimeBase") - .HasColumnType("TEXT"); - - b.Property("ColorPrimaries") - .HasColumnType("TEXT"); - - b.Property("ColorSpace") - .HasColumnType("TEXT"); - - b.Property("ColorTransfer") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("DvBlSignalCompatibilityId") - .HasColumnType("INTEGER"); - - b.Property("DvLevel") - .HasColumnType("INTEGER"); - - b.Property("DvProfile") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMajor") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMinor") - .HasColumnType("INTEGER"); - - b.Property("ElPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Hdr10PlusPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IsAnamorphic") - .HasColumnType("INTEGER"); - - b.Property("IsAvc") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("IsHearingImpaired") - .HasColumnType("INTEGER"); - - b.Property("IsInterlaced") - .HasColumnType("INTEGER"); - - b.Property("KeyFrames") - .HasColumnType("TEXT"); - - b.Property("Language") - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("REAL"); - - b.Property("NalLengthSize") - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PixelFormat") - .HasColumnType("TEXT"); - - b.Property("Profile") - .HasColumnType("TEXT"); - - b.Property("RealFrameRate") - .HasColumnType("REAL"); - - b.Property("RefFrames") - .HasColumnType("INTEGER"); - - b.Property("Rotation") - .HasColumnType("INTEGER"); - - b.Property("RpuPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("SampleRate") - .HasColumnType("INTEGER"); - - b.Property("StreamType") - .HasColumnType("INTEGER"); - - b.Property("TimeBase") - .HasColumnType("TEXT"); - - b.Property("Title") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "StreamIndex"); - - b.HasIndex("StreamIndex"); - - b.HasIndex("StreamType"); - - b.HasIndex("StreamIndex", "StreamType"); - - b.HasIndex("StreamIndex", "StreamType", "Language"); - - b.ToTable("MediaStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PersonType") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name"); - - b.ToTable("Peoples"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("PeopleId") - .HasColumnType("TEXT"); - - b.Property("ListOrder") - .HasColumnType("INTEGER"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "PeopleId"); - - b.HasIndex("PeopleId"); - - b.HasIndex("ItemId", "ListOrder"); - - b.HasIndex("ItemId", "SortOrder"); - - b.ToTable("PeopleBaseItemMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalRatingScore") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalRatingSubScore") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("CustomDataKey") - .HasColumnType("TEXT"); - - b.Property("AudioStreamIndex") - .HasColumnType("INTEGER"); - - b.Property("IsFavorite") - .HasColumnType("INTEGER"); - - b.Property("LastPlayedDate") - .HasColumnType("TEXT"); - - b.Property("Likes") - .HasColumnType("INTEGER"); - - b.Property("PlayCount") - .HasColumnType("INTEGER"); - - b.Property("PlaybackPositionTicks") - .HasColumnType("INTEGER"); - - b.Property("Played") - .HasColumnType("INTEGER"); - - b.Property("Rating") - .HasColumnType("REAL"); - - b.Property("RetentionDate") - .HasColumnType("TEXT"); - - b.Property("SubtitleStreamIndex") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "UserId", "CustomDataKey"); - - b.HasIndex("UserId"); - - b.HasIndex("ItemId", "UserId", "IsFavorite"); - - b.HasIndex("ItemId", "UserId", "LastPlayedDate"); - - b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks"); - - b.HasIndex("ItemId", "UserId", "Played"); - - b.ToTable("UserData"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Parents") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "ParentItem") - .WithMany("Children") - .HasForeignKey("ParentItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ParentItem"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Images") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("LockedFields") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Provider") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("TrailerTypes") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Chapters") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Database.Implementations.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("ItemValues") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.ItemValue", "ItemValue") - .WithMany("BaseItemsMap") - .HasForeignKey("ItemValueId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ItemValue"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.KeyframeData", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("MediaStreams") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Peoples") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.People", "People") - .WithMany("BaseItems") - .HasForeignKey("PeopleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("People"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("UserData") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.SetNull); - - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Navigation("Chapters"); - - b.Navigation("Children"); - - b.Navigation("Images"); - - b.Navigation("ItemValues"); - - b.Navigation("LockedFields"); - - b.Navigation("MediaStreams"); - - b.Navigation("Parents"); - - b.Navigation("Peoples"); - - b.Navigation("Provider"); - - b.Navigation("TrailerTypes"); - - b.Navigation("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Navigation("BaseItemsMap"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Navigation("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250609115616_DetachUserDataInsteadOfDelete.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250609115616_DetachUserDataInsteadOfDelete.cs deleted file mode 100644 index 82eb4cf4..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250609115616_DetachUserDataInsteadOfDelete.cs +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using System; - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class DetachUserDataInsteadOfDelete : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "RetentionDate", - table: "UserData", - type: "TEXT", - nullable: true); - - migrationBuilder.InsertData( - table: "BaseItems", - columns: new[] { "Id", "Album", "AlbumArtists", "Artists", "Audio", "ChannelId", "CleanName", "CommunityRating", "CriticRating", "CustomRating", "Data", "DateCreated", "DateLastMediaAdded", "DateLastRefreshed", "DateLastSaved", "DateModified", "EndDate", "EpisodeTitle", "ExternalId", "ExternalSeriesId", "ExternalServiceId", "ExtraIds", "ExtraType", "ForcedSortName", "Genres", "Height", "IndexNumber", "InheritedParentalRatingSubValue", "InheritedParentalRatingValue", "IsFolder", "IsInMixedFolder", "IsLocked", "IsMovie", "IsRepeat", "IsSeries", "IsVirtualItem", "LUFS", "MediaType", "Name", "NormalizationGain", "OfficialRating", "OriginalTitle", "Overview", "OwnerId", "ParentId", "ParentIndexNumber", "Path", "PreferredMetadataCountryCode", "PreferredMetadataLanguage", "PremiereDate", "PresentationUniqueKey", "PrimaryVersionId", "ProductionLocations", "ProductionYear", "RunTimeTicks", "SeasonId", "SeasonName", "SeriesId", "SeriesName", "SeriesPresentationUniqueKey", "ShowId", "Size", "SortName", "StartDate", "Studios", "Tagline", "Tags", "TopParentId", "TotalBitrate", "Type", "UnratedType", "Width" }, - values: new object[] { new Guid("00000000-0000-0000-0000-000000000001"), null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, false, false, false, false, false, false, false, null, null, "This is a placeholder item for UserData that has been detacted from its original item", null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, "PLACEHOLDER", null, null }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "RetentionDate", - table: "UserData"); - - migrationBuilder.DeleteData( - table: "BaseItems", - keyColumn: "Id", - keyValue: new Guid("00000000-0000-0000-0000-000000000001")); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250622170802_BaseItemImageInfoDateModifiedNullable.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250622170802_BaseItemImageInfoDateModifiedNullable.Designer.cs deleted file mode 100644 index a0622c14..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250622170802_BaseItemImageInfoDateModifiedNullable.Designer.cs +++ /dev/null @@ -1,1709 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20250622170802_BaseItemImageInfoDateModifiedNullable")] - partial class BaseItemImageInfoDateModifiedNullable - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.6"); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ParentItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ParentItemId"); - - b.HasIndex("ParentItemId"); - - b.ToTable("AncestorIds"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Index") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("Filename") - .HasColumnType("TEXT"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "Index"); - - b.ToTable("AttachmentStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Album") - .HasColumnType("TEXT"); - - b.Property("AlbumArtists") - .HasColumnType("TEXT"); - - b.Property("Artists") - .HasColumnType("TEXT"); - - b.Property("Audio") - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("TEXT"); - - b.Property("CleanName") - .HasColumnType("TEXT"); - - b.Property("CommunityRating") - .HasColumnType("REAL"); - - b.Property("CriticRating") - .HasColumnType("REAL"); - - b.Property("CustomRating") - .HasColumnType("TEXT"); - - b.Property("Data") - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastMediaAdded") - .HasColumnType("TEXT"); - - b.Property("DateLastRefreshed") - .HasColumnType("TEXT"); - - b.Property("DateLastSaved") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("EpisodeTitle") - .HasColumnType("TEXT"); - - b.Property("ExternalId") - .HasColumnType("TEXT"); - - b.Property("ExternalSeriesId") - .HasColumnType("TEXT"); - - b.Property("ExternalServiceId") - .HasColumnType("TEXT"); - - b.Property("ExtraIds") - .HasColumnType("TEXT"); - - b.Property("ExtraType") - .HasColumnType("INTEGER"); - - b.Property("ForcedSortName") - .HasColumnType("TEXT"); - - b.Property("Genres") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IndexNumber") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingSubValue") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingValue") - .HasColumnType("INTEGER"); - - b.Property("IsFolder") - .HasColumnType("INTEGER"); - - b.Property("IsInMixedFolder") - .HasColumnType("INTEGER"); - - b.Property("IsLocked") - .HasColumnType("INTEGER"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("IsRepeat") - .HasColumnType("INTEGER"); - - b.Property("IsSeries") - .HasColumnType("INTEGER"); - - b.Property("IsVirtualItem") - .HasColumnType("INTEGER"); - - b.Property("LUFS") - .HasColumnType("REAL"); - - b.Property("MediaType") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("NormalizationGain") - .HasColumnType("REAL"); - - b.Property("OfficialRating") - .HasColumnType("TEXT"); - - b.Property("OriginalTitle") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .HasColumnType("TEXT"); - - b.Property("ParentId") - .HasColumnType("TEXT"); - - b.Property("ParentIndexNumber") - .HasColumnType("INTEGER"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataCountryCode") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataLanguage") - .HasColumnType("TEXT"); - - b.Property("PremiereDate") - .HasColumnType("TEXT"); - - b.Property("PresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("PrimaryVersionId") - .HasColumnType("TEXT"); - - b.Property("ProductionLocations") - .HasColumnType("TEXT"); - - b.Property("ProductionYear") - .HasColumnType("INTEGER"); - - b.Property("RunTimeTicks") - .HasColumnType("INTEGER"); - - b.Property("SeasonId") - .HasColumnType("TEXT"); - - b.Property("SeasonName") - .HasColumnType("TEXT"); - - b.Property("SeriesId") - .HasColumnType("TEXT"); - - b.Property("SeriesName") - .HasColumnType("TEXT"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("ShowId") - .HasColumnType("TEXT"); - - b.Property("Size") - .HasColumnType("INTEGER"); - - b.Property("SortName") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Studios") - .HasColumnType("TEXT"); - - b.Property("Tagline") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT"); - - b.Property("TopParentId") - .HasColumnType("TEXT"); - - b.Property("TotalBitrate") - .HasColumnType("INTEGER"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UnratedType") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("Path"); - - b.HasIndex("PresentationUniqueKey"); - - b.HasIndex("TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - - b.HasIndex("Type", "TopParentId", "StartDate"); - - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); - - b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.ToTable("BaseItems"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - - b.HasData( - new - { - Id = new Guid("00000000-0000-0000-0000-000000000001"), - IsFolder = false, - IsInMixedFolder = false, - IsLocked = false, - IsMovie = false, - IsRepeat = false, - IsSeries = false, - IsVirtualItem = false, - Name = "This is a placeholder item for UserData that has been detacted from its original item", - Type = "PLACEHOLDER" - }); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Blurhash") - .HasColumnType("BLOB"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("ImageType") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemMetadataFields"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ProviderId") - .HasColumnType("TEXT"); - - b.Property("ProviderValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ProviderId"); - - b.HasIndex("ProviderId", "ProviderValue", "ItemId"); - - b.ToTable("BaseItemProviders"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemTrailerTypes"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ChapterIndex") - .HasColumnType("INTEGER"); - - b.Property("ImageDateModified") - .HasColumnType("TEXT"); - - b.Property("ImagePath") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("StartPositionTicks") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "ChapterIndex"); - - b.ToTable("Chapters"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Property("ItemValueId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CleanValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId"); - - b.HasIndex("Type", "CleanValue"); - - b.HasIndex("Type", "Value") - .IsUnique(); - - b.ToTable("ItemValues"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.Property("ItemValueId") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("ItemValuesMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.KeyframeData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.PrimitiveCollection("KeyframeTicks") - .HasColumnType("TEXT"); - - b.Property("TotalDuration") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId"); - - b.ToTable("KeyframeData"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StreamIndex") - .HasColumnType("INTEGER"); - - b.Property("AspectRatio") - .HasColumnType("TEXT"); - - b.Property("AverageFrameRate") - .HasColumnType("REAL"); - - b.Property("BitDepth") - .HasColumnType("INTEGER"); - - b.Property("BitRate") - .HasColumnType("INTEGER"); - - b.Property("BlPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("ChannelLayout") - .HasColumnType("TEXT"); - - b.Property("Channels") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("CodecTimeBase") - .HasColumnType("TEXT"); - - b.Property("ColorPrimaries") - .HasColumnType("TEXT"); - - b.Property("ColorSpace") - .HasColumnType("TEXT"); - - b.Property("ColorTransfer") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("DvBlSignalCompatibilityId") - .HasColumnType("INTEGER"); - - b.Property("DvLevel") - .HasColumnType("INTEGER"); - - b.Property("DvProfile") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMajor") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMinor") - .HasColumnType("INTEGER"); - - b.Property("ElPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Hdr10PlusPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IsAnamorphic") - .HasColumnType("INTEGER"); - - b.Property("IsAvc") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("IsHearingImpaired") - .HasColumnType("INTEGER"); - - b.Property("IsInterlaced") - .HasColumnType("INTEGER"); - - b.Property("KeyFrames") - .HasColumnType("TEXT"); - - b.Property("Language") - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("REAL"); - - b.Property("NalLengthSize") - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PixelFormat") - .HasColumnType("TEXT"); - - b.Property("Profile") - .HasColumnType("TEXT"); - - b.Property("RealFrameRate") - .HasColumnType("REAL"); - - b.Property("RefFrames") - .HasColumnType("INTEGER"); - - b.Property("Rotation") - .HasColumnType("INTEGER"); - - b.Property("RpuPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("SampleRate") - .HasColumnType("INTEGER"); - - b.Property("StreamType") - .HasColumnType("INTEGER"); - - b.Property("TimeBase") - .HasColumnType("TEXT"); - - b.Property("Title") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "StreamIndex"); - - b.HasIndex("StreamIndex"); - - b.HasIndex("StreamType"); - - b.HasIndex("StreamIndex", "StreamType"); - - b.HasIndex("StreamIndex", "StreamType", "Language"); - - b.ToTable("MediaStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PersonType") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name"); - - b.ToTable("Peoples"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("PeopleId") - .HasColumnType("TEXT"); - - b.Property("ListOrder") - .HasColumnType("INTEGER"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "PeopleId"); - - b.HasIndex("PeopleId"); - - b.HasIndex("ItemId", "ListOrder"); - - b.HasIndex("ItemId", "SortOrder"); - - b.ToTable("PeopleBaseItemMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalRatingScore") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalRatingSubScore") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("CustomDataKey") - .HasColumnType("TEXT"); - - b.Property("AudioStreamIndex") - .HasColumnType("INTEGER"); - - b.Property("IsFavorite") - .HasColumnType("INTEGER"); - - b.Property("LastPlayedDate") - .HasColumnType("TEXT"); - - b.Property("Likes") - .HasColumnType("INTEGER"); - - b.Property("PlayCount") - .HasColumnType("INTEGER"); - - b.Property("PlaybackPositionTicks") - .HasColumnType("INTEGER"); - - b.Property("Played") - .HasColumnType("INTEGER"); - - b.Property("Rating") - .HasColumnType("REAL"); - - b.Property("RetentionDate") - .HasColumnType("TEXT"); - - b.Property("SubtitleStreamIndex") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "UserId", "CustomDataKey"); - - b.HasIndex("UserId"); - - b.HasIndex("ItemId", "UserId", "IsFavorite"); - - b.HasIndex("ItemId", "UserId", "LastPlayedDate"); - - b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks"); - - b.HasIndex("ItemId", "UserId", "Played"); - - b.ToTable("UserData"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Parents") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "ParentItem") - .WithMany("Children") - .HasForeignKey("ParentItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ParentItem"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Images") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("LockedFields") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Provider") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("TrailerTypes") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Chapters") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Database.Implementations.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("ItemValues") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.ItemValue", "ItemValue") - .WithMany("BaseItemsMap") - .HasForeignKey("ItemValueId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ItemValue"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.KeyframeData", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("MediaStreams") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Peoples") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.People", "People") - .WithMany("BaseItems") - .HasForeignKey("PeopleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("People"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("UserData") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Navigation("Chapters"); - - b.Navigation("Children"); - - b.Navigation("Images"); - - b.Navigation("ItemValues"); - - b.Navigation("LockedFields"); - - b.Navigation("MediaStreams"); - - b.Navigation("Parents"); - - b.Navigation("Peoples"); - - b.Navigation("Provider"); - - b.Navigation("TrailerTypes"); - - b.Navigation("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Navigation("BaseItemsMap"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Navigation("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250622170802_BaseItemImageInfoDateModifiedNullable.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250622170802_BaseItemImageInfoDateModifiedNullable.cs deleted file mode 100644 index a282492c..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250622170802_BaseItemImageInfoDateModifiedNullable.cs +++ /dev/null @@ -1,41 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using System; - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class BaseItemImageInfoDateModifiedNullable : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "DateModified", - table: "BaseItemImageInfos", - type: "TEXT", - nullable: true, - oldClrType: typeof(DateTime), - oldType: "TEXT"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "DateModified", - table: "BaseItemImageInfos", - type: "TEXT", - nullable: false, - defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified), - oldClrType: typeof(DateTime), - oldType: "TEXT", - oldNullable: true); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250714044826_ResetJournalMode.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250714044826_ResetJournalMode.Designer.cs deleted file mode 100644 index 3ceb907c..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250714044826_ResetJournalMode.Designer.cs +++ /dev/null @@ -1,1709 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20250714044826_ResetJournalMode")] - partial class ResetJournalMode - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.7"); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ParentItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ParentItemId"); - - b.HasIndex("ParentItemId"); - - b.ToTable("AncestorIds"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Index") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("Filename") - .HasColumnType("TEXT"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "Index"); - - b.ToTable("AttachmentStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Album") - .HasColumnType("TEXT"); - - b.Property("AlbumArtists") - .HasColumnType("TEXT"); - - b.Property("Artists") - .HasColumnType("TEXT"); - - b.Property("Audio") - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("TEXT"); - - b.Property("CleanName") - .HasColumnType("TEXT"); - - b.Property("CommunityRating") - .HasColumnType("REAL"); - - b.Property("CriticRating") - .HasColumnType("REAL"); - - b.Property("CustomRating") - .HasColumnType("TEXT"); - - b.Property("Data") - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastMediaAdded") - .HasColumnType("TEXT"); - - b.Property("DateLastRefreshed") - .HasColumnType("TEXT"); - - b.Property("DateLastSaved") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("EpisodeTitle") - .HasColumnType("TEXT"); - - b.Property("ExternalId") - .HasColumnType("TEXT"); - - b.Property("ExternalSeriesId") - .HasColumnType("TEXT"); - - b.Property("ExternalServiceId") - .HasColumnType("TEXT"); - - b.Property("ExtraIds") - .HasColumnType("TEXT"); - - b.Property("ExtraType") - .HasColumnType("INTEGER"); - - b.Property("ForcedSortName") - .HasColumnType("TEXT"); - - b.Property("Genres") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IndexNumber") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingSubValue") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingValue") - .HasColumnType("INTEGER"); - - b.Property("IsFolder") - .HasColumnType("INTEGER"); - - b.Property("IsInMixedFolder") - .HasColumnType("INTEGER"); - - b.Property("IsLocked") - .HasColumnType("INTEGER"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("IsRepeat") - .HasColumnType("INTEGER"); - - b.Property("IsSeries") - .HasColumnType("INTEGER"); - - b.Property("IsVirtualItem") - .HasColumnType("INTEGER"); - - b.Property("LUFS") - .HasColumnType("REAL"); - - b.Property("MediaType") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("NormalizationGain") - .HasColumnType("REAL"); - - b.Property("OfficialRating") - .HasColumnType("TEXT"); - - b.Property("OriginalTitle") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .HasColumnType("TEXT"); - - b.Property("ParentId") - .HasColumnType("TEXT"); - - b.Property("ParentIndexNumber") - .HasColumnType("INTEGER"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataCountryCode") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataLanguage") - .HasColumnType("TEXT"); - - b.Property("PremiereDate") - .HasColumnType("TEXT"); - - b.Property("PresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("PrimaryVersionId") - .HasColumnType("TEXT"); - - b.Property("ProductionLocations") - .HasColumnType("TEXT"); - - b.Property("ProductionYear") - .HasColumnType("INTEGER"); - - b.Property("RunTimeTicks") - .HasColumnType("INTEGER"); - - b.Property("SeasonId") - .HasColumnType("TEXT"); - - b.Property("SeasonName") - .HasColumnType("TEXT"); - - b.Property("SeriesId") - .HasColumnType("TEXT"); - - b.Property("SeriesName") - .HasColumnType("TEXT"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("ShowId") - .HasColumnType("TEXT"); - - b.Property("Size") - .HasColumnType("INTEGER"); - - b.Property("SortName") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Studios") - .HasColumnType("TEXT"); - - b.Property("Tagline") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT"); - - b.Property("TopParentId") - .HasColumnType("TEXT"); - - b.Property("TotalBitrate") - .HasColumnType("INTEGER"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UnratedType") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("Path"); - - b.HasIndex("PresentationUniqueKey"); - - b.HasIndex("TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - - b.HasIndex("Type", "TopParentId", "StartDate"); - - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); - - b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.ToTable("BaseItems"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - - b.HasData( - new - { - Id = new Guid("00000000-0000-0000-0000-000000000001"), - IsFolder = false, - IsInMixedFolder = false, - IsLocked = false, - IsMovie = false, - IsRepeat = false, - IsSeries = false, - IsVirtualItem = false, - Name = "This is a placeholder item for UserData that has been detacted from its original item", - Type = "PLACEHOLDER" - }); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Blurhash") - .HasColumnType("BLOB"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("ImageType") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemMetadataFields"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ProviderId") - .HasColumnType("TEXT"); - - b.Property("ProviderValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ProviderId"); - - b.HasIndex("ProviderId", "ProviderValue", "ItemId"); - - b.ToTable("BaseItemProviders"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemTrailerTypes"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ChapterIndex") - .HasColumnType("INTEGER"); - - b.Property("ImageDateModified") - .HasColumnType("TEXT"); - - b.Property("ImagePath") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("StartPositionTicks") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "ChapterIndex"); - - b.ToTable("Chapters"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Property("ItemValueId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CleanValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId"); - - b.HasIndex("Type", "CleanValue"); - - b.HasIndex("Type", "Value") - .IsUnique(); - - b.ToTable("ItemValues"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.Property("ItemValueId") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("ItemValuesMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.KeyframeData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.PrimitiveCollection("KeyframeTicks") - .HasColumnType("TEXT"); - - b.Property("TotalDuration") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId"); - - b.ToTable("KeyframeData"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StreamIndex") - .HasColumnType("INTEGER"); - - b.Property("AspectRatio") - .HasColumnType("TEXT"); - - b.Property("AverageFrameRate") - .HasColumnType("REAL"); - - b.Property("BitDepth") - .HasColumnType("INTEGER"); - - b.Property("BitRate") - .HasColumnType("INTEGER"); - - b.Property("BlPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("ChannelLayout") - .HasColumnType("TEXT"); - - b.Property("Channels") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("CodecTimeBase") - .HasColumnType("TEXT"); - - b.Property("ColorPrimaries") - .HasColumnType("TEXT"); - - b.Property("ColorSpace") - .HasColumnType("TEXT"); - - b.Property("ColorTransfer") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("DvBlSignalCompatibilityId") - .HasColumnType("INTEGER"); - - b.Property("DvLevel") - .HasColumnType("INTEGER"); - - b.Property("DvProfile") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMajor") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMinor") - .HasColumnType("INTEGER"); - - b.Property("ElPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Hdr10PlusPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IsAnamorphic") - .HasColumnType("INTEGER"); - - b.Property("IsAvc") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("IsHearingImpaired") - .HasColumnType("INTEGER"); - - b.Property("IsInterlaced") - .HasColumnType("INTEGER"); - - b.Property("KeyFrames") - .HasColumnType("TEXT"); - - b.Property("Language") - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("REAL"); - - b.Property("NalLengthSize") - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PixelFormat") - .HasColumnType("TEXT"); - - b.Property("Profile") - .HasColumnType("TEXT"); - - b.Property("RealFrameRate") - .HasColumnType("REAL"); - - b.Property("RefFrames") - .HasColumnType("INTEGER"); - - b.Property("Rotation") - .HasColumnType("INTEGER"); - - b.Property("RpuPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("SampleRate") - .HasColumnType("INTEGER"); - - b.Property("StreamType") - .HasColumnType("INTEGER"); - - b.Property("TimeBase") - .HasColumnType("TEXT"); - - b.Property("Title") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "StreamIndex"); - - b.HasIndex("StreamIndex"); - - b.HasIndex("StreamType"); - - b.HasIndex("StreamIndex", "StreamType"); - - b.HasIndex("StreamIndex", "StreamType", "Language"); - - b.ToTable("MediaStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PersonType") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name"); - - b.ToTable("Peoples"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("PeopleId") - .HasColumnType("TEXT"); - - b.Property("ListOrder") - .HasColumnType("INTEGER"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "PeopleId"); - - b.HasIndex("PeopleId"); - - b.HasIndex("ItemId", "ListOrder"); - - b.HasIndex("ItemId", "SortOrder"); - - b.ToTable("PeopleBaseItemMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalRatingScore") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalRatingSubScore") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("CustomDataKey") - .HasColumnType("TEXT"); - - b.Property("AudioStreamIndex") - .HasColumnType("INTEGER"); - - b.Property("IsFavorite") - .HasColumnType("INTEGER"); - - b.Property("LastPlayedDate") - .HasColumnType("TEXT"); - - b.Property("Likes") - .HasColumnType("INTEGER"); - - b.Property("PlayCount") - .HasColumnType("INTEGER"); - - b.Property("PlaybackPositionTicks") - .HasColumnType("INTEGER"); - - b.Property("Played") - .HasColumnType("INTEGER"); - - b.Property("Rating") - .HasColumnType("REAL"); - - b.Property("RetentionDate") - .HasColumnType("TEXT"); - - b.Property("SubtitleStreamIndex") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "UserId", "CustomDataKey"); - - b.HasIndex("UserId"); - - b.HasIndex("ItemId", "UserId", "IsFavorite"); - - b.HasIndex("ItemId", "UserId", "LastPlayedDate"); - - b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks"); - - b.HasIndex("ItemId", "UserId", "Played"); - - b.ToTable("UserData"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Parents") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "ParentItem") - .WithMany("Children") - .HasForeignKey("ParentItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ParentItem"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Images") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("LockedFields") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Provider") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("TrailerTypes") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Chapters") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Database.Implementations.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("ItemValues") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.ItemValue", "ItemValue") - .WithMany("BaseItemsMap") - .HasForeignKey("ItemValueId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ItemValue"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.KeyframeData", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("MediaStreams") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Peoples") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.People", "People") - .WithMany("BaseItems") - .HasForeignKey("PeopleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("People"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("UserData") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Navigation("Chapters"); - - b.Navigation("Children"); - - b.Navigation("Images"); - - b.Navigation("ItemValues"); - - b.Navigation("LockedFields"); - - b.Navigation("MediaStreams"); - - b.Navigation("Parents"); - - b.Navigation("Peoples"); - - b.Navigation("Provider"); - - b.Navigation("TrailerTypes"); - - b.Navigation("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Navigation("BaseItemsMap"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Navigation("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250714044826_ResetJournalMode.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250714044826_ResetJournalMode.cs deleted file mode 100644 index b90620e0..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250714044826_ResetJournalMode.cs +++ /dev/null @@ -1,26 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class ResetJournalMode : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - // Resets journal mode to WAL for users that have created their database during 10.11-RC1 or 2 - migrationBuilder.Sql("PRAGMA journal_mode = 'WAL';", true); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250913211637_AddProperParentChildRelationBaseItemWithCascade.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250913211637_AddProperParentChildRelationBaseItemWithCascade.Designer.cs deleted file mode 100644 index 5c5464a4..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250913211637_AddProperParentChildRelationBaseItemWithCascade.Designer.cs +++ /dev/null @@ -1,1721 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20250913211637_AddProperParentChildRelationBaseItemWithCascade")] - partial class AddProperParentChildRelationBaseItemWithCascade - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.9"); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ParentItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ParentItemId"); - - b.HasIndex("ParentItemId"); - - b.ToTable("AncestorIds"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Index") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("Filename") - .HasColumnType("TEXT"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "Index"); - - b.ToTable("AttachmentStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Album") - .HasColumnType("TEXT"); - - b.Property("AlbumArtists") - .HasColumnType("TEXT"); - - b.Property("Artists") - .HasColumnType("TEXT"); - - b.Property("Audio") - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("TEXT"); - - b.Property("CleanName") - .HasColumnType("TEXT"); - - b.Property("CommunityRating") - .HasColumnType("REAL"); - - b.Property("CriticRating") - .HasColumnType("REAL"); - - b.Property("CustomRating") - .HasColumnType("TEXT"); - - b.Property("Data") - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastMediaAdded") - .HasColumnType("TEXT"); - - b.Property("DateLastRefreshed") - .HasColumnType("TEXT"); - - b.Property("DateLastSaved") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("EpisodeTitle") - .HasColumnType("TEXT"); - - b.Property("ExternalId") - .HasColumnType("TEXT"); - - b.Property("ExternalSeriesId") - .HasColumnType("TEXT"); - - b.Property("ExternalServiceId") - .HasColumnType("TEXT"); - - b.Property("ExtraIds") - .HasColumnType("TEXT"); - - b.Property("ExtraType") - .HasColumnType("INTEGER"); - - b.Property("ForcedSortName") - .HasColumnType("TEXT"); - - b.Property("Genres") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IndexNumber") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingSubValue") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingValue") - .HasColumnType("INTEGER"); - - b.Property("IsFolder") - .HasColumnType("INTEGER"); - - b.Property("IsInMixedFolder") - .HasColumnType("INTEGER"); - - b.Property("IsLocked") - .HasColumnType("INTEGER"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("IsRepeat") - .HasColumnType("INTEGER"); - - b.Property("IsSeries") - .HasColumnType("INTEGER"); - - b.Property("IsVirtualItem") - .HasColumnType("INTEGER"); - - b.Property("LUFS") - .HasColumnType("REAL"); - - b.Property("MediaType") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("NormalizationGain") - .HasColumnType("REAL"); - - b.Property("OfficialRating") - .HasColumnType("TEXT"); - - b.Property("OriginalTitle") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .HasColumnType("TEXT"); - - b.Property("ParentId") - .HasColumnType("TEXT"); - - b.Property("ParentIndexNumber") - .HasColumnType("INTEGER"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataCountryCode") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataLanguage") - .HasColumnType("TEXT"); - - b.Property("PremiereDate") - .HasColumnType("TEXT"); - - b.Property("PresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("PrimaryVersionId") - .HasColumnType("TEXT"); - - b.Property("ProductionLocations") - .HasColumnType("TEXT"); - - b.Property("ProductionYear") - .HasColumnType("INTEGER"); - - b.Property("RunTimeTicks") - .HasColumnType("INTEGER"); - - b.Property("SeasonId") - .HasColumnType("TEXT"); - - b.Property("SeasonName") - .HasColumnType("TEXT"); - - b.Property("SeriesId") - .HasColumnType("TEXT"); - - b.Property("SeriesName") - .HasColumnType("TEXT"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("ShowId") - .HasColumnType("TEXT"); - - b.Property("Size") - .HasColumnType("INTEGER"); - - b.Property("SortName") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Studios") - .HasColumnType("TEXT"); - - b.Property("Tagline") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT"); - - b.Property("TopParentId") - .HasColumnType("TEXT"); - - b.Property("TotalBitrate") - .HasColumnType("INTEGER"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UnratedType") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("Path"); - - b.HasIndex("PresentationUniqueKey"); - - b.HasIndex("TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - - b.HasIndex("Type", "TopParentId", "StartDate"); - - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); - - b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.ToTable("BaseItems"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - - b.HasData( - new - { - Id = new Guid("00000000-0000-0000-0000-000000000001"), - IsFolder = false, - IsInMixedFolder = false, - IsLocked = false, - IsMovie = false, - IsRepeat = false, - IsSeries = false, - IsVirtualItem = false, - Name = "This is a placeholder item for UserData that has been detacted from its original item", - Type = "PLACEHOLDER" - }); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Blurhash") - .HasColumnType("BLOB"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("ImageType") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemMetadataFields"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ProviderId") - .HasColumnType("TEXT"); - - b.Property("ProviderValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ProviderId"); - - b.HasIndex("ProviderId", "ProviderValue", "ItemId"); - - b.ToTable("BaseItemProviders"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemTrailerTypes"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ChapterIndex") - .HasColumnType("INTEGER"); - - b.Property("ImageDateModified") - .HasColumnType("TEXT"); - - b.Property("ImagePath") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("StartPositionTicks") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "ChapterIndex"); - - b.ToTable("Chapters"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Property("ItemValueId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CleanValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId"); - - b.HasIndex("Type", "CleanValue"); - - b.HasIndex("Type", "Value") - .IsUnique(); - - b.ToTable("ItemValues"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.Property("ItemValueId") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("ItemValuesMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.KeyframeData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.PrimitiveCollection("KeyframeTicks") - .HasColumnType("TEXT"); - - b.Property("TotalDuration") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId"); - - b.ToTable("KeyframeData"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StreamIndex") - .HasColumnType("INTEGER"); - - b.Property("AspectRatio") - .HasColumnType("TEXT"); - - b.Property("AverageFrameRate") - .HasColumnType("REAL"); - - b.Property("BitDepth") - .HasColumnType("INTEGER"); - - b.Property("BitRate") - .HasColumnType("INTEGER"); - - b.Property("BlPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("ChannelLayout") - .HasColumnType("TEXT"); - - b.Property("Channels") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("CodecTimeBase") - .HasColumnType("TEXT"); - - b.Property("ColorPrimaries") - .HasColumnType("TEXT"); - - b.Property("ColorSpace") - .HasColumnType("TEXT"); - - b.Property("ColorTransfer") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("DvBlSignalCompatibilityId") - .HasColumnType("INTEGER"); - - b.Property("DvLevel") - .HasColumnType("INTEGER"); - - b.Property("DvProfile") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMajor") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMinor") - .HasColumnType("INTEGER"); - - b.Property("ElPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Hdr10PlusPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IsAnamorphic") - .HasColumnType("INTEGER"); - - b.Property("IsAvc") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("IsHearingImpaired") - .HasColumnType("INTEGER"); - - b.Property("IsInterlaced") - .HasColumnType("INTEGER"); - - b.Property("KeyFrames") - .HasColumnType("TEXT"); - - b.Property("Language") - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("REAL"); - - b.Property("NalLengthSize") - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PixelFormat") - .HasColumnType("TEXT"); - - b.Property("Profile") - .HasColumnType("TEXT"); - - b.Property("RealFrameRate") - .HasColumnType("REAL"); - - b.Property("RefFrames") - .HasColumnType("INTEGER"); - - b.Property("Rotation") - .HasColumnType("INTEGER"); - - b.Property("RpuPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("SampleRate") - .HasColumnType("INTEGER"); - - b.Property("StreamType") - .HasColumnType("INTEGER"); - - b.Property("TimeBase") - .HasColumnType("TEXT"); - - b.Property("Title") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "StreamIndex"); - - b.HasIndex("StreamIndex"); - - b.HasIndex("StreamType"); - - b.HasIndex("StreamIndex", "StreamType"); - - b.HasIndex("StreamIndex", "StreamType", "Language"); - - b.ToTable("MediaStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PersonType") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name"); - - b.ToTable("Peoples"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("PeopleId") - .HasColumnType("TEXT"); - - b.Property("ListOrder") - .HasColumnType("INTEGER"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "PeopleId"); - - b.HasIndex("PeopleId"); - - b.HasIndex("ItemId", "ListOrder"); - - b.HasIndex("ItemId", "SortOrder"); - - b.ToTable("PeopleBaseItemMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalRatingScore") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalRatingSubScore") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("CustomDataKey") - .HasColumnType("TEXT"); - - b.Property("AudioStreamIndex") - .HasColumnType("INTEGER"); - - b.Property("IsFavorite") - .HasColumnType("INTEGER"); - - b.Property("LastPlayedDate") - .HasColumnType("TEXT"); - - b.Property("Likes") - .HasColumnType("INTEGER"); - - b.Property("PlayCount") - .HasColumnType("INTEGER"); - - b.Property("PlaybackPositionTicks") - .HasColumnType("INTEGER"); - - b.Property("Played") - .HasColumnType("INTEGER"); - - b.Property("Rating") - .HasColumnType("REAL"); - - b.Property("RetentionDate") - .HasColumnType("TEXT"); - - b.Property("SubtitleStreamIndex") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "UserId", "CustomDataKey"); - - b.HasIndex("UserId"); - - b.HasIndex("ItemId", "UserId", "IsFavorite"); - - b.HasIndex("ItemId", "UserId", "LastPlayedDate"); - - b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks"); - - b.HasIndex("ItemId", "UserId", "Played"); - - b.ToTable("UserData"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Parents") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "ParentItem") - .WithMany("Children") - .HasForeignKey("ParentItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ParentItem"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "DirectParent") - .WithMany("DirectChildren") - .HasForeignKey("ParentId") - .OnDelete(DeleteBehavior.Cascade); - - b.Navigation("DirectParent"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Images") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("LockedFields") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Provider") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("TrailerTypes") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Chapters") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Database.Implementations.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("ItemValues") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.ItemValue", "ItemValue") - .WithMany("BaseItemsMap") - .HasForeignKey("ItemValueId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ItemValue"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.KeyframeData", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("MediaStreams") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Peoples") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.People", "People") - .WithMany("BaseItems") - .HasForeignKey("PeopleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("People"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("UserData") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Navigation("Chapters"); - - b.Navigation("Children"); - - b.Navigation("DirectChildren"); - - b.Navigation("Images"); - - b.Navigation("ItemValues"); - - b.Navigation("LockedFields"); - - b.Navigation("MediaStreams"); - - b.Navigation("Parents"); - - b.Navigation("Peoples"); - - b.Navigation("Provider"); - - b.Navigation("TrailerTypes"); - - b.Navigation("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Navigation("BaseItemsMap"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Navigation("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250913211637_AddProperParentChildRelationBaseItemWithCascade.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250913211637_AddProperParentChildRelationBaseItemWithCascade.cs deleted file mode 100644 index 3fabed21..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250913211637_AddProperParentChildRelationBaseItemWithCascade.cs +++ /dev/null @@ -1,56 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class AddProperParentChildRelationBaseItemWithCascade : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.Sql(""" -DELETE FROM BaseItems - WHERE - ParentId IS NOT NULL - AND - NOT EXISTS(SELECT 1 FROM BaseItems parent WHERE parent.Id = BaseItems.ParentId); -DELETE FROM BaseItems - WHERE - ParentId IS NOT NULL - AND - NOT EXISTS(SELECT 1 FROM BaseItems parent WHERE parent.Id = BaseItems.ParentId); -DELETE FROM BaseItems - WHERE - ParentId IS NOT NULL - AND - NOT EXISTS(SELECT 1 FROM BaseItems parent WHERE parent.Id = BaseItems.ParentId); -DELETE FROM BaseItems - WHERE - ParentId IS NOT NULL - AND - NOT EXISTS(SELECT 1 FROM BaseItems parent WHERE parent.Id = BaseItems.ParentId); -"""); - migrationBuilder.AddForeignKey( - name: "FK_BaseItems_BaseItems_ParentId", - table: "BaseItems", - column: "ParentId", - principalTable: "BaseItems", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_BaseItems_BaseItems_ParentId", - table: "BaseItems"); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250925203415_ExtendPeopleMapKey.Designer.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250925203415_ExtendPeopleMapKey.Designer.cs deleted file mode 100644 index edf30b0e..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250925203415_ExtendPeopleMapKey.Designer.cs +++ /dev/null @@ -1,1721 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - [Migration("20250925203415_ExtendPeopleMapKey")] - partial class ExtendPeopleMapKey - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.9"); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ParentItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ParentItemId"); - - b.HasIndex("ParentItemId"); - - b.ToTable("AncestorIds"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Index") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("Filename") - .HasColumnType("TEXT"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "Index"); - - b.ToTable("AttachmentStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Album") - .HasColumnType("TEXT"); - - b.Property("AlbumArtists") - .HasColumnType("TEXT"); - - b.Property("Artists") - .HasColumnType("TEXT"); - - b.Property("Audio") - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("TEXT"); - - b.Property("CleanName") - .HasColumnType("TEXT"); - - b.Property("CommunityRating") - .HasColumnType("REAL"); - - b.Property("CriticRating") - .HasColumnType("REAL"); - - b.Property("CustomRating") - .HasColumnType("TEXT"); - - b.Property("Data") - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastMediaAdded") - .HasColumnType("TEXT"); - - b.Property("DateLastRefreshed") - .HasColumnType("TEXT"); - - b.Property("DateLastSaved") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("EpisodeTitle") - .HasColumnType("TEXT"); - - b.Property("ExternalId") - .HasColumnType("TEXT"); - - b.Property("ExternalSeriesId") - .HasColumnType("TEXT"); - - b.Property("ExternalServiceId") - .HasColumnType("TEXT"); - - b.Property("ExtraIds") - .HasColumnType("TEXT"); - - b.Property("ExtraType") - .HasColumnType("INTEGER"); - - b.Property("ForcedSortName") - .HasColumnType("TEXT"); - - b.Property("Genres") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IndexNumber") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingSubValue") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingValue") - .HasColumnType("INTEGER"); - - b.Property("IsFolder") - .HasColumnType("INTEGER"); - - b.Property("IsInMixedFolder") - .HasColumnType("INTEGER"); - - b.Property("IsLocked") - .HasColumnType("INTEGER"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("IsRepeat") - .HasColumnType("INTEGER"); - - b.Property("IsSeries") - .HasColumnType("INTEGER"); - - b.Property("IsVirtualItem") - .HasColumnType("INTEGER"); - - b.Property("LUFS") - .HasColumnType("REAL"); - - b.Property("MediaType") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("NormalizationGain") - .HasColumnType("REAL"); - - b.Property("OfficialRating") - .HasColumnType("TEXT"); - - b.Property("OriginalTitle") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .HasColumnType("TEXT"); - - b.Property("ParentId") - .HasColumnType("TEXT"); - - b.Property("ParentIndexNumber") - .HasColumnType("INTEGER"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataCountryCode") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataLanguage") - .HasColumnType("TEXT"); - - b.Property("PremiereDate") - .HasColumnType("TEXT"); - - b.Property("PresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("PrimaryVersionId") - .HasColumnType("TEXT"); - - b.Property("ProductionLocations") - .HasColumnType("TEXT"); - - b.Property("ProductionYear") - .HasColumnType("INTEGER"); - - b.Property("RunTimeTicks") - .HasColumnType("INTEGER"); - - b.Property("SeasonId") - .HasColumnType("TEXT"); - - b.Property("SeasonName") - .HasColumnType("TEXT"); - - b.Property("SeriesId") - .HasColumnType("TEXT"); - - b.Property("SeriesName") - .HasColumnType("TEXT"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("ShowId") - .HasColumnType("TEXT"); - - b.Property("Size") - .HasColumnType("INTEGER"); - - b.Property("SortName") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Studios") - .HasColumnType("TEXT"); - - b.Property("Tagline") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT"); - - b.Property("TopParentId") - .HasColumnType("TEXT"); - - b.Property("TotalBitrate") - .HasColumnType("INTEGER"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UnratedType") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("Path"); - - b.HasIndex("PresentationUniqueKey"); - - b.HasIndex("TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - - b.HasIndex("Type", "TopParentId", "StartDate"); - - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); - - b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.ToTable("BaseItems"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - - b.HasData( - new - { - Id = new Guid("00000000-0000-0000-0000-000000000001"), - IsFolder = false, - IsInMixedFolder = false, - IsLocked = false, - IsMovie = false, - IsRepeat = false, - IsSeries = false, - IsVirtualItem = false, - Name = "This is a placeholder item for UserData that has been detacted from its original item", - Type = "PLACEHOLDER" - }); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Blurhash") - .HasColumnType("BLOB"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("ImageType") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemMetadataFields"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ProviderId") - .HasColumnType("TEXT"); - - b.Property("ProviderValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ProviderId"); - - b.HasIndex("ProviderId", "ProviderValue", "ItemId"); - - b.ToTable("BaseItemProviders"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemTrailerTypes"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ChapterIndex") - .HasColumnType("INTEGER"); - - b.Property("ImageDateModified") - .HasColumnType("TEXT"); - - b.Property("ImagePath") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("StartPositionTicks") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "ChapterIndex"); - - b.ToTable("Chapters"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Property("ItemValueId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CleanValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId"); - - b.HasIndex("Type", "CleanValue"); - - b.HasIndex("Type", "Value") - .IsUnique(); - - b.ToTable("ItemValues"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.Property("ItemValueId") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("ItemValuesMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.KeyframeData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.PrimitiveCollection("KeyframeTicks") - .HasColumnType("TEXT"); - - b.Property("TotalDuration") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId"); - - b.ToTable("KeyframeData"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StreamIndex") - .HasColumnType("INTEGER"); - - b.Property("AspectRatio") - .HasColumnType("TEXT"); - - b.Property("AverageFrameRate") - .HasColumnType("REAL"); - - b.Property("BitDepth") - .HasColumnType("INTEGER"); - - b.Property("BitRate") - .HasColumnType("INTEGER"); - - b.Property("BlPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("ChannelLayout") - .HasColumnType("TEXT"); - - b.Property("Channels") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("CodecTimeBase") - .HasColumnType("TEXT"); - - b.Property("ColorPrimaries") - .HasColumnType("TEXT"); - - b.Property("ColorSpace") - .HasColumnType("TEXT"); - - b.Property("ColorTransfer") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("DvBlSignalCompatibilityId") - .HasColumnType("INTEGER"); - - b.Property("DvLevel") - .HasColumnType("INTEGER"); - - b.Property("DvProfile") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMajor") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMinor") - .HasColumnType("INTEGER"); - - b.Property("ElPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Hdr10PlusPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IsAnamorphic") - .HasColumnType("INTEGER"); - - b.Property("IsAvc") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("IsHearingImpaired") - .HasColumnType("INTEGER"); - - b.Property("IsInterlaced") - .HasColumnType("INTEGER"); - - b.Property("KeyFrames") - .HasColumnType("TEXT"); - - b.Property("Language") - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("REAL"); - - b.Property("NalLengthSize") - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PixelFormat") - .HasColumnType("TEXT"); - - b.Property("Profile") - .HasColumnType("TEXT"); - - b.Property("RealFrameRate") - .HasColumnType("REAL"); - - b.Property("RefFrames") - .HasColumnType("INTEGER"); - - b.Property("Rotation") - .HasColumnType("INTEGER"); - - b.Property("RpuPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("SampleRate") - .HasColumnType("INTEGER"); - - b.Property("StreamType") - .HasColumnType("INTEGER"); - - b.Property("TimeBase") - .HasColumnType("TEXT"); - - b.Property("Title") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "StreamIndex"); - - b.HasIndex("StreamIndex"); - - b.HasIndex("StreamType"); - - b.HasIndex("StreamIndex", "StreamType"); - - b.HasIndex("StreamIndex", "StreamType", "Language"); - - b.ToTable("MediaStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PersonType") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name"); - - b.ToTable("Peoples"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("PeopleId") - .HasColumnType("TEXT"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("ListOrder") - .HasColumnType("INTEGER"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "PeopleId", "Role"); - - b.HasIndex("PeopleId"); - - b.HasIndex("ItemId", "ListOrder"); - - b.HasIndex("ItemId", "SortOrder"); - - b.ToTable("PeopleBaseItemMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalRatingScore") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalRatingSubScore") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("CustomDataKey") - .HasColumnType("TEXT"); - - b.Property("AudioStreamIndex") - .HasColumnType("INTEGER"); - - b.Property("IsFavorite") - .HasColumnType("INTEGER"); - - b.Property("LastPlayedDate") - .HasColumnType("TEXT"); - - b.Property("Likes") - .HasColumnType("INTEGER"); - - b.Property("PlayCount") - .HasColumnType("INTEGER"); - - b.Property("PlaybackPositionTicks") - .HasColumnType("INTEGER"); - - b.Property("Played") - .HasColumnType("INTEGER"); - - b.Property("Rating") - .HasColumnType("REAL"); - - b.Property("RetentionDate") - .HasColumnType("TEXT"); - - b.Property("SubtitleStreamIndex") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "UserId", "CustomDataKey"); - - b.HasIndex("UserId"); - - b.HasIndex("ItemId", "UserId", "IsFavorite"); - - b.HasIndex("ItemId", "UserId", "LastPlayedDate"); - - b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks"); - - b.HasIndex("ItemId", "UserId", "Played"); - - b.ToTable("UserData"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Parents") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "ParentItem") - .WithMany("Children") - .HasForeignKey("ParentItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ParentItem"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "DirectParent") - .WithMany("DirectChildren") - .HasForeignKey("ParentId") - .OnDelete(DeleteBehavior.Cascade); - - b.Navigation("DirectParent"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Images") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("LockedFields") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Provider") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("TrailerTypes") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Chapters") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Database.Implementations.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("ItemValues") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.ItemValue", "ItemValue") - .WithMany("BaseItemsMap") - .HasForeignKey("ItemValueId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ItemValue"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.KeyframeData", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("MediaStreams") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Peoples") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.People", "People") - .WithMany("BaseItems") - .HasForeignKey("PeopleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("People"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("UserData") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Navigation("Chapters"); - - b.Navigation("Children"); - - b.Navigation("DirectChildren"); - - b.Navigation("Images"); - - b.Navigation("ItemValues"); - - b.Navigation("LockedFields"); - - b.Navigation("MediaStreams"); - - b.Navigation("Parents"); - - b.Navigation("Peoples"); - - b.Navigation("Provider"); - - b.Navigation("TrailerTypes"); - - b.Navigation("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Navigation("BaseItemsMap"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Navigation("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250925203415_ExtendPeopleMapKey.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250925203415_ExtendPeopleMapKey.cs deleted file mode 100644 index f99291a4..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20250925203415_ExtendPeopleMapKey.cs +++ /dev/null @@ -1,58 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class ExtendPeopleMapKey : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropPrimaryKey( - name: "PK_PeopleBaseItemMap", - table: "PeopleBaseItemMap"); - - migrationBuilder.AlterColumn( - name: "Role", - table: "PeopleBaseItemMap", - type: "TEXT", - nullable: false, - defaultValue: string.Empty, - oldClrType: typeof(string), - oldType: "TEXT", - oldNullable: true); - - migrationBuilder.AddPrimaryKey( - name: "PK_PeopleBaseItemMap", - table: "PeopleBaseItemMap", - columns: new[] { "ItemId", "PeopleId", "Role" }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropPrimaryKey( - name: "PK_PeopleBaseItemMap", - table: "PeopleBaseItemMap"); - - migrationBuilder.AlterColumn( - name: "Role", - table: "PeopleBaseItemMap", - type: "TEXT", - nullable: true, - oldClrType: typeof(string), - oldType: "TEXT"); - - migrationBuilder.AddPrimaryKey( - name: "PK_PeopleBaseItemMap", - table: "PeopleBaseItemMap", - columns: new[] { "ItemId", "PeopleId" }); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20260501000000_AddLibraryOptionsTable.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20260501000000_AddLibraryOptionsTable.cs deleted file mode 100644 index a89cd37f..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/20260501000000_AddLibraryOptionsTable.cs +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -#nullable disable - -namespace Jellyfin.Database.Providers.Sqlite.Migrations -{ - using System; - using Microsoft.EntityFrameworkCore.Migrations; - - /// - public partial class AddLibraryOptionsTable : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "LibraryOptions", - columns: table => new - { - LibraryPath = table.Column(type: "TEXT", nullable: false), - OptionsJson = table.Column(type: "TEXT", nullable: false), - Version = table.Column(type: "INTEGER", nullable: false, defaultValue: 1), - DateCreated = table.Column(type: "TEXT", nullable: false, defaultValueSql: "datetime('now')"), - DateModified = table.Column(type: "TEXT", nullable: false, defaultValueSql: "datetime('now')") - }, - constraints: table => - { - table.PrimaryKey("PK_LibraryOptions", x => x.LibraryPath); - }); - - migrationBuilder.CreateIndex( - name: "IX_LibraryOptions_DateModified", - table: "LibraryOptions", - column: "DateModified", - descending: new[] { true }); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "LibraryOptions"); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/JellyfinDbModelSnapshot.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/JellyfinDbModelSnapshot.cs deleted file mode 100644 index bea2364d..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/JellyfinDbModelSnapshot.cs +++ /dev/null @@ -1,1718 +0,0 @@ -// -using System; -using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Jellyfin.Server.Implementations.Migrations -{ - [DbContext(typeof(JellyfinDbContext))] - partial class JellyfinDbModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder.HasAnnotation("ProductVersion", "9.0.9"); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DayOfWeek") - .HasColumnType("INTEGER"); - - b.Property("EndHour") - .HasColumnType("REAL"); - - b.Property("StartHour") - .HasColumnType("REAL"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("AccessSchedules"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ActivityLog", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("LogSeverity") - .HasColumnType("INTEGER"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("ShortOverview") - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("Type") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DateCreated"); - - b.ToTable("ActivityLogs"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ParentItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ParentItemId"); - - b.HasIndex("ParentItemId"); - - b.ToTable("AncestorIds"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Index") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("Filename") - .HasColumnType("TEXT"); - - b.Property("MimeType") - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "Index"); - - b.ToTable("AttachmentStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Album") - .HasColumnType("TEXT"); - - b.Property("AlbumArtists") - .HasColumnType("TEXT"); - - b.Property("Artists") - .HasColumnType("TEXT"); - - b.Property("Audio") - .HasColumnType("INTEGER"); - - b.Property("ChannelId") - .HasColumnType("TEXT"); - - b.Property("CleanName") - .HasColumnType("TEXT"); - - b.Property("CommunityRating") - .HasColumnType("REAL"); - - b.Property("CriticRating") - .HasColumnType("REAL"); - - b.Property("CustomRating") - .HasColumnType("TEXT"); - - b.Property("Data") - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastMediaAdded") - .HasColumnType("TEXT"); - - b.Property("DateLastRefreshed") - .HasColumnType("TEXT"); - - b.Property("DateLastSaved") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("EndDate") - .HasColumnType("TEXT"); - - b.Property("EpisodeTitle") - .HasColumnType("TEXT"); - - b.Property("ExternalId") - .HasColumnType("TEXT"); - - b.Property("ExternalSeriesId") - .HasColumnType("TEXT"); - - b.Property("ExternalServiceId") - .HasColumnType("TEXT"); - - b.Property("ExtraIds") - .HasColumnType("TEXT"); - - b.Property("ExtraType") - .HasColumnType("INTEGER"); - - b.Property("ForcedSortName") - .HasColumnType("TEXT"); - - b.Property("Genres") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IndexNumber") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingSubValue") - .HasColumnType("INTEGER"); - - b.Property("InheritedParentalRatingValue") - .HasColumnType("INTEGER"); - - b.Property("IsFolder") - .HasColumnType("INTEGER"); - - b.Property("IsInMixedFolder") - .HasColumnType("INTEGER"); - - b.Property("IsLocked") - .HasColumnType("INTEGER"); - - b.Property("IsMovie") - .HasColumnType("INTEGER"); - - b.Property("IsRepeat") - .HasColumnType("INTEGER"); - - b.Property("IsSeries") - .HasColumnType("INTEGER"); - - b.Property("IsVirtualItem") - .HasColumnType("INTEGER"); - - b.Property("LUFS") - .HasColumnType("REAL"); - - b.Property("MediaType") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("NormalizationGain") - .HasColumnType("REAL"); - - b.Property("OfficialRating") - .HasColumnType("TEXT"); - - b.Property("OriginalTitle") - .HasColumnType("TEXT"); - - b.Property("Overview") - .HasColumnType("TEXT"); - - b.Property("OwnerId") - .HasColumnType("TEXT"); - - b.Property("ParentId") - .HasColumnType("TEXT"); - - b.Property("ParentIndexNumber") - .HasColumnType("INTEGER"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataCountryCode") - .HasColumnType("TEXT"); - - b.Property("PreferredMetadataLanguage") - .HasColumnType("TEXT"); - - b.Property("PremiereDate") - .HasColumnType("TEXT"); - - b.Property("PresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("PrimaryVersionId") - .HasColumnType("TEXT"); - - b.Property("ProductionLocations") - .HasColumnType("TEXT"); - - b.Property("ProductionYear") - .HasColumnType("INTEGER"); - - b.Property("RunTimeTicks") - .HasColumnType("INTEGER"); - - b.Property("SeasonId") - .HasColumnType("TEXT"); - - b.Property("SeasonName") - .HasColumnType("TEXT"); - - b.Property("SeriesId") - .HasColumnType("TEXT"); - - b.Property("SeriesName") - .HasColumnType("TEXT"); - - b.Property("SeriesPresentationUniqueKey") - .HasColumnType("TEXT"); - - b.Property("ShowId") - .HasColumnType("TEXT"); - - b.Property("Size") - .HasColumnType("INTEGER"); - - b.Property("SortName") - .HasColumnType("TEXT"); - - b.Property("StartDate") - .HasColumnType("TEXT"); - - b.Property("Studios") - .HasColumnType("TEXT"); - - b.Property("Tagline") - .HasColumnType("TEXT"); - - b.Property("Tags") - .HasColumnType("TEXT"); - - b.Property("TopParentId") - .HasColumnType("TEXT"); - - b.Property("TotalBitrate") - .HasColumnType("INTEGER"); - - b.Property("Type") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UnratedType") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ParentId"); - - b.HasIndex("Path"); - - b.HasIndex("PresentationUniqueKey"); - - b.HasIndex("TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "Id"); - - b.HasIndex("Type", "TopParentId", "PresentationUniqueKey"); - - b.HasIndex("Type", "TopParentId", "StartDate"); - - b.HasIndex("Id", "Type", "IsFolder", "IsVirtualItem"); - - b.HasIndex("MediaType", "TopParentId", "IsVirtualItem", "PresentationUniqueKey"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "IsFolder", "IsVirtualItem"); - - b.HasIndex("Type", "SeriesPresentationUniqueKey", "PresentationUniqueKey", "SortName"); - - b.HasIndex("IsFolder", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.HasIndex("Type", "TopParentId", "IsVirtualItem", "PresentationUniqueKey", "DateCreated"); - - b.ToTable("BaseItems"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - - b.HasData( - new - { - Id = new Guid("00000000-0000-0000-0000-000000000001"), - IsFolder = false, - IsInMixedFolder = false, - IsLocked = false, - IsMovie = false, - IsRepeat = false, - IsSeries = false, - IsVirtualItem = false, - Name = "This is a placeholder item for UserData that has been detacted from its original item", - Type = "PLACEHOLDER" - }); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Blurhash") - .HasColumnType("BLOB"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("ImageType") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemMetadataFields"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ProviderId") - .HasColumnType("TEXT"); - - b.Property("ProviderValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemId", "ProviderId"); - - b.HasIndex("ProviderId", "ProviderValue", "ItemId"); - - b.ToTable("BaseItemProviders"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.Property("Id") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("Id", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("BaseItemTrailerTypes"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ChapterIndex") - .HasColumnType("INTEGER"); - - b.Property("ImageDateModified") - .HasColumnType("TEXT"); - - b.Property("ImagePath") - .HasColumnType("TEXT"); - - b.Property("Name") - .HasColumnType("TEXT"); - - b.Property("StartPositionTicks") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "ChapterIndex"); - - b.ToTable("Chapters"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.CustomItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Key") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client", "Key") - .IsUnique(); - - b.ToTable("CustomItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("ChromecastVersion") - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DashboardTheme") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("EnableNextVideoInfoOverlay") - .HasColumnType("INTEGER"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("ScrollDirection") - .HasColumnType("INTEGER"); - - b.Property("ShowBackdrop") - .HasColumnType("INTEGER"); - - b.Property("ShowSidebar") - .HasColumnType("INTEGER"); - - b.Property("SkipBackwardLength") - .HasColumnType("INTEGER"); - - b.Property("SkipForwardLength") - .HasColumnType("INTEGER"); - - b.Property("TvHome") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "ItemId", "Client") - .IsUnique(); - - b.ToTable("DisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("DisplayPreferencesId") - .HasColumnType("INTEGER"); - - b.Property("Order") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("DisplayPreferencesId"); - - b.ToTable("HomeSection"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("LastModified") - .HasColumnType("TEXT"); - - b.Property("Path") - .IsRequired() - .HasMaxLength(512) - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId") - .IsUnique(); - - b.ToTable("ImageInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Client") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("IndexBy") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("RememberIndexing") - .HasColumnType("INTEGER"); - - b.Property("RememberSorting") - .HasColumnType("INTEGER"); - - b.Property("SortBy") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("ViewType") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId"); - - b.ToTable("ItemDisplayPreferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Property("ItemValueId") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("CleanValue") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.Property("Value") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId"); - - b.HasIndex("Type", "CleanValue"); - - b.HasIndex("Type", "Value") - .IsUnique(); - - b.ToTable("ItemValues"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.Property("ItemValueId") - .HasColumnType("TEXT"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.HasKey("ItemValueId", "ItemId"); - - b.HasIndex("ItemId"); - - b.ToTable("ItemValuesMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.KeyframeData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.PrimitiveCollection("KeyframeTicks") - .HasColumnType("TEXT"); - - b.Property("TotalDuration") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId"); - - b.ToTable("KeyframeData"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaSegment", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("EndTicks") - .HasColumnType("INTEGER"); - - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("SegmentProviderId") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("StartTicks") - .HasColumnType("INTEGER"); - - b.Property("Type") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.ToTable("MediaSegments"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("StreamIndex") - .HasColumnType("INTEGER"); - - b.Property("AspectRatio") - .HasColumnType("TEXT"); - - b.Property("AverageFrameRate") - .HasColumnType("REAL"); - - b.Property("BitDepth") - .HasColumnType("INTEGER"); - - b.Property("BitRate") - .HasColumnType("INTEGER"); - - b.Property("BlPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("ChannelLayout") - .HasColumnType("TEXT"); - - b.Property("Channels") - .HasColumnType("INTEGER"); - - b.Property("Codec") - .HasColumnType("TEXT"); - - b.Property("CodecTag") - .HasColumnType("TEXT"); - - b.Property("CodecTimeBase") - .HasColumnType("TEXT"); - - b.Property("ColorPrimaries") - .HasColumnType("TEXT"); - - b.Property("ColorSpace") - .HasColumnType("TEXT"); - - b.Property("ColorTransfer") - .HasColumnType("TEXT"); - - b.Property("Comment") - .HasColumnType("TEXT"); - - b.Property("DvBlSignalCompatibilityId") - .HasColumnType("INTEGER"); - - b.Property("DvLevel") - .HasColumnType("INTEGER"); - - b.Property("DvProfile") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMajor") - .HasColumnType("INTEGER"); - - b.Property("DvVersionMinor") - .HasColumnType("INTEGER"); - - b.Property("ElPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Hdr10PlusPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("IsAnamorphic") - .HasColumnType("INTEGER"); - - b.Property("IsAvc") - .HasColumnType("INTEGER"); - - b.Property("IsDefault") - .HasColumnType("INTEGER"); - - b.Property("IsExternal") - .HasColumnType("INTEGER"); - - b.Property("IsForced") - .HasColumnType("INTEGER"); - - b.Property("IsHearingImpaired") - .HasColumnType("INTEGER"); - - b.Property("IsInterlaced") - .HasColumnType("INTEGER"); - - b.Property("KeyFrames") - .HasColumnType("TEXT"); - - b.Property("Language") - .HasColumnType("TEXT"); - - b.Property("Level") - .HasColumnType("REAL"); - - b.Property("NalLengthSize") - .HasColumnType("TEXT"); - - b.Property("Path") - .HasColumnType("TEXT"); - - b.Property("PixelFormat") - .HasColumnType("TEXT"); - - b.Property("Profile") - .HasColumnType("TEXT"); - - b.Property("RealFrameRate") - .HasColumnType("REAL"); - - b.Property("RefFrames") - .HasColumnType("INTEGER"); - - b.Property("Rotation") - .HasColumnType("INTEGER"); - - b.Property("RpuPresentFlag") - .HasColumnType("INTEGER"); - - b.Property("SampleRate") - .HasColumnType("INTEGER"); - - b.Property("StreamType") - .HasColumnType("INTEGER"); - - b.Property("TimeBase") - .HasColumnType("TEXT"); - - b.Property("Title") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "StreamIndex"); - - b.HasIndex("StreamIndex"); - - b.HasIndex("StreamType"); - - b.HasIndex("StreamIndex", "StreamType"); - - b.HasIndex("StreamIndex", "StreamType", "Language"); - - b.ToTable("MediaStreamInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("PersonType") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Name"); - - b.ToTable("Peoples"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("PeopleId") - .HasColumnType("TEXT"); - - b.Property("Role") - .HasColumnType("TEXT"); - - b.Property("ListOrder") - .HasColumnType("INTEGER"); - - b.Property("SortOrder") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "PeopleId", "Role"); - - b.HasIndex("PeopleId"); - - b.HasIndex("ItemId", "ListOrder"); - - b.HasIndex("ItemId", "SortOrder"); - - b.ToTable("PeopleBaseItemMap"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Permission_Permissions_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .HasColumnType("INTEGER"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Permissions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("Kind") - .HasColumnType("INTEGER"); - - b.Property("Preference_Preferences_Guid") - .HasColumnType("TEXT"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("Value") - .IsRequired() - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("UserId", "Kind") - .IsUnique() - .HasFilter("[UserId] IS NOT NULL"); - - b.ToTable("Preferences"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.ApiKey", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("Name") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("AccessToken") - .IsUnique(); - - b.ToTable("ApiKeys"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("AccessToken") - .IsRequired() - .HasColumnType("TEXT"); - - b.Property("AppName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("AppVersion") - .IsRequired() - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DateCreated") - .HasColumnType("TEXT"); - - b.Property("DateLastActivity") - .HasColumnType("TEXT"); - - b.Property("DateModified") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasMaxLength(256) - .HasColumnType("TEXT"); - - b.Property("DeviceName") - .IsRequired() - .HasMaxLength(64) - .HasColumnType("TEXT"); - - b.Property("IsActive") - .HasColumnType("INTEGER"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId"); - - b.HasIndex("AccessToken", "DateLastActivity"); - - b.HasIndex("DeviceId", "DateLastActivity"); - - b.HasIndex("UserId", "DeviceId"); - - b.ToTable("Devices"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.DeviceOptions", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("INTEGER"); - - b.Property("CustomName") - .HasColumnType("TEXT"); - - b.Property("DeviceId") - .IsRequired() - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("DeviceId") - .IsUnique(); - - b.ToTable("DeviceOptions"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.TrickplayInfo", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("Width") - .HasColumnType("INTEGER"); - - b.Property("Bandwidth") - .HasColumnType("INTEGER"); - - b.Property("Height") - .HasColumnType("INTEGER"); - - b.Property("Interval") - .HasColumnType("INTEGER"); - - b.Property("ThumbnailCount") - .HasColumnType("INTEGER"); - - b.Property("TileHeight") - .HasColumnType("INTEGER"); - - b.Property("TileWidth") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "Width"); - - b.ToTable("TrickplayInfos"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("TEXT"); - - b.Property("AudioLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("AuthenticationProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("CastReceiverId") - .HasMaxLength(32) - .HasColumnType("TEXT"); - - b.Property("DisplayCollectionsView") - .HasColumnType("INTEGER"); - - b.Property("DisplayMissingEpisodes") - .HasColumnType("INTEGER"); - - b.Property("EnableAutoLogin") - .HasColumnType("INTEGER"); - - b.Property("EnableLocalPassword") - .HasColumnType("INTEGER"); - - b.Property("EnableNextEpisodeAutoPlay") - .HasColumnType("INTEGER"); - - b.Property("EnableUserPreferenceAccess") - .HasColumnType("INTEGER"); - - b.Property("HidePlayedInLatest") - .HasColumnType("INTEGER"); - - b.Property("InternalId") - .HasColumnType("INTEGER"); - - b.Property("InvalidLoginAttemptCount") - .HasColumnType("INTEGER"); - - b.Property("LastActivityDate") - .HasColumnType("TEXT"); - - b.Property("LastLoginDate") - .HasColumnType("TEXT"); - - b.Property("LoginAttemptsBeforeLockout") - .HasColumnType("INTEGER"); - - b.Property("MaxActiveSessions") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalRatingScore") - .HasColumnType("INTEGER"); - - b.Property("MaxParentalRatingSubScore") - .HasColumnType("INTEGER"); - - b.Property("MustUpdatePassword") - .HasColumnType("INTEGER"); - - b.Property("Password") - .HasMaxLength(65535) - .HasColumnType("TEXT"); - - b.Property("PasswordResetProviderId") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("PlayDefaultAudioTrack") - .HasColumnType("INTEGER"); - - b.Property("RememberAudioSelections") - .HasColumnType("INTEGER"); - - b.Property("RememberSubtitleSelections") - .HasColumnType("INTEGER"); - - b.Property("RemoteClientBitrateLimit") - .HasColumnType("INTEGER"); - - b.Property("RowVersion") - .IsConcurrencyToken() - .HasColumnType("INTEGER"); - - b.Property("SubtitleLanguagePreference") - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.Property("SubtitleMode") - .HasColumnType("INTEGER"); - - b.Property("SyncPlayAccess") - .HasColumnType("INTEGER"); - - b.Property("Username") - .IsRequired() - .HasMaxLength(255) - .HasColumnType("TEXT"); - - b.HasKey("Id"); - - b.HasIndex("Username") - .IsUnique(); - - b.ToTable("Users"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.Property("ItemId") - .HasColumnType("TEXT"); - - b.Property("UserId") - .HasColumnType("TEXT"); - - b.Property("CustomDataKey") - .HasColumnType("TEXT"); - - b.Property("AudioStreamIndex") - .HasColumnType("INTEGER"); - - b.Property("IsFavorite") - .HasColumnType("INTEGER"); - - b.Property("LastPlayedDate") - .HasColumnType("TEXT"); - - b.Property("Likes") - .HasColumnType("INTEGER"); - - b.Property("PlayCount") - .HasColumnType("INTEGER"); - - b.Property("PlaybackPositionTicks") - .HasColumnType("INTEGER"); - - b.Property("Played") - .HasColumnType("INTEGER"); - - b.Property("Rating") - .HasColumnType("REAL"); - - b.Property("RetentionDate") - .HasColumnType("TEXT"); - - b.Property("SubtitleStreamIndex") - .HasColumnType("INTEGER"); - - b.HasKey("ItemId", "UserId", "CustomDataKey"); - - b.HasIndex("UserId"); - - b.HasIndex("ItemId", "UserId", "IsFavorite"); - - b.HasIndex("ItemId", "UserId", "LastPlayedDate"); - - b.HasIndex("ItemId", "UserId", "PlaybackPositionTicks"); - - b.HasIndex("ItemId", "UserId", "Played"); - - b.ToTable("UserData"); - - b.HasAnnotation("Sqlite:UseSqlReturningClause", false); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AccessSchedule", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("AccessSchedules") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AncestorId", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Parents") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "ParentItem") - .WithMany("Children") - .HasForeignKey("ParentItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ParentItem"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.AttachmentStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "DirectParent") - .WithMany("DirectChildren") - .HasForeignKey("ParentId") - .OnDelete(DeleteBehavior.Cascade); - - b.Navigation("DirectParent"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Images") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemMetadataField", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("LockedFields") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemProvider", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Provider") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemTrailerType", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("TrailerTypes") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Chapter", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Chapters") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("DisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.HomeSection", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.DisplayPreferences", null) - .WithMany("HomeSections") - .HasForeignKey("DisplayPreferencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ImageInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithOne("ProfileImage") - .HasForeignKey("Jellyfin.Database.Implementations.Entities.ImageInfo", "UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemDisplayPreferences", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("ItemDisplayPreferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValueMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("ItemValues") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.ItemValue", "ItemValue") - .WithMany("BaseItemsMap") - .HasForeignKey("ItemValueId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("ItemValue"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.KeyframeData", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany() - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.MediaStreamInfo", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("MediaStreams") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.PeopleBaseItemMap", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("Peoples") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.People", "People") - .WithMany("BaseItems") - .HasForeignKey("PeopleId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("People"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Permission", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Permissions") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Preference", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", null) - .WithMany("Preferences") - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.Security.Device", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.UserData", b => - { - b.HasOne("Jellyfin.Database.Implementations.Entities.BaseItemEntity", "Item") - .WithMany("UserData") - .HasForeignKey("ItemId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Jellyfin.Database.Implementations.Entities.User", "User") - .WithMany() - .HasForeignKey("UserId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Item"); - - b.Navigation("User"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.BaseItemEntity", b => - { - b.Navigation("Chapters"); - - b.Navigation("Children"); - - b.Navigation("DirectChildren"); - - b.Navigation("Images"); - - b.Navigation("ItemValues"); - - b.Navigation("LockedFields"); - - b.Navigation("MediaStreams"); - - b.Navigation("Parents"); - - b.Navigation("Peoples"); - - b.Navigation("Provider"); - - b.Navigation("TrailerTypes"); - - b.Navigation("UserData"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.DisplayPreferences", b => - { - b.Navigation("HomeSections"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.ItemValue", b => - { - b.Navigation("BaseItemsMap"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.People", b => - { - b.Navigation("BaseItems"); - }); - - modelBuilder.Entity("Jellyfin.Database.Implementations.Entities.User", b => - { - b.Navigation("AccessSchedules"); - - b.Navigation("DisplayPreferences"); - - b.Navigation("ItemDisplayPreferences"); - - b.Navigation("Permissions"); - - b.Navigation("Preferences"); - - b.Navigation("ProfileImage"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/SqliteDesignTimeJellyfinDbFactory.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/SqliteDesignTimeJellyfinDbFactory.cs deleted file mode 100644 index 87c6d6ae..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Migrations/SqliteDesignTimeJellyfinDbFactory.cs +++ /dev/null @@ -1,31 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Jellyfin.Database.Providers.Sqlite.Migrations -{ - using Jellyfin.Database.Implementations; - using Jellyfin.Database.Implementations.Locking; - using Microsoft.EntityFrameworkCore; - using Microsoft.EntityFrameworkCore.Design; - using Microsoft.Extensions.Logging.Abstractions; - - /// - /// The design time factory for . - /// This is only used for the creation of migrations and not during runtime. - /// - internal sealed class SqliteDesignTimeJellyfinDbFactory : IDesignTimeDbContextFactory - { - public JellyfinDbContext CreateDbContext(string[] args) - { - var optionsBuilder = new DbContextOptionsBuilder(); - optionsBuilder.UseSqlite("Data Source=jellyfin.db", f => f.MigrationsAssembly(GetType().Assembly)); - - return new JellyfinDbContext( - optionsBuilder.Options, - NullLogger.Instance, - new SqliteDatabaseProvider(null!, NullLogger.Instance), - new NoLockBehavior(NullLogger.Instance)); - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/ModelBuilderExtensions.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/ModelBuilderExtensions.cs deleted file mode 100644 index d898536e..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/ModelBuilderExtensions.cs +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Jellyfin.Database.Providers.Sqlite; - -using System; -using Jellyfin.Database.Providers.Sqlite.ValueConverters; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -/// -/// Model builder extensions. -/// -public static class ModelBuilderExtensions -{ - /// - /// Specify value converter for the object type. - /// - /// The model builder. - /// The . - /// The type to convert. - /// The modified . - public static ModelBuilder UseValueConverterForType(this ModelBuilder modelBuilder, ValueConverter converter) - { - var type = typeof(T); - foreach (var entityType in modelBuilder.Model.GetEntityTypes()) - { - foreach (var property in entityType.GetProperties()) - { - if (property.ClrType == type) - { - property.SetValueConverter(converter); - } - } - } - - return modelBuilder; - } - - /// - /// Specify the default . - /// - /// The model builder to extend. - /// The to specify. - public static void SetDefaultDateTimeKind(this ModelBuilder modelBuilder, DateTimeKind kind) - { - modelBuilder.UseValueConverterForType(new DateTimeKindValueConverter(kind)); - modelBuilder.UseValueConverterForType(new DateTimeKindValueConverter(kind)); - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/PragmaConnectionInterceptor.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/PragmaConnectionInterceptor.cs deleted file mode 100644 index 4fb29c3a..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/PragmaConnectionInterceptor.cs +++ /dev/null @@ -1,112 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Jellyfin.Database.Providers.Sqlite; - -using System.Collections.Generic; -using System.Data.Common; -using System.Globalization; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.Extensions.Logging; - -/// -/// Injects a series of PRAGMA on each connection starts. -/// -public class PragmaConnectionInterceptor : DbConnectionInterceptor -{ - private readonly ILogger _logger; - private readonly int? _cacheSize; - private readonly string _lockingMode; - private readonly int? _journalSizeLimit; - private readonly int _tempStoreMode; - private readonly int _syncMode; - private readonly IDictionary _customPragma; - - /// - /// Initializes a new instance of the class. - /// - /// The logger. - /// Cache size. - /// Locking mode. - /// Journal Size. - /// The https://sqlite.org/pragma.html#pragma_temp_store pragma. - /// The https://sqlite.org/pragma.html#pragma_synchronous pragma. - /// A list of custom provided Pragma in the list of CustomOptions starting with "#PRAGMA:". - public PragmaConnectionInterceptor(ILogger logger, int? cacheSize, string lockingMode, int? journalSizeLimit, int tempStoreMode, int syncMode, IDictionary customPragma) - { - _logger = logger; - _cacheSize = cacheSize; - _lockingMode = lockingMode; - _journalSizeLimit = journalSizeLimit; - _tempStoreMode = tempStoreMode; - _syncMode = syncMode; - _customPragma = customPragma; - - InitialCommand = BuildCommandText(); - _logger.LogInformation("SQLITE connection pragma command set to: \r\n{PragmaCommand}", InitialCommand); - } - - private string? InitialCommand { get; set; } - - /// - public override void ConnectionOpened(DbConnection connection, ConnectionEndEventData eventData) - { - base.ConnectionOpened(connection, eventData); - - using (var command = connection.CreateCommand()) - { -#pragma warning disable CA2100 // Review SQL queries for security vulnerabilities - command.CommandText = InitialCommand; -#pragma warning restore CA2100 // Review SQL queries for security vulnerabilities - command.ExecuteNonQuery(); - } - } - - /// - public override async Task ConnectionOpenedAsync(DbConnection connection, ConnectionEndEventData eventData, CancellationToken cancellationToken = default) - { - await base.ConnectionOpenedAsync(connection, eventData, cancellationToken).ConfigureAwait(false); - - var command = connection.CreateCommand(); - await using (command.ConfigureAwait(false)) - { -#pragma warning disable CA2100 // Review SQL queries for security vulnerabilities - command.CommandText = InitialCommand; -#pragma warning restore CA2100 // Review SQL queries for security vulnerabilities - await command.ExecuteNonQueryAsync(cancellationToken).ConfigureAwait(false); - } - } - - private string BuildCommandText() - { - var sb = new StringBuilder(); - if (_cacheSize.HasValue) - { - sb.AppendLine(CultureInfo.InvariantCulture, $"PRAGMA cache_size={_cacheSize.Value};"); - } - - if (!string.IsNullOrWhiteSpace(_lockingMode)) - { - sb.AppendLine(CultureInfo.InvariantCulture, $"PRAGMA locking_mode={_lockingMode};"); - } - - if (_journalSizeLimit.HasValue) - { - sb.AppendLine(CultureInfo.InvariantCulture, $"PRAGMA journal_size_limit={_journalSizeLimit};"); - } - - sb.AppendLine(CultureInfo.InvariantCulture, $"PRAGMA synchronous={_syncMode};"); - sb.AppendLine(CultureInfo.InvariantCulture, $"PRAGMA temp_store={_tempStoreMode};"); - - foreach (var item in _customPragma) - { - sb.AppendLine(CultureInfo.InvariantCulture, $"PRAGMA {item.Key}={item.Value};"); - } - - return sb.ToString(); - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Properties/AssemblyInfo.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Properties/AssemblyInfo.cs deleted file mode 100644 index d5087f57..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,27 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -using System.Reflection; -using System.Resources; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Jellyfin.Database.Providers.Sqlite")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Jellyfin Project")] -[assembly: AssemblyProduct("Jellyfin Server")] -[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] -[assembly: NeutralResourcesLanguage("en")] -[assembly: InternalsVisibleTo("Jellyfin.Server.Implementations.Tests")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/SqliteDatabaseProvider.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/SqliteDatabaseProvider.cs deleted file mode 100644 index 6b4c28f7..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/SqliteDatabaseProvider.cs +++ /dev/null @@ -1,269 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Jellyfin.Database.Providers.Sqlite; - -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Jellyfin.Database.Implementations; -using Jellyfin.Database.Implementations.DbConfiguration; -using MediaBrowser.Common.Configuration; -using Microsoft.Data.Sqlite; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.Extensions.Logging; - -/// -/// Configures jellyfin to use an SQLite database. -/// -[JellyfinDatabaseProviderKey("Jellyfin-SQLite")] -public sealed class SqliteDatabaseProvider : IJellyfinDatabaseProvider -{ - private const string BackupFolderName = "SQLiteBackups"; - private readonly IApplicationPaths applicationPaths; - private readonly ILogger logger; - - /// - /// Initializes a new instance of the class. - /// - /// Service to construct the fallback when the old data path configuration is used. - /// A logger. - public SqliteDatabaseProvider(IApplicationPaths applicationPaths, ILogger logger) - { - this.applicationPaths = applicationPaths; - this.logger = logger; - } - - /// - public IDbContextFactory? DbContextFactory { get; set; } - - /// - public void Initialise(DbContextOptionsBuilder options, DatabaseConfigurationOptions databaseConfiguration) - { - static T? GetOption(ICollection? options, string key, Func converter, Func? defaultValue = null) - { - if (options is null) - { - return defaultValue is not null ? defaultValue() : default; - } - - var value = options.FirstOrDefault(e => e.Key.Equals(key, StringComparison.OrdinalIgnoreCase)); - if (value is null) - { - return defaultValue is not null ? defaultValue() : default; - } - - return converter(value.Value); - } - - var customOptions = databaseConfiguration.CustomProviderOptions?.Options; - - var sqliteConnectionBuilder = new SqliteConnectionStringBuilder(); - sqliteConnectionBuilder.DataSource = Path.Combine(applicationPaths.DataPath, "jellyfin.db"); - sqliteConnectionBuilder.Cache = GetOption(customOptions, "cache", Enum.Parse, () => SqliteCacheMode.Default); - sqliteConnectionBuilder.Pooling = GetOption(customOptions, "pooling", e => e.Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase), () => true); - sqliteConnectionBuilder.DefaultTimeout = GetOption(customOptions, "command-timeout", int.Parse, () => 30); - - var connectionString = sqliteConnectionBuilder.ToString(); - - // Log SQLite connection parameters - logger.LogInformation("SQLite connection string: {ConnectionString}", connectionString); - - options - .UseSqlite( - connectionString, - sqLiteOptions => sqLiteOptions.MigrationsAssembly(GetType().Assembly)) - // TODO: Remove when https://github.com/dotnet/efcore/pull/35873 is merged & released - .ConfigureWarnings(warnings => - { - warnings.Ignore(RelationalEventId.NonTransactionalMigrationOperationWarning); - warnings.Ignore(RelationalEventId.PendingModelChangesWarning); - }) - .AddInterceptors(new PragmaConnectionInterceptor( - logger, - GetOption(customOptions, "cacheSize", e => int.Parse(e, CultureInfo.InvariantCulture)), - GetOption(customOptions, "lockingmode", e => e, () => "NORMAL")!, - GetOption(customOptions, "journalsizelimit", int.Parse, () => 134_217_728), - GetOption(customOptions, "tempstoremode", int.Parse, () => 2), - GetOption(customOptions, "syncmode", int.Parse, () => 1), - customOptions?.Where(e => e.Key.StartsWith("#PRAGMA:", StringComparison.OrdinalIgnoreCase)).ToDictionary(e => e.Key["#PRAGMA:".Length..], e => e.Value) ?? [])); - - var enableSensitiveDataLogging = GetOption(customOptions, "EnableSensitiveDataLogging", e => e.Equals(bool.TrueString, StringComparison.OrdinalIgnoreCase), () => false); - if (enableSensitiveDataLogging) - { - options.EnableSensitiveDataLogging(enableSensitiveDataLogging); - logger.LogInformation("EnableSensitiveDataLogging is enabled on SQLite connection"); - } - } - - /// - public async Task RunScheduledOptimisation(CancellationToken cancellationToken) - { - var context = await DbContextFactory!.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); - await using (context.ConfigureAwait(false)) - { - await context.Database.ExecuteSqlRawAsync("PRAGMA wal_checkpoint(TRUNCATE)", cancellationToken).ConfigureAwait(false); - await context.Database.ExecuteSqlRawAsync("PRAGMA optimize", cancellationToken).ConfigureAwait(false); - await context.Database.ExecuteSqlRawAsync("VACUUM", cancellationToken).ConfigureAwait(false); - await context.Database.ExecuteSqlRawAsync("PRAGMA wal_checkpoint(TRUNCATE)", cancellationToken).ConfigureAwait(false); - logger.LogInformation("jellyfin.db optimized successfully!"); - } - } - - /// - public void OnModelCreating(ModelBuilder modelBuilder) - { - modelBuilder.SetDefaultDateTimeKind(DateTimeKind.Utc); - } - - /// - public async Task RunShutdownTask(CancellationToken cancellationToken) - { - if (DbContextFactory is null) - { - return; - } - - // Run before disposing the application - var context = await DbContextFactory.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); - await using (context.ConfigureAwait(false)) - { - await context.Database.ExecuteSqlRawAsync("PRAGMA optimize", cancellationToken).ConfigureAwait(false); - } - - SqliteConnection.ClearAllPools(); - } - - /// - public void ConfigureConventions(ModelConfigurationBuilder configurationBuilder) - { - configurationBuilder.Conventions.Add(_ => new DoNotUseReturningClauseConvention()); - } - - /// - public Task MigrationBackupFast(CancellationToken cancellationToken) - { - var key = DateTime.UtcNow.ToString("yyyyMMddhhmmss", CultureInfo.InvariantCulture); - var path = Path.Combine(applicationPaths.DataPath, "jellyfin.db"); - var backupFile = Path.Combine(applicationPaths.DataPath, BackupFolderName); - Directory.CreateDirectory(backupFile); - - backupFile = Path.Combine(backupFile, $"{key}_jellyfin.db"); - File.Copy(path, backupFile); - return Task.FromResult(key); - } - - /// - public Task RestoreBackupFast(string key, CancellationToken cancellationToken) - { - // ensure there are absolutly no dangling Sqlite connections. - SqliteConnection.ClearAllPools(); - var path = Path.Combine(applicationPaths.DataPath, "jellyfin.db"); - var backupFile = Path.Combine(applicationPaths.DataPath, BackupFolderName, $"{key}_jellyfin.db"); - - if (!File.Exists(backupFile)) - { - logger.LogCritical("Tried to restore a backup that does not exist: {Key}", key); - return Task.CompletedTask; - } - - File.Copy(backupFile, path, true); - return Task.CompletedTask; - } - - /// - public Task DeleteBackup(string key) - { - var backupFile = Path.Combine(applicationPaths.DataPath, BackupFolderName, $"{key}_jellyfin.db"); - - if (!File.Exists(backupFile)) - { - logger.LogCritical("Tried to delete a backup that does not exist: {Key}", key); - return Task.CompletedTask; - } - - File.Delete(backupFile); - return Task.CompletedTask; - } - - /// - public async Task PurgeDatabase(JellyfinDbContext dbContext, IEnumerable? tableNames) - { - ArgumentNullException.ThrowIfNull(tableNames); - - var deleteQueries = new List(); - foreach (var tableName in tableNames) - { - deleteQueries.Add($"DELETE FROM \"{tableName}\";"); - } - - var deleteAllQuery = - $""" - PRAGMA foreign_keys = OFF; - {string.Join('\n', deleteQueries)} - PRAGMA foreign_keys = ON; - """; - - await dbContext.Database.ExecuteSqlRawAsync(deleteAllQuery).ConfigureAwait(false); - } - - /// - public async Task EnsureTablesExistAsync(CancellationToken cancellationToken = default) - { - try - { - logger.LogInformation("Checking SQLite database for missing tables..."); - - var context = await DbContextFactory!.CreateDbContextAsync(cancellationToken).ConfigureAwait(false); - await using (context.ConfigureAwait(false)) - { - // Get pending migrations - var pendingMigrations = await context.Database.GetPendingMigrationsAsync(cancellationToken).ConfigureAwait(false); - var pendingMigrationsList = pendingMigrations.ToList(); - - if (pendingMigrationsList.Count > 0) - { - logger.LogInformation("Found {Count} pending migrations: {Migrations}", pendingMigrationsList.Count, string.Join(", ", pendingMigrationsList)); - logger.LogInformation("Applying migrations..."); - - try - { - // Apply all pending migrations - await context.Database.MigrateAsync(cancellationToken).ConfigureAwait(false); - logger.LogInformation("Successfully applied {Count} migrations", pendingMigrationsList.Count); - } - catch (InvalidOperationException ex) when (ex.Message.Contains("pending changes", StringComparison.OrdinalIgnoreCase)) - { - // This can happen if the model has changed but migrations haven't been generated - logger.LogWarning("Model has pending changes. This may indicate missing migration files. Error: {Message}", ex.Message); - logger.LogWarning("If you're seeing this on a test/production system, ensure all migration files are deployed."); - throw; - } - } - else - { - logger.LogInformation("All database tables are up to date. No migrations needed."); - } - - // Verify database integrity - var tableCount = await context.Database.ExecuteSqlRawAsync( - "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'", - cancellationToken).ConfigureAwait(false); - - logger.LogDebug("Database contains {TableCount} user tables", tableCount); - logger.LogInformation("Database table verification complete"); - } - } - catch (Exception ex) - { - logger.LogError(ex, "Failed to ensure SQLite tables exist. Error: {Message}", ex.Message); - throw; - } - } -} diff --git a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/ValueConverters/DateTimeKindValueConverter.cs b/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/ValueConverters/DateTimeKindValueConverter.cs deleted file mode 100644 index ee8c54a7..00000000 --- a/src/Jellyfin.Database/Jellyfin.Database.Providers.Sqlite/ValueConverters/DateTimeKindValueConverter.cs +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright (c) PlaceholderCompany. All rights reserved. -// - -namespace Jellyfin.Database.Providers.Sqlite.ValueConverters -{ - using System; - using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - - /// - /// ValueConverter to specify kind. - /// - public class DateTimeKindValueConverter : ValueConverter - { - /// - /// Initializes a new instance of the class. - /// - /// The kind to specify. - /// The mapping hints. - public DateTimeKindValueConverter(DateTimeKind kind, ConverterMappingHints? mappingHints = null) - : base(v => v.ToUniversalTime(), v => DateTime.SpecifyKind(v, kind), mappingHints) - { - } - } -} diff --git a/tests/Jellyfin.Server.Implementations.Tests/Data/SearchPunctuationTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Data/SearchPunctuationTests.cs index e2c37811..8f292d6f 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Data/SearchPunctuationTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Data/SearchPunctuationTests.cs @@ -2,6 +2,8 @@ // Copyright (c) PlaceholderCompany. All rights reserved. // +#pragma warning disable CA1308 // Normalize strings to uppercase + namespace Jellyfin.Server.Implementations.Tests.Data { using System; @@ -28,11 +30,11 @@ namespace Jellyfin.Server.Implementations.Tests.Data var configSection = new Mock(); configSection - .SetupGet(x => x[It.Is(s => s == MediaBrowser.Controller.Extensions.ConfigurationExtensions.SqliteCacheSizeKey)]) + .SetupGet(x => x[It.IsAny()]) .Returns("0"); var config = new Mock(); config - .Setup(x => x.GetSection(It.Is(s => s == MediaBrowser.Controller.Extensions.ConfigurationExtensions.SqliteCacheSizeKey))) + .Setup(x => x.GetSection(It.IsAny())) .Returns(configSection.Object); _fixture = new Fixture().Customize(new AutoMoqCustomization { ConfigureMembers = true }); diff --git a/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs index 376fa726..062272c4 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Data/SqliteItemRepositoryTests.cs @@ -36,11 +36,11 @@ namespace Jellyfin.Server.Implementations.Tests.Data var configSection = new Mock(); configSection - .SetupGet(x => x[It.Is(s => s == MediaBrowser.Controller.Extensions.ConfigurationExtensions.SqliteCacheSizeKey)]) + .SetupGet(x => x[It.IsAny()]) .Returns("0"); var config = new Mock(); config - .Setup(x => x.GetSection(It.Is(s => s == MediaBrowser.Controller.Extensions.ConfigurationExtensions.SqliteCacheSizeKey))) + .Setup(x => x.GetSection(It.IsAny())) .Returns(configSection.Object); _fixture = new Fixture().Customize(new AutoMoqCustomization { ConfigureMembers = true }); diff --git a/tests/Jellyfin.Server.Implementations.Tests/HttpServer/WebSocketConnectionTests.cs b/tests/Jellyfin.Server.Implementations.Tests/HttpServer/WebSocketConnectionTests.cs index aef4edd7..73f973b0 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/HttpServer/WebSocketConnectionTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/HttpServer/WebSocketConnectionTests.cs @@ -2,6 +2,8 @@ // Copyright (c) PlaceholderCompany. All rights reserved. // +#pragma warning disable CA1517 // Do not use overloads of StartsWith/EndsWith with char when multiple characters are expected + namespace Jellyfin.Server.Implementations.Tests.HttpServer { using System; @@ -54,7 +56,7 @@ namespace Jellyfin.Server.Implementations.Tests.HttpServer internal sealed class BufferSegment : ReadOnlySequenceSegment { - public BufferSegment(Memory memory) + public BufferSegment(ReadOnlyMemory memory) { Memory = memory; } diff --git a/tests/Jellyfin.Server.Implementations.Tests/Item/BaseItemRepositoryTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Item/BaseItemRepositoryTests.cs index d5ff2a8e..df769acf 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Item/BaseItemRepositoryTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Item/BaseItemRepositoryTests.cs @@ -8,7 +8,6 @@ using System; using System.Threading; using System.Threading.Tasks; using Jellyfin.Database.Implementations; -using Microsoft.EntityFrameworkCore; using Jellyfin.Database.Implementations.Entities; using Jellyfin.Database.Implementations.Locking; using Jellyfin.Server.Implementations.Item; @@ -116,7 +115,7 @@ public class BaseItemRepositoryTests await context.SaveChangesAsync(); - var placeholder = await context.BaseItems.SingleAsync(e => e.Id == BaseItemRepository.PlaceholderId); + var placeholder = await context.BaseItems.SingleAsync(e => e.Id.Equals(BaseItemRepository.PlaceholderId)); context.BaseItems.Remove(placeholder); await context.SaveChangesAsync(); @@ -133,11 +132,11 @@ public class BaseItemRepositoryTests await repository.DeleteItemAsync([itemId], CancellationToken.None); await using var verificationContext = await dbFactory.CreateDbContextAsync(CancellationToken.None); - var recreatedPlaceholder = await verificationContext.BaseItems.SingleOrDefaultAsync(e => e.Id == BaseItemRepository.PlaceholderId); + var recreatedPlaceholder = await verificationContext.BaseItems.SingleOrDefaultAsync(e => e.Id.Equals(BaseItemRepository.PlaceholderId)); var detachedUserData = await verificationContext.UserData.SingleAsync(); Assert.NotNull(recreatedPlaceholder); - Assert.Null(await verificationContext.BaseItems.SingleOrDefaultAsync(e => e.Id == itemId)); + Assert.Null(await verificationContext.BaseItems.SingleOrDefaultAsync(e => e.Id.Equals(itemId))); Assert.Equal(BaseItemRepository.PlaceholderId, detachedUserData.ItemId); Assert.NotNull(detachedUserData.RetentionDate); } diff --git a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj index 269daaa1..94fce55b 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj +++ b/tests/Jellyfin.Server.Implementations.Tests/Jellyfin.Server.Implementations.Tests.csproj @@ -22,6 +22,7 @@ + diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/AudioResolverTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/AudioResolverTests.cs index d66db835..454f0b32 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Library/AudioResolverTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/AudioResolverTests.cs @@ -60,7 +60,7 @@ public class AudioResolverTests var childrenMetadata = children.Select(name => new FileSystemMetadata { FullName = parent + "/" + name, - IsDirectory = name.EndsWith("/", StringComparison.OrdinalIgnoreCase) + IsDirectory = name.EndsWith('/', StringComparison.OrdinalIgnoreCase) }).ToArray(); var resolver = new AudioResolver(_namingOptions); diff --git a/tests/Jellyfin.Server.Integration.Tests/Controllers/BrandingControllerTests.cs b/tests/Jellyfin.Server.Integration.Tests/Controllers/BrandingControllerTests.cs index 1d564a58..00ac587e 100644 --- a/tests/Jellyfin.Server.Integration.Tests/Controllers/BrandingControllerTests.cs +++ b/tests/Jellyfin.Server.Integration.Tests/Controllers/BrandingControllerTests.cs @@ -2,6 +2,8 @@ // Copyright (c) PlaceholderCompany. All rights reserved. // +#pragma warning disable CA1054 // URI parameters in test methods + namespace Jellyfin.Server.Integration.Tests { using System.Net; diff --git a/tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs b/tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs index 3947e04a..6c878ab5 100644 --- a/tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs +++ b/tests/Jellyfin.Server.Integration.Tests/EncodedQueryStringTest.cs @@ -2,6 +2,8 @@ // Copyright (c) PlaceholderCompany. All rights reserved. // +#pragma warning disable CA1054 // URI parameters in test methods + namespace Jellyfin.Server.Integration.Tests { using System.Net; diff --git a/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs b/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs index 70ec9703..bd2a0222 100644 --- a/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs +++ b/tests/Jellyfin.Server.Integration.Tests/JellyfinApplicationFactory.cs @@ -169,12 +169,12 @@ namespace Jellyfin.Server.Integration.Tests NullLogger.Instance.Log(logLevel, eventId, state, exception, formatter); } - public Microsoft.Extensions.Logging.ILogger With(Microsoft.Extensions.Logging.ILogger logger) + public Microsoft.Extensions.Logging.ILogger Attach(Microsoft.Extensions.Logging.ILogger logger) { return this; } - public IStartupLogger With(Microsoft.Extensions.Logging.ILogger logger) + public IStartupLogger Attach(Microsoft.Extensions.Logging.ILogger logger) { return new NullStartupLogger(); } @@ -184,12 +184,12 @@ namespace Jellyfin.Server.Integration.Tests return new NullStartupLogger(); } - IStartupLogger IStartupLogger.With(Microsoft.Extensions.Logging.ILogger logger) + IStartupLogger IStartupLogger.Attach(Microsoft.Extensions.Logging.ILogger logger) { return this; } - IStartupLogger IStartupLogger.With(Microsoft.Extensions.Logging.ILogger logger) + IStartupLogger IStartupLogger.Attach(Microsoft.Extensions.Logging.ILogger logger) { return this; }