aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/Library/Resolvers/TV
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2016-11-03 02:37:52 -0400
committerLuke Pulverenti <luke.pulverenti@gmail.com>2016-11-03 02:37:52 -0400
commit3eb4091808735858b01855d298226d239be464af (patch)
treea17a94e2c677d60471a79617218c8ef9a7a7dee3 /Emby.Server.Implementations/Library/Resolvers/TV
parent41bef184d1036b02baec00734f3edd8abbebf5fe (diff)
move additional classes to new server lib
Diffstat (limited to 'Emby.Server.Implementations/Library/Resolvers/TV')
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs75
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs62
-rw-r--r--Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs251
3 files changed, 388 insertions, 0 deletions
diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs
new file mode 100644
index 0000000000..2a4cc49b76
--- /dev/null
+++ b/Emby.Server.Implementations/Library/Resolvers/TV/EpisodeResolver.cs
@@ -0,0 +1,75 @@
+using System;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
+using System.Linq;
+using MediaBrowser.Model.Entities;
+
+namespace Emby.Server.Implementations.Library.Resolvers.TV
+{
+ /// <summary>
+ /// Class EpisodeResolver
+ /// </summary>
+ public class EpisodeResolver : BaseVideoResolver<Episode>
+ {
+ public EpisodeResolver(ILibraryManager libraryManager) : base(libraryManager)
+ {
+ }
+
+ /// <summary>
+ /// Resolves the specified args.
+ /// </summary>
+ /// <param name="args">The args.</param>
+ /// <returns>Episode.</returns>
+ protected override Episode Resolve(ItemResolveArgs args)
+ {
+ var parent = args.Parent;
+
+ if (parent == null)
+ {
+ return null;
+ }
+
+ var season = parent as Season;
+ // Just in case the user decided to nest episodes.
+ // Not officially supported but in some cases we can handle it.
+ if (season == null)
+ {
+ season = parent.GetParents().OfType<Season>().FirstOrDefault();
+ }
+
+ // If the parent is a Season or Series, then this is an Episode if the VideoResolver returns something
+ // Also handle flat tv folders
+ if (season != null ||
+ string.Equals(args.GetCollectionType(), CollectionType.TvShows, StringComparison.OrdinalIgnoreCase) ||
+ args.HasParent<Series>())
+ {
+ var episode = ResolveVideo<Episode>(args, false);
+
+ if (episode != null)
+ {
+ var series = parent as Series;
+ if (series == null)
+ {
+ series = parent.GetParents().OfType<Series>().FirstOrDefault();
+ }
+
+ if (series != null)
+ {
+ episode.SeriesId = series.Id;
+ episode.SeriesName = series.Name;
+ episode.SeriesSortName = series.SortName;
+ }
+ if (season != null)
+ {
+ episode.SeasonId = season.Id;
+ episode.SeasonName = season.Name;
+ }
+ }
+
+ return episode;
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs
new file mode 100644
index 0000000000..c065feda10
--- /dev/null
+++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeasonResolver.cs
@@ -0,0 +1,62 @@
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Naming.Common;
+using MediaBrowser.Naming.TV;
+
+namespace Emby.Server.Implementations.Library.Resolvers.TV
+{
+ /// <summary>
+ /// Class SeasonResolver
+ /// </summary>
+ public class SeasonResolver : FolderResolver<Season>
+ {
+ /// <summary>
+ /// The _config
+ /// </summary>
+ private readonly IServerConfigurationManager _config;
+
+ private readonly ILibraryManager _libraryManager;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SeasonResolver"/> class.
+ /// </summary>
+ /// <param name="config">The config.</param>
+ public SeasonResolver(IServerConfigurationManager config, ILibraryManager libraryManager)
+ {
+ _config = config;
+ _libraryManager = libraryManager;
+ }
+
+ /// <summary>
+ /// Resolves the specified args.
+ /// </summary>
+ /// <param name="args">The args.</param>
+ /// <returns>Season.</returns>
+ protected override Season Resolve(ItemResolveArgs args)
+ {
+ if (args.Parent is Series && args.IsDirectory)
+ {
+ var namingOptions = ((LibraryManager)_libraryManager).GetNamingOptions();
+ var series = ((Series)args.Parent);
+
+ var season = new Season
+ {
+ IndexNumber = new SeasonPathParser(namingOptions, new RegexProvider()).Parse(args.Path, true, true).SeasonNumber,
+ SeriesId = series.Id,
+ SeriesSortName = series.SortName,
+ SeriesName = series.Name
+ };
+
+ if (season.IndexNumber.HasValue && season.IndexNumber.Value == 0)
+ {
+ season.Name = _config.Configuration.SeasonZeroDisplayName;
+ }
+
+ return season;
+ }
+
+ return null;
+ }
+ }
+}
diff --git a/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
new file mode 100644
index 0000000000..44eb0e3e2c
--- /dev/null
+++ b/Emby.Server.Implementations/Library/Resolvers/TV/SeriesResolver.cs
@@ -0,0 +1,251 @@
+using MediaBrowser.Controller.Entities.TV;
+using MediaBrowser.Controller.Library;
+using MediaBrowser.Controller.Providers;
+using MediaBrowser.Controller.Resolvers;
+using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Naming.Common;
+using MediaBrowser.Naming.TV;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using Emby.Server.Implementations.Logging;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Model.IO;
+using MediaBrowser.Controller.Configuration;
+using MediaBrowser.Controller.IO;
+using MediaBrowser.Model.Configuration;
+
+namespace Emby.Server.Implementations.Library.Resolvers.TV
+{
+ /// <summary>
+ /// Class SeriesResolver
+ /// </summary>
+ public class SeriesResolver : FolderResolver<Series>
+ {
+ private readonly IFileSystem _fileSystem;
+ private readonly ILogger _logger;
+ private readonly ILibraryManager _libraryManager;
+
+ public SeriesResolver(IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager)
+ {
+ _fileSystem = fileSystem;
+ _logger = logger;
+ _libraryManager = libraryManager;
+ }
+
+ /// <summary>
+ /// Gets the priority.
+ /// </summary>
+ /// <value>The priority.</value>
+ public override ResolverPriority Priority
+ {
+ get
+ {
+ return ResolverPriority.Second;
+ }
+ }
+
+ /// <summary>
+ /// Resolves the specified args.
+ /// </summary>
+ /// <param name="args">The args.</param>
+ /// <returns>Series.</returns>
+ protected override Series Resolve(ItemResolveArgs args)
+ {
+ if (args.IsDirectory)
+ {
+ if (args.HasParent<Series>() || args.HasParent<Season>())
+ {
+ return null;
+ }
+
+ var collectionType = args.GetCollectionType();
+ if (string.Equals(collectionType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
+ {
+ //if (args.ContainsFileSystemEntryByName("tvshow.nfo"))
+ //{
+ // return new Series
+ // {
+ // Path = args.Path,
+ // Name = Path.GetFileName(args.Path)
+ // };
+ //}
+
+ var configuredContentType = _libraryManager.GetConfiguredContentType(args.Path);
+ if (!string.Equals(configuredContentType, CollectionType.TvShows, StringComparison.OrdinalIgnoreCase))
+ {
+ return new Series
+ {
+ Path = args.Path,
+ Name = Path.GetFileName(args.Path)
+ };
+ }
+ }
+ else if (string.IsNullOrWhiteSpace(collectionType))
+ {
+ if (args.ContainsFileSystemEntryByName("tvshow.nfo"))
+ {
+ if (args.Parent.IsRoot)
+ {
+ // For now, return null, but if we want to allow this in the future then add some additional checks to guard against a misplaced tvshow.nfo
+ return null;
+ }
+
+ return new Series
+ {
+ Path = args.Path,
+ Name = Path.GetFileName(args.Path)
+ };
+ }
+
+ if (args.Parent.IsRoot)
+ {
+ return null;
+ }
+
+ if (IsSeriesFolder(args.Path, args.FileSystemChildren, args.DirectoryService, _fileSystem, _logger, _libraryManager, args.GetLibraryOptions(), false))
+ {
+ return new Series
+ {
+ Path = args.Path,
+ Name = Path.GetFileName(args.Path)
+ };
+ }
+ }
+ }
+
+ return null;
+ }
+
+ public static bool IsSeriesFolder(string path,
+ IEnumerable<FileSystemMetadata> fileSystemChildren,
+ IDirectoryService directoryService,
+ IFileSystem fileSystem,
+ ILogger logger,
+ ILibraryManager libraryManager,
+ LibraryOptions libraryOptions,
+ bool isTvContentType)
+ {
+ foreach (var child in fileSystemChildren)
+ {
+ //if ((attributes & FileAttributes.Hidden) == FileAttributes.Hidden)
+ //{
+ // //logger.Debug("Igoring series file or folder marked hidden: {0}", child.FullName);
+ // continue;
+ //}
+
+ // Can't enforce this because files saved by Bitcasa are always marked System
+ //if ((attributes & FileAttributes.System) == FileAttributes.System)
+ //{
+ // logger.Debug("Igoring series subfolder marked system: {0}", child.FullName);
+ // continue;
+ //}
+
+ if (child.IsDirectory)
+ {
+ if (IsSeasonFolder(child.FullName, isTvContentType, libraryManager))
+ {
+ //logger.Debug("{0} is a series because of season folder {1}.", path, child.FullName);
+ return true;
+ }
+ }
+ else
+ {
+ string fullName = child.FullName;
+ if (libraryManager.IsVideoFile(fullName, libraryOptions))
+ {
+ if (isTvContentType)
+ {
+ return true;
+ }
+
+ var namingOptions = ((LibraryManager)libraryManager).GetNamingOptions();
+
+ // In mixed folders we need to be conservative and avoid expressions that may result in false positives (e.g. movies with numbers in the title)
+ if (!isTvContentType)
+ {
+ namingOptions.EpisodeExpressions = namingOptions.EpisodeExpressions
+ .Where(i => i.IsNamed && !i.IsOptimistic)
+ .ToList();
+ }
+
+ var episodeResolver = new MediaBrowser.Naming.TV.EpisodeResolver(namingOptions, new PatternsLogger());
+ var episodeInfo = episodeResolver.Resolve(fullName, false, false);
+ if (episodeInfo != null && episodeInfo.EpisodeNumber.HasValue)
+ {
+ return true;
+ }
+ }
+ }
+ }
+
+ logger.Debug("{0} is not a series folder.", path);
+ return false;
+ }
+
+ /// <summary>
+ /// Determines whether [is place holder] [the specified path].
+ /// </summary>
+ /// <param name="path">The path.</param>
+ /// <returns><c>true</c> if [is place holder] [the specified path]; otherwise, <c>false</c>.</returns>
+ /// <exception cref="System.ArgumentNullException">path</exception>
+ private static bool IsVideoPlaceHolder(string path)
+ {
+ if (string.IsNullOrEmpty(path))
+ {
+ throw new ArgumentNullException("path");
+ }
+
+ var extension = Path.GetExtension(path);
+
+ return string.Equals(extension, ".disc", StringComparison.OrdinalIgnoreCase);
+ }
+
+ /// <summary>
+ /// Determines whether [is season folder] [the specified path].
+ /// </summary>
+ /// <param name="path">The path.</param>
+ /// <param name="isTvContentType">if set to <c>true</c> [is tv content type].</param>
+ /// <param name="libraryManager">The library manager.</param>
+ /// <returns><c>true</c> if [is season folder] [the specified path]; otherwise, <c>false</c>.</returns>
+ private static bool IsSeasonFolder(string path, bool isTvContentType, ILibraryManager libraryManager)
+ {
+ var namingOptions = ((LibraryManager)libraryManager).GetNamingOptions();
+
+ var seasonNumber = new SeasonPathParser(namingOptions, new RegexProvider()).Parse(path, isTvContentType, isTvContentType).SeasonNumber;
+
+ return seasonNumber.HasValue;
+ }
+
+ /// <summary>
+ /// Sets the initial item values.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="args">The args.</param>
+ protected override void SetInitialItemValues(Series item, ItemResolveArgs args)
+ {
+ base.SetInitialItemValues(item, args);
+
+ SetProviderIdFromPath(item, args.Path);
+ }
+
+ /// <summary>
+ /// Sets the provider id from path.
+ /// </summary>
+ /// <param name="item">The item.</param>
+ /// <param name="path">The path.</param>
+ private void SetProviderIdFromPath(Series item, string path)
+ {
+ var justName = Path.GetFileName(path);
+
+ var id = justName.GetAttributeValue("tvdbid");
+
+ if (!string.IsNullOrEmpty(id))
+ {
+ item.SetProviderId(MetadataProviders.Tvdb, id);
+ }
+ }
+ }
+}