瀏覽代碼

Merge remote-tracking branch 'upstream/master' into fixes

crobibero 4 年之前
父節點
當前提交
09bcc38feb

+ 12 - 2
.vscode/launch.json

@@ -6,11 +6,21 @@
             "type": "coreclr",
             "request": "launch",
             "preLaunchTask": "build",
-            // If you have changed target frameworks, make sure to update the program path.
             "program": "${workspaceFolder}/Jellyfin.Server/bin/Debug/netcoreapp3.1/jellyfin.dll",
             "args": [],
             "cwd": "${workspaceFolder}/Jellyfin.Server",
-            // For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window
+            "console": "internalConsole",
+            "stopAtEntry": false,
+            "internalConsoleOptions": "openOnSessionStart"
+        },
+        {
+            "name": ".NET Core Launch (nowebclient)",
+            "type": "coreclr",
+            "request": "launch",
+            "preLaunchTask": "build",
+            "program": "${workspaceFolder}/Jellyfin.Server/bin/Debug/netcoreapp3.1/jellyfin.dll",
+            "args": ["--nowebclient"],
+            "cwd": "${workspaceFolder}/Jellyfin.Server",
             "console": "internalConsole",
             "stopAtEntry": false,
             "internalConsoleOptions": "openOnSessionStart"

+ 1 - 1
Emby.Server.Implementations/Emby.Server.Implementations.csproj

@@ -38,7 +38,7 @@
     <PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.6" />
     <PackageReference Include="Mono.Nat" Version="2.0.2" />
     <PackageReference Include="prometheus-net.DotNetRuntime" Version="3.3.1" />
-    <PackageReference Include="ServiceStack.Text.Core" Version="5.9.0" />
+    <PackageReference Include="ServiceStack.Text.Core" Version="5.9.2" />
     <PackageReference Include="sharpcompress" Version="0.26.0" />
     <PackageReference Include="SQLitePCL.pretty.netstandard" Version="2.1.0" />
     <PackageReference Include="DotNet.Glob" Version="3.0.9" />

+ 41 - 52
Emby.Server.Implementations/EntryPoints/LibraryChangedNotifier.cs

@@ -23,10 +23,12 @@ namespace Emby.Server.Implementations.EntryPoints
     public class LibraryChangedNotifier : IServerEntryPoint
     {
         /// <summary>
-        /// The library manager.
+        /// The library update duration.
         /// </summary>
-        private readonly ILibraryManager _libraryManager;
+        private const int LibraryUpdateDuration = 30000;
 
+        private readonly ILibraryManager _libraryManager;
+        private readonly IProviderManager _providerManager;
         private readonly ISessionManager _sessionManager;
         private readonly IUserManager _userManager;
         private readonly ILogger<LibraryChangedNotifier> _logger;
@@ -38,23 +40,10 @@ namespace Emby.Server.Implementations.EntryPoints
 
         private readonly List<Folder> _foldersAddedTo = new List<Folder>();
         private readonly List<Folder> _foldersRemovedFrom = new List<Folder>();
-
         private readonly List<BaseItem> _itemsAdded = new List<BaseItem>();
         private readonly List<BaseItem> _itemsRemoved = new List<BaseItem>();
         private readonly List<BaseItem> _itemsUpdated = new List<BaseItem>();
-
-        /// <summary>
-        /// Gets or sets the library update timer.
-        /// </summary>
-        /// <value>The library update timer.</value>
-        private Timer LibraryUpdateTimer { get; set; }
-
-        /// <summary>
-        /// The library update duration.
-        /// </summary>
-        private const int LibraryUpdateDuration = 30000;
-
-        private readonly IProviderManager _providerManager;
+        private readonly Dictionary<Guid, DateTime> _lastProgressMessageTimes = new Dictionary<Guid, DateTime>();
 
         public LibraryChangedNotifier(
             ILibraryManager libraryManager,
@@ -70,22 +59,26 @@ namespace Emby.Server.Implementations.EntryPoints
             _providerManager = providerManager;
         }
 
+        /// <summary>
+        /// Gets or sets the library update timer.
+        /// </summary>
+        /// <value>The library update timer.</value>
+        private Timer LibraryUpdateTimer { get; set; }
+
         public Task RunAsync()
         {
-            _libraryManager.ItemAdded += libraryManager_ItemAdded;
-            _libraryManager.ItemUpdated += libraryManager_ItemUpdated;
-            _libraryManager.ItemRemoved += libraryManager_ItemRemoved;
+            _libraryManager.ItemAdded += OnLibraryItemAdded;
+            _libraryManager.ItemUpdated += OnLibraryItemUpdated;
+            _libraryManager.ItemRemoved += OnLibraryItemRemoved;
 
-            _providerManager.RefreshCompleted += _providerManager_RefreshCompleted;
-            _providerManager.RefreshStarted += _providerManager_RefreshStarted;
-            _providerManager.RefreshProgress += _providerManager_RefreshProgress;
+            _providerManager.RefreshCompleted += OnProviderRefreshCompleted;
+            _providerManager.RefreshStarted += OnProviderRefreshStarted;
+            _providerManager.RefreshProgress += OnProviderRefreshProgress;
 
             return Task.CompletedTask;
         }
 
-        private Dictionary<Guid, DateTime> _lastProgressMessageTimes = new Dictionary<Guid, DateTime>();
-
-        private void _providerManager_RefreshProgress(object sender, GenericEventArgs<Tuple<BaseItem, double>> e)
+        private void OnProviderRefreshProgress(object sender, GenericEventArgs<Tuple<BaseItem, double>> e)
         {
             var item = e.Argument.Item1;
 
@@ -122,9 +115,11 @@ namespace Emby.Server.Implementations.EntryPoints
 
             foreach (var collectionFolder in collectionFolders)
             {
-                var collectionFolderDict = new Dictionary<string, string>();
-                collectionFolderDict["ItemId"] = collectionFolder.Id.ToString("N", CultureInfo.InvariantCulture);
-                collectionFolderDict["Progress"] = (collectionFolder.GetRefreshProgress() ?? 0).ToString(CultureInfo.InvariantCulture);
+                var collectionFolderDict = new Dictionary<string, string>
+                {
+                    ["ItemId"] = collectionFolder.Id.ToString("N", CultureInfo.InvariantCulture),
+                    ["Progress"] = (collectionFolder.GetRefreshProgress() ?? 0).ToString(CultureInfo.InvariantCulture)
+                };
 
                 try
                 {
@@ -136,21 +131,19 @@ namespace Emby.Server.Implementations.EntryPoints
             }
         }
 
-        private void _providerManager_RefreshStarted(object sender, GenericEventArgs<BaseItem> e)
+        private void OnProviderRefreshStarted(object sender, GenericEventArgs<BaseItem> e)
         {
-            _providerManager_RefreshProgress(sender, new GenericEventArgs<Tuple<BaseItem, double>>(new Tuple<BaseItem, double>(e.Argument, 0)));
+            OnProviderRefreshProgress(sender, new GenericEventArgs<Tuple<BaseItem, double>>(new Tuple<BaseItem, double>(e.Argument, 0)));
         }
 
-        private void _providerManager_RefreshCompleted(object sender, GenericEventArgs<BaseItem> e)
+        private void OnProviderRefreshCompleted(object sender, GenericEventArgs<BaseItem> e)
         {
-            _providerManager_RefreshProgress(sender, new GenericEventArgs<Tuple<BaseItem, double>>(new Tuple<BaseItem, double>(e.Argument, 100)));
+            OnProviderRefreshProgress(sender, new GenericEventArgs<Tuple<BaseItem, double>>(new Tuple<BaseItem, double>(e.Argument, 100)));
         }
 
         private static bool EnableRefreshMessage(BaseItem item)
         {
-            var folder = item as Folder;
-
-            if (folder == null)
+            if (!(item is Folder folder))
             {
                 return false;
             }
@@ -183,7 +176,7 @@ namespace Emby.Server.Implementations.EntryPoints
         /// </summary>
         /// <param name="sender">The source of the event.</param>
         /// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
-        void libraryManager_ItemAdded(object sender, ItemChangeEventArgs e)
+        private void OnLibraryItemAdded(object sender, ItemChangeEventArgs e)
         {
             if (!FilterItem(e.Item))
             {
@@ -205,8 +198,7 @@ namespace Emby.Server.Implementations.EntryPoints
                     LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite);
                 }
 
-                var parent = e.Item.GetParent() as Folder;
-                if (parent != null)
+                if (e.Item.GetParent() is Folder parent)
                 {
                     _foldersAddedTo.Add(parent);
                 }
@@ -220,7 +212,7 @@ namespace Emby.Server.Implementations.EntryPoints
         /// </summary>
         /// <param name="sender">The source of the event.</param>
         /// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
-        void libraryManager_ItemUpdated(object sender, ItemChangeEventArgs e)
+        private void OnLibraryItemUpdated(object sender, ItemChangeEventArgs e)
         {
             if (!FilterItem(e.Item))
             {
@@ -231,8 +223,7 @@ namespace Emby.Server.Implementations.EntryPoints
             {
                 if (LibraryUpdateTimer == null)
                 {
-                    LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration,
-                                                   Timeout.Infinite);
+                    LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, Timeout.Infinite);
                 }
                 else
                 {
@@ -248,7 +239,7 @@ namespace Emby.Server.Implementations.EntryPoints
         /// </summary>
         /// <param name="sender">The source of the event.</param>
         /// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</param>
-        void libraryManager_ItemRemoved(object sender, ItemChangeEventArgs e)
+        private void OnLibraryItemRemoved(object sender, ItemChangeEventArgs e)
         {
             if (!FilterItem(e.Item))
             {
@@ -259,16 +250,14 @@ namespace Emby.Server.Implementations.EntryPoints
             {
                 if (LibraryUpdateTimer == null)
                 {
-                    LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration,
-                                                   Timeout.Infinite);
+                    LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, Timeout.Infinite);
                 }
                 else
                 {
                     LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite);
                 }
 
-                var parent = e.Parent as Folder;
-                if (parent != null)
+                if (e.Parent is Folder parent)
                 {
                     _foldersRemovedFrom.Add(parent);
                 }
@@ -486,13 +475,13 @@ namespace Emby.Server.Implementations.EntryPoints
                     LibraryUpdateTimer = null;
                 }
 
-                _libraryManager.ItemAdded -= libraryManager_ItemAdded;
-                _libraryManager.ItemUpdated -= libraryManager_ItemUpdated;
-                _libraryManager.ItemRemoved -= libraryManager_ItemRemoved;
+                _libraryManager.ItemAdded -= OnLibraryItemAdded;
+                _libraryManager.ItemUpdated -= OnLibraryItemUpdated;
+                _libraryManager.ItemRemoved -= OnLibraryItemRemoved;
 
-                _providerManager.RefreshCompleted -= _providerManager_RefreshCompleted;
-                _providerManager.RefreshStarted -= _providerManager_RefreshStarted;
-                _providerManager.RefreshProgress -= _providerManager_RefreshProgress;
+                _providerManager.RefreshCompleted -= OnProviderRefreshCompleted;
+                _providerManager.RefreshStarted -= OnProviderRefreshStarted;
+                _providerManager.RefreshProgress -= OnProviderRefreshProgress;
             }
         }
     }

+ 2 - 2
Emby.Server.Implementations/Localization/Core/de.json

@@ -5,7 +5,7 @@
     "Artists": "Interpreten",
     "AuthenticationSucceededWithUserName": "{0} hat sich erfolgreich angemeldet",
     "Books": "Bücher",
-    "CameraImageUploadedFrom": "Ein neues Foto wurde von {0} hochgeladen",
+    "CameraImageUploadedFrom": "Ein neues Kamerafoto wurde von {0} hochgeladen",
     "Channels": "Kanäle",
     "ChapterNameValue": "Kapitel {0}",
     "Collections": "Sammlungen",
@@ -106,7 +106,7 @@
     "TaskCleanLogsDescription": "Lösche Log Dateien die älter als {0} Tage sind.",
     "TaskCleanLogs": "Lösche Log Pfad",
     "TaskRefreshLibraryDescription": "Scanne alle Bibliotheken für hinzugefügte Datein und erneuere Metadaten.",
-    "TaskRefreshLibrary": "Scanne alle Bibliotheken",
+    "TaskRefreshLibrary": "Scanne Medien-Bibliothek",
     "TaskRefreshChapterImagesDescription": "Kreiert Vorschaubilder für Videos welche Kapitel haben.",
     "TaskRefreshChapterImages": "Extrahiert Kapitel-Bilder",
     "TaskCleanCacheDescription": "Löscht Zwischenspeicherdatein die nicht länger von System gebraucht werden.",

+ 94 - 13
Emby.Server.Implementations/Localization/Core/uk.json

@@ -1,13 +1,13 @@
 {
-    "MusicVideos": "Музичні відео",
+    "MusicVideos": "Музичні кліпи",
     "Music": "Музика",
     "Movies": "Фільми",
-    "MessageApplicationUpdatedTo": "Jellyfin Server був оновлений до версії {0}",
-    "MessageApplicationUpdated": "Jellyfin Server був оновлений",
+    "MessageApplicationUpdatedTo": "Jellyfin Server оновлено до версії {0}",
+    "MessageApplicationUpdated": "Jellyfin Server оновлено",
     "Latest": "Останні",
-    "LabelIpAddressValue": "IP-адреси: {0}",
-    "ItemRemovedWithName": "{0} видалено з бібліотеки",
-    "ItemAddedWithName": "{0} додано до бібліотеки",
+    "LabelIpAddressValue": "IP-адреса: {0}",
+    "ItemRemovedWithName": "{0} видалено з медіатеки",
+    "ItemAddedWithName": "{0} додано до медіатеки",
     "HeaderNextUp": "Наступний",
     "HeaderLiveTV": "Ефірне ТБ",
     "HeaderFavoriteSongs": "Улюблені пісні",
@@ -17,20 +17,101 @@
     "HeaderFavoriteAlbums": "Улюблені альбоми",
     "HeaderContinueWatching": "Продовжити перегляд",
     "HeaderCameraUploads": "Завантажено з камери",
-    "HeaderAlbumArtists": "Виконавці альбомів",
+    "HeaderAlbumArtists": "Виконавці альбому",
     "Genres": "Жанри",
-    "Folders": "Директорії",
+    "Folders": "Каталоги",
     "Favorites": "Улюблені",
-    "DeviceOnlineWithName": "{0} під'єднано",
-    "DeviceOfflineWithName": "{0} від'єднано",
+    "DeviceOnlineWithName": "Пристрій {0} підключився",
+    "DeviceOfflineWithName": "Пристрій {0} відключився",
     "Collections": "Колекції",
-    "ChapterNameValue": "Глава {0}",
+    "ChapterNameValue": "Розділ {0}",
     "Channels": "Канали",
     "CameraImageUploadedFrom": "Нова фотографія завантажена з {0}",
     "Books": "Книги",
-    "AuthenticationSucceededWithUserName": "{0} успішно авторизовані",
+    "AuthenticationSucceededWithUserName": "{0} успішно авторизований",
     "Artists": "Виконавці",
     "Application": "Додаток",
     "AppDeviceValues": "Додаток: {0}, Пристрій: {1}",
-    "Albums": "Альбоми"
+    "Albums": "Альбоми",
+    "NotificationOptionServerRestartRequired": "Необхідно перезапустити сервер",
+    "NotificationOptionPluginUpdateInstalled": "Встановлено оновлення плагіна",
+    "NotificationOptionPluginUninstalled": "Плагін видалено",
+    "NotificationOptionPluginInstalled": "Плагін встановлено",
+    "NotificationOptionPluginError": "Помилка плагіна",
+    "NotificationOptionNewLibraryContent": "Додано новий контент",
+    "HomeVideos": "Домашнє відео",
+    "FailedLoginAttemptWithUserName": "Невдала спроба входу від {0}",
+    "LabelRunningTimeValue": "Тривалість: {0}",
+    "TaskDownloadMissingSubtitlesDescription": "Шукає в Інтернеті відсутні субтитри на основі конфігурації метаданих.",
+    "TaskDownloadMissingSubtitles": "Завантажити відсутні субтитри",
+    "TaskRefreshChannelsDescription": "Оновлення інформації про Інтернет-канали.",
+    "TaskRefreshChannels": "Оновити канали",
+    "TaskCleanTranscodeDescription": "Вилучає файли для перекодування старше одного дня.",
+    "TaskCleanTranscode": "Очистити каталог перекодування",
+    "TaskUpdatePluginsDescription": "Завантажує та встановлює оновлення для плагінів, налаштованих на автоматичне оновлення.",
+    "TaskUpdatePlugins": "Оновити плагіни",
+    "TaskRefreshPeopleDescription": "Оновлення метаданих для акторів та режисерів у вашій медіатеці.",
+    "TaskRefreshPeople": "Оновити людей",
+    "TaskCleanLogsDescription": "Видаляє файли журналу, яким більше {0} днів.",
+    "TaskCleanLogs": "Очистити журнали",
+    "TaskRefreshLibraryDescription": "Сканує медіатеку на нові файли та оновлює метадані.",
+    "TaskRefreshLibrary": "Сканувати медіатеку",
+    "TaskRefreshChapterImagesDescription": "Створює ескізи для відео, які мають розділи.",
+    "TaskRefreshChapterImages": "Створити ескізи розділів",
+    "TaskCleanCacheDescription": "Видаляє файли кешу, які більше не потрібні системі.",
+    "TaskCleanCache": "Очистити кеш",
+    "TasksChannelsCategory": "Інтернет-канали",
+    "TasksApplicationCategory": "Додаток",
+    "TasksLibraryCategory": "Медіатека",
+    "TasksMaintenanceCategory": "Обслуговування",
+    "VersionNumber": "Версія {0}",
+    "ValueSpecialEpisodeName": "Спецепізод - {0}",
+    "ValueHasBeenAddedToLibrary": "{0} додано до медіатеки",
+    "UserStoppedPlayingItemWithValues": "{0} закінчив відтворення {1} на {2}",
+    "UserStartedPlayingItemWithValues": "{0} відтворює {1} на {2}",
+    "UserPolicyUpdatedWithName": "Політика користувача оновлена для {0}",
+    "UserPasswordChangedWithName": "Пароль змінено для користувача {0}",
+    "UserOnlineFromDevice": "{0} підключився з {1}",
+    "UserOfflineFromDevice": "{0} відключився від {1}",
+    "UserLockedOutWithName": "Користувача {0} заблоковано",
+    "UserDownloadingItemWithValues": "{0} завантажує {1}",
+    "UserDeletedWithName": "Користувача {0} видалено",
+    "UserCreatedWithName": "Користувача {0} створено",
+    "User": "Користувач",
+    "TvShows": "ТВ-шоу",
+    "System": "Система",
+    "Sync": "Синхронізація",
+    "SubtitleDownloadFailureFromForItem": "Не вдалося завантажити субтитри з {0} для {1}",
+    "StartupEmbyServerIsLoading": "Jellyfin Server завантажується. Будь ласка, спробуйте трішки пізніше.",
+    "Songs": "Пісні",
+    "Shows": "Шоу",
+    "ServerNameNeedsToBeRestarted": "{0} потрібно перезапустити",
+    "ScheduledTaskStartedWithName": "{0} розпочато",
+    "ScheduledTaskFailedWithName": "Помилка {0}",
+    "ProviderValue": "Постачальник: {0}",
+    "PluginUpdatedWithName": "{0} оновлено",
+    "PluginUninstalledWithName": "{0} видалено",
+    "PluginInstalledWithName": "{0} встановлено",
+    "Plugin": "Плагін",
+    "Playlists": "Плейлисти",
+    "Photos": "Фотографії",
+    "NotificationOptionVideoPlaybackStopped": "Відтворення відео зупинено",
+    "NotificationOptionVideoPlayback": "Розпочато відтворення відео",
+    "NotificationOptionUserLockedOut": "Користувача заблоковано",
+    "NotificationOptionTaskFailed": "Помилка запланованого завдання",
+    "NotificationOptionInstallationFailed": "Помилка встановлення",
+    "NotificationOptionCameraImageUploaded": "Фотографію завантажено",
+    "NotificationOptionAudioPlaybackStopped": "Відтворення аудіо зупинено",
+    "NotificationOptionAudioPlayback": "Розпочато відтворення аудіо",
+    "NotificationOptionApplicationUpdateInstalled": "Встановлено оновлення додатка",
+    "NotificationOptionApplicationUpdateAvailable": "Доступне оновлення додатка",
+    "NewVersionIsAvailable": "Для завантаження доступна нова версія Jellyfin Server.",
+    "NameSeasonUnknown": "Сезон Невідомий",
+    "NameSeasonNumber": "Сезон {0}",
+    "NameInstallFailed": "Не вдалося встановити {0}",
+    "MixedContent": "Змішаний контент",
+    "MessageServerConfigurationUpdated": "Конфігурація сервера оновлена",
+    "MessageNamedServerConfigurationUpdatedWithValue": "Розділ конфігурації сервера {0} оновлено",
+    "Inherit": "Успадкувати",
+    "HeaderRecordingGroups": "Групи запису"
 }

+ 2 - 3
Jellyfin.Api/Auth/FirstTimeOrIgnoreParentalControlSetupPolicy/FirstTimeOrIgnoreParentalControlSetupHandler.cs

@@ -1,5 +1,4 @@
 using System.Threading.Tasks;
-using Jellyfin.Api.Auth.IgnoreParentalControlPolicy;
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Common.Net;
 using MediaBrowser.Controller.Library;
@@ -11,7 +10,7 @@ namespace Jellyfin.Api.Auth.FirstTimeOrIgnoreParentalControlSetupPolicy
     /// <summary>
     /// Ignore parental control schedule and allow before startup wizard has been completed.
     /// </summary>
-    public class FirstTimeOrIgnoreParentalControlSetupHandler : BaseAuthorizationHandler<IgnoreParentalControlRequirement>
+    public class FirstTimeOrIgnoreParentalControlSetupHandler : BaseAuthorizationHandler<FirstTimeOrIgnoreParentalControlSetupRequirement>
     {
         private readonly IConfigurationManager _configurationManager;
 
@@ -33,7 +32,7 @@ namespace Jellyfin.Api.Auth.FirstTimeOrIgnoreParentalControlSetupPolicy
         }
 
         /// <inheritdoc />
-        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IgnoreParentalControlRequirement requirement)
+        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FirstTimeOrIgnoreParentalControlSetupRequirement requirement)
         {
             if (!_configurationManager.CommonConfiguration.IsStartupWizardCompleted)
             {

+ 1 - 1
Jellyfin.Api/Controllers/UserController.cs

@@ -386,7 +386,7 @@ namespace Jellyfin.Api.Controllers
             var user = _userManager.GetUserById(userId);
 
             // If removing admin access
-            if (!(newPolicy.IsAdministrator && user.HasPermission(PermissionKind.IsAdministrator)))
+            if (!newPolicy.IsAdministrator && user.HasPermission(PermissionKind.IsAdministrator))
             {
                 if (_userManager.Users.Count(i => i.HasPermission(PermissionKind.IsAdministrator)) == 1)
                 {

+ 1 - 1
Jellyfin.Api/Jellyfin.Api.csproj

@@ -18,7 +18,7 @@
     <PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
     <PackageReference Include="Microsoft.Extensions.Http" Version="3.1.6" />
     <PackageReference Include="Swashbuckle.AspNetCore" Version="5.5.1" />
-    <PackageReference Include="Swashbuckle.AspNetCore.ReDoc" Version="5.3.3" />
+    <PackageReference Include="Swashbuckle.AspNetCore.ReDoc" Version="5.5.1" />
   </ItemGroup>
 
   <ItemGroup>

+ 2 - 2
Jellyfin.Drawing.Skia/StripCollageBuilder.cs

@@ -115,7 +115,7 @@ namespace Jellyfin.Drawing.Skia
 
                 // resize to the same aspect as the original
                 int iWidth = Math.Abs(iHeight * currentBitmap.Width / currentBitmap.Height);
-                using var resizedImage = SkiaEncoder.ResizeImage(bitmap, new SKImageInfo(iWidth, iHeight, currentBitmap.ColorType, currentBitmap.AlphaType, currentBitmap.ColorSpace));
+                using var resizedImage = SkiaEncoder.ResizeImage(currentBitmap, new SKImageInfo(iWidth, iHeight, currentBitmap.ColorType, currentBitmap.AlphaType, currentBitmap.ColorSpace));
 
                 // crop image
                 int ix = Math.Abs((iWidth - iSlice) / 2);
@@ -177,7 +177,7 @@ namespace Jellyfin.Drawing.Skia
 
                     // Scale image. The FromBitmap creates a copy
                     var imageInfo = new SKImageInfo(cellWidth, cellHeight, currentBitmap.ColorType, currentBitmap.AlphaType, currentBitmap.ColorSpace);
-                    using var resizedBitmap = SKBitmap.FromImage(SkiaEncoder.ResizeImage(bitmap, imageInfo));
+                    using var resizedBitmap = SKBitmap.FromImage(SkiaEncoder.ResizeImage(currentBitmap, imageInfo));
 
                     // draw this image into the strip at the next position
                     var xPos = x * cellWidth;

+ 12 - 0
MediaBrowser.Providers/Manager/ProviderManager.cs

@@ -4,6 +4,8 @@ using System.Collections.Generic;
 using System.Globalization;
 using System.IO;
 using System.Linq;
+using System.Net;
+using System.Net.Mime;
 using System.Threading;
 using System.Threading.Tasks;
 using Jellyfin.Data.Entities;
@@ -22,6 +24,7 @@ using MediaBrowser.Model.Configuration;
 using MediaBrowser.Model.Entities;
 using MediaBrowser.Model.Events;
 using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Net;
 using MediaBrowser.Model.Providers;
 using Microsoft.Extensions.Logging;
 using Priority_Queue;
@@ -169,6 +172,15 @@ namespace MediaBrowser.Providers.Manager
                 }
             }
 
+            // thetvdb will sometimes serve a rubbish 404 html page with a 200 OK code, because reasons...
+            if (response.ContentType.Equals(MediaTypeNames.Text.Html, StringComparison.OrdinalIgnoreCase))
+            {
+                throw new HttpException("Invalid image received.")
+                {
+                    StatusCode = HttpStatusCode.NotFound
+                };
+            }
+
             await SaveImage(item, response.Content, response.ContentType, type, imageIndex, cancellationToken).ConfigureAwait(false);
         }
 

+ 1 - 1
MediaBrowser.Providers/MediaBrowser.Providers.csproj

@@ -20,7 +20,7 @@
     <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.1.6" />
     <PackageReference Include="OptimizedPriorityQueue" Version="4.2.0" />
     <PackageReference Include="PlaylistsNET" Version="1.1.2" />
-    <PackageReference Include="TvDbSharper" Version="3.2.0" />
+    <PackageReference Include="TvDbSharper" Version="3.2.1" />
   </ItemGroup>
 
   <PropertyGroup>

+ 2 - 0
README.md

@@ -166,3 +166,5 @@ To instruct the server not to host the web content, there is a `nowebclient` con
 switch `--nowebclient` or the environment variable `JELLYFIN_NOWEBCONTENT=true`.
 
 Since this is a common scenario, there is also a separate launch profile defined for Visual Studio called `Jellyfin.Server (nowebcontent)` that can be selected from the 'Start Debugging' dropdown in the main toolbar.
+
+**NOTE:** The setup wizard can not be run if the web client is hosted separately.

+ 1 - 1
tests/Jellyfin.Api.Tests/Jellyfin.Api.Tests.csproj

@@ -17,7 +17,7 @@
     <PackageReference Include="AutoFixture.AutoMoq" Version="4.12.0" />
     <PackageReference Include="AutoFixture.Xunit2" Version="4.12.0" />
     <PackageReference Include="Microsoft.Extensions.Options" Version="3.1.6" />
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.0" />
     <PackageReference Include="xunit" Version="2.4.1" />
     <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
     <PackageReference Include="coverlet.collector" Version="1.3.0" />

+ 1 - 1
tests/Jellyfin.Common.Tests/Jellyfin.Common.Tests.csproj

@@ -13,7 +13,7 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.0" />
     <PackageReference Include="xunit" Version="2.4.1" />
     <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
     <PackageReference Include="coverlet.collector" Version="1.3.0" />

+ 1 - 1
tests/Jellyfin.Controller.Tests/Jellyfin.Controller.Tests.csproj

@@ -13,7 +13,7 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.0" />
     <PackageReference Include="xunit" Version="2.4.1" />
     <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
     <PackageReference Include="coverlet.collector" Version="1.3.0" />

+ 1 - 1
tests/Jellyfin.MediaEncoding.Tests/Jellyfin.MediaEncoding.Tests.csproj

@@ -19,7 +19,7 @@
   </ItemGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.0" />
     <PackageReference Include="xunit" Version="2.4.1" />
     <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
     <PackageReference Include="coverlet.collector" Version="1.3.0" />

+ 1 - 1
tests/Jellyfin.Naming.Tests/Jellyfin.Naming.Tests.csproj

@@ -13,7 +13,7 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.0" />
     <PackageReference Include="xunit" Version="2.4.1" />
     <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
     <PackageReference Include="coverlet.collector" Version="1.3.0" />

+ 1 - 1
tests/MediaBrowser.Api.Tests/MediaBrowser.Api.Tests.csproj

@@ -9,7 +9,7 @@
 
   <ItemGroup>
     <PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.6" />
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.0" />
     <PackageReference Include="xunit" Version="2.4.1" />
     <PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
     <PackageReference Include="coverlet.collector" Version="1.3.0" />