mirror of
https://github.com/Readarr/Readarr.git
synced 2026-04-25 22:36:59 -04:00
Anime!
New: Anime support New: pull alternate names from thexem.de New: Search using all alternate names (if rage ID is unavailable) New: Show scene mapping information when hovering over episode number New: Full season searching for anime (searches for each episode) New: animezb.com anime indexer New: Treat BD as bluray Fixed: Parsing of 2 digit absolute episode numbers Fixed: Loading series details page for series that start with period Fixed: Return 0 results when manual search fails, instead of an error Fixed: animezb URL
This commit is contained in:
@@ -8,7 +8,7 @@ namespace NzbDrone.Core.IndexerSearch.Definitions
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("[{0} : {1:00}]", SceneTitle, AbsoluteEpisodeNumber);
|
||||
return string.Format("[{0} : {1:00}]", Series.Title, AbsoluteEpisodeNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ namespace NzbDrone.Core.IndexerSearch.Definitions
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("[{0} : {1}", SceneTitle, AirDate);
|
||||
return string.Format("[{0} : {1}", Series.Title, AirDate);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using NzbDrone.Common.EnsureThat;
|
||||
using NzbDrone.Core.Tv;
|
||||
@@ -12,14 +13,14 @@ namespace NzbDrone.Core.IndexerSearch.Definitions
|
||||
private static readonly Regex BeginningThe = new Regex(@"^the\s", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
|
||||
public Series Series { get; set; }
|
||||
public string SceneTitle { get; set; }
|
||||
public List<String> SceneTitles { get; set; }
|
||||
public List<Episode> Episodes { get; set; }
|
||||
|
||||
public string QueryTitle
|
||||
public List<String> QueryTitles
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetQueryTitle(SceneTitle);
|
||||
return SceneTitles.Select(GetQueryTitle).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace NzbDrone.Core.IndexerSearch.Definitions
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("[{0} : S{1:00}]", SceneTitle, SeasonNumber);
|
||||
return string.Format("[{0} : S{1:00}]", Series.Title, SeasonNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace NzbDrone.Core.IndexerSearch.Definitions
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("[{0} : S{1:00}E{2:00}]", SceneTitle, SeasonNumber, EpisodeNumber);
|
||||
return string.Format("[{0} : S{1:00}E{2:00}]", Series.Title, SeasonNumber, EpisodeNumber);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ namespace NzbDrone.Core.IndexerSearch.Definitions
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("[{0} : {1}]", SceneTitle, String.Join(",", EpisodeQueryTitles));
|
||||
return string.Format("[{0} : {1}]", Series.Title, String.Join(",", EpisodeQueryTitles));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Threading.Tasks;
|
||||
using NLog;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.DataAugmentation.Scene;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||
@@ -84,6 +86,71 @@ namespace NzbDrone.Core.IndexerSearch
|
||||
return SearchSingle(series, episode);
|
||||
}
|
||||
|
||||
public List<DownloadDecision> SeasonSearch(int seriesId, int seasonNumber)
|
||||
{
|
||||
var series = _seriesService.GetSeries(seriesId);
|
||||
var episodes = _episodeService.GetEpisodesBySeason(seriesId, seasonNumber);
|
||||
|
||||
if (series.SeriesType == SeriesTypes.Anime)
|
||||
{
|
||||
return SearchAnimeSeason(series, episodes);
|
||||
}
|
||||
|
||||
if (seasonNumber == 0)
|
||||
{
|
||||
// search for special episodes in season 0
|
||||
return SearchSpecial(series, episodes);
|
||||
}
|
||||
|
||||
var downloadDecisions = new List<DownloadDecision>();
|
||||
|
||||
if (series.UseSceneNumbering)
|
||||
{
|
||||
var sceneSeasonGroups = episodes.GroupBy(v =>
|
||||
{
|
||||
if (v.SceneSeasonNumber == 0 && v.SceneEpisodeNumber == 0)
|
||||
return v.SeasonNumber;
|
||||
else
|
||||
return v.SceneSeasonNumber;
|
||||
}).Distinct();
|
||||
|
||||
foreach (var sceneSeasonEpisodes in sceneSeasonGroups)
|
||||
{
|
||||
if (sceneSeasonEpisodes.Count() == 1)
|
||||
{
|
||||
var episode = sceneSeasonEpisodes.First();
|
||||
var searchSpec = Get<SingleEpisodeSearchCriteria>(series, sceneSeasonEpisodes.ToList());
|
||||
searchSpec.SeasonNumber = sceneSeasonEpisodes.Key;
|
||||
if (episode.SceneSeasonNumber == 0 && episode.SceneEpisodeNumber == 0)
|
||||
searchSpec.EpisodeNumber = episode.EpisodeNumber;
|
||||
else
|
||||
searchSpec.EpisodeNumber = episode.SceneEpisodeNumber;
|
||||
|
||||
var decisions = Dispatch(indexer => _feedFetcher.Fetch(indexer, searchSpec), searchSpec);
|
||||
downloadDecisions.AddRange(decisions);
|
||||
}
|
||||
else
|
||||
{
|
||||
var searchSpec = Get<SeasonSearchCriteria>(series, sceneSeasonEpisodes.ToList());
|
||||
searchSpec.SeasonNumber = sceneSeasonEpisodes.Key;
|
||||
|
||||
var decisions = Dispatch(indexer => _feedFetcher.Fetch(indexer, searchSpec), searchSpec);
|
||||
downloadDecisions.AddRange(decisions);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var searchSpec = Get<SeasonSearchCriteria>(series, episodes);
|
||||
searchSpec.SeasonNumber = seasonNumber;
|
||||
|
||||
var decisions = Dispatch(indexer => _feedFetcher.Fetch(indexer, searchSpec), searchSpec);
|
||||
downloadDecisions.AddRange(decisions);
|
||||
}
|
||||
|
||||
return downloadDecisions;
|
||||
}
|
||||
|
||||
private List<DownloadDecision> SearchSingle(Series series, Episode episode)
|
||||
{
|
||||
var searchSpec = Get<SingleEpisodeSearchCriteria>(series, new List<Episode>{episode});
|
||||
@@ -123,10 +190,17 @@ namespace NzbDrone.Core.IndexerSearch
|
||||
private List<DownloadDecision> SearchAnime(Series series, Episode episode)
|
||||
{
|
||||
var searchSpec = Get<AnimeEpisodeSearchCriteria>(series, new List<Episode> { episode });
|
||||
// TODO: Get the scene title from TheXEM
|
||||
searchSpec.SceneTitle = series.Title;
|
||||
// TODO: Calculate the Absolute Episode Number on the fly (if I have to)
|
||||
searchSpec.AbsoluteEpisodeNumber = episode.AbsoluteEpisodeNumber.GetValueOrDefault(0);
|
||||
searchSpec.AbsoluteEpisodeNumber = episode.SceneAbsoluteEpisodeNumber.GetValueOrDefault(0);
|
||||
|
||||
if (searchSpec.AbsoluteEpisodeNumber == 0)
|
||||
{
|
||||
searchSpec.AbsoluteEpisodeNumber = episode.AbsoluteEpisodeNumber.GetValueOrDefault(0);
|
||||
}
|
||||
|
||||
if (searchSpec.AbsoluteEpisodeNumber == 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("AbsoluteEpisodeNumber", "Can not search for an episode absolute episode number of zero");
|
||||
}
|
||||
|
||||
return Dispatch(indexer => _feedFetcher.Fetch(indexer, searchSpec), searchSpec);
|
||||
}
|
||||
@@ -136,67 +210,19 @@ namespace NzbDrone.Core.IndexerSearch
|
||||
var searchSpec = Get<SpecialEpisodeSearchCriteria>(series, episodes);
|
||||
// build list of queries for each episode in the form: "<series> <episode-title>"
|
||||
searchSpec.EpisodeQueryTitles = episodes.Where(e => !String.IsNullOrWhiteSpace(e.Title))
|
||||
.Select(e => searchSpec.QueryTitle + " " + SearchCriteriaBase.GetQueryTitle(e.Title))
|
||||
.SelectMany(e => searchSpec.QueryTitles.Select(title => title + " " + SearchCriteriaBase.GetQueryTitle(e.Title)))
|
||||
.ToArray();
|
||||
|
||||
return Dispatch(indexer => _feedFetcher.Fetch(indexer, searchSpec), searchSpec);
|
||||
}
|
||||
|
||||
public List<DownloadDecision> SeasonSearch(int seriesId, int seasonNumber)
|
||||
private List<DownloadDecision> SearchAnimeSeason(Series series, List<Episode> episodes)
|
||||
{
|
||||
var series = _seriesService.GetSeries(seriesId);
|
||||
var episodes = _episodeService.GetEpisodesBySeason(seriesId, seasonNumber);
|
||||
var downloadDecisions = new List<DownloadDecision>();
|
||||
|
||||
if (seasonNumber == 0)
|
||||
foreach (var episode in episodes)
|
||||
{
|
||||
// search for special episodes in season 0
|
||||
return SearchSpecial(series, episodes);
|
||||
}
|
||||
|
||||
List<DownloadDecision> downloadDecisions = new List<DownloadDecision>();
|
||||
|
||||
if (series.UseSceneNumbering)
|
||||
{
|
||||
var sceneSeasonGroups = episodes.GroupBy(v =>
|
||||
{
|
||||
if (v.SceneSeasonNumber == 0 && v.SceneEpisodeNumber == 0)
|
||||
return v.SeasonNumber;
|
||||
else
|
||||
return v.SceneSeasonNumber;
|
||||
}).Distinct();
|
||||
|
||||
foreach (var sceneSeasonEpisodes in sceneSeasonGroups)
|
||||
{
|
||||
if (sceneSeasonEpisodes.Count() == 1)
|
||||
{
|
||||
var episode = sceneSeasonEpisodes.First();
|
||||
var searchSpec = Get<SingleEpisodeSearchCriteria>(series, sceneSeasonEpisodes.ToList());
|
||||
searchSpec.SeasonNumber = sceneSeasonEpisodes.Key;
|
||||
if (episode.SceneSeasonNumber == 0 && episode.SceneEpisodeNumber == 0)
|
||||
searchSpec.EpisodeNumber = episode.EpisodeNumber;
|
||||
else
|
||||
searchSpec.EpisodeNumber = episode.SceneEpisodeNumber;
|
||||
|
||||
var decisions = Dispatch(indexer => _feedFetcher.Fetch(indexer, searchSpec), searchSpec);
|
||||
downloadDecisions.AddRange(decisions);
|
||||
}
|
||||
else
|
||||
{
|
||||
var searchSpec = Get<SeasonSearchCriteria>(series, sceneSeasonEpisodes.ToList());
|
||||
searchSpec.SeasonNumber = sceneSeasonEpisodes.Key;
|
||||
|
||||
var decisions = Dispatch(indexer => _feedFetcher.Fetch(indexer, searchSpec), searchSpec);
|
||||
downloadDecisions.AddRange(decisions);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var searchSpec = Get<SeasonSearchCriteria>(series, episodes);
|
||||
searchSpec.SeasonNumber = seasonNumber;
|
||||
|
||||
var decisions = Dispatch(indexer => _feedFetcher.Fetch(indexer, searchSpec), searchSpec);
|
||||
downloadDecisions.AddRange(decisions);
|
||||
downloadDecisions.AddRange(SearchAnime(series, episode));
|
||||
}
|
||||
|
||||
return downloadDecisions;
|
||||
@@ -207,13 +233,14 @@ namespace NzbDrone.Core.IndexerSearch
|
||||
var spec = new TSpec();
|
||||
|
||||
spec.Series = series;
|
||||
spec.SceneTitle = _sceneMapping.GetSceneName(series.TvdbId);
|
||||
spec.SceneTitles = _sceneMapping.GetSceneNames(series.TvdbId,
|
||||
episodes.Select(e => e.SeasonNumber)
|
||||
.Concat(episodes.Select(e => e.SceneSeasonNumber)
|
||||
.Distinct()));
|
||||
|
||||
spec.Episodes = episodes;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(spec.SceneTitle))
|
||||
{
|
||||
spec.SceneTitle = series.Title;
|
||||
}
|
||||
spec.SceneTitles.Add(series.Title);
|
||||
|
||||
return spec;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user