Adds Anime-specific searching and Fanzub support

Splits searching in the same way as a Daily search, each indexer has a
method to search specifically for anime. Fanzub support was also added,
with its own indexer and parser classes.
This commit is contained in:
Scott Rice 2014-04-21 17:50:43 -05:00 committed by Mark McDowall
parent a75ce9ab87
commit 828dd5f5ad
12 changed files with 172 additions and 2 deletions

View File

@ -0,0 +1,14 @@
using System;
namespace NzbDrone.Core.IndexerSearch.Definitions
{
public class AnimeEpisodeSearchCriteria : SearchCriteriaBase
{
public int AbsoluteEpisodeNumber { get; set; }
public override string ToString()
{
return string.Format("[{0} : {1:00}]", SceneTitle, AbsoluteEpisodeNumber);
}
}
}

View File

@ -70,6 +70,10 @@ namespace NzbDrone.Core.IndexerSearch
return SearchDaily(series, episode);
}
if (series.SeriesType == SeriesTypes.Anime)
{
return SearchAnime(series, episode);
}
if (episode.SeasonNumber == 0)
{
@ -116,6 +120,17 @@ namespace NzbDrone.Core.IndexerSearch
return Dispatch(indexer => _feedFetcher.Fetch(indexer, searchSpec), searchSpec);
}
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);
return Dispatch(indexer => _feedFetcher.Fetch(indexer, searchSpec), searchSpec);
}
private List<DownloadDecision> SearchSpecial(Series series, List<Episode> episodes)
{
var searchSpec = Get<SpecialEpisodeSearchCriteria>(series, episodes);

View File

@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Core.ThingiProvider;
namespace NzbDrone.Core.Indexers.Fanzub
{
public class Fanzub : IndexerBase<NullConfig>
{
public override DownloadProtocol Protocol
{
get
{
return DownloadProtocol.Usenet;
}
}
public override bool SupportsPaging
{
get
{
return false;
}
}
public override bool SupportsSearching
{
get
{
return true;
}
}
public override IParseFeed Parser
{
get
{
return new FanzubParser();
}
}
public override IEnumerable<string> RecentFeed
{
get
{
yield return "http://fanzub.com/rss/?cat=anime";
}
}
public override IEnumerable<string> GetEpisodeSearchUrls(string seriesTitle, int tvRageId, int seasonNumber, int episodeNumber)
{
return new List<string>();
}
public override IEnumerable<string> GetSeasonSearchUrls(string seriesTitle, int tvRageId, int seasonNumber, int offset)
{
return new List<string>();
}
public override IEnumerable<string> GetDailyEpisodeSearchUrls(string seriesTitle, int tvRageId, DateTime date)
{
return new List<string>();
}
public override IEnumerable<string> GetAnimeEpisodeSearchUrls(string seriesTitle, int tvRageId, int absoluteEpisodeNumber)
{
return RecentFeed.Select(url => String.Format("{0}&q={1}%20{2}", url, seriesTitle, absoluteEpisodeNumber));
}
public override IEnumerable<string> GetSearchUrls(string query, int offset)
{
return new List<string>();
}
}
}

View File

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Xml.Linq;
using System.Linq;
namespace NzbDrone.Core.Indexers.Fanzub
{
public class FanzubParser : RssParserBase
{
protected override string GetNzbInfoUrl(XElement item)
{
IEnumerable<XElement> matches = item.DescendantsAndSelf("link");
if (matches.Any())
{
return matches.First().Value;
}
return String.Empty;
}
protected override long GetSize(XElement item)
{
IEnumerable<XElement> matches = item.DescendantsAndSelf("enclosure");
if (matches.Any())
{
XElement enclosureElement = matches.First();
return Convert.ToInt64(enclosureElement.Attribute("length").Value);
}
return 0;
}
}
}

View File

@ -15,6 +15,7 @@ namespace NzbDrone.Core.Indexers
IEnumerable<string> RecentFeed { get; }
IEnumerable<string> GetEpisodeSearchUrls(string seriesTitle, int tvRageId, int seasonNumber, int episodeNumber);
IEnumerable<string> GetDailyEpisodeSearchUrls(string seriesTitle, int tvRageId, DateTime date);
IEnumerable<string> GetAnimeEpisodeSearchUrls(string seriesTitle, int tvRageId, int absoluteEpisodeNumber);
IEnumerable<string> GetSeasonSearchUrls(string seriesTitle, int tvRageId, int seasonNumber, int offset);
IEnumerable<string> GetSearchUrls(string query, int offset = 0);
}

View File

@ -52,6 +52,7 @@ namespace NzbDrone.Core.Indexers
public abstract IEnumerable<string> RecentFeed { get; }
public abstract IEnumerable<string> GetEpisodeSearchUrls(string seriesTitle, int tvRageId, int seasonNumber, int episodeNumber);
public abstract IEnumerable<string> GetDailyEpisodeSearchUrls(string seriesTitle, int tvRageId, DateTime date);
public abstract IEnumerable<string> GetAnimeEpisodeSearchUrls(string seriesTitle, int tvRageId, int absoluteEpisodeNumber);
public abstract IEnumerable<string> GetSeasonSearchUrls(string seriesTitle, int tvRageId, int seasonNumber, int offset);
public abstract IEnumerable<string> GetSearchUrls(string query, int offset);

View File

@ -18,6 +18,7 @@ namespace NzbDrone.Core.Indexers
IList<ReleaseInfo> Fetch(IIndexer indexer, SeasonSearchCriteria searchCriteria);
IList<ReleaseInfo> Fetch(IIndexer indexer, SingleEpisodeSearchCriteria searchCriteria);
IList<ReleaseInfo> Fetch(IIndexer indexer, DailyEpisodeSearchCriteria searchCriteria);
IList<ReleaseInfo> Fetch(IIndexer indexer, AnimeEpisodeSearchCriteria searchCriteria);
IList<ReleaseInfo> Fetch(IIndexer indexer, SpecialEpisodeSearchCriteria searchCriteria);
}
@ -93,6 +94,17 @@ namespace NzbDrone.Core.Indexers
return result;
}
public IList<ReleaseInfo> Fetch(IIndexer indexer, AnimeEpisodeSearchCriteria searchCriteria)
{
_logger.Debug("Searching for {0}", searchCriteria);
var searchUrls = indexer.GetAnimeEpisodeSearchUrls(searchCriteria.QueryTitle, searchCriteria.Series.TvRageId, searchCriteria.AbsoluteEpisodeNumber);
var result = Fetch(indexer, searchUrls);
_logger.Info("Finished searching {0} for {1}. Found {2}", indexer, searchCriteria, result.Count);
return result;
}
public IList<ReleaseInfo> Fetch(IIndexer indexer, SpecialEpisodeSearchCriteria searchCriteria)
{
var queryUrls = new List<String>();

View File

@ -125,6 +125,12 @@ namespace NzbDrone.Core.Indexers.Newznab
return RecentFeed.Select(url => String.Format("{0}&limit=100&q={1}&season={2:yyyy}&ep={2:MM}/{2:dd}", url, NewsnabifyTitle(seriesTitle), date)).ToList();
}
public override IEnumerable<string> GetAnimeEpisodeSearchUrls(string seriesTitle, int tvRageId, int absoluteEpisodeNumber)
{
// TODO: Implement
return new List<string>();
}
public override IEnumerable<string> GetSeasonSearchUrls(string seriesTitle, int tvRageId, int seasonNumber, int offset)
{
if (tvRageId > 0)

View File

@ -48,6 +48,12 @@ namespace NzbDrone.Core.Indexers.Omgwtfnzbs
return searchUrls;
}
public override IEnumerable<string> GetAnimeEpisodeSearchUrls(string seriesTitle, int tvRageId, int absoluteEpisodeNumber)
{
// TODO: Implement
return new List<string>();
}
public override IEnumerable<string> GetSeasonSearchUrls(string seriesTitle, int tvRageId, int seasonNumber, int offset)
{
var searchUrls = new List<String>();

View File

@ -37,6 +37,11 @@ namespace NzbDrone.Core.Indexers.Wombles
return new List<string>();
}
public override IEnumerable<string> GetAnimeEpisodeSearchUrls(string seriesTitle, int tvRageId, int absoluteEpisodeNumber)
{
return new List<string>();
}
public override IEnumerable<string> GetSearchUrls(string query, int offset)
{
return new List<string>();

View File

@ -311,6 +311,7 @@
<Compile Include="Housekeeping\HousekeepingCommand.cs" />
<Compile Include="Housekeeping\HousekeepingService.cs" />
<Compile Include="Housekeeping\IHousekeepingTask.cs" />
<Compile Include="IndexerSearch\Definitions\AnimeEpisodeSearchCriteria.cs" />
<Compile Include="IndexerSearch\MissingEpisodeSearchCommand.cs" />
<Compile Include="IndexerSearch\Definitions\SpecialEpisodeSearchCriteria.cs" />
<Compile Include="IndexerSearch\SeriesSearchService.cs" />
@ -323,6 +324,9 @@
<Compile Include="Indexers\DownloadProtocol.cs" />
<Compile Include="Indexers\Exceptions\ApiKeyException.cs" />
<Compile Include="Indexers\Exceptions\RequestLimitReachedException.cs" />
<Compile Include="Indexers\Eztv\Eztv.cs" />
<Compile Include="Indexers\Fanzub\Fanzub.cs" />
<Compile Include="Indexers\Fanzub\FanzubParser.cs" />
<Compile Include="Indexers\FetchAndParseRssService.cs" />
<Compile Include="Indexers\IIndexer.cs" />
<Compile Include="Indexers\IndexerSettingUpdatedEvent.cs" />

View File

@ -15,6 +15,8 @@
<TargetFrameworkProfile>
</TargetFrameworkProfile>
<IsWebBootstrapper>false</IsWebBootstrapper>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
@ -29,8 +31,6 @@
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<PlatformTarget>x86</PlatformTarget>