aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.Providers
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.Providers')
-rw-r--r--MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs1
-rw-r--r--MediaBrowser.Providers/LiveTv/LiveTvMetadataService.cs (renamed from MediaBrowser.Providers/LiveTv/ProgramMetadataService.cs)0
-rw-r--r--MediaBrowser.Providers/Manager/ImageSaver.cs32
-rw-r--r--MediaBrowser.Providers/Manager/ItemImageProvider.cs56
-rw-r--r--MediaBrowser.Providers/Manager/MetadataService.cs80
-rw-r--r--MediaBrowser.Providers/Manager/ProviderManager.cs4
-rw-r--r--MediaBrowser.Providers/Manager/ProviderUtils.cs4
-rw-r--r--MediaBrowser.Providers/Manager/RefreshResult.cs15
-rw-r--r--MediaBrowser.Providers/MediaBrowser.Providers.csproj8
-rw-r--r--MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs16
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs29
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs72
-rw-r--r--MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs23
-rw-r--r--MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs31
-rw-r--r--MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs18
-rw-r--r--MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs104
-rw-r--r--MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs9
-rw-r--r--MediaBrowser.Providers/Movies/ImdbExternalId.cs (renamed from MediaBrowser.Providers/Movies/MovieExternalIds.cs)18
-rw-r--r--MediaBrowser.Providers/Movies/ImdbPersonExternalId.cs27
-rw-r--r--MediaBrowser.Providers/Music/AlbumInfoExtensions.cs (renamed from MediaBrowser.Providers/Music/Extensions.cs)0
-rw-r--r--MediaBrowser.Providers/Music/ImvdbId.cs (renamed from MediaBrowser.Providers/Music/MusicExternalIds.cs)0
-rw-r--r--MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs10
-rw-r--r--MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs10
-rw-r--r--MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumExternalId.cs27
-rw-r--r--MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistExternalId.cs27
-rw-r--r--MediaBrowser.Providers/Plugins/AudioDb/AudioDbOtherAlbumExternalId.cs27
-rw-r--r--MediaBrowser.Providers/Plugins/AudioDb/AudioDbOtherArtistExternalId.cs27
-rw-r--r--MediaBrowser.Providers/Plugins/AudioDb/ExternalIds.cs81
-rw-r--r--MediaBrowser.Providers/Plugins/AudioDb/Plugin.cs12
-rw-r--r--MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs1
-rw-r--r--MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs (renamed from MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs)33
-rw-r--r--MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs12
-rw-r--r--MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs10
-rw-r--r--MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs27
-rw-r--r--MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs1
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs9
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/Models/General/Videos.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/Trailers.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/Models/People/PersonImages.cs2
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs1
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbImageProvider.cs5
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbImageSettings.cs (renamed from MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSettings.cs)11
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs38
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs11
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSettingsResult.cs9
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/Music/TmdbMusicVideoProvider.cs4
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs15
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeImageProvider.cs23
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs17
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs23
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonImageProvider.cs5
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs34
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs28
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs53
-rw-r--r--MediaBrowser.Providers/Plugins/Tmdb/Trailers/TmdbTrailerProvider.cs8
-rw-r--r--MediaBrowser.Providers/Studios/StudiosImageProvider.cs16
-rw-r--r--MediaBrowser.Providers/Subtitles/SubtitleManager.cs2
-rw-r--r--MediaBrowser.Providers/TV/DummySeasonProvider.cs15
-rw-r--r--MediaBrowser.Providers/TV/MissingEpisodeProvider.cs46
-rw-r--r--MediaBrowser.Providers/TV/SeasonMetadataService.cs6
-rw-r--r--MediaBrowser.Providers/TV/TvExternalIds.cs82
-rw-r--r--MediaBrowser.Providers/TV/TvdbEpisodeExternalId.cs28
-rw-r--r--MediaBrowser.Providers/TV/TvdbExternalId.cs28
-rw-r--r--MediaBrowser.Providers/TV/TvdbSeasonExternalId.cs28
-rw-r--r--MediaBrowser.Providers/TV/Zap2ItExternalId.cs28
65 files changed, 785 insertions, 646 deletions
diff --git a/MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs b/MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs
index 46f368f72..e0f3131fd 100644
--- a/MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs
+++ b/MediaBrowser.Providers/Folders/CollectionFolderMetadataService.cs
@@ -1,6 +1,5 @@
#pragma warning disable CS1591
-
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
diff --git a/MediaBrowser.Providers/LiveTv/ProgramMetadataService.cs b/MediaBrowser.Providers/LiveTv/LiveTvMetadataService.cs
index 2e6cf4530..2e6cf4530 100644
--- a/MediaBrowser.Providers/LiveTv/ProgramMetadataService.cs
+++ b/MediaBrowser.Providers/LiveTv/LiveTvMetadataService.cs
diff --git a/MediaBrowser.Providers/Manager/ImageSaver.cs b/MediaBrowser.Providers/Manager/ImageSaver.cs
index 413d297cb..19a42d506 100644
--- a/MediaBrowser.Providers/Manager/ImageSaver.cs
+++ b/MediaBrowser.Providers/Manager/ImageSaver.cs
@@ -7,7 +7,6 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
@@ -59,6 +58,16 @@ namespace MediaBrowser.Providers.Manager
_logger = logger;
}
+ private bool EnableExtraThumbsDuplication
+ {
+ get
+ {
+ var config = _config.GetConfiguration<XbmcMetadataOptions>("xbmcmetadata");
+
+ return config.EnableExtraThumbsDuplication;
+ }
+ }
+
/// <summary>
/// Saves the image.
/// </summary>
@@ -69,7 +78,7 @@ namespace MediaBrowser.Providers.Manager
/// <param name="imageIndex">Index of the image.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task.</returns>
- /// <exception cref="ArgumentNullException">mimeType</exception>
+ /// <exception cref="ArgumentNullException">mimeType.</exception>
public Task SaveImage(BaseItem item, Stream source, string mimeType, ImageType type, int? imageIndex, CancellationToken cancellationToken)
{
return SaveImage(item, source, mimeType, type, imageIndex, null, cancellationToken);
@@ -312,7 +321,7 @@ namespace MediaBrowser.Providers.Manager
/// <exception cref="ArgumentNullException">
/// imageIndex
/// or
- /// imageIndex
+ /// imageIndex.
/// </exception>
private ItemImageInfo GetCurrentImage(BaseItem item, ImageType type, int imageIndex)
{
@@ -328,7 +337,8 @@ namespace MediaBrowser.Providers.Manager
/// <param name="path">The path.</param>
/// <exception cref="ArgumentNullException">imageIndex
/// or
- /// imageIndex</exception>
+ /// imageIndex.
+ /// </exception>
private void SetImagePath(BaseItem item, ImageType type, int? imageIndex, string path)
{
item.SetImagePath(type, imageIndex ?? 0, _fileSystem.GetFileInfo(path));
@@ -346,7 +356,7 @@ namespace MediaBrowser.Providers.Manager
/// <exception cref="ArgumentNullException">
/// imageIndex
/// or
- /// imageIndex
+ /// imageIndex.
/// </exception>
private string GetStandardSavePath(BaseItem item, ImageType type, int? imageIndex, string mimeType, bool saveLocally)
{
@@ -500,7 +510,7 @@ namespace MediaBrowser.Providers.Manager
/// <param name="imageIndex">Index of the image.</param>
/// <param name="mimeType">Type of the MIME.</param>
/// <returns>IEnumerable{System.String}.</returns>
- /// <exception cref="ArgumentNullException">imageIndex</exception>
+ /// <exception cref="ArgumentNullException">imageIndex.</exception>
private string[] GetCompatibleSavePaths(BaseItem item, ImageType type, int? imageIndex, string mimeType)
{
var season = item as Season;
@@ -604,16 +614,6 @@ namespace MediaBrowser.Providers.Manager
return new[] { GetStandardSavePath(item, type, imageIndex, mimeType, true) };
}
- private bool EnableExtraThumbsDuplication
- {
- get
- {
- var config = _config.GetConfiguration<XbmcMetadataOptions>("xbmcmetadata");
-
- return config.EnableExtraThumbsDuplication;
- }
- }
-
/// <summary>
/// Gets the save path for item in mixed folder.
/// </summary>
diff --git a/MediaBrowser.Providers/Manager/ItemImageProvider.cs b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
index 9227b6d93..d0bdbd7c9 100644
--- a/MediaBrowser.Providers/Manager/ItemImageProvider.cs
+++ b/MediaBrowser.Providers/Manager/ItemImageProvider.cs
@@ -28,6 +28,22 @@ namespace MediaBrowser.Providers.Manager
private readonly IProviderManager _providerManager;
private readonly IFileSystem _fileSystem;
+ /// <summary>
+ /// Image types that are only one per item.
+ /// </summary>
+ private readonly ImageType[] _singularImages =
+ {
+ ImageType.Primary,
+ ImageType.Art,
+ ImageType.Banner,
+ ImageType.Box,
+ ImageType.BoxRear,
+ ImageType.Disc,
+ ImageType.Logo,
+ ImageType.Menu,
+ ImageType.Thumb
+ };
+
public ItemImageProvider(ILogger logger, IProviderManager providerManager, IFileSystem fileSystem)
{
_logger = logger;
@@ -175,22 +191,6 @@ namespace MediaBrowser.Providers.Manager
}
}
- /// <summary>
- /// Image types that are only one per item.
- /// </summary>
- private readonly ImageType[] _singularImages =
- {
- ImageType.Primary,
- ImageType.Art,
- ImageType.Banner,
- ImageType.Box,
- ImageType.BoxRear,
- ImageType.Disc,
- ImageType.Logo,
- ImageType.Menu,
- ImageType.Thumb
- };
-
private bool HasImage(BaseItem item, ImageType type)
{
return item.HasImage(type);
@@ -378,7 +378,6 @@ namespace MediaBrowser.Providers.Manager
}
else
{
-
var newDateModified = _fileSystem.GetLastWriteTimeUtc(image.FileInfo);
// If date changed then we need to reset saved image dimensions
@@ -441,7 +440,9 @@ namespace MediaBrowser.Providers.Manager
return changed;
}
- private async Task<bool> DownloadImage(BaseItem item, LibraryOptions libraryOptions,
+ private async Task<bool> DownloadImage(
+ BaseItem item,
+ LibraryOptions libraryOptions,
IRemoteImageProvider provider,
RefreshResult result,
IEnumerable<RemoteImageInfo> images,
@@ -522,11 +523,6 @@ namespace MediaBrowser.Providers.Manager
return false;
}
- // if (!item.IsSaveLocalMetadataEnabled())
- //{
- // return true;
- //}
-
return true;
}
@@ -539,13 +535,15 @@ namespace MediaBrowser.Providers.Manager
private void SaveImageStub(BaseItem item, ImageType imageType, IEnumerable<string> urls, int newIndex)
{
- var path = string.Join("|", urls.Take(1).ToArray());
+ var path = string.Join('|', urls.Take(1));
- item.SetImage(new ItemImageInfo
- {
- Path = path,
- Type = imageType
- }, newIndex);
+ item.SetImage(
+ new ItemImageInfo
+ {
+ Path = path,
+ Type = imageType
+ },
+ newIndex);
}
private async Task DownloadBackdrops(BaseItem item, LibraryOptions libraryOptions, ImageType imageType, int limit, IRemoteImageProvider provider, RefreshResult result, IEnumerable<RemoteImageInfo> images, int minWidth, CancellationToken cancellationToken)
diff --git a/MediaBrowser.Providers/Manager/MetadataService.cs b/MediaBrowser.Providers/Manager/MetadataService.cs
index d0de58427..f110eafa5 100644
--- a/MediaBrowser.Providers/Manager/MetadataService.cs
+++ b/MediaBrowser.Providers/Manager/MetadataService.cs
@@ -21,12 +21,6 @@ namespace MediaBrowser.Providers.Manager
where TItemType : BaseItem, IHasLookupInfo<TIdType>, new()
where TIdType : ItemLookupInfo, new()
{
- protected readonly IServerConfigurationManager ServerConfigurationManager;
- protected readonly ILogger<MetadataService<TItemType, TIdType>> Logger;
- protected readonly IProviderManager ProviderManager;
- protected readonly IFileSystem FileSystem;
- protected readonly ILibraryManager LibraryManager;
-
protected MetadataService(IServerConfigurationManager serverConfigurationManager, ILogger<MetadataService<TItemType, TIdType>> logger, IProviderManager providerManager, IFileSystem fileSystem, ILibraryManager libraryManager)
{
ServerConfigurationManager = serverConfigurationManager;
@@ -36,6 +30,26 @@ namespace MediaBrowser.Providers.Manager
LibraryManager = libraryManager;
}
+ protected IServerConfigurationManager ServerConfigurationManager { get; }
+
+ protected ILogger<MetadataService<TItemType, TIdType>> Logger { get; }
+
+ protected IProviderManager ProviderManager { get; }
+
+ protected IFileSystem FileSystem { get; }
+
+ protected ILibraryManager LibraryManager { get; }
+
+ protected virtual bool EnableUpdatingPremiereDateFromChildren => false;
+
+ protected virtual bool EnableUpdatingGenresFromChildren => false;
+
+ protected virtual bool EnableUpdatingStudiosFromChildren => false;
+
+ protected virtual bool EnableUpdatingOfficialRatingFromChildren => false;
+
+ public virtual int Order => 0;
+
private FileSystemMetadata TryGetFile(string path, IDirectoryService directoryService)
{
try
@@ -283,7 +297,7 @@ namespace MediaBrowser.Providers.Manager
}
/// <summary>
- /// Befores the save.
+ /// Before the save.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="isFullRefresh">if set to <c>true</c> [is full refresh].</param>
@@ -341,13 +355,12 @@ namespace MediaBrowser.Providers.Manager
protected virtual IList<BaseItem> GetChildrenForMetadataUpdates(TItemType item)
{
- var folder = item as Folder;
- if (folder != null)
+ if (item is Folder folder)
{
return folder.GetRecursiveChildren();
}
- return new List<BaseItem>();
+ return Array.Empty<BaseItem>();
}
protected virtual ItemUpdateType UpdateMetadataFromChildren(TItemType item, IList<BaseItem> children, bool isFullRefresh, ItemUpdateType currentUpdateType)
@@ -442,14 +455,6 @@ namespace MediaBrowser.Providers.Manager
return updateType;
}
- protected virtual bool EnableUpdatingPremiereDateFromChildren => false;
-
- protected virtual bool EnableUpdatingGenresFromChildren => false;
-
- protected virtual bool EnableUpdatingStudiosFromChildren => false;
-
- protected virtual bool EnableUpdatingOfficialRatingFromChildren => false;
-
private ItemUpdateType UpdatePremiereDate(TItemType item, IList<BaseItem> children)
{
var updateType = ItemUpdateType.None;
@@ -658,7 +663,8 @@ namespace MediaBrowser.Providers.Manager
return type == typeof(TItemType);
}
- protected virtual async Task<RefreshResult> RefreshWithProviders(MetadataResult<TItemType> metadata,
+ protected virtual async Task<RefreshResult> RefreshWithProviders(
+ MetadataResult<TItemType> metadata,
TIdType id,
MetadataRefreshOptions options,
List<IMetadataProvider> providers,
@@ -773,7 +779,7 @@ namespace MediaBrowser.Providers.Manager
else
{
// TODO: If the new metadata from above has some blank data, this can cause old data to get filled into those empty fields
- MergeData(metadata, temp, new MetadataField[] { }, false, false);
+ MergeData(metadata, temp, Array.Empty<MetadataField>(), false, false);
MergeData(temp, metadata, item.LockedFields, true, false);
}
}
@@ -807,7 +813,7 @@ namespace MediaBrowser.Providers.Manager
try
{
- refreshResult.UpdateType = refreshResult.UpdateType | await provider.FetchAsync(item, options, cancellationToken).ConfigureAwait(false);
+ refreshResult.UpdateType |= await provider.FetchAsync(item, options, cancellationToken).ConfigureAwait(false);
}
catch (OperationCanceledException)
{
@@ -875,16 +881,6 @@ namespace MediaBrowser.Providers.Manager
return refreshResult;
}
- private string NormalizeLanguage(string language)
- {
- if (string.IsNullOrWhiteSpace(language))
- {
- return "en";
- }
-
- return language;
- }
-
private void MergeNewData(TItemType source, TIdType lookupInfo)
{
// Copy new provider id's that may have been obtained
@@ -900,24 +896,23 @@ namespace MediaBrowser.Providers.Manager
}
}
- protected abstract void MergeData(MetadataResult<TItemType> source,
+ protected abstract void MergeData(
+ MetadataResult<TItemType> source,
MetadataResult<TItemType> target,
MetadataField[] lockedFields,
bool replaceData,
bool mergeMetadataSettings);
- public virtual int Order => 0;
-
private bool HasChanged(BaseItem item, IHasItemChangeMonitor changeMonitor, IDirectoryService directoryService)
{
try
{
var hasChanged = changeMonitor.HasChanged(item, directoryService);
- // if (hasChanged)
- //{
- // logger.LogDebug("{0} reports change to {1}", changeMonitor.GetType().Name, item.Path ?? item.Name);
- //}
+ if (hasChanged)
+ {
+ Logger.LogDebug("{0} reports change to {1}", changeMonitor.GetType().Name, item.Path ?? item.Name);
+ }
return hasChanged;
}
@@ -928,13 +923,4 @@ namespace MediaBrowser.Providers.Manager
}
}
}
-
- public class RefreshResult
- {
- public ItemUpdateType UpdateType { get; set; }
-
- public string ErrorMessage { get; set; }
-
- public int Failures { get; set; }
- }
}
diff --git a/MediaBrowser.Providers/Manager/ProviderManager.cs b/MediaBrowser.Providers/Manager/ProviderManager.cs
index 171b824ca..b6fb4267f 100644
--- a/MediaBrowser.Providers/Manager/ProviderManager.cs
+++ b/MediaBrowser.Providers/Manager/ProviderManager.cs
@@ -9,7 +9,6 @@ using System.Net.Http;
using System.Net.Mime;
using System.Threading;
using System.Threading.Tasks;
-using Jellyfin.Data.Entities;
using Jellyfin.Data.Events;
using MediaBrowser.Common.Net;
using MediaBrowser.Common.Progress;
@@ -905,8 +904,7 @@ namespace MediaBrowser.Providers.Manager
return provider.GetImageResponse(url, cancellationToken);
}
- /// <inheritdoc/>
- public IEnumerable<IExternalId> GetExternalIds(IHasProviderIds item)
+ private IEnumerable<IExternalId> GetExternalIds(IHasProviderIds item)
{
return _externalIds.Where(i =>
{
diff --git a/MediaBrowser.Providers/Manager/ProviderUtils.cs b/MediaBrowser.Providers/Manager/ProviderUtils.cs
index a4fd6ca84..70a5a6ac1 100644
--- a/MediaBrowser.Providers/Manager/ProviderUtils.cs
+++ b/MediaBrowser.Providers/Manager/ProviderUtils.cs
@@ -26,12 +26,12 @@ namespace MediaBrowser.Providers.Manager
if (source == null)
{
- throw new ArgumentNullException(nameof(source));
+ throw new ArgumentException("Item cannot be null.", nameof(sourceResult));
}
if (target == null)
{
- throw new ArgumentNullException(nameof(target));
+ throw new ArgumentException("Item cannot be null.", nameof(targetResult));
}
if (!lockedFields.Contains(MetadataField.Name))
diff --git a/MediaBrowser.Providers/Manager/RefreshResult.cs b/MediaBrowser.Providers/Manager/RefreshResult.cs
new file mode 100644
index 000000000..72fc61e42
--- /dev/null
+++ b/MediaBrowser.Providers/Manager/RefreshResult.cs
@@ -0,0 +1,15 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Library;
+
+namespace MediaBrowser.Providers.Manager
+{
+ public class RefreshResult
+ {
+ public ItemUpdateType UpdateType { get; set; }
+
+ public string ErrorMessage { get; set; }
+
+ public int Failures { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/MediaBrowser.Providers.csproj b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
index 39f93c479..813dd441f 100644
--- a/MediaBrowser.Providers/MediaBrowser.Providers.csproj
+++ b/MediaBrowser.Providers/MediaBrowser.Providers.csproj
@@ -16,12 +16,12 @@
</ItemGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.7" />
- <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.1.7" />
- <PackageReference Include="Microsoft.Extensions.Http" Version="3.1.7" />
+ <PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.8" />
+ <PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="3.1.8" />
+ <PackageReference Include="Microsoft.Extensions.Http" Version="3.1.8" />
<PackageReference Include="OptimizedPriorityQueue" Version="4.2.0" />
<PackageReference Include="PlaylistsNET" Version="1.1.2" />
- <PackageReference Include="TvDbSharper" Version="3.2.1" />
+ <PackageReference Include="TvDbSharper" Version="3.2.2" />
</ItemGroup>
<PropertyGroup>
diff --git a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
index f69ec9744..64ad1bddf 100644
--- a/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/AudioImageProvider.cs
@@ -34,6 +34,10 @@ namespace MediaBrowser.Providers.MediaInfo
_fileSystem = fileSystem;
}
+ public string AudioImagesPath => Path.Combine(_config.ApplicationPaths.CachePath, "extracted-audio-images");
+
+ public string Name => "Image Extractor";
+
public IEnumerable<ImageType> GetSupportedImages(BaseItem item)
{
return new List<ImageType> { ImageType.Primary };
@@ -97,11 +101,11 @@ namespace MediaBrowser.Providers.MediaInfo
if (item.GetType() == typeof(Audio))
{
- var albumArtist = item.AlbumArtists.FirstOrDefault();
-
- if (!string.IsNullOrWhiteSpace(item.Album) && !string.IsNullOrWhiteSpace(albumArtist))
+ if (item.AlbumArtists.Count > 0
+ && !string.IsNullOrWhiteSpace(item.Album)
+ && !string.IsNullOrWhiteSpace(item.AlbumArtists[0]))
{
- filename = (item.Album + "-" + albumArtist).GetMD5().ToString("N", CultureInfo.InvariantCulture);
+ filename = (item.Album + "-" + item.AlbumArtists[0]).GetMD5().ToString("N", CultureInfo.InvariantCulture);
}
else
{
@@ -121,10 +125,6 @@ namespace MediaBrowser.Providers.MediaInfo
return Path.Join(AudioImagesPath, prefix, filename);
}
- public string AudioImagesPath => Path.Combine(_config.ApplicationPaths.CachePath, "extracted-audio-images");
-
- public string Name => "Image Extractor";
-
public bool Supports(BaseItem item)
{
if (item.IsShortcut)
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
index 77f03580a..945463666 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeAudioInfo.cs
@@ -37,7 +37,9 @@ namespace MediaBrowser.Providers.MediaInfo
_mediaSourceManager = mediaSourceManager;
}
- public async Task<ItemUpdateType> Probe<T>(T item, MetadataRefreshOptions options,
+ public async Task<ItemUpdateType> Probe<T>(
+ T item,
+ MetadataRefreshOptions options,
CancellationToken cancellationToken)
where T : Audio
{
@@ -52,19 +54,21 @@ namespace MediaBrowser.Providers.MediaInfo
protocol = _mediaSourceManager.GetPathProtocol(path);
}
- var result = await _mediaEncoder.GetMediaInfo(new MediaInfoRequest
- {
- MediaType = DlnaProfileType.Audio,
- MediaSource = new MediaSourceInfo
+ var result = await _mediaEncoder.GetMediaInfo(
+ new MediaInfoRequest
{
- Path = path,
- Protocol = protocol
- }
- }, cancellationToken).ConfigureAwait(false);
+ MediaType = DlnaProfileType.Audio,
+ MediaSource = new MediaSourceInfo
+ {
+ Path = path,
+ Protocol = protocol
+ }
+ },
+ cancellationToken).ConfigureAwait(false);
cancellationToken.ThrowIfCancellationRequested();
- Fetch(item, cancellationToken, result);
+ Fetch(item, result, cancellationToken);
}
return ItemUpdateType.MetadataImport;
@@ -74,10 +78,9 @@ namespace MediaBrowser.Providers.MediaInfo
/// Fetches the specified audio.
/// </summary>
/// <param name="audio">The audio.</param>
- /// <param name="cancellationToken">The cancellation token.</param>
/// <param name="mediaInfo">The media information.</param>
- /// <returns>Task.</returns>
- protected void Fetch(Audio audio, CancellationToken cancellationToken, Model.MediaInfo.MediaInfo mediaInfo)
+ /// <param name="cancellationToken">The cancellation token.</param>
+ protected void Fetch(Audio audio, Model.MediaInfo.MediaInfo mediaInfo, CancellationToken cancellationToken)
{
var mediaStreams = mediaInfo.MediaStreams;
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
index 9926275ae..c61187fdf 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeProvider.cs
@@ -5,8 +5,6 @@ using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using MediaBrowser.Common.Configuration;
-using MediaBrowser.Controller.Channels;
using MediaBrowser.Controller.Chapters;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
@@ -20,9 +18,7 @@ using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Globalization;
-using MediaBrowser.Model.IO;
using MediaBrowser.Model.MediaInfo;
-using MediaBrowser.Model.Serialization;
using Microsoft.Extensions.Logging;
namespace MediaBrowser.Providers.MediaInfo
@@ -50,9 +46,43 @@ namespace MediaBrowser.Providers.MediaInfo
private readonly IChapterManager _chapterManager;
private readonly ILibraryManager _libraryManager;
private readonly IMediaSourceManager _mediaSourceManager;
+ private readonly SubtitleResolver _subtitleResolver;
+
+ private readonly Task<ItemUpdateType> _cachedTask = Task.FromResult(ItemUpdateType.None);
+
+ public FFProbeProvider(
+ ILogger<FFProbeProvider> logger,
+ IMediaSourceManager mediaSourceManager,
+ IMediaEncoder mediaEncoder,
+ IItemRepository itemRepo,
+ IBlurayExaminer blurayExaminer,
+ ILocalizationManager localization,
+ IEncodingManager encodingManager,
+ IServerConfigurationManager config,
+ ISubtitleManager subtitleManager,
+ IChapterManager chapterManager,
+ ILibraryManager libraryManager)
+ {
+ _logger = logger;
+ _mediaEncoder = mediaEncoder;
+ _itemRepo = itemRepo;
+ _blurayExaminer = blurayExaminer;
+ _localization = localization;
+ _encodingManager = encodingManager;
+ _config = config;
+ _subtitleManager = subtitleManager;
+ _chapterManager = chapterManager;
+ _libraryManager = libraryManager;
+ _mediaSourceManager = mediaSourceManager;
+
+ _subtitleResolver = new SubtitleResolver(BaseItem.LocalizationManager);
+ }
public string Name => "ffprobe";
+ // Run last
+ public int Order => 100;
+
public bool HasChanged(BaseItem item, IDirectoryService directoryService)
{
var video = item as Video;
@@ -117,37 +147,6 @@ namespace MediaBrowser.Providers.MediaInfo
return FetchAudioInfo(item, options, cancellationToken);
}
- private SubtitleResolver _subtitleResolver;
-
- public FFProbeProvider(
- ILogger<FFProbeProvider> logger,
- IMediaSourceManager mediaSourceManager,
- IMediaEncoder mediaEncoder,
- IItemRepository itemRepo,
- IBlurayExaminer blurayExaminer,
- ILocalizationManager localization,
- IEncodingManager encodingManager,
- IServerConfigurationManager config,
- ISubtitleManager subtitleManager,
- IChapterManager chapterManager,
- ILibraryManager libraryManager)
- {
- _logger = logger;
- _mediaEncoder = mediaEncoder;
- _itemRepo = itemRepo;
- _blurayExaminer = blurayExaminer;
- _localization = localization;
- _encodingManager = encodingManager;
- _config = config;
- _subtitleManager = subtitleManager;
- _chapterManager = chapterManager;
- _libraryManager = libraryManager;
- _mediaSourceManager = mediaSourceManager;
-
- _subtitleResolver = new SubtitleResolver(BaseItem.LocalizationManager);
- }
-
- private readonly Task<ItemUpdateType> _cachedTask = Task.FromResult(ItemUpdateType.None);
public Task<ItemUpdateType> FetchVideoInfo<T>(T item, MetadataRefreshOptions options, CancellationToken cancellationToken)
where T : Video
{
@@ -234,8 +233,5 @@ namespace MediaBrowser.Providers.MediaInfo
return prober.Probe(item, options, cancellationToken);
}
-
- // Run last
- public int Order => 100;
}
}
diff --git a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
index 53a6bb619..776dee780 100644
--- a/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
+++ b/MediaBrowser.Providers/MediaInfo/FFProbeVideoInfo.cs
@@ -539,17 +539,18 @@ namespace MediaBrowser.Providers.MediaInfo
if (enableSubtitleDownloading && enabled)
{
- var downloadedLanguages = await new SubtitleDownloader(_logger,
- _subtitleManager)
- .DownloadSubtitles(video,
- currentStreams.Concat(externalSubtitleStreams).ToList(),
- skipIfEmbeddedSubtitlesPresent,
- skipIfAudioTrackMatches,
- requirePerfectMatch,
- subtitleDownloadLanguages,
- libraryOptions.DisabledSubtitleFetchers,
- libraryOptions.SubtitleFetcherOrder,
- cancellationToken).ConfigureAwait(false);
+ var downloadedLanguages = await new SubtitleDownloader(
+ _logger,
+ _subtitleManager).DownloadSubtitles(
+ video,
+ currentStreams.Concat(externalSubtitleStreams).ToList(),
+ skipIfEmbeddedSubtitlesPresent,
+ skipIfAudioTrackMatches,
+ requirePerfectMatch,
+ subtitleDownloadLanguages,
+ libraryOptions.DisabledSubtitleFetchers,
+ libraryOptions.SubtitleFetcherOrder,
+ cancellationToken).ConfigureAwait(false);
// Rescan
if (downloadedLanguages.Count > 0)
diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs b/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs
index acddb73d0..912aedb0d 100644
--- a/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs
+++ b/MediaBrowser.Providers/MediaInfo/SubtitleDownloader.cs
@@ -42,8 +42,16 @@ namespace MediaBrowser.Providers.MediaInfo
foreach (var lang in languages)
{
- var downloaded = await DownloadSubtitles(video, mediaStreams, skipIfEmbeddedSubtitlesPresent,
- skipIfAudioTrackMatches, requirePerfectMatch, lang, disabledSubtitleFetchers, subtitleFetcherOrder, cancellationToken).ConfigureAwait(false);
+ var downloaded = await DownloadSubtitles(
+ video,
+ mediaStreams,
+ skipIfEmbeddedSubtitlesPresent,
+ skipIfAudioTrackMatches,
+ requirePerfectMatch,
+ lang,
+ disabledSubtitleFetchers,
+ subtitleFetcherOrder,
+ cancellationToken).ConfigureAwait(false);
if (downloaded)
{
@@ -54,7 +62,8 @@ namespace MediaBrowser.Providers.MediaInfo
return downloadedLanguages;
}
- public Task<bool> DownloadSubtitles(Video video,
+ public Task<bool> DownloadSubtitles(
+ Video video,
List<MediaStream> mediaStreams,
bool skipIfEmbeddedSubtitlesPresent,
bool skipIfAudioTrackMatches,
@@ -90,11 +99,21 @@ namespace MediaBrowser.Providers.MediaInfo
return Task.FromResult(false);
}
- return DownloadSubtitles(video, mediaStreams, skipIfEmbeddedSubtitlesPresent, skipIfAudioTrackMatches,
- requirePerfectMatch, lang, disabledSubtitleFetchers, subtitleFetcherOrder, mediaType, cancellationToken);
+ return DownloadSubtitles(
+ video,
+ mediaStreams,
+ skipIfEmbeddedSubtitlesPresent,
+ skipIfAudioTrackMatches,
+ requirePerfectMatch,
+ lang,
+ disabledSubtitleFetchers,
+ subtitleFetcherOrder,
+ mediaType,
+ cancellationToken);
}
- private async Task<bool> DownloadSubtitles(Video video,
+ private async Task<bool> DownloadSubtitles(
+ Video video,
List<MediaStream> mediaStreams,
bool skipIfEmbeddedSubtitlesPresent,
bool skipIfAudioTrackMatches,
diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
index 43659b68c..e9f999c6d 100644
--- a/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
+++ b/MediaBrowser.Providers/MediaInfo/SubtitleResolver.cs
@@ -66,9 +66,10 @@ namespace MediaBrowser.Providers.MediaInfo
return streams;
}
- public List<string> GetExternalSubtitleFiles(Video video,
- IDirectoryService directoryService,
- bool clearCache)
+ public List<string> GetExternalSubtitleFiles(
+ Video video,
+ IDirectoryService directoryService,
+ bool clearCache)
{
var list = new List<string>();
@@ -87,7 +88,9 @@ namespace MediaBrowser.Providers.MediaInfo
return list;
}
- private void AddExternalSubtitleStreams(List<MediaStream> streams, string folder,
+ private void AddExternalSubtitleStreams(
+ List<MediaStream> streams,
+ string folder,
string videoPath,
int startIndex,
IDirectoryService directoryService,
@@ -98,7 +101,8 @@ namespace MediaBrowser.Providers.MediaInfo
AddExternalSubtitleStreams(streams, videoPath, startIndex, files);
}
- public void AddExternalSubtitleStreams(List<MediaStream> streams,
+ public void AddExternalSubtitleStreams(
+ List<MediaStream> streams,
string videoPath,
int startIndex,
string[] files)
@@ -185,8 +189,8 @@ namespace MediaBrowser.Providers.MediaInfo
private string NormalizeFilenameForSubtitleComparison(string filename)
{
// Try to account for sloppy file naming
- filename = filename.Replace("_", string.Empty);
- filename = filename.Replace(" ", string.Empty);
+ filename = filename.Replace("_", string.Empty, StringComparison.Ordinal);
+ filename = filename.Replace(" ", string.Empty, StringComparison.Ordinal);
// can't normalize this due to languages such as pt-br
// filename = filename.Replace("-", string.Empty);
diff --git a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs
index 91ab7b4ac..d231bfa2f 100644
--- a/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs
+++ b/MediaBrowser.Providers/MediaInfo/SubtitleScheduledTask.cs
@@ -12,11 +12,10 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Providers;
-using MediaBrowser.Model.Serialization;
using MediaBrowser.Model.Tasks;
using Microsoft.Extensions.Logging;
-using MediaBrowser.Model.Globalization;
namespace MediaBrowser.Providers.MediaInfo
{
@@ -25,29 +24,37 @@ namespace MediaBrowser.Providers.MediaInfo
private readonly ILibraryManager _libraryManager;
private readonly IServerConfigurationManager _config;
private readonly ISubtitleManager _subtitleManager;
- private readonly IMediaSourceManager _mediaSourceManager;
private readonly ILogger<SubtitleScheduledTask> _logger;
- private readonly IJsonSerializer _json;
private readonly ILocalizationManager _localization;
public SubtitleScheduledTask(
ILibraryManager libraryManager,
- IJsonSerializer json,
IServerConfigurationManager config,
ISubtitleManager subtitleManager,
ILogger<SubtitleScheduledTask> logger,
- IMediaSourceManager mediaSourceManager,
ILocalizationManager localization)
{
_libraryManager = libraryManager;
_config = config;
_subtitleManager = subtitleManager;
_logger = logger;
- _mediaSourceManager = mediaSourceManager;
- _json = json;
_localization = localization;
}
+ public string Name => _localization.GetLocalizedString("TaskDownloadMissingSubtitles");
+
+ public string Description => _localization.GetLocalizedString("TaskDownloadMissingSubtitlesDescription");
+
+ public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
+
+ public string Key => "DownloadSubtitles";
+
+ public bool IsHidden => false;
+
+ public bool IsEnabled => true;
+
+ public bool IsLogged => true;
+
private SubtitleOptions GetOptions()
{
return _config.GetConfiguration<SubtitleOptions>("subtitles");
@@ -66,23 +73,23 @@ namespace MediaBrowser.Providers.MediaInfo
var libraryOptions = _libraryManager.GetLibraryOptions(library);
string[] subtitleDownloadLanguages;
- bool SkipIfEmbeddedSubtitlesPresent;
- bool SkipIfAudioTrackMatches;
- bool RequirePerfectMatch;
+ bool skipIfEmbeddedSubtitlesPresent;
+ bool skipIfAudioTrackMatches;
+ bool requirePerfectMatch;
if (libraryOptions.SubtitleDownloadLanguages == null)
{
subtitleDownloadLanguages = options.DownloadLanguages;
- SkipIfEmbeddedSubtitlesPresent = options.SkipIfEmbeddedSubtitlesPresent;
- SkipIfAudioTrackMatches = options.SkipIfAudioTrackMatches;
- RequirePerfectMatch = options.RequirePerfectMatch;
+ skipIfEmbeddedSubtitlesPresent = options.SkipIfEmbeddedSubtitlesPresent;
+ skipIfAudioTrackMatches = options.SkipIfAudioTrackMatches;
+ requirePerfectMatch = options.RequirePerfectMatch;
}
else
{
subtitleDownloadLanguages = libraryOptions.SubtitleDownloadLanguages;
- SkipIfEmbeddedSubtitlesPresent = libraryOptions.SkipSubtitlesIfEmbeddedSubtitlesPresent;
- SkipIfAudioTrackMatches = libraryOptions.SkipSubtitlesIfAudioTrackMatches;
- RequirePerfectMatch = libraryOptions.RequirePerfectSubtitleMatch;
+ skipIfEmbeddedSubtitlesPresent = libraryOptions.SkipSubtitlesIfEmbeddedSubtitlesPresent;
+ skipIfAudioTrackMatches = libraryOptions.SkipSubtitlesIfAudioTrackMatches;
+ requirePerfectMatch = libraryOptions.RequirePerfectSubtitleMatch;
}
foreach (var lang in subtitleDownloadLanguages)
@@ -98,12 +105,12 @@ namespace MediaBrowser.Providers.MediaInfo
Recursive = true
};
- if (SkipIfAudioTrackMatches)
+ if (skipIfAudioTrackMatches)
{
query.HasNoAudioTrackWithLanguage = lang;
}
- if (SkipIfEmbeddedSubtitlesPresent)
+ if (skipIfEmbeddedSubtitlesPresent)
{
// Exclude if it already has any subtitles of the same language
query.HasNoSubtitleTrackWithLanguage = lang;
@@ -160,36 +167,37 @@ namespace MediaBrowser.Providers.MediaInfo
var libraryOptions = _libraryManager.GetLibraryOptions(video);
string[] subtitleDownloadLanguages;
- bool SkipIfEmbeddedSubtitlesPresent;
- bool SkipIfAudioTrackMatches;
- bool RequirePerfectMatch;
+ bool skipIfEmbeddedSubtitlesPresent;
+ bool skipIfAudioTrackMatches;
+ bool requirePerfectMatch;
if (libraryOptions.SubtitleDownloadLanguages == null)
{
subtitleDownloadLanguages = options.DownloadLanguages;
- SkipIfEmbeddedSubtitlesPresent = options.SkipIfEmbeddedSubtitlesPresent;
- SkipIfAudioTrackMatches = options.SkipIfAudioTrackMatches;
- RequirePerfectMatch = options.RequirePerfectMatch;
+ skipIfEmbeddedSubtitlesPresent = options.SkipIfEmbeddedSubtitlesPresent;
+ skipIfAudioTrackMatches = options.SkipIfAudioTrackMatches;
+ requirePerfectMatch = options.RequirePerfectMatch;
}
else
{
subtitleDownloadLanguages = libraryOptions.SubtitleDownloadLanguages;
- SkipIfEmbeddedSubtitlesPresent = libraryOptions.SkipSubtitlesIfEmbeddedSubtitlesPresent;
- SkipIfAudioTrackMatches = libraryOptions.SkipSubtitlesIfAudioTrackMatches;
- RequirePerfectMatch = libraryOptions.RequirePerfectSubtitleMatch;
+ skipIfEmbeddedSubtitlesPresent = libraryOptions.SkipSubtitlesIfEmbeddedSubtitlesPresent;
+ skipIfAudioTrackMatches = libraryOptions.SkipSubtitlesIfAudioTrackMatches;
+ requirePerfectMatch = libraryOptions.RequirePerfectSubtitleMatch;
}
- var downloadedLanguages = await new SubtitleDownloader(_logger,
- _subtitleManager)
- .DownloadSubtitles(video,
- mediaStreams,
- SkipIfEmbeddedSubtitlesPresent,
- SkipIfAudioTrackMatches,
- RequirePerfectMatch,
- subtitleDownloadLanguages,
- libraryOptions.DisabledSubtitleFetchers,
- libraryOptions.SubtitleFetcherOrder,
- cancellationToken).ConfigureAwait(false);
+ var downloadedLanguages = await new SubtitleDownloader(
+ _logger,
+ _subtitleManager).DownloadSubtitles(
+ video,
+ mediaStreams,
+ skipIfEmbeddedSubtitlesPresent,
+ skipIfAudioTrackMatches,
+ requirePerfectMatch,
+ subtitleDownloadLanguages,
+ libraryOptions.DisabledSubtitleFetchers,
+ libraryOptions.SubtitleFetcherOrder,
+ cancellationToken).ConfigureAwait(false);
// Rescan
if (downloadedLanguages.Count > 0)
@@ -203,25 +211,11 @@ namespace MediaBrowser.Providers.MediaInfo
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
{
- return new[] {
-
+ return new[]
+ {
// Every so often
new TaskTriggerInfo { Type = TaskTriggerInfo.TriggerInterval, IntervalTicks = TimeSpan.FromHours(24).Ticks}
};
}
-
- public string Name => _localization.GetLocalizedString("TaskDownloadMissingSubtitles");
-
- public string Description => _localization.GetLocalizedString("TaskDownloadMissingSubtitlesDescription");
-
- public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
-
- public string Key => "DownloadSubtitles";
-
- public bool IsHidden => false;
-
- public bool IsEnabled => true;
-
- public bool IsLogged => true;
}
}
diff --git a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
index e23854d90..fc38d3832 100644
--- a/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
+++ b/MediaBrowser.Providers/MediaInfo/VideoImageProvider.cs
@@ -29,6 +29,11 @@ namespace MediaBrowser.Providers.MediaInfo
_fileSystem = fileSystem;
}
+ public string Name => "Screen Grabber";
+
+ // Make sure this comes after internet image providers
+ public int Order => 100;
+
public IEnumerable<ImageType> GetSupportedImages(BaseItem item)
{
return new List<ImageType> { ImageType.Primary };
@@ -127,8 +132,6 @@ namespace MediaBrowser.Providers.MediaInfo
};
}
- public string Name => "Screen Grabber";
-
public bool Supports(BaseItem item)
{
if (item.IsShortcut)
@@ -150,7 +153,5 @@ namespace MediaBrowser.Providers.MediaInfo
return false;
}
- // Make sure this comes after internet image providers
- public int Order => 100;
}
}
diff --git a/MediaBrowser.Providers/Movies/MovieExternalIds.cs b/MediaBrowser.Providers/Movies/ImdbExternalId.cs
index 14080841c..a8d74aa0b 100644
--- a/MediaBrowser.Providers/Movies/MovieExternalIds.cs
+++ b/MediaBrowser.Providers/Movies/ImdbExternalId.cs
@@ -36,22 +36,4 @@ namespace MediaBrowser.Providers.Movies
return item is Movie || item is MusicVideo || item is Series || item is Episode || item is Trailer;
}
}
-
- public class ImdbPersonExternalId : IExternalId
- {
- /// <inheritdoc />
- public string ProviderName => "IMDb";
-
- /// <inheritdoc />
- public string Key => MetadataProvider.Imdb.ToString();
-
- /// <inheritdoc />
- public ExternalIdMediaType? Type => ExternalIdMediaType.Person;
-
- /// <inheritdoc />
- public string UrlFormatString => "https://www.imdb.com/name/{0}";
-
- /// <inheritdoc />
- public bool Supports(IHasProviderIds item) => item is Person;
- }
}
diff --git a/MediaBrowser.Providers/Movies/ImdbPersonExternalId.cs b/MediaBrowser.Providers/Movies/ImdbPersonExternalId.cs
new file mode 100644
index 000000000..8151ab471
--- /dev/null
+++ b/MediaBrowser.Providers/Movies/ImdbPersonExternalId.cs
@@ -0,0 +1,27 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+
+namespace MediaBrowser.Providers.Movies
+{
+ public class ImdbPersonExternalId : IExternalId
+ {
+ /// <inheritdoc />
+ public string ProviderName => "IMDb";
+
+ /// <inheritdoc />
+ public string Key => MetadataProvider.Imdb.ToString();
+
+ /// <inheritdoc />
+ public ExternalIdMediaType? Type => ExternalIdMediaType.Person;
+
+ /// <inheritdoc />
+ public string UrlFormatString => "https://www.imdb.com/name/{0}";
+
+ /// <inheritdoc />
+ public bool Supports(IHasProviderIds item) => item is Person;
+ }
+}
diff --git a/MediaBrowser.Providers/Music/Extensions.cs b/MediaBrowser.Providers/Music/AlbumInfoExtensions.cs
index dddfd02e4..dddfd02e4 100644
--- a/MediaBrowser.Providers/Music/Extensions.cs
+++ b/MediaBrowser.Providers/Music/AlbumInfoExtensions.cs
diff --git a/MediaBrowser.Providers/Music/MusicExternalIds.cs b/MediaBrowser.Providers/Music/ImvdbId.cs
index a1726b996..a1726b996 100644
--- a/MediaBrowser.Providers/Music/MusicExternalIds.cs
+++ b/MediaBrowser.Providers/Music/ImvdbId.cs
diff --git a/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs b/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs
index 5cc0a527e..067d585cb 100644
--- a/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs
+++ b/MediaBrowser.Providers/Playlists/PlaylistItemsProvider.cs
@@ -10,7 +10,6 @@ using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Playlists;
using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.IO;
using Microsoft.Extensions.Logging;
using PlaylistsNET.Content;
@@ -23,16 +22,17 @@ namespace MediaBrowser.Providers.Playlists
IHasItemChangeMonitor
{
private readonly ILogger<PlaylistItemsProvider> _logger;
- private IFileSystem _fileSystem;
- public PlaylistItemsProvider(IFileSystem fileSystem, ILogger<PlaylistItemsProvider> logger)
+ public PlaylistItemsProvider(ILogger<PlaylistItemsProvider> logger)
{
- _fileSystem = fileSystem;
_logger = logger;
}
public string Name => "Playlist Reader";
+ // Run last
+ public int Order => 100;
+
public Task<ItemUpdateType> FetchAsync(Playlist item, MetadataRefreshOptions options, CancellationToken cancellationToken)
{
var path = item.Path;
@@ -163,7 +163,5 @@ namespace MediaBrowser.Providers.Playlists
return false;
}
- // Run last
- public int Order => 100;
}
}
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs
index 670c0cd05..72dad8a25 100644
--- a/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs
+++ b/MediaBrowser.Providers/Plugins/AudioDb/ArtistProvider.cs
@@ -23,16 +23,14 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
{
public class AudioDbArtistProvider : IRemoteMetadataProvider<MusicArtist, ArtistInfo>, IHasOrder
{
+ private const string ApiKey = "195003";
+ public const string BaseUrl = "https://www.theaudiodb.com/api/v1/json/" + ApiKey;
+
private readonly IServerConfigurationManager _config;
private readonly IFileSystem _fileSystem;
private readonly IHttpClientFactory _httpClientFactory;
private readonly IJsonSerializer _json;
- public static AudioDbArtistProvider Current;
-
- private const string ApiKey = "195003";
- public const string BaseUrl = "https://www.theaudiodb.com/api/v1/json/" + ApiKey;
-
public AudioDbArtistProvider(IServerConfigurationManager config, IFileSystem fileSystem, IHttpClientFactory httpClientFactory, IJsonSerializer json)
{
_config = config;
@@ -42,6 +40,8 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
Current = this;
}
+ public static AudioDbArtistProvider Current { get; private set; }
+
/// <inheritdoc />
public string Name => "TheAudioDB";
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumExternalId.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumExternalId.cs
new file mode 100644
index 000000000..138cfef19
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbAlbumExternalId.cs
@@ -0,0 +1,27 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+
+namespace MediaBrowser.Providers.Plugins.AudioDb
+{
+ public class AudioDbAlbumExternalId : IExternalId
+ {
+ /// <inheritdoc />
+ public string ProviderName => "TheAudioDb";
+
+ /// <inheritdoc />
+ public string Key => MetadataProvider.AudioDbAlbum.ToString();
+
+ /// <inheritdoc />
+ public ExternalIdMediaType? Type => null;
+
+ /// <inheritdoc />
+ public string UrlFormatString => "https://www.theaudiodb.com/album/{0}";
+
+ /// <inheritdoc />
+ public bool Supports(IHasProviderIds item) => item is MusicAlbum;
+ }
+}
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistExternalId.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistExternalId.cs
new file mode 100644
index 000000000..8aceb48c0
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbArtistExternalId.cs
@@ -0,0 +1,27 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+
+namespace MediaBrowser.Providers.Plugins.AudioDb
+{
+ public class AudioDbArtistExternalId : IExternalId
+ {
+ /// <inheritdoc />
+ public string ProviderName => "TheAudioDb";
+
+ /// <inheritdoc />
+ public string Key => MetadataProvider.AudioDbArtist.ToString();
+
+ /// <inheritdoc />
+ public ExternalIdMediaType? Type => ExternalIdMediaType.Artist;
+
+ /// <inheritdoc />
+ public string UrlFormatString => "https://www.theaudiodb.com/artist/{0}";
+
+ /// <inheritdoc />
+ public bool Supports(IHasProviderIds item) => item is MusicArtist;
+ }
+}
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbOtherAlbumExternalId.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbOtherAlbumExternalId.cs
new file mode 100644
index 000000000..014481da2
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbOtherAlbumExternalId.cs
@@ -0,0 +1,27 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+
+namespace MediaBrowser.Providers.Plugins.AudioDb
+{
+ public class AudioDbOtherAlbumExternalId : IExternalId
+ {
+ /// <inheritdoc />
+ public string ProviderName => "TheAudioDb";
+
+ /// <inheritdoc />
+ public string Key => MetadataProvider.AudioDbAlbum.ToString();
+
+ /// <inheritdoc />
+ public ExternalIdMediaType? Type => ExternalIdMediaType.Album;
+
+ /// <inheritdoc />
+ public string UrlFormatString => "https://www.theaudiodb.com/album/{0}";
+
+ /// <inheritdoc />
+ public bool Supports(IHasProviderIds item) => item is Audio;
+ }
+}
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/AudioDbOtherArtistExternalId.cs b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbOtherArtistExternalId.cs
new file mode 100644
index 000000000..787539104
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/AudioDb/AudioDbOtherArtistExternalId.cs
@@ -0,0 +1,27 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Entities.Audio;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+
+namespace MediaBrowser.Providers.Plugins.AudioDb
+{
+ public class AudioDbOtherArtistExternalId : IExternalId
+ {
+ /// <inheritdoc />
+ public string ProviderName => "TheAudioDb";
+
+ /// <inheritdoc />
+ public string Key => MetadataProvider.AudioDbArtist.ToString();
+
+ /// <inheritdoc />
+ public ExternalIdMediaType? Type => ExternalIdMediaType.OtherArtist;
+
+ /// <inheritdoc />
+ public string UrlFormatString => "https://www.theaudiodb.com/artist/{0}";
+
+ /// <inheritdoc />
+ public bool Supports(IHasProviderIds item) => item is Audio || item is MusicAlbum;
+ }
+}
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/ExternalIds.cs b/MediaBrowser.Providers/Plugins/AudioDb/ExternalIds.cs
deleted file mode 100644
index 1cc1f0fa1..000000000
--- a/MediaBrowser.Providers/Plugins/AudioDb/ExternalIds.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
-
-namespace MediaBrowser.Providers.Plugins.AudioDb
-{
- public class AudioDbAlbumExternalId : IExternalId
- {
- /// <inheritdoc />
- public string ProviderName => "TheAudioDb";
-
- /// <inheritdoc />
- public string Key => MetadataProvider.AudioDbAlbum.ToString();
-
- /// <inheritdoc />
- public ExternalIdMediaType? Type => null;
-
- /// <inheritdoc />
- public string UrlFormatString => "https://www.theaudiodb.com/album/{0}";
-
- /// <inheritdoc />
- public bool Supports(IHasProviderIds item) => item is MusicAlbum;
- }
-
- public class AudioDbOtherAlbumExternalId : IExternalId
- {
- /// <inheritdoc />
- public string ProviderName => "TheAudioDb";
-
- /// <inheritdoc />
- public string Key => MetadataProvider.AudioDbAlbum.ToString();
-
- /// <inheritdoc />
- public ExternalIdMediaType? Type => ExternalIdMediaType.Album;
-
- /// <inheritdoc />
- public string UrlFormatString => "https://www.theaudiodb.com/album/{0}";
-
- /// <inheritdoc />
- public bool Supports(IHasProviderIds item) => item is Audio;
- }
-
- public class AudioDbArtistExternalId : IExternalId
- {
- /// <inheritdoc />
- public string ProviderName => "TheAudioDb";
-
- /// <inheritdoc />
- public string Key => MetadataProvider.AudioDbArtist.ToString();
-
- /// <inheritdoc />
- public ExternalIdMediaType? Type => ExternalIdMediaType.Artist;
-
- /// <inheritdoc />
- public string UrlFormatString => "https://www.theaudiodb.com/artist/{0}";
-
- /// <inheritdoc />
- public bool Supports(IHasProviderIds item) => item is MusicArtist;
- }
-
- public class AudioDbOtherArtistExternalId : IExternalId
- {
- /// <inheritdoc />
- public string ProviderName => "TheAudioDb";
-
- /// <inheritdoc />
- public string Key => MetadataProvider.AudioDbArtist.ToString();
-
- /// <inheritdoc />
- public ExternalIdMediaType? Type => ExternalIdMediaType.OtherArtist;
-
- /// <inheritdoc />
- public string UrlFormatString => "https://www.theaudiodb.com/artist/{0}";
-
- /// <inheritdoc />
- public bool Supports(IHasProviderIds item) => item is Audio || item is MusicAlbum;
- }
-}
diff --git a/MediaBrowser.Providers/Plugins/AudioDb/Plugin.cs b/MediaBrowser.Providers/Plugins/AudioDb/Plugin.cs
index 54054d015..b5bd72ff0 100644
--- a/MediaBrowser.Providers/Plugins/AudioDb/Plugin.cs
+++ b/MediaBrowser.Providers/Plugins/AudioDb/Plugin.cs
@@ -11,6 +11,12 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
{
public class Plugin : BasePlugin<PluginConfiguration>, IHasWebPages
{
+ public Plugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer)
+ : base(applicationPaths, xmlSerializer)
+ {
+ Instance = this;
+ }
+
public static Plugin Instance { get; private set; }
public override Guid Id => new Guid("a629c0da-fac5-4c7e-931a-7174223f14c8");
@@ -22,12 +28,6 @@ namespace MediaBrowser.Providers.Plugins.AudioDb
// TODO remove when plugin removed from server.
public override string ConfigurationFileName => "Jellyfin.Plugin.AudioDb.xml";
- public Plugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer)
- : base(applicationPaths, xmlSerializer)
- {
- Instance = this;
- }
-
public IEnumerable<PluginPageInfo> GetPages()
{
yield return new PluginPageInfo
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs
index 781b71640..f27da7ce6 100644
--- a/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/ArtistProvider.cs
@@ -198,6 +198,7 @@ namespace MediaBrowser.Providers.Music
result.Name = reader.ReadElementContentAsString();
break;
}
+
case "annotation":
{
result.Overview = reader.ReadElementContentAsString();
diff --git a/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs
index 8414c9328..abfa1c6e7 100644
--- a/MediaBrowser.Providers/Plugins/MusicBrainz/AlbumProvider.cs
+++ b/MediaBrowser.Providers/Plugins/MusicBrainz/MusicBrainzAlbumProvider.cs
@@ -8,7 +8,6 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
-using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -27,21 +26,19 @@ namespace MediaBrowser.Providers.Music
public class MusicBrainzAlbumProvider : IRemoteMetadataProvider<MusicAlbum, AlbumInfo>, IHasOrder
{
/// <summary>
- /// The Jellyfin user-agent is unrestricted but source IP must not exceed
- /// one request per second, therefore we rate limit to avoid throttling.
- /// Be prudent, use a value slightly above the minimun required.
- /// https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting
- /// </summary>
- private readonly long _musicBrainzQueryIntervalMs;
-
- /// <summary>
/// For each single MB lookup/search, this is the maximum number of
/// attempts that shall be made whilst receiving a 503 Server
/// Unavailable (indicating throttled) response.
/// </summary>
private const uint MusicBrainzQueryAttempts = 5u;
- internal static MusicBrainzAlbumProvider Current;
+ /// <summary>
+ /// The Jellyfin user-agent is unrestricted but source IP must not exceed
+ /// one request per second, therefore we rate limit to avoid throttling.
+ /// Be prudent, use a value slightly above the minimun required.
+ /// https://musicbrainz.org/doc/XML_Web_Service/Rate_Limiting
+ /// </summary>
+ private readonly long _musicBrainzQueryIntervalMs;
private readonly IHttpClientFactory _httpClientFactory;
private readonly IApplicationHost _appHost;
@@ -69,6 +66,8 @@ namespace MediaBrowser.Providers.Music
Current = this;
}
+ internal static MusicBrainzAlbumProvider Current { get; private set; }
+
/// <inheritdoc />
public string Name => "MusicBrainz";
@@ -112,7 +111,7 @@ namespace MediaBrowser.Providers.Music
else
{
// I'm sure there is a better way but for now it resolves search for 12" Mixes
- var queryName = searchInfo.Name.Replace("\"", string.Empty);
+ var queryName = searchInfo.Name.Replace("\"", string.Empty, StringComparison.Ordinal);
url = string.Format(
CultureInfo.InvariantCulture,
@@ -277,7 +276,9 @@ namespace MediaBrowser.Providers.Music
private async Task<ReleaseResult> GetReleaseResult(string albumName, string artistId, CancellationToken cancellationToken)
{
- var url = string.Format(CultureInfo.InvariantCulture, "/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);
@@ -443,6 +444,7 @@ namespace MediaBrowser.Providers.Music
result.Title = reader.ReadElementContentAsString();
break;
}
+
case "date":
{
var val = reader.ReadElementContentAsString();
@@ -453,17 +455,20 @@ namespace MediaBrowser.Providers.Music
break;
}
+
case "annotation":
{
result.Overview = reader.ReadElementContentAsString();
break;
}
+
case "release-group":
{
result.ReleaseGroupId = reader.GetAttribute("id");
reader.Skip();
break;
}
+
case "artist-credit":
{
using (var subReader = reader.ReadSubtree())
@@ -496,7 +501,7 @@ namespace MediaBrowser.Providers.Music
}
}
- private static ValueTuple<string, string> ParseArtistCredit(XmlReader reader)
+ private static (string, string) ParseArtistCredit(XmlReader reader)
{
reader.MoveToContent();
reader.Read();
@@ -531,7 +536,7 @@ namespace MediaBrowser.Providers.Music
}
}
- return new ValueTuple<string, string>();
+ return default;
}
private static (string, string) ParseArtistNameCredit(XmlReader reader)
diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs
index 8b8fea09e..8f4240dc1 100644
--- a/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbImageProvider.cs
@@ -36,6 +36,12 @@ namespace MediaBrowser.Providers.Plugins.Omdb
_appHost = appHost;
}
+ public string Name => "The Open Movie Database";
+
+ // After other internet providers, because they're better
+ // But before fallback providers like screengrab
+ public int Order => 90;
+
public IEnumerable<ImageType> GetSupportedImages(BaseItem item)
{
return new List<ImageType>
@@ -86,15 +92,9 @@ namespace MediaBrowser.Providers.Plugins.Omdb
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
}
- public string Name => "The Open Movie Database";
-
public bool Supports(BaseItem item)
{
return item is Movie || item is Trailer || item is Episode;
}
-
- // After other internet providers, because they're better
- // But before fallback providers like screengrab
- public int Order => 90;
}
}
diff --git a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs
index d53eba7e9..705359d2c 100644
--- a/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Omdb/OmdbItemProvider.cs
@@ -49,6 +49,8 @@ namespace MediaBrowser.Providers.Plugins.Omdb
_appHost = appHost;
}
+ public string Name => "The Open Movie Database";
+
// After primary option
public int Order => 2;
@@ -199,8 +201,6 @@ namespace MediaBrowser.Providers.Plugins.Omdb
return GetSearchResults(searchInfo, "movie", cancellationToken);
}
- public string Name => "The Open Movie Database";
-
public async Task<MetadataResult<Series>> GetMetadata(SeriesInfo info, CancellationToken cancellationToken)
{
var result = new MetadataResult<Series>
@@ -263,14 +263,14 @@ namespace MediaBrowser.Providers.Plugins.Omdb
{
var results = await GetSearchResultsInternal(info, "movie", false, cancellationToken).ConfigureAwait(false);
var first = results.FirstOrDefault();
- return first == null ? null : first.GetProviderId(MetadataProvider.Imdb);
+ return first?.GetProviderId(MetadataProvider.Imdb);
}
private async Task<string> GetSeriesImdbId(SeriesInfo info, CancellationToken cancellationToken)
{
var results = await GetSearchResultsInternal(info, "series", false, cancellationToken).ConfigureAwait(false);
var first = results.FirstOrDefault();
- return first == null ? null : first.GetProviderId(MetadataProvider.Imdb);
+ return first?.GetProviderId(MetadataProvider.Imdb);
}
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
@@ -278,7 +278,7 @@ namespace MediaBrowser.Providers.Plugins.Omdb
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
}
- class SearchResult
+ private class SearchResult
{
public string Title { get; set; }
diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs
index de2f6875f..50a876d6c 100644
--- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs
+++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeImageProvider.cs
@@ -57,21 +57,28 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
// Process images
try
{
- var episodeInfo = new EpisodeInfo
+ string episodeTvdbId = null;
+
+ if (episode.IndexNumber.HasValue && episode.ParentIndexNumber.HasValue)
{
- IndexNumber = episode.IndexNumber.Value,
- ParentIndexNumber = episode.ParentIndexNumber.Value,
- SeriesProviderIds = series.ProviderIds,
- SeriesDisplayOrder = series.DisplayOrder
- };
- string episodeTvdbId = await _tvdbClientManager
- .GetEpisodeTvdbId(episodeInfo, language, cancellationToken).ConfigureAwait(false);
+ var episodeInfo = new EpisodeInfo
+ {
+ IndexNumber = episode.IndexNumber.Value,
+ ParentIndexNumber = episode.ParentIndexNumber.Value,
+ SeriesProviderIds = series.ProviderIds,
+ SeriesDisplayOrder = series.DisplayOrder
+ };
+
+ episodeTvdbId = await _tvdbClientManager
+ .GetEpisodeTvdbId(episodeInfo, language, cancellationToken).ConfigureAwait(false);
+ }
+
if (string.IsNullOrEmpty(episodeTvdbId))
{
_logger.LogError(
"Episode {SeasonNumber}x{EpisodeNumber} not found for series {SeriesTvdbId}",
- episodeInfo.ParentIndexNumber,
- episodeInfo.IndexNumber,
+ episode.ParentIndexNumber,
+ episode.IndexNumber,
series.GetProviderId(MetadataProvider.Tvdb));
return imageResult;
}
diff --git a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs
index c088d8cec..5fa8a3e1c 100644
--- a/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs
+++ b/MediaBrowser.Providers/Plugins/TheTvdb/TvdbEpisodeProvider.cs
@@ -141,6 +141,7 @@ namespace MediaBrowser.Providers.Plugins.TheTvdb
Name = episode.EpisodeName,
Overview = episode.Overview,
CommunityRating = (float?)episode.SiteRating,
+ OfficialRating = episode.ContentRating,
}
};
result.ResetPeople();
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs
index e627550f1..e7328b553 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/BoxSets/TmdbBoxSetProvider.cs
@@ -37,7 +37,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets
private readonly IJsonSerializer _json;
private readonly IServerConfigurationManager _config;
private readonly IFileSystem _fileSystem;
- private readonly ILocalizationManager _localization;
private readonly IHttpClientFactory _httpClientFactory;
private readonly ILibraryManager _libraryManager;
@@ -46,7 +45,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets
IJsonSerializer json,
IServerConfigurationManager config,
IFileSystem fileSystem,
- ILocalizationManager localization,
IHttpClientFactory httpClientFactory,
ILibraryManager libraryManager)
{
@@ -54,7 +52,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets
_json = json;
_config = config;
_fileSystem = fileSystem;
- _localization = localization;
_httpClientFactory = httpClientFactory;
_libraryManager = libraryManager;
Current = this;
@@ -177,7 +174,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets
private async Task<CollectionResult> FetchMainResult(string id, string language, CancellationToken cancellationToken)
{
- var url = string.Format(GetCollectionInfo3, id, TmdbUtils.ApiKey);
+ var url = string.Format(CultureInfo.InvariantCulture, GetCollectionInfo3, id, TmdbUtils.ApiKey);
if (!string.IsNullOrEmpty(language))
{
@@ -195,7 +192,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(header));
}
- using var mainResponse = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage);
+ using var mainResponse = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage, cancellationToken).ConfigureAwait(false);
await using var stream = await mainResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
var mainResult = await _json.DeserializeFromStreamAsync<CollectionResult>(stream).ConfigureAwait(false);
@@ -205,7 +202,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.BoxSets
{
if (!string.IsNullOrEmpty(language) && !string.Equals(language, "en", StringComparison.OrdinalIgnoreCase))
{
- url = string.Format(GetCollectionInfo3, id, TmdbUtils.ApiKey) + "&language=en";
+ url = string.Format(CultureInfo.InvariantCulture, GetCollectionInfo3, id, TmdbUtils.ApiKey) + "&language=en";
if (!string.IsNullOrEmpty(language))
{
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Videos.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Videos.cs
index 241dcab4d..1c673fdbd 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Videos.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/General/Videos.cs
@@ -6,6 +6,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.General
{
public class Videos
{
- public List<Video> Results { get; set; }
+ public IReadOnlyList<Video> Results { get; set; }
}
}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/Trailers.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/Trailers.cs
index 166860f51..057177294 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/Trailers.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/Movies/Trailers.cs
@@ -6,6 +6,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.Movies
{
public class Trailers
{
- public List<Youtube> Youtube { get; set; }
+ public IReadOnlyList<Youtube> Youtube { get; set; }
}
}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Models/People/PersonImages.cs b/MediaBrowser.Providers/Plugins/Tmdb/Models/People/PersonImages.cs
index 3ea12334e..d82e0fc6d 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/Models/People/PersonImages.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/Models/People/PersonImages.cs
@@ -7,6 +7,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Models.People
{
public class PersonImages
{
- public List<Profile> Profiles { get; set; }
+ public IReadOnlyList<Profile> Profiles { get; set; }
}
}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs
index 01a887eed..3c626f9eb 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/GenericTmdbMovieInfo.cs
@@ -302,7 +302,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
{
Url = string.Format(CultureInfo.InvariantCulture, "https://www.youtube.com/watch?v={0}", i.Source),
Name = i.Name
-
}).ToArray();
}
}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbImageProvider.cs
index a975fb8f6..9db7e0997 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbImageProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbImageProvider.cs
@@ -38,6 +38,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
public static string ProviderName => TmdbUtils.ProviderName;
+ /// <inheritdoc />
+ public int Order => 0;
+
public bool Supports(BaseItem item)
{
return item is Movie || item is MusicVideo || item is Trailer;
@@ -201,8 +204,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
return null;
}
- public int Order => 0;
-
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
{
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSettings.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbImageSettings.cs
index 128258ab3..1ba8f9072 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSettings.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbImageSettings.cs
@@ -6,22 +6,17 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
{
internal class TmdbImageSettings
{
- public List<string> backdrop_sizes { get; set; }
+ public IReadOnlyList<string> backdrop_sizes { get; set; }
public string secure_base_url { get; set; }
- public List<string> poster_sizes { get; set; }
+ public IReadOnlyList<string> poster_sizes { get; set; }
- public List<string> profile_sizes { get; set; }
+ public IReadOnlyList<string> profile_sizes { get; set; }
public string GetImageUrl(string image)
{
return secure_base_url + image;
}
}
-
- internal class TmdbSettingsResult
- {
- public TmdbImageSettings images { get; set; }
- }
}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs
index f8bc19395..31cfd8649 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbMovieProvider.cs
@@ -34,7 +34,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
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 CultureInfo _usCulture = new CultureInfo("en-US");
private readonly IJsonSerializer _jsonSerializer;
private readonly IHttpClientFactory _httpClientFactory;
@@ -44,7 +44,10 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
private readonly ILibraryManager _libraryManager;
private readonly IApplicationHost _appHost;
- private readonly CultureInfo _usCulture = new CultureInfo("en-US");
+ /// <summary>
+ /// The _TMDB settings task.
+ /// </summary>
+ private TmdbSettingsResult _tmdbSettings;
public TmdbMovieProvider(
IJsonSerializer jsonSerializer,
@@ -65,6 +68,14 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
Current = this;
}
+ internal static TmdbMovieProvider Current { get; private set; }
+
+ /// <inheritdoc />
+ public string Name => TmdbUtils.ProviderName;
+
+ /// <inheritdoc />
+ public int Order => 1;
+
public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(MovieInfo searchInfo, CancellationToken cancellationToken)
{
return GetMovieSearchResults(searchInfo, cancellationToken);
@@ -131,13 +142,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
return movieDb.GetMetadata(id, cancellationToken);
}
- public string Name => TmdbUtils.ProviderName;
-
- /// <summary>
- /// The _TMDB settings task.
- /// </summary>
- private TmdbSettingsResult _tmdbSettings;
-
/// <summary>
/// Gets the TMDB settings.
/// </summary>
@@ -155,7 +159,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(header));
}
- using var response = await GetMovieDbResponse(requestMessage).ConfigureAwait(false);
+ using var response = await GetMovieDbResponse(requestMessage, cancellationToken).ConfigureAwait(false);
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
_tmdbSettings = await _jsonSerializer.DeserializeFromStreamAsync<TmdbSettingsResult>(stream).ConfigureAwait(false);
return _tmdbSettings;
@@ -272,7 +276,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
languages.Add("en");
}
- return string.Join(",", languages);
+ return string.Join(',', languages);
}
public static string NormalizeLanguage(string language)
@@ -335,7 +339,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(header));
}
- using var mainResponse = await GetMovieDbResponse(requestMessage).ConfigureAwait(false);
+ using var mainResponse = await GetMovieDbResponse(requestMessage, cancellationToken).ConfigureAwait(false);
if (mainResponse.StatusCode == HttpStatusCode.NotFound)
{
return null;
@@ -368,7 +372,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
langRequestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(header));
}
- using var langResponse = await GetMovieDbResponse(langRequestMessage).ConfigureAwait(false);
+ using var langResponse = await GetMovieDbResponse(langRequestMessage, cancellationToken).ConfigureAwait(false);
await using var langStream = await langResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
var langResult = await _jsonSerializer.DeserializeFromStreamAsync<MovieResult>(stream).ConfigureAwait(false);
@@ -381,16 +385,14 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
/// <summary>
/// Gets the movie db response.
/// </summary>
- internal Task<HttpResponseMessage> GetMovieDbResponse(HttpRequestMessage message)
+ /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
+ internal Task<HttpResponseMessage> GetMovieDbResponse(HttpRequestMessage message, CancellationToken cancellationToken = default)
{
message.Headers.UserAgent.ParseAdd(_appHost.ApplicationUserAgent);
- return _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(message);
+ return _httpClientFactory.CreateClient(NamedClient.Default).SendAsync(message, cancellationToken);
}
/// <inheritdoc />
- public int Order => 1;
-
- /// <inheritdoc />
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
{
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs
index 2a6c6d035..36a4eef8a 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSearch.cs
@@ -198,7 +198,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(header));
}
- using var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage).ConfigureAwait(false);
+ using var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage, cancellationToken).ConfigureAwait(false);
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
var searchResults = await _json.DeserializeFromStreamAsync<TmdbSearchResult<MovieResult>>(stream).ConfigureAwait(false);
@@ -207,7 +207,12 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
return results
.Select(i =>
{
- var remoteResult = new RemoteSearchResult {SearchProviderName = TmdbMovieProvider.Current.Name, Name = i.Title ?? i.Name ?? i.Original_Title, ImageUrl = string.IsNullOrWhiteSpace(i.Poster_Path) ? null : baseImageUrl + i.Poster_Path};
+ var remoteResult = new RemoteSearchResult
+ {
+ SearchProviderName = TmdbMovieProvider.Current.Name,
+ Name = i.Title ?? i.Name ?? i.Original_Title,
+ ImageUrl = string.IsNullOrWhiteSpace(i.Poster_Path) ? null : baseImageUrl + i.Poster_Path
+ };
if (!string.IsNullOrWhiteSpace(i.Release_Date))
{
@@ -261,7 +266,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(header));
}
- using var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage).ConfigureAwait(false);
+ using var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage, cancellationToken).ConfigureAwait(false);
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
var searchResults = await _json.DeserializeFromStreamAsync<TmdbSearchResult<TvResult>>(stream).ConfigureAwait(false);
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSettingsResult.cs b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSettingsResult.cs
new file mode 100644
index 000000000..c7ba97438
--- /dev/null
+++ b/MediaBrowser.Providers/Plugins/Tmdb/Movies/TmdbSettingsResult.cs
@@ -0,0 +1,9 @@
+#pragma warning disable CS1591
+
+namespace MediaBrowser.Providers.Plugins.Tmdb.Movies
+{
+ internal class TmdbSettingsResult
+ {
+ public TmdbImageSettings images { get; set; }
+ }
+}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Music/TmdbMusicVideoProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Music/TmdbMusicVideoProvider.cs
index 73e49ba5b..b88ecce87 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/Music/TmdbMusicVideoProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/Music/TmdbMusicVideoProvider.cs
@@ -14,6 +14,8 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Music
{
public class TmdbMusicVideoProvider : IRemoteMetadataProvider<MusicVideo, MusicVideoInfo>
{
+ public string Name => TmdbMovieProvider.Current.Name;
+
public Task<MetadataResult<MusicVideo>> GetMetadata(MusicVideoInfo info, CancellationToken cancellationToken)
{
return TmdbMovieProvider.Current.GetItemMetadata<MusicVideo>(info, cancellationToken);
@@ -24,8 +26,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Music
return Task.FromResult((IEnumerable<RemoteSearchResult>)new List<RemoteSearchResult>());
}
- public string Name => TmdbMovieProvider.Current.Name;
-
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
{
throw new NotImplementedException();
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs
index 6bf04b81a..777ebce49 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/People/TmdbPersonProvider.cs
@@ -31,7 +31,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
{
public class TmdbPersonProvider : IRemoteMetadataProvider<Person, PersonLookupInfo>
{
- const string DataFileName = "info.json";
+ private const string DataFileName = "info.json";
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
@@ -39,20 +39,17 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
private readonly IFileSystem _fileSystem;
private readonly IServerConfigurationManager _configurationManager;
private readonly IHttpClientFactory _httpClientFactory;
- private readonly ILogger<TmdbPersonProvider> _logger;
public TmdbPersonProvider(
IFileSystem fileSystem,
IServerConfigurationManager configurationManager,
IJsonSerializer jsonSerializer,
- IHttpClientFactory httpClientFactory,
- ILogger<TmdbPersonProvider> logger)
+ IHttpClientFactory httpClientFactory)
{
_fileSystem = fileSystem;
_configurationManager = configurationManager;
_jsonSerializer = jsonSerializer;
_httpClientFactory = httpClientFactory;
- _logger = logger;
Current = this;
}
@@ -75,7 +72,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
var dataFilePath = GetPersonDataFilePath(_configurationManager.ApplicationPaths, tmdbId);
var info = _jsonSerializer.DeserializeFromFile<PersonResult>(dataFilePath);
- var images = (info.Images ?? new PersonImages()).Profiles ?? new List<Profile>();
+ IReadOnlyList<Profile> images = info.Images?.Profiles ?? Array.Empty<Profile>();
var result = new RemoteSearchResult
{
@@ -95,7 +92,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
if (searchInfo.IsAutomated)
{
// Don't hammer moviedb searching by name
- return new List<RemoteSearchResult>();
+ return Array.Empty<RemoteSearchResult>();
}
var url = string.Format(
@@ -110,7 +107,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(header));
}
- var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage).ConfigureAwait(false);
+ var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage, cancellationToken).ConfigureAwait(false);
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
var result2 = await _jsonSerializer.DeserializeFromStreamAsync<TmdbSearchResult<PersonSearchResult>>(stream).ConfigureAwait(false)
@@ -243,7 +240,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.People
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(header));
}
- using var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage).ConfigureAwait(false);
+ using var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage, cancellationToken).ConfigureAwait(false);
Directory.CreateDirectory(Path.GetDirectoryName(dataFilePath));
await using var fs = new FileStream(dataFilePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true);
await response.Content.CopyToAsync(fs).ConfigureAwait(false);
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeImageProvider.cs
index eebecdac6..c56774f8e 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeImageProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeImageProvider.cs
@@ -28,7 +28,13 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
{
public TmdbEpisodeImageProvider(IHttpClientFactory httpClientFactory, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILoggerFactory loggerFactory)
: base(httpClientFactory, configurationManager, jsonSerializer, fileSystem, localization, loggerFactory)
- { }
+ {
+ }
+
+ public string Name => TmdbUtils.ProviderName;
+
+ // After TheTvDb
+ public int Order => 1;
public IEnumerable<ImageType> GetSupportedImages(BaseItem item)
{
@@ -43,7 +49,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
var episode = (Controller.Entities.TV.Episode)item;
var series = episode.Series;
- var seriesId = series != null ? series.GetProviderId(MetadataProvider.Tmdb) : null;
+ var seriesId = series?.GetProviderId(MetadataProvider.Tmdb);
var list = new List<RemoteImageInfo>();
@@ -62,8 +68,12 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
var language = item.GetPreferredMetadataLanguage();
- var response = await GetEpisodeInfo(seriesId, seasonNumber.Value, episodeNumber.Value,
- language, cancellationToken).ConfigureAwait(false);
+ var response = await GetEpisodeInfo(
+ seriesId,
+ seasonNumber.Value,
+ episodeNumber.Value,
+ language,
+ cancellationToken).ConfigureAwait(false);
var tmdbSettings = await TmdbMovieProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
@@ -120,14 +130,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
return GetResponse(url, cancellationToken);
}
- public string Name => TmdbUtils.ProviderName;
-
public bool Supports(BaseItem item)
{
return item is Controller.Entities.TV.Episode;
}
-
- // After TheTvDb
- public int Order => 1;
}
}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs
index 90e3cea93..a7e3a03fe 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProvider.cs
@@ -29,7 +29,13 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
{
public TmdbEpisodeProvider(IHttpClientFactory httpClientFactory, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILoggerFactory loggerFactory)
: base(httpClientFactory, configurationManager, jsonSerializer, fileSystem, localization, loggerFactory)
- { }
+ {
+ }
+
+ // After TheTvDb
+ public int Order => 1;
+
+ public string Name => TmdbUtils.ProviderName;
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(EpisodeInfo searchInfo, CancellationToken cancellationToken)
{
@@ -41,7 +47,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
return list;
}
- var metadataResult = await GetMetadata(searchInfo, cancellationToken);
+ var metadataResult = await GetMetadata(searchInfo, cancellationToken).ConfigureAwait(false);
if (metadataResult.HasMetadata)
{
@@ -109,7 +115,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
item.ParentIndexNumber = info.ParentIndexNumber;
item.IndexNumberEnd = info.IndexNumberEnd;
- if (response.External_Ids.Tvdb_Id > 0)
+ if (response.External_Ids != null && response.External_Ids.Tvdb_Id > 0)
{
item.SetProviderId(MetadataProvider.Tvdb, response.External_Ids.Tvdb_Id.Value.ToString(CultureInfo.InvariantCulture));
}
@@ -205,10 +211,5 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
{
return GetResponse(url, cancellationToken);
}
-
- // After TheTvDb
- public int Order => 1;
-
- public string Name => TmdbUtils.ProviderName;
}
}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs
index 30b7674e3..34d2424a3 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbEpisodeProviderBase.cs
@@ -21,11 +21,11 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
public abstract class TmdbEpisodeProviderBase
{
private const string EpisodeUrlPattern = TmdbUtils.BaseTmdbApiUrl + @"3/tv/{0}/season/{1}/episode/{2}?api_key={3}&append_to_response=images,external_ids,credits,videos";
+
private readonly IHttpClientFactory _httpClientFactory;
private readonly IServerConfigurationManager _configurationManager;
private readonly IJsonSerializer _jsonSerializer;
private readonly IFileSystem _fileSystem;
- private readonly ILocalizationManager _localization;
private readonly ILogger<TmdbEpisodeProviderBase> _logger;
protected TmdbEpisodeProviderBase(IHttpClientFactory httpClientFactory, IServerConfigurationManager configurationManager, IJsonSerializer jsonSerializer, IFileSystem fileSystem, ILocalizationManager localization, ILoggerFactory loggerFactory)
@@ -34,13 +34,16 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
_configurationManager = configurationManager;
_jsonSerializer = jsonSerializer;
_fileSystem = fileSystem;
- _localization = localization;
_logger = loggerFactory.CreateLogger<TmdbEpisodeProviderBase>();
}
protected ILogger Logger => _logger;
- protected async Task<EpisodeResult> GetEpisodeInfo(string seriesTmdbId, int season, int episodeNumber, string preferredMetadataLanguage,
+ protected async Task<EpisodeResult> GetEpisodeInfo(
+ string seriesTmdbId,
+ int season,
+ int episodeNumber,
+ string preferredMetadataLanguage,
CancellationToken cancellationToken)
{
await EnsureEpisodeInfo(seriesTmdbId, season, episodeNumber, preferredMetadataLanguage, cancellationToken)
@@ -93,7 +96,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
var path = TmdbSeriesProvider.GetSeriesDataPath(_configurationManager.ApplicationPaths, tmdbId);
- var filename = string.Format(CultureInfo.InvariantCulture, "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);
@@ -113,7 +118,13 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
internal async Task<EpisodeResult> FetchMainResult(string urlPattern, string id, int seasonNumber, int episodeNumber, string language, CancellationToken cancellationToken)
{
- var url = string.Format(urlPattern, id, seasonNumber.ToString(CultureInfo.InvariantCulture), episodeNumber, TmdbUtils.ApiKey);
+ var url = string.Format(
+ CultureInfo.InvariantCulture,
+ urlPattern,
+ id,
+ seasonNumber.ToString(CultureInfo.InvariantCulture),
+ episodeNumber,
+ TmdbUtils.ApiKey);
if (!string.IsNullOrEmpty(language))
{
@@ -132,7 +143,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(header));
}
- using var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage);
+ using var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage, cancellationToken).ConfigureAwait(false);
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
return await _jsonSerializer.DeserializeFromStreamAsync<EpisodeResult>(stream).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonImageProvider.cs
index e7e2fd05b..dcc7f8700 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonImageProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonImageProvider.cs
@@ -112,9 +112,10 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
private async Task<List<Poster>> FetchImages(Season item, string tmdbId, string language, CancellationToken cancellationToken)
{
- await TmdbSeasonProvider.Current.EnsureSeasonInfo(tmdbId, item.IndexNumber.GetValueOrDefault(), language, cancellationToken).ConfigureAwait(false);
+ var seasonNumber = item.IndexNumber.GetValueOrDefault();
+ await TmdbSeasonProvider.Current.EnsureSeasonInfo(tmdbId, seasonNumber, language, cancellationToken).ConfigureAwait(false);
- var path = TmdbSeriesProvider.Current.GetDataFilePath(tmdbId, language);
+ var path = TmdbSeasonProvider.Current.GetDataFilePath(tmdbId, seasonNumber, language);
if (!string.IsNullOrEmpty(path))
{
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs
index 73ed13267..c9b257fcc 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeasonProvider.cs
@@ -28,26 +28,32 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
public class TmdbSeasonProvider : IRemoteMetadataProvider<Season, SeasonInfo>
{
private const string GetTvInfo3 = TmdbUtils.BaseTmdbApiUrl + @"3/tv/{0}/season/{1}?api_key={2}&append_to_response=images,keywords,external_ids,credits,videos";
+
private readonly IHttpClientFactory _httpClientFactory;
private readonly IServerConfigurationManager _configurationManager;
private readonly IJsonSerializer _jsonSerializer;
private readonly IFileSystem _fileSystem;
- private readonly ILocalizationManager _localization;
private readonly ILogger<TmdbSeasonProvider> _logger;
internal static TmdbSeasonProvider Current { get; private set; }
- public TmdbSeasonProvider(IHttpClientFactory httpClientFactory, IServerConfigurationManager configurationManager, IFileSystem fileSystem, ILocalizationManager localization, IJsonSerializer jsonSerializer, ILogger<TmdbSeasonProvider> logger)
+ public TmdbSeasonProvider(
+ IHttpClientFactory httpClientFactory,
+ IServerConfigurationManager configurationManager,
+ IFileSystem fileSystem,
+ IJsonSerializer jsonSerializer,
+ ILogger<TmdbSeasonProvider> logger)
{
_httpClientFactory = httpClientFactory;
_configurationManager = configurationManager;
_fileSystem = fileSystem;
- _localization = localization;
_jsonSerializer = jsonSerializer;
_logger = logger;
Current = this;
}
+ public string Name => TmdbUtils.ProviderName;
+
public async Task<MetadataResult<Season>> GetMetadata(SeasonInfo info, CancellationToken cancellationToken)
{
var result = new MetadataResult<Season>();
@@ -75,7 +81,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
result.Item.Overview = seasonInfo.Overview;
- if (seasonInfo.External_Ids.Tvdb_Id > 0)
+ if (seasonInfo.External_Ids != null && seasonInfo.External_Ids.Tvdb_Id > 0)
{
result.Item.SetProviderId(MetadataProvider.Tvdb, seasonInfo.External_Ids.Tvdb_Id.Value.ToString(CultureInfo.InvariantCulture));
}
@@ -116,8 +122,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
return result;
}
- public string Name => TmdbUtils.ProviderName;
-
public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeasonInfo searchInfo, CancellationToken cancellationToken)
{
return Task.FromResult<IEnumerable<RemoteSearchResult>>(new List<RemoteSearchResult>());
@@ -128,7 +132,10 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
}
- private async Task<SeasonResult> GetSeasonInfo(string seriesTmdbId, int season, string preferredMetadataLanguage,
+ private async Task<SeasonResult> GetSeasonInfo(
+ string seriesTmdbId,
+ int season,
+ string preferredMetadataLanguage,
CancellationToken cancellationToken)
{
await EnsureSeasonInfo(seriesTmdbId, season, preferredMetadataLanguage, cancellationToken)
@@ -181,7 +188,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
var path = TmdbSeriesProvider.GetSeriesDataPath(_configurationManager.ApplicationPaths, tmdbId);
- var filename = string.Format(CultureInfo.InvariantCulture, "season-{0}-{1}.json",
+ var filename = string.Format(
+ CultureInfo.InvariantCulture,
+ "season-{0}-{1}.json",
seasonNumber.ToString(CultureInfo.InvariantCulture),
preferredLanguage);
@@ -200,7 +209,12 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
internal async Task<SeasonResult> FetchMainResult(string id, int seasonNumber, string language, CancellationToken cancellationToken)
{
- var url = string.Format(GetTvInfo3, id, seasonNumber.ToString(CultureInfo.InvariantCulture), TmdbUtils.ApiKey);
+ var url = string.Format(
+ CultureInfo.InvariantCulture,
+ GetTvInfo3,
+ id,
+ seasonNumber.ToString(CultureInfo.InvariantCulture),
+ TmdbUtils.ApiKey);
if (!string.IsNullOrEmpty(language))
{
@@ -219,7 +233,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(header));
}
- using var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage).ConfigureAwait(false);
+ using var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage, cancellationToken).ConfigureAwait(false);
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
return await _jsonSerializer.DeserializeFromStreamAsync<SeasonResult>(stream).ConfigureAwait(false);
}
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs
index 125560175..179ceb825 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesImageProvider.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading;
@@ -12,7 +13,6 @@ using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.IO;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Providers.Plugins.Tmdb.Models.General;
@@ -25,19 +25,20 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
{
private readonly IJsonSerializer _jsonSerializer;
private readonly IHttpClientFactory _httpClientFactory;
- private readonly IFileSystem _fileSystem;
- public TmdbSeriesImageProvider(IJsonSerializer jsonSerializer, IHttpClientFactory httpClientFactory, IFileSystem fileSystem)
+ public TmdbSeriesImageProvider(IJsonSerializer jsonSerializer, IHttpClientFactory httpClientFactory)
{
_jsonSerializer = jsonSerializer;
_httpClientFactory = httpClientFactory;
- _fileSystem = fileSystem;
}
public string Name => ProviderName;
public static string ProviderName => TmdbUtils.ProviderName;
+ // After tvdb and fanart
+ public int Order => 2;
+
public bool Supports(BaseItem item)
{
return item is Series;
@@ -56,7 +57,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
{
var list = new List<RemoteImageInfo>();
- var results = await FetchImages(item, null, _jsonSerializer, cancellationToken).ConfigureAwait(false);
+ var results = await FetchImages(item, null, cancellationToken).ConfigureAwait(false);
if (results == null)
{
@@ -148,10 +149,11 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
/// </summary>
/// <param name="item">The item.</param>
/// <param name="language">The language.</param>
- /// <param name="jsonSerializer">The json serializer.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{MovieImages}.</returns>
- private async Task<Images> FetchImages(BaseItem item, string language, IJsonSerializer jsonSerializer,
+ private async Task<Images> FetchImages(
+ BaseItem item,
+ string language,
CancellationToken cancellationToken)
{
var tmdbId = item.GetProviderId(MetadataProvider.Tmdb);
@@ -165,22 +167,14 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
var path = TmdbSeriesProvider.Current.GetDataFilePath(tmdbId, language);
- if (!string.IsNullOrEmpty(path))
+ if (!string.IsNullOrEmpty(path) && File.Exists(path))
{
- var fileInfo = _fileSystem.GetFileInfo(path);
-
- if (fileInfo.Exists)
- {
- return jsonSerializer.DeserializeFromFile<SeriesResult>(path).Images;
- }
+ return _jsonSerializer.DeserializeFromFile<SeriesResult>(path).Images;
}
return null;
}
- // After tvdb and fanart
- public int Order => 2;
-
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
{
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs
index aaba6ffc0..287ebca8c 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/TV/TmdbSeriesProvider.cs
@@ -17,8 +17,6 @@ using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Globalization;
-using MediaBrowser.Model.IO;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Providers.Plugins.Tmdb.Models.Search;
@@ -33,38 +31,35 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
private const string GetTvInfo3 = TmdbUtils.BaseTmdbApiUrl + @"3/tv/{0}?api_key={1}&append_to_response=credits,images,keywords,external_ids,videos,content_ratings";
private readonly IJsonSerializer _jsonSerializer;
- private readonly IFileSystem _fileSystem;
private readonly IServerConfigurationManager _configurationManager;
private readonly ILogger<TmdbSeriesProvider> _logger;
- private readonly ILocalizationManager _localization;
private readonly IHttpClientFactory _httpClientFactory;
private readonly ILibraryManager _libraryManager;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
- internal static TmdbSeriesProvider Current { get; private set; }
-
public TmdbSeriesProvider(
IJsonSerializer jsonSerializer,
- IFileSystem fileSystem,
IServerConfigurationManager configurationManager,
ILogger<TmdbSeriesProvider> logger,
- ILocalizationManager localization,
IHttpClientFactory httpClientFactory,
ILibraryManager libraryManager)
{
_jsonSerializer = jsonSerializer;
- _fileSystem = fileSystem;
_configurationManager = configurationManager;
_logger = logger;
- _localization = localization;
_httpClientFactory = httpClientFactory;
_libraryManager = libraryManager;
Current = this;
}
+ internal static TmdbSeriesProvider Current { get; private set; }
+
public string Name => TmdbUtils.ProviderName;
+ // After TheTVDB
+ public int Order => 1;
+
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken)
{
var tmdbId = searchInfo.GetProviderId(MetadataProvider.Tmdb);
@@ -92,7 +87,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
remoteResult.SetProviderId(MetadataProvider.Tmdb, obj.Id.ToString(_usCulture));
remoteResult.SetProviderId(MetadataProvider.Imdb, obj.External_Ids.Imdb_Id);
- if (obj.External_Ids.Tvdb_Id > 0)
+ if (obj.External_Ids != null && obj.External_Ids.Tvdb_Id > 0)
{
remoteResult.SetProviderId(MetadataProvider.Tvdb, obj.External_Ids.Tvdb_Id.Value.ToString(_usCulture));
}
@@ -129,8 +124,10 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
public async Task<MetadataResult<Series>> GetMetadata(SeriesInfo info, CancellationToken cancellationToken)
{
- var result = new MetadataResult<Series>();
- result.QueriedById = true;
+ var result = new MetadataResult<Series>
+ {
+ QueriedById = true
+ };
var tmdbId = info.GetProviderId(MetadataProvider.Tmdb);
@@ -206,9 +203,11 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
await EnsureSeriesInfo(tmdbId, language, cancellationToken).ConfigureAwait(false);
- var result = new MetadataResult<Series>();
- result.Item = new Series();
- result.ResultLanguage = seriesInfo.ResultLanguage;
+ var result = new MetadataResult<Series>
+ {
+ Item = new Series(),
+ ResultLanguage = seriesInfo.ResultLanguage
+ };
var settings = await TmdbMovieProvider.Current.GetTmdbSettings(cancellationToken).ConfigureAwait(false);
@@ -405,7 +404,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
internal async Task<SeriesResult> FetchMainResult(string id, string language, CancellationToken cancellationToken)
{
- var url = string.Format(GetTvInfo3, id, TmdbUtils.ApiKey);
+ var url = string.Format(CultureInfo.InvariantCulture, GetTvInfo3, id, TmdbUtils.ApiKey);
if (!string.IsNullOrEmpty(language))
{
@@ -421,7 +420,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
mainRequestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(header));
}
- using var mainResponse = await TmdbMovieProvider.Current.GetMovieDbResponse(mainRequestMessage);
+ using var mainResponse = await TmdbMovieProvider.Current.GetMovieDbResponse(mainRequestMessage, cancellationToken).ConfigureAwait(false);
await using var mainStream = await mainResponse.Content.ReadAsStreamAsync().ConfigureAwait(false);
var mainResult = await _jsonSerializer.DeserializeFromStreamAsync<SeriesResult>(mainStream).ConfigureAwait(false);
@@ -440,7 +439,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
{
_logger.LogInformation("MovieDbSeriesProvider couldn't find meta for language {Language}. Trying English...", language);
- url = string.Format(GetTvInfo3, id, TmdbUtils.ApiKey) + "&language=en";
+ url = string.Format(CultureInfo.InvariantCulture, GetTvInfo3, id, TmdbUtils.ApiKey) + "&language=en";
if (!string.IsNullOrEmpty(language))
{
@@ -454,7 +453,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
mainRequestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(header));
}
- using var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage);
+ using var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage, cancellationToken).ConfigureAwait(false);
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
var englishResult = await _jsonSerializer.DeserializeFromStreamAsync<SeriesResult>(stream).ConfigureAwait(false);
@@ -474,12 +473,11 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
var path = GetDataFilePath(tmdbId, language);
- var fileInfo = _fileSystem.GetFileSystemInfo(path);
-
+ var fileInfo = new FileInfo(path);
if (fileInfo.Exists)
{
// If it's recent or automatic updates are enabled, don't re-download
- if ((DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 2)
+ if ((DateTime.UtcNow - fileInfo.LastWriteTimeUtc).TotalDays <= 2)
{
return Task.CompletedTask;
}
@@ -504,7 +502,9 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
private async Task<RemoteSearchResult> FindByExternalId(string id, string externalSource, CancellationToken cancellationToken)
{
- var url = string.Format(TmdbUtils.BaseTmdbApiUrl + @"3/find/{0}?api_key={1}&external_source={2}",
+ var url = string.Format(
+ CultureInfo.InvariantCulture,
+ TmdbUtils.BaseTmdbApiUrl + @"3/find/{0}?api_key={1}&external_source={2}",
id,
TmdbUtils.ApiKey,
externalSource);
@@ -515,7 +515,7 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
requestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(header));
}
- using var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage);
+ using var response = await TmdbMovieProvider.Current.GetMovieDbResponse(requestMessage, cancellationToken).ConfigureAwait(false);
await using var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
var result = await _jsonSerializer.DeserializeFromStreamAsync<ExternalIdLookupResult>(stream).ConfigureAwait(false);
@@ -547,9 +547,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.TV
return null;
}
- // After TheTVDB
- public int Order => 1;
-
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
{
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
diff --git a/MediaBrowser.Providers/Plugins/Tmdb/Trailers/TmdbTrailerProvider.cs b/MediaBrowser.Providers/Plugins/Tmdb/Trailers/TmdbTrailerProvider.cs
index 25296387b..613dc17e3 100644
--- a/MediaBrowser.Providers/Plugins/Tmdb/Trailers/TmdbTrailerProvider.cs
+++ b/MediaBrowser.Providers/Plugins/Tmdb/Trailers/TmdbTrailerProvider.cs
@@ -21,6 +21,10 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Trailers
_httpClientFactory = httpClientFactory;
}
+ public string Name => TmdbMovieProvider.Current.Name;
+
+ public int Order => 0;
+
public Task<IEnumerable<RemoteSearchResult>> GetSearchResults(TrailerInfo searchInfo, CancellationToken cancellationToken)
{
return TmdbMovieProvider.Current.GetMovieSearchResults(searchInfo, cancellationToken);
@@ -31,10 +35,6 @@ namespace MediaBrowser.Providers.Plugins.Tmdb.Trailers
return TmdbMovieProvider.Current.GetItemMetadata<Trailer>(info, cancellationToken);
}
- public string Name => TmdbMovieProvider.Current.Name;
-
- public int Order => 0;
-
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
{
return _httpClientFactory.CreateClient(NamedClient.Default).GetAsync(url, cancellationToken);
diff --git a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs
index 76dc7df7f..90e13f12f 100644
--- a/MediaBrowser.Providers/Studios/StudiosImageProvider.cs
+++ b/MediaBrowser.Providers/Studios/StudiosImageProvider.cs
@@ -33,6 +33,8 @@ namespace MediaBrowser.Providers.Studios
public string Name => "Emby Designs";
+ public int Order => 0;
+
public bool Supports(BaseItem item)
{
return item is Studio;
@@ -119,8 +121,6 @@ namespace MediaBrowser.Providers.Studios
return EnsureList(url, file, _fileSystem, cancellationToken);
}
- public int Order => 0;
-
public Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
{
var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
@@ -161,12 +161,12 @@ namespace MediaBrowser.Providers.Studios
private string GetComparableName(string name)
{
- return name.Replace(" ", string.Empty)
- .Replace(".", string.Empty)
- .Replace("&", string.Empty)
- .Replace("!", string.Empty)
- .Replace(",", string.Empty)
- .Replace("/", string.Empty);
+ return name.Replace(" ", string.Empty, StringComparison.Ordinal)
+ .Replace(".", string.Empty, StringComparison.Ordinal)
+ .Replace("&", string.Empty, StringComparison.Ordinal)
+ .Replace("!", string.Empty, StringComparison.Ordinal)
+ .Replace(",", string.Empty, StringComparison.Ordinal)
+ .Replace("/", string.Empty, StringComparison.Ordinal);
}
public IEnumerable<string> GetAvailableImages(string file)
diff --git a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
index 0f7cb3f8f..f25d3d5ee 100644
--- a/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
+++ b/MediaBrowser.Providers/Subtitles/SubtitleManager.cs
@@ -303,7 +303,7 @@ namespace MediaBrowser.Providers.Subtitles
private ISubtitleProvider GetProvider(string id)
{
- return _subtitleProviders.First(i => string.Equals(id, GetProviderId(i.Name)));
+ return _subtitleProviders.First(i => string.Equals(id, GetProviderId(i.Name), StringComparison.Ordinal));
}
/// <inheritdoc />
diff --git a/MediaBrowser.Providers/TV/DummySeasonProvider.cs b/MediaBrowser.Providers/TV/DummySeasonProvider.cs
index 0c09cdef6..905cbefd3 100644
--- a/MediaBrowser.Providers/TV/DummySeasonProvider.cs
+++ b/MediaBrowser.Providers/TV/DummySeasonProvider.cs
@@ -124,7 +124,8 @@ namespace MediaBrowser.Providers.TV
/// <summary>
/// Adds the season.
/// </summary>
- public async Task<Season> AddSeason(Series series,
+ public async Task<Season> AddSeason(
+ Series series,
int? seasonNumber,
bool isVirtualItem,
CancellationToken cancellationToken)
@@ -211,11 +212,13 @@ namespace MediaBrowser.Providers.TV
{
_logger.LogInformation("Removing virtual season {0} {1}", series.Name, seasonToRemove.IndexNumber);
- _libraryManager.DeleteItem(seasonToRemove, new DeleteOptions
- {
- DeleteFileLocation = true
-
- }, false);
+ _libraryManager.DeleteItem(
+ seasonToRemove,
+ new DeleteOptions
+ {
+ DeleteFileLocation = true
+ },
+ false);
hasChanges = true;
}
diff --git a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
index 09850beb0..c833b1227 100644
--- a/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
+++ b/MediaBrowser.Providers/TV/MissingEpisodeProvider.cs
@@ -48,18 +48,25 @@ namespace MediaBrowser.Providers.TV
public async Task<bool> Run(Series series, bool addNewItems, CancellationToken cancellationToken)
{
- var tvdbId = series.GetProviderId(MetadataProvider.Tvdb);
- if (string.IsNullOrEmpty(tvdbId))
+ var tvdbIdString = series.GetProviderId(MetadataProvider.Tvdb);
+ if (string.IsNullOrEmpty(tvdbIdString))
{
return false;
}
- var episodes = await _tvdbClientManager.GetAllEpisodesAsync(Convert.ToInt32(tvdbId), series.GetPreferredMetadataLanguage(), cancellationToken);
+ var episodes = await _tvdbClientManager.GetAllEpisodesAsync(
+ int.Parse(tvdbIdString, CultureInfo.InvariantCulture),
+ series.GetPreferredMetadataLanguage(),
+ cancellationToken).ConfigureAwait(false);
var episodeLookup = episodes
.Select(i =>
{
- DateTime.TryParse(i.FirstAired, out var firstAired);
+ if (!DateTime.TryParse(i.FirstAired, out var firstAired))
+ {
+ firstAired = default;
+ }
+
var seasonNumber = i.AiredSeason.GetValueOrDefault(-1);
var episodeNumber = i.AiredEpisodeNumber.GetValueOrDefault(-1);
return (seasonNumber, episodeNumber, firstAired);
@@ -159,7 +166,7 @@ namespace MediaBrowser.Providers.TV
var now = DateTime.UtcNow.AddDays(-UnairedEpisodeThresholdDays);
- if (airDate < now && addMissingEpisodes || airDate > now)
+ if ((airDate < now && addMissingEpisodes) || airDate > now)
{
// tvdb has a lot of nearly blank episodes
_logger.LogInformation("Creating virtual missing/unaired episode {0} {1}x{2}", series.Name, tuple.seasonNumber, tuple.episodenumber);
@@ -232,10 +239,13 @@ namespace MediaBrowser.Providers.TV
foreach (var episodeToRemove in episodesToRemove)
{
- _libraryManager.DeleteItem(episodeToRemove, new DeleteOptions
- {
- DeleteFileLocation = true
- }, false);
+ _libraryManager.DeleteItem(
+ episodeToRemove,
+ new DeleteOptions
+ {
+ DeleteFileLocation = true
+ },
+ false);
hasChanges = true;
}
@@ -246,7 +256,7 @@ namespace MediaBrowser.Providers.TV
/// <summary>
/// Removes the obsolete or missing seasons.
/// </summary>
- /// <param name="allRecursiveChildren"></param>
+ /// <param name="allRecursiveChildren">All recursive children.</param>
/// <param name="episodeLookup">The episode lookup.</param>
/// <returns><see cref="bool" />.</returns>
private bool RemoveObsoleteOrMissingSeasons(
@@ -297,10 +307,13 @@ namespace MediaBrowser.Providers.TV
foreach (var seasonToRemove in seasonsToRemove)
{
- _libraryManager.DeleteItem(seasonToRemove, new DeleteOptions
- {
- DeleteFileLocation = true
- }, false);
+ _libraryManager.DeleteItem(
+ seasonToRemove,
+ new DeleteOptions
+ {
+ DeleteFileLocation = true
+ },
+ false);
hasChanges = true;
}
@@ -354,7 +367,10 @@ namespace MediaBrowser.Providers.TV
/// <param name="seasonCounts"></param>
/// <param name="episodeTuple"></param>
/// <returns>Episode.</returns>
- private Episode GetExistingEpisode(IEnumerable<Episode> existingEpisodes, IReadOnlyDictionary<int, int> seasonCounts, (int seasonNumber, int episodeNumber, DateTime firstAired) episodeTuple)
+ private Episode GetExistingEpisode(
+ IEnumerable<Episode> existingEpisodes,
+ IReadOnlyDictionary<int, int> seasonCounts,
+ (int seasonNumber, int episodeNumber, DateTime firstAired) episodeTuple)
{
var seasonNumber = episodeTuple.seasonNumber;
var episodeNumber = episodeTuple.episodeNumber;
diff --git a/MediaBrowser.Providers/TV/SeasonMetadataService.cs b/MediaBrowser.Providers/TV/SeasonMetadataService.cs
index 5431de623..4e59f78bc 100644
--- a/MediaBrowser.Providers/TV/SeasonMetadataService.cs
+++ b/MediaBrowser.Providers/TV/SeasonMetadataService.cs
@@ -28,6 +28,9 @@ namespace MediaBrowser.Providers.TV
}
/// <inheritdoc />
+ protected override bool EnableUpdatingPremiereDateFromChildren => true;
+
+ /// <inheritdoc />
protected override ItemUpdateType BeforeSaveInternal(Season item, bool isFullRefresh, ItemUpdateType currentUpdateType)
{
var updateType = base.BeforeSaveInternal(item, isFullRefresh, currentUpdateType);
@@ -68,9 +71,6 @@ namespace MediaBrowser.Providers.TV
}
/// <inheritdoc />
- protected override bool EnableUpdatingPremiereDateFromChildren => true;
-
- /// <inheritdoc />
protected override IList<BaseItem> GetChildrenForMetadataUpdates(Season item)
=> item.GetEpisodes();
diff --git a/MediaBrowser.Providers/TV/TvExternalIds.cs b/MediaBrowser.Providers/TV/TvExternalIds.cs
deleted file mode 100644
index a6040edd1..000000000
--- a/MediaBrowser.Providers/TV/TvExternalIds.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-#pragma warning disable CS1591
-
-using MediaBrowser.Controller.Entities.TV;
-using MediaBrowser.Controller.Providers;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Providers;
-using MediaBrowser.Providers.Plugins.TheTvdb;
-
-namespace MediaBrowser.Providers.TV
-{
- public class Zap2ItExternalId : IExternalId
- {
- /// <inheritdoc />
- public string ProviderName => "Zap2It";
-
- /// <inheritdoc />
- public string Key => MetadataProvider.Zap2It.ToString();
-
- /// <inheritdoc />
- public ExternalIdMediaType? Type => null;
-
- /// <inheritdoc />
- public string UrlFormatString => "http://tvlistings.zap2it.com/overview.html?programSeriesId={0}";
-
- /// <inheritdoc />
- public bool Supports(IHasProviderIds item) => item is Series;
- }
-
- public class TvdbExternalId : IExternalId
- {
- /// <inheritdoc />
- public string ProviderName => "TheTVDB";
-
- /// <inheritdoc />
- public string Key => MetadataProvider.Tvdb.ToString();
-
- /// <inheritdoc />
- public ExternalIdMediaType? Type => null;
-
- /// <inheritdoc />
- public string UrlFormatString => TvdbUtils.TvdbBaseUrl + "?tab=series&id={0}";
-
- /// <inheritdoc />
- public bool Supports(IHasProviderIds item) => item is Series;
- }
-
- public class TvdbSeasonExternalId : IExternalId
- {
- /// <inheritdoc />
- public string ProviderName => "TheTVDB";
-
- /// <inheritdoc />
- public string Key => MetadataProvider.Tvdb.ToString();
-
- /// <inheritdoc />
- public ExternalIdMediaType? Type => ExternalIdMediaType.Season;
-
- /// <inheritdoc />
- public string UrlFormatString => null;
-
- /// <inheritdoc />
- public bool Supports(IHasProviderIds item) => item is Season;
- }
-
- public class TvdbEpisodeExternalId : IExternalId
- {
- /// <inheritdoc />
- public string ProviderName => "TheTVDB";
-
- /// <inheritdoc />
- public string Key => MetadataProvider.Tvdb.ToString();
-
- /// <inheritdoc />
- public ExternalIdMediaType? Type => ExternalIdMediaType.Episode;
-
- /// <inheritdoc />
- public string UrlFormatString => TvdbUtils.TvdbBaseUrl + "?tab=episode&id={0}";
-
- /// <inheritdoc />
- public bool Supports(IHasProviderIds item) => item is Episode;
- }
-}
diff --git a/MediaBrowser.Providers/TV/TvdbEpisodeExternalId.cs b/MediaBrowser.Providers/TV/TvdbEpisodeExternalId.cs
new file mode 100644
index 000000000..40c5f2d78
--- /dev/null
+++ b/MediaBrowser.Providers/TV/TvdbEpisodeExternalId.cs
@@ -0,0 +1,28 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+using MediaBrowser.Providers.Plugins.TheTvdb;
+
+namespace MediaBrowser.Providers.TV
+{
+ public class TvdbEpisodeExternalId : IExternalId
+ {
+ /// <inheritdoc />
+ public string ProviderName => "TheTVDB";
+
+ /// <inheritdoc />
+ public string Key => MetadataProvider.Tvdb.ToString();
+
+ /// <inheritdoc />
+ public ExternalIdMediaType? Type => ExternalIdMediaType.Episode;
+
+ /// <inheritdoc />
+ public string UrlFormatString => TvdbUtils.TvdbBaseUrl + "?tab=episode&id={0}";
+
+ /// <inheritdoc />
+ public bool Supports(IHasProviderIds item) => item is Episode;
+ }
+}
diff --git a/MediaBrowser.Providers/TV/TvdbExternalId.cs b/MediaBrowser.Providers/TV/TvdbExternalId.cs
new file mode 100644
index 000000000..4c54de9f8
--- /dev/null
+++ b/MediaBrowser.Providers/TV/TvdbExternalId.cs
@@ -0,0 +1,28 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+using MediaBrowser.Providers.Plugins.TheTvdb;
+
+namespace MediaBrowser.Providers.TV
+{
+ public class TvdbExternalId : IExternalId
+ {
+ /// <inheritdoc />
+ public string ProviderName => "TheTVDB";
+
+ /// <inheritdoc />
+ public string Key => MetadataProvider.Tvdb.ToString();
+
+ /// <inheritdoc />
+ public ExternalIdMediaType? Type => null;
+
+ /// <inheritdoc />
+ public string UrlFormatString => TvdbUtils.TvdbBaseUrl + "?tab=series&id={0}";
+
+ /// <inheritdoc />
+ public bool Supports(IHasProviderIds item) => item is Series;
+ }
+}
diff --git a/MediaBrowser.Providers/TV/TvdbSeasonExternalId.cs b/MediaBrowser.Providers/TV/TvdbSeasonExternalId.cs
new file mode 100644
index 000000000..807ebb3ee
--- /dev/null
+++ b/MediaBrowser.Providers/TV/TvdbSeasonExternalId.cs
@@ -0,0 +1,28 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+using MediaBrowser.Providers.Plugins.TheTvdb;
+
+namespace MediaBrowser.Providers.TV
+{
+ public class TvdbSeasonExternalId : IExternalId
+ {
+ /// <inheritdoc />
+ public string ProviderName => "TheTVDB";
+
+ /// <inheritdoc />
+ public string Key => MetadataProvider.Tvdb.ToString();
+
+ /// <inheritdoc />
+ public ExternalIdMediaType? Type => ExternalIdMediaType.Season;
+
+ /// <inheritdoc />
+ public string UrlFormatString => null;
+
+ /// <inheritdoc />
+ public bool Supports(IHasProviderIds item) => item is Season;
+ }
+}
diff --git a/MediaBrowser.Providers/TV/Zap2ItExternalId.cs b/MediaBrowser.Providers/TV/Zap2ItExternalId.cs
new file mode 100644
index 000000000..c9f314af9
--- /dev/null
+++ b/MediaBrowser.Providers/TV/Zap2ItExternalId.cs
@@ -0,0 +1,28 @@
+#pragma warning disable CS1591
+
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Providers;
+using MediaBrowser.Providers.Plugins.TheTvdb;
+
+namespace MediaBrowser.Providers.TV
+{
+ public class Zap2ItExternalId : IExternalId
+ {
+ /// <inheritdoc />
+ public string ProviderName => "Zap2It";
+
+ /// <inheritdoc />
+ public string Key => MetadataProvider.Zap2It.ToString();
+
+ /// <inheritdoc />
+ public ExternalIdMediaType? Type => null;
+
+ /// <inheritdoc />
+ public string UrlFormatString => "http://tvlistings.zap2it.com/overview.html?programSeriesId={0}";
+
+ /// <inheritdoc />
+ public bool Supports(IHasProviderIds item) => item is Series;
+ }
+}