mirror of
https://github.com/jellyfin/jellyfin.git
synced 2024-07-23 06:00:47 +02:00
Merge remote-tracking branch 'upstream/master' into fixes
This commit is contained in:
commit
09bcc38feb
14
.vscode/launch.json
vendored
14
.vscode/launch.json
vendored
|
@ -6,11 +6,21 @@
|
||||||
"type": "coreclr",
|
"type": "coreclr",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"preLaunchTask": "build",
|
"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",
|
"program": "${workspaceFolder}/Jellyfin.Server/bin/Debug/netcoreapp3.1/jellyfin.dll",
|
||||||
"args": [],
|
"args": [],
|
||||||
"cwd": "${workspaceFolder}/Jellyfin.Server",
|
"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",
|
"console": "internalConsole",
|
||||||
"stopAtEntry": false,
|
"stopAtEntry": false,
|
||||||
"internalConsoleOptions": "openOnSessionStart"
|
"internalConsoleOptions": "openOnSessionStart"
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.6" />
|
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="3.1.6" />
|
||||||
<PackageReference Include="Mono.Nat" Version="2.0.2" />
|
<PackageReference Include="Mono.Nat" Version="2.0.2" />
|
||||||
<PackageReference Include="prometheus-net.DotNetRuntime" Version="3.3.1" />
|
<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="sharpcompress" Version="0.26.0" />
|
||||||
<PackageReference Include="SQLitePCL.pretty.netstandard" Version="2.1.0" />
|
<PackageReference Include="SQLitePCL.pretty.netstandard" Version="2.1.0" />
|
||||||
<PackageReference Include="DotNet.Glob" Version="3.0.9" />
|
<PackageReference Include="DotNet.Glob" Version="3.0.9" />
|
||||||
|
|
|
@ -23,10 +23,12 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||||
public class LibraryChangedNotifier : IServerEntryPoint
|
public class LibraryChangedNotifier : IServerEntryPoint
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The library manager.
|
/// The library update duration.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private readonly ILibraryManager _libraryManager;
|
private const int LibraryUpdateDuration = 30000;
|
||||||
|
|
||||||
|
private readonly ILibraryManager _libraryManager;
|
||||||
|
private readonly IProviderManager _providerManager;
|
||||||
private readonly ISessionManager _sessionManager;
|
private readonly ISessionManager _sessionManager;
|
||||||
private readonly IUserManager _userManager;
|
private readonly IUserManager _userManager;
|
||||||
private readonly ILogger<LibraryChangedNotifier> _logger;
|
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> _foldersAddedTo = new List<Folder>();
|
||||||
private readonly List<Folder> _foldersRemovedFrom = new List<Folder>();
|
private readonly List<Folder> _foldersRemovedFrom = new List<Folder>();
|
||||||
|
|
||||||
private readonly List<BaseItem> _itemsAdded = new List<BaseItem>();
|
private readonly List<BaseItem> _itemsAdded = new List<BaseItem>();
|
||||||
private readonly List<BaseItem> _itemsRemoved = new List<BaseItem>();
|
private readonly List<BaseItem> _itemsRemoved = new List<BaseItem>();
|
||||||
private readonly List<BaseItem> _itemsUpdated = new List<BaseItem>();
|
private readonly List<BaseItem> _itemsUpdated = new List<BaseItem>();
|
||||||
|
private readonly Dictionary<Guid, DateTime> _lastProgressMessageTimes = new Dictionary<Guid, DateTime>();
|
||||||
/// <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;
|
|
||||||
|
|
||||||
public LibraryChangedNotifier(
|
public LibraryChangedNotifier(
|
||||||
ILibraryManager libraryManager,
|
ILibraryManager libraryManager,
|
||||||
|
@ -70,22 +59,26 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||||
_providerManager = providerManager;
|
_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()
|
public Task RunAsync()
|
||||||
{
|
{
|
||||||
_libraryManager.ItemAdded += libraryManager_ItemAdded;
|
_libraryManager.ItemAdded += OnLibraryItemAdded;
|
||||||
_libraryManager.ItemUpdated += libraryManager_ItemUpdated;
|
_libraryManager.ItemUpdated += OnLibraryItemUpdated;
|
||||||
_libraryManager.ItemRemoved += libraryManager_ItemRemoved;
|
_libraryManager.ItemRemoved += OnLibraryItemRemoved;
|
||||||
|
|
||||||
_providerManager.RefreshCompleted += _providerManager_RefreshCompleted;
|
_providerManager.RefreshCompleted += OnProviderRefreshCompleted;
|
||||||
_providerManager.RefreshStarted += _providerManager_RefreshStarted;
|
_providerManager.RefreshStarted += OnProviderRefreshStarted;
|
||||||
_providerManager.RefreshProgress += _providerManager_RefreshProgress;
|
_providerManager.RefreshProgress += OnProviderRefreshProgress;
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Dictionary<Guid, DateTime> _lastProgressMessageTimes = new Dictionary<Guid, DateTime>();
|
private void OnProviderRefreshProgress(object sender, GenericEventArgs<Tuple<BaseItem, double>> e)
|
||||||
|
|
||||||
private void _providerManager_RefreshProgress(object sender, GenericEventArgs<Tuple<BaseItem, double>> e)
|
|
||||||
{
|
{
|
||||||
var item = e.Argument.Item1;
|
var item = e.Argument.Item1;
|
||||||
|
|
||||||
|
@ -122,9 +115,11 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||||
|
|
||||||
foreach (var collectionFolder in collectionFolders)
|
foreach (var collectionFolder in collectionFolders)
|
||||||
{
|
{
|
||||||
var collectionFolderDict = new Dictionary<string, string>();
|
var collectionFolderDict = new Dictionary<string, string>
|
||||||
collectionFolderDict["ItemId"] = collectionFolder.Id.ToString("N", CultureInfo.InvariantCulture);
|
{
|
||||||
collectionFolderDict["Progress"] = (collectionFolder.GetRefreshProgress() ?? 0).ToString(CultureInfo.InvariantCulture);
|
["ItemId"] = collectionFolder.Id.ToString("N", CultureInfo.InvariantCulture),
|
||||||
|
["Progress"] = (collectionFolder.GetRefreshProgress() ?? 0).ToString(CultureInfo.InvariantCulture)
|
||||||
|
};
|
||||||
|
|
||||||
try
|
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)
|
private static bool EnableRefreshMessage(BaseItem item)
|
||||||
{
|
{
|
||||||
var folder = item as Folder;
|
if (!(item is Folder folder))
|
||||||
|
|
||||||
if (folder == null)
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -183,7 +176,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sender">The source of the event.</param>
|
/// <param name="sender">The source of the event.</param>
|
||||||
/// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</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))
|
if (!FilterItem(e.Item))
|
||||||
{
|
{
|
||||||
|
@ -205,8 +198,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||||
LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite);
|
LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite);
|
||||||
}
|
}
|
||||||
|
|
||||||
var parent = e.Item.GetParent() as Folder;
|
if (e.Item.GetParent() is Folder parent)
|
||||||
if (parent != null)
|
|
||||||
{
|
{
|
||||||
_foldersAddedTo.Add(parent);
|
_foldersAddedTo.Add(parent);
|
||||||
}
|
}
|
||||||
|
@ -220,7 +212,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sender">The source of the event.</param>
|
/// <param name="sender">The source of the event.</param>
|
||||||
/// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</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))
|
if (!FilterItem(e.Item))
|
||||||
{
|
{
|
||||||
|
@ -231,8 +223,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||||
{
|
{
|
||||||
if (LibraryUpdateTimer == null)
|
if (LibraryUpdateTimer == null)
|
||||||
{
|
{
|
||||||
LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration,
|
LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, Timeout.Infinite);
|
||||||
Timeout.Infinite);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -248,7 +239,7 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sender">The source of the event.</param>
|
/// <param name="sender">The source of the event.</param>
|
||||||
/// <param name="e">The <see cref="ItemChangeEventArgs"/> instance containing the event data.</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))
|
if (!FilterItem(e.Item))
|
||||||
{
|
{
|
||||||
|
@ -259,16 +250,14 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||||
{
|
{
|
||||||
if (LibraryUpdateTimer == null)
|
if (LibraryUpdateTimer == null)
|
||||||
{
|
{
|
||||||
LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration,
|
LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration, Timeout.Infinite);
|
||||||
Timeout.Infinite);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite);
|
LibraryUpdateTimer.Change(LibraryUpdateDuration, Timeout.Infinite);
|
||||||
}
|
}
|
||||||
|
|
||||||
var parent = e.Parent as Folder;
|
if (e.Parent is Folder parent)
|
||||||
if (parent != null)
|
|
||||||
{
|
{
|
||||||
_foldersRemovedFrom.Add(parent);
|
_foldersRemovedFrom.Add(parent);
|
||||||
}
|
}
|
||||||
|
@ -486,13 +475,13 @@ namespace Emby.Server.Implementations.EntryPoints
|
||||||
LibraryUpdateTimer = null;
|
LibraryUpdateTimer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
_libraryManager.ItemAdded -= libraryManager_ItemAdded;
|
_libraryManager.ItemAdded -= OnLibraryItemAdded;
|
||||||
_libraryManager.ItemUpdated -= libraryManager_ItemUpdated;
|
_libraryManager.ItemUpdated -= OnLibraryItemUpdated;
|
||||||
_libraryManager.ItemRemoved -= libraryManager_ItemRemoved;
|
_libraryManager.ItemRemoved -= OnLibraryItemRemoved;
|
||||||
|
|
||||||
_providerManager.RefreshCompleted -= _providerManager_RefreshCompleted;
|
_providerManager.RefreshCompleted -= OnProviderRefreshCompleted;
|
||||||
_providerManager.RefreshStarted -= _providerManager_RefreshStarted;
|
_providerManager.RefreshStarted -= OnProviderRefreshStarted;
|
||||||
_providerManager.RefreshProgress -= _providerManager_RefreshProgress;
|
_providerManager.RefreshProgress -= OnProviderRefreshProgress;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
"Artists": "Interpreten",
|
"Artists": "Interpreten",
|
||||||
"AuthenticationSucceededWithUserName": "{0} hat sich erfolgreich angemeldet",
|
"AuthenticationSucceededWithUserName": "{0} hat sich erfolgreich angemeldet",
|
||||||
"Books": "Bücher",
|
"Books": "Bücher",
|
||||||
"CameraImageUploadedFrom": "Ein neues Foto wurde von {0} hochgeladen",
|
"CameraImageUploadedFrom": "Ein neues Kamerafoto wurde von {0} hochgeladen",
|
||||||
"Channels": "Kanäle",
|
"Channels": "Kanäle",
|
||||||
"ChapterNameValue": "Kapitel {0}",
|
"ChapterNameValue": "Kapitel {0}",
|
||||||
"Collections": "Sammlungen",
|
"Collections": "Sammlungen",
|
||||||
|
@ -106,7 +106,7 @@
|
||||||
"TaskCleanLogsDescription": "Lösche Log Dateien die älter als {0} Tage sind.",
|
"TaskCleanLogsDescription": "Lösche Log Dateien die älter als {0} Tage sind.",
|
||||||
"TaskCleanLogs": "Lösche Log Pfad",
|
"TaskCleanLogs": "Lösche Log Pfad",
|
||||||
"TaskRefreshLibraryDescription": "Scanne alle Bibliotheken für hinzugefügte Datein und erneuere Metadaten.",
|
"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.",
|
"TaskRefreshChapterImagesDescription": "Kreiert Vorschaubilder für Videos welche Kapitel haben.",
|
||||||
"TaskRefreshChapterImages": "Extrahiert Kapitel-Bilder",
|
"TaskRefreshChapterImages": "Extrahiert Kapitel-Bilder",
|
||||||
"TaskCleanCacheDescription": "Löscht Zwischenspeicherdatein die nicht länger von System gebraucht werden.",
|
"TaskCleanCacheDescription": "Löscht Zwischenspeicherdatein die nicht länger von System gebraucht werden.",
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
{
|
{
|
||||||
"MusicVideos": "Музичні відео",
|
"MusicVideos": "Музичні кліпи",
|
||||||
"Music": "Музика",
|
"Music": "Музика",
|
||||||
"Movies": "Фільми",
|
"Movies": "Фільми",
|
||||||
"MessageApplicationUpdatedTo": "Jellyfin Server був оновлений до версії {0}",
|
"MessageApplicationUpdatedTo": "Jellyfin Server оновлено до версії {0}",
|
||||||
"MessageApplicationUpdated": "Jellyfin Server був оновлений",
|
"MessageApplicationUpdated": "Jellyfin Server оновлено",
|
||||||
"Latest": "Останні",
|
"Latest": "Останні",
|
||||||
"LabelIpAddressValue": "IP-адреси: {0}",
|
"LabelIpAddressValue": "IP-адреса: {0}",
|
||||||
"ItemRemovedWithName": "{0} видалено з бібліотеки",
|
"ItemRemovedWithName": "{0} видалено з медіатеки",
|
||||||
"ItemAddedWithName": "{0} додано до бібліотеки",
|
"ItemAddedWithName": "{0} додано до медіатеки",
|
||||||
"HeaderNextUp": "Наступний",
|
"HeaderNextUp": "Наступний",
|
||||||
"HeaderLiveTV": "Ефірне ТБ",
|
"HeaderLiveTV": "Ефірне ТБ",
|
||||||
"HeaderFavoriteSongs": "Улюблені пісні",
|
"HeaderFavoriteSongs": "Улюблені пісні",
|
||||||
|
@ -17,20 +17,101 @@
|
||||||
"HeaderFavoriteAlbums": "Улюблені альбоми",
|
"HeaderFavoriteAlbums": "Улюблені альбоми",
|
||||||
"HeaderContinueWatching": "Продовжити перегляд",
|
"HeaderContinueWatching": "Продовжити перегляд",
|
||||||
"HeaderCameraUploads": "Завантажено з камери",
|
"HeaderCameraUploads": "Завантажено з камери",
|
||||||
"HeaderAlbumArtists": "Виконавці альбомів",
|
"HeaderAlbumArtists": "Виконавці альбому",
|
||||||
"Genres": "Жанри",
|
"Genres": "Жанри",
|
||||||
"Folders": "Директорії",
|
"Folders": "Каталоги",
|
||||||
"Favorites": "Улюблені",
|
"Favorites": "Улюблені",
|
||||||
"DeviceOnlineWithName": "{0} під'єднано",
|
"DeviceOnlineWithName": "Пристрій {0} підключився",
|
||||||
"DeviceOfflineWithName": "{0} від'єднано",
|
"DeviceOfflineWithName": "Пристрій {0} відключився",
|
||||||
"Collections": "Колекції",
|
"Collections": "Колекції",
|
||||||
"ChapterNameValue": "Глава {0}",
|
"ChapterNameValue": "Розділ {0}",
|
||||||
"Channels": "Канали",
|
"Channels": "Канали",
|
||||||
"CameraImageUploadedFrom": "Нова фотографія завантажена з {0}",
|
"CameraImageUploadedFrom": "Нова фотографія завантажена з {0}",
|
||||||
"Books": "Книги",
|
"Books": "Книги",
|
||||||
"AuthenticationSucceededWithUserName": "{0} успішно авторизовані",
|
"AuthenticationSucceededWithUserName": "{0} успішно авторизований",
|
||||||
"Artists": "Виконавці",
|
"Artists": "Виконавці",
|
||||||
"Application": "Додаток",
|
"Application": "Додаток",
|
||||||
"AppDeviceValues": "Додаток: {0}, Пристрій: {1}",
|
"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": "Групи запису"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Jellyfin.Api.Auth.IgnoreParentalControlPolicy;
|
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using MediaBrowser.Controller.Library;
|
using MediaBrowser.Controller.Library;
|
||||||
|
@ -11,7 +10,7 @@ namespace Jellyfin.Api.Auth.FirstTimeOrIgnoreParentalControlSetupPolicy
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ignore parental control schedule and allow before startup wizard has been completed.
|
/// Ignore parental control schedule and allow before startup wizard has been completed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class FirstTimeOrIgnoreParentalControlSetupHandler : BaseAuthorizationHandler<IgnoreParentalControlRequirement>
|
public class FirstTimeOrIgnoreParentalControlSetupHandler : BaseAuthorizationHandler<FirstTimeOrIgnoreParentalControlSetupRequirement>
|
||||||
{
|
{
|
||||||
private readonly IConfigurationManager _configurationManager;
|
private readonly IConfigurationManager _configurationManager;
|
||||||
|
|
||||||
|
@ -33,7 +32,7 @@ namespace Jellyfin.Api.Auth.FirstTimeOrIgnoreParentalControlSetupPolicy
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, IgnoreParentalControlRequirement requirement)
|
protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FirstTimeOrIgnoreParentalControlSetupRequirement requirement)
|
||||||
{
|
{
|
||||||
if (!_configurationManager.CommonConfiguration.IsStartupWizardCompleted)
|
if (!_configurationManager.CommonConfiguration.IsStartupWizardCompleted)
|
||||||
{
|
{
|
||||||
|
|
|
@ -386,7 +386,7 @@ namespace Jellyfin.Api.Controllers
|
||||||
var user = _userManager.GetUserById(userId);
|
var user = _userManager.GetUserById(userId);
|
||||||
|
|
||||||
// If removing admin access
|
// 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)
|
if (_userManager.Users.Count(i => i.HasPermission(PermissionKind.IsAdministrator)) == 1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc" Version="2.2.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Http" Version="3.1.6" />
|
<PackageReference Include="Microsoft.Extensions.Http" Version="3.1.6" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.5.1" />
|
<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>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|
|
@ -115,7 +115,7 @@ namespace Jellyfin.Drawing.Skia
|
||||||
|
|
||||||
// resize to the same aspect as the original
|
// resize to the same aspect as the original
|
||||||
int iWidth = Math.Abs(iHeight * currentBitmap.Width / currentBitmap.Height);
|
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
|
// crop image
|
||||||
int ix = Math.Abs((iWidth - iSlice) / 2);
|
int ix = Math.Abs((iWidth - iSlice) / 2);
|
||||||
|
@ -177,7 +177,7 @@ namespace Jellyfin.Drawing.Skia
|
||||||
|
|
||||||
// Scale image. The FromBitmap creates a copy
|
// Scale image. The FromBitmap creates a copy
|
||||||
var imageInfo = new SKImageInfo(cellWidth, cellHeight, currentBitmap.ColorType, currentBitmap.AlphaType, currentBitmap.ColorSpace);
|
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
|
// draw this image into the strip at the next position
|
||||||
var xPos = x * cellWidth;
|
var xPos = x * cellWidth;
|
||||||
|
|
|
@ -4,6 +4,8 @@ using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
|
using System.Net.Mime;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Jellyfin.Data.Entities;
|
using Jellyfin.Data.Entities;
|
||||||
|
@ -22,6 +24,7 @@ using MediaBrowser.Model.Configuration;
|
||||||
using MediaBrowser.Model.Entities;
|
using MediaBrowser.Model.Entities;
|
||||||
using MediaBrowser.Model.Events;
|
using MediaBrowser.Model.Events;
|
||||||
using MediaBrowser.Model.IO;
|
using MediaBrowser.Model.IO;
|
||||||
|
using MediaBrowser.Model.Net;
|
||||||
using MediaBrowser.Model.Providers;
|
using MediaBrowser.Model.Providers;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Priority_Queue;
|
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);
|
await SaveImage(item, response.Content, response.ContentType, type, imageIndex, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.1.6" />
|
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.1.6" />
|
||||||
<PackageReference Include="OptimizedPriorityQueue" Version="4.2.0" />
|
<PackageReference Include="OptimizedPriorityQueue" Version="4.2.0" />
|
||||||
<PackageReference Include="PlaylistsNET" Version="1.1.2" />
|
<PackageReference Include="PlaylistsNET" Version="1.1.2" />
|
||||||
<PackageReference Include="TvDbSharper" Version="3.2.0" />
|
<PackageReference Include="TvDbSharper" Version="3.2.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
|
|
@ -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`.
|
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.
|
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.
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<PackageReference Include="AutoFixture.AutoMoq" Version="4.12.0" />
|
<PackageReference Include="AutoFixture.AutoMoq" Version="4.12.0" />
|
||||||
<PackageReference Include="AutoFixture.Xunit2" Version="4.12.0" />
|
<PackageReference Include="AutoFixture.Xunit2" Version="4.12.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Options" Version="3.1.6" />
|
<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" Version="2.4.1" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
||||||
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<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" Version="2.4.1" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
||||||
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<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" Version="2.4.1" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
||||||
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<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" Version="2.4.1" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
||||||
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<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" Version="2.4.1" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
||||||
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.6" />
|
<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" Version="2.4.1" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.1" />
|
||||||
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
||||||
|
|
Loading…
Reference in a new issue