diff --git a/README.md b/README.md index f70b08359..9ff1973b2 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/ ### Supported Public Trackers * Anidex + * Anime Tosho * cpasbien * EZTV * Horrible Subs diff --git a/src/Jackett/Indexers/Feeds/AnimeTosho.cs b/src/Jackett/Indexers/Feeds/AnimeTosho.cs new file mode 100644 index 000000000..1ca6b6b0d --- /dev/null +++ b/src/Jackett/Indexers/Feeds/AnimeTosho.cs @@ -0,0 +1,33 @@ +using System; +using System.Text; +using Jackett.Models; +using Jackett.Models.IndexerConfig; +using Jackett.Services; +using Jackett.Utils.Clients; +using NLog; + +namespace Jackett.Indexers.Newznab +{ + public class AnimeTosho : BaseNewznabIndexer + { + public AnimeTosho(IIndexerConfigurationService configService, IWebClient client, Logger logger, IProtectionService p) : base("Anime Tosho", "https://animetosho.org/", "", configService, client, logger, new ConfigurationData(), p) + { + // TODO + // this might be downloaded and refreshed instead of hard-coding it + TorznabCaps = new TorznabCapabilities + { + SearchAvailable = true, + TVSearchAvailable = false, + MovieSearchAvailable = false, + SupportsImdbSearch = false, + SupportsTVRageSearch = false + }; + + Encoding = Encoding.UTF8; + Language = "en-en"; + Type = "public"; + } + + protected override Uri FeedUri => new Uri("https://animetosho.org/feed/api"); + } +} diff --git a/src/Jackett/Indexers/Feeds/BaseFeedIndexer.cs b/src/Jackett/Indexers/Feeds/BaseFeedIndexer.cs new file mode 100644 index 000000000..7ddd65ab8 --- /dev/null +++ b/src/Jackett/Indexers/Feeds/BaseFeedIndexer.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Jackett.Models; +using Jackett.Models.IndexerConfig; +using Jackett.Services; +using Jackett.Utils; +using Jackett.Utils.Clients; +using Newtonsoft.Json.Linq; +using NLog; + +namespace Jackett.Indexers +{ + public abstract class BaseFeedIndexer : BaseWebIndexer + { + protected abstract Uri FeedUri { get; } + + protected BaseFeedIndexer(string name, string link, string description, IIndexerConfigurationService configService, IWebClient client, Logger logger, ConfigurationData configData, IProtectionService p, TorznabCapabilities caps = null, string downloadBase = null) : base(name, link, description, configService, client, logger, configData, p, caps, downloadBase) + { + } + + public override Task ApplyConfiguration(JToken configJson) + { + IsConfigured = true; + return Task.FromResult(IndexerConfigurationStatus.RequiresTesting); + } + + protected override async Task> PerformQuery(TorznabQuery query) + { + var requestUri = FeedUri.ToString(); + if (!query.SanitizedSearchTerm.IsNullOrEmptyOrWhitespace()) + requestUri = requestUri + "?q=" + query.SanitizedSearchTerm; + var request = new WebRequest + { + Url = requestUri, + Type = RequestType.GET + }; + var result = await webclient.GetString(request); + + var results = ParseFeedForResults(result.Content); + + return results; + } + + protected abstract IEnumerable ParseFeedForResults(string feedContent); + } +} diff --git a/src/Jackett/Indexers/Feeds/BaseNewznabIndexer.cs b/src/Jackett/Indexers/Feeds/BaseNewznabIndexer.cs new file mode 100644 index 000000000..bff59a6fa --- /dev/null +++ b/src/Jackett/Indexers/Feeds/BaseNewznabIndexer.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Xml.Linq; +using Jackett.Models; +using Jackett.Models.IndexerConfig; +using Jackett.Services; +using Jackett.Utils; +using Jackett.Utils.Clients; +using NLog; + +namespace Jackett.Indexers +{ + public abstract class BaseNewznabIndexer : BaseFeedIndexer + { + protected BaseNewznabIndexer(string name, string link, string description, IIndexerConfigurationService configService, IWebClient client, Logger logger, ConfigurationData configData, IProtectionService p, TorznabCapabilities caps = null, string downloadBase = null) : base(name, link, description, configService, client, logger, configData, p, caps, downloadBase) + { + } + + protected override IEnumerable ParseFeedForResults(string feedContent) + { + var doc = XDocument.Parse(feedContent); + + var results = doc.Descendants("item").Select((XElement item) => + { + var attributes = item.Descendants().Where(e => e.Name.LocalName == "attr"); + var release = new ReleaseInfo + { + Title = item.FirstValue("title"), + Guid = item.FirstValue("guid").ToUri(), + Link = item.FirstValue("link").ToUri(), + Comments = item.FirstValue("comments").ToUri(), + PublishDate = item.FirstValue("pubDate").ToDateTime(), + Category = new List { Int32.Parse(attributes.First(e => e.Attribute("name").Value == "category").Attribute("value").Value) }, + Size = Int64.Parse(attributes.First(e => e.Attribute("name").Value == "size").Attribute("value").Value), + Files = Int64.Parse(attributes.First(e => e.Attribute("name").Value == "files").Attribute("value").Value), + Description = item.FirstValue("description"), + Seeders = Int32.Parse(attributes.First(e => e.Attribute("name").Value == "seeders").Attribute("value").Value), + Peers = Int32.Parse(attributes.First(e => e.Attribute("name").Value == "peers").Attribute("value").Value), + InfoHash = attributes.First(e => e.Attribute("name").Value == "infohash").Attribute("value").Value, + MagnetUri = attributes.First(e => e.Attribute("name").Value == "magneturl").Attribute("value").Value.ToUri(), + }; + return release; + }); + + return results; + } + } +} diff --git a/src/Jackett/Jackett.csproj b/src/Jackett/Jackett.csproj index 8c5337c4a..fd9442772 100644 --- a/src/Jackett/Jackett.csproj +++ b/src/Jackett/Jackett.csproj @@ -380,6 +380,9 @@ + + + @@ -564,6 +567,9 @@ + + +