initial awesomeHD support

This commit is contained in:
Devin Buhl 2017-01-12 23:06:26 -05:00
parent abf4b137f1
commit b93a9719fe
6 changed files with 305 additions and 0 deletions

View File

@ -0,0 +1,30 @@
using NLog;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Parser;
namespace NzbDrone.Core.Indexers.AwesomeHD
{
public class AwesomeHD : HttpIndexerBase<AwesomeHDSettings>
{
public override string Name => "AwesomeHD";
public override DownloadProtocol Protocol => DownloadProtocol.Torrent;
public override bool SupportsRss => false;
public override bool SupportsSearch => true;
public override int PageSize => 50;
public AwesomeHD(IHttpClient httpClient, IIndexerStatusService indexerStatusService, IConfigService configService, IParsingService parsingService, Logger logger)
: base(httpClient, indexerStatusService, configService, parsingService, logger)
{ }
public override IIndexerRequestGenerator GetRequestGenerator()
{
return new AwesomeHDRequestGenerator() { Settings = Settings };
}
public override IParseIndexerResponse GetParser()
{
return new AwesomeHDRssParser(Settings);
}
}
}

View File

@ -0,0 +1,80 @@
using System;
using Newtonsoft.Json;
using System.Xml.Serialization;
using System.Collections.Generic;
namespace NzbDrone.Core.Indexers.AwesomeHD
{
public class Torrent
{
[XmlElement(ElementName = "id")]
public string Id { get; set; }
[XmlElement(ElementName = "groupid")]
public string GroupId { get; set; }
[XmlElement(ElementName = "time")]
public DateTime Time { get; set; }
[XmlElement(ElementName = "userid")]
public string Userid { get; set; }
[XmlElement(ElementName = "size")]
public long Size { get; set; }
[XmlElement(ElementName = "snatched")]
public string Snatched { get; set; }
[XmlElement(ElementName = "seeders")]
public string Seeders { get; set; }
[XmlElement(ElementName = "leechers")]
public string Leechers { get; set; }
[XmlElement(ElementName = "releasegroup")]
public string Releasegroup { get; set; }
[XmlElement(ElementName = "resolution")]
public string Resolution { get; set; }
[XmlElement(ElementName = "media")]
public string Media { get; set; }
[XmlElement(ElementName = "format")]
public string Format { get; set; }
[XmlElement(ElementName = "encoding")]
public string Encoding { get; set; }
[XmlElement(ElementName = "audioformat")]
public string Audioformat { get; set; }
[XmlElement(ElementName = "audiobitrate")]
public string Audiobitrate { get; set; }
[XmlElement(ElementName = "audiochannels")]
public string Audiochannels { get; set; }
[XmlElement(ElementName = "subtitles")]
public string Subtitles { get; set; }
[XmlElement(ElementName = "encodestatus")]
public string Encodestatus { get; set; }
[XmlElement(ElementName = "freeleech")]
public string Freeleech { get; set; }
[XmlElement(ElementName = "cover")]
public string Cover { get; set; }
[XmlElement(ElementName = "smallcover")]
public string Smallcover { get; set; }
[XmlElement(ElementName = "year")]
public string Year { get; set; }
[XmlElement(ElementName = "name")]
public string Name { get; set; }
[XmlElement(ElementName = "imdb")]
public string Imdb { get; set; }
[XmlElement(ElementName = "type")]
public string Type { get; set; }
[XmlElement(ElementName = "plotoutline")]
public string Plotoutline { get; set; }
}
public class SearchResults
{
[XmlElement(ElementName = "authkey")]
public string AuthKey { get; set; }
[XmlElement(ElementName = "torrent")]
public List<Torrent> Torrent { get; set; }
}
public class AwesomeHDSearchResponse
{
[XmlElement(ElementName = "?xml")]
public string Xml { get; set; }
[XmlElement(ElementName = "searchresults")]
public SearchResults SearchResults { get; set; }
}
}

View File

@ -0,0 +1,61 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.IndexerSearch.Definitions;
namespace NzbDrone.Core.Indexers.AwesomeHD
{
public class AwesomeHDRequestGenerator : IIndexerRequestGenerator
{
public AwesomeHDSettings Settings { get; set; }
public virtual IndexerPageableRequestChain GetRecentRequests()
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest("tt2488496"));
return pageableRequests;
}
public virtual IndexerPageableRequestChain GetSearchRequests(SingleEpisodeSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public virtual IndexerPageableRequestChain GetSearchRequests(AnimeEpisodeSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public virtual IndexerPageableRequestChain GetSearchRequests(SpecialEpisodeSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public virtual IndexerPageableRequestChain GetSearchRequests(DailyEpisodeSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public virtual IndexerPageableRequestChain GetSearchRequests(SeasonSearchCriteria searchCriteria)
{
return new IndexerPageableRequestChain();
}
public IndexerPageableRequestChain GetSearchRequests(MovieSearchCriteria searchCriteria)
{
var pageableRequests = new IndexerPageableRequestChain();
pageableRequests.Add(GetRequest(searchCriteria.Movie.ImdbId));
return pageableRequests;
}
private IEnumerable<IndexerRequest> GetRequest(string searchParameters)
{
var request = new IndexerRequest(string.Format("{0}/searchapi.php?action=imdbsearch&passkey={1}&imdb={2}", Settings.BaseUrl.Trim().TrimEnd('/'), Settings.Passkey.Trim(), searchParameters), HttpAccept.Rss);
yield return request;
}
}
}

View File

@ -0,0 +1,92 @@
using System.Collections.Generic;
using System.Net;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NzbDrone.Common.Http;
using NzbDrone.Core.Indexers.Exceptions;
using NzbDrone.Core.Parser.Model;
using System;
using System.Linq;
using System.Xml;
namespace NzbDrone.Core.Indexers.AwesomeHD
{
public class AwesomeHDRssParser : IParseIndexerResponse
{
private readonly AwesomeHDSettings _settings;
public AwesomeHDRssParser(AwesomeHDSettings settings)
{
_settings = settings;
}
public IList<ReleaseInfo> ParseResponse(IndexerResponse indexerResponse)
{
var torrentInfos = new List<ReleaseInfo>();
if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
{
throw new IndexerException(indexerResponse,
"Unexpected response status {0} code from API request",
indexerResponse.HttpResponse.StatusCode);
}
// Hacky ¯\_(ツ)_/¯
XmlDocument doc = new XmlDocument();
doc.LoadXml(indexerResponse.Content);
var json = JsonConvert.SerializeXmlNode(doc);
Console.WriteLine(json);
var jsonResponse = JsonConvert.DeserializeObject<AwesomeHDSearchResponse>(json);
if (jsonResponse == null)
{
throw new IndexerException(indexerResponse, "Unexpected response from request");
}
foreach (var torrent in jsonResponse.SearchResults.Torrent)
{
var id = torrent.Id;
var title = $"{torrent.Name}.{torrent.Year}.{torrent.Resolution}.{torrent.Media}.{torrent.Encoding}.{torrent.Audioformat}-{torrent.Releasegroup}";
torrentInfos.Add(new TorrentInfo()
{
Guid = string.Format("AwesomeHD-{0}", id),
Title = title,
Size = torrent.Size,
DownloadUrl = GetDownloadUrl(id, jsonResponse.SearchResults.AuthKey, _settings.Passkey),
InfoUrl = GetInfoUrl(torrent.GroupId, id),
Seeders = int.Parse(torrent.Seeders),
Peers = int.Parse(torrent.Leechers) + int.Parse(torrent.Seeders),
PublishDate = torrent.Time.ToUniversalTime()
});
}
return torrentInfos.OrderByDescending(o => ((dynamic)o).Seeders).ToArray();
}
private string GetDownloadUrl(string torrentId, string authKey, string passKey)
{
var url = new HttpUri(_settings.BaseUrl)
.CombinePath("/torrents.php")
.AddQueryParam("action", "download")
.AddQueryParam("id", torrentId)
.AddQueryParam("authkey", authKey)
.AddQueryParam("torrent_pass", passKey);
return url.FullUri;
}
private string GetInfoUrl(string groupId, string torrentId)
{
var url = new HttpUri(_settings.BaseUrl)
.CombinePath("/torrents.php")
.AddQueryParam("id", groupId)
.AddQueryParam("torrentid", torrentId);
return url.FullUri;
}
}
}

View File

@ -0,0 +1,37 @@
using FluentValidation;
using NzbDrone.Core.Annotations;
using NzbDrone.Core.ThingiProvider;
using NzbDrone.Core.Validation;
namespace NzbDrone.Core.Indexers.AwesomeHD
{
public class AwesomeHDSettingsValidator : AbstractValidator<AwesomeHDSettings>
{
public AwesomeHDSettingsValidator()
{
RuleFor(c => c.BaseUrl).ValidRootUrl();
RuleFor(c => c.Passkey).NotEmpty();
}
}
public class AwesomeHDSettings : IProviderConfig
{
private static readonly AwesomeHDSettingsValidator Validator = new AwesomeHDSettingsValidator();
public AwesomeHDSettings()
{
BaseUrl = "https://awesome-hd.me";
}
[FieldDefinition(0, Label = "API URL", Advanced = true, HelpText = "Do not change this unless you know what you're doing. Since you Passkey will be sent to that host.")]
public string BaseUrl { get; set; }
[FieldDefinition(1, Label = "Passkey")]
public string Passkey { get; set; }
public NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
}

View File

@ -578,6 +578,7 @@
<Compile Include="IndexerSearch\Definitions\MovieSearchCriteria.cs" />
<Compile Include="IndexerSearch\MoviesSearchCommand.cs" />
<Compile Include="IndexerSearch\MoviesSearchService.cs" />
<Compile Include="Indexers\AwesomeHD\AwesomeHDRssParser.cs" />
<Compile Include="Indexers\DownloadProtocol.cs" />
<Compile Include="Indexers\Exceptions\ApiKeyException.cs" />
<Compile Include="Indexers\Exceptions\IndexerException.cs" />
@ -585,6 +586,10 @@
<Compile Include="Indexers\Exceptions\UnsupportedFeedException.cs" />
<Compile Include="Indexers\EzrssTorrentRssParser.cs" />
<Compile Include="Indexers\FetchAndParseRssService.cs" />
<Compile Include="Indexers\AwesomeHD\AwesomeHD.cs" />
<Compile Include="Indexers\AwesomeHD\AwesomeHDApi.cs" />
<Compile Include="Indexers\AwesomeHD\AwesomeHDRequestGenerator.cs" />
<Compile Include="Indexers\AwesomeHD\AwesomeHDSettings.cs" />
<Compile Include="Indexers\PassThePopcorn\PassThePopcorn.cs" />
<Compile Include="Indexers\PassThePopcorn\PassThePopcornApi.cs" />
<Compile Include="Indexers\PassThePopcorn\PassThePopcornInfo.cs" />