You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
6.1 KiB
170 lines
6.1 KiB
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using FluentValidation;
|
|
using FluentValidation.Results;
|
|
using NLog;
|
|
using NzbDrone.Common.EnsureThat;
|
|
using NzbDrone.Common.Extensions;
|
|
using NzbDrone.Core.Exceptions;
|
|
using NzbDrone.Core.MetadataSource;
|
|
using NzbDrone.Core.Organizer;
|
|
using NzbDrone.Core.Parser;
|
|
|
|
namespace NzbDrone.Core.Tv
|
|
{
|
|
public interface IAddSeriesService
|
|
{
|
|
Series AddSeries(Series newSeries);
|
|
List<Series> AddSeries(List<Series> newSeries, bool ignoreErrors = false);
|
|
}
|
|
|
|
public class AddSeriesService : IAddSeriesService
|
|
{
|
|
private readonly ISeriesService _seriesService;
|
|
private readonly IProvideSeriesInfo _seriesInfo;
|
|
private readonly IBuildFileNames _fileNameBuilder;
|
|
private readonly IAddSeriesValidator _addSeriesValidator;
|
|
private readonly Logger _logger;
|
|
|
|
public AddSeriesService(ISeriesService seriesService,
|
|
IProvideSeriesInfo seriesInfo,
|
|
IBuildFileNames fileNameBuilder,
|
|
IAddSeriesValidator addSeriesValidator,
|
|
Logger logger)
|
|
{
|
|
_seriesService = seriesService;
|
|
_seriesInfo = seriesInfo;
|
|
_fileNameBuilder = fileNameBuilder;
|
|
_addSeriesValidator = addSeriesValidator;
|
|
_logger = logger;
|
|
}
|
|
|
|
public Series AddSeries(Series newSeries)
|
|
{
|
|
Ensure.That(newSeries, () => newSeries).IsNotNull();
|
|
|
|
newSeries = AddSkyhookData(newSeries);
|
|
newSeries = SetPropertiesAndValidate(newSeries);
|
|
|
|
_logger.Info("Adding Series {0} Path: [{1}]", newSeries, newSeries.Path);
|
|
_seriesService.AddSeries(newSeries);
|
|
|
|
return newSeries;
|
|
}
|
|
|
|
public List<Series> AddSeries(List<Series> newSeries, bool ignoreErrors = false)
|
|
{
|
|
var added = DateTime.UtcNow;
|
|
var seriesToAdd = new List<Series>();
|
|
var existingSeries = _seriesService.GetAllSeries();
|
|
|
|
foreach (var s in newSeries)
|
|
{
|
|
if (s.Path.IsNullOrWhiteSpace())
|
|
{
|
|
_logger.Info("Adding Series {0} Root Folder Path: [{1}]", s, s.RootFolderPath);
|
|
}
|
|
else
|
|
{
|
|
_logger.Info("Adding Series {0} Path: [{1}]", s, s.Path);
|
|
}
|
|
|
|
try
|
|
{
|
|
var series = AddSkyhookData(s);
|
|
series = SetPropertiesAndValidate(series);
|
|
series.Added = added;
|
|
if (existingSeries.Any(f => f.TvdbId == series.TvdbId))
|
|
{
|
|
_logger.Debug("TVDB ID {0} was not added due to validation failure: Series already exists in database", s.TvdbId);
|
|
continue;
|
|
}
|
|
|
|
if (seriesToAdd.Any(f => f.TvdbId == series.TvdbId))
|
|
{
|
|
_logger.Debug("TVDB ID {0} was not added due to validation failure: Series already exists on list", s.TvdbId);
|
|
continue;
|
|
}
|
|
|
|
var duplicateSlug = seriesToAdd.FirstOrDefault(f => f.TitleSlug == series.TitleSlug);
|
|
if (duplicateSlug != null)
|
|
{
|
|
_logger.Debug("TVDB ID {0} was not added due to validation failure: Duplicate Slug {1} used by series {2}", s.TvdbId, s.TitleSlug, duplicateSlug.TvdbId);
|
|
continue;
|
|
}
|
|
|
|
seriesToAdd.Add(series);
|
|
}
|
|
catch (ValidationException ex)
|
|
{
|
|
if (!ignoreErrors)
|
|
{
|
|
throw;
|
|
}
|
|
|
|
_logger.Debug("TVDB ID {0} was not added due to validation failures. {1}", s.TvdbId, ex.Message);
|
|
}
|
|
}
|
|
|
|
return _seriesService.AddSeries(seriesToAdd);
|
|
}
|
|
|
|
private Series AddSkyhookData(Series newSeries)
|
|
{
|
|
Tuple<Series, List<Episode>> tuple;
|
|
|
|
try
|
|
{
|
|
tuple = _seriesInfo.GetSeriesInfo(newSeries.TvdbId);
|
|
}
|
|
catch (SeriesNotFoundException)
|
|
{
|
|
_logger.Error("TVDB ID {0} was not found, it may have been removed from TheTVDB. Path: {1}", newSeries.TvdbId, newSeries.Path);
|
|
|
|
throw new ValidationException(new List<ValidationFailure>
|
|
{
|
|
new ValidationFailure("TvdbId", $"A series with this ID was not found. Path: {newSeries.Path}", newSeries.TvdbId)
|
|
});
|
|
}
|
|
|
|
var series = tuple.Item1;
|
|
|
|
// If seasons were passed in on the new series use them, otherwise use the seasons from Skyhook
|
|
newSeries.Seasons = newSeries.Seasons != null && newSeries.Seasons.Any() ? newSeries.Seasons : series.Seasons;
|
|
|
|
series.ApplyChanges(newSeries);
|
|
|
|
return series;
|
|
}
|
|
|
|
private Series SetPropertiesAndValidate(Series newSeries)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(newSeries.Path))
|
|
{
|
|
var folderName = _fileNameBuilder.GetSeriesFolder(newSeries);
|
|
newSeries.Path = Path.Combine(newSeries.RootFolderPath, folderName);
|
|
}
|
|
|
|
newSeries.CleanTitle = newSeries.Title.CleanSeriesTitle();
|
|
newSeries.SortTitle = SeriesTitleNormalizer.Normalize(newSeries.Title, newSeries.TvdbId);
|
|
newSeries.Added = DateTime.UtcNow;
|
|
|
|
if (newSeries.AddOptions != null && newSeries.AddOptions.Monitor == MonitorTypes.None)
|
|
{
|
|
newSeries.Monitored = false;
|
|
}
|
|
|
|
var validationResult = _addSeriesValidator.Validate(newSeries);
|
|
|
|
if (!validationResult.IsValid)
|
|
{
|
|
throw new ValidationException(validationResult.Errors);
|
|
}
|
|
|
|
return newSeries;
|
|
}
|
|
}
|
|
}
|