mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-06-15 12:10:47 +01:00
Merge branch 'master' into event-rewrite-1
# Conflicts: # Emby.Dlna/Emby.Dlna.csproj # Emby.Dlna/Eventing/DlnaEventManager.cs # Emby.Dlna/Service/BaseService.cs # Emby.Server.Implementations/ScheduledTasks/ScheduledTaskWorker.cs # MediaBrowser.Controller/Subtitles/SubtitleDownloadEventArgs.cs
This commit is contained in:
@@ -187,7 +187,7 @@ namespace MediaBrowser.Providers.Manager
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SaveImage(User user, Stream source, string path)
|
||||
public async Task SaveImage(Stream source, string path)
|
||||
{
|
||||
await SaveImageToLocation(source, path, path, CancellationToken.None).ConfigureAwait(false);
|
||||
}
|
||||
@@ -355,7 +355,7 @@ namespace MediaBrowser.Providers.Manager
|
||||
|
||||
if (string.IsNullOrWhiteSpace(extension))
|
||||
{
|
||||
throw new ArgumentException(string.Format("Unable to determine image file extension from mime type {0}", mimeType));
|
||||
throw new ArgumentException(string.Format(CultureInfo.InvariantCulture, "Unable to determine image file extension from mime type {0}", mimeType));
|
||||
}
|
||||
|
||||
if (type == ImageType.Thumb && saveLocally)
|
||||
|
||||
@@ -54,7 +54,12 @@ namespace MediaBrowser.Providers.Manager
|
||||
return hasChanges;
|
||||
}
|
||||
|
||||
public async Task<RefreshResult> RefreshImages(BaseItem item, LibraryOptions libraryOptions, List<IImageProvider> providers, ImageRefreshOptions refreshOptions, MetadataOptions savedOptions, CancellationToken cancellationToken)
|
||||
public async Task<RefreshResult> RefreshImages(
|
||||
BaseItem item,
|
||||
LibraryOptions libraryOptions,
|
||||
List<IImageProvider> providers,
|
||||
ImageRefreshOptions refreshOptions,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (refreshOptions.IsReplacingImage(ImageType.Backdrop))
|
||||
{
|
||||
@@ -78,19 +83,15 @@ namespace MediaBrowser.Providers.Manager
|
||||
|
||||
foreach (var provider in providers)
|
||||
{
|
||||
var remoteProvider = provider as IRemoteImageProvider;
|
||||
|
||||
if (remoteProvider != null)
|
||||
if (provider is IRemoteImageProvider remoteProvider)
|
||||
{
|
||||
await RefreshFromProvider(item, libraryOptions, remoteProvider, refreshOptions, typeOptions, backdropLimit, screenshotLimit, downloadedImages, result, cancellationToken).ConfigureAwait(false);
|
||||
continue;
|
||||
}
|
||||
|
||||
var dynamicImageProvider = provider as IDynamicImageProvider;
|
||||
|
||||
if (dynamicImageProvider != null)
|
||||
if (provider is IDynamicImageProvider dynamicImageProvider)
|
||||
{
|
||||
await RefreshFromProvider(item, dynamicImageProvider, refreshOptions, typeOptions, libraryOptions, downloadedImages, result, cancellationToken).ConfigureAwait(false);
|
||||
await RefreshFromProvider(item, dynamicImageProvider, refreshOptions, typeOptions, downloadedImages, result, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,11 +101,11 @@ namespace MediaBrowser.Providers.Manager
|
||||
/// <summary>
|
||||
/// Refreshes from provider.
|
||||
/// </summary>
|
||||
private async Task RefreshFromProvider(BaseItem item,
|
||||
private async Task RefreshFromProvider(
|
||||
BaseItem item,
|
||||
IDynamicImageProvider provider,
|
||||
ImageRefreshOptions refreshOptions,
|
||||
TypeOptions savedOptions,
|
||||
LibraryOptions libraryOptions,
|
||||
ICollection<ImageType> downloadedImages,
|
||||
RefreshResult result,
|
||||
CancellationToken cancellationToken)
|
||||
@@ -115,7 +116,7 @@ namespace MediaBrowser.Providers.Manager
|
||||
|
||||
foreach (var imageType in images)
|
||||
{
|
||||
if (!IsEnabled(savedOptions, imageType, item))
|
||||
if (!IsEnabled(savedOptions, imageType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -133,12 +134,13 @@ namespace MediaBrowser.Providers.Manager
|
||||
if (response.Protocol == MediaProtocol.Http)
|
||||
{
|
||||
_logger.LogDebug("Setting image url into item {0}", item.Id);
|
||||
item.SetImage(new ItemImageInfo
|
||||
{
|
||||
Path = response.Path,
|
||||
Type = imageType
|
||||
|
||||
}, 0);
|
||||
item.SetImage(
|
||||
new ItemImageInfo
|
||||
{
|
||||
Path = response.Path,
|
||||
Type = imageType
|
||||
},
|
||||
0);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -157,7 +159,7 @@ namespace MediaBrowser.Providers.Manager
|
||||
}
|
||||
|
||||
downloadedImages.Add(imageType);
|
||||
result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate;
|
||||
result.UpdateType |= ItemUpdateType.ImageUpdate;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -279,7 +281,7 @@ namespace MediaBrowser.Providers.Manager
|
||||
|
||||
foreach (var imageType in _singularImages)
|
||||
{
|
||||
if (!IsEnabled(savedOptions, imageType, item))
|
||||
if (!IsEnabled(savedOptions, imageType))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -299,8 +301,7 @@ namespace MediaBrowser.Providers.Manager
|
||||
minWidth = savedOptions.GetMinWidth(ImageType.Backdrop);
|
||||
await DownloadBackdrops(item, libraryOptions, ImageType.Backdrop, backdropLimit, provider, result, list, minWidth, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var hasScreenshots = item as IHasScreenshots;
|
||||
if (hasScreenshots != null)
|
||||
if (item is IHasScreenshots hasScreenshots)
|
||||
{
|
||||
minWidth = savedOptions.GetMinWidth(ImageType.Screenshot);
|
||||
await DownloadBackdrops(item, libraryOptions, ImageType.Screenshot, screenshotLimit, provider, result, list, minWidth, cancellationToken).ConfigureAwait(false);
|
||||
@@ -317,7 +318,7 @@ namespace MediaBrowser.Providers.Manager
|
||||
}
|
||||
}
|
||||
|
||||
private bool IsEnabled(TypeOptions options, ImageType type, BaseItem item)
|
||||
private bool IsEnabled(TypeOptions options, ImageType type)
|
||||
{
|
||||
return options.IsEnabled(type);
|
||||
}
|
||||
@@ -452,10 +453,10 @@ namespace MediaBrowser.Providers.Manager
|
||||
.Where(i => i.Type == type && !(i.Width.HasValue && i.Width.Value < minWidth))
|
||||
.ToList();
|
||||
|
||||
if (EnableImageStub(item, type, libraryOptions) && eligibleImages.Count > 0)
|
||||
if (EnableImageStub(item, libraryOptions) && eligibleImages.Count > 0)
|
||||
{
|
||||
SaveImageStub(item, type, eligibleImages.Select(i => i.Url));
|
||||
result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate;
|
||||
result.UpdateType |= ItemUpdateType.ImageUpdate;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -476,7 +477,7 @@ namespace MediaBrowser.Providers.Manager
|
||||
null,
|
||||
cancellationToken).ConfigureAwait(false);
|
||||
|
||||
result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate;
|
||||
result.UpdateType |= ItemUpdateType.ImageUpdate;
|
||||
return true;
|
||||
}
|
||||
catch (HttpException ex)
|
||||
@@ -495,7 +496,7 @@ namespace MediaBrowser.Providers.Manager
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool EnableImageStub(BaseItem item, ImageType type, LibraryOptions libraryOptions)
|
||||
private bool EnableImageStub(BaseItem item, LibraryOptions libraryOptions)
|
||||
{
|
||||
if (item is LiveTvProgram)
|
||||
{
|
||||
@@ -563,10 +564,10 @@ namespace MediaBrowser.Providers.Manager
|
||||
|
||||
var url = image.Url;
|
||||
|
||||
if (EnableImageStub(item, imageType, libraryOptions))
|
||||
if (EnableImageStub(item, libraryOptions))
|
||||
{
|
||||
SaveImageStub(item, imageType, new[] { url });
|
||||
result.UpdateType = result.UpdateType | ItemUpdateType.ImageUpdate;
|
||||
result.UpdateType |= ItemUpdateType.ImageUpdate;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,6 @@ namespace MediaBrowser.Providers.Manager
|
||||
public async Task<ItemUpdateType> RefreshMetadata(BaseItem item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken)
|
||||
{
|
||||
var itemOfType = (TItemType)item;
|
||||
var config = ProviderManager.GetMetadataOptions(item);
|
||||
|
||||
var updateType = ItemUpdateType.None;
|
||||
var requiresRefresh = false;
|
||||
@@ -86,7 +85,7 @@ namespace MediaBrowser.Providers.Manager
|
||||
// Always validate images and check for new locally stored ones.
|
||||
if (itemImageProvider.ValidateImages(item, allImageProviders.OfType<ILocalImageProvider>(), refreshOptions.DirectoryService))
|
||||
{
|
||||
updateType = updateType | ItemUpdateType.ImageUpdate;
|
||||
updateType |= ItemUpdateType.ImageUpdate;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -102,7 +101,7 @@ namespace MediaBrowser.Providers.Manager
|
||||
|
||||
bool hasRefreshedMetadata = true;
|
||||
bool hasRefreshedImages = true;
|
||||
var isFirstRefresh = item.DateLastRefreshed == default(DateTime);
|
||||
var isFirstRefresh = item.DateLastRefreshed == default;
|
||||
|
||||
// Next run metadata providers
|
||||
if (refreshOptions.MetadataRefreshMode != MetadataRefreshMode.None)
|
||||
@@ -114,7 +113,7 @@ namespace MediaBrowser.Providers.Manager
|
||||
{
|
||||
if (item.BeforeMetadataRefresh(refreshOptions.ReplaceAllMetadata))
|
||||
{
|
||||
updateType = updateType | ItemUpdateType.MetadataImport;
|
||||
updateType |= ItemUpdateType.MetadataImport;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +131,7 @@ namespace MediaBrowser.Providers.Manager
|
||||
|
||||
var result = await RefreshWithProviders(metadataResult, id, refreshOptions, providers, itemImageProvider, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
updateType = updateType | result.UpdateType;
|
||||
updateType |= result.UpdateType;
|
||||
if (result.Failures > 0)
|
||||
{
|
||||
hasRefreshedMetadata = false;
|
||||
@@ -147,9 +146,9 @@ namespace MediaBrowser.Providers.Manager
|
||||
|
||||
if (providers.Count > 0)
|
||||
{
|
||||
var result = await itemImageProvider.RefreshImages(itemOfType, libraryOptions, providers, refreshOptions, config, cancellationToken).ConfigureAwait(false);
|
||||
var result = await itemImageProvider.RefreshImages(itemOfType, libraryOptions, providers, refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
updateType = updateType | result.UpdateType;
|
||||
updateType |= result.UpdateType;
|
||||
if (result.Failures > 0)
|
||||
{
|
||||
hasRefreshedImages = false;
|
||||
@@ -158,7 +157,7 @@ namespace MediaBrowser.Providers.Manager
|
||||
}
|
||||
|
||||
var beforeSaveResult = BeforeSave(itemOfType, isFirstRefresh || refreshOptions.ReplaceAllMetadata || refreshOptions.MetadataRefreshMode == MetadataRefreshMode.FullRefresh || requiresRefresh || refreshOptions.ForceSave, updateType);
|
||||
updateType = updateType | beforeSaveResult;
|
||||
updateType |= beforeSaveResult;
|
||||
|
||||
// Save if changes were made, or it's never been saved before
|
||||
if (refreshOptions.ForceSave || updateType > ItemUpdateType.None || isFirstRefresh || refreshOptions.ReplaceAllMetadata || requiresRefresh)
|
||||
@@ -175,7 +174,7 @@ namespace MediaBrowser.Providers.Manager
|
||||
// If any of these properties are set then make sure the updateType is not None, just to force everything to save
|
||||
if (refreshOptions.ForceSave || refreshOptions.ReplaceAllMetadata)
|
||||
{
|
||||
updateType = updateType | ItemUpdateType.MetadataDownload;
|
||||
updateType |= ItemUpdateType.MetadataDownload;
|
||||
}
|
||||
|
||||
if (hasRefreshedMetadata && hasRefreshedImages)
|
||||
@@ -184,11 +183,11 @@ namespace MediaBrowser.Providers.Manager
|
||||
}
|
||||
else
|
||||
{
|
||||
item.DateLastRefreshed = default(DateTime);
|
||||
item.DateLastRefreshed = default;
|
||||
}
|
||||
|
||||
// Save to database
|
||||
SaveItem(metadataResult, libraryOptions, updateType, cancellationToken);
|
||||
await SaveItemAsync(metadataResult, libraryOptions, updateType, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
await AfterMetadataRefresh(itemOfType, refreshOptions, cancellationToken).ConfigureAwait(false);
|
||||
@@ -203,26 +202,26 @@ namespace MediaBrowser.Providers.Manager
|
||||
lookupInfo.Year = result.ProductionYear;
|
||||
}
|
||||
|
||||
protected void SaveItem(MetadataResult<TItemType> result, LibraryOptions libraryOptions, ItemUpdateType reason, CancellationToken cancellationToken)
|
||||
protected async Task SaveItemAsync(MetadataResult<TItemType> result, LibraryOptions libraryOptions, ItemUpdateType reason, CancellationToken cancellationToken)
|
||||
{
|
||||
if (result.Item.SupportsPeople && result.People != null)
|
||||
{
|
||||
var baseItem = result.Item;
|
||||
|
||||
LibraryManager.UpdatePeople(baseItem, result.People);
|
||||
SavePeopleMetadata(result.People, libraryOptions, cancellationToken);
|
||||
await SavePeopleMetadataAsync(result.People, libraryOptions, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
result.Item.UpdateToRepository(reason, cancellationToken);
|
||||
await result.Item.UpdateToRepositoryAsync(reason, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private void SavePeopleMetadata(List<PersonInfo> people, LibraryOptions libraryOptions, CancellationToken cancellationToken)
|
||||
private async Task SavePeopleMetadataAsync(List<PersonInfo> people, LibraryOptions libraryOptions, CancellationToken cancellationToken)
|
||||
{
|
||||
foreach (var person in people)
|
||||
{
|
||||
cancellationToken.ThrowIfCancellationRequested();
|
||||
|
||||
if (person.ProviderIds.Any() || !string.IsNullOrWhiteSpace(person.ImageUrl))
|
||||
if (person.ProviderIds.Count > 0 || !string.IsNullOrWhiteSpace(person.ImageUrl))
|
||||
{
|
||||
var updateType = ItemUpdateType.MetadataDownload;
|
||||
|
||||
@@ -239,40 +238,42 @@ namespace MediaBrowser.Providers.Manager
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(person.ImageUrl) && !personEntity.HasImage(ImageType.Primary))
|
||||
{
|
||||
AddPersonImage(personEntity, libraryOptions, person.ImageUrl, cancellationToken);
|
||||
await AddPersonImageAsync(personEntity, libraryOptions, person.ImageUrl, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
saveEntity = true;
|
||||
updateType = updateType | ItemUpdateType.ImageUpdate;
|
||||
updateType |= ItemUpdateType.ImageUpdate;
|
||||
}
|
||||
|
||||
if (saveEntity)
|
||||
{
|
||||
personEntity.UpdateToRepository(updateType, cancellationToken);
|
||||
await personEntity.UpdateToRepositoryAsync(updateType, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void AddPersonImage(Person personEntity, LibraryOptions libraryOptions, string imageUrl, CancellationToken cancellationToken)
|
||||
private async Task AddPersonImageAsync(Person personEntity, LibraryOptions libraryOptions, string imageUrl, CancellationToken cancellationToken)
|
||||
{
|
||||
// if (libraryOptions.DownloadImagesInAdvance)
|
||||
//{
|
||||
// try
|
||||
// {
|
||||
// await ProviderManager.SaveImage(personEntity, imageUrl, ImageType.Primary, null, cancellationToken).ConfigureAwait(false);
|
||||
// return;
|
||||
// }
|
||||
// catch (Exception ex)
|
||||
// {
|
||||
// Logger.LogError(ex, "Error in AddPersonImage");
|
||||
// }
|
||||
//}
|
||||
|
||||
personEntity.SetImage(new ItemImageInfo
|
||||
if (libraryOptions.DownloadImagesInAdvance)
|
||||
{
|
||||
Path = imageUrl,
|
||||
Type = ImageType.Primary
|
||||
}, 0);
|
||||
try
|
||||
{
|
||||
await ProviderManager.SaveImage(personEntity, imageUrl, ImageType.Primary, null, cancellationToken).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError(ex, "Error in AddPersonImage");
|
||||
}
|
||||
}
|
||||
|
||||
personEntity.SetImage(
|
||||
new ItemImageInfo
|
||||
{
|
||||
Path = imageUrl,
|
||||
Type = ImageType.Primary
|
||||
},
|
||||
0);
|
||||
}
|
||||
|
||||
protected virtual Task AfterMetadataRefresh(TItemType item, MetadataRefreshOptions refreshOptions, CancellationToken cancellationToken)
|
||||
|
||||
@@ -210,10 +210,10 @@ namespace MediaBrowser.Providers.Manager
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task SaveImage(User user, Stream source, string mimeType, string path)
|
||||
public Task SaveImage(Stream source, string mimeType, string path)
|
||||
{
|
||||
return new ImageSaver(_configurationManager, _libraryMonitor, _fileSystem, _logger)
|
||||
.SaveImage(user, source, path);
|
||||
.SaveImage(source, path);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
@@ -563,7 +563,7 @@ namespace MediaBrowser.Providers.Manager
|
||||
var pluginList = summary.Plugins.ToList();
|
||||
|
||||
AddMetadataPlugins(pluginList, dummy, libraryOptions, options);
|
||||
AddImagePlugins(pluginList, dummy, imageProviders);
|
||||
AddImagePlugins(pluginList, imageProviders);
|
||||
|
||||
var subtitleProviders = _subtitleManager.GetSupportedProviders(dummy);
|
||||
|
||||
@@ -594,14 +594,14 @@ namespace MediaBrowser.Providers.Manager
|
||||
var providers = GetMetadataProvidersInternal<T>(item, libraryOptions, options, true, true).ToList();
|
||||
|
||||
// Locals
|
||||
list.AddRange(providers.Where(i => (i is ILocalMetadataProvider)).Select(i => new MetadataPlugin
|
||||
list.AddRange(providers.Where(i => i is ILocalMetadataProvider).Select(i => new MetadataPlugin
|
||||
{
|
||||
Name = i.Name,
|
||||
Type = MetadataPluginType.LocalMetadataProvider
|
||||
}));
|
||||
|
||||
// Fetchers
|
||||
list.AddRange(providers.Where(i => (i is IRemoteMetadataProvider)).Select(i => new MetadataPlugin
|
||||
list.AddRange(providers.Where(i => i is IRemoteMetadataProvider).Select(i => new MetadataPlugin
|
||||
{
|
||||
Name = i.Name,
|
||||
Type = MetadataPluginType.MetadataFetcher
|
||||
@@ -615,11 +615,10 @@ namespace MediaBrowser.Providers.Manager
|
||||
}));
|
||||
}
|
||||
|
||||
private void AddImagePlugins<T>(List<MetadataPlugin> list, T item, List<IImageProvider> imageProviders)
|
||||
where T : BaseItem
|
||||
private void AddImagePlugins(List<MetadataPlugin> list, List<IImageProvider> imageProviders)
|
||||
{
|
||||
// Locals
|
||||
list.AddRange(imageProviders.Where(i => (i is ILocalImageProvider)).Select(i => new MetadataPlugin
|
||||
list.AddRange(imageProviders.Where(i => i is ILocalImageProvider).Select(i => new MetadataPlugin
|
||||
{
|
||||
Name = i.Name,
|
||||
Type = MetadataPluginType.LocalImageProvider
|
||||
@@ -1166,12 +1165,32 @@ namespace MediaBrowser.Providers.Manager
|
||||
/// <inheritdoc/>
|
||||
public void Dispose()
|
||||
{
|
||||
_disposed = true;
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases unmanaged and optionally managed resources.
|
||||
/// </summary>
|
||||
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_disposeCancellationTokenSource.IsCancellationRequested)
|
||||
{
|
||||
_disposeCancellationTokenSource.Cancel();
|
||||
}
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
_disposeCancellationTokenSource.Dispose();
|
||||
}
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,9 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.Library;
|
||||
@@ -17,7 +15,6 @@ using MediaBrowser.Model.Dlna;
|
||||
using MediaBrowser.Model.Dto;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.MediaInfo;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
|
||||
namespace MediaBrowser.Providers.MediaInfo
|
||||
{
|
||||
@@ -25,19 +22,17 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
{
|
||||
private readonly IMediaEncoder _mediaEncoder;
|
||||
private readonly IItemRepository _itemRepo;
|
||||
private readonly IApplicationPaths _appPaths;
|
||||
private readonly IJsonSerializer _json;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly IMediaSourceManager _mediaSourceManager;
|
||||
|
||||
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
||||
|
||||
public FFProbeAudioInfo(IMediaSourceManager mediaSourceManager, IMediaEncoder mediaEncoder, IItemRepository itemRepo, IApplicationPaths appPaths, IJsonSerializer json, ILibraryManager libraryManager)
|
||||
public FFProbeAudioInfo(
|
||||
IMediaSourceManager mediaSourceManager,
|
||||
IMediaEncoder mediaEncoder,
|
||||
IItemRepository itemRepo,
|
||||
ILibraryManager libraryManager)
|
||||
{
|
||||
_mediaEncoder = mediaEncoder;
|
||||
_itemRepo = itemRepo;
|
||||
_appPaths = appPaths;
|
||||
_json = json;
|
||||
_libraryManager = libraryManager;
|
||||
_mediaSourceManager = mediaSourceManager;
|
||||
}
|
||||
|
||||
@@ -40,19 +40,15 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
IHasItemChangeMonitor
|
||||
{
|
||||
private readonly ILogger<FFProbeProvider> _logger;
|
||||
private readonly IIsoManager _isoManager;
|
||||
private readonly IMediaEncoder _mediaEncoder;
|
||||
private readonly IItemRepository _itemRepo;
|
||||
private readonly IBlurayExaminer _blurayExaminer;
|
||||
private readonly ILocalizationManager _localization;
|
||||
private readonly IApplicationPaths _appPaths;
|
||||
private readonly IJsonSerializer _json;
|
||||
private readonly IEncodingManager _encodingManager;
|
||||
private readonly IServerConfigurationManager _config;
|
||||
private readonly ISubtitleManager _subtitleManager;
|
||||
private readonly IChapterManager _chapterManager;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly IChannelManager _channelManager;
|
||||
private readonly IMediaSourceManager _mediaSourceManager;
|
||||
|
||||
public string Name => "ffprobe";
|
||||
@@ -126,14 +122,10 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
public FFProbeProvider(
|
||||
ILogger<FFProbeProvider> logger,
|
||||
IMediaSourceManager mediaSourceManager,
|
||||
IChannelManager channelManager,
|
||||
IIsoManager isoManager,
|
||||
IMediaEncoder mediaEncoder,
|
||||
IItemRepository itemRepo,
|
||||
IBlurayExaminer blurayExaminer,
|
||||
ILocalizationManager localization,
|
||||
IApplicationPaths appPaths,
|
||||
IJsonSerializer json,
|
||||
IEncodingManager encodingManager,
|
||||
IServerConfigurationManager config,
|
||||
ISubtitleManager subtitleManager,
|
||||
@@ -141,19 +133,15 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
ILibraryManager libraryManager)
|
||||
{
|
||||
_logger = logger;
|
||||
_isoManager = isoManager;
|
||||
_mediaEncoder = mediaEncoder;
|
||||
_itemRepo = itemRepo;
|
||||
_blurayExaminer = blurayExaminer;
|
||||
_localization = localization;
|
||||
_appPaths = appPaths;
|
||||
_json = json;
|
||||
_encodingManager = encodingManager;
|
||||
_config = config;
|
||||
_subtitleManager = subtitleManager;
|
||||
_chapterManager = chapterManager;
|
||||
_libraryManager = libraryManager;
|
||||
_channelManager = channelManager;
|
||||
_mediaSourceManager = mediaSourceManager;
|
||||
|
||||
_subtitleResolver = new SubtitleResolver(BaseItem.LocalizationManager);
|
||||
@@ -211,9 +199,9 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
|
||||
private string NormalizeStrmLine(string line)
|
||||
{
|
||||
return line.Replace("\t", string.Empty)
|
||||
.Replace("\r", string.Empty)
|
||||
.Replace("\n", string.Empty)
|
||||
return line.Replace("\t", string.Empty, StringComparison.Ordinal)
|
||||
.Replace("\r", string.Empty, StringComparison.Ordinal)
|
||||
.Replace("\n", string.Empty, StringComparison.Ordinal)
|
||||
.Trim();
|
||||
}
|
||||
|
||||
@@ -242,10 +230,11 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
FetchShortcutInfo(item);
|
||||
}
|
||||
|
||||
var prober = new FFProbeAudioInfo(_mediaSourceManager, _mediaEncoder, _itemRepo, _appPaths, _json, _libraryManager);
|
||||
var prober = new FFProbeAudioInfo(_mediaSourceManager, _mediaEncoder, _itemRepo, _libraryManager);
|
||||
|
||||
return prober.Probe(item, options, cancellationToken);
|
||||
}
|
||||
|
||||
// Run last
|
||||
public int Order => 100;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ using MediaBrowser.Model.Entities;
|
||||
|
||||
namespace MediaBrowser.Providers.Music
|
||||
{
|
||||
public static class Extensions
|
||||
public static class AlbumInfoExtensions
|
||||
{
|
||||
public static string GetAlbumArtist(this AlbumInfo info)
|
||||
{
|
||||
@@ -18,7 +18,7 @@ namespace MediaBrowser.Providers.Music
|
||||
return id;
|
||||
}
|
||||
|
||||
return info.AlbumArtists.FirstOrDefault();
|
||||
return info.AlbumArtists.Count > 0 ? info.AlbumArtists[0] : default;
|
||||
}
|
||||
|
||||
public static string GetReleaseGroupId(this AlbumInfo info)
|
||||
|
||||
@@ -276,7 +276,7 @@ namespace MediaBrowser.Providers.Music
|
||||
|
||||
private async Task<ReleaseResult> GetReleaseResult(string albumName, string artistId, CancellationToken cancellationToken)
|
||||
{
|
||||
var url = string.Format("/ws/2/release/?query=\"{0}\" AND arid:{1}",
|
||||
var url = string.Format(CultureInfo.InvariantCulture, "/ws/2/release/?query=\"{0}\" AND arid:{1}",
|
||||
WebUtility.UrlEncode(albumName),
|
||||
artistId);
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace MediaBrowser.Providers.Music
|
||||
// They seem to throw bad request failures on any term with a slash
|
||||
var nameToSearch = searchInfo.Name.Replace('/', ' ');
|
||||
|
||||
var url = string.Format("/ws/2/artist/?query=\"{0}\"&dismax=true", UrlEncode(nameToSearch));
|
||||
var url = string.Format(CultureInfo.InvariantCulture, "/ws/2/artist/?query=\"{0}\"&dismax=true", UrlEncode(nameToSearch));
|
||||
|
||||
using (var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false))
|
||||
await using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
|
||||
@@ -62,7 +62,7 @@ namespace MediaBrowser.Providers.Music
|
||||
if (HasDiacritics(searchInfo.Name))
|
||||
{
|
||||
// Try again using the search with accent characters url
|
||||
url = string.Format("/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch));
|
||||
url = string.Format(CultureInfo.InvariantCulture, "/ws/2/artist/?query=artistaccent:\"{0}\"", UrlEncode(nameToSearch));
|
||||
|
||||
using var response = await MusicBrainzAlbumProvider.Current.GetMusicBrainzResponse(url, cancellationToken).ConfigureAwait(false);
|
||||
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common;
|
||||
@@ -70,7 +71,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
||||
list.Add(new RemoteImageInfo
|
||||
{
|
||||
ProviderName = Name,
|
||||
Url = string.Format("https://img.omdbapi.com/?i={0}&apikey=2c9d9507", imdbId)
|
||||
Url = string.Format(CultureInfo.InvariantCulture, "https://img.omdbapi.com/?i={0}&apikey=2c9d9507", imdbId)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
||||
}
|
||||
}
|
||||
|
||||
var url = OmdbProvider.GetOmdbUrl(urlQuery, _appHost, cancellationToken);
|
||||
var url = OmdbProvider.GetOmdbUrl(urlQuery);
|
||||
|
||||
using var response = await OmdbProvider.GetOmdbResponse(_httpClientFactory.CreateClient(), url, cancellationToken).ConfigureAwait(false);
|
||||
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||
|
||||
@@ -256,16 +256,16 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
||||
return false;
|
||||
}
|
||||
|
||||
public static string GetOmdbUrl(string query, IApplicationHost appHost, CancellationToken cancellationToken)
|
||||
public static string GetOmdbUrl(string query)
|
||||
{
|
||||
const string url = "https://www.omdbapi.com?apikey=2c9d9507";
|
||||
const string Url = "https://www.omdbapi.com?apikey=2c9d9507";
|
||||
|
||||
if (string.IsNullOrWhiteSpace(query))
|
||||
{
|
||||
return url;
|
||||
return Url;
|
||||
}
|
||||
|
||||
return url + "&" + query;
|
||||
return Url + "&" + query;
|
||||
}
|
||||
|
||||
private async Task<string> EnsureItemInfo(string imdbId, CancellationToken cancellationToken)
|
||||
@@ -290,7 +290,11 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
||||
}
|
||||
}
|
||||
|
||||
var url = GetOmdbUrl(string.Format("i={0}&plot=short&tomatoes=true&r=json", imdbParam), _appHost, cancellationToken);
|
||||
var url = GetOmdbUrl(
|
||||
string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"i={0}&plot=short&tomatoes=true&r=json",
|
||||
imdbParam));
|
||||
|
||||
using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(), url, cancellationToken).ConfigureAwait(false);
|
||||
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||
@@ -323,7 +327,12 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
||||
}
|
||||
}
|
||||
|
||||
var url = GetOmdbUrl(string.Format("i={0}&season={1}&detail=full", imdbParam, seasonId), _appHost, cancellationToken);
|
||||
var url = GetOmdbUrl(
|
||||
string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
"i={0}&season={1}&detail=full",
|
||||
imdbParam,
|
||||
seasonId));
|
||||
|
||||
using var response = await GetOmdbResponse(_httpClientFactory.CreateClient(), url, cancellationToken).ConfigureAwait(false);
|
||||
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||
@@ -348,7 +357,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
||||
|
||||
var dataPath = Path.Combine(_configurationManager.ApplicationPaths.CachePath, "omdb");
|
||||
|
||||
var filename = string.Format("{0}.json", imdbId);
|
||||
var filename = string.Format(CultureInfo.InvariantCulture, "{0}.json", imdbId);
|
||||
|
||||
return Path.Combine(dataPath, filename);
|
||||
}
|
||||
@@ -362,7 +371,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
|
||||
|
||||
var dataPath = Path.Combine(_configurationManager.ApplicationPaths.CachePath, "omdb");
|
||||
|
||||
var filename = string.Format("{0}_season_{1}.json", imdbId, seasonId);
|
||||
var filename = string.Format(CultureInfo.InvariantCulture, "{0}_season_{1}.json", imdbId, seasonId);
|
||||
|
||||
return Path.Combine(dataPath, filename);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
@@ -19,7 +20,6 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
|
||||
{
|
||||
private const string DefaultLanguage = "en";
|
||||
|
||||
private readonly SemaphoreSlim _cacheWriteLock = new SemaphoreSlim(1, 1);
|
||||
private readonly IMemoryCache _cache;
|
||||
private readonly TvDbClient _tvDbClient;
|
||||
private DateTime _tokenCreatedAt;
|
||||
@@ -176,7 +176,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
|
||||
string language,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
searchInfo.SeriesProviderIds.TryGetValue(MetadataProvider.Tvdb.ToString(),
|
||||
searchInfo.SeriesProviderIds.TryGetValue(nameof(MetadataProvider.Tvdb),
|
||||
out var seriesTvdbId);
|
||||
|
||||
var episodeQuery = new EpisodeQuery();
|
||||
@@ -203,10 +203,10 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
|
||||
else if (searchInfo.PremiereDate.HasValue)
|
||||
{
|
||||
// tvdb expects yyyy-mm-dd format
|
||||
episodeQuery.FirstAired = searchInfo.PremiereDate.Value.ToString("yyyy-MM-dd");
|
||||
episodeQuery.FirstAired = searchInfo.PremiereDate.Value.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
return GetEpisodeTvdbId(Convert.ToInt32(seriesTvdbId), episodeQuery, language, cancellationToken);
|
||||
return GetEpisodeTvdbId(Convert.ToInt32(seriesTvdbId, CultureInfo.InvariantCulture), episodeQuery, language, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<string> GetEpisodeTvdbId(
|
||||
@@ -218,7 +218,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
|
||||
var episodePage =
|
||||
await GetEpisodesPageAsync(Convert.ToInt32(seriesTvdbId), episodeQuery, language, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
return episodePage.Data.FirstOrDefault()?.Id.ToString();
|
||||
return episodePage.Data.FirstOrDefault()?.Id.ToString(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
public Task<TvDbResponse<EpisodeRecord[]>> GetEpisodesPageAsync(
|
||||
@@ -276,23 +276,10 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
|
||||
return cachedValue;
|
||||
}
|
||||
|
||||
await _cacheWriteLock.WaitAsync().ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
if (_cache.TryGetValue(key, out cachedValue))
|
||||
{
|
||||
return cachedValue;
|
||||
}
|
||||
|
||||
_tvDbClient.AcceptedLanguage = TvdbUtils.NormalizeLanguage(language) ?? DefaultLanguage;
|
||||
var result = await resultFactory.Invoke().ConfigureAwait(false);
|
||||
_cache.Set(key, result, TimeSpan.FromHours(1));
|
||||
return result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_cacheWriteLock.Release();
|
||||
}
|
||||
_tvDbClient.AcceptedLanguage = TvdbUtils.NormalizeLanguage(language) ?? DefaultLanguage;
|
||||
var result = await resultFactory.Invoke().ConfigureAwait(false);
|
||||
_cache.Set(key, result, TimeSpan.FromHours(1));
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string GenerateKey(params object[] objects)
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
@@ -76,7 +77,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
|
||||
|
||||
var episodeResult =
|
||||
await _tvdbClientManager
|
||||
.GetEpisodesAsync(Convert.ToInt32(episodeTvdbId), language, cancellationToken)
|
||||
.GetEpisodesAsync(Convert.ToInt32(episodeTvdbId, CultureInfo.InvariantCulture), language, cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var image = GetImageInfo(episodeResult.Data);
|
||||
@@ -103,8 +104,8 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
|
||||
|
||||
return new RemoteImageInfo
|
||||
{
|
||||
Width = Convert.ToInt32(episode.ThumbWidth),
|
||||
Height = Convert.ToInt32(episode.ThumbHeight),
|
||||
Width = Convert.ToInt32(episode.ThumbWidth, CultureInfo.InvariantCulture),
|
||||
Height = Convert.ToInt32(episode.ThumbHeight, CultureInfo.InvariantCulture),
|
||||
ProviderName = Name,
|
||||
Url = TvdbUtils.BannerUrl + episode.Filename,
|
||||
Type = ImageType.Primary
|
||||
|
||||
@@ -180,7 +180,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets
|
||||
|
||||
if (!string.IsNullOrEmpty(language))
|
||||
{
|
||||
url += string.Format("&language={0}", TmdbMovieProvider.NormalizeLanguage(language));
|
||||
url += string.Format(CultureInfo.InvariantCulture, "&language={0}", TmdbMovieProvider.NormalizeLanguage(language));
|
||||
|
||||
// Get images in english and with no language
|
||||
url += "&include_image_language=" + TmdbMovieProvider.GetImageLanguagesParam(language);
|
||||
@@ -250,7 +250,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets
|
||||
{
|
||||
var path = GetDataPath(appPaths, tmdbId);
|
||||
|
||||
var filename = string.Format("all-{0}.json", preferredLanguage ?? string.Empty);
|
||||
var filename = string.Format(CultureInfo.InvariantCulture, "all-{0}.json", preferredLanguage ?? string.Empty);
|
||||
|
||||
return Path.Combine(path, filename);
|
||||
}
|
||||
|
||||
@@ -300,7 +300,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
|
||||
{
|
||||
movie.RemoteTrailers = movieData.Trailers.Youtube.Select(i => new MediaUrl
|
||||
{
|
||||
Url = string.Format("https://www.youtube.com/watch?v={0}", i.Source),
|
||||
Url = string.Format(CultureInfo.InvariantCulture, "https://www.youtube.com/watch?v={0}", i.Source),
|
||||
Name = i.Name
|
||||
|
||||
}).ToArray();
|
||||
|
||||
@@ -30,6 +30,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
|
||||
/// </summary>
|
||||
public class TmdbMovieProvider : IRemoteMetadataProvider<Movie, MovieInfo>, IHasOrder
|
||||
{
|
||||
private const string TmdbConfigUrl = TmdbUtils.BaseTmdbApiUrl + "3/configuration?api_key={0}";
|
||||
private const string GetMovieInfo3 = TmdbUtils.BaseTmdbApiUrl + @"3/movie/{0}?api_key={1}&append_to_response=casts,releases,images,keywords,trailers";
|
||||
|
||||
internal static TmdbMovieProvider Current { get; private set; }
|
||||
|
||||
private readonly IJsonSerializer _jsonSerializer;
|
||||
@@ -157,9 +160,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
|
||||
return _tmdbSettings;
|
||||
}
|
||||
|
||||
private const string TmdbConfigUrl = TmdbUtils.BaseTmdbApiUrl + "3/configuration?api_key={0}";
|
||||
private const string GetMovieInfo3 = TmdbUtils.BaseTmdbApiUrl + @"3/movie/{0}?api_key={1}&append_to_response=casts,releases,images,keywords,trailers";
|
||||
|
||||
/// <summary>
|
||||
/// Gets the movie data path.
|
||||
/// </summary>
|
||||
@@ -334,7 +334,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
|
||||
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(header));
|
||||
}
|
||||
|
||||
using var mainResponse = await GetMovieDbResponse(requestMessage);
|
||||
using var mainResponse = await GetMovieDbResponse(requestMessage).ConfigureAwait(false);
|
||||
if (mainResponse.StatusCode == HttpStatusCode.NotFound)
|
||||
{
|
||||
return null;
|
||||
@@ -367,7 +367,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
|
||||
langRequestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(header));
|
||||
}
|
||||
|
||||
using var langResponse = await GetMovieDbResponse(langRequestMessage);
|
||||
using var langResponse = await GetMovieDbResponse(langRequestMessage).ConfigureAwait(false);
|
||||
|
||||
await using var langStream = await langResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||
var langResult = await _jsonSerializer.DeserializeFromStreamAsync<MovieResult>(stream).ConfigureAwait(false);
|
||||
@@ -380,10 +380,10 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
|
||||
/// <summary>
|
||||
/// Gets the movie db response.
|
||||
/// </summary>
|
||||
internal async Task<HttpResponseMessage> GetMovieDbResponse(HttpRequestMessage message)
|
||||
internal Task<HttpResponseMessage> GetMovieDbResponse(HttpRequestMessage message)
|
||||
{
|
||||
message.Headers.UserAgent.Add(new ProductInfoHeaderValue(_appHost.ApplicationUserAgent));
|
||||
return await _httpClientFactory.CreateClient().SendAsync(message);
|
||||
return _httpClientFactory.CreateClient().SendAsync(message);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -22,11 +22,16 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
|
||||
{
|
||||
public class TmdbSearch
|
||||
{
|
||||
private const string SearchUrl = TmdbUtils.BaseTmdbApiUrl + @"3/search/{3}?api_key={1}&query={0}&language={2}";
|
||||
private const string SearchUrlTvWithYear = TmdbUtils.BaseTmdbApiUrl + @"3/search/tv?api_key={1}&query={0}&language={2}&first_air_date_year={3}";
|
||||
private const string SearchUrlMovieWithYear = TmdbUtils.BaseTmdbApiUrl + @"3/search/movie?api_key={1}&query={0}&language={2}&primary_release_year={3}";
|
||||
|
||||
private static readonly CultureInfo _usCulture = new CultureInfo("en-US");
|
||||
|
||||
private static readonly Regex _cleanEnclosed = new Regex(@"\p{Ps}.*\p{Pe}", RegexOptions.Compiled);
|
||||
private static readonly Regex _cleanNonWord = new Regex(@"[\W_]+", RegexOptions.Compiled);
|
||||
private static readonly Regex _cleanStopWords = new Regex(@"\b( # Start at word boundary
|
||||
private static readonly Regex _cleanStopWords = new Regex(
|
||||
@"\b( # Start at word boundary
|
||||
19[0-9]{2}|20[0-9]{2}| # 1900-2099
|
||||
S[0-9]{2}| # Season
|
||||
E[0-9]{2}| # Episode
|
||||
@@ -37,8 +42,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
|
||||
).* # Match rest of string",
|
||||
RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase);
|
||||
|
||||
private const string _searchURL = TmdbUtils.BaseTmdbApiUrl + @"3/search/{3}?api_key={1}&query={0}&language={2}";
|
||||
|
||||
private readonly ILogger _logger;
|
||||
private readonly IJsonSerializer _json;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
@@ -124,7 +127,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
|
||||
name2 = name2.Trim();
|
||||
|
||||
// Search again if the new name is different
|
||||
if (!string.Equals(name2, name) && !string.IsNullOrWhiteSpace(name2))
|
||||
if (!string.Equals(name2, name, StringComparison.Ordinal) && !string.IsNullOrWhiteSpace(name2))
|
||||
{
|
||||
_logger.LogInformation("TmdbSearch: Finding id for item: {0} ({1})", name2, year);
|
||||
results = await GetSearchResults(name2, searchType, year, language, tmdbImageUrl, cancellationToken).ConfigureAwait(false);
|
||||
@@ -164,12 +167,32 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
throw new ArgumentException("name");
|
||||
throw new ArgumentException("String can't be null or empty.", nameof(name));
|
||||
}
|
||||
|
||||
var url3 = string.Format(_searchURL, WebUtility.UrlEncode(name), TmdbUtils.ApiKey, language, type);
|
||||
string url3;
|
||||
if (year != null && string.Equals(type, "movie", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
url3 = string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
SearchUrlMovieWithYear,
|
||||
WebUtility.UrlEncode(name),
|
||||
TmdbUtils.ApiKey,
|
||||
language,
|
||||
year);
|
||||
}
|
||||
else
|
||||
{
|
||||
url3 = string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
SearchUrl,
|
||||
WebUtility.UrlEncode(name),
|
||||
TmdbUtils.ApiKey,
|
||||
language,
|
||||
type);
|
||||
}
|
||||
|
||||
var requestMessage = new HttpRequestMessage(HttpMethod.Get, url3);
|
||||
using var requestMessage = new HttpRequestMessage(HttpMethod.Get, url3);
|
||||
foreach (var header in TmdbUtils.AcceptHeaders)
|
||||
{
|
||||
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(header));
|
||||
@@ -207,12 +230,32 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
{
|
||||
throw new ArgumentException("name");
|
||||
throw new ArgumentException("String can't be null or empty.", nameof(name));
|
||||
}
|
||||
|
||||
var url3 = string.Format(_searchURL, WebUtility.UrlEncode(name), TmdbUtils.ApiKey, language, "tv");
|
||||
string url3;
|
||||
if (year == null)
|
||||
{
|
||||
url3 = string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
SearchUrl,
|
||||
WebUtility.UrlEncode(name),
|
||||
TmdbUtils.ApiKey,
|
||||
language,
|
||||
"tv");
|
||||
}
|
||||
else
|
||||
{
|
||||
url3 = string.Format(
|
||||
CultureInfo.InvariantCulture,
|
||||
SearchUrlTvWithYear,
|
||||
WebUtility.UrlEncode(name),
|
||||
TmdbUtils.ApiKey,
|
||||
language,
|
||||
year);
|
||||
}
|
||||
|
||||
var requestMessage = new HttpRequestMessage(HttpMethod.Get, url3);
|
||||
using var requestMessage = new HttpRequestMessage(HttpMethod.Get, url3);
|
||||
foreach (var header in TmdbUtils.AcceptHeaders)
|
||||
{
|
||||
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(header));
|
||||
@@ -227,7 +270,12 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
|
||||
return results
|
||||
.Select(i =>
|
||||
{
|
||||
var remoteResult = new RemoteSearchResult {SearchProviderName = TmdbMovieProvider.Current.Name, Name = i.Name ?? i.Original_Name, ImageUrl = string.IsNullOrWhiteSpace(i.Poster_Path) ? null : baseImageUrl + i.Poster_Path};
|
||||
var remoteResult = new RemoteSearchResult
|
||||
{
|
||||
SearchProviderName = TmdbMovieProvider.Current.Name,
|
||||
Name = i.Name ?? i.Original_Name,
|
||||
ImageUrl = string.IsNullOrWhiteSpace(i.Poster_Path) ? null : baseImageUrl + i.Poster_Path
|
||||
};
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(i.First_Air_Date))
|
||||
{
|
||||
|
||||
@@ -131,7 +131,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
||||
{
|
||||
if (video.Site.Equals("youtube", System.StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var videoUrl = string.Format("http://www.youtube.com/watch?v={0}", video.Key);
|
||||
var videoUrl = string.Format(CultureInfo.InvariantCulture, "http://www.youtube.com/watch?v={0}", video.Key);
|
||||
item.AddTrailerUrl(videoUrl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
||||
|
||||
var path = TmdbSeriesProvider.GetSeriesDataPath(_configurationManager.ApplicationPaths, tmdbId);
|
||||
|
||||
var filename = string.Format("season-{0}-episode-{1}-{2}.json",
|
||||
var filename = string.Format(CultureInfo.InvariantCulture, "season-{0}-episode-{1}-{2}.json",
|
||||
seasonNumber.ToString(CultureInfo.InvariantCulture),
|
||||
episodeNumber.ToString(CultureInfo.InvariantCulture),
|
||||
preferredLanguage);
|
||||
@@ -116,7 +116,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
||||
|
||||
if (!string.IsNullOrEmpty(language))
|
||||
{
|
||||
url += string.Format("&language={0}", language);
|
||||
url += string.Format(CultureInfo.InvariantCulture, "&language={0}", language);
|
||||
}
|
||||
|
||||
var includeImageLanguageParam = TmdbMovieProvider.GetImageLanguagesParam(language);
|
||||
|
||||
@@ -180,7 +180,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
||||
|
||||
var path = TmdbSeriesProvider.GetSeriesDataPath(_configurationManager.ApplicationPaths, tmdbId);
|
||||
|
||||
var filename = string.Format("season-{0}-{1}.json",
|
||||
var filename = string.Format(CultureInfo.InvariantCulture, "season-{0}-{1}.json",
|
||||
seasonNumber.ToString(CultureInfo.InvariantCulture),
|
||||
preferredLanguage);
|
||||
|
||||
@@ -203,7 +203,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
||||
|
||||
if (!string.IsNullOrEmpty(language))
|
||||
{
|
||||
url += string.Format("&language={0}", TmdbMovieProvider.NormalizeLanguage(language));
|
||||
url += string.Format(CultureInfo.InvariantCulture, "&language={0}", TmdbMovieProvider.NormalizeLanguage(language));
|
||||
}
|
||||
|
||||
var includeImageLanguageParam = TmdbMovieProvider.GetImageLanguagesParam(language);
|
||||
|
||||
@@ -496,7 +496,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
|
||||
|
||||
var path = GetSeriesDataPath(_configurationManager.ApplicationPaths, tmdbId);
|
||||
|
||||
var filename = string.Format("series-{0}.json", preferredLanguage ?? string.Empty);
|
||||
var filename = string.Format(CultureInfo.InvariantCulture, "series-{0}.json", preferredLanguage ?? string.Empty);
|
||||
|
||||
return Path.Combine(path, filename);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
@@ -100,7 +101,7 @@ namespace MediaBrowser.Providers.Studios
|
||||
|
||||
private string GetUrl(string image, string filename)
|
||||
{
|
||||
return string.Format("https://raw.github.com/MediaBrowser/MediaBrowser.Resources/master/images/imagesbyname/studios/{0}/{1}.jpg", image, filename);
|
||||
return string.Format(CultureInfo.InvariantCulture, "https://raw.github.com/MediaBrowser/MediaBrowser.Resources/master/images/imagesbyname/studios/{0}/{1}.jpg", image, filename);
|
||||
}
|
||||
|
||||
private Task<string> EnsureThumbsList(string file, CancellationToken cancellationToken)
|
||||
|
||||
@@ -87,7 +87,7 @@ namespace MediaBrowser.Providers.TV
|
||||
else if (existingSeason.IsVirtualItem)
|
||||
{
|
||||
existingSeason.IsVirtualItem = false;
|
||||
existingSeason.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken);
|
||||
await existingSeason.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
|
||||
seasons = null;
|
||||
}
|
||||
}
|
||||
@@ -113,7 +113,7 @@ namespace MediaBrowser.Providers.TV
|
||||
else if (existingSeason.IsVirtualItem)
|
||||
{
|
||||
existingSeason.IsVirtualItem = false;
|
||||
existingSeason.UpdateToRepository(ItemUpdateType.MetadataEdit, cancellationToken);
|
||||
await existingSeason.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
|
||||
seasons = null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user