parent
7297c1b8e4
commit
068ea1e934
|
@ -4,6 +4,7 @@ using Sonarr.Http.REST;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Api.Series;
|
using NzbDrone.Api.Series;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Api.Blacklist
|
namespace NzbDrone.Api.Blacklist
|
||||||
{
|
{
|
||||||
|
@ -17,6 +18,7 @@ namespace NzbDrone.Api.Blacklist
|
||||||
public DownloadProtocol Protocol { get; set; }
|
public DownloadProtocol Protocol { get; set; }
|
||||||
public string Indexer { get; set; }
|
public string Indexer { get; set; }
|
||||||
public string Message { get; set; }
|
public string Message { get; set; }
|
||||||
|
public Language Language { get; set; }
|
||||||
|
|
||||||
public SeriesResource Series { get; set; }
|
public SeriesResource Series { get; set; }
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,9 +12,9 @@ namespace NzbDrone.Api.Calendar
|
||||||
{
|
{
|
||||||
public CalendarModule(IEpisodeService episodeService,
|
public CalendarModule(IEpisodeService episodeService,
|
||||||
ISeriesService seriesService,
|
ISeriesService seriesService,
|
||||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
IUpgradableSpecification upgradableSpecification,
|
||||||
IBroadcastSignalRMessage signalRBroadcaster)
|
IBroadcastSignalRMessage signalRBroadcaster)
|
||||||
: base(episodeService, seriesService, qualityUpgradableSpecification, signalRBroadcaster, "calendar")
|
: base(episodeService, seriesService, upgradableSpecification, signalRBroadcaster, "calendar")
|
||||||
{
|
{
|
||||||
GetResourceAll = GetCalendar;
|
GetResourceAll = GetCalendar;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Sonarr.Http.REST;
|
|
||||||
using NzbDrone.Core.Datastore.Events;
|
using NzbDrone.Core.Datastore.Events;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.MediaFiles.Events;
|
using NzbDrone.Core.MediaFiles.Events;
|
||||||
|
@ -8,6 +7,7 @@ using NzbDrone.Core.Tv;
|
||||||
using NzbDrone.Core.DecisionEngine;
|
using NzbDrone.Core.DecisionEngine;
|
||||||
using NzbDrone.Core.Exceptions;
|
using NzbDrone.Core.Exceptions;
|
||||||
using NzbDrone.SignalR;
|
using NzbDrone.SignalR;
|
||||||
|
using Sonarr.Http;
|
||||||
using HttpStatusCode = System.Net.HttpStatusCode;
|
using HttpStatusCode = System.Net.HttpStatusCode;
|
||||||
|
|
||||||
namespace NzbDrone.Api.EpisodeFiles
|
namespace NzbDrone.Api.EpisodeFiles
|
||||||
|
@ -18,19 +18,19 @@ namespace NzbDrone.Api.EpisodeFiles
|
||||||
private readonly IMediaFileService _mediaFileService;
|
private readonly IMediaFileService _mediaFileService;
|
||||||
private readonly IDeleteMediaFiles _mediaFileDeletionService;
|
private readonly IDeleteMediaFiles _mediaFileDeletionService;
|
||||||
private readonly ISeriesService _seriesService;
|
private readonly ISeriesService _seriesService;
|
||||||
private readonly IQualityUpgradableSpecification _qualityUpgradableSpecification;
|
private readonly IUpgradableSpecification _upgradableSpecification;
|
||||||
|
|
||||||
public EpisodeFileModule(IBroadcastSignalRMessage signalRBroadcaster,
|
public EpisodeFileModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||||
IMediaFileService mediaFileService,
|
IMediaFileService mediaFileService,
|
||||||
IDeleteMediaFiles mediaFileDeletionService,
|
IDeleteMediaFiles mediaFileDeletionService,
|
||||||
ISeriesService seriesService,
|
ISeriesService seriesService,
|
||||||
IQualityUpgradableSpecification qualityUpgradableSpecification)
|
IUpgradableSpecification upgradableSpecification)
|
||||||
: base(signalRBroadcaster)
|
: base(signalRBroadcaster)
|
||||||
{
|
{
|
||||||
_mediaFileService = mediaFileService;
|
_mediaFileService = mediaFileService;
|
||||||
_mediaFileDeletionService = mediaFileDeletionService;
|
_mediaFileDeletionService = mediaFileDeletionService;
|
||||||
_seriesService = seriesService;
|
_seriesService = seriesService;
|
||||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
_upgradableSpecification = upgradableSpecification;
|
||||||
GetResourceById = GetEpisodeFile;
|
GetResourceById = GetEpisodeFile;
|
||||||
GetResourceAll = GetEpisodeFiles;
|
GetResourceAll = GetEpisodeFiles;
|
||||||
UpdateResource = SetQuality;
|
UpdateResource = SetQuality;
|
||||||
|
@ -42,7 +42,7 @@ namespace NzbDrone.Api.EpisodeFiles
|
||||||
var episodeFile = _mediaFileService.Get(id);
|
var episodeFile = _mediaFileService.Get(id);
|
||||||
var series = _seriesService.GetSeries(episodeFile.SeriesId);
|
var series = _seriesService.GetSeries(episodeFile.SeriesId);
|
||||||
|
|
||||||
return episodeFile.ToResource(series, _qualityUpgradableSpecification);
|
return episodeFile.ToResource(series, _upgradableSpecification);
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<EpisodeFileResource> GetEpisodeFiles()
|
private List<EpisodeFileResource> GetEpisodeFiles()
|
||||||
|
@ -56,13 +56,14 @@ namespace NzbDrone.Api.EpisodeFiles
|
||||||
|
|
||||||
var series = _seriesService.GetSeries(seriesId);
|
var series = _seriesService.GetSeries(seriesId);
|
||||||
|
|
||||||
return _mediaFileService.GetFilesBySeries(seriesId).ConvertAll(f => f.ToResource(series, _qualityUpgradableSpecification));
|
return _mediaFileService.GetFilesBySeries(seriesId).ConvertAll(f => f.ToResource(series, _upgradableSpecification));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetQuality(EpisodeFileResource episodeFileResource)
|
private void SetQuality(EpisodeFileResource episodeFileResource)
|
||||||
{
|
{
|
||||||
var episodeFile = _mediaFileService.Get(episodeFileResource.Id);
|
var episodeFile = _mediaFileService.Get(episodeFileResource.Id);
|
||||||
episodeFile.Quality = episodeFileResource.Quality;
|
episodeFile.Quality = episodeFileResource.Quality;
|
||||||
|
episodeFile.Language = episodeFileResource.Language;
|
||||||
_mediaFileService.Update(episodeFile);
|
_mediaFileService.Update(episodeFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ using NzbDrone.Core.DecisionEngine;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
using Sonarr.Http.REST;
|
using Sonarr.Http.REST;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Api.EpisodeFiles
|
namespace NzbDrone.Api.EpisodeFiles
|
||||||
{
|
{
|
||||||
|
@ -17,6 +18,7 @@ namespace NzbDrone.Api.EpisodeFiles
|
||||||
public DateTime DateAdded { get; set; }
|
public DateTime DateAdded { get; set; }
|
||||||
public string SceneName { get; set; }
|
public string SceneName { get; set; }
|
||||||
public QualityModel Quality { get; set; }
|
public QualityModel Quality { get; set; }
|
||||||
|
public Language Language { get; set; }
|
||||||
public MediaInfoResource MediaInfo { get; set; }
|
public MediaInfoResource MediaInfo { get; set; }
|
||||||
public string OriginalFilePath { get; set; }
|
public string OriginalFilePath { get; set; }
|
||||||
|
|
||||||
|
@ -46,7 +48,7 @@ namespace NzbDrone.Api.EpisodeFiles
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public static EpisodeFileResource ToResource(this EpisodeFile model, Core.Tv.Series series, IQualityUpgradableSpecification qualityUpgradableSpecification)
|
public static EpisodeFileResource ToResource(this EpisodeFile model, Core.Tv.Series series, IUpgradableSpecification upgradableSpecification)
|
||||||
{
|
{
|
||||||
if (model == null) return null;
|
if (model == null) return null;
|
||||||
|
|
||||||
|
@ -62,6 +64,7 @@ namespace NzbDrone.Api.EpisodeFiles
|
||||||
DateAdded = model.DateAdded,
|
DateAdded = model.DateAdded,
|
||||||
SceneName = model.SceneName,
|
SceneName = model.SceneName,
|
||||||
Quality = model.Quality,
|
Quality = model.Quality,
|
||||||
|
Language = model.Language,
|
||||||
QualityCutoffNotMet = upgradableSpecification.QualityCutoffNotMet(series.Profile.Value, model.Quality),
|
QualityCutoffNotMet = upgradableSpecification.QualityCutoffNotMet(series.Profile.Value, model.Quality),
|
||||||
MediaInfo = model.MediaInfo.ToResource(model.SceneName),
|
MediaInfo = model.MediaInfo.ToResource(model.SceneName),
|
||||||
OriginalFilePath = model.OriginalFilePath
|
OriginalFilePath = model.OriginalFilePath
|
||||||
|
|
|
@ -10,9 +10,9 @@ namespace NzbDrone.Api.Episodes
|
||||||
{
|
{
|
||||||
public EpisodeModule(ISeriesService seriesService,
|
public EpisodeModule(ISeriesService seriesService,
|
||||||
IEpisodeService episodeService,
|
IEpisodeService episodeService,
|
||||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
IUpgradableSpecification upgradableSpecification,
|
||||||
IBroadcastSignalRMessage signalRBroadcaster)
|
IBroadcastSignalRMessage signalRBroadcaster)
|
||||||
: base(episodeService, seriesService, qualityUpgradableSpecification, signalRBroadcaster)
|
: base(episodeService, seriesService, upgradableSpecification, signalRBroadcaster)
|
||||||
{
|
{
|
||||||
GetResourceAll = GetEpisodes;
|
GetResourceAll = GetEpisodes;
|
||||||
UpdateResource = SetMonitored;
|
UpdateResource = SetMonitored;
|
||||||
|
|
|
@ -19,31 +19,31 @@ namespace NzbDrone.Api.Episodes
|
||||||
{
|
{
|
||||||
protected readonly IEpisodeService _episodeService;
|
protected readonly IEpisodeService _episodeService;
|
||||||
protected readonly ISeriesService _seriesService;
|
protected readonly ISeriesService _seriesService;
|
||||||
protected readonly IQualityUpgradableSpecification _qualityUpgradableSpecification;
|
protected readonly IUpgradableSpecification _upgradableSpecification;
|
||||||
|
|
||||||
protected EpisodeModuleWithSignalR(IEpisodeService episodeService,
|
protected EpisodeModuleWithSignalR(IEpisodeService episodeService,
|
||||||
ISeriesService seriesService,
|
ISeriesService seriesService,
|
||||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
IUpgradableSpecification upgradableSpecification,
|
||||||
IBroadcastSignalRMessage signalRBroadcaster)
|
IBroadcastSignalRMessage signalRBroadcaster)
|
||||||
: base(signalRBroadcaster)
|
: base(signalRBroadcaster)
|
||||||
{
|
{
|
||||||
_episodeService = episodeService;
|
_episodeService = episodeService;
|
||||||
_seriesService = seriesService;
|
_seriesService = seriesService;
|
||||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
_upgradableSpecification = upgradableSpecification;
|
||||||
|
|
||||||
GetResourceById = GetEpisode;
|
GetResourceById = GetEpisode;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected EpisodeModuleWithSignalR(IEpisodeService episodeService,
|
protected EpisodeModuleWithSignalR(IEpisodeService episodeService,
|
||||||
ISeriesService seriesService,
|
ISeriesService seriesService,
|
||||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
IUpgradableSpecification upgradableSpecification,
|
||||||
IBroadcastSignalRMessage signalRBroadcaster,
|
IBroadcastSignalRMessage signalRBroadcaster,
|
||||||
string resource)
|
string resource)
|
||||||
: base(signalRBroadcaster, resource)
|
: base(signalRBroadcaster, resource)
|
||||||
{
|
{
|
||||||
_episodeService = episodeService;
|
_episodeService = episodeService;
|
||||||
_seriesService = seriesService;
|
_seriesService = seriesService;
|
||||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
_upgradableSpecification = upgradableSpecification;
|
||||||
|
|
||||||
GetResourceById = GetEpisode;
|
GetResourceById = GetEpisode;
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ namespace NzbDrone.Api.Episodes
|
||||||
}
|
}
|
||||||
if (includeEpisodeFile && episode.EpisodeFileId != 0)
|
if (includeEpisodeFile && episode.EpisodeFileId != 0)
|
||||||
{
|
{
|
||||||
resource.EpisodeFile = episode.EpisodeFile.Value.ToResource(series, _qualityUpgradableSpecification);
|
resource.EpisodeFile = episode.EpisodeFile.Value.ToResource(series, _upgradableSpecification);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ namespace NzbDrone.Api.Episodes
|
||||||
}
|
}
|
||||||
if (includeEpisodeFile && episodes[i].EpisodeFileId != 0)
|
if (includeEpisodeFile && episodes[i].EpisodeFileId != 0)
|
||||||
{
|
{
|
||||||
resource.EpisodeFile = episodes[i].EpisodeFile.Value.ToResource(series, _qualityUpgradableSpecification);
|
resource.EpisodeFile = episodes[i].EpisodeFile.Value.ToResource(series, _upgradableSpecification);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,15 +17,15 @@ namespace NzbDrone.Api.History
|
||||||
public class HistoryModule : SonarrRestModule<HistoryResource>
|
public class HistoryModule : SonarrRestModule<HistoryResource>
|
||||||
{
|
{
|
||||||
private readonly IHistoryService _historyService;
|
private readonly IHistoryService _historyService;
|
||||||
private readonly IQualityUpgradableSpecification _qualityUpgradableSpecification;
|
private readonly IUpgradableSpecification _upgradableSpecification;
|
||||||
private readonly IFailedDownloadService _failedDownloadService;
|
private readonly IFailedDownloadService _failedDownloadService;
|
||||||
|
|
||||||
public HistoryModule(IHistoryService historyService,
|
public HistoryModule(IHistoryService historyService,
|
||||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
IUpgradableSpecification upgradableSpecification,
|
||||||
IFailedDownloadService failedDownloadService)
|
IFailedDownloadService failedDownloadService)
|
||||||
{
|
{
|
||||||
_historyService = historyService;
|
_historyService = historyService;
|
||||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
_upgradableSpecification = upgradableSpecification;
|
||||||
_failedDownloadService = failedDownloadService;
|
_failedDownloadService = failedDownloadService;
|
||||||
GetResourcePaged = GetHistory;
|
GetResourcePaged = GetHistory;
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ namespace NzbDrone.Api.History
|
||||||
|
|
||||||
if (model.Series != null)
|
if (model.Series != null)
|
||||||
{
|
{
|
||||||
resource.QualityCutoffNotMet = _qualityUpgradableSpecification.CutoffNotMet(model.Series.Profile.Value, model.Quality);
|
resource.QualityCutoffNotMet = _upgradableSpecification.QualityCutoffNotMet(model.Series.Profile.Value, model.Quality);
|
||||||
}
|
}
|
||||||
|
|
||||||
return resource;
|
return resource;
|
||||||
|
|
|
@ -5,6 +5,7 @@ using Sonarr.Http.REST;
|
||||||
using NzbDrone.Api.Series;
|
using NzbDrone.Api.Series;
|
||||||
using NzbDrone.Core.History;
|
using NzbDrone.Core.History;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Api.History
|
namespace NzbDrone.Api.History
|
||||||
{
|
{
|
||||||
|
@ -17,6 +18,7 @@ namespace NzbDrone.Api.History
|
||||||
public bool QualityCutoffNotMet { get; set; }
|
public bool QualityCutoffNotMet { get; set; }
|
||||||
public DateTime Date { get; set; }
|
public DateTime Date { get; set; }
|
||||||
public string DownloadId { get; set; }
|
public string DownloadId { get; set; }
|
||||||
|
public Language Language { get; set; }
|
||||||
|
|
||||||
public HistoryEventType EventType { get; set; }
|
public HistoryEventType EventType { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ using Sonarr.Http.REST;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.DecisionEngine;
|
using NzbDrone.Core.DecisionEngine;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
|
@ -112,6 +112,8 @@
|
||||||
<Compile Include="Profiles\Delay\DelayProfileModule.cs" />
|
<Compile Include="Profiles\Delay\DelayProfileModule.cs" />
|
||||||
<Compile Include="Profiles\Delay\DelayProfileResource.cs" />
|
<Compile Include="Profiles\Delay\DelayProfileResource.cs" />
|
||||||
<Compile Include="ProviderModuleBase.cs" />
|
<Compile Include="ProviderModuleBase.cs" />
|
||||||
|
<Compile Include="Profiles\ProfileModule.cs" />
|
||||||
|
<Compile Include="Profiles\ProfileResource.cs" />
|
||||||
<Compile Include="Queue\QueueActionModule.cs" />
|
<Compile Include="Queue\QueueActionModule.cs" />
|
||||||
<Compile Include="RemotePathMappings\RemotePathMappingModule.cs" />
|
<Compile Include="RemotePathMappings\RemotePathMappingModule.cs" />
|
||||||
<Compile Include="RemotePathMappings\RemotePathMappingResource.cs" />
|
<Compile Include="RemotePathMappings\RemotePathMappingResource.cs" />
|
||||||
|
@ -164,8 +166,6 @@
|
||||||
<Compile Include="Profiles\Languages\LanguageModule.cs" />
|
<Compile Include="Profiles\Languages\LanguageModule.cs" />
|
||||||
<Compile Include="Profiles\Languages\LanguageResource.cs" />
|
<Compile Include="Profiles\Languages\LanguageResource.cs" />
|
||||||
<Compile Include="Profiles\LegacyProfileModule.cs" />
|
<Compile Include="Profiles\LegacyProfileModule.cs" />
|
||||||
<Compile Include="Profiles\ProfileModule.cs" />
|
|
||||||
<Compile Include="Profiles\ProfileResource.cs" />
|
|
||||||
<Compile Include="Profiles\ProfileSchemaModule.cs" />
|
<Compile Include="Profiles\ProfileSchemaModule.cs" />
|
||||||
<Compile Include="Profiles\ProfileValidation.cs" />
|
<Compile Include="Profiles\ProfileValidation.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Languages;
|
||||||
using Sonarr.Http;
|
using Sonarr.Http;
|
||||||
|
|
||||||
namespace NzbDrone.Api.Profiles.Languages
|
namespace NzbDrone.Api.Profiles.Languages
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Validation;
|
|
||||||
using Sonarr.Http;
|
using Sonarr.Http;
|
||||||
using Sonarr.Http.Mapping;
|
using Sonarr.Http.Mapping;
|
||||||
|
|
||||||
|
@ -17,7 +16,6 @@ namespace NzbDrone.Api.Profiles
|
||||||
SharedValidator.RuleFor(c => c.Name).NotEmpty();
|
SharedValidator.RuleFor(c => c.Name).NotEmpty();
|
||||||
SharedValidator.RuleFor(c => c.Cutoff).NotNull();
|
SharedValidator.RuleFor(c => c.Cutoff).NotNull();
|
||||||
SharedValidator.RuleFor(c => c.Items).MustHaveAllowedQuality();
|
SharedValidator.RuleFor(c => c.Items).MustHaveAllowedQuality();
|
||||||
SharedValidator.RuleFor(c => c.Language).ValidLanguage();
|
|
||||||
|
|
||||||
GetResourceAll = GetAll;
|
GetResourceAll = GetAll;
|
||||||
GetResourceById = GetById;
|
GetResourceById = GetById;
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Linq;
|
||||||
using Sonarr.Http.REST;
|
using Sonarr.Http.REST;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles;
|
||||||
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
|
|
||||||
namespace NzbDrone.Api.Profiles
|
namespace NzbDrone.Api.Profiles
|
||||||
|
@ -12,7 +13,6 @@ namespace NzbDrone.Api.Profiles
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public Quality Cutoff { get; set; }
|
public Quality Cutoff { get; set; }
|
||||||
public List<ProfileQualityItemResource> Items { get; set; }
|
public List<ProfileQualityItemResource> Items { get; set; }
|
||||||
public Language Language { get; set; }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ProfileQualityItemResource : RestResource
|
public class ProfileQualityItemResource : RestResource
|
||||||
|
@ -33,8 +33,7 @@ namespace NzbDrone.Api.Profiles
|
||||||
|
|
||||||
Name = model.Name,
|
Name = model.Name,
|
||||||
Cutoff = model.Cutoff,
|
Cutoff = model.Cutoff,
|
||||||
Items = model.Items.ConvertAll(ToResource),
|
Items = model.Items.ConvertAll(ToResource)
|
||||||
Language = model.Language
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,8 +58,7 @@ namespace NzbDrone.Api.Profiles
|
||||||
|
|
||||||
Name = resource.Name,
|
Name = resource.Name,
|
||||||
Cutoff = (Quality)resource.Cutoff.Id,
|
Cutoff = (Quality)resource.Cutoff.Id,
|
||||||
Items = resource.Items.ConvertAll(ToModel),
|
Items = resource.Items.ConvertAll(ToModel)
|
||||||
Language = resource.Language
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Profiles;
|
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using Sonarr.Http;
|
using Sonarr.Http;
|
||||||
using Sonarr.Http.Mapping;
|
using Sonarr.Http.Mapping;
|
||||||
|
@ -30,7 +29,6 @@ namespace NzbDrone.Api.Profiles
|
||||||
var profile = new Profile();
|
var profile = new Profile();
|
||||||
profile.Cutoff = Quality.Unknown;
|
profile.Cutoff = Quality.Unknown;
|
||||||
profile.Items = items;
|
profile.Items = items;
|
||||||
profile.Language = Language.English;
|
|
||||||
|
|
||||||
return new List<ProfileResource> { profile.ToResource() };
|
return new List<ProfileResource> { profile.ToResource() };
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,22 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Nancy;
|
using Nancy;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
using Sonarr.Http.Extensions;
|
using Sonarr.Http.Extensions;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
using Sonarr.Http.Mapping;
|
|
||||||
|
|
||||||
namespace NzbDrone.Api.Series
|
namespace NzbDrone.Api.Series
|
||||||
{
|
{
|
||||||
public class SeriesEditorModule : NzbDroneApiModule
|
public class SeriesEditorModule : NzbDroneApiModule
|
||||||
{
|
{
|
||||||
private readonly ISeriesService _seriesService;
|
private readonly ISeriesService _seriesService;
|
||||||
|
private readonly ILanguageProfileService _languageProfileService;
|
||||||
|
|
||||||
public SeriesEditorModule(ISeriesService seriesService)
|
public SeriesEditorModule(ISeriesService seriesService, ILanguageProfileService languageProfileService)
|
||||||
: base("/series/editor")
|
: base("/series/editor")
|
||||||
{
|
{
|
||||||
_seriesService = seriesService;
|
_seriesService = seriesService;
|
||||||
|
_languageProfileService = languageProfileService;
|
||||||
Put["/"] = series => SaveAll();
|
Put["/"] = series => SaveAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,9 +24,24 @@ namespace NzbDrone.Api.Series
|
||||||
{
|
{
|
||||||
var resources = Request.Body.FromJson<List<SeriesResource>>();
|
var resources = Request.Body.FromJson<List<SeriesResource>>();
|
||||||
|
|
||||||
var series = resources.Select(seriesResource => seriesResource.ToModel(_seriesService.GetSeries(seriesResource.Id))).ToList();
|
var seriesToUpdate = resources.Select(seriesResource =>
|
||||||
|
{
|
||||||
|
var series = _seriesService.GetSeries(seriesResource.Id);
|
||||||
|
var updatedSeries = seriesResource.ToModel(series);
|
||||||
|
|
||||||
return _seriesService.UpdateSeries(series, true)
|
// If the new language profile doens't exist, keep it the same.
|
||||||
|
// This could happen if a 3rd-party app uses this endpoint to update a
|
||||||
|
// series and doesn't pass the languageProfileI as well.
|
||||||
|
|
||||||
|
if (!_languageProfileService.Exists(updatedSeries.LanguageProfileId))
|
||||||
|
{
|
||||||
|
updatedSeries.LanguageProfileId = series.LanguageProfileId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return updatedSeries;
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
return _seriesService.UpdateSeries(seriesToUpdate, true)
|
||||||
.ToResource(false)
|
.ToResource(false)
|
||||||
.AsResponse(HttpStatusCode.Accepted);
|
.AsResponse(HttpStatusCode.Accepted);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ using NzbDrone.Core.Tv;
|
||||||
using NzbDrone.Core.Tv.Events;
|
using NzbDrone.Core.Tv.Events;
|
||||||
using NzbDrone.Core.Validation.Paths;
|
using NzbDrone.Core.Validation.Paths;
|
||||||
using NzbDrone.Core.DataAugmentation.Scene;
|
using NzbDrone.Core.DataAugmentation.Scene;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
using NzbDrone.SignalR;
|
using NzbDrone.SignalR;
|
||||||
using Sonarr.Http;
|
using Sonarr.Http;
|
||||||
|
@ -35,6 +36,7 @@ namespace NzbDrone.Api.Series
|
||||||
private readonly ISeriesStatisticsService _seriesStatisticsService;
|
private readonly ISeriesStatisticsService _seriesStatisticsService;
|
||||||
private readonly ISceneMappingService _sceneMappingService;
|
private readonly ISceneMappingService _sceneMappingService;
|
||||||
private readonly IMapCoversToLocal _coverMapper;
|
private readonly IMapCoversToLocal _coverMapper;
|
||||||
|
private readonly ILanguageProfileService _languageProfileService;
|
||||||
|
|
||||||
public SeriesModule(IBroadcastSignalRMessage signalRBroadcaster,
|
public SeriesModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||||
ISeriesService seriesService,
|
ISeriesService seriesService,
|
||||||
|
@ -42,13 +44,15 @@ namespace NzbDrone.Api.Series
|
||||||
ISeriesStatisticsService seriesStatisticsService,
|
ISeriesStatisticsService seriesStatisticsService,
|
||||||
ISceneMappingService sceneMappingService,
|
ISceneMappingService sceneMappingService,
|
||||||
IMapCoversToLocal coverMapper,
|
IMapCoversToLocal coverMapper,
|
||||||
|
ILanguageProfileService languageProfileService,
|
||||||
RootFolderValidator rootFolderValidator,
|
RootFolderValidator rootFolderValidator,
|
||||||
SeriesPathValidator seriesPathValidator,
|
SeriesPathValidator seriesPathValidator,
|
||||||
SeriesExistsValidator seriesExistsValidator,
|
SeriesExistsValidator seriesExistsValidator,
|
||||||
DroneFactoryValidator droneFactoryValidator,
|
DroneFactoryValidator droneFactoryValidator,
|
||||||
SeriesAncestorValidator seriesAncestorValidator,
|
SeriesAncestorValidator seriesAncestorValidator,
|
||||||
SystemFolderValidator systemFolderValidator,
|
SystemFolderValidator systemFolderValidator,
|
||||||
ProfileExistsValidator profileExistsValidator
|
ProfileExistsValidator profileExistsValidator,
|
||||||
|
LanguageProfileExistsValidator languageProfileExistsValidator
|
||||||
)
|
)
|
||||||
: base(signalRBroadcaster)
|
: base(signalRBroadcaster)
|
||||||
{
|
{
|
||||||
|
@ -58,6 +62,7 @@ namespace NzbDrone.Api.Series
|
||||||
_sceneMappingService = sceneMappingService;
|
_sceneMappingService = sceneMappingService;
|
||||||
|
|
||||||
_coverMapper = coverMapper;
|
_coverMapper = coverMapper;
|
||||||
|
_languageProfileService = languageProfileService;
|
||||||
|
|
||||||
GetResourceAll = AllSeries;
|
GetResourceAll = AllSeries;
|
||||||
GetResourceById = GetSeries;
|
GetResourceById = GetSeries;
|
||||||
|
@ -66,6 +71,7 @@ namespace NzbDrone.Api.Series
|
||||||
DeleteResource = DeleteSeries;
|
DeleteResource = DeleteSeries;
|
||||||
|
|
||||||
SharedValidator.RuleFor(s => s.ProfileId).ValidId();
|
SharedValidator.RuleFor(s => s.ProfileId).ValidId();
|
||||||
|
SharedValidator.RuleFor(s => s.LanguageProfileId);
|
||||||
|
|
||||||
SharedValidator.RuleFor(s => s.Path)
|
SharedValidator.RuleFor(s => s.Path)
|
||||||
.Cascade(CascadeMode.StopOnFirstFailure)
|
.Cascade(CascadeMode.StopOnFirstFailure)
|
||||||
|
@ -82,8 +88,12 @@ namespace NzbDrone.Api.Series
|
||||||
PostValidator.RuleFor(s => s.Path).IsValidPath().When(s => s.RootFolderPath.IsNullOrWhiteSpace());
|
PostValidator.RuleFor(s => s.Path).IsValidPath().When(s => s.RootFolderPath.IsNullOrWhiteSpace());
|
||||||
PostValidator.RuleFor(s => s.RootFolderPath).IsValidPath().When(s => s.Path.IsNullOrWhiteSpace());
|
PostValidator.RuleFor(s => s.RootFolderPath).IsValidPath().When(s => s.Path.IsNullOrWhiteSpace());
|
||||||
PostValidator.RuleFor(s => s.TvdbId).GreaterThan(0).SetValidator(seriesExistsValidator);
|
PostValidator.RuleFor(s => s.TvdbId).GreaterThan(0).SetValidator(seriesExistsValidator);
|
||||||
|
PostValidator.RuleFor(s => s.LanguageProfileId).SetValidator(languageProfileExistsValidator).When(s => s.LanguageProfileId != 0);
|
||||||
|
|
||||||
PutValidator.RuleFor(s => s.Path).IsValidPath();
|
PutValidator.RuleFor(s => s.Path).IsValidPath();
|
||||||
|
|
||||||
|
// Ensure any editing has a valid LanguageProfile
|
||||||
|
PutValidator.RuleFor(s => s.LanguageProfileId).SetValidator(languageProfileExistsValidator);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SeriesResource GetSeries(int id)
|
private SeriesResource GetSeries(int id)
|
||||||
|
@ -111,6 +121,12 @@ namespace NzbDrone.Api.Series
|
||||||
{
|
{
|
||||||
var model = seriesResource.ToModel();
|
var model = seriesResource.ToModel();
|
||||||
|
|
||||||
|
// Set a default LanguageProfileId to maintain backwards compatibility with apps using the v2 API
|
||||||
|
if (model.LanguageProfileId == 0 || !_languageProfileService.Exists(model.LanguageProfileId))
|
||||||
|
{
|
||||||
|
model.LanguageProfileId = _languageProfileService.All().First().Id;
|
||||||
|
}
|
||||||
|
|
||||||
return _addSeriesService.AddSeries(model).Id;
|
return _addSeriesService.AddSeries(model).Id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@ namespace NzbDrone.Api.Series
|
||||||
//View & Edit
|
//View & Edit
|
||||||
public string Path { get; set; }
|
public string Path { get; set; }
|
||||||
public int ProfileId { get; set; }
|
public int ProfileId { get; set; }
|
||||||
|
public int LanguageProfileId { get; set; }
|
||||||
|
|
||||||
//Editing Only
|
//Editing Only
|
||||||
public bool SeasonFolder { get; set; }
|
public bool SeasonFolder { get; set; }
|
||||||
|
@ -124,6 +125,7 @@ namespace NzbDrone.Api.Series
|
||||||
|
|
||||||
Path = model.Path,
|
Path = model.Path,
|
||||||
ProfileId = model.ProfileId,
|
ProfileId = model.ProfileId,
|
||||||
|
LanguageProfileId = model.LanguageProfileId,
|
||||||
|
|
||||||
SeasonFolder = model.SeasonFolder,
|
SeasonFolder = model.SeasonFolder,
|
||||||
Monitored = model.Monitored,
|
Monitored = model.Monitored,
|
||||||
|
@ -178,6 +180,7 @@ namespace NzbDrone.Api.Series
|
||||||
|
|
||||||
Path = resource.Path,
|
Path = resource.Path,
|
||||||
ProfileId = resource.ProfileId,
|
ProfileId = resource.ProfileId,
|
||||||
|
LanguageProfileId = resource.LanguageProfileId,
|
||||||
|
|
||||||
SeasonFolder = resource.SeasonFolder,
|
SeasonFolder = resource.SeasonFolder,
|
||||||
Monitored = resource.Monitored,
|
Monitored = resource.Monitored,
|
||||||
|
|
|
@ -15,9 +15,9 @@ namespace NzbDrone.Api.Wanted
|
||||||
public CutoffModule(IEpisodeCutoffService episodeCutoffService,
|
public CutoffModule(IEpisodeCutoffService episodeCutoffService,
|
||||||
IEpisodeService episodeService,
|
IEpisodeService episodeService,
|
||||||
ISeriesService seriesService,
|
ISeriesService seriesService,
|
||||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
IUpgradableSpecification upgradableSpecification,
|
||||||
IBroadcastSignalRMessage signalRBroadcaster)
|
IBroadcastSignalRMessage signalRBroadcaster)
|
||||||
: base(episodeService, seriesService, qualityUpgradableSpecification, signalRBroadcaster, "wanted/cutoff")
|
: base(episodeService, seriesService, upgradableSpecification, signalRBroadcaster, "wanted/cutoff")
|
||||||
{
|
{
|
||||||
_episodeCutoffService = episodeCutoffService;
|
_episodeCutoffService = episodeCutoffService;
|
||||||
GetResourcePaged = GetCutoffUnmetEpisodes;
|
GetResourcePaged = GetCutoffUnmetEpisodes;
|
||||||
|
|
|
@ -12,9 +12,9 @@ namespace NzbDrone.Api.Wanted
|
||||||
{
|
{
|
||||||
public MissingModule(IEpisodeService episodeService,
|
public MissingModule(IEpisodeService episodeService,
|
||||||
ISeriesService seriesService,
|
ISeriesService seriesService,
|
||||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
IUpgradableSpecification upgradableSpecification,
|
||||||
IBroadcastSignalRMessage signalRBroadcaster)
|
IBroadcastSignalRMessage signalRBroadcaster)
|
||||||
: base(episodeService, seriesService, qualityUpgradableSpecification, signalRBroadcaster, "wanted/missing")
|
: base(episodeService, seriesService, upgradableSpecification, signalRBroadcaster, "wanted/missing")
|
||||||
{
|
{
|
||||||
GetResourcePaged = GetMissingEpisodes;
|
GetResourcePaged = GetMissingEpisodes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.Datastore
|
namespace NzbDrone.Core.Test.Datastore
|
||||||
{
|
{
|
||||||
|
@ -17,6 +18,7 @@ namespace NzbDrone.Core.Test.Datastore
|
||||||
{
|
{
|
||||||
var episodeFile = Builder<EpisodeFile>.CreateNew()
|
var episodeFile = Builder<EpisodeFile>.CreateNew()
|
||||||
.With(c => c.Quality = new QualityModel())
|
.With(c => c.Quality = new QualityModel())
|
||||||
|
.With(c => c.Language = Language.English)
|
||||||
.BuildNew();
|
.BuildNew();
|
||||||
|
|
||||||
Db.Insert(episodeFile);
|
Db.Insert(episodeFile);
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
using FizzWare.NBuilder;
|
using FizzWare.NBuilder;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using System.Linq;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
|
using NzbDrone.Core.Test.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.Datastore
|
namespace NzbDrone.Core.Test.Datastore
|
||||||
{
|
{
|
||||||
|
@ -20,15 +24,23 @@ namespace NzbDrone.Core.Test.Datastore
|
||||||
{
|
{
|
||||||
Name = "Test",
|
Name = "Test",
|
||||||
Cutoff = Quality.WEBDL720p,
|
Cutoff = Quality.WEBDL720p,
|
||||||
Items = Qualities.QualityFixture.GetDefaultQualities()
|
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var languageProfile = new LanguageProfile
|
||||||
|
{
|
||||||
|
Name = "Test",
|
||||||
|
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||||
|
Cutoff = Language.English
|
||||||
|
};
|
||||||
|
|
||||||
profile = Db.Insert(profile);
|
profile = Db.Insert(profile);
|
||||||
|
languageProfile = Db.Insert(languageProfile);
|
||||||
|
|
||||||
var series = Builder<Series>.CreateListOfSize(1)
|
var series = Builder<Series>.CreateListOfSize(1)
|
||||||
.All()
|
.All()
|
||||||
.With(v => v.ProfileId = profile.Id)
|
.With(v => v.ProfileId = profile.Id)
|
||||||
|
.With(v => v.LanguageProfileId = languageProfile.Id)
|
||||||
.BuildListOfNew();
|
.BuildListOfNew();
|
||||||
|
|
||||||
Db.InsertMany(series);
|
Db.InsertMany(series);
|
||||||
|
@ -65,6 +77,7 @@ namespace NzbDrone.Core.Test.Datastore
|
||||||
{
|
{
|
||||||
Assert.IsNotNull(episode.Series);
|
Assert.IsNotNull(episode.Series);
|
||||||
Assert.IsFalse(episode.Series.Profile.IsLoaded);
|
Assert.IsFalse(episode.Series.Profile.IsLoaded);
|
||||||
|
Assert.IsFalse(episode.Series.LanguageProfile.IsLoaded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,8 +113,27 @@ namespace NzbDrone.Core.Test.Datastore
|
||||||
{
|
{
|
||||||
Assert.IsNotNull(episode.Series);
|
Assert.IsNotNull(episode.Series);
|
||||||
Assert.IsTrue(episode.Series.Profile.IsLoaded);
|
Assert.IsTrue(episode.Series.Profile.IsLoaded);
|
||||||
|
Assert.IsFalse(episode.Series.LanguageProfile.IsLoaded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_explicit_load_languageprofile_if_joined()
|
||||||
|
{
|
||||||
|
var db = Mocker.Resolve<IDatabase>();
|
||||||
|
var DataMapper = db.GetDataMapper();
|
||||||
|
|
||||||
|
var episodes = DataMapper.Query<Episode>()
|
||||||
|
.Join<Episode, Series>(Marr.Data.QGen.JoinType.Inner, v => v.Series, (l, r) => l.SeriesId == r.Id)
|
||||||
|
.Join<Series, LanguageProfile>(Marr.Data.QGen.JoinType.Inner, v => v.LanguageProfile, (l, r) => l.ProfileId == r.Id)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
foreach (var episode in episodes)
|
||||||
|
{
|
||||||
|
Assert.IsNotNull(episode.Series);
|
||||||
|
Assert.IsFalse(episode.Series.Profile.IsLoaded);
|
||||||
|
Assert.IsTrue(episode.Series.LanguageProfile.IsLoaded);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -55,6 +55,14 @@ namespace NzbDrone.Core.Test.Datastore.Migration
|
||||||
{
|
{
|
||||||
var db = WithMigrationTestDb(c =>
|
var db = WithMigrationTestDb(c =>
|
||||||
{
|
{
|
||||||
|
c.Insert.IntoTable("Profiles").Row(new
|
||||||
|
{
|
||||||
|
Name = "Profile1",
|
||||||
|
CutOff = 0,
|
||||||
|
Items = "[]",
|
||||||
|
Language = 1
|
||||||
|
});
|
||||||
|
|
||||||
c.Insert.IntoTable("Series").Row(new
|
c.Insert.IntoTable("Series").Row(new
|
||||||
{
|
{
|
||||||
Tvdbid = 1,
|
Tvdbid = 1,
|
||||||
|
@ -69,7 +77,8 @@ namespace NzbDrone.Core.Test.Datastore.Migration
|
||||||
Runtime= 0,
|
Runtime= 0,
|
||||||
SeriesType=0,
|
SeriesType=0,
|
||||||
UseSceneNumbering =0,
|
UseSceneNumbering =0,
|
||||||
LastInfoSync = "2000-01-01 00:00:00"
|
LastInfoSync = "2000-01-01 00:00:00",
|
||||||
|
ProfileId = 1
|
||||||
});
|
});
|
||||||
|
|
||||||
c.Insert.IntoTable("Series").Row(new
|
c.Insert.IntoTable("Series").Row(new
|
||||||
|
@ -86,7 +95,8 @@ namespace NzbDrone.Core.Test.Datastore.Migration
|
||||||
Runtime = 0,
|
Runtime = 0,
|
||||||
SeriesType = 0,
|
SeriesType = 0,
|
||||||
UseSceneNumbering = 0,
|
UseSceneNumbering = 0,
|
||||||
LastInfoSync = "2000-01-01 00:00:00"
|
LastInfoSync = "2000-01-01 00:00:00",
|
||||||
|
ProfileId = 1
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,14 @@ namespace NzbDrone.Core.Test.Datastore.Migration
|
||||||
{
|
{
|
||||||
var db = WithMigrationTestDb(c =>
|
var db = WithMigrationTestDb(c =>
|
||||||
{
|
{
|
||||||
|
c.Insert.IntoTable("Profiles").Row(new
|
||||||
|
{
|
||||||
|
Name = "Profile1",
|
||||||
|
CutOff = 0,
|
||||||
|
Items = "[]",
|
||||||
|
Language = 1
|
||||||
|
});
|
||||||
|
|
||||||
c.Insert.IntoTable("Series").Row(new
|
c.Insert.IntoTable("Series").Row(new
|
||||||
{
|
{
|
||||||
Tvdbid = 1,
|
Tvdbid = 1,
|
||||||
|
@ -28,7 +36,8 @@ namespace NzbDrone.Core.Test.Datastore.Migration
|
||||||
Runtime = 0,
|
Runtime = 0,
|
||||||
SeriesType = 0,
|
SeriesType = 0,
|
||||||
UseSceneNumbering = 0,
|
UseSceneNumbering = 0,
|
||||||
LastInfoSync = "2000-01-01 00:00:00"
|
LastInfoSync = "2000-01-01 00:00:00",
|
||||||
|
ProfileId = 1
|
||||||
});
|
});
|
||||||
|
|
||||||
c.Insert.IntoTable("Tags").Row(new
|
c.Insert.IntoTable("Tags").Row(new
|
||||||
|
@ -46,6 +55,14 @@ namespace NzbDrone.Core.Test.Datastore.Migration
|
||||||
{
|
{
|
||||||
var db = WithMigrationTestDb(c =>
|
var db = WithMigrationTestDb(c =>
|
||||||
{
|
{
|
||||||
|
c.Insert.IntoTable("Profiles").Row(new
|
||||||
|
{
|
||||||
|
Name = "Profile1",
|
||||||
|
CutOff = 0,
|
||||||
|
Items = "[]",
|
||||||
|
Language = 1
|
||||||
|
});
|
||||||
|
|
||||||
c.Insert.IntoTable("Series").Row(new
|
c.Insert.IntoTable("Series").Row(new
|
||||||
{
|
{
|
||||||
Tvdbid = 1,
|
Tvdbid = 1,
|
||||||
|
@ -61,7 +78,8 @@ namespace NzbDrone.Core.Test.Datastore.Migration
|
||||||
SeriesType = 0,
|
SeriesType = 0,
|
||||||
UseSceneNumbering = 0,
|
UseSceneNumbering = 0,
|
||||||
LastInfoSync = "2000-01-01 00:00:00",
|
LastInfoSync = "2000-01-01 00:00:00",
|
||||||
Tags = "[]"
|
Tags = "[]",
|
||||||
|
ProfileId = 1
|
||||||
});
|
});
|
||||||
|
|
||||||
c.Insert.IntoTable("Tags").Row(new
|
c.Insert.IntoTable("Tags").Row(new
|
||||||
|
@ -113,6 +131,14 @@ namespace NzbDrone.Core.Test.Datastore.Migration
|
||||||
{
|
{
|
||||||
var db = WithMigrationTestDb(c =>
|
var db = WithMigrationTestDb(c =>
|
||||||
{
|
{
|
||||||
|
c.Insert.IntoTable("Profiles").Row(new
|
||||||
|
{
|
||||||
|
Name = "Profile1",
|
||||||
|
CutOff = 0,
|
||||||
|
Items = "[]",
|
||||||
|
Language = 1
|
||||||
|
});
|
||||||
|
|
||||||
c.Insert.IntoTable("Series").Row(new
|
c.Insert.IntoTable("Series").Row(new
|
||||||
{
|
{
|
||||||
Tvdbid = 1,
|
Tvdbid = 1,
|
||||||
|
@ -128,7 +154,8 @@ namespace NzbDrone.Core.Test.Datastore.Migration
|
||||||
SeriesType = 0,
|
SeriesType = 0,
|
||||||
UseSceneNumbering = 0,
|
UseSceneNumbering = 0,
|
||||||
LastInfoSync = "2000-01-01 00:00:00",
|
LastInfoSync = "2000-01-01 00:00:00",
|
||||||
Tags = "[2]"
|
Tags = "[2]",
|
||||||
|
ProfileId = 1
|
||||||
});
|
});
|
||||||
|
|
||||||
c.Insert.IntoTable("Tags").Row(new
|
c.Insert.IntoTable("Tags").Row(new
|
||||||
|
@ -151,6 +178,14 @@ namespace NzbDrone.Core.Test.Datastore.Migration
|
||||||
{
|
{
|
||||||
var db = WithMigrationTestDb(c =>
|
var db = WithMigrationTestDb(c =>
|
||||||
{
|
{
|
||||||
|
c.Insert.IntoTable("Profiles").Row(new
|
||||||
|
{
|
||||||
|
Name = "Profile1",
|
||||||
|
CutOff = 0,
|
||||||
|
Items = "[]",
|
||||||
|
Language = 1
|
||||||
|
});
|
||||||
|
|
||||||
c.Insert.IntoTable("Series").Row(new
|
c.Insert.IntoTable("Series").Row(new
|
||||||
{
|
{
|
||||||
Tvdbid = 1,
|
Tvdbid = 1,
|
||||||
|
@ -166,7 +201,8 @@ namespace NzbDrone.Core.Test.Datastore.Migration
|
||||||
SeriesType = 0,
|
SeriesType = 0,
|
||||||
UseSceneNumbering = 0,
|
UseSceneNumbering = 0,
|
||||||
LastInfoSync = "2000-01-01 00:00:00",
|
LastInfoSync = "2000-01-01 00:00:00",
|
||||||
Tags = "[2]"
|
Tags = "[2]",
|
||||||
|
ProfileId = 1
|
||||||
});
|
});
|
||||||
|
|
||||||
c.Insert.IntoTable("Series").Row(new
|
c.Insert.IntoTable("Series").Row(new
|
||||||
|
@ -184,7 +220,8 @@ namespace NzbDrone.Core.Test.Datastore.Migration
|
||||||
SeriesType = 0,
|
SeriesType = 0,
|
||||||
UseSceneNumbering = 0,
|
UseSceneNumbering = 0,
|
||||||
LastInfoSync = "2000-01-01 00:00:00",
|
LastInfoSync = "2000-01-01 00:00:00",
|
||||||
Tags = "[]"
|
Tags = "[]",
|
||||||
|
ProfileId = 1
|
||||||
});
|
});
|
||||||
|
|
||||||
c.Insert.IntoTable("Tags").Row(new
|
c.Insert.IntoTable("Tags").Row(new
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.Datastore.Migration;
|
using NzbDrone.Core.Datastore.Migration;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
|
||||||
|
@ -45,7 +46,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
|
||||||
RelativePath = "Series.Title.S01E01.en.srt",
|
RelativePath = "Series.Title.S01E01.en.srt",
|
||||||
Added = "2016-05-30 20:23:02.3725923",
|
Added = "2016-05-30 20:23:02.3725923",
|
||||||
LastUpdated = "2016-05-30 20:23:02.3725923",
|
LastUpdated = "2016-05-30 20:23:02.3725923",
|
||||||
Language = Language.English,
|
Language = (int)Language.English,
|
||||||
Extension = "en.srt"
|
Extension = "en.srt"
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
Mocker.Resolve<QualityUpgradableSpecification>();
|
Mocker.Resolve<UpgradableSpecification>();
|
||||||
_subject = Mocker.Resolve<AnimeVersionUpgradeSpecification>();
|
_subject = Mocker.Resolve<AnimeVersionUpgradeSpecification>();
|
||||||
|
|
||||||
_episodeFile = new EpisodeFile
|
_episodeFile = new EpisodeFile
|
||||||
|
|
|
@ -1,50 +1,223 @@
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.DecisionEngine;
|
using NzbDrone.Core.DecisionEngine;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
|
using NzbDrone.Core.Test.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.DecisionEngineTests
|
namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class CutoffSpecificationFixture : CoreTest<QualityUpgradableSpecification>
|
public class CutoffSpecificationFixture : CoreTest<UpgradableSpecification>
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_true_if_current_episode_is_less_than_cutoff()
|
public void should_return_true_if_current_episode_is_less_than_cutoff()
|
||||||
{
|
{
|
||||||
Subject.CutoffNotMet(new Profile { Cutoff = Quality.Bluray1080p, Items = Qualities.QualityFixture.GetDefaultQualities() },
|
Subject.CutoffNotMet(
|
||||||
new QualityModel(Quality.DVD, new Revision(version: 2))).Should().BeTrue();
|
new Profile
|
||||||
|
{
|
||||||
|
Cutoff = Quality.Bluray1080p,
|
||||||
|
Items = Qualities.QualityFixture.GetDefaultQualities()
|
||||||
|
},
|
||||||
|
new LanguageProfile
|
||||||
|
{
|
||||||
|
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||||
|
Cutoff = Language.English
|
||||||
|
},
|
||||||
|
new QualityModel(Quality.DVD, new Revision(version: 2)), Language.English).Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_false_if_current_episode_is_equal_to_cutoff()
|
public void should_return_false_if_current_episode_is_equal_to_cutoff()
|
||||||
{
|
{
|
||||||
Subject.CutoffNotMet(new Profile { Cutoff = Quality.HDTV720p, Items = Qualities.QualityFixture.GetDefaultQualities() },
|
Subject.CutoffNotMet(
|
||||||
new QualityModel(Quality.HDTV720p, new Revision(version: 2))).Should().BeFalse();
|
new Profile
|
||||||
|
{
|
||||||
|
Cutoff = Quality.HDTV720p,
|
||||||
|
Items = Qualities.QualityFixture.GetDefaultQualities()
|
||||||
|
},
|
||||||
|
new LanguageProfile
|
||||||
|
{
|
||||||
|
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||||
|
Cutoff = Language.English
|
||||||
|
},
|
||||||
|
new QualityModel(Quality.HDTV720p, new Revision(version: 2)), Language.English).Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_false_if_current_episode_is_greater_than_cutoff()
|
public void should_return_false_if_current_episode_is_greater_than_cutoff()
|
||||||
{
|
{
|
||||||
Subject.CutoffNotMet(new Profile { Cutoff = Quality.HDTV720p, Items = Qualities.QualityFixture.GetDefaultQualities() },
|
Subject.CutoffNotMet(
|
||||||
new QualityModel(Quality.Bluray1080p, new Revision(version: 2))).Should().BeFalse();
|
new Profile
|
||||||
|
{
|
||||||
|
Cutoff = Quality.HDTV720p,
|
||||||
|
Items = Qualities.QualityFixture.GetDefaultQualities()
|
||||||
|
},
|
||||||
|
new LanguageProfile
|
||||||
|
{
|
||||||
|
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||||
|
Cutoff = Language.English
|
||||||
|
},
|
||||||
|
new QualityModel(Quality.Bluray1080p, new Revision(version: 2)), Language.English).Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_true_when_new_episode_is_proper_but_existing_is_not()
|
public void should_return_true_when_new_episode_is_proper_but_existing_is_not()
|
||||||
{
|
{
|
||||||
Subject.CutoffNotMet(new Profile { Cutoff = Quality.HDTV720p, Items = Qualities.QualityFixture.GetDefaultQualities() },
|
Subject.CutoffNotMet(
|
||||||
|
new Profile
|
||||||
|
{
|
||||||
|
Cutoff = Quality.HDTV720p,
|
||||||
|
Items = Qualities.QualityFixture.GetDefaultQualities()
|
||||||
|
},
|
||||||
|
new LanguageProfile
|
||||||
|
{
|
||||||
|
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||||
|
Cutoff = Language.English
|
||||||
|
},
|
||||||
new QualityModel(Quality.HDTV720p, new Revision(version: 1)),
|
new QualityModel(Quality.HDTV720p, new Revision(version: 1)),
|
||||||
|
Language.English,
|
||||||
new QualityModel(Quality.HDTV720p, new Revision(version: 2))).Should().BeTrue();
|
new QualityModel(Quality.HDTV720p, new Revision(version: 2))).Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_false_if_cutoff_is_met_and_quality_is_higher()
|
public void should_return_false_if_cutoff_is_met_and_quality_is_higher()
|
||||||
{
|
{
|
||||||
Subject.CutoffNotMet(new Profile { Cutoff = Quality.HDTV720p, Items = Qualities.QualityFixture.GetDefaultQualities() },
|
Subject.CutoffNotMet(
|
||||||
|
new Profile
|
||||||
|
{
|
||||||
|
Cutoff = Quality.HDTV720p,
|
||||||
|
Items = Qualities.QualityFixture.GetDefaultQualities()
|
||||||
|
},
|
||||||
|
new LanguageProfile
|
||||||
|
{
|
||||||
|
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||||
|
Cutoff = Language.English
|
||||||
|
},
|
||||||
new QualityModel(Quality.HDTV720p, new Revision(version: 2)),
|
new QualityModel(Quality.HDTV720p, new Revision(version: 2)),
|
||||||
|
Language.English,
|
||||||
new QualityModel(Quality.Bluray1080p, new Revision(version: 2))).Should().BeFalse();
|
new QualityModel(Quality.Bluray1080p, new Revision(version: 2))).Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_true_if_quality_cutoff_is_met_and_quality_is_higher_but_language_is_not_met()
|
||||||
|
{
|
||||||
|
|
||||||
|
Profile _profile = new Profile
|
||||||
|
{
|
||||||
|
Cutoff = Quality.HDTV720p,
|
||||||
|
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||||
|
};
|
||||||
|
|
||||||
|
LanguageProfile _langProfile = new LanguageProfile
|
||||||
|
{
|
||||||
|
Cutoff = Language.Spanish,
|
||||||
|
Languages = LanguageFixture.GetDefaultLanguages()
|
||||||
|
};
|
||||||
|
|
||||||
|
Subject.CutoffNotMet(_profile,
|
||||||
|
_langProfile,
|
||||||
|
new QualityModel(Quality.HDTV720p, new Revision(version: 2)),
|
||||||
|
Language.English,
|
||||||
|
new QualityModel(Quality.Bluray1080p, new Revision(version: 2))).Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_false_if_cutoff_is_met_and_quality_is_higher_and_language_is_met()
|
||||||
|
{
|
||||||
|
|
||||||
|
Profile _profile = new Profile
|
||||||
|
{
|
||||||
|
Cutoff = Quality.HDTV720p,
|
||||||
|
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||||
|
};
|
||||||
|
|
||||||
|
LanguageProfile _langProfile = new LanguageProfile
|
||||||
|
{
|
||||||
|
Cutoff = Language.Spanish,
|
||||||
|
Languages = LanguageFixture.GetDefaultLanguages()
|
||||||
|
};
|
||||||
|
|
||||||
|
Subject.CutoffNotMet(
|
||||||
|
_profile,
|
||||||
|
_langProfile,
|
||||||
|
new QualityModel(Quality.HDTV720p, new Revision(version: 2)),
|
||||||
|
Language.Spanish,
|
||||||
|
new QualityModel(Quality.Bluray1080p, new Revision(version: 2))).Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_false_if_cutoff_is_met_and_quality_is_higher_and_language_is_higher()
|
||||||
|
{
|
||||||
|
|
||||||
|
Profile _profile = new Profile
|
||||||
|
{
|
||||||
|
Cutoff = Quality.HDTV720p,
|
||||||
|
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||||
|
};
|
||||||
|
|
||||||
|
LanguageProfile _langProfile = new LanguageProfile
|
||||||
|
{
|
||||||
|
Cutoff = Language.Spanish,
|
||||||
|
Languages = LanguageFixture.GetDefaultLanguages()
|
||||||
|
};
|
||||||
|
|
||||||
|
Subject.CutoffNotMet(
|
||||||
|
_profile,
|
||||||
|
_langProfile,
|
||||||
|
new QualityModel(Quality.HDTV720p, new Revision(version: 2)),
|
||||||
|
Language.French,
|
||||||
|
new QualityModel(Quality.Bluray1080p, new Revision(version: 2))).Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_true_if_cutoff_is_not_met_and_new_quality_is_higher_and_language_is_higher()
|
||||||
|
{
|
||||||
|
|
||||||
|
Profile _profile = new Profile
|
||||||
|
{
|
||||||
|
Cutoff = Quality.HDTV720p,
|
||||||
|
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||||
|
};
|
||||||
|
|
||||||
|
LanguageProfile _langProfile = new LanguageProfile
|
||||||
|
{
|
||||||
|
Cutoff = Language.Spanish,
|
||||||
|
Languages = LanguageFixture.GetDefaultLanguages()
|
||||||
|
};
|
||||||
|
|
||||||
|
Subject.CutoffNotMet(
|
||||||
|
_profile,
|
||||||
|
_langProfile,
|
||||||
|
new QualityModel(Quality.SDTV, new Revision(version: 2)),
|
||||||
|
Language.French,
|
||||||
|
new QualityModel(Quality.Bluray1080p, new Revision(version: 2))).Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_true_if_cutoff_is_not_met_and_language_is_higher()
|
||||||
|
{
|
||||||
|
|
||||||
|
Profile _profile = new Profile
|
||||||
|
{
|
||||||
|
Cutoff = Quality.HDTV720p,
|
||||||
|
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||||
|
};
|
||||||
|
|
||||||
|
LanguageProfile _langProfile = new LanguageProfile
|
||||||
|
{
|
||||||
|
Cutoff = Language.Spanish,
|
||||||
|
Languages = LanguageFixture.GetDefaultLanguages()
|
||||||
|
};
|
||||||
|
|
||||||
|
Subject.CutoffNotMet(
|
||||||
|
_profile,
|
||||||
|
_langProfile,
|
||||||
|
new QualityModel(Quality.SDTV, new Revision(version: 2)),
|
||||||
|
Language.French).Should().BeTrue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,12 @@
|
||||||
using Marr.Data;
|
using Marr.Data;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Languages;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Profiles;
|
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
|
using NzbDrone.Core.Test.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.DecisionEngineTests
|
namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
{
|
{
|
||||||
|
@ -19,6 +20,12 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
|
LanguageProfile _profile = new LazyLoaded<LanguageProfile> (new LanguageProfile
|
||||||
|
{
|
||||||
|
Languages = LanguageFixture.GetDefaultLanguages(Language.English, Language.Spanish),
|
||||||
|
Cutoff = Language.Spanish
|
||||||
|
});
|
||||||
|
|
||||||
_remoteEpisode = new RemoteEpisode
|
_remoteEpisode = new RemoteEpisode
|
||||||
{
|
{
|
||||||
ParsedEpisodeInfo = new ParsedEpisodeInfo
|
ParsedEpisodeInfo = new ParsedEpisodeInfo
|
||||||
|
@ -27,10 +34,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
},
|
},
|
||||||
Series = new Series
|
Series = new Series
|
||||||
{
|
{
|
||||||
Profile = new LazyLoaded<Profile>(new Profile
|
LanguageProfile = _profile
|
||||||
{
|
|
||||||
Language = Language.English
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -40,6 +44,16 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
_remoteEpisode.ParsedEpisodeInfo.Language = Language.English;
|
_remoteEpisode.ParsedEpisodeInfo.Language = Language.English;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void WithSpanishRelease()
|
||||||
|
{
|
||||||
|
_remoteEpisode.ParsedEpisodeInfo.Language = Language.Spanish;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void WithFrenchRelease()
|
||||||
|
{
|
||||||
|
_remoteEpisode.ParsedEpisodeInfo.Language = Language.French;
|
||||||
|
}
|
||||||
|
|
||||||
private void WithGermanRelease()
|
private void WithGermanRelease()
|
||||||
{
|
{
|
||||||
_remoteEpisode.ParsedEpisodeInfo.Language = Language.German;
|
_remoteEpisode.ParsedEpisodeInfo.Language = Language.German;
|
||||||
|
@ -60,5 +74,23 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
|
|
||||||
Mocker.Resolve<LanguageSpecification>().IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
|
Mocker.Resolve<LanguageSpecification>().IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_false_if_language_is_french()
|
||||||
|
{
|
||||||
|
WithFrenchRelease();
|
||||||
|
|
||||||
|
Mocker.Resolve<LanguageSpecification>().IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_true_if_language_is_spanish()
|
||||||
|
{
|
||||||
|
WithSpanishRelease();
|
||||||
|
|
||||||
|
Mocker.Resolve<LanguageSpecification>().IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,7 +5,7 @@ using Moq;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
using NzbDrone.Core.Profiles.Delay;
|
using NzbDrone.Core.Profiles.Delay;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.DecisionEngine;
|
using NzbDrone.Core.DecisionEngine;
|
||||||
|
@ -14,6 +14,9 @@ using FluentAssertions;
|
||||||
using FizzWare.NBuilder;
|
using FizzWare.NBuilder;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
|
using NzbDrone.Core.Test.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.DecisionEngineTests
|
namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
{
|
{
|
||||||
|
@ -34,11 +37,12 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
.Build();
|
.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private RemoteEpisode GivenRemoteEpisode(List<Episode> episodes, QualityModel quality, int age = 0, long size = 0, DownloadProtocol downloadProtocol = DownloadProtocol.Usenet)
|
private RemoteEpisode GivenRemoteEpisode(List<Episode> episodes, QualityModel quality, Language language, int age = 0, long size = 0, DownloadProtocol downloadProtocol = DownloadProtocol.Usenet)
|
||||||
{
|
{
|
||||||
var remoteEpisode = new RemoteEpisode();
|
var remoteEpisode = new RemoteEpisode();
|
||||||
remoteEpisode.ParsedEpisodeInfo = new ParsedEpisodeInfo();
|
remoteEpisode.ParsedEpisodeInfo = new ParsedEpisodeInfo();
|
||||||
remoteEpisode.ParsedEpisodeInfo.Quality = quality;
|
remoteEpisode.ParsedEpisodeInfo.Quality = quality;
|
||||||
|
remoteEpisode.ParsedEpisodeInfo.Language = language;
|
||||||
|
|
||||||
remoteEpisode.Episodes = new List<Episode>();
|
remoteEpisode.Episodes = new List<Episode>();
|
||||||
remoteEpisode.Episodes.AddRange(episodes);
|
remoteEpisode.Episodes.AddRange(episodes);
|
||||||
|
@ -49,7 +53,15 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
remoteEpisode.Release.DownloadProtocol = downloadProtocol;
|
remoteEpisode.Release.DownloadProtocol = downloadProtocol;
|
||||||
|
|
||||||
remoteEpisode.Series = Builder<Series>.CreateNew()
|
remoteEpisode.Series = Builder<Series>.CreateNew()
|
||||||
.With(e => e.Profile = new Profile { Items = Qualities.QualityFixture.GetDefaultQualities() })
|
.With(e => e.Profile = new Profile
|
||||||
|
{
|
||||||
|
Items = Qualities.QualityFixture.GetDefaultQualities()
|
||||||
|
})
|
||||||
|
.With(l => l.LanguageProfile = new LanguageProfile
|
||||||
|
{
|
||||||
|
Languages = LanguageFixture.GetDefaultLanguages(),
|
||||||
|
Cutoff = Language.Spanish
|
||||||
|
})
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
return remoteEpisode;
|
return remoteEpisode;
|
||||||
|
@ -68,8 +80,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_put_propers_before_non_propers()
|
public void should_put_propers_before_non_propers()
|
||||||
{
|
{
|
||||||
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p, new Revision(version: 1)));
|
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p, new Revision(version: 1)), Language.English);
|
||||||
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p, new Revision(version: 2)));
|
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p, new Revision(version: 2)), Language.English);
|
||||||
|
|
||||||
var decisions = new List<DownloadDecision>();
|
var decisions = new List<DownloadDecision>();
|
||||||
decisions.Add(new DownloadDecision(remoteEpisode1));
|
decisions.Add(new DownloadDecision(remoteEpisode1));
|
||||||
|
@ -82,8 +94,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_put_higher_quality_before_lower()
|
public void should_put_higher_quality_before_lower()
|
||||||
{
|
{
|
||||||
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.SDTV));
|
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.SDTV), Language.English);
|
||||||
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p));
|
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
|
|
||||||
var decisions = new List<DownloadDecision>();
|
var decisions = new List<DownloadDecision>();
|
||||||
decisions.Add(new DownloadDecision(remoteEpisode1));
|
decisions.Add(new DownloadDecision(remoteEpisode1));
|
||||||
|
@ -96,8 +108,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_order_by_lowest_number_of_episodes()
|
public void should_order_by_lowest_number_of_episodes()
|
||||||
{
|
{
|
||||||
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(2) }, new QualityModel(Quality.HDTV720p));
|
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(2) }, new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p));
|
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
|
|
||||||
var decisions = new List<DownloadDecision>();
|
var decisions = new List<DownloadDecision>();
|
||||||
decisions.Add(new DownloadDecision(remoteEpisode1));
|
decisions.Add(new DownloadDecision(remoteEpisode1));
|
||||||
|
@ -110,8 +122,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_order_by_lowest_number_of_episodes_with_multiple_episodes()
|
public void should_order_by_lowest_number_of_episodes_with_multiple_episodes()
|
||||||
{
|
{
|
||||||
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(2), GivenEpisode(3) }, new QualityModel(Quality.HDTV720p));
|
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(2), GivenEpisode(3) }, new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1), GivenEpisode(2) }, new QualityModel(Quality.HDTV720p));
|
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1), GivenEpisode(2) }, new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
|
|
||||||
var decisions = new List<DownloadDecision>();
|
var decisions = new List<DownloadDecision>();
|
||||||
decisions.Add(new DownloadDecision(remoteEpisode1));
|
decisions.Add(new DownloadDecision(remoteEpisode1));
|
||||||
|
@ -124,10 +136,10 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_order_by_age_then_largest_rounded_to_200mb()
|
public void should_order_by_age_then_largest_rounded_to_200mb()
|
||||||
{
|
{
|
||||||
var remoteEpisodeSd = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.SDTV), size: 100.Megabytes(), age: 1);
|
var remoteEpisodeSd = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.SDTV), Language.English, size: 100.Megabytes(), age: 1);
|
||||||
var remoteEpisodeHdSmallOld = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), size: 1200.Megabytes(), age: 1000);
|
var remoteEpisodeHdSmallOld = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English, size: 1200.Megabytes(), age: 1000);
|
||||||
var remoteEpisodeSmallYoung = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), size: 1250.Megabytes(), age: 10);
|
var remoteEpisodeSmallYoung = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English, size: 1250.Megabytes(), age: 10);
|
||||||
var remoteEpisodeHdLargeYoung = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), size: 3000.Megabytes(), age: 1);
|
var remoteEpisodeHdLargeYoung = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English, size: 3000.Megabytes(), age: 1);
|
||||||
|
|
||||||
var decisions = new List<DownloadDecision>();
|
var decisions = new List<DownloadDecision>();
|
||||||
decisions.Add(new DownloadDecision(remoteEpisodeSd));
|
decisions.Add(new DownloadDecision(remoteEpisodeSd));
|
||||||
|
@ -142,8 +154,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_order_by_youngest()
|
public void should_order_by_youngest()
|
||||||
{
|
{
|
||||||
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), age: 10);
|
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English, age: 10);
|
||||||
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), age: 5);
|
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English, age: 5);
|
||||||
|
|
||||||
|
|
||||||
var decisions = new List<DownloadDecision>();
|
var decisions = new List<DownloadDecision>();
|
||||||
|
@ -157,8 +169,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_not_throw_if_no_episodes_are_found()
|
public void should_not_throw_if_no_episodes_are_found()
|
||||||
{
|
{
|
||||||
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), size: 500.Megabytes());
|
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English, size: 500.Megabytes());
|
||||||
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), size: 500.Megabytes());
|
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English, size: 500.Megabytes());
|
||||||
|
|
||||||
remoteEpisode1.Episodes = new List<Episode>();
|
remoteEpisode1.Episodes = new List<Episode>();
|
||||||
|
|
||||||
|
@ -174,8 +186,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
{
|
{
|
||||||
GivenPreferredDownloadProtocol(DownloadProtocol.Usenet);
|
GivenPreferredDownloadProtocol(DownloadProtocol.Usenet);
|
||||||
|
|
||||||
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), downloadProtocol: DownloadProtocol.Torrent);
|
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English, downloadProtocol: DownloadProtocol.Torrent);
|
||||||
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), downloadProtocol: DownloadProtocol.Usenet);
|
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English, downloadProtocol: DownloadProtocol.Usenet);
|
||||||
|
|
||||||
var decisions = new List<DownloadDecision>();
|
var decisions = new List<DownloadDecision>();
|
||||||
decisions.Add(new DownloadDecision(remoteEpisode1));
|
decisions.Add(new DownloadDecision(remoteEpisode1));
|
||||||
|
@ -190,8 +202,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
{
|
{
|
||||||
GivenPreferredDownloadProtocol(DownloadProtocol.Torrent);
|
GivenPreferredDownloadProtocol(DownloadProtocol.Torrent);
|
||||||
|
|
||||||
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), downloadProtocol: DownloadProtocol.Torrent);
|
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English, downloadProtocol: DownloadProtocol.Torrent);
|
||||||
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), downloadProtocol: DownloadProtocol.Usenet);
|
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English, downloadProtocol: DownloadProtocol.Usenet);
|
||||||
|
|
||||||
var decisions = new List<DownloadDecision>();
|
var decisions = new List<DownloadDecision>();
|
||||||
decisions.Add(new DownloadDecision(remoteEpisode1));
|
decisions.Add(new DownloadDecision(remoteEpisode1));
|
||||||
|
@ -204,8 +216,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_prefer_season_pack_above_single_episode()
|
public void should_prefer_season_pack_above_single_episode()
|
||||||
{
|
{
|
||||||
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1), GivenEpisode(2) }, new QualityModel(Quality.HDTV720p));
|
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1), GivenEpisode(2) }, new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p));
|
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
|
|
||||||
remoteEpisode1.ParsedEpisodeInfo.FullSeason = true;
|
remoteEpisode1.ParsedEpisodeInfo.FullSeason = true;
|
||||||
|
|
||||||
|
@ -220,8 +232,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_prefer_multiepisode_over_single_episode_for_anime()
|
public void should_prefer_multiepisode_over_single_episode_for_anime()
|
||||||
{
|
{
|
||||||
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1), GivenEpisode(2) }, new QualityModel(Quality.HDTV720p));
|
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1), GivenEpisode(2) }, new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p));
|
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
|
|
||||||
remoteEpisode1.Series.SeriesType = SeriesTypes.Anime;
|
remoteEpisode1.Series.SeriesType = SeriesTypes.Anime;
|
||||||
remoteEpisode2.Series.SeriesType = SeriesTypes.Anime;
|
remoteEpisode2.Series.SeriesType = SeriesTypes.Anime;
|
||||||
|
@ -237,8 +249,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_prefer_single_episode_over_multi_episode_for_non_anime()
|
public void should_prefer_single_episode_over_multi_episode_for_non_anime()
|
||||||
{
|
{
|
||||||
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1), GivenEpisode(2) }, new QualityModel(Quality.HDTV720p));
|
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1), GivenEpisode(2) }, new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p));
|
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
|
|
||||||
var decisions = new List<DownloadDecision>();
|
var decisions = new List<DownloadDecision>();
|
||||||
decisions.Add(new DownloadDecision(remoteEpisode1));
|
decisions.Add(new DownloadDecision(remoteEpisode1));
|
||||||
|
@ -251,8 +263,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_prefer_releases_with_more_seeders()
|
public void should_prefer_releases_with_more_seeders()
|
||||||
{
|
{
|
||||||
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p));
|
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p));
|
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
|
|
||||||
var torrentInfo1 = new TorrentInfo();
|
var torrentInfo1 = new TorrentInfo();
|
||||||
torrentInfo1.PublishDate = DateTime.Now;
|
torrentInfo1.PublishDate = DateTime.Now;
|
||||||
|
@ -277,8 +289,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_prefer_releases_with_more_peers_given_equal_number_of_seeds()
|
public void should_prefer_releases_with_more_peers_given_equal_number_of_seeds()
|
||||||
{
|
{
|
||||||
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p));
|
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p));
|
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
|
|
||||||
var torrentInfo1 = new TorrentInfo();
|
var torrentInfo1 = new TorrentInfo();
|
||||||
torrentInfo1.PublishDate = DateTime.Now;
|
torrentInfo1.PublishDate = DateTime.Now;
|
||||||
|
@ -305,8 +317,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_prefer_releases_with_more_peers_no_seeds()
|
public void should_prefer_releases_with_more_peers_no_seeds()
|
||||||
{
|
{
|
||||||
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p));
|
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p));
|
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
|
|
||||||
var torrentInfo1 = new TorrentInfo();
|
var torrentInfo1 = new TorrentInfo();
|
||||||
torrentInfo1.PublishDate = DateTime.Now;
|
torrentInfo1.PublishDate = DateTime.Now;
|
||||||
|
@ -334,8 +346,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_prefer_first_release_if_peers_and_size_are_too_similar()
|
public void should_prefer_first_release_if_peers_and_size_are_too_similar()
|
||||||
{
|
{
|
||||||
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p));
|
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p));
|
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
|
|
||||||
var torrentInfo1 = new TorrentInfo();
|
var torrentInfo1 = new TorrentInfo();
|
||||||
torrentInfo1.PublishDate = DateTime.Now;
|
torrentInfo1.PublishDate = DateTime.Now;
|
||||||
|
@ -363,8 +375,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_prefer_first_release_if_age_and_size_are_too_similar()
|
public void should_prefer_first_release_if_age_and_size_are_too_similar()
|
||||||
{
|
{
|
||||||
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p));
|
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p));
|
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
|
|
||||||
remoteEpisode1.Release.PublishDate = DateTime.UtcNow.AddDays(-100);
|
remoteEpisode1.Release.PublishDate = DateTime.UtcNow.AddDays(-100);
|
||||||
remoteEpisode1.Release.Size = 200.Megabytes();
|
remoteEpisode1.Release.Size = 200.Megabytes();
|
||||||
|
@ -383,8 +395,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_prefer_quality_over_the_number_of_peers()
|
public void should_prefer_quality_over_the_number_of_peers()
|
||||||
{
|
{
|
||||||
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.Bluray1080p));
|
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.Bluray1080p), Language.English);
|
||||||
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.SDTV));
|
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.SDTV), Language.English);
|
||||||
|
|
||||||
var torrentInfo1 = new TorrentInfo();
|
var torrentInfo1 = new TorrentInfo();
|
||||||
torrentInfo1.PublishDate = DateTime.Now;
|
torrentInfo1.PublishDate = DateTime.Now;
|
||||||
|
@ -408,5 +420,37 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
|
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
|
||||||
((TorrentInfo)qualifiedReports.First().RemoteEpisode.Release).Should().Be(torrentInfo1);
|
((TorrentInfo)qualifiedReports.First().RemoteEpisode.Release).Should().Be(torrentInfo1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_order_by_language()
|
||||||
|
{
|
||||||
|
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
|
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.French);
|
||||||
|
var remoteEpisode3 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.German);
|
||||||
|
|
||||||
|
|
||||||
|
var decisions = new List<DownloadDecision>();
|
||||||
|
decisions.Add(new DownloadDecision(remoteEpisode1));
|
||||||
|
decisions.Add(new DownloadDecision(remoteEpisode2));
|
||||||
|
decisions.Add(new DownloadDecision(remoteEpisode3));
|
||||||
|
|
||||||
|
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
|
||||||
|
qualifiedReports.First().RemoteEpisode.ParsedEpisodeInfo.Language.Should().Be(Language.French);
|
||||||
|
qualifiedReports.Last().RemoteEpisode.ParsedEpisodeInfo.Language.Should().Be(Language.German);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_put_higher_quality_before_lower_allways()
|
||||||
|
{
|
||||||
|
var remoteEpisode1 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.SDTV), Language.French);
|
||||||
|
var remoteEpisode2 = GivenRemoteEpisode(new List<Episode> { GivenEpisode(1) }, new QualityModel(Quality.HDTV720p), Language.German);
|
||||||
|
|
||||||
|
var decisions = new List<DownloadDecision>();
|
||||||
|
decisions.Add(new DownloadDecision(remoteEpisode1));
|
||||||
|
decisions.Add(new DownloadDecision(remoteEpisode2));
|
||||||
|
|
||||||
|
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
|
||||||
|
qualifiedReports.First().RemoteEpisode.ParsedEpisodeInfo.Quality.Quality.Should().Be(Quality.HDTV720p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ using Marr.Data;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
|
|
@ -1,16 +1,19 @@
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.DecisionEngine;
|
using NzbDrone.Core.DecisionEngine;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
|
using NzbDrone.Core.Test.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.DecisionEngineTests
|
namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
|
|
||||||
public class QualityUpgradeSpecificationFixture : CoreTest<QualityUpgradableSpecification>
|
public class QualityUpgradeSpecificationFixture : CoreTest<UpgradableSpecification>
|
||||||
{
|
{
|
||||||
public static object[] IsUpgradeTestCases =
|
public static object[] IsUpgradeTestCases =
|
||||||
{
|
{
|
||||||
|
@ -23,6 +26,16 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
new object[] { Quality.WEBDL1080p, 1, Quality.WEBDL1080p, 1, Quality.WEBDL1080p, false }
|
new object[] { Quality.WEBDL1080p, 1, Quality.WEBDL1080p, 1, Quality.WEBDL1080p, false }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static object[] IsUpgradeTestCasesLanguages =
|
||||||
|
{
|
||||||
|
new object[] { Quality.SDTV, 1, Language.English, Quality.SDTV, 2, Language.English, Quality.SDTV, Language.Spanish, true },
|
||||||
|
new object[] { Quality.SDTV, 1, Language.English, Quality.SDTV, 1, Language.Spanish, Quality.SDTV, Language.Spanish, true },
|
||||||
|
new object[] { Quality.WEBDL720p, 1, Language.French, Quality.WEBDL720p, 2, Language.English, Quality.WEBDL720p, Language.Spanish, true },
|
||||||
|
new object[] { Quality.SDTV, 1, Language.English, Quality.SDTV, 1, Language.English, Quality.SDTV, Language.English, false },
|
||||||
|
new object[] { Quality.WEBDL720p, 1, Language.English, Quality.HDTV720p, 2, Language.Spanish, Quality.Bluray720p, Language.Spanish, false },
|
||||||
|
new object[] { Quality.WEBDL720p, 1, Language.Spanish, Quality.HDTV720p, 2, Language.French, Quality.WEBDL720p, Language.Spanish, false }
|
||||||
|
};
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
|
@ -41,9 +54,40 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
{
|
{
|
||||||
GivenAutoDownloadPropers(true);
|
GivenAutoDownloadPropers(true);
|
||||||
|
|
||||||
var profile = new Profile { Items = Qualities.QualityFixture.GetDefaultQualities() };
|
|
||||||
|
|
||||||
Subject.IsUpgradable(profile, new QualityModel(current, new Revision(version: currentVersion)), new QualityModel(newQuality, new Revision(version: newVersion)))
|
var profile = new Profile
|
||||||
|
{
|
||||||
|
Items = Qualities.QualityFixture.GetDefaultQualities()
|
||||||
|
};
|
||||||
|
|
||||||
|
var langProfile = new LanguageProfile
|
||||||
|
{
|
||||||
|
Languages = LanguageFixture.GetDefaultLanguages(),
|
||||||
|
Cutoff = Language.English
|
||||||
|
};
|
||||||
|
|
||||||
|
Subject.IsUpgradable(profile, langProfile, new QualityModel(current, new Revision(version: currentVersion)), Language.English, new QualityModel(newQuality, new Revision(version: newVersion)), Language.English)
|
||||||
|
.Should().Be(expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, TestCaseSource("IsUpgradeTestCasesLanguages")]
|
||||||
|
public void IsUpgradeTestLanguage(Quality current, int currentVersion, Language currentLanguage, Quality newQuality, int newVersion, Language newLanguage, Quality cutoff, Language languageCutoff, bool expected)
|
||||||
|
{
|
||||||
|
GivenAutoDownloadPropers(true);
|
||||||
|
|
||||||
|
var profile = new Profile
|
||||||
|
{
|
||||||
|
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||||
|
Cutoff = cutoff,
|
||||||
|
};
|
||||||
|
|
||||||
|
var langProfile = new LanguageProfile
|
||||||
|
{
|
||||||
|
Languages = LanguageFixture.GetDefaultLanguages(),
|
||||||
|
Cutoff = languageCutoff
|
||||||
|
};
|
||||||
|
|
||||||
|
Subject.IsUpgradable(profile, langProfile, new QualityModel(current, new Revision(version: currentVersion)), currentLanguage, new QualityModel(newQuality, new Revision(version: newVersion)), newLanguage)
|
||||||
.Should().Be(expected);
|
.Should().Be(expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,9 +96,19 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
{
|
{
|
||||||
GivenAutoDownloadPropers(false);
|
GivenAutoDownloadPropers(false);
|
||||||
|
|
||||||
var profile = new Profile { Items = Qualities.QualityFixture.GetDefaultQualities() };
|
var profile = new Profile
|
||||||
|
{
|
||||||
|
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||||
|
};
|
||||||
|
|
||||||
Subject.IsUpgradable(profile, new QualityModel(Quality.DVD, new Revision(version: 2)), new QualityModel(Quality.DVD, new Revision(version: 1)))
|
var langProfile = new LanguageProfile
|
||||||
|
{
|
||||||
|
Languages = LanguageFixture.GetDefaultLanguages(),
|
||||||
|
Cutoff = Language.English
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Subject.IsUpgradable(profile, langProfile, new QualityModel(Quality.DVD, new Revision(version: 2)), Language.English, new QualityModel(Quality.DVD, new Revision(version: 1)), Language.English)
|
||||||
.Should().BeFalse();
|
.Should().BeFalse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,12 +5,14 @@ using FluentAssertions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.DecisionEngine;
|
using NzbDrone.Core.DecisionEngine;
|
||||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Queue;
|
using NzbDrone.Core.Queue;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.DecisionEngineTests
|
namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
{
|
{
|
||||||
|
@ -27,10 +29,18 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
Mocker.Resolve<QualityUpgradableSpecification>();
|
Mocker.Resolve<UpgradableSpecification>();
|
||||||
|
|
||||||
_series = Builder<Series>.CreateNew()
|
_series = Builder<Series>.CreateNew()
|
||||||
.With(e => e.Profile = new Profile { Items = Qualities.QualityFixture.GetDefaultQualities() })
|
.With(e => e.Profile = new Profile
|
||||||
|
{
|
||||||
|
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||||
|
})
|
||||||
|
.With(l => l.LanguageProfile = new LanguageProfile
|
||||||
|
{
|
||||||
|
Languages = Languages.LanguageFixture.GetDefaultLanguages(),
|
||||||
|
Cutoff = Language.Spanish
|
||||||
|
})
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
_episode = Builder<Episode>.CreateNew()
|
_episode = Builder<Episode>.CreateNew()
|
||||||
|
@ -51,7 +61,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
_remoteEpisode = Builder<RemoteEpisode>.CreateNew()
|
_remoteEpisode = Builder<RemoteEpisode>.CreateNew()
|
||||||
.With(r => r.Series = _series)
|
.With(r => r.Series = _series)
|
||||||
.With(r => r.Episodes = new List<Episode> { _episode })
|
.With(r => r.Episodes = new List<Episode> { _episode })
|
||||||
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.DVD) })
|
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.DVD) , Language = Language.Spanish})
|
||||||
.Build();
|
.Build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,13 +107,35 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
public void should_return_true_when_quality_in_queue_is_lower()
|
public void should_return_true_when_quality_in_queue_is_lower()
|
||||||
{
|
{
|
||||||
_series.Profile.Value.Cutoff = Quality.Bluray1080p;
|
_series.Profile.Value.Cutoff = Quality.Bluray1080p;
|
||||||
|
_series.LanguageProfile.Value.Cutoff = Language.Spanish;
|
||||||
|
|
||||||
var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
|
var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
|
||||||
.With(r => r.Series = _series)
|
.With(r => r.Series = _series)
|
||||||
.With(r => r.Episodes = new List<Episode> { _episode })
|
.With(r => r.Episodes = new List<Episode> { _episode })
|
||||||
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
|
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
|
||||||
{
|
{
|
||||||
Quality = new QualityModel(Quality.SDTV)
|
Quality = new QualityModel(Quality.SDTV),
|
||||||
|
Language = Language.Spanish
|
||||||
|
})
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
GivenQueue(new List<RemoteEpisode> { remoteEpisode });
|
||||||
|
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_true_when_quality_in_queue_is_lower_but_language_is_higher()
|
||||||
|
{
|
||||||
|
_series.Profile.Value.Cutoff = Quality.Bluray1080p;
|
||||||
|
_series.LanguageProfile.Value.Cutoff = Language.Spanish;
|
||||||
|
|
||||||
|
var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
|
||||||
|
.With(r => r.Series = _series)
|
||||||
|
.With(r => r.Episodes = new List<Episode> { _episode })
|
||||||
|
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
|
||||||
|
{
|
||||||
|
Quality = new QualityModel(Quality.SDTV),
|
||||||
|
Language = Language.English
|
||||||
})
|
})
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
@ -128,14 +160,15 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_false_when_qualities_are_the_same()
|
public void should_return_false_when_qualities_are_the_same_and_languages_are_the_same()
|
||||||
{
|
{
|
||||||
var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
|
var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
|
||||||
.With(r => r.Series = _series)
|
.With(r => r.Series = _series)
|
||||||
.With(r => r.Episodes = new List<Episode> { _episode })
|
.With(r => r.Episodes = new List<Episode> { _episode })
|
||||||
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
|
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
|
||||||
{
|
{
|
||||||
Quality = new QualityModel(Quality.DVD)
|
Quality = new QualityModel(Quality.DVD),
|
||||||
|
Language = Language.Spanish,
|
||||||
})
|
})
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
@ -143,6 +176,23 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
|
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_true_when_qualities_are_the_same_but_language_is_better()
|
||||||
|
{
|
||||||
|
var remoteEpisode = Builder<RemoteEpisode>.CreateNew()
|
||||||
|
.With(r => r.Series = _series)
|
||||||
|
.With(r => r.Episodes = new List<Episode> { _episode })
|
||||||
|
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
|
||||||
|
{
|
||||||
|
Quality = new QualityModel(Quality.DVD),
|
||||||
|
Language = Language.English,
|
||||||
|
})
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
GivenQueue(new List<RemoteEpisode> { remoteEpisode });
|
||||||
|
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_false_when_quality_in_queue_is_better()
|
public void should_return_false_when_quality_in_queue_is_better()
|
||||||
{
|
{
|
||||||
|
@ -153,7 +203,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
.With(r => r.Episodes = new List<Episode> { _episode })
|
.With(r => r.Episodes = new List<Episode> { _episode })
|
||||||
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
|
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
|
||||||
{
|
{
|
||||||
Quality = new QualityModel(Quality.HDTV720p)
|
Quality = new QualityModel(Quality.HDTV720p),
|
||||||
|
Language = Language.English
|
||||||
})
|
})
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
@ -169,7 +220,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
.With(r => r.Episodes = new List<Episode> { _episode, _otherEpisode })
|
.With(r => r.Episodes = new List<Episode> { _episode, _otherEpisode })
|
||||||
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
|
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
|
||||||
{
|
{
|
||||||
Quality = new QualityModel(Quality.HDTV720p)
|
Quality = new QualityModel(Quality.HDTV720p),
|
||||||
|
Language = Language.English
|
||||||
})
|
})
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
@ -185,7 +237,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
.With(r => r.Episodes = new List<Episode> { _episode })
|
.With(r => r.Episodes = new List<Episode> { _episode })
|
||||||
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
|
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
|
||||||
{
|
{
|
||||||
Quality = new QualityModel(Quality.HDTV720p)
|
Quality = new QualityModel(Quality.HDTV720p),
|
||||||
|
Language = Language.English
|
||||||
})
|
})
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
@ -203,7 +256,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
.With(r => r.Episodes = new List<Episode> { _episode, _otherEpisode })
|
.With(r => r.Episodes = new List<Episode> { _episode, _otherEpisode })
|
||||||
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
|
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
|
||||||
{
|
{
|
||||||
Quality = new QualityModel(Quality.HDTV720p)
|
Quality = new QualityModel(Quality.HDTV720p),
|
||||||
|
Language = Language.English
|
||||||
})
|
})
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
@ -223,7 +277,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
{
|
{
|
||||||
Quality =
|
Quality =
|
||||||
new QualityModel(
|
new QualityModel(
|
||||||
Quality.HDTV720p)
|
Quality.HDTV720p),
|
||||||
|
Language = Language.English
|
||||||
})
|
})
|
||||||
.TheFirst(1)
|
.TheFirst(1)
|
||||||
.With(r => r.Episodes = new List<Episode> { _episode })
|
.With(r => r.Episodes = new List<Episode> { _episode })
|
||||||
|
@ -237,7 +292,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_false_if_quality_in_queue_meets_cutoff()
|
public void should_return_false_if_quality_and_language_in_queue_meets_cutoff()
|
||||||
{
|
{
|
||||||
_series.Profile.Value.Cutoff = _remoteEpisode.ParsedEpisodeInfo.Quality.Quality;
|
_series.Profile.Value.Cutoff = _remoteEpisode.ParsedEpisodeInfo.Quality.Quality;
|
||||||
|
|
||||||
|
@ -246,7 +301,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
.With(r => r.Episodes = new List<Episode> { _episode })
|
.With(r => r.Episodes = new List<Episode> { _episode })
|
||||||
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
|
.With(r => r.ParsedEpisodeInfo = new ParsedEpisodeInfo
|
||||||
{
|
{
|
||||||
Quality = new QualityModel(Quality.HDTV720p)
|
Quality = new QualityModel(Quality.HDTV720p),
|
||||||
|
Language = Language.Spanish
|
||||||
})
|
})
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,13 @@ using NzbDrone.Core.Indexers;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Profiles;
|
|
||||||
using NzbDrone.Core.Profiles.Delay;
|
using NzbDrone.Core.Profiles.Delay;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||||
{
|
{
|
||||||
|
@ -25,6 +27,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||||
public class DelaySpecificationFixture : CoreTest<DelaySpecification>
|
public class DelaySpecificationFixture : CoreTest<DelaySpecification>
|
||||||
{
|
{
|
||||||
private Profile _profile;
|
private Profile _profile;
|
||||||
|
private LanguageProfile _langProfile;
|
||||||
private DelayProfile _delayProfile;
|
private DelayProfile _delayProfile;
|
||||||
private RemoteEpisode _remoteEpisode;
|
private RemoteEpisode _remoteEpisode;
|
||||||
|
|
||||||
|
@ -34,12 +37,16 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||||
_profile = Builder<Profile>.CreateNew()
|
_profile = Builder<Profile>.CreateNew()
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
_langProfile = Builder<LanguageProfile>.CreateNew()
|
||||||
|
.Build();
|
||||||
|
|
||||||
_delayProfile = Builder<DelayProfile>.CreateNew()
|
_delayProfile = Builder<DelayProfile>.CreateNew()
|
||||||
.With(d => d.PreferredProtocol = DownloadProtocol.Usenet)
|
.With(d => d.PreferredProtocol = DownloadProtocol.Usenet)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var series = Builder<Series>.CreateNew()
|
var series = Builder<Series>.CreateNew()
|
||||||
.With(s => s.Profile = _profile)
|
.With(s => s.Profile = _profile)
|
||||||
|
.With(s => s.LanguageProfile = _langProfile)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
_remoteEpisode = Builder<RemoteEpisode>.CreateNew()
|
_remoteEpisode = Builder<RemoteEpisode>.CreateNew()
|
||||||
|
@ -53,6 +60,9 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||||
|
|
||||||
_profile.Cutoff = Quality.WEBDL720p;
|
_profile.Cutoff = Quality.WEBDL720p;
|
||||||
|
|
||||||
|
_langProfile.Cutoff = Language.Spanish;
|
||||||
|
_langProfile.Languages = Languages.LanguageFixture.GetDefaultLanguages();
|
||||||
|
|
||||||
_remoteEpisode.ParsedEpisodeInfo = new ParsedEpisodeInfo();
|
_remoteEpisode.ParsedEpisodeInfo = new ParsedEpisodeInfo();
|
||||||
_remoteEpisode.Release = new ReleaseInfo();
|
_remoteEpisode.Release = new ReleaseInfo();
|
||||||
_remoteEpisode.Release.DownloadProtocol = DownloadProtocol.Usenet;
|
_remoteEpisode.Release.DownloadProtocol = DownloadProtocol.Usenet;
|
||||||
|
@ -69,20 +79,21 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||||
.Returns(new List<RemoteEpisode>());
|
.Returns(new List<RemoteEpisode>());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenExistingFile(QualityModel quality)
|
private void GivenExistingFile(QualityModel quality, Language language)
|
||||||
{
|
{
|
||||||
_remoteEpisode.Episodes.First().EpisodeFileId = 1;
|
_remoteEpisode.Episodes.First().EpisodeFileId = 1;
|
||||||
|
|
||||||
_remoteEpisode.Episodes.First().EpisodeFile = new LazyLoaded<EpisodeFile>(new EpisodeFile
|
_remoteEpisode.Episodes.First().EpisodeFile = new LazyLoaded<EpisodeFile>(new EpisodeFile
|
||||||
{
|
{
|
||||||
Quality = quality
|
Quality = quality,
|
||||||
|
Language = language
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenUpgradeForExistingFile()
|
private void GivenUpgradeForExistingFile()
|
||||||
{
|
{
|
||||||
Mocker.GetMock<IQualityUpgradableSpecification>()
|
Mocker.GetMock<IUpgradableSpecification>()
|
||||||
.Setup(s => s.IsUpgradable(It.IsAny<Profile>(), It.IsAny<QualityModel>(), It.IsAny<QualityModel>()))
|
.Setup(s => s.IsUpgradable(It.IsAny<Profile>(), It.IsAny<LanguageProfile>(), It.IsAny<QualityModel>(), It.IsAny<Language>(), It.IsAny<QualityModel>(), It.IsAny<Language>()))
|
||||||
.Returns(true);
|
.Returns(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,9 +123,10 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_be_true_when_quality_is_last_allowed_in_profile()
|
public void should_be_true_when_quality_and_language_is_last_allowed_in_profile()
|
||||||
{
|
{
|
||||||
_remoteEpisode.ParsedEpisodeInfo.Quality = new QualityModel(Quality.Bluray720p);
|
_remoteEpisode.ParsedEpisodeInfo.Quality = new QualityModel(Quality.Bluray720p);
|
||||||
|
_remoteEpisode.ParsedEpisodeInfo.Language = Language.French;
|
||||||
|
|
||||||
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
@ -147,10 +159,10 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||||
_remoteEpisode.ParsedEpisodeInfo.Quality = new QualityModel(Quality.HDTV720p, new Revision(version: 2));
|
_remoteEpisode.ParsedEpisodeInfo.Quality = new QualityModel(Quality.HDTV720p, new Revision(version: 2));
|
||||||
_remoteEpisode.Release.PublishDate = DateTime.UtcNow;
|
_remoteEpisode.Release.PublishDate = DateTime.UtcNow;
|
||||||
|
|
||||||
GivenExistingFile(new QualityModel(Quality.HDTV720p));
|
GivenExistingFile(new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
GivenUpgradeForExistingFile();
|
GivenUpgradeForExistingFile();
|
||||||
|
|
||||||
Mocker.GetMock<IQualityUpgradableSpecification>()
|
Mocker.GetMock<IUpgradableSpecification>()
|
||||||
.Setup(s => s.IsRevisionUpgrade(It.IsAny<QualityModel>(), It.IsAny<QualityModel>()))
|
.Setup(s => s.IsRevisionUpgrade(It.IsAny<QualityModel>(), It.IsAny<QualityModel>()))
|
||||||
.Returns(true);
|
.Returns(true);
|
||||||
|
|
||||||
|
@ -165,10 +177,10 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||||
_remoteEpisode.ParsedEpisodeInfo.Quality = new QualityModel(Quality.HDTV720p, new Revision(real: 1));
|
_remoteEpisode.ParsedEpisodeInfo.Quality = new QualityModel(Quality.HDTV720p, new Revision(real: 1));
|
||||||
_remoteEpisode.Release.PublishDate = DateTime.UtcNow;
|
_remoteEpisode.Release.PublishDate = DateTime.UtcNow;
|
||||||
|
|
||||||
GivenExistingFile(new QualityModel(Quality.HDTV720p));
|
GivenExistingFile(new QualityModel(Quality.HDTV720p), Language.English);
|
||||||
GivenUpgradeForExistingFile();
|
GivenUpgradeForExistingFile();
|
||||||
|
|
||||||
Mocker.GetMock<IQualityUpgradableSpecification>()
|
Mocker.GetMock<IUpgradableSpecification>()
|
||||||
.Setup(s => s.IsRevisionUpgrade(It.IsAny<QualityModel>(), It.IsAny<QualityModel>()))
|
.Setup(s => s.IsRevisionUpgrade(It.IsAny<QualityModel>(), It.IsAny<QualityModel>()))
|
||||||
.Returns(true);
|
.Returns(true);
|
||||||
|
|
||||||
|
@ -183,7 +195,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||||
_remoteEpisode.ParsedEpisodeInfo.Quality = new QualityModel(Quality.HDTV720p, new Revision(version: 2));
|
_remoteEpisode.ParsedEpisodeInfo.Quality = new QualityModel(Quality.HDTV720p, new Revision(version: 2));
|
||||||
_remoteEpisode.Release.PublishDate = DateTime.UtcNow;
|
_remoteEpisode.Release.PublishDate = DateTime.UtcNow;
|
||||||
|
|
||||||
GivenExistingFile(new QualityModel(Quality.SDTV));
|
GivenExistingFile(new QualityModel(Quality.SDTV), Language.English);
|
||||||
|
|
||||||
_delayProfile.UsenetDelay = 720;
|
_delayProfile.UsenetDelay = 720;
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ using NzbDrone.Common.Disk;
|
||||||
using Moq;
|
using Moq;
|
||||||
using NzbDrone.Test.Common;
|
using NzbDrone.Test.Common;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,12 +9,14 @@ using NzbDrone.Core.DecisionEngine.Specifications.RssSync;
|
||||||
using NzbDrone.Core.History;
|
using NzbDrone.Core.History;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Profiles;
|
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
using NzbDrone.Core.DecisionEngine;
|
|
||||||
|
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Core.DecisionEngine;
|
||||||
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Test.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||||
{
|
{
|
||||||
|
@ -25,8 +27,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||||
|
|
||||||
private RemoteEpisode _parseResultMulti;
|
private RemoteEpisode _parseResultMulti;
|
||||||
private RemoteEpisode _parseResultSingle;
|
private RemoteEpisode _parseResultSingle;
|
||||||
private QualityModel _upgradableQuality;
|
private Tuple<QualityModel, Language> _upgradableQuality;
|
||||||
private QualityModel _notupgradableQuality;
|
private Tuple<QualityModel, Language> _notupgradableQuality;
|
||||||
private Series _fakeSeries;
|
private Series _fakeSeries;
|
||||||
private const int FIRST_EPISODE_ID = 1;
|
private const int FIRST_EPISODE_ID = 1;
|
||||||
private const int SECOND_EPISODE_ID = 2;
|
private const int SECOND_EPISODE_ID = 2;
|
||||||
|
@ -34,7 +36,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
Mocker.Resolve<QualityUpgradableSpecification>();
|
Mocker.Resolve<UpgradableSpecification>();
|
||||||
_upgradeHistory = Mocker.Resolve<HistorySpecification>();
|
_upgradeHistory = Mocker.Resolve<HistorySpecification>();
|
||||||
|
|
||||||
var singleEpisodeList = new List<Episode> { new Episode { Id = FIRST_EPISODE_ID, SeasonNumber = 12, EpisodeNumber = 3 } };
|
var singleEpisodeList = new List<Episode> { new Episode { Id = FIRST_EPISODE_ID, SeasonNumber = 12, EpisodeNumber = 3 } };
|
||||||
|
@ -46,34 +48,36 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||||
|
|
||||||
_fakeSeries = Builder<Series>.CreateNew()
|
_fakeSeries = Builder<Series>.CreateNew()
|
||||||
.With(c => c.Profile = new Profile { Cutoff = Quality.Bluray1080p, Items = Qualities.QualityFixture.GetDefaultQualities() })
|
.With(c => c.Profile = new Profile { Cutoff = Quality.Bluray1080p, Items = Qualities.QualityFixture.GetDefaultQualities() })
|
||||||
|
.With(l => l.LanguageProfile = new LanguageProfile { Cutoff = Language.Spanish, Languages = LanguageFixture.GetDefaultLanguages() })
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
_parseResultMulti = new RemoteEpisode
|
_parseResultMulti = new RemoteEpisode
|
||||||
{
|
{
|
||||||
Series = _fakeSeries,
|
Series = _fakeSeries,
|
||||||
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.DVD, new Revision(version: 2)) },
|
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.DVD, new Revision(version: 2)), Language = Language.English },
|
||||||
Episodes = doubleEpisodeList
|
Episodes = doubleEpisodeList
|
||||||
};
|
};
|
||||||
|
|
||||||
_parseResultSingle = new RemoteEpisode
|
_parseResultSingle = new RemoteEpisode
|
||||||
{
|
{
|
||||||
Series = _fakeSeries,
|
Series = _fakeSeries,
|
||||||
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.DVD, new Revision(version: 2)) },
|
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.DVD, new Revision(version: 2)), Language = Language.English },
|
||||||
Episodes = singleEpisodeList
|
Episodes = singleEpisodeList
|
||||||
};
|
};
|
||||||
|
|
||||||
_upgradableQuality = new QualityModel(Quality.SDTV, new Revision(version: 1));
|
_upgradableQuality = new Tuple<QualityModel, Language> (new QualityModel(Quality.SDTV, new Revision(version: 1)), Language.English);
|
||||||
_notupgradableQuality = new QualityModel(Quality.HDTV1080p, new Revision(version: 2));
|
|
||||||
|
_notupgradableQuality = new Tuple<QualityModel, Language> (new QualityModel(Quality.HDTV1080p, new Revision(version: 2)), Language.English);
|
||||||
|
|
||||||
Mocker.GetMock<IConfigService>()
|
Mocker.GetMock<IConfigService>()
|
||||||
.SetupGet(s => s.EnableCompletedDownloadHandling)
|
.SetupGet(s => s.EnableCompletedDownloadHandling)
|
||||||
.Returns(true);
|
.Returns(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenMostRecentForEpisode(int episodeId, string downloadId, QualityModel quality, DateTime date, HistoryEventType eventType)
|
private void GivenMostRecentForEpisode(int episodeId, string downloadId, Tuple<QualityModel, Language> quality, DateTime date, HistoryEventType eventType)
|
||||||
{
|
{
|
||||||
Mocker.GetMock<IHistoryService>().Setup(s => s.MostRecentForEpisode(episodeId))
|
Mocker.GetMock<IHistoryService>().Setup(s => s.MostRecentForEpisode(episodeId))
|
||||||
.Returns(new History.History { DownloadId = downloadId, Quality = quality, Date = date, EventType = eventType });
|
.Returns(new History.History { DownloadId = downloadId, Quality = quality.Item1, Date = date, EventType = eventType, Language = quality.Item2 });
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenCdhDisabled()
|
private void GivenCdhDisabled()
|
||||||
|
@ -161,19 +165,32 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||||
{
|
{
|
||||||
_fakeSeries.Profile = new Profile { Cutoff = Quality.Bluray1080p, Items = Qualities.QualityFixture.GetDefaultQualities() };
|
_fakeSeries.Profile = new Profile { Cutoff = Quality.Bluray1080p, Items = Qualities.QualityFixture.GetDefaultQualities() };
|
||||||
_parseResultSingle.ParsedEpisodeInfo.Quality = new QualityModel(Quality.WEBDL1080p, new Revision(version: 1));
|
_parseResultSingle.ParsedEpisodeInfo.Quality = new QualityModel(Quality.WEBDL1080p, new Revision(version: 1));
|
||||||
_upgradableQuality = new QualityModel(Quality.WEBDL1080p, new Revision(version: 1));
|
_upgradableQuality = new Tuple<QualityModel, Language>(new QualityModel(Quality.WEBDL1080p, new Revision(version: 1)), Language.English);
|
||||||
|
|
||||||
GivenMostRecentForEpisode(FIRST_EPISODE_ID, string.Empty, _upgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
|
GivenMostRecentForEpisode(FIRST_EPISODE_ID, string.Empty, _upgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
|
||||||
|
|
||||||
_upgradeHistory.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeFalse();
|
_upgradeHistory.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_be_upgradable_if_episode_is_of_same_quality_as_existing_but_new_has_better_language()
|
||||||
|
{
|
||||||
|
_fakeSeries.Profile = new Profile { Cutoff = Quality.WEBDL1080p, Items = Qualities.QualityFixture.GetDefaultQualities() };
|
||||||
|
_parseResultSingle.ParsedEpisodeInfo.Quality = new QualityModel(Quality.WEBDL1080p, new Revision(version: 1));
|
||||||
|
_parseResultSingle.ParsedEpisodeInfo.Language = Language.Spanish;
|
||||||
|
_upgradableQuality = new Tuple<QualityModel, Language>(new QualityModel(Quality.WEBDL1080p, new Revision(version: 1)), Language.English);
|
||||||
|
|
||||||
|
GivenMostRecentForEpisode(FIRST_EPISODE_ID, string.Empty, _upgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
|
||||||
|
|
||||||
|
_upgradeHistory.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_not_be_upgradable_if_cutoff_already_met()
|
public void should_not_be_upgradable_if_cutoff_already_met()
|
||||||
{
|
{
|
||||||
_fakeSeries.Profile = new Profile { Cutoff = Quality.WEBDL1080p, Items = Qualities.QualityFixture.GetDefaultQualities() };
|
_fakeSeries.Profile = new Profile { Cutoff = Quality.WEBDL1080p, Items = Qualities.QualityFixture.GetDefaultQualities() };
|
||||||
_parseResultSingle.ParsedEpisodeInfo.Quality = new QualityModel(Quality.WEBDL1080p, new Revision(version: 1));
|
_parseResultSingle.ParsedEpisodeInfo.Quality = new QualityModel(Quality.WEBDL1080p, new Revision(version: 1));
|
||||||
_upgradableQuality = new QualityModel(Quality.Bluray1080p, new Revision(version: 1));
|
_upgradableQuality = new Tuple<QualityModel, Language>(new QualityModel(Quality.WEBDL1080p, new Revision(version: 1)), Language.Spanish);
|
||||||
|
|
||||||
GivenMostRecentForEpisode(FIRST_EPISODE_ID, string.Empty, _upgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
|
GivenMostRecentForEpisode(FIRST_EPISODE_ID, string.Empty, _upgradableQuality, DateTime.UtcNow, HistoryEventType.Grabbed);
|
||||||
|
|
||||||
|
@ -201,7 +218,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||||
GivenCdhDisabled();
|
GivenCdhDisabled();
|
||||||
_fakeSeries.Profile = new Profile { Cutoff = Quality.WEBDL1080p, Items = Qualities.QualityFixture.GetDefaultQualities() };
|
_fakeSeries.Profile = new Profile { Cutoff = Quality.WEBDL1080p, Items = Qualities.QualityFixture.GetDefaultQualities() };
|
||||||
_parseResultSingle.ParsedEpisodeInfo.Quality = new QualityModel(Quality.Bluray1080p, new Revision(version: 1));
|
_parseResultSingle.ParsedEpisodeInfo.Quality = new QualityModel(Quality.Bluray1080p, new Revision(version: 1));
|
||||||
_upgradableQuality = new QualityModel(Quality.WEBDL1080p, new Revision(version: 1));
|
_upgradableQuality = new Tuple<QualityModel, Language>(new QualityModel(Quality.WEBDL1080p, new Revision(version: 1)), Language.Spanish);
|
||||||
|
|
||||||
GivenMostRecentForEpisode(FIRST_EPISODE_ID, "test", _upgradableQuality, DateTime.UtcNow.AddDays(-100), HistoryEventType.Grabbed);
|
GivenMostRecentForEpisode(FIRST_EPISODE_ID, "test", _upgradableQuality, DateTime.UtcNow.AddDays(-100), HistoryEventType.Grabbed);
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ using NzbDrone.Core.DecisionEngine.Specifications.RssSync;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
using NzbDrone.Core.DecisionEngine;
|
using NzbDrone.Core.DecisionEngine;
|
||||||
|
@ -29,7 +29,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
Mocker.Resolve<QualityUpgradableSpecification>();
|
Mocker.Resolve<UpgradableSpecification>();
|
||||||
|
|
||||||
_firstFile = new EpisodeFile { Quality = new QualityModel(Quality.Bluray1080p, new Revision(version: 1)), DateAdded = DateTime.Now };
|
_firstFile = new EpisodeFile { Quality = new QualityModel(Quality.Bluray1080p, new Revision(version: 1)), DateAdded = DateTime.Now };
|
||||||
_secondFile = new EpisodeFile { Quality = new QualityModel(Quality.Bluray1080p, new Revision(version: 1)), DateAdded = DateTime.Now };
|
_secondFile = new EpisodeFile { Quality = new QualityModel(Quality.Bluray1080p, new Revision(version: 1)), DateAdded = DateTime.Now };
|
||||||
|
|
|
@ -6,12 +6,13 @@ using NUnit.Framework;
|
||||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
using NzbDrone.Core.DecisionEngine;
|
using NzbDrone.Core.DecisionEngine;
|
||||||
|
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.DecisionEngineTests
|
namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
{
|
{
|
||||||
|
@ -29,30 +30,33 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
Mocker.Resolve<QualityUpgradableSpecification>();
|
Mocker.Resolve<UpgradableSpecification>();
|
||||||
_upgradeDisk = Mocker.Resolve<UpgradeDiskSpecification>();
|
_upgradeDisk = Mocker.Resolve<UpgradeDiskSpecification>();
|
||||||
|
|
||||||
_firstFile = new EpisodeFile { Quality = new QualityModel(Quality.Bluray1080p, new Revision(version: 2)), DateAdded = DateTime.Now };
|
_firstFile = new EpisodeFile { Quality = new QualityModel(Quality.Bluray1080p, new Revision(version: 2)), DateAdded = DateTime.Now, Language = Language.English };
|
||||||
_secondFile = new EpisodeFile { Quality = new QualityModel(Quality.Bluray1080p, new Revision(version: 2)), DateAdded = DateTime.Now };
|
_secondFile = new EpisodeFile { Quality = new QualityModel(Quality.Bluray1080p, new Revision(version: 2)), DateAdded = DateTime.Now, Language = Language.English };
|
||||||
|
|
||||||
var singleEpisodeList = new List<Episode> { new Episode { EpisodeFile = _firstFile, EpisodeFileId = 1 }, new Episode { EpisodeFile = null } };
|
var singleEpisodeList = new List<Episode> { new Episode { EpisodeFile = _firstFile, EpisodeFileId = 1 }, new Episode { EpisodeFile = null } };
|
||||||
var doubleEpisodeList = new List<Episode> { new Episode { EpisodeFile = _firstFile, EpisodeFileId = 1 }, new Episode { EpisodeFile = _secondFile, EpisodeFileId = 1 }, new Episode { EpisodeFile = null } };
|
var doubleEpisodeList = new List<Episode> { new Episode { EpisodeFile = _firstFile, EpisodeFileId = 1 }, new Episode { EpisodeFile = _secondFile, EpisodeFileId = 1 }, new Episode { EpisodeFile = null } };
|
||||||
|
|
||||||
|
var languages = Languages.LanguageFixture.GetDefaultLanguages(Language.English, Language.Spanish);
|
||||||
|
|
||||||
var fakeSeries = Builder<Series>.CreateNew()
|
var fakeSeries = Builder<Series>.CreateNew()
|
||||||
.With(c => c.Profile = new Profile { Cutoff = Quality.Bluray1080p, Items = Qualities.QualityFixture.GetDefaultQualities()})
|
.With(c => c.Profile = new Profile { Cutoff = Quality.Bluray1080p, Items = Qualities.QualityFixture.GetDefaultQualities()})
|
||||||
|
.With(l => l.LanguageProfile = new LanguageProfile { Cutoff = Language.Spanish, Languages = languages })
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
_parseResultMulti = new RemoteEpisode
|
_parseResultMulti = new RemoteEpisode
|
||||||
{
|
{
|
||||||
Series = fakeSeries,
|
Series = fakeSeries,
|
||||||
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.DVD, new Revision(version: 2)) },
|
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.DVD, new Revision(version: 2)), Language = Language.English },
|
||||||
Episodes = doubleEpisodeList
|
Episodes = doubleEpisodeList
|
||||||
};
|
};
|
||||||
|
|
||||||
_parseResultSingle = new RemoteEpisode
|
_parseResultSingle = new RemoteEpisode
|
||||||
{
|
{
|
||||||
Series = fakeSeries,
|
Series = fakeSeries,
|
||||||
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.DVD, new Revision(version: 2)) },
|
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.DVD, new Revision(version: 2)), Language = Language.English },
|
||||||
Episodes = singleEpisodeList
|
Episodes = singleEpisodeList
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ using NzbDrone.Core.Download.Pending;
|
||||||
using NzbDrone.Core.Exceptions;
|
using NzbDrone.Core.Exceptions;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
|
@ -10,7 +10,7 @@ using NzbDrone.Core.DecisionEngine;
|
||||||
using NzbDrone.Core.Download.Pending;
|
using NzbDrone.Core.Download.Pending;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
|
@ -10,7 +10,7 @@ using NzbDrone.Core.Download;
|
||||||
using NzbDrone.Core.Download.Pending;
|
using NzbDrone.Core.Download.Pending;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
|
@ -11,7 +11,7 @@ using NzbDrone.Core.Download.Pending;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
|
@ -7,15 +7,15 @@ using NUnit.Framework;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.MediaFiles.Events;
|
using NzbDrone.Core.MediaFiles.Events;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
using NzbDrone.Core.History;
|
using NzbDrone.Core.History;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using System.Collections.Generic;
|
|
||||||
using NzbDrone.Core.Test.Qualities;
|
using NzbDrone.Core.Test.Qualities;
|
||||||
using FluentAssertions;
|
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.HistoryTests
|
namespace NzbDrone.Core.Test.HistoryTests
|
||||||
{
|
{
|
||||||
|
@ -23,48 +23,31 @@ namespace NzbDrone.Core.Test.HistoryTests
|
||||||
{
|
{
|
||||||
private Profile _profile;
|
private Profile _profile;
|
||||||
private Profile _profileCustom;
|
private Profile _profileCustom;
|
||||||
|
private LanguageProfile _languageProfile;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
_profile = new Profile { Cutoff = Quality.WEBDL720p, Items = QualityFixture.GetDefaultQualities() };
|
_profile = new Profile
|
||||||
_profileCustom = new Profile { Cutoff = Quality.WEBDL720p, Items = QualityFixture.GetDefaultQualities(Quality.DVD) };
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_return_null_if_no_history()
|
|
||||||
{
|
{
|
||||||
Mocker.GetMock<IHistoryRepository>()
|
Cutoff = Quality.WEBDL720p,
|
||||||
.Setup(v => v.GetBestQualityInHistory(2))
|
Items = QualityFixture.GetDefaultQualities(),
|
||||||
.Returns(new List<QualityModel>());
|
};
|
||||||
|
|
||||||
var quality = Subject.GetBestQualityInHistory(_profile, 2);
|
_profileCustom = new Profile
|
||||||
|
|
||||||
quality.Should().BeNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_return_best_quality()
|
|
||||||
{
|
{
|
||||||
Mocker.GetMock<IHistoryRepository>()
|
Cutoff = Quality.WEBDL720p,
|
||||||
.Setup(v => v.GetBestQualityInHistory(2))
|
Items = QualityFixture.GetDefaultQualities(Quality.DVD),
|
||||||
.Returns(new List<QualityModel> { new QualityModel(Quality.DVD), new QualityModel(Quality.Bluray1080p) });
|
|
||||||
|
|
||||||
var quality = Subject.GetBestQualityInHistory(_profile, 2);
|
};
|
||||||
|
|
||||||
quality.Should().Be(new QualityModel(Quality.Bluray1080p));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
_languageProfile = new LanguageProfile
|
||||||
public void should_return_best_quality_with_custom_order()
|
|
||||||
{
|
{
|
||||||
Mocker.GetMock<IHistoryRepository>()
|
Cutoff = Language.Spanish,
|
||||||
.Setup(v => v.GetBestQualityInHistory(2))
|
Languages = Languages.LanguageFixture.GetDefaultLanguages()
|
||||||
.Returns(new List<QualityModel> { new QualityModel(Quality.DVD), new QualityModel(Quality.Bluray1080p) });
|
};
|
||||||
|
|
||||||
var quality = Subject.GetBestQualityInHistory(_profileCustom, 2);
|
|
||||||
|
|
||||||
quality.Should().Be(new QualityModel(Quality.DVD));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
using System.Linq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using FluentAssertions;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.Languages
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class LanguageFixture : CoreTest
|
||||||
|
{
|
||||||
|
public static object[] FromIntCases =
|
||||||
|
{
|
||||||
|
new object[] {1, Language.English},
|
||||||
|
new object[] {2, Language.French},
|
||||||
|
new object[] {3, Language.Spanish},
|
||||||
|
new object[] {4, Language.German},
|
||||||
|
new object[] {5, Language.Italian},
|
||||||
|
new object[] {6, Language.Danish},
|
||||||
|
new object[] {7, Language.Dutch},
|
||||||
|
new object[] {8, Language.Japanese},
|
||||||
|
new object[] {9, Language.Cantonese},
|
||||||
|
new object[] {10, Language.Mandarin},
|
||||||
|
new object[] {11, Language.Russian},
|
||||||
|
new object[] {12, Language.Polish},
|
||||||
|
new object[] {13, Language.Vietnamese},
|
||||||
|
new object[] {14, Language.Swedish},
|
||||||
|
new object[] {15, Language.Norwegian},
|
||||||
|
new object[] {16, Language.Finnish},
|
||||||
|
new object[] {17, Language.Turkish},
|
||||||
|
new object[] {18, Language.Portuguese},
|
||||||
|
new object[] {19, Language.Flemish},
|
||||||
|
new object[] {20, Language.Greek},
|
||||||
|
new object[] {21, Language.Korean},
|
||||||
|
new object[] {22, Language.Hungarian}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static object[] ToIntCases =
|
||||||
|
{
|
||||||
|
new object[] {Language.English, 1},
|
||||||
|
new object[] {Language.French, 2},
|
||||||
|
new object[] {Language.Spanish, 3},
|
||||||
|
new object[] {Language.German, 4},
|
||||||
|
new object[] {Language.Italian, 5},
|
||||||
|
new object[] {Language.Danish, 6},
|
||||||
|
new object[] {Language.Dutch, 7},
|
||||||
|
new object[] {Language.Japanese, 8},
|
||||||
|
new object[] {Language.Cantonese, 9},
|
||||||
|
new object[] {Language.Mandarin, 10},
|
||||||
|
new object[] {Language.Russian, 11},
|
||||||
|
new object[] {Language.Polish, 12},
|
||||||
|
new object[] {Language.Vietnamese, 13},
|
||||||
|
new object[] {Language.Swedish, 14},
|
||||||
|
new object[] {Language.Norwegian, 15},
|
||||||
|
new object[] {Language.Finnish, 16},
|
||||||
|
new object[] {Language.Turkish, 17},
|
||||||
|
new object[] {Language.Portuguese, 18},
|
||||||
|
new object[] {Language.Flemish, 19},
|
||||||
|
new object[] {Language.Greek, 20},
|
||||||
|
new object[] {Language.Korean, 21},
|
||||||
|
new object[] {Language.Hungarian, 22}
|
||||||
|
};
|
||||||
|
|
||||||
|
[Test, TestCaseSource("FromIntCases")]
|
||||||
|
public void should_be_able_to_convert_int_to_languageTypes(int source, Language expected)
|
||||||
|
{
|
||||||
|
var language = (Language)source;
|
||||||
|
language.Should().Be(expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test, TestCaseSource("ToIntCases")]
|
||||||
|
public void should_be_able_to_convert_languageTypes_to_int(Language source, int expected)
|
||||||
|
{
|
||||||
|
var i = (int)source;
|
||||||
|
i.Should().Be(expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<LanguageProfileItem> GetDefaultLanguages(params Language[] allowed)
|
||||||
|
{
|
||||||
|
var languages = new List<Language>
|
||||||
|
{
|
||||||
|
Language.English,
|
||||||
|
Language.Spanish,
|
||||||
|
Language.French
|
||||||
|
};
|
||||||
|
|
||||||
|
if (allowed.Length == 0)
|
||||||
|
allowed = languages.ToArray();
|
||||||
|
|
||||||
|
var items = languages
|
||||||
|
.Except(allowed)
|
||||||
|
.Concat(allowed)
|
||||||
|
.Select(v => new LanguageProfileItem { Language = v, Allowed = allowed.Contains(v) }).ToList();
|
||||||
|
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
using FluentAssertions;
|
||||||
|
using System.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.Languages
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class LanguageProfileRepositoryFixture : DbTest<LanguageProfileRepository, LanguageProfile>
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void should_be_able_to_read_and_write()
|
||||||
|
{
|
||||||
|
var profile = new LanguageProfile
|
||||||
|
{
|
||||||
|
Languages = Language.All.OrderByDescending(l => l.Name).Select(l => new LanguageProfileItem {Language = l, Allowed = l == Language.English}).ToList(),
|
||||||
|
Name = "TestProfile",
|
||||||
|
Cutoff = Language.English
|
||||||
|
};
|
||||||
|
|
||||||
|
Subject.Insert(profile);
|
||||||
|
|
||||||
|
|
||||||
|
StoredModel.Name.Should().Be(profile.Name);
|
||||||
|
StoredModel.Cutoff.Should().Be(profile.Cutoff);
|
||||||
|
|
||||||
|
StoredModel.Languages.Should().Equal(profile.Languages, (a, b) => a.Language == b.Language && a.Allowed == b.Allowed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
using System.Linq;
|
||||||
|
using FizzWare.NBuilder;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Lifecycle;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.Languages
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
|
||||||
|
public class LanguageProfileServiceFixture : CoreTest<LanguageProfileService>
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void init_should_add_default_profiles()
|
||||||
|
{
|
||||||
|
Subject.Handle(new ApplicationStartedEvent());
|
||||||
|
|
||||||
|
Mocker.GetMock<ILanguageProfileRepository>()
|
||||||
|
.Verify(v => v.Insert(It.IsAny<LanguageProfile>()), Times.Once());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
//This confirms that new profiles are added only if no other profiles exists.
|
||||||
|
//We don't want to keep adding them back if a user deleted them on purpose.
|
||||||
|
public void Init_should_skip_if_any_profiles_already_exist()
|
||||||
|
{
|
||||||
|
Mocker.GetMock<ILanguageProfileRepository>()
|
||||||
|
.Setup(s => s.All())
|
||||||
|
.Returns(Builder<LanguageProfile>.CreateListOfSize(2).Build().ToList());
|
||||||
|
|
||||||
|
Subject.Handle(new ApplicationStartedEvent());
|
||||||
|
|
||||||
|
Mocker.GetMock<ILanguageProfileRepository>()
|
||||||
|
.Verify(v => v.Insert(It.IsAny<LanguageProfile>()), Times.Never());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_not_be_able_to_delete_profile_if_assigned_to_series()
|
||||||
|
{
|
||||||
|
var seriesList = Builder<Series>.CreateListOfSize(3)
|
||||||
|
.Random(1)
|
||||||
|
.With(c => c.LanguageProfileId = 2)
|
||||||
|
.Build().ToList();
|
||||||
|
|
||||||
|
|
||||||
|
Mocker.GetMock<ISeriesService>().Setup(c => c.GetAllSeries()).Returns(seriesList);
|
||||||
|
|
||||||
|
Assert.Throws<LanguageProfileInUseException>(() => Subject.Delete(2));
|
||||||
|
|
||||||
|
Mocker.GetMock<ILanguageProfileRepository>().Verify(c => c.Delete(It.IsAny<int>()), Times.Never());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_delete_profile_if_not_assigned_to_series()
|
||||||
|
{
|
||||||
|
var seriesList = Builder<Series>.CreateListOfSize(3)
|
||||||
|
.All()
|
||||||
|
.With(c => c.LanguageProfileId = 2)
|
||||||
|
.Build().ToList();
|
||||||
|
|
||||||
|
|
||||||
|
Mocker.GetMock<ISeriesService>().Setup(c => c.GetAllSeries()).Returns(seriesList);
|
||||||
|
|
||||||
|
Subject.Delete(1);
|
||||||
|
|
||||||
|
Mocker.GetMock<ILanguageProfileRepository>().Verify(c => c.Delete(1), Times.Once());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
using FizzWare.NBuilder;
|
||||||
|
using FluentAssertions;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation.Aggregators;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Aggregation.Aggregators
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class AggregateLanguageFixture : CoreTest<AggregateLanguage>
|
||||||
|
{
|
||||||
|
private LocalEpisode _localEpisode;
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
_localEpisode = Builder<LocalEpisode>.CreateNew()
|
||||||
|
.With(l => l.DownloadClientEpisodeInfo = null)
|
||||||
|
.With(l => l.FolderEpisodeInfo = null)
|
||||||
|
.With(l => l.FileEpisodeInfo = null)
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private ParsedEpisodeInfo GetParsedEpisodeInfo(Language language)
|
||||||
|
{
|
||||||
|
return new ParsedEpisodeInfo
|
||||||
|
{
|
||||||
|
Language = language
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_file_language_when_only_file_info_is_known()
|
||||||
|
{
|
||||||
|
_localEpisode.FileEpisodeInfo = GetParsedEpisodeInfo(Language.English);
|
||||||
|
|
||||||
|
Subject.Aggregate(_localEpisode, false).Language.Should().Be(_localEpisode.FileEpisodeInfo.Language);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_folder_language_when_folder_info_is_known()
|
||||||
|
{
|
||||||
|
_localEpisode.FolderEpisodeInfo = GetParsedEpisodeInfo(Language.English);
|
||||||
|
_localEpisode.FileEpisodeInfo = GetParsedEpisodeInfo(Language.English);
|
||||||
|
|
||||||
|
Subject.Aggregate(_localEpisode, false).Language.Should().Be(_localEpisode.FolderEpisodeInfo.Language);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_download_client_item_language_when_download_client_item_info_is_known()
|
||||||
|
{
|
||||||
|
_localEpisode.DownloadClientEpisodeInfo = GetParsedEpisodeInfo(Language.English);
|
||||||
|
_localEpisode.FolderEpisodeInfo = GetParsedEpisodeInfo(Language.English);
|
||||||
|
_localEpisode.FileEpisodeInfo = GetParsedEpisodeInfo(Language.English);
|
||||||
|
|
||||||
|
Subject.Aggregate(_localEpisode, false).Language.Should().Be(_localEpisode.DownloadClientEpisodeInfo.Language);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_file_language_when_file_language_is_higher_than_others()
|
||||||
|
{
|
||||||
|
_localEpisode.DownloadClientEpisodeInfo = GetParsedEpisodeInfo(Language.English);
|
||||||
|
_localEpisode.FolderEpisodeInfo = GetParsedEpisodeInfo(Language.English);
|
||||||
|
_localEpisode.FileEpisodeInfo = GetParsedEpisodeInfo(Language.French);
|
||||||
|
|
||||||
|
Subject.Aggregate(_localEpisode, false).Language.Should().Be(_localEpisode.FileEpisodeInfo.Language);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Moq;
|
using Moq;
|
||||||
|
@ -7,14 +7,16 @@ using NzbDrone.Core.DecisionEngine;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Profiles;
|
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
using NzbDrone.Test.Common;
|
using NzbDrone.Test.Common;
|
||||||
using FizzWare.NBuilder;
|
using FizzWare.NBuilder;
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
using NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation;
|
using NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation;
|
||||||
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
||||||
{
|
{
|
||||||
|
@ -56,6 +58,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
||||||
_series = Builder<Series>.CreateNew()
|
_series = Builder<Series>.CreateNew()
|
||||||
.With(e => e.Path = @"C:\Test\Series".AsOsAgnostic())
|
.With(e => e.Path = @"C:\Test\Series".AsOsAgnostic())
|
||||||
.With(e => e.Profile = new Profile { Items = Qualities.QualityFixture.GetDefaultQualities() })
|
.With(e => e.Profile = new Profile { Items = Qualities.QualityFixture.GetDefaultQualities() })
|
||||||
|
.With(e => e.LanguageProfile = new LanguageProfile { Languages = Languages.LanguageFixture.GetDefaultLanguages() })
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
_quality = new QualityModel(Quality.DVD);
|
_quality = new QualityModel(Quality.DVD);
|
||||||
|
@ -64,11 +67,12 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
||||||
{
|
{
|
||||||
Series = _series,
|
Series = _series,
|
||||||
Quality = _quality,
|
Quality = _quality,
|
||||||
|
Language = Language.Spanish,
|
||||||
Episodes = new List<Episode> { new Episode() },
|
Episodes = new List<Episode> { new Episode() },
|
||||||
Path = @"C:\Test\Unsorted\The.Office.S03E115.DVDRip.XviD-OSiTV.avi"
|
Path = @"C:\Test\Unsorted\The.Office.S03E115.DVDRip.Spanish.XviD-OSiTV.avi"
|
||||||
};
|
};
|
||||||
|
|
||||||
GivenVideoFiles(new List<string> { @"C:\Test\Unsorted\The.Office.S03E115.DVDRip.XviD-OSiTV.avi".AsOsAgnostic() });
|
GivenVideoFiles(new List<string> { @"C:\Test\Unsorted\The.Office.S03E115.DVDRip.Spanish.XviD-OSiTV.avi".AsOsAgnostic() });
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenSpecifications(params Mock<IImportDecisionEngineSpecification>[] mocks)
|
private void GivenSpecifications(params Mock<IImportDecisionEngineSpecification>[] mocks)
|
||||||
|
@ -179,7 +183,6 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
||||||
ExceptionVerification.ExpectedErrors(3);
|
ExceptionVerification.ExpectedErrors(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_not_throw_if_episodes_are_not_found()
|
public void should_not_throw_if_episodes_are_not_found()
|
||||||
{
|
{
|
||||||
GivenSpecifications(_pass1);
|
GivenSpecifications(_pass1);
|
||||||
|
|
|
@ -6,10 +6,12 @@ using NUnit.Framework;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.MediaFiles.EpisodeImport.Specifications;
|
using NzbDrone.Core.MediaFiles.EpisodeImport.Specifications;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
||||||
{
|
{
|
||||||
|
@ -24,13 +26,22 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
||||||
{
|
{
|
||||||
_series = Builder<Series>.CreateNew()
|
_series = Builder<Series>.CreateNew()
|
||||||
.With(s => s.SeriesType = SeriesTypes.Standard)
|
.With(s => s.SeriesType = SeriesTypes.Standard)
|
||||||
.With(e => e.Profile = new Profile { Items = Qualities.QualityFixture.GetDefaultQualities() })
|
.With(e => e.Profile = new Profile
|
||||||
|
{
|
||||||
|
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||||
|
})
|
||||||
|
.With(l => l.LanguageProfile = new LanguageProfile
|
||||||
|
{
|
||||||
|
Languages = Languages.LanguageFixture.GetDefaultLanguages(),
|
||||||
|
Cutoff = Language.Spanish,
|
||||||
|
})
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
_localEpisode = new LocalEpisode
|
_localEpisode = new LocalEpisode
|
||||||
{
|
{
|
||||||
Path = @"C:\Test\30 Rock\30.rock.s01e01.avi",
|
Path = @"C:\Test\30 Rock\30.rock.s01e01.avi",
|
||||||
Quality = new QualityModel(Quality.HDTV720p, new Revision(version: 1)),
|
Quality = new QualityModel(Quality.HDTV720p, new Revision(version: 1)),
|
||||||
|
Language = Language.Spanish,
|
||||||
Series = _series
|
Series = _series
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -70,7 +81,8 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
||||||
.With(e => e.EpisodeFile = new LazyLoaded<EpisodeFile>(
|
.With(e => e.EpisodeFile = new LazyLoaded<EpisodeFile>(
|
||||||
new EpisodeFile
|
new EpisodeFile
|
||||||
{
|
{
|
||||||
Quality = new QualityModel(Quality.SDTV, new Revision(version: 1))
|
Quality = new QualityModel(Quality.SDTV, new Revision(version: 1)),
|
||||||
|
Language = Language.Spanish
|
||||||
}))
|
}))
|
||||||
.Build()
|
.Build()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
@ -78,6 +90,43 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
||||||
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_true_if_language_upgrade_for_existing_episodeFile_and_quality_is_same()
|
||||||
|
{
|
||||||
|
_localEpisode.Episodes = Builder<Episode>.CreateListOfSize(1)
|
||||||
|
.All()
|
||||||
|
.With(e => e.EpisodeFileId = 1)
|
||||||
|
.With(e => e.EpisodeFile = new LazyLoaded<EpisodeFile>(
|
||||||
|
new EpisodeFile
|
||||||
|
{
|
||||||
|
Quality = new QualityModel(Quality.HDTV720p, new Revision(version: 1)),
|
||||||
|
Language = Language.English
|
||||||
|
}))
|
||||||
|
.Build()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_false_if_language_upgrade_for_existing_episodeFile_and_quality_is_worse()
|
||||||
|
{
|
||||||
|
_localEpisode.Episodes = Builder<Episode>.CreateListOfSize(1)
|
||||||
|
.All()
|
||||||
|
.With(e => e.EpisodeFileId = 1)
|
||||||
|
.With(e => e.EpisodeFile = new LazyLoaded<EpisodeFile>(
|
||||||
|
new EpisodeFile
|
||||||
|
{
|
||||||
|
Quality = new QualityModel(Quality.Bluray1080p, new Revision(version: 1)),
|
||||||
|
Language = Language.English
|
||||||
|
}))
|
||||||
|
.Build()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_true_if_upgrade_for_existing_episodeFile_for_multi_episodes()
|
public void should_return_true_if_upgrade_for_existing_episodeFile_for_multi_episodes()
|
||||||
{
|
{
|
||||||
|
@ -95,6 +144,43 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
||||||
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_true_if_language_upgrade_for_existing_episodeFile_for_multi_episodes_and_quality_is_same()
|
||||||
|
{
|
||||||
|
_localEpisode.Episodes = Builder<Episode>.CreateListOfSize(2)
|
||||||
|
.All()
|
||||||
|
.With(e => e.EpisodeFileId = 1)
|
||||||
|
.With(e => e.EpisodeFile = new LazyLoaded<EpisodeFile>(
|
||||||
|
new EpisodeFile
|
||||||
|
{
|
||||||
|
Quality = new QualityModel(Quality.HDTV720p, new Revision(version: 1)),
|
||||||
|
Language = Language.English
|
||||||
|
}))
|
||||||
|
.Build()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_false_if_language_upgrade_for_existing_episodeFile_for_multi_episodes_and_quality_is_worse()
|
||||||
|
{
|
||||||
|
_localEpisode.Episodes = Builder<Episode>.CreateListOfSize(2)
|
||||||
|
.All()
|
||||||
|
.With(e => e.EpisodeFileId = 1)
|
||||||
|
.With(e => e.EpisodeFile = new LazyLoaded<EpisodeFile>(
|
||||||
|
new EpisodeFile
|
||||||
|
{
|
||||||
|
Quality = new QualityModel(Quality.Bluray1080p, new Revision(version: 1)),
|
||||||
|
Language = Language.English
|
||||||
|
}))
|
||||||
|
.Build()
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
Subject.IsSatisfiedBy(_localEpisode, null).Accepted.Should().BeFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_false_if_not_an_upgrade_for_existing_episodeFile()
|
public void should_return_false_if_not_an_upgrade_for_existing_episodeFile()
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,11 +13,13 @@ using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||||
using NzbDrone.Core.MediaFiles.Events;
|
using NzbDrone.Core.MediaFiles.Events;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
using NzbDrone.Test.Common;
|
using NzbDrone.Test.Common;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.MediaFiles
|
namespace NzbDrone.Core.Test.MediaFiles
|
||||||
{
|
{
|
||||||
|
@ -39,6 +41,11 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||||
|
|
||||||
var series = Builder<Series>.CreateNew()
|
var series = Builder<Series>.CreateNew()
|
||||||
.With(e => e.Profile = new Profile { Items = Qualities.QualityFixture.GetDefaultQualities() })
|
.With(e => e.Profile = new Profile { Items = Qualities.QualityFixture.GetDefaultQualities() })
|
||||||
|
.With(l => l.LanguageProfile = new LanguageProfile
|
||||||
|
{
|
||||||
|
Cutoff = Language.Spanish,
|
||||||
|
Languages = Languages.LanguageFixture.GetDefaultLanguages()
|
||||||
|
})
|
||||||
.With(s => s.Path = @"C:\Test\TV\30 Rock".AsOsAgnostic())
|
.With(s => s.Path = @"C:\Test\TV\30 Rock".AsOsAgnostic())
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
|
|
|
@ -301,6 +301,7 @@
|
||||||
<Compile Include="Instrumentation\DatabaseTargetFixture.cs" />
|
<Compile Include="Instrumentation\DatabaseTargetFixture.cs" />
|
||||||
<Compile Include="JobTests\JobRepositoryFixture.cs" />
|
<Compile Include="JobTests\JobRepositoryFixture.cs" />
|
||||||
<Compile Include="JobTests\TestJobs.cs" />
|
<Compile Include="JobTests\TestJobs.cs" />
|
||||||
|
<Compile Include="Languages\LanguageFixture.cs" />
|
||||||
<Compile Include="MediaCoverTests\CoverExistsSpecificationFixture.cs" />
|
<Compile Include="MediaCoverTests\CoverExistsSpecificationFixture.cs" />
|
||||||
<Compile Include="MediaCoverTests\ImageResizerFixture.cs" />
|
<Compile Include="MediaCoverTests\ImageResizerFixture.cs" />
|
||||||
<Compile Include="MediaCoverTests\MediaCoverServiceFixture.cs" />
|
<Compile Include="MediaCoverTests\MediaCoverServiceFixture.cs" />
|
||||||
|
@ -309,6 +310,7 @@
|
||||||
<Compile Include="MediaFiles\DownloadedEpisodesImportServiceFixture.cs" />
|
<Compile Include="MediaFiles\DownloadedEpisodesImportServiceFixture.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeFileMovingServiceTests\MoveEpisodeFileFixture.cs" />
|
<Compile Include="MediaFiles\EpisodeFileMovingServiceTests\MoveEpisodeFileFixture.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\Aggregation\Aggregators\AggregateEpisodesFixture.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\Aggregation\Aggregators\AggregateEpisodesFixture.cs" />
|
||||||
|
<Compile Include="MediaFiles\EpisodeImport\Aggregation\Aggregators\AggregateLanguageFixture.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\Aggregation\Aggregators\AggregateQualityFixture.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\Aggregation\Aggregators\AggregateQualityFixture.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\Aggregation\Aggregators\Augmenters\Quality\AugmentQualityFromMediaInfoFixture.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\Aggregation\Aggregators\Augmenters\Quality\AugmentQualityFromMediaInfoFixture.cs" />
|
||||||
<Compile Include="MediaFiles\EpisodeImport\ImportDecisionMakerFixture.cs" />
|
<Compile Include="MediaFiles\EpisodeImport\ImportDecisionMakerFixture.cs" />
|
||||||
|
@ -392,6 +394,8 @@
|
||||||
<Compile Include="ParserTests\SceneCheckerFixture.cs" />
|
<Compile Include="ParserTests\SceneCheckerFixture.cs" />
|
||||||
<Compile Include="Profiles\ProfileRepositoryFixture.cs" />
|
<Compile Include="Profiles\ProfileRepositoryFixture.cs" />
|
||||||
<Compile Include="Profiles\ProfileServiceFixture.cs" />
|
<Compile Include="Profiles\ProfileServiceFixture.cs" />
|
||||||
|
<Compile Include="Languages\LanguageProfileRepositoryFixture.cs" />
|
||||||
|
<Compile Include="Languages\LanguageProfileServiceFixture.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
<Compile Include="Providers\XemProxyFixture.cs" />
|
<Compile Include="Providers\XemProxyFixture.cs" />
|
||||||
<Compile Include="ProviderTests\DiskProviderTests\ArchiveProviderFixture.cs" />
|
<Compile Include="ProviderTests\DiskProviderTests\ArchiveProviderFixture.cs" />
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
|
||||||
|
@ -9,61 +10,208 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class LanguageParserFixture : CoreTest
|
public class LanguageParserFixture : CoreTest
|
||||||
{
|
{
|
||||||
[TestCase("Castle.2009.S01E14.English.HDTV.XviD-LOL", Language.English)]
|
[TestCase("Castle.2009.S01E14.English.HDTV.XviD-LOL")]
|
||||||
[TestCase("Castle.2009.S01E14.French.HDTV.XviD-LOL", Language.French)]
|
[TestCase("Castle.2009.S01E14.Germany.HDTV.XviD-LOL")]
|
||||||
[TestCase("Castle.2009.S01E14.Spanish.HDTV.XviD-LOL", Language.Spanish)]
|
[TestCase("Castle.2009.S01E14.HDTV.XviD-LOL")]
|
||||||
[TestCase("Castle.2009.S01E14.German.HDTV.XviD-LOL", Language.German)]
|
[TestCase("Two.Greedy.Italians.S01E01.The.Family.720p.HDTV.x264-FTP")]
|
||||||
[TestCase("Castle.2009.S01E14.Germany.HDTV.XviD-LOL", Language.English)]
|
[TestCase("The.Trip.To.Italy.S02E01.720p.HDTV.x264-TLA")]
|
||||||
[TestCase("Castle.2009.S01E14.Italian.HDTV.XviD-LOL", Language.Italian)]
|
[TestCase("2 Broke Girls - S01E01 - Pilot.en.sub")]
|
||||||
[TestCase("Castle.2009.S01E14.Danish.HDTV.XviD-LOL", Language.Danish)]
|
[TestCase("2 Broke Girls - S01E01 - Pilot.eng.sub")]
|
||||||
[TestCase("Castle.2009.S01E14.Dutch.HDTV.XviD-LOL", Language.Dutch)]
|
[TestCase("2 Broke Girls - S01E01 - Pilot.English.sub")]
|
||||||
[TestCase("Castle.2009.S01E14.Japanese.HDTV.XviD-LOL", Language.Japanese)]
|
[TestCase("2 Broke Girls - S01E01 - Pilot.english.sub")]
|
||||||
[TestCase("Castle.2009.S01E14.Cantonese.HDTV.XviD-LOL", Language.Cantonese)]
|
public void should_parse_language_english(string postTitle)
|
||||||
[TestCase("Castle.2009.S01E14.Mandarin.HDTV.XviD-LOL", Language.Mandarin)]
|
|
||||||
[TestCase("Castle.2009.S01E14.Korean.HDTV.XviD-LOL", Language.Korean)]
|
|
||||||
[TestCase("Castle.2009.S01E14.Russian.HDTV.XviD-LOL", Language.Russian)]
|
|
||||||
[TestCase("Castle.2009.S01E14.Polish.HDTV.XviD-LOL", Language.Polish)]
|
|
||||||
[TestCase("Castle.2009.S01E14.Vietnamese.HDTV.XviD-LOL", Language.Vietnamese)]
|
|
||||||
[TestCase("Castle.2009.S01E14.Swedish.HDTV.XviD-LOL", Language.Swedish)]
|
|
||||||
[TestCase("Castle.2009.S01E14.Norwegian.HDTV.XviD-LOL", Language.Norwegian)]
|
|
||||||
[TestCase("Castle.2009.S01E14.Finnish.HDTV.XviD-LOL", Language.Finnish)]
|
|
||||||
[TestCase("Castle.2009.S01E14.Turkish.HDTV.XviD-LOL", Language.Turkish)]
|
|
||||||
[TestCase("Castle.2009.S01E14.Portuguese.HDTV.XviD-LOL", Language.Portuguese)]
|
|
||||||
[TestCase("Castle.2009.S01E14.HDTV.XviD-LOL", Language.English)]
|
|
||||||
[TestCase("person.of.interest.1x19.ita.720p.bdmux.x264-novarip", Language.Italian)]
|
|
||||||
[TestCase("Salamander.S01E01.FLEMISH.HDTV.x264-BRiGAND", Language.Flemish)]
|
|
||||||
[TestCase("H.Polukatoikia.S03E13.Greek.PDTV.XviD-Ouzo", Language.Greek)]
|
|
||||||
[TestCase("Burn.Notice.S04E15.Brotherly.Love.GERMAN.DUBBED.WS.WEBRiP.XviD.REPACK-TVP", Language.German)]
|
|
||||||
[TestCase("Ray Donovan - S01E01.720p.HDtv.x264-Evolve (NLsub)", Language.Dutch)]
|
|
||||||
[TestCase("Shield,.The.1x13.Tueurs.De.Flics.FR.DVDRip.XviD", Language.French)]
|
|
||||||
[TestCase("True.Detective.S01E01.1080p.WEB-DL.Rus.Eng.TVKlondike", Language.Russian)]
|
|
||||||
[TestCase("The.Trip.To.Italy.S02E01.720p.HDTV.x264-TLA", Language.English)]
|
|
||||||
[TestCase("Revolution S01E03 No Quarter 2012 WEB-DL 720p Nordic-philipo mkv", Language.Norwegian)]
|
|
||||||
[TestCase("Extant.S01E01.VOSTFR.HDTV.x264-RiDERS", Language.French)]
|
|
||||||
[TestCase("Constantine.2014.S01E01.WEBRiP.H264.AAC.5.1-NL.SUBS", Language.Dutch)]
|
|
||||||
[TestCase("Elementary - S02E16 - Kampfhaehne - mkv - by Videomann", Language.German)]
|
|
||||||
[TestCase("Two.Greedy.Italians.S01E01.The.Family.720p.HDTV.x264-FTP", Language.English)]
|
|
||||||
[TestCase("Castle.2009.S01E14.HDTV.XviD.HUNDUB-LOL", Language.Hungarian)]
|
|
||||||
[TestCase("Castle.2009.S01E14.HDTV.XviD.ENG.HUN-LOL", Language.Hungarian)]
|
|
||||||
[TestCase("Castle.2009.S01E14.HDTV.XviD.HUN-LOL", Language.Hungarian)]
|
|
||||||
[TestCase("Avatar.The.Last.Airbender.S01-03.DVDRip.HebDub",Language.Hebrew)]
|
|
||||||
[TestCase("Prison.Break.S05E01.WEBRip.x264.AC3.LT.EN-CNN", Language.Lithuanian)]
|
|
||||||
[TestCase("The.Walking.Dead.S07E11.WEB Rip.XviD.Louige-CZ.EN.5.1", Language.Czech)]
|
|
||||||
public void should_parse_language(string postTitle, Language language)
|
|
||||||
{
|
{
|
||||||
var result = LanguageParser.ParseLanguage(postTitle);
|
var result = LanguageParser.ParseLanguage(postTitle);
|
||||||
result.Should().Be(language);
|
result.Should().Be(Language.English);
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("2 Broke Girls - S01E01 - Pilot.en.sub", Language.English)]
|
[TestCase("2 Broke Girls - S01E01 - Pilot.sub")]
|
||||||
[TestCase("2 Broke Girls - S01E01 - Pilot.eng.sub", Language.English)]
|
public void should_parse_subtitle_language_unknown(string fileName)
|
||||||
[TestCase("2 Broke Girls - S01E01 - Pilot.English.sub", Language.English)]
|
|
||||||
[TestCase("2 Broke Girls - S01E01 - Pilot.english.sub", Language.English)]
|
|
||||||
[TestCase("2 Broke Girls - S01E01 - Pilot.sub", Language.Unknown)]
|
|
||||||
public void should_parse_subtitle_language(string fileName, Language language)
|
|
||||||
{
|
{
|
||||||
var result = LanguageParser.ParseSubtitleLanguage(fileName);
|
var result = LanguageParser.ParseSubtitleLanguage(fileName);
|
||||||
result.Should().Be(language);
|
result.Should().Be(Language.Unknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestCase("Castle.2009.S01E14.French.HDTV.XviD-LOL")]
|
||||||
|
[TestCase("Extant.S01E01.VOSTFR.HDTV.x264-RiDERS")]
|
||||||
|
[TestCase("Shield,.The.1x13.Tueurs.De.Flics.FR.DVDRip.XviD")]
|
||||||
|
public void should_parse_language_french(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.French.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Castle.2009.S01E14.Spanish.HDTV.XviD-LOL")]
|
||||||
|
public void should_parse_language_spanish(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.Spanish.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Castle.2009.S01E14.German.HDTV.XviD-LOL")]
|
||||||
|
[TestCase("Burn.Notice.S04E15.Brotherly.Love.GERMAN.DUBBED.WS.WEBRiP.XviD.REPACK-TVP")]
|
||||||
|
[TestCase("Elementary - S02E16 - Kampfhaehne - mkv - by Videomann")]
|
||||||
|
public void should_parse_language_german(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.German.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Castle.2009.S01E14.Italian.HDTV.XviD-LOL")]
|
||||||
|
[TestCase("person.of.interest.1x19.ita.720p.bdmux.x264-novarip")]
|
||||||
|
public void should_parse_language_italian(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.Italian.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Castle.2009.S01E14.Danish.HDTV.XviD-LOL")]
|
||||||
|
public void should_parse_language_danish(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.Danish.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Castle.2009.S01E14.Dutch.HDTV.XviD-LOL")]
|
||||||
|
[TestCase("Constantine.2014.S01E01.WEBRiP.H264.AAC.5.1-NL.SUBS")]
|
||||||
|
[TestCase("Ray Donovan - S01E01.720p.HDtv.x264-Evolve (NLsub)")]
|
||||||
|
public void should_parse_language_dutch(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.Dutch.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Castle.2009.S01E14.Japanese.HDTV.XviD-LOL")]
|
||||||
|
public void should_parse_language_japanese(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.Japanese.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Castle.2009.S01E14.Cantonese.HDTV.XviD-LOL")]
|
||||||
|
public void should_parse_language_cantonese(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.Cantonese.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Castle.2009.S01E14.Mandarin.HDTV.XviD-LOL")]
|
||||||
|
public void should_parse_language_mandarin(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.Mandarin.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Castle.2009.S01E14.Korean.HDTV.XviD-LOL")]
|
||||||
|
public void should_parse_language_korean(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.Korean.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Castle.2009.S01E14.Russian.HDTV.XviD-LOL")]
|
||||||
|
[TestCase("True.Detective.S01E01.1080p.WEB-DL.Rus.Eng.TVKlondike")]
|
||||||
|
public void should_parse_language_russian(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.Russian.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Castle.2009.S01E14.Polish.HDTV.XviD-LOL")]
|
||||||
|
public void should_parse_language_polish(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.Polish.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Castle.2009.S01E14.Vietnamese.HDTV.XviD-LOL")]
|
||||||
|
public void should_parse_language_vietnamese(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.Vietnamese.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Castle.2009.S01E14.Swedish.HDTV.XviD-LOL")]
|
||||||
|
public void should_parse_language_swedish(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.Swedish.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Castle.2009.S01E14.Norwegian.HDTV.XviD-LOL")]
|
||||||
|
[TestCase("Revolution S01E03 No Quarter 2012 WEB-DL 720p Nordic-philipo mkv")]
|
||||||
|
public void should_parse_language_norwegian(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.Norwegian.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Castle.2009.S01E14.Finnish.HDTV.XviD-LOL")]
|
||||||
|
public void should_parse_language_finnish(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.Finnish.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Castle.2009.S01E14.Turkish.HDTV.XviD-LOL")]
|
||||||
|
public void should_parse_language_turkish(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.Turkish.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Castle.2009.S01E14.Portuguese.HDTV.XviD-LOL")]
|
||||||
|
public void should_parse_language_portuguese(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.Portuguese.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Salamander.S01E01.FLEMISH.HDTV.x264-BRiGAND")]
|
||||||
|
public void should_parse_language_flemish(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.Flemish.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("H.Polukatoikia.S03E13.Greek.PDTV.XviD-Ouzo")]
|
||||||
|
public void should_parse_language_greek(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.Greek.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Castle.2009.S01E14.HDTV.XviD.HUNDUB-LOL")]
|
||||||
|
[TestCase("Castle.2009.S01E14.HDTV.XviD.ENG.HUN-LOL")]
|
||||||
|
[TestCase("Castle.2009.S01E14.HDTV.XviD.HUN-LOL")]
|
||||||
|
public void should_parse_language_hungarian(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.Hungarian.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestCase("Avatar.The.Last.Airbender.S01-03.DVDRip.HebDub")]
|
||||||
|
public void should_parse_language_hebrew(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.Hebrew.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[TestCase("Prison.Break.S05E01.WEBRip.x264.AC3.LT.EN-CNN")]
|
||||||
|
public void should_parse_language_lithuanian(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.Lithuanian.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[TestCase("The.Walking.Dead.S07E11.WEB Rip.XviD.Louige-CZ.EN.5.1")]
|
||||||
|
public void should_parse_language_czech(string postTitle)
|
||||||
|
{
|
||||||
|
var result = Parser.Parser.ParseTitle(postTitle);
|
||||||
|
result.Language.Id.Should().Be(Language.Czech.Id);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ using FizzWare.NBuilder;
|
||||||
using Moq;
|
using Moq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.Lifecycle;
|
using NzbDrone.Core.Lifecycle;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
|
||||||
|
|
|
@ -5,11 +5,13 @@ using FizzWare.NBuilder;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
|
namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
|
||||||
{
|
{
|
||||||
|
@ -20,6 +22,7 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
|
||||||
private Series _unmonitoredSeries;
|
private Series _unmonitoredSeries;
|
||||||
private PagingSpec<Episode> _pagingSpec;
|
private PagingSpec<Episode> _pagingSpec;
|
||||||
private List<QualitiesBelowCutoff> _qualitiesBelowCutoff;
|
private List<QualitiesBelowCutoff> _qualitiesBelowCutoff;
|
||||||
|
private List<LanguagesBelowCutoff> _languagesBelowCutoff;
|
||||||
private List<Episode> _unairedEpisodes;
|
private List<Episode> _unairedEpisodes;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
|
@ -37,12 +40,20 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var langProfile = new LanguageProfile
|
||||||
|
{
|
||||||
|
Id = 1,
|
||||||
|
Languages = Languages.LanguageFixture.GetDefaultLanguages(),
|
||||||
|
Cutoff = Language.Spanish
|
||||||
|
};
|
||||||
|
|
||||||
_monitoredSeries = Builder<Series>.CreateNew()
|
_monitoredSeries = Builder<Series>.CreateNew()
|
||||||
.With(s => s.TvRageId = RandomNumber)
|
.With(s => s.TvRageId = RandomNumber)
|
||||||
.With(s => s.Runtime = 30)
|
.With(s => s.Runtime = 30)
|
||||||
.With(s => s.Monitored = true)
|
.With(s => s.Monitored = true)
|
||||||
.With(s => s.TitleSlug = "Title3")
|
.With(s => s.TitleSlug = "Title3")
|
||||||
.With(s => s.Id = profile.Id)
|
.With(s => s.ProfileId = profile.Id)
|
||||||
|
.With(s => s.LanguageProfileId = langProfile.Id)
|
||||||
.BuildNew();
|
.BuildNew();
|
||||||
|
|
||||||
_unmonitoredSeries = Builder<Series>.CreateNew()
|
_unmonitoredSeries = Builder<Series>.CreateNew()
|
||||||
|
@ -50,7 +61,8 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
|
||||||
.With(s => s.Runtime = 30)
|
.With(s => s.Runtime = 30)
|
||||||
.With(s => s.Monitored = false)
|
.With(s => s.Monitored = false)
|
||||||
.With(s => s.TitleSlug = "Title2")
|
.With(s => s.TitleSlug = "Title2")
|
||||||
.With(s => s.Id = profile.Id)
|
.With(s => s.ProfileId = profile.Id)
|
||||||
|
.With(s => s.LanguageProfileId = langProfile.Id)
|
||||||
.BuildNew();
|
.BuildNew();
|
||||||
|
|
||||||
_monitoredSeries.Id = Db.Insert(_monitoredSeries).Id;
|
_monitoredSeries.Id = Db.Insert(_monitoredSeries).Id;
|
||||||
|
@ -69,15 +81,32 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
|
||||||
new QualitiesBelowCutoff(profile.Id, new[] {Quality.SDTV.Id})
|
new QualitiesBelowCutoff(profile.Id, new[] {Quality.SDTV.Id})
|
||||||
};
|
};
|
||||||
|
|
||||||
var qualityMet = new EpisodeFile { RelativePath = "a", Quality = new QualityModel { Quality = Quality.WEBDL480p } };
|
_languagesBelowCutoff = new List<LanguagesBelowCutoff>
|
||||||
var qualityUnmet = new EpisodeFile { RelativePath = "b", Quality = new QualityModel { Quality = Quality.SDTV } };
|
{
|
||||||
var qualityRawHD = new EpisodeFile { RelativePath = "c", Quality = new QualityModel { Quality = Quality.RAWHD } };
|
new LanguagesBelowCutoff(profile.Id, new[] {Language.English.Id})
|
||||||
|
};
|
||||||
|
|
||||||
|
var qualityMetLanguageUnmet = new EpisodeFile { RelativePath = "a", Quality = new QualityModel { Quality = Quality.WEBDL480p } , Language = Language.English };
|
||||||
|
var qualityMetLanguageMet = new EpisodeFile { RelativePath = "b", Quality = new QualityModel { Quality = Quality.WEBDL480p }, Language = Language.Spanish };
|
||||||
|
var qualityMetLanguageExceed = new EpisodeFile { RelativePath = "c", Quality = new QualityModel { Quality = Quality.WEBDL480p }, Language = Language.French };
|
||||||
|
var qualityUnmetLanguageUnmet = new EpisodeFile { RelativePath = "d", Quality = new QualityModel { Quality = Quality.SDTV }, Language = Language.English };
|
||||||
|
var qualityUnmetLanguageMet = new EpisodeFile { RelativePath = "e", Quality = new QualityModel { Quality = Quality.SDTV }, Language = Language.Spanish };
|
||||||
|
var qualityUnmetLanguageExceed = new EpisodeFile { RelativePath = "f", Quality = new QualityModel { Quality = Quality.SDTV }, Language = Language.French };
|
||||||
|
var qualityRawHDLanguageUnmet = new EpisodeFile { RelativePath = "g", Quality = new QualityModel { Quality = Quality.RAWHD }, Language = Language.English };
|
||||||
|
var qualityRawHDLanguageMet = new EpisodeFile { RelativePath = "h", Quality = new QualityModel { Quality = Quality.RAWHD }, Language = Language.Spanish };
|
||||||
|
var qualityRawHDLanguageExceed = new EpisodeFile { RelativePath = "i", Quality = new QualityModel { Quality = Quality.RAWHD }, Language = Language.French };
|
||||||
|
|
||||||
MediaFileRepository fileRepository = Mocker.Resolve<MediaFileRepository>();
|
MediaFileRepository fileRepository = Mocker.Resolve<MediaFileRepository>();
|
||||||
|
|
||||||
qualityMet = fileRepository.Insert(qualityMet);
|
qualityMetLanguageUnmet = fileRepository.Insert(qualityMetLanguageUnmet);
|
||||||
qualityUnmet = fileRepository.Insert(qualityUnmet);
|
qualityMetLanguageMet = fileRepository.Insert(qualityMetLanguageMet);
|
||||||
qualityRawHD = fileRepository.Insert(qualityRawHD);
|
qualityMetLanguageExceed = fileRepository.Insert(qualityMetLanguageExceed);
|
||||||
|
qualityUnmetLanguageUnmet = fileRepository.Insert(qualityUnmetLanguageUnmet);
|
||||||
|
qualityUnmetLanguageMet = fileRepository.Insert(qualityUnmetLanguageMet);
|
||||||
|
qualityUnmetLanguageExceed = fileRepository.Insert(qualityUnmetLanguageExceed);
|
||||||
|
qualityRawHDLanguageUnmet = fileRepository.Insert(qualityRawHDLanguageUnmet);
|
||||||
|
qualityRawHDLanguageMet = fileRepository.Insert(qualityRawHDLanguageMet);
|
||||||
|
qualityRawHDLanguageExceed = fileRepository.Insert(qualityRawHDLanguageExceed);
|
||||||
|
|
||||||
var monitoredSeriesEpisodes = Builder<Episode>.CreateListOfSize(4)
|
var monitoredSeriesEpisodes = Builder<Episode>.CreateListOfSize(4)
|
||||||
.All()
|
.All()
|
||||||
|
@ -85,12 +114,12 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
|
||||||
.With(e => e.SeriesId = _monitoredSeries.Id)
|
.With(e => e.SeriesId = _monitoredSeries.Id)
|
||||||
.With(e => e.AirDateUtc = DateTime.Now.AddDays(-5))
|
.With(e => e.AirDateUtc = DateTime.Now.AddDays(-5))
|
||||||
.With(e => e.Monitored = true)
|
.With(e => e.Monitored = true)
|
||||||
.With(e => e.EpisodeFileId = qualityUnmet.Id)
|
.With(e => e.EpisodeFileId = qualityUnmetLanguageUnmet.Id)
|
||||||
.TheFirst(1)
|
.TheFirst(1)
|
||||||
.With(e => e.Monitored = false)
|
.With(e => e.Monitored = false)
|
||||||
.With(e => e.EpisodeFileId = qualityMet.Id)
|
.With(e => e.EpisodeFileId = qualityMetLanguageMet.Id)
|
||||||
.TheNext(1)
|
.TheNext(1)
|
||||||
.With(e => e.EpisodeFileId = qualityRawHD.Id)
|
.With(e => e.EpisodeFileId = qualityRawHDLanguageExceed.Id)
|
||||||
.TheLast(1)
|
.TheLast(1)
|
||||||
.With(e => e.SeasonNumber = 0)
|
.With(e => e.SeasonNumber = 0)
|
||||||
.Build();
|
.Build();
|
||||||
|
@ -101,10 +130,10 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
|
||||||
.With(e => e.SeriesId = _unmonitoredSeries.Id)
|
.With(e => e.SeriesId = _unmonitoredSeries.Id)
|
||||||
.With(e => e.AirDateUtc = DateTime.Now.AddDays(-5))
|
.With(e => e.AirDateUtc = DateTime.Now.AddDays(-5))
|
||||||
.With(e => e.Monitored = true)
|
.With(e => e.Monitored = true)
|
||||||
.With(e => e.EpisodeFileId = qualityUnmet.Id)
|
.With(e => e.EpisodeFileId = qualityRawHDLanguageUnmet.Id)
|
||||||
.TheFirst(1)
|
.TheFirst(1)
|
||||||
.With(e => e.Monitored = false)
|
.With(e => e.Monitored = false)
|
||||||
.With(e => e.EpisodeFileId = qualityMet.Id)
|
.With(e => e.EpisodeFileId = qualityMetLanguageMet.Id)
|
||||||
.TheLast(1)
|
.TheLast(1)
|
||||||
.With(e => e.SeasonNumber = 0)
|
.With(e => e.SeasonNumber = 0)
|
||||||
.Build();
|
.Build();
|
||||||
|
@ -116,7 +145,7 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
|
||||||
.With(e => e.SeriesId = _monitoredSeries.Id)
|
.With(e => e.SeriesId = _monitoredSeries.Id)
|
||||||
.With(e => e.AirDateUtc = DateTime.Now.AddDays(5))
|
.With(e => e.AirDateUtc = DateTime.Now.AddDays(5))
|
||||||
.With(e => e.Monitored = true)
|
.With(e => e.Monitored = true)
|
||||||
.With(e => e.EpisodeFileId = qualityUnmet.Id)
|
.With(e => e.EpisodeFileId = qualityUnmetLanguageUnmet.Id)
|
||||||
.Build()
|
.Build()
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
@ -139,7 +168,7 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
|
||||||
{
|
{
|
||||||
GivenMonitoredFilterExpression();
|
GivenMonitoredFilterExpression();
|
||||||
|
|
||||||
var spec = Subject.EpisodesWhereCutoffUnmet(_pagingSpec, _qualitiesBelowCutoff, false);
|
var spec = Subject.EpisodesWhereCutoffUnmet(_pagingSpec, _qualitiesBelowCutoff, _languagesBelowCutoff, false);
|
||||||
|
|
||||||
spec.Records.Should().HaveCount(1);
|
spec.Records.Should().HaveCount(1);
|
||||||
spec.Records.Should().OnlyContain(e => e.EpisodeFile.Value.Quality.Quality == Quality.SDTV);
|
spec.Records.Should().OnlyContain(e => e.EpisodeFile.Value.Quality.Quality == Quality.SDTV);
|
||||||
|
@ -150,7 +179,7 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
|
||||||
{
|
{
|
||||||
GivenMonitoredFilterExpression();
|
GivenMonitoredFilterExpression();
|
||||||
|
|
||||||
var spec = Subject.EpisodesWhereCutoffUnmet(_pagingSpec, _qualitiesBelowCutoff, false);
|
var spec = Subject.EpisodesWhereCutoffUnmet(_pagingSpec, _qualitiesBelowCutoff, _languagesBelowCutoff, false);
|
||||||
|
|
||||||
spec.Records.Should().HaveCount(1);
|
spec.Records.Should().HaveCount(1);
|
||||||
spec.Records.Should().OnlyContain(e => e.Monitored);
|
spec.Records.Should().OnlyContain(e => e.Monitored);
|
||||||
|
@ -161,7 +190,7 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
|
||||||
{
|
{
|
||||||
GivenMonitoredFilterExpression();
|
GivenMonitoredFilterExpression();
|
||||||
|
|
||||||
var spec = Subject.EpisodesWhereCutoffUnmet(_pagingSpec, _qualitiesBelowCutoff, false);
|
var spec = Subject.EpisodesWhereCutoffUnmet(_pagingSpec, _qualitiesBelowCutoff, _languagesBelowCutoff, false);
|
||||||
|
|
||||||
spec.Records.Should().HaveCount(1);
|
spec.Records.Should().HaveCount(1);
|
||||||
spec.Records.Should().OnlyContain(e => e.Series.Monitored);
|
spec.Records.Should().OnlyContain(e => e.Series.Monitored);
|
||||||
|
@ -174,7 +203,7 @@ namespace NzbDrone.Core.Test.TvTests.EpisodeRepositoryTests
|
||||||
|
|
||||||
GivenMonitoredFilterExpression();
|
GivenMonitoredFilterExpression();
|
||||||
|
|
||||||
var spec = Subject.EpisodesWhereCutoffUnmet(_pagingSpec, _qualitiesBelowCutoff, false);
|
var spec = Subject.EpisodesWhereCutoffUnmet(_pagingSpec, _qualitiesBelowCutoff, _languagesBelowCutoff, false);
|
||||||
|
|
||||||
spec.Records.Should().HaveCount(2);
|
spec.Records.Should().HaveCount(2);
|
||||||
spec.Records.Should().OnlyContain(e => e.Series.Monitored);
|
spec.Records.Should().OnlyContain(e => e.Series.Monitored);
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
using FizzWare.NBuilder;
|
using FizzWare.NBuilder;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.Profiles;
|
using System.Linq;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.TvTests.SeriesRepositoryTests
|
namespace NzbDrone.Core.Test.TvTests.SeriesRepositoryTests
|
||||||
{
|
{
|
||||||
|
@ -23,16 +26,26 @@ namespace NzbDrone.Core.Test.TvTests.SeriesRepositoryTests
|
||||||
Name = "TestProfile"
|
Name = "TestProfile"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var langProfile = new LanguageProfile
|
||||||
|
{
|
||||||
|
Name = "TestProfile",
|
||||||
|
Languages = Languages.LanguageFixture.GetDefaultLanguages(Language.English),
|
||||||
|
Cutoff = Language.English
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
Mocker.Resolve<ProfileRepository>().Insert(profile);
|
Mocker.Resolve<ProfileRepository>().Insert(profile);
|
||||||
|
Mocker.Resolve<LanguageProfileRepository>().Insert(langProfile);
|
||||||
|
|
||||||
var series = Builder<Series>.CreateNew().BuildNew();
|
var series = Builder<Series>.CreateNew().BuildNew();
|
||||||
series.ProfileId = profile.Id;
|
series.ProfileId = profile.Id;
|
||||||
|
series.LanguageProfileId = langProfile.Id;
|
||||||
|
|
||||||
Subject.Insert(series);
|
Subject.Insert(series);
|
||||||
|
|
||||||
|
|
||||||
StoredModel.Profile.Should().NotBeNull();
|
StoredModel.Profile.Should().NotBeNull();
|
||||||
|
StoredModel.LanguageProfile.Should().NotBeNull();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.Indexers;
|
using NzbDrone.Core.Indexers;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Blacklisting
|
namespace NzbDrone.Core.Blacklisting
|
||||||
{
|
{
|
||||||
|
@ -21,5 +22,6 @@ namespace NzbDrone.Core.Blacklisting
|
||||||
public string Indexer { get; set; }
|
public string Indexer { get; set; }
|
||||||
public string Message { get; set; }
|
public string Message { get; set; }
|
||||||
public string TorrentInfoHash { get; set; }
|
public string TorrentInfoHash { get; set; }
|
||||||
|
public Language Language { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,7 +138,8 @@ namespace NzbDrone.Core.Blacklisting
|
||||||
Indexer = message.Data.GetValueOrDefault("indexer"),
|
Indexer = message.Data.GetValueOrDefault("indexer"),
|
||||||
Protocol = (DownloadProtocol)Convert.ToInt32(message.Data.GetValueOrDefault("protocol")),
|
Protocol = (DownloadProtocol)Convert.ToInt32(message.Data.GetValueOrDefault("protocol")),
|
||||||
Message = message.Message,
|
Message = message.Message,
|
||||||
TorrentInfoHash = message.Data.GetValueOrDefault("torrentInfoHash")
|
TorrentInfoHash = message.Data.GetValueOrDefault("torrentInfoHash"),
|
||||||
|
Language = message.Language
|
||||||
};
|
};
|
||||||
|
|
||||||
_blacklistRepository.Insert(blacklist);
|
_blacklistRepository.Insert(blacklist);
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
using System;
|
||||||
|
using Marr.Data.Converters;
|
||||||
|
using Marr.Data.Mapping;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Converters
|
||||||
|
{
|
||||||
|
public class LanguageIntConverter : JsonConverter, IConverter
|
||||||
|
{
|
||||||
|
public object FromDB(ConverterContext context)
|
||||||
|
{
|
||||||
|
if (context.DbValue == DBNull.Value)
|
||||||
|
{
|
||||||
|
return Language.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
var val = Convert.ToInt32(context.DbValue);
|
||||||
|
|
||||||
|
return (Language)val;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object FromDB(ColumnMap map, object dbValue)
|
||||||
|
{
|
||||||
|
return FromDB(new ConverterContext { ColumnMap = map, DbValue = dbValue });
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ToDB(object clrValue)
|
||||||
|
{
|
||||||
|
if (clrValue == DBNull.Value) return 0;
|
||||||
|
|
||||||
|
if (clrValue as Language == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Attempted to save a language that isn't really a language");
|
||||||
|
}
|
||||||
|
|
||||||
|
var language = clrValue as Language;
|
||||||
|
return (int)language;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type DbType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return typeof(int);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool CanConvert(Type objectType)
|
||||||
|
{
|
||||||
|
return objectType == typeof(Language);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
var item = reader.Value;
|
||||||
|
return (Language)Convert.ToInt32(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
||||||
|
{
|
||||||
|
writer.WriteValue(ToDB(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
using System.Data;
|
using System.Data;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NzbDrone.Common.Serializer;
|
using NzbDrone.Common.Serializer;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NzbDrone.Core.Datastore.Converters;
|
using NzbDrone.Core.Datastore.Converters;
|
||||||
|
|
|
@ -1 +1,97 @@
|
||||||
// This is a placeholder for migration 102
|
using System.Data;
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
using NzbDrone.Core.Datastore.Converters;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(102)]
|
||||||
|
public class add_language_to_episodeFiles_history_and_blacklist : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Alter.Table("EpisodeFiles")
|
||||||
|
.AddColumn("Language").AsInt32().NotNullable().WithDefaultValue(0);
|
||||||
|
|
||||||
|
Alter.Table("History")
|
||||||
|
.AddColumn("Language").AsInt32().NotNullable().WithDefaultValue(0);
|
||||||
|
|
||||||
|
Alter.Table("Blacklist")
|
||||||
|
.AddColumn("Language").AsInt32().NotNullable().WithDefaultValue(0);
|
||||||
|
|
||||||
|
Execute.WithConnection(UpdateLanguage);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateLanguage(IDbConnection conn, IDbTransaction tran)
|
||||||
|
{
|
||||||
|
var LanguageConverter = new EmbeddedDocumentConverter(new LanguageIntConverter());
|
||||||
|
|
||||||
|
using (IDbCommand getSeriesCmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
getSeriesCmd.Transaction = tran;
|
||||||
|
getSeriesCmd.CommandText = @"SELECT Id, ProfileId FROM Series";
|
||||||
|
using (IDataReader seriesReader = getSeriesCmd.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (seriesReader.Read())
|
||||||
|
{
|
||||||
|
var seriesId = seriesReader.GetInt32(0);
|
||||||
|
var seriesProfileId = seriesReader.GetInt32(1);
|
||||||
|
|
||||||
|
using (IDbCommand getProfileCmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
getProfileCmd.Transaction = tran;
|
||||||
|
getProfileCmd.CommandText = "SELECT Language FROM Profiles WHERE Id = ?";
|
||||||
|
getProfileCmd.AddParameter(seriesProfileId);
|
||||||
|
IDataReader profilesReader = getProfileCmd.ExecuteReader();
|
||||||
|
while (profilesReader.Read())
|
||||||
|
{
|
||||||
|
var episodeLanguage = Language.English.Id;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
episodeLanguage = profilesReader.GetInt32(0);
|
||||||
|
} catch (InvalidCastException e)
|
||||||
|
{
|
||||||
|
_logger.Debug("Language field not found in Profiles, using English as default." + e.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
var validJson = LanguageConverter.ToDB(Language.FindById(episodeLanguage));
|
||||||
|
|
||||||
|
using (IDbCommand updateEpisodeFilesCmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
updateEpisodeFilesCmd.Transaction = tran;
|
||||||
|
updateEpisodeFilesCmd.CommandText = "UPDATE EpisodeFiles SET Language = ? WHERE SeriesId = ?";
|
||||||
|
updateEpisodeFilesCmd.AddParameter(validJson);
|
||||||
|
updateEpisodeFilesCmd.AddParameter(seriesId);
|
||||||
|
|
||||||
|
updateEpisodeFilesCmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
using (IDbCommand updateHistoryCmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
updateHistoryCmd.Transaction = tran;
|
||||||
|
updateHistoryCmd.CommandText = "UPDATE History SET Language = ? WHERE SeriesId = ?";
|
||||||
|
updateHistoryCmd.AddParameter(validJson);
|
||||||
|
updateHistoryCmd.AddParameter(seriesId);
|
||||||
|
|
||||||
|
updateHistoryCmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
using (IDbCommand updateBlacklistCmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
updateBlacklistCmd.Transaction = tran;
|
||||||
|
updateBlacklistCmd.CommandText = "UPDATE Blacklist SET Language = ? WHERE SeriesId = ?";
|
||||||
|
updateBlacklistCmd.AddParameter(validJson);
|
||||||
|
updateBlacklistCmd.AddParameter(seriesId);
|
||||||
|
|
||||||
|
updateBlacklistCmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1 +1,180 @@
|
||||||
// This is a placeholder for migration 111
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Converters;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(111)]
|
||||||
|
public class create_language_profiles : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Create.TableForModel("LanguageProfiles").WithColumn("Name").AsString().Unique()
|
||||||
|
.WithColumn("Languages").AsString()
|
||||||
|
.WithColumn("Cutoff").AsInt32();
|
||||||
|
|
||||||
|
Alter.Table("Series").AddColumn("LanguageProfileId").AsInt32().WithDefaultValue(1);
|
||||||
|
|
||||||
|
Execute.WithConnection(InsertDefaultLanguages);
|
||||||
|
|
||||||
|
Delete.Column("Language").FromTable("Profiles");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void InsertDefaultLanguages(IDbConnection conn, IDbTransaction tran)
|
||||||
|
{
|
||||||
|
var profiles = GetLanguageProfiles(conn, tran);
|
||||||
|
var languageConverter = new EmbeddedDocumentConverter(new LanguageIntConverter());
|
||||||
|
|
||||||
|
foreach (var profile in profiles.OrderBy(p => p.Id))
|
||||||
|
{
|
||||||
|
using (IDbCommand insertNewLanguageProfileCmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
var itemsJson = languageConverter.ToDB(profile.Languages);
|
||||||
|
insertNewLanguageProfileCmd.Transaction = tran;
|
||||||
|
insertNewLanguageProfileCmd.CommandText = "INSERT INTO LanguageProfiles (Id, Name, Cutoff, Languages) VALUES (?, ?, ?, ?)";
|
||||||
|
insertNewLanguageProfileCmd.AddParameter(profile.Id);
|
||||||
|
insertNewLanguageProfileCmd.AddParameter(profile.Name);
|
||||||
|
insertNewLanguageProfileCmd.AddParameter(profile.Cutoff.Id);
|
||||||
|
insertNewLanguageProfileCmd.AddParameter(itemsJson);
|
||||||
|
|
||||||
|
insertNewLanguageProfileCmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
using (IDbCommand updateSeriesCmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
foreach (var profileId in profile.ProfileIds)
|
||||||
|
{
|
||||||
|
updateSeriesCmd.Transaction = tran;
|
||||||
|
updateSeriesCmd.CommandText = "UPDATE Series SET LanguageProfileId = ? WHERE ProfileId = ?";
|
||||||
|
updateSeriesCmd.AddParameter(profile.Id);
|
||||||
|
updateSeriesCmd.AddParameter(profileId);
|
||||||
|
updateSeriesCmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<LanguageProfile111> GetDefaultLanguageProfiles()
|
||||||
|
{
|
||||||
|
var profiles = new List<LanguageProfile111>();
|
||||||
|
|
||||||
|
var languages = GetOrderedLanguages().Select(v => new LanguageProfileItem111 { Language = v, Allowed = v == Language.English })
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
profiles.Add(new LanguageProfile111
|
||||||
|
{
|
||||||
|
Id = 1,
|
||||||
|
Name = "English",
|
||||||
|
Cutoff = Language.English,
|
||||||
|
Languages = languages
|
||||||
|
});
|
||||||
|
|
||||||
|
return profiles;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<LanguageProfile111> GetLanguageProfiles(IDbConnection conn, IDbTransaction tran)
|
||||||
|
{
|
||||||
|
var profiles = GetDefaultLanguageProfiles();
|
||||||
|
var thereAreProfiles = false;
|
||||||
|
|
||||||
|
using (IDbCommand getProfilesCmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
getProfilesCmd.Transaction = tran;
|
||||||
|
getProfilesCmd.CommandText = @"SELECT Id, Language FROM Profiles";
|
||||||
|
|
||||||
|
using (IDataReader profileReader = getProfilesCmd.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (profileReader.Read())
|
||||||
|
{
|
||||||
|
thereAreProfiles = true;
|
||||||
|
var profileId = profileReader.GetInt32(0);
|
||||||
|
var lang = Language.English.Id;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
lang = profileReader.GetInt32(1);
|
||||||
|
}
|
||||||
|
catch (InvalidCastException e)
|
||||||
|
{
|
||||||
|
_logger.Debug("Language field not found in Profiles, using English as default." + e.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (profiles.None(p => p.Cutoff.Id == lang))
|
||||||
|
{
|
||||||
|
var language = Language.FindById(lang);
|
||||||
|
var languages = GetOrderedLanguages().Select(l => new LanguageProfileItem111 { Language = l, Allowed = l.Id == lang })
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
profiles.Add(new LanguageProfile111
|
||||||
|
{
|
||||||
|
Id = profiles.Count + 1,
|
||||||
|
Name = language.Name,
|
||||||
|
Cutoff = language,
|
||||||
|
Languages = languages,
|
||||||
|
ProfileIds = new List<int> { profileId }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
profiles = profiles.Select(p =>
|
||||||
|
{
|
||||||
|
if (p.Cutoff.Id == lang)
|
||||||
|
{
|
||||||
|
p.ProfileIds.Add(profileId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!thereAreProfiles)
|
||||||
|
{
|
||||||
|
return new List<LanguageProfile111>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return profiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Language> GetOrderedLanguages()
|
||||||
|
{
|
||||||
|
var orderedLanguages = Language.All
|
||||||
|
.Where(l => l != Language.Unknown)
|
||||||
|
.OrderByDescending(l => l.Name)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
orderedLanguages.Insert(0, Language.Unknown);
|
||||||
|
|
||||||
|
return orderedLanguages;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LanguageProfile111
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public List<int> ProfileIds { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
public Language Cutoff { get; set; }
|
||||||
|
public List<LanguageProfileItem111> Languages { get; set; }
|
||||||
|
|
||||||
|
public LanguageProfile111 ()
|
||||||
|
{
|
||||||
|
ProfileIds = new List<int>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class LanguageProfileItem111
|
||||||
|
{
|
||||||
|
public Language Language { get; set; }
|
||||||
|
public bool Allowed { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ using NzbDrone.Core.RemotePathMappings;
|
||||||
using NzbDrone.Core.Notifications;
|
using NzbDrone.Core.Notifications;
|
||||||
using NzbDrone.Core.Organizer;
|
using NzbDrone.Core.Organizer;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Profiles;
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Restrictions;
|
using NzbDrone.Core.Restrictions;
|
||||||
using NzbDrone.Core.RootFolders;
|
using NzbDrone.Core.RootFolders;
|
||||||
|
@ -35,6 +35,8 @@ using NzbDrone.Core.Extras.Metadata.Files;
|
||||||
using NzbDrone.Core.Extras.Others;
|
using NzbDrone.Core.Extras.Others;
|
||||||
using NzbDrone.Core.Extras.Subtitles;
|
using NzbDrone.Core.Extras.Subtitles;
|
||||||
using NzbDrone.Core.Messaging.Commands;
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Datastore
|
namespace NzbDrone.Core.Datastore
|
||||||
{
|
{
|
||||||
|
@ -82,7 +84,8 @@ namespace NzbDrone.Core.Datastore
|
||||||
Mapper.Entity<Series>().RegisterModel("Series")
|
Mapper.Entity<Series>().RegisterModel("Series")
|
||||||
.Ignore(s => s.RootFolderPath)
|
.Ignore(s => s.RootFolderPath)
|
||||||
.Relationship()
|
.Relationship()
|
||||||
.HasOne(s => s.Profile, s => s.ProfileId);
|
.HasOne(s => s.Profile, s => s.ProfileId)
|
||||||
|
.HasOne(s => s.LanguageProfile, s => s.LanguageProfileId);
|
||||||
|
|
||||||
Mapper.Entity<EpisodeFile>().RegisterModel("EpisodeFiles")
|
Mapper.Entity<EpisodeFile>().RegisterModel("EpisodeFiles")
|
||||||
.Ignore(f => f.Path)
|
.Ignore(f => f.Path)
|
||||||
|
@ -103,6 +106,7 @@ namespace NzbDrone.Core.Datastore
|
||||||
.Ignore(d => d.Weight);
|
.Ignore(d => d.Weight);
|
||||||
|
|
||||||
Mapper.Entity<Profile>().RegisterModel("Profiles");
|
Mapper.Entity<Profile>().RegisterModel("Profiles");
|
||||||
|
Mapper.Entity<LanguageProfile>().RegisterModel("LanguageProfiles");
|
||||||
Mapper.Entity<Log>().RegisterModel("Logs");
|
Mapper.Entity<Log>().RegisterModel("Logs");
|
||||||
Mapper.Entity<NamingConfig>().RegisterModel("NamingConfig");
|
Mapper.Entity<NamingConfig>().RegisterModel("NamingConfig");
|
||||||
Mapper.Entity<SeasonStatistics>().MapResultSet();
|
Mapper.Entity<SeasonStatistics>().MapResultSet();
|
||||||
|
@ -144,7 +148,9 @@ namespace NzbDrone.Core.Datastore
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(QualityModel), new EmbeddedDocumentConverter(new QualityIntConverter()));
|
MapRepository.Instance.RegisterTypeConverter(typeof(QualityModel), new EmbeddedDocumentConverter(new QualityIntConverter()));
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(Dictionary<string, string>), new EmbeddedDocumentConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(Dictionary<string, string>), new EmbeddedDocumentConverter());
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(List<int>), new EmbeddedDocumentConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(List<int>), new EmbeddedDocumentConverter());
|
||||||
|
MapRepository.Instance.RegisterTypeConverter(typeof(Language), new LanguageIntConverter());
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(List<string>), new EmbeddedDocumentConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(List<string>), new EmbeddedDocumentConverter());
|
||||||
|
MapRepository.Instance.RegisterTypeConverter(typeof(List<LanguageProfileItem>), new EmbeddedDocumentConverter(new LanguageIntConverter()));
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(ParsedEpisodeInfo), new EmbeddedDocumentConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(ParsedEpisodeInfo), new EmbeddedDocumentConverter());
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(ReleaseInfo), new EmbeddedDocumentConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(ReleaseInfo), new EmbeddedDocumentConverter());
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(HashSet<int>), new EmbeddedDocumentConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(HashSet<int>), new EmbeddedDocumentConverter());
|
||||||
|
|
|
@ -24,6 +24,7 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
var comparers = new List<CompareDelegate>
|
var comparers = new List<CompareDelegate>
|
||||||
{
|
{
|
||||||
CompareQuality,
|
CompareQuality,
|
||||||
|
CompareLanguage,
|
||||||
CompareProtocol,
|
CompareProtocol,
|
||||||
CompareEpisodeCount,
|
CompareEpisodeCount,
|
||||||
CompareEpisodeNumber,
|
CompareEpisodeNumber,
|
||||||
|
@ -62,6 +63,11 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.ParsedEpisodeInfo.Quality.Revision.Version));
|
CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.ParsedEpisodeInfo.Quality.Revision.Version));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int CompareLanguage(DownloadDecision x, DownloadDecision y)
|
||||||
|
{
|
||||||
|
return CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode => remoteEpisode.Series.LanguageProfile.Value.Languages.FindIndex(l => l.Language == remoteEpisode.ParsedEpisodeInfo.Language));
|
||||||
|
}
|
||||||
|
|
||||||
private int CompareProtocol(DownloadDecision x, DownloadDecision y)
|
private int CompareProtocol(DownloadDecision x, DownloadDecision y)
|
||||||
{
|
{
|
||||||
var result = CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode =>
|
var result = CompareBy(x.RemoteEpisode, y.RemoteEpisode, remoteEpisode =>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NzbDrone.Core.Profiles.Delay;
|
using NzbDrone.Core.Profiles.Delay;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.DecisionEngine
|
namespace NzbDrone.Core.DecisionEngine
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Profiles;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.DecisionEngine
|
||||||
|
{
|
||||||
|
public interface ILanguageUpgradableSpecification
|
||||||
|
{
|
||||||
|
bool IsUpgradable(Profile profile, LanguageModel currentLanguage, LanguageModel newLanguage = null);
|
||||||
|
bool CutoffNotMet(Profile profile, LanguageModel currentLanguage, LanguageModel newLanguage = null);
|
||||||
|
bool IsRevisionUpgrade(LanguageModel currentLanguage, LanguageModel newLanguage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class LanguageUpgradableSpecification : ILanguageUpgradableSpecification
|
||||||
|
{
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public LanguageUpgradableSpecification(Logger logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsUpgradable(Profile profile, LanguageModel currentLanguage, LanguageModel newLanguage = null)
|
||||||
|
{
|
||||||
|
if (newLanguage != null)
|
||||||
|
{
|
||||||
|
int compare = new LanguageModelComparer(profile).Compare(newLanguage, currentLanguage);
|
||||||
|
if (compare <= 0)
|
||||||
|
{
|
||||||
|
_logger.Debug("existing item has better or equal language. skipping");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsRevisionUpgrade(currentLanguage, newLanguage))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CutoffNotMet(Profile profile, LanguageModel currentLanguage, LanguageModel newLanguage = null)
|
||||||
|
{
|
||||||
|
int compare = new LanguageModelComparer(profile).Compare(currentLanguage.Language, profile.Languages.Find(v => v.Allowed == true).Language);
|
||||||
|
|
||||||
|
if (compare >= 0)
|
||||||
|
{
|
||||||
|
if (newLanguage != null && IsRevisionUpgrade(currentLanguage, newLanguage))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.Debug("Existing item meets cut-off. skipping.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsRevisionUpgrade(LanguageModel currentLanguage, LanguageModel newLanguage)
|
||||||
|
{
|
||||||
|
int compare = newLanguage.Revision.CompareTo(currentLanguage.Revision);
|
||||||
|
|
||||||
|
if (currentLanguage.Language == newLanguage.Language && compare > 0)
|
||||||
|
{
|
||||||
|
_logger.Debug("New language is a better revision for existing quality");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,72 +0,0 @@
|
||||||
using NLog;
|
|
||||||
using NzbDrone.Core.Profiles;
|
|
||||||
using NzbDrone.Core.Qualities;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.DecisionEngine
|
|
||||||
{
|
|
||||||
public interface IQualityUpgradableSpecification
|
|
||||||
{
|
|
||||||
bool IsUpgradable(Profile profile, QualityModel currentQuality, QualityModel newQuality = null);
|
|
||||||
bool CutoffNotMet(Profile profile, QualityModel currentQuality, QualityModel newQuality = null);
|
|
||||||
bool IsRevisionUpgrade(QualityModel currentQuality, QualityModel newQuality);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class QualityUpgradableSpecification : IQualityUpgradableSpecification
|
|
||||||
{
|
|
||||||
private readonly Logger _logger;
|
|
||||||
|
|
||||||
public QualityUpgradableSpecification(Logger logger)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsUpgradable(Profile profile, QualityModel currentQuality, QualityModel newQuality = null)
|
|
||||||
{
|
|
||||||
if (newQuality != null)
|
|
||||||
{
|
|
||||||
int compare = new QualityModelComparer(profile).Compare(newQuality, currentQuality);
|
|
||||||
if (compare <= 0)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (IsRevisionUpgrade(currentQuality, newQuality))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CutoffNotMet(Profile profile, QualityModel currentQuality, QualityModel newQuality = null)
|
|
||||||
{
|
|
||||||
var compare = new QualityModelComparer(profile).Compare(currentQuality.Quality, profile.Cutoff);
|
|
||||||
|
|
||||||
if (compare < 0)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newQuality != null && IsRevisionUpgrade(currentQuality, newQuality))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsRevisionUpgrade(QualityModel currentQuality, QualityModel newQuality)
|
|
||||||
{
|
|
||||||
var compare = newQuality.Revision.CompareTo(currentQuality.Revision);
|
|
||||||
|
|
||||||
if (currentQuality.Quality == newQuality.Quality && compare > 0)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -9,12 +9,12 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
{
|
{
|
||||||
public class AnimeVersionUpgradeSpecification : IDecisionEngineSpecification
|
public class AnimeVersionUpgradeSpecification : IDecisionEngineSpecification
|
||||||
{
|
{
|
||||||
private readonly QualityUpgradableSpecification _qualityUpgradableSpecification;
|
private readonly UpgradableSpecification _upgradableSpecification;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public AnimeVersionUpgradeSpecification(QualityUpgradableSpecification qualityUpgradableSpecification, Logger logger)
|
public AnimeVersionUpgradeSpecification(UpgradableSpecification UpgradableSpecification, Logger logger)
|
||||||
{
|
{
|
||||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
_upgradableSpecification = UpgradableSpecification;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
|
|
||||||
foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value))
|
foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value))
|
||||||
{
|
{
|
||||||
if (_qualityUpgradableSpecification.IsRevisionUpgrade(file.Quality, subject.ParsedEpisodeInfo.Quality))
|
if (_upgradableSpecification.IsRevisionUpgrade(file.Quality, subject.ParsedEpisodeInfo.Quality))
|
||||||
{
|
{
|
||||||
if (file.ReleaseGroup.IsNullOrWhiteSpace())
|
if (file.ReleaseGroup.IsNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,12 +7,12 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
{
|
{
|
||||||
public class CutoffSpecification : IDecisionEngineSpecification
|
public class CutoffSpecification : IDecisionEngineSpecification
|
||||||
{
|
{
|
||||||
private readonly QualityUpgradableSpecification _qualityUpgradableSpecification;
|
private readonly UpgradableSpecification _upgradableSpecification;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public CutoffSpecification(QualityUpgradableSpecification qualityUpgradableSpecification, Logger logger)
|
public CutoffSpecification(UpgradableSpecification UpgradableSpecification, Logger logger)
|
||||||
{
|
{
|
||||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
_upgradableSpecification = UpgradableSpecification;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,13 +28,16 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
_logger.Debug("File is no longer available, skipping this file.");
|
_logger.Debug("File is no longer available, skipping this file.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
_logger.Debug("Comparing file quality and language with report. Existing file is {0} - {1}", file.Quality, file.Language);
|
||||||
|
|
||||||
_logger.Debug("Comparing file quality with report. Existing file is {0}", file.Quality);
|
if (!_upgradableSpecification.CutoffNotMet(subject.Series.Profile,
|
||||||
|
subject.Series.LanguageProfile,
|
||||||
if (!_qualityUpgradableSpecification.CutoffNotMet(subject.Series.Profile, file.Quality, subject.ParsedEpisodeInfo.Quality))
|
file.Quality,
|
||||||
|
file.Language,
|
||||||
|
subject.ParsedEpisodeInfo.Quality))
|
||||||
{
|
{
|
||||||
_logger.Debug("Cutoff already met, rejecting.");
|
_logger.Debug("Cutoff already met, rejecting.");
|
||||||
return Decision.Reject("Existing file meets cutoff: {0}", subject.Series.Profile.Value.Cutoff);
|
return Decision.Reject("Existing file meets cutoff: {0} - {1}", subject.Series.Profile.Value.Cutoff, subject.Series.LanguageProfile.Value.Cutoff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using System.Linq;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
|
||||||
|
@ -18,14 +19,15 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
|
|
||||||
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
public virtual Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCriteria)
|
||||||
{
|
{
|
||||||
var wantedLanguage = subject.Series.Profile.Value.Language;
|
var wantedLanguage = subject.Series.LanguageProfile.Value.Languages;
|
||||||
|
var _language = subject.ParsedEpisodeInfo.Language;
|
||||||
|
|
||||||
_logger.Debug("Checking if report meets language requirements. {0}", subject.ParsedEpisodeInfo.Language);
|
_logger.Debug("Checking if report meets language requirements. {0}", subject.ParsedEpisodeInfo.Language);
|
||||||
|
|
||||||
if (subject.ParsedEpisodeInfo.Language != wantedLanguage)
|
if (!wantedLanguage.Exists(v => v.Allowed && v.Language == _language))
|
||||||
{
|
{
|
||||||
_logger.Debug("Report Language: {0} rejected because it is not wanted, wanted {1}", subject.ParsedEpisodeInfo.Language, wantedLanguage);
|
_logger.Debug("Report Language: {0} rejected because it is not wanted in profile {1}", _language, subject.Series.LanguageProfile.Value.Name);
|
||||||
return Decision.Reject("{0} is wanted, but found {1}", wantedLanguage, subject.ParsedEpisodeInfo.Language);
|
return Decision.Reject("{0} is not allowed in profile {1}", _language, subject.Series.LanguageProfile.Value.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Decision.Accept();
|
return Decision.Accept();
|
||||||
|
|
|
@ -9,15 +9,15 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
public class QueueSpecification : IDecisionEngineSpecification
|
public class QueueSpecification : IDecisionEngineSpecification
|
||||||
{
|
{
|
||||||
private readonly IQueueService _queueService;
|
private readonly IQueueService _queueService;
|
||||||
private readonly QualityUpgradableSpecification _qualityUpgradableSpecification;
|
private readonly UpgradableSpecification _upgradableSpecification;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public QueueSpecification(IQueueService queueService,
|
public QueueSpecification(IQueueService queueService,
|
||||||
QualityUpgradableSpecification qualityUpgradableSpecification,
|
UpgradableSpecification UpgradableSpecification,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
{
|
{
|
||||||
_queueService = queueService;
|
_queueService = queueService;
|
||||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
_upgradableSpecification = UpgradableSpecification;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,18 +34,27 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
|
|
||||||
foreach (var remoteEpisode in matchingEpisode)
|
foreach (var remoteEpisode in matchingEpisode)
|
||||||
{
|
{
|
||||||
_logger.Debug("Checking if existing release in queue meets cutoff. Queued quality is: {0}", remoteEpisode.ParsedEpisodeInfo.Quality);
|
_logger.Debug("Checking if existing release in queue meets cutoff. Queued quality is: {0} - {1}", remoteEpisode.ParsedEpisodeInfo.Quality, remoteEpisode.ParsedEpisodeInfo.Language);
|
||||||
|
|
||||||
if (!_qualityUpgradableSpecification.CutoffNotMet(subject.Series.Profile, remoteEpisode.ParsedEpisodeInfo.Quality, subject.ParsedEpisodeInfo.Quality))
|
if (!_upgradableSpecification.CutoffNotMet(subject.Series.Profile,
|
||||||
|
subject.Series.LanguageProfile,
|
||||||
|
remoteEpisode.ParsedEpisodeInfo.Quality,
|
||||||
|
remoteEpisode.ParsedEpisodeInfo.Language,
|
||||||
|
subject.ParsedEpisodeInfo.Quality))
|
||||||
{
|
{
|
||||||
return Decision.Reject("Quality for release in queue already meets cutoff: {0}", remoteEpisode.ParsedEpisodeInfo.Quality);
|
return Decision.Reject("Quality for release in queue already meets cutoff: {0} - {1}", remoteEpisode.ParsedEpisodeInfo.Quality, remoteEpisode.ParsedEpisodeInfo.Language);
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Debug("Checking if release is higher quality than queued release. Queued quality is: {0}", remoteEpisode.ParsedEpisodeInfo.Quality);
|
_logger.Debug("Checking if release is higher quality than queued release. Queued quality is: {0} - {1}", remoteEpisode.ParsedEpisodeInfo.Quality, remoteEpisode.ParsedEpisodeInfo.Language);
|
||||||
|
|
||||||
if (!_qualityUpgradableSpecification.IsUpgradable(subject.Series.Profile, remoteEpisode.ParsedEpisodeInfo.Quality, subject.ParsedEpisodeInfo.Quality))
|
if (!_upgradableSpecification.IsUpgradable(subject.Series.Profile,
|
||||||
|
subject.Series.LanguageProfile,
|
||||||
|
remoteEpisode.ParsedEpisodeInfo.Quality,
|
||||||
|
remoteEpisode.ParsedEpisodeInfo.Language,
|
||||||
|
subject.ParsedEpisodeInfo.Quality,
|
||||||
|
subject.ParsedEpisodeInfo.Language))
|
||||||
{
|
{
|
||||||
return Decision.Reject("Quality for release in queue is of equal or higher preference: {0}", remoteEpisode.ParsedEpisodeInfo.Quality);
|
return Decision.Reject("Quality for release in queue is of equal or higher preference: {0} - {1}", remoteEpisode.ParsedEpisodeInfo.Quality, remoteEpisode.ParsedEpisodeInfo.Language);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,23 +5,24 @@ using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Profiles.Delay;
|
using NzbDrone.Core.Profiles.Delay;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||||
{
|
{
|
||||||
public class DelaySpecification : IDecisionEngineSpecification
|
public class DelaySpecification : IDecisionEngineSpecification
|
||||||
{
|
{
|
||||||
private readonly IPendingReleaseService _pendingReleaseService;
|
private readonly IPendingReleaseService _pendingReleaseService;
|
||||||
private readonly IQualityUpgradableSpecification _qualityUpgradableSpecification;
|
private readonly IUpgradableSpecification _upgradableSpecification;
|
||||||
private readonly IDelayProfileService _delayProfileService;
|
private readonly IDelayProfileService _delayProfileService;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public DelaySpecification(IPendingReleaseService pendingReleaseService,
|
public DelaySpecification(IPendingReleaseService pendingReleaseService,
|
||||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
IUpgradableSpecification UpgradableSpecification,
|
||||||
IDelayProfileService delayProfileService,
|
IDelayProfileService delayProfileService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
{
|
{
|
||||||
_pendingReleaseService = pendingReleaseService;
|
_pendingReleaseService = pendingReleaseService;
|
||||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
_upgradableSpecification = UpgradableSpecification;
|
||||||
_delayProfileService = delayProfileService;
|
_delayProfileService = delayProfileService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
@ -38,6 +39,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||||
}
|
}
|
||||||
|
|
||||||
var profile = subject.Series.Profile.Value;
|
var profile = subject.Series.Profile.Value;
|
||||||
|
var languageProfile = subject.Series.LanguageProfile.Value;
|
||||||
var delayProfile = _delayProfileService.BestForTags(subject.Series.Tags);
|
var delayProfile = _delayProfileService.BestForTags(subject.Series.Tags);
|
||||||
var delay = delayProfile.GetProtocolDelay(subject.Release.DownloadProtocol);
|
var delay = delayProfile.GetProtocolDelay(subject.Release.DownloadProtocol);
|
||||||
var isPreferredProtocol = subject.Release.DownloadProtocol == delayProfile.PreferredProtocol;
|
var isPreferredProtocol = subject.Release.DownloadProtocol == delayProfile.PreferredProtocol;
|
||||||
|
@ -49,33 +51,35 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||||
}
|
}
|
||||||
|
|
||||||
var comparer = new QualityModelComparer(profile);
|
var comparer = new QualityModelComparer(profile);
|
||||||
|
var comparerLanguage = new LanguageComparer(languageProfile);
|
||||||
|
|
||||||
if (isPreferredProtocol)
|
if (isPreferredProtocol)
|
||||||
{
|
{
|
||||||
foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value))
|
foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value))
|
||||||
{
|
{
|
||||||
var upgradable = _qualityUpgradableSpecification.IsUpgradable(profile, file.Quality, subject.ParsedEpisodeInfo.Quality);
|
var upgradable = _upgradableSpecification.IsUpgradable(profile,
|
||||||
|
languageProfile,
|
||||||
|
file.Quality,
|
||||||
|
file.Language,
|
||||||
|
subject.ParsedEpisodeInfo.Quality,
|
||||||
|
subject.ParsedEpisodeInfo.Language);
|
||||||
|
|
||||||
if (upgradable)
|
if (upgradable)
|
||||||
{
|
|
||||||
var revisionUpgrade = _qualityUpgradableSpecification.IsRevisionUpgrade(file.Quality, subject.ParsedEpisodeInfo.Quality);
|
|
||||||
|
|
||||||
if (revisionUpgrade)
|
|
||||||
{
|
{
|
||||||
_logger.Debug("New quality is a better revision for existing quality, skipping delay");
|
_logger.Debug("New quality is a better revision for existing quality, skipping delay");
|
||||||
return Decision.Accept();
|
return Decision.Accept();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If quality meets or exceeds the best allowed quality in the profile accept it immediately
|
// If quality meets or exceeds the best allowed quality in the profile accept it immediately
|
||||||
var bestQualityInProfile = new QualityModel(profile.LastAllowedQuality());
|
var bestQualityInProfile = new QualityModel(profile.LastAllowedQuality());
|
||||||
var isBestInProfile = comparer.Compare(subject.ParsedEpisodeInfo.Quality, bestQualityInProfile) >= 0;
|
var isBestInProfile = comparer.Compare(subject.ParsedEpisodeInfo.Quality, bestQualityInProfile) >= 0;
|
||||||
|
var isBestInProfileLanguage = comparerLanguage.Compare(subject.ParsedEpisodeInfo.Language, languageProfile.LastAllowedLanguage()) >= 0;
|
||||||
|
|
||||||
if (isBestInProfile && isPreferredProtocol)
|
if (isBestInProfile && isBestInProfileLanguage && isPreferredProtocol)
|
||||||
{
|
{
|
||||||
_logger.Debug("Quality is highest in profile for preferred protocol, will not delay");
|
_logger.Debug("Quality and language is highest in profile for preferred protocol, will not delay");
|
||||||
return Decision.Accept();
|
return Decision.Accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,17 +11,17 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||||
public class HistorySpecification : IDecisionEngineSpecification
|
public class HistorySpecification : IDecisionEngineSpecification
|
||||||
{
|
{
|
||||||
private readonly IHistoryService _historyService;
|
private readonly IHistoryService _historyService;
|
||||||
private readonly QualityUpgradableSpecification _qualityUpgradableSpecification;
|
private readonly UpgradableSpecification _upgradableSpecification;
|
||||||
private readonly IConfigService _configService;
|
private readonly IConfigService _configService;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public HistorySpecification(IHistoryService historyService,
|
public HistorySpecification(IHistoryService historyService,
|
||||||
QualityUpgradableSpecification qualityUpgradableSpecification,
|
UpgradableSpecification upgradableSpecification,
|
||||||
IConfigService configService,
|
IConfigService configService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
{
|
{
|
||||||
_historyService = historyService;
|
_historyService = historyService;
|
||||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
_upgradableSpecification = upgradableSpecification;
|
||||||
_configService = configService;
|
_configService = configService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
@ -48,8 +48,8 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||||
if (mostRecent != null && mostRecent.EventType == HistoryEventType.Grabbed)
|
if (mostRecent != null && mostRecent.EventType == HistoryEventType.Grabbed)
|
||||||
{
|
{
|
||||||
var recent = mostRecent.Date.After(DateTime.UtcNow.AddHours(-12));
|
var recent = mostRecent.Date.After(DateTime.UtcNow.AddHours(-12));
|
||||||
var cutoffUnmet = _qualityUpgradableSpecification.CutoffNotMet(subject.Series.Profile, mostRecent.Quality, subject.ParsedEpisodeInfo.Quality);
|
var cutoffUnmet = _upgradableSpecification.CutoffNotMet(subject.Series.Profile, subject.Series.LanguageProfile, mostRecent.Quality, mostRecent.Language, subject.ParsedEpisodeInfo.Quality);
|
||||||
var upgradeable = _qualityUpgradableSpecification.IsUpgradable(subject.Series.Profile, mostRecent.Quality, subject.ParsedEpisodeInfo.Quality);
|
var upgradeable = _upgradableSpecification.IsUpgradable(subject.Series.Profile, subject.Series.LanguageProfile, mostRecent.Quality, mostRecent.Language, subject.ParsedEpisodeInfo.Quality, subject.ParsedEpisodeInfo.Language);
|
||||||
|
|
||||||
if (!recent && cdhEnabled)
|
if (!recent && cdhEnabled)
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,13 +9,13 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||||
{
|
{
|
||||||
public class ProperSpecification : IDecisionEngineSpecification
|
public class ProperSpecification : IDecisionEngineSpecification
|
||||||
{
|
{
|
||||||
private readonly QualityUpgradableSpecification _qualityUpgradableSpecification;
|
private readonly UpgradableSpecification _upgradableSpecification;
|
||||||
private readonly IConfigService _configService;
|
private readonly IConfigService _configService;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public ProperSpecification(QualityUpgradableSpecification qualityUpgradableSpecification, IConfigService configService, Logger logger)
|
public ProperSpecification(UpgradableSpecification upgradableSpecification, IConfigService configService, Logger logger)
|
||||||
{
|
{
|
||||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
_upgradableSpecification = upgradableSpecification;
|
||||||
_configService = configService;
|
_configService = configService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||||
|
|
||||||
foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value))
|
foreach (var file in subject.Episodes.Where(c => c.EpisodeFileId != 0).Select(c => c.EpisodeFile.Value))
|
||||||
{
|
{
|
||||||
if (_qualityUpgradableSpecification.IsRevisionUpgrade(file.Quality, subject.ParsedEpisodeInfo.Quality))
|
if (_upgradableSpecification.IsRevisionUpgrade(file.Quality, subject.ParsedEpisodeInfo.Quality))
|
||||||
{
|
{
|
||||||
if (file.DateAdded < DateTime.Today.AddDays(-7))
|
if (file.DateAdded < DateTime.Today.AddDays(-7))
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,12 +7,12 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
{
|
{
|
||||||
public class UpgradeDiskSpecification : IDecisionEngineSpecification
|
public class UpgradeDiskSpecification : IDecisionEngineSpecification
|
||||||
{
|
{
|
||||||
private readonly QualityUpgradableSpecification _qualityUpgradableSpecification;
|
private readonly UpgradableSpecification _upgradableSpecification;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public UpgradeDiskSpecification(QualityUpgradableSpecification qualityUpgradableSpecification, Logger logger)
|
public UpgradeDiskSpecification(UpgradableSpecification upgradableSpecification, Logger logger)
|
||||||
{
|
{
|
||||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
_upgradableSpecification = upgradableSpecification;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,11 +29,17 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.Debug("Comparing file quality with report. Existing file is {0}", file.Quality);
|
_logger.Debug("Comparing file quality and language with report. Existing file is {0} - {1}", file.Quality, file.Language);
|
||||||
|
|
||||||
if (!_qualityUpgradableSpecification.IsUpgradable(subject.Series.Profile, file.Quality, subject.ParsedEpisodeInfo.Quality))
|
|
||||||
|
if (!_upgradableSpecification.IsUpgradable(subject.Series.Profile,
|
||||||
|
subject.Series.LanguageProfile,
|
||||||
|
file.Quality,
|
||||||
|
file.Language,
|
||||||
|
subject.ParsedEpisodeInfo.Quality,
|
||||||
|
subject.ParsedEpisodeInfo.Language))
|
||||||
{
|
{
|
||||||
return Decision.Reject("Quality for existing file on disk is of equal or higher preference: {0}", file.Quality);
|
return Decision.Reject("Quality for existing file on disk is of equal or higher preference: {0} - {1}", file.Quality, file.Language);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.DecisionEngine
|
||||||
|
{
|
||||||
|
public interface IUpgradableSpecification
|
||||||
|
{
|
||||||
|
bool IsUpgradable(Profile profile, LanguageProfile languageProfile, QualityModel currentQuality, Language currentLanguage, QualityModel newQuality, Language newLanguage);
|
||||||
|
bool QualityCutoffNotMet(Profile profile, QualityModel currentQuality, QualityModel newQuality = null);
|
||||||
|
bool LanguageCutoffNotMet(LanguageProfile languageProfile, Language currentLanguage);
|
||||||
|
bool CutoffNotMet(Profile profile, LanguageProfile languageProfile, QualityModel currentQuality, Language currentLanguage, QualityModel newQuality = null);
|
||||||
|
bool IsRevisionUpgrade(QualityModel currentQuality, QualityModel newQuality);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class UpgradableSpecification : IUpgradableSpecification
|
||||||
|
{
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public UpgradableSpecification(Logger logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsLanguageUpgradable(LanguageProfile profile, Language currentLanguage, Language newLanguage = null)
|
||||||
|
{
|
||||||
|
if (newLanguage != null)
|
||||||
|
{
|
||||||
|
var compare = new LanguageComparer(profile).Compare(newLanguage, currentLanguage);
|
||||||
|
if (compare <= 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsQualityUpgradable(Profile profile, QualityModel currentQuality, QualityModel newQuality = null)
|
||||||
|
{
|
||||||
|
if (newQuality != null)
|
||||||
|
{
|
||||||
|
var compare = new QualityModelComparer(profile).Compare(newQuality, currentQuality);
|
||||||
|
if (compare <= 0)
|
||||||
|
{
|
||||||
|
_logger.Debug("existing item has better quality. skipping");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public bool IsUpgradable(Profile profile, LanguageProfile languageProfile, QualityModel currentQuality, Language currentLanguage, QualityModel newQuality, Language newLanguage)
|
||||||
|
{
|
||||||
|
// If qualities are the same then check language
|
||||||
|
if (newQuality != null && currentQuality == newQuality)
|
||||||
|
{
|
||||||
|
return IsLanguageUpgradable(languageProfile, currentLanguage, newLanguage);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If quality is worse then always return false
|
||||||
|
if (!IsQualityUpgradable(profile, currentQuality, newQuality))
|
||||||
|
{
|
||||||
|
_logger.Debug("existing item has better quality. skipping");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool QualityCutoffNotMet(Profile profile, QualityModel currentQuality, QualityModel newQuality = null)
|
||||||
|
{
|
||||||
|
var qualityCompare = new QualityModelComparer(profile).Compare(currentQuality.Quality, profile.Cutoff);
|
||||||
|
|
||||||
|
if (qualityCompare < 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qualityCompare == 0 && newQuality != null && IsRevisionUpgrade(currentQuality, newQuality))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool LanguageCutoffNotMet(LanguageProfile languageProfile, Language currentLanguage)
|
||||||
|
{
|
||||||
|
var languageCompare = new LanguageComparer(languageProfile).Compare(currentLanguage, languageProfile.Cutoff);
|
||||||
|
|
||||||
|
return languageCompare < 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CutoffNotMet(Profile profile, LanguageProfile languageProfile, QualityModel currentQuality, Language currentLanguage, QualityModel newQuality = null)
|
||||||
|
{
|
||||||
|
// If we can upgrade the language (it is not the cutoff) then doesn't matter the quality we can always get same quality with prefered language
|
||||||
|
if (LanguageCutoffNotMet(languageProfile, currentLanguage))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (QualityCutoffNotMet(profile, currentQuality, newQuality))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.Debug("Existing item meets cut-off. skipping.");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsRevisionUpgrade(QualityModel currentQuality, QualityModel newQuality)
|
||||||
|
{
|
||||||
|
var compare = newQuality.Revision.CompareTo(currentQuality.Revision);
|
||||||
|
|
||||||
|
if (currentQuality.Quality == newQuality.Quality && compare > 0)
|
||||||
|
{
|
||||||
|
_logger.Debug("New quality is a better revision for existing quality");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
using NzbDrone.Common.Messaging;
|
using NzbDrone.Common.Messaging;
|
||||||
using NzbDrone.Core.Download.TrackedDownloads;
|
using NzbDrone.Core.Download.TrackedDownloads;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Download
|
namespace NzbDrone.Core.Download
|
||||||
{
|
{
|
||||||
|
@ -21,5 +22,6 @@ namespace NzbDrone.Core.Download
|
||||||
public string Message { get; set; }
|
public string Message { get; set; }
|
||||||
public Dictionary<string, string> Data { get; set; }
|
public Dictionary<string, string> Data { get; set; }
|
||||||
public TrackedDownload TrackedDownload { get; set; }
|
public TrackedDownload TrackedDownload { get; set; }
|
||||||
|
public Language Language { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -95,7 +95,8 @@ namespace NzbDrone.Core.Download
|
||||||
DownloadId = historyItem.DownloadId,
|
DownloadId = historyItem.DownloadId,
|
||||||
Message = message,
|
Message = message,
|
||||||
Data = historyItem.Data,
|
Data = historyItem.Data,
|
||||||
TrackedDownload = trackedDownload
|
TrackedDownload = trackedDownload,
|
||||||
|
Language = historyItem.Language
|
||||||
};
|
};
|
||||||
|
|
||||||
_eventAggregator.PublishEvent(downloadFailedEvent);
|
_eventAggregator.PublishEvent(downloadFailedEvent);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
using NzbDrone.Core.Extras.Files;
|
using NzbDrone.Core.Extras.Files;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Extras.Subtitles
|
namespace NzbDrone.Core.Extras.Subtitles
|
||||||
{
|
{
|
||||||
|
|
|
@ -7,6 +7,7 @@ using NzbDrone.Common.Disk;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Extras.Files;
|
using NzbDrone.Core.Extras.Files;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.History
|
namespace NzbDrone.Core.History
|
||||||
{
|
{
|
||||||
|
@ -24,6 +25,7 @@ namespace NzbDrone.Core.History
|
||||||
public Series Series { get; set; }
|
public Series Series { get; set; }
|
||||||
public HistoryEventType EventType { get; set; }
|
public HistoryEventType EventType { get; set; }
|
||||||
public Dictionary<string, string> Data { get; set; }
|
public Dictionary<string, string> Data { get; set; }
|
||||||
|
public Language Language { get; set; }
|
||||||
|
|
||||||
public string DownloadId { get; set; }
|
public string DownloadId { get; set; }
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,6 @@ namespace NzbDrone.Core.History
|
||||||
{
|
{
|
||||||
public interface IHistoryRepository : IBasicRepository<History>
|
public interface IHistoryRepository : IBasicRepository<History>
|
||||||
{
|
{
|
||||||
List<QualityModel> GetBestQualityInHistory(int episodeId);
|
|
||||||
History MostRecentForEpisode(int episodeId);
|
History MostRecentForEpisode(int episodeId);
|
||||||
List<History> FindByEpisodeId(int episodeId);
|
List<History> FindByEpisodeId(int episodeId);
|
||||||
History MostRecentForDownloadId(string downloadId);
|
History MostRecentForDownloadId(string downloadId);
|
||||||
|
@ -31,14 +30,6 @@ namespace NzbDrone.Core.History
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public List<QualityModel> GetBestQualityInHistory(int episodeId)
|
|
||||||
{
|
|
||||||
var history = Query.Where(c => c.EpisodeId == episodeId);
|
|
||||||
|
|
||||||
return history.Select(h => h.Quality).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public History MostRecentForEpisode(int episodeId)
|
public History MostRecentForEpisode(int episodeId)
|
||||||
{
|
{
|
||||||
return Query.Where(h => h.EpisodeId == episodeId)
|
return Query.Where(h => h.EpisodeId == episodeId)
|
||||||
|
|
|
@ -11,15 +11,16 @@ using NzbDrone.Core.MediaFiles;
|
||||||
using NzbDrone.Core.MediaFiles.Events;
|
using NzbDrone.Core.MediaFiles.Events;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Profiles;
|
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
using NzbDrone.Core.Tv.Events;
|
using NzbDrone.Core.Tv.Events;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.History
|
namespace NzbDrone.Core.History
|
||||||
{
|
{
|
||||||
public interface IHistoryService
|
public interface IHistoryService
|
||||||
{
|
{
|
||||||
QualityModel GetBestQualityInHistory(Profile profile, int episodeId);
|
|
||||||
PagingSpec<History> Paged(PagingSpec<History> pagingSpec);
|
PagingSpec<History> Paged(PagingSpec<History> pagingSpec);
|
||||||
History MostRecentForEpisode(int episodeId);
|
History MostRecentForEpisode(int episodeId);
|
||||||
List<History> FindByEpisodeId(int episodeId);
|
List<History> FindByEpisodeId(int episodeId);
|
||||||
|
@ -94,14 +95,6 @@ namespace NzbDrone.Core.History
|
||||||
return _historyRepository.FindByDownloadId(downloadId);
|
return _historyRepository.FindByDownloadId(downloadId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public QualityModel GetBestQualityInHistory(Profile profile, int episodeId)
|
|
||||||
{
|
|
||||||
var comparer = new QualityModelComparer(profile);
|
|
||||||
return _historyRepository.GetBestQualityInHistory(episodeId)
|
|
||||||
.OrderByDescending(q => q, comparer)
|
|
||||||
.FirstOrDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
private string FindDownloadId(EpisodeImportedEvent trackedDownload)
|
private string FindDownloadId(EpisodeImportedEvent trackedDownload)
|
||||||
{
|
{
|
||||||
_logger.Debug("Trying to find downloadId for {0} from history", trackedDownload.ImportedEpisode.Path);
|
_logger.Debug("Trying to find downloadId for {0} from history", trackedDownload.ImportedEpisode.Path);
|
||||||
|
@ -159,7 +152,8 @@ namespace NzbDrone.Core.History
|
||||||
SourceTitle = message.Episode.Release.Title,
|
SourceTitle = message.Episode.Release.Title,
|
||||||
SeriesId = episode.SeriesId,
|
SeriesId = episode.SeriesId,
|
||||||
EpisodeId = episode.Id,
|
EpisodeId = episode.Id,
|
||||||
DownloadId = message.DownloadId
|
DownloadId = message.DownloadId,
|
||||||
|
Language = message.Episode.ParsedEpisodeInfo.Language
|
||||||
};
|
};
|
||||||
|
|
||||||
history.Data.Add("Indexer", message.Episode.Release.Indexer);
|
history.Data.Add("Indexer", message.Episode.Release.Indexer);
|
||||||
|
@ -217,7 +211,8 @@ namespace NzbDrone.Core.History
|
||||||
SourceTitle = message.ImportedEpisode.SceneName ?? Path.GetFileNameWithoutExtension(message.EpisodeInfo.Path),
|
SourceTitle = message.ImportedEpisode.SceneName ?? Path.GetFileNameWithoutExtension(message.EpisodeInfo.Path),
|
||||||
SeriesId = message.ImportedEpisode.SeriesId,
|
SeriesId = message.ImportedEpisode.SeriesId,
|
||||||
EpisodeId = episode.Id,
|
EpisodeId = episode.Id,
|
||||||
DownloadId = downloadId
|
DownloadId = downloadId,
|
||||||
|
Language = message.EpisodeInfo.Language
|
||||||
};
|
};
|
||||||
|
|
||||||
//Won't have a value since we publish this event before saving to DB.
|
//Won't have a value since we publish this event before saving to DB.
|
||||||
|
@ -242,7 +237,8 @@ namespace NzbDrone.Core.History
|
||||||
SourceTitle = message.SourceTitle,
|
SourceTitle = message.SourceTitle,
|
||||||
SeriesId = message.SeriesId,
|
SeriesId = message.SeriesId,
|
||||||
EpisodeId = episodeId,
|
EpisodeId = episodeId,
|
||||||
DownloadId = message.DownloadId
|
DownloadId = message.DownloadId,
|
||||||
|
Language = message.Language
|
||||||
};
|
};
|
||||||
|
|
||||||
history.Data.Add("DownloadClient", message.DownloadClient);
|
history.Data.Add("DownloadClient", message.DownloadClient);
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Housekeeping.Housekeepers
|
||||||
|
{
|
||||||
|
// For some unknown reason series added through the v2 API can be added without a lanuage profile ID, which breaks things later.
|
||||||
|
// This ensures there is a language profile ID and it's valid as a safety net.
|
||||||
|
|
||||||
|
public class EnsureValidLanguageProfileId : IHousekeepingTask
|
||||||
|
{
|
||||||
|
private readonly ISeriesRepository _seriesRepository;
|
||||||
|
private readonly ILanguageProfileService _languageProfileService;
|
||||||
|
|
||||||
|
public EnsureValidLanguageProfileId(ISeriesRepository seriesRepository, ILanguageProfileService languageProfileService)
|
||||||
|
{
|
||||||
|
_seriesRepository = seriesRepository;
|
||||||
|
_languageProfileService = languageProfileService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clean()
|
||||||
|
{
|
||||||
|
var languageProfiles = _languageProfileService.All();
|
||||||
|
var firstLangaugeProfile = languageProfiles.First();
|
||||||
|
var series = _seriesRepository.All().ToList();
|
||||||
|
var seriesToUpdate = new List<Series>();
|
||||||
|
|
||||||
|
series.ForEach(s =>
|
||||||
|
{
|
||||||
|
if (s.LanguageProfileId == 0 || languageProfiles.None(l => l.Id == s.LanguageProfileId))
|
||||||
|
{
|
||||||
|
s.LanguageProfileId = firstLangaugeProfile.Id;
|
||||||
|
seriesToUpdate.Add(s);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_seriesRepository.UpdateMany(seriesToUpdate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,158 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Languages
|
||||||
|
{
|
||||||
|
public class Language : IEmbeddedDocument, IEquatable<Language>
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public Language()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private Language(int id, string name)
|
||||||
|
{
|
||||||
|
Id = id;
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return Id.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(Language other)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, other)) return false;
|
||||||
|
if (ReferenceEquals(this, other)) return true;
|
||||||
|
return Id.Equals(other.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, obj)) return false;
|
||||||
|
if (ReferenceEquals(this, obj)) return true;
|
||||||
|
|
||||||
|
return Equals(obj as Language);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(Language left, Language right)
|
||||||
|
{
|
||||||
|
return Equals(left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(Language left, Language right)
|
||||||
|
{
|
||||||
|
return !Equals(left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Language Unknown { get { return new Language(0, "Unknown"); } }
|
||||||
|
public static Language English { get { return new Language(1, "English"); } }
|
||||||
|
public static Language French { get { return new Language(2, "French"); } }
|
||||||
|
public static Language Spanish { get { return new Language(3, "Spanish"); } }
|
||||||
|
public static Language German { get { return new Language(4, "German"); } }
|
||||||
|
public static Language Italian { get { return new Language(5, "Italian"); } }
|
||||||
|
public static Language Danish { get { return new Language(6, "Danish"); } }
|
||||||
|
public static Language Dutch { get { return new Language(7, "Dutch"); } }
|
||||||
|
public static Language Japanese { get { return new Language(8, "Japanese"); } }
|
||||||
|
public static Language Cantonese { get { return new Language(9, "Cantonese"); } }
|
||||||
|
public static Language Mandarin { get { return new Language(10, "Mandarin"); } }
|
||||||
|
public static Language Russian { get { return new Language(11, "Russian"); } }
|
||||||
|
public static Language Polish { get { return new Language(12, "Polish"); } }
|
||||||
|
public static Language Vietnamese { get { return new Language(13, "Vietnamese"); } }
|
||||||
|
public static Language Swedish { get { return new Language(14, "Swedish"); } }
|
||||||
|
public static Language Norwegian { get { return new Language(15, "Norwegian"); } }
|
||||||
|
public static Language Finnish { get { return new Language(16, "Finnish"); } }
|
||||||
|
public static Language Turkish { get { return new Language(17, "Turkish"); } }
|
||||||
|
public static Language Portuguese { get { return new Language(18, "Portuguese"); } }
|
||||||
|
public static Language Flemish { get { return new Language(19, "Flemish"); } }
|
||||||
|
public static Language Greek { get { return new Language(20, "Greek"); } }
|
||||||
|
public static Language Korean { get { return new Language(21, "Korean"); } }
|
||||||
|
public static Language Hungarian { get { return new Language(22, "Hungarian"); } }
|
||||||
|
public static Language Hebrew { get { return new Language(23, "Hebrew"); } }
|
||||||
|
public static Language Lithuanian { get { return new Language(24, "Lithuanian"); } }
|
||||||
|
public static Language Czech { get { return new Language(25, "Czech"); } }
|
||||||
|
|
||||||
|
|
||||||
|
public static List<Language> All
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return new List<Language>
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
English,
|
||||||
|
French,
|
||||||
|
Spanish,
|
||||||
|
German,
|
||||||
|
Italian,
|
||||||
|
Danish,
|
||||||
|
Dutch,
|
||||||
|
Japanese,
|
||||||
|
Cantonese,
|
||||||
|
Mandarin,
|
||||||
|
Russian,
|
||||||
|
Polish,
|
||||||
|
Vietnamese,
|
||||||
|
Swedish,
|
||||||
|
Norwegian,
|
||||||
|
Finnish,
|
||||||
|
Turkish,
|
||||||
|
Portuguese,
|
||||||
|
Flemish,
|
||||||
|
Greek,
|
||||||
|
Korean,
|
||||||
|
Hungarian,
|
||||||
|
Hebrew,
|
||||||
|
Lithuanian,
|
||||||
|
Czech
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Language FindById(int id)
|
||||||
|
{
|
||||||
|
if (id == 0) return Unknown;
|
||||||
|
|
||||||
|
Language language = All.FirstOrDefault(v => v.Id == id);
|
||||||
|
|
||||||
|
if (language == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("ID does not match a known language", nameof(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
return language;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static explicit operator Language(int id)
|
||||||
|
{
|
||||||
|
return FindById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static explicit operator int(Language language)
|
||||||
|
{
|
||||||
|
return language.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static explicit operator Language(string lang)
|
||||||
|
{
|
||||||
|
var language = All.FirstOrDefault(v => v.Name.Equals(lang, StringComparison.InvariantCultureIgnoreCase));
|
||||||
|
|
||||||
|
if (language == null)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("Language does not match a known language", nameof(lang));
|
||||||
|
}
|
||||||
|
|
||||||
|
return language;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NzbDrone.Common.EnsureThat;
|
||||||
|
using NzbDrone.Core.Profiles.Languages;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Languages
|
||||||
|
{
|
||||||
|
public class LanguageComparer : IComparer<Language>
|
||||||
|
{
|
||||||
|
private readonly LanguageProfile _profile;
|
||||||
|
|
||||||
|
public LanguageComparer(LanguageProfile profile)
|
||||||
|
{
|
||||||
|
Ensure.That(profile, () => profile).IsNotNull();
|
||||||
|
Ensure.That(profile.Languages, () => profile.Languages).HasItems();
|
||||||
|
|
||||||
|
_profile = profile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Compare(Language left, Language right)
|
||||||
|
{
|
||||||
|
int leftIndex = _profile.Languages.FindIndex(v => v.Language == left);
|
||||||
|
int rightIndex = _profile.Languages.FindIndex(v => v.Language == right);
|
||||||
|
|
||||||
|
return leftIndex.CompareTo(rightIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Languages
|
||||||
|
{
|
||||||
|
public class LanguagesBelowCutoff
|
||||||
|
{
|
||||||
|
public int ProfileId { get; set; }
|
||||||
|
public IEnumerable<int> LanguageIds { get; set; }
|
||||||
|
|
||||||
|
public LanguagesBelowCutoff(int profileId, IEnumerable<int> languageIds)
|
||||||
|
{
|
||||||
|
ProfileId = profileId;
|
||||||
|
LanguageIds = languageIds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
using NzbDrone.Core.MediaFiles.MediaInfo;
|
using NzbDrone.Core.MediaFiles.MediaInfo;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.MediaFiles
|
namespace NzbDrone.Core.MediaFiles
|
||||||
{
|
{
|
||||||
|
@ -24,6 +25,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
public MediaInfoModel MediaInfo { get; set; }
|
public MediaInfoModel MediaInfo { get; set; }
|
||||||
public LazyLoaded<List<Episode>> Episodes { get; set; }
|
public LazyLoaded<List<Episode>> Episodes { get; set; }
|
||||||
public LazyLoaded<Series> Series { get; set; }
|
public LazyLoaded<Series> Series { get; set; }
|
||||||
|
public Language Language { get; set; }
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.MediaFiles.EpisodeImport.Aggregation.Aggregators
|
||||||
|
{
|
||||||
|
public class AggregateLanguage : IAggregateLocalEpisode
|
||||||
|
{
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public AggregateLanguage(Logger logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocalEpisode Aggregate(LocalEpisode localEpisode, bool otherFiles)
|
||||||
|
{
|
||||||
|
// Get languages in preferred order, download client item, folder and finally file.
|
||||||
|
// Non-English languages will be preferred later, in the event there is a conflict
|
||||||
|
// between parsed languages the more preferred item will be used.
|
||||||
|
|
||||||
|
var languages = new List<Language>
|
||||||
|
{
|
||||||
|
GetLanguage(localEpisode.DownloadClientEpisodeInfo),
|
||||||
|
GetLanguage(localEpisode.FolderEpisodeInfo),
|
||||||
|
GetLanguage(localEpisode.FileEpisodeInfo)
|
||||||
|
};
|
||||||
|
|
||||||
|
var language = languages.FirstOrDefault(l => l != Language.English) ?? Language.English;
|
||||||
|
|
||||||
|
_logger.Debug("Using language: {0}", language);
|
||||||
|
|
||||||
|
localEpisode.Language = language;
|
||||||
|
|
||||||
|
return localEpisode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Language GetLanguage(ParsedEpisodeInfo parsedEpisodeInfo)
|
||||||
|
{
|
||||||
|
if (parsedEpisodeInfo == null)
|
||||||
|
{
|
||||||
|
// English is the default language when otherwise unknown
|
||||||
|
|
||||||
|
return Language.English;
|
||||||
|
}
|
||||||
|
|
||||||
|
return parsedEpisodeInfo.Language;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Disk;
|
using NzbDrone.Common.Disk;
|
||||||
|
using NzbDrone.Common.Exceptions;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.MediaFiles.Events;
|
using NzbDrone.Core.MediaFiles.Events;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
@ -12,7 +13,7 @@ using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
using NzbDrone.Core.Extras;
|
using NzbDrone.Core.Extras;
|
||||||
using NzbDrone.Common.Exceptions;
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||||
{
|
{
|
||||||
|
@ -50,6 +51,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||||
var qualifiedImports = decisions.Where(c => c.Approved)
|
var qualifiedImports = decisions.Where(c => c.Approved)
|
||||||
.GroupBy(c => c.LocalEpisode.Series.Id, (i, s) => s
|
.GroupBy(c => c.LocalEpisode.Series.Id, (i, s) => s
|
||||||
.OrderByDescending(c => c.LocalEpisode.Quality, new QualityModelComparer(s.First().LocalEpisode.Series.Profile))
|
.OrderByDescending(c => c.LocalEpisode.Quality, new QualityModelComparer(s.First().LocalEpisode.Series.Profile))
|
||||||
|
.ThenByDescending(c => c.LocalEpisode.Language, new LanguageComparer(s.First().LocalEpisode.Series.LanguageProfile))
|
||||||
.ThenByDescending(c => c.LocalEpisode.Size))
|
.ThenByDescending(c => c.LocalEpisode.Size))
|
||||||
.SelectMany(c => c)
|
.SelectMany(c => c)
|
||||||
.ToList();
|
.ToList();
|
||||||
|
@ -84,6 +86,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||||
episodeFile.SeasonNumber = localEpisode.SeasonNumber;
|
episodeFile.SeasonNumber = localEpisode.SeasonNumber;
|
||||||
episodeFile.Episodes = localEpisode.Episodes;
|
episodeFile.Episodes = localEpisode.Episodes;
|
||||||
episodeFile.ReleaseGroup = localEpisode.ReleaseGroup;
|
episodeFile.ReleaseGroup = localEpisode.ReleaseGroup;
|
||||||
|
episodeFile.Language = localEpisode.Language;
|
||||||
|
|
||||||
bool copyOnly;
|
bool copyOnly;
|
||||||
switch (importMode)
|
switch (importMode)
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Disk;
|
using NzbDrone.Common.Disk;
|
||||||
|
|
|
@ -4,6 +4,9 @@ using NzbDrone.Core.DecisionEngine;
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
using NzbDrone.Core.Profiles.Qualities;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
|
namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
|
||||||
{
|
{
|
||||||
|
@ -19,9 +22,20 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
|
||||||
public Decision IsSatisfiedBy(LocalEpisode localEpisode, DownloadClientItem downloadClientItem)
|
public Decision IsSatisfiedBy(LocalEpisode localEpisode, DownloadClientItem downloadClientItem)
|
||||||
{
|
{
|
||||||
var qualityComparer = new QualityModelComparer(localEpisode.Series.Profile);
|
var qualityComparer = new QualityModelComparer(localEpisode.Series.Profile);
|
||||||
|
var languageComparer = new LanguageComparer(localEpisode.Series.LanguageProfile);
|
||||||
|
var profile = localEpisode.Series.Profile.Value;
|
||||||
|
|
||||||
if (localEpisode.Episodes.Any(e => e.EpisodeFileId != 0 && qualityComparer.Compare(e.EpisodeFile.Value.Quality, localEpisode.Quality) > 0))
|
if (localEpisode.Episodes.Any(e => e.EpisodeFileId != 0 && qualityComparer.Compare(e.EpisodeFile.Value.Quality, localEpisode.Quality) > 0))
|
||||||
{
|
{
|
||||||
_logger.Debug("This file isn't an upgrade for all episodes. Skipping {0}", localEpisode.Path);
|
_logger.Debug("This file isn't a quality upgrade for all episodes. Skipping {0}", localEpisode.Path);
|
||||||
|
return Decision.Reject("Not an upgrade for existing episode file(s)");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localEpisode.Episodes.Any(e => e.EpisodeFileId != 0 &&
|
||||||
|
languageComparer.Compare(e.EpisodeFile.Value.Language, localEpisode.Language) > 0 &&
|
||||||
|
qualityComparer.Compare(e.EpisodeFile.Value.Quality, localEpisode.Quality) == 0))
|
||||||
|
{
|
||||||
|
_logger.Debug("This file isn't a language upgrade for all episodes. Skipping {0}", localEpisode.Path);
|
||||||
return Decision.Reject("Not an upgrade for existing episode file(s)");
|
return Decision.Reject("Not an upgrade for existing episode file(s)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -151,6 +151,10 @@
|
||||||
<Compile Include="CustomFilters\CustomFilterService.cs" />
|
<Compile Include="CustomFilters\CustomFilterService.cs" />
|
||||||
<Compile Include="Datastore\Migration\126_add_custom_filters.cs" />
|
<Compile Include="Datastore\Migration\126_add_custom_filters.cs" />
|
||||||
<Compile Include="Extras\Metadata\MetadataSectionType.cs" />
|
<Compile Include="Extras\Metadata\MetadataSectionType.cs" />
|
||||||
|
<Compile Include="Download\Aggregation\RemoteEpisodeAggregationService.cs" />
|
||||||
|
<Compile Include="Download\Aggregation\Aggregators\AggregatePreferredWordScore.cs" />
|
||||||
|
<Compile Include="Download\Aggregation\Aggregators\IAggregateRemoteEpisode.cs" />
|
||||||
|
<Compile Include="Housekeeping\Housekeepers\EnsureValidLanguageProfileId.cs" />
|
||||||
<Compile Include="Indexers\SeedConfigProvider.cs" />
|
<Compile Include="Indexers\SeedConfigProvider.cs" />
|
||||||
<Compile Include="DataAugmentation\DailySeries\DailySeries.cs" />
|
<Compile Include="DataAugmentation\DailySeries\DailySeries.cs" />
|
||||||
<Compile Include="DataAugmentation\DailySeries\DailySeriesDataProxy.cs" />
|
<Compile Include="DataAugmentation\DailySeries\DailySeriesDataProxy.cs" />
|
||||||
|
@ -175,6 +179,7 @@
|
||||||
<Compile Include="Datastore\Converters\DoubleConverter.cs" />
|
<Compile Include="Datastore\Converters\DoubleConverter.cs" />
|
||||||
<Compile Include="Datastore\Converters\EmbeddedDocumentConverter.cs" />
|
<Compile Include="Datastore\Converters\EmbeddedDocumentConverter.cs" />
|
||||||
<Compile Include="Datastore\Converters\EnumIntConverter.cs" />
|
<Compile Include="Datastore\Converters\EnumIntConverter.cs" />
|
||||||
|
<Compile Include="Datastore\Converters\LanguageIntConverter.cs" />
|
||||||
<Compile Include="Datastore\Converters\TimeSpanConverter.cs" />
|
<Compile Include="Datastore\Converters\TimeSpanConverter.cs" />
|
||||||
<Compile Include="Datastore\Converters\Int32Converter.cs" />
|
<Compile Include="Datastore\Converters\Int32Converter.cs" />
|
||||||
<Compile Include="Datastore\Converters\GuidConverter.cs" />
|
<Compile Include="Datastore\Converters\GuidConverter.cs" />
|
||||||
|
@ -268,7 +273,6 @@
|
||||||
<Compile Include="Datastore\Migration\069_quality_proper.cs" />
|
<Compile Include="Datastore\Migration\069_quality_proper.cs" />
|
||||||
<Compile Include="Datastore\Migration\070_delay_profile.cs" />
|
<Compile Include="Datastore\Migration\070_delay_profile.cs" />
|
||||||
<Compile Include="Datastore\Migration\116_disable_nyaa.cs" />
|
<Compile Include="Datastore\Migration\116_disable_nyaa.cs" />
|
||||||
<Compile Include="Datastore\Migration\102_add_language_to_episodeFiles_history_and_blacklist.cs" />
|
|
||||||
<Compile Include="Datastore\Migration\113_consolidate_indexer_baseurl.cs" />
|
<Compile Include="Datastore\Migration\113_consolidate_indexer_baseurl.cs" />
|
||||||
<Compile Include="Datastore\Migration\114_rename_indexer_status_id.cs" />
|
<Compile Include="Datastore\Migration\114_rename_indexer_status_id.cs" />
|
||||||
<Compile Include="Datastore\Migration\112_added_regex_to_scenemapping.cs" />
|
<Compile Include="Datastore\Migration\112_added_regex_to_scenemapping.cs" />
|
||||||
|
@ -312,6 +316,7 @@
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Datastore\Migration\105_rename_torrent_downloadstation.cs" />
|
<Compile Include="Datastore\Migration\105_rename_torrent_downloadstation.cs" />
|
||||||
|
<Compile Include="Datastore\Migration\102_add_language_to_episodeFiles_history_and_blacklist.cs" />
|
||||||
<Compile Include="Datastore\Migration\111_create_language_profiles.cs" />
|
<Compile Include="Datastore\Migration\111_create_language_profiles.cs" />
|
||||||
<Compile Include="Datastore\Migration\115_add_downloadclient_status.cs" />
|
<Compile Include="Datastore\Migration\115_add_downloadclient_status.cs" />
|
||||||
<Compile Include="Datastore\Migration\121_update_animetosho_url.cs" />
|
<Compile Include="Datastore\Migration\121_update_animetosho_url.cs" />
|
||||||
|
@ -339,7 +344,7 @@
|
||||||
<Compile Include="DecisionEngine\DownloadDecisionPriorizationService.cs" />
|
<Compile Include="DecisionEngine\DownloadDecisionPriorizationService.cs" />
|
||||||
<Compile Include="DecisionEngine\IDecisionEngineSpecification.cs" />
|
<Compile Include="DecisionEngine\IDecisionEngineSpecification.cs" />
|
||||||
<Compile Include="DecisionEngine\IRejectWithReason.cs" />
|
<Compile Include="DecisionEngine\IRejectWithReason.cs" />
|
||||||
<Compile Include="DecisionEngine\QualityUpgradableSpecification.cs" />
|
<Compile Include="DecisionEngine\UpgradableSpecification.cs" />
|
||||||
<Compile Include="DecisionEngine\Rejection.cs" />
|
<Compile Include="DecisionEngine\Rejection.cs" />
|
||||||
<Compile Include="DecisionEngine\RejectionType.cs" />
|
<Compile Include="DecisionEngine\RejectionType.cs" />
|
||||||
<Compile Include="DecisionEngine\SameEpisodesSpecification.cs" />
|
<Compile Include="DecisionEngine\SameEpisodesSpecification.cs" />
|
||||||
|
@ -769,6 +774,12 @@
|
||||||
<Compile Include="Jobs\ScheduledTask.cs" />
|
<Compile Include="Jobs\ScheduledTask.cs" />
|
||||||
<Compile Include="Jobs\Scheduler.cs" />
|
<Compile Include="Jobs\Scheduler.cs" />
|
||||||
<Compile Include="Jobs\TaskManager.cs" />
|
<Compile Include="Jobs\TaskManager.cs" />
|
||||||
|
<Compile Include="Languages\Language.cs" />
|
||||||
|
<Compile Include="Languages\LanguageComparer.cs" />
|
||||||
|
<Compile Include="Languages\LanguagesBelowCutoff.cs" />
|
||||||
|
<Compile Include="MediaFiles\EpisodeImport\Aggregation\Aggregators\AggregateLanguage.cs" />
|
||||||
|
<Compile Include="Profiles\Languages\LanguageProfile.cs" />
|
||||||
|
<Compile Include="Profiles\Languages\LanguageProfileInUseException.cs" />
|
||||||
<Compile Include="Lifecycle\ApplicationShutdownRequested.cs" />
|
<Compile Include="Lifecycle\ApplicationShutdownRequested.cs" />
|
||||||
<Compile Include="Lifecycle\ApplicationStartedEvent.cs" />
|
<Compile Include="Lifecycle\ApplicationStartedEvent.cs" />
|
||||||
<Compile Include="Lifecycle\Commands\RestartCommand.cs" />
|
<Compile Include="Lifecycle\Commands\RestartCommand.cs" />
|
||||||
|
@ -985,7 +996,13 @@
|
||||||
<Compile Include="Profiles\Delay\DelayProfile.cs" />
|
<Compile Include="Profiles\Delay\DelayProfile.cs" />
|
||||||
<Compile Include="Profiles\Delay\DelayProfileService.cs" />
|
<Compile Include="Profiles\Delay\DelayProfileService.cs" />
|
||||||
<Compile Include="Profiles\Delay\DelayProfileTagInUseValidator.cs" />
|
<Compile Include="Profiles\Delay\DelayProfileTagInUseValidator.cs" />
|
||||||
<Compile Include="Profiles\ProfileRepository.cs" />
|
<Compile Include="Profiles\Languages\LanguageProfileItem.cs" />
|
||||||
|
<Compile Include="Profiles\Languages\LanguageProfileRepository.cs" />
|
||||||
|
<Compile Include="Profiles\Qualities\Profile.cs" />
|
||||||
|
<Compile Include="Profiles\Qualities\ProfileInUseException.cs" />
|
||||||
|
<Compile Include="Profiles\Qualities\ProfileQualityItem.cs" />
|
||||||
|
<Compile Include="Profiles\Qualities\ProfileRepository.cs" />
|
||||||
|
<Compile Include="Profiles\Qualities\ProfileService.cs" />
|
||||||
<Compile Include="ProgressMessaging\ProgressMessageContext.cs" />
|
<Compile Include="ProgressMessaging\ProgressMessageContext.cs" />
|
||||||
<Compile Include="Qualities\QualityDetectionSource.cs" />
|
<Compile Include="Qualities\QualityDetectionSource.cs" />
|
||||||
<Compile Include="Qualities\QualitySource.cs" />
|
<Compile Include="Qualities\QualitySource.cs" />
|
||||||
|
@ -1097,7 +1114,6 @@
|
||||||
<Compile Include="Organizer\NamingConfigService.cs" />
|
<Compile Include="Organizer\NamingConfigService.cs" />
|
||||||
<Compile Include="Organizer\SampleResult.cs" />
|
<Compile Include="Organizer\SampleResult.cs" />
|
||||||
<Compile Include="Parser\InvalidDateException.cs" />
|
<Compile Include="Parser\InvalidDateException.cs" />
|
||||||
<Compile Include="Parser\Language.cs" />
|
|
||||||
<Compile Include="Parser\Model\LocalEpisode.cs" />
|
<Compile Include="Parser\Model\LocalEpisode.cs" />
|
||||||
<Compile Include="Parser\Model\ParsedEpisodeInfo.cs" />
|
<Compile Include="Parser\Model\ParsedEpisodeInfo.cs" />
|
||||||
<Compile Include="Parser\Model\ReleaseInfo.cs" />
|
<Compile Include="Parser\Model\ReleaseInfo.cs" />
|
||||||
|
@ -1108,11 +1124,8 @@
|
||||||
<Compile Include="Parser\ParsingService.cs" />
|
<Compile Include="Parser\ParsingService.cs" />
|
||||||
<Compile Include="Parser\SceneChecker.cs" />
|
<Compile Include="Parser\SceneChecker.cs" />
|
||||||
<Compile Include="Parser\QualityParser.cs" />
|
<Compile Include="Parser\QualityParser.cs" />
|
||||||
<Compile Include="Profiles\Profile.cs" />
|
|
||||||
<Compile Include="Profiles\ProfileInUseException.cs" />
|
|
||||||
<Compile Include="Profiles\ProfileQualityItem.cs" />
|
|
||||||
<Compile Include="Profiles\Delay\DelayProfileRepository.cs" />
|
<Compile Include="Profiles\Delay\DelayProfileRepository.cs" />
|
||||||
<Compile Include="Profiles\ProfileService.cs" />
|
<Compile Include="Profiles\Languages\LanguageProfileService.cs" />
|
||||||
<Compile Include="ProgressMessaging\CommandUpdatedEvent.cs" />
|
<Compile Include="ProgressMessaging\CommandUpdatedEvent.cs" />
|
||||||
<Compile Include="ProgressMessaging\ProgressMessageTarget.cs" />
|
<Compile Include="ProgressMessaging\ProgressMessageTarget.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
@ -1229,7 +1242,6 @@
|
||||||
<Compile Include="Update\UpdateVerificationFailedException.cs" />
|
<Compile Include="Update\UpdateVerificationFailedException.cs" />
|
||||||
<Compile Include="Validation\FolderValidator.cs" />
|
<Compile Include="Validation\FolderValidator.cs" />
|
||||||
<Compile Include="Validation\IpValidation.cs" />
|
<Compile Include="Validation\IpValidation.cs" />
|
||||||
<Compile Include="Validation\LanguageValidator.cs" />
|
|
||||||
<Compile Include="Validation\NzbDroneValidationExtensions.cs" />
|
<Compile Include="Validation\NzbDroneValidationExtensions.cs" />
|
||||||
<Compile Include="Validation\NzbDroneValidationFailure.cs" />
|
<Compile Include="Validation\NzbDroneValidationFailure.cs" />
|
||||||
<Compile Include="Validation\NzbDroneValidationResult.cs" />
|
<Compile Include="Validation\NzbDroneValidationResult.cs" />
|
||||||
|
@ -1245,6 +1257,7 @@
|
||||||
<Compile Include="Validation\Paths\SeriesAncestorValidator.cs" />
|
<Compile Include="Validation\Paths\SeriesAncestorValidator.cs" />
|
||||||
<Compile Include="Validation\Paths\SeriesExistsValidator.cs" />
|
<Compile Include="Validation\Paths\SeriesExistsValidator.cs" />
|
||||||
<Compile Include="Validation\Paths\SeriesPathValidator.cs" />
|
<Compile Include="Validation\Paths\SeriesPathValidator.cs" />
|
||||||
|
<Compile Include="Validation\LanguageProfileExistsValidator.cs" />
|
||||||
<Compile Include="Validation\ProfileExistsValidator.cs" />
|
<Compile Include="Validation\ProfileExistsValidator.cs" />
|
||||||
<Compile Include="Validation\RuleBuilderExtensions.cs" />
|
<Compile Include="Validation\RuleBuilderExtensions.cs" />
|
||||||
<Compile Include="Validation\UrlValidator.cs" />
|
<Compile Include="Validation\UrlValidator.cs" />
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
namespace NzbDrone.Core.Parser
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Parser
|
||||||
{
|
{
|
||||||
public class IsoLanguage
|
public class IsoLanguage
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Parser
|
namespace NzbDrone.Core.Parser
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
namespace NzbDrone.Core.Parser
|
|
||||||
{
|
|
||||||
public enum Language
|
|
||||||
{
|
|
||||||
Unknown = 0,
|
|
||||||
English = 1,
|
|
||||||
French = 2,
|
|
||||||
Spanish = 3,
|
|
||||||
German = 4,
|
|
||||||
Italian = 5,
|
|
||||||
Danish = 6,
|
|
||||||
Dutch = 7,
|
|
||||||
Japanese = 8,
|
|
||||||
Cantonese = 9,
|
|
||||||
Mandarin = 10,
|
|
||||||
Russian = 11,
|
|
||||||
Polish = 12,
|
|
||||||
Vietnamese = 13,
|
|
||||||
Swedish = 14,
|
|
||||||
Norwegian = 15,
|
|
||||||
Finnish = 16,
|
|
||||||
Turkish = 17,
|
|
||||||
Portuguese = 18,
|
|
||||||
Flemish = 19,
|
|
||||||
Greek = 20,
|
|
||||||
Korean = 21,
|
|
||||||
Hungarian = 22,
|
|
||||||
Hebrew = 23,
|
|
||||||
Lithuanian = 24,
|
|
||||||
Czech = 25
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Instrumentation;
|
using NzbDrone.Common.Instrumentation;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Parser
|
namespace NzbDrone.Core.Parser
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,6 +4,7 @@ using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
using NzbDrone.Core.MediaFiles.MediaInfo;
|
using NzbDrone.Core.MediaFiles.MediaInfo;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Parser.Model
|
namespace NzbDrone.Core.Parser.Model
|
||||||
{
|
{
|
||||||
|
@ -22,6 +23,7 @@ namespace NzbDrone.Core.Parser.Model
|
||||||
public Series Series { get; set; }
|
public Series Series { get; set; }
|
||||||
public List<Episode> Episodes { get; set; }
|
public List<Episode> Episodes { get; set; }
|
||||||
public QualityModel Quality { get; set; }
|
public QualityModel Quality { get; set; }
|
||||||
|
public Language Language { get; set; }
|
||||||
public MediaInfoModel MediaInfo { get; set; }
|
public MediaInfoModel MediaInfo { get; set; }
|
||||||
public bool ExistingFile { get; set; }
|
public bool ExistingFile { get; set; }
|
||||||
public bool SceneSource { get; set; }
|
public bool SceneSource { get; set; }
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Parser.Model
|
namespace NzbDrone.Core.Parser.Model
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,6 +8,7 @@ using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Common.Instrumentation;
|
using NzbDrone.Common.Instrumentation;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Core.Languages;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Parser
|
namespace NzbDrone.Core.Parser
|
||||||
{
|
{
|
||||||
|
@ -322,6 +323,9 @@ namespace NzbDrone.Core.Parser
|
||||||
private static readonly Regex AnimeReleaseGroupRegex = new Regex(@"^(?:\[(?<subgroup>(?!\s).+?(?<!\s))\](?:_|-|\s|\.)?)",
|
private static readonly Regex AnimeReleaseGroupRegex = new Regex(@"^(?:\[(?<subgroup>(?!\s).+?(?<!\s))\](?:_|-|\s|\.)?)",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||||
|
|
||||||
|
private static readonly Regex LanguageRegex = new Regex(@"(?:\W|_)(?<italian>\b(?:ita|italian)\b)|(?<german>german\b|videomann)|(?<flemish>flemish)|(?<greek>greek)|(?<french>(?:\W|_)(?:FR|VOSTFR)(?:\W|_))|(?<russian>\brus\b)|(?<dutch>nl\W?subs?)|(?<hungarian>\b(?:HUNDUB|HUN)\b)|(?<spanish>\b(?:español|castellano)\b)",
|
||||||
|
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||||
|
|
||||||
private static readonly Regex YearInTitleRegex = new Regex(@"^(?<title>.+?)(?:\W|_)?(?<year>\d{4})",
|
private static readonly Regex YearInTitleRegex = new Regex(@"^(?<title>.+?)(?:\W|_)?(?<year>\d{4})",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||||
|
|
||||||
|
@ -575,6 +579,99 @@ namespace NzbDrone.Core.Parser
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Language ParseLanguage(string title)
|
||||||
|
{
|
||||||
|
var lowerTitle = title.ToLower();
|
||||||
|
|
||||||
|
if (lowerTitle.Contains("english"))
|
||||||
|
return Language.English;
|
||||||
|
|
||||||
|
if (lowerTitle.Contains("french"))
|
||||||
|
return Language.French;
|
||||||
|
|
||||||
|
if (lowerTitle.Contains("spanish"))
|
||||||
|
return Language.Spanish;
|
||||||
|
|
||||||
|
if (lowerTitle.Contains("danish"))
|
||||||
|
return Language.Danish;
|
||||||
|
|
||||||
|
if (lowerTitle.Contains("dutch"))
|
||||||
|
return Language.Dutch;
|
||||||
|
|
||||||
|
if (lowerTitle.Contains("japanese"))
|
||||||
|
return Language.Japanese;
|
||||||
|
|
||||||
|
if (lowerTitle.Contains("cantonese"))
|
||||||
|
return Language.Cantonese;
|
||||||
|
|
||||||
|
if (lowerTitle.Contains("mandarin"))
|
||||||
|
return Language.Mandarin;
|
||||||
|
|
||||||
|
if (lowerTitle.Contains("korean"))
|
||||||
|
return Language.Korean;
|
||||||
|
|
||||||
|
if (lowerTitle.Contains("russian"))
|
||||||
|
return Language.Russian;
|
||||||
|
|
||||||
|
if (lowerTitle.Contains("polish"))
|
||||||
|
return Language.Polish;
|
||||||
|
|
||||||
|
if (lowerTitle.Contains("vietnamese"))
|
||||||
|
return Language.Vietnamese;
|
||||||
|
|
||||||
|
if (lowerTitle.Contains("swedish"))
|
||||||
|
return Language.Swedish;
|
||||||
|
|
||||||
|
if (lowerTitle.Contains("norwegian"))
|
||||||
|
return Language.Norwegian;
|
||||||
|
|
||||||
|
if (lowerTitle.Contains("nordic"))
|
||||||
|
return Language.Norwegian;
|
||||||
|
|
||||||
|
if (lowerTitle.Contains("finnish"))
|
||||||
|
return Language.Finnish;
|
||||||
|
|
||||||
|
if (lowerTitle.Contains("turkish"))
|
||||||
|
return Language.Turkish;
|
||||||
|
|
||||||
|
if (lowerTitle.Contains("portuguese"))
|
||||||
|
return Language.Portuguese;
|
||||||
|
|
||||||
|
if (lowerTitle.Contains("hungarian"))
|
||||||
|
return Language.Hungarian;
|
||||||
|
|
||||||
|
var match = LanguageRegex.Match(title);
|
||||||
|
|
||||||
|
if (match.Groups["italian"].Captures.Cast<Capture>().Any())
|
||||||
|
return Language.Italian;
|
||||||
|
|
||||||
|
if (match.Groups["german"].Captures.Cast<Capture>().Any())
|
||||||
|
return Language.German;
|
||||||
|
|
||||||
|
if (match.Groups["flemish"].Captures.Cast<Capture>().Any())
|
||||||
|
return Language.Flemish;
|
||||||
|
|
||||||
|
if (match.Groups["greek"].Captures.Cast<Capture>().Any())
|
||||||
|
return Language.Greek;
|
||||||
|
|
||||||
|
if (match.Groups["spanish"].Captures.Cast<Capture>().Any())
|
||||||
|
return Language.Spanish;
|
||||||
|
|
||||||
|
if (match.Groups["french"].Success)
|
||||||
|
return Language.French;
|
||||||
|
|
||||||
|
if (match.Groups["russian"].Success)
|
||||||
|
return Language.Russian;
|
||||||
|
|
||||||
|
if (match.Groups["dutch"].Success)
|
||||||
|
return Language.Dutch;
|
||||||
|
|
||||||
|
if (match.Groups["hungarian"].Success)
|
||||||
|
return Language.Hungarian;
|
||||||
|
|
||||||
|
return Language.English;
|
||||||
|
}
|
||||||
|
|
||||||
private static SeriesTitleInfo GetSeriesTitleInfo(string title)
|
private static SeriesTitleInfo GetSeriesTitleInfo(string title)
|
||||||
{
|
{
|
||||||
var seriesTitleInfo = new SeriesTitleInfo();
|
var seriesTitleInfo = new SeriesTitleInfo();
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue