diff --git a/README.md b/README.md index 8ec4c86cb..5e97dc36c 100644 --- a/README.md +++ b/README.md @@ -2,12 +2,10 @@ This project is a new fork and is recruiting development help. If you are able to help out please contact us. -#### Overview -This software creates a [Torznab](https://github.com/Sonarr/Sonarr/wiki/Implementing-a-Torznab-indexer) (with [nZEDb](https://github.com/nZEDb/nZEDb/blob/master/docs/newznab_api_specification.txt) category numbering) and [TorrentPotato](https://github.com/RuudBurger/CouchPotatoServer/wiki/Couchpotato-torrent-provider) API server on your machine. Torznab enables software such as [Sonarr](https://sonarr.tv) to access data from your favorite indexers in a similar fashion to rss but with added features such as searching. TorrentPotato is an interface accessible to [CouchPotato](https://couchpota.to/). - Jackett works as a proxy server: it translates queries from apps (Sonarr, SickRage, CouchPotato, Mylar, etc) into tracker-site-specific http queries, parses the html response, then sends results back to the requesting software. This allows for getting recent uploads (like RSS) and performing searches. Jackett is a single repository of maintained indexer scraping & translation logic - removing the burden from other apps. -We were previously focused on TV but are working on extending searches to allow for searching other items such as movies, comics, and music. +Developer note: The software implments the [Torznab](https://github.com/Sonarr/Sonarr/wiki/Implementing-a-Torznab-indexer) (with [nZEDb](https://github.com/nZEDb/nZEDb/blob/master/docs/newznab_api_specification.txt) category numbering) and [TorrentPotato](https://github.com/RuudBurger/CouchPotatoServer/wiki/Couchpotato-torrent-provider) APIs. + #### Supported Systems @@ -15,47 +13,38 @@ We were previously focused on TV but are working on extending searches to allow * Linux and OSX using Mono 4 (v3 should work but you may experience crashes). -#### Supported Trackers - * [AlphaRatio](https://alpharatio.cc/) - * [AnimeBytes](https://animebytes.tv/) - * [AnimeTorrents](http://animetorrents.me/) - * [Avistaz](https://avistaz.to/) - * [BakaBT](http://bakabt.me/) - * [bB](http://reddit.com/r/baconbits) - * [BeyondHD](https://beyondhd.me/) - * [BIT-HDTV](https://www.bit-hdtv.com) - * [BitMeTV](http://www.bitmetv.org/) - * [BlueTigers](https://www.bluetigers.ca/) - * [BTN](http://broadcasthe.net) - * [Demonoid](http://www.demonoid.pw/) - * [EuTorrents](https://eutorrents.to/) - * [FileList](http://filelist.ro/) - * [FrenchTorrentDb](http://www.frenchtorrentdb.com/) - * [Freshon](https://freshon.tv/) - * [HD-Space](https://hd-space.org/) - * [HD-Torrents.org](https://hd-torrents.org/) - * [Immortalseed.me](http://immortalseed.me) - * [IPTorrents](https://iptorrents.com/) - * [MoreThan.tv](https://morethan.tv/) - * [NextGen](https://nxtgn.org/) - * [pretome](https://pretome.info) - * [PrivateHD](https://privatehd.to/) - * [RARBG](https://rarbg.to/) - * [RuTor](http://rutor.org/) - * [SceneAccess](https://sceneaccess.eu/login) - * [SceneTime](https://www.scenetime.com/) - * [Shazbat](www.shazbat.tv/login) - * [ShowRSS](https://showrss.info/) - * [Strike](https://getstrike.net/) - * [T411](http://www.t411.io/) - * [TehConnection](https://tehconnection.eu/) - * [The Pirate Bay](https://thepiratebay.se/) - * [TorrentBytes](https://www.torrentbytes.net/) - * [TorrentDay](https://torrentday.eu/) - * [TorrentLeech](http://www.torrentleech.org/) - * [TorrentShack](http://torrentshack.me/) - * [Torrentz](https://torrentz.eu/) - * [TV Chaos UK](https://tvchaosuk.com/) +#### Supported Private Trackers + * AlphaRatio + * AnimeBytes + * Avistaz + * BakaBT + * bB + * BeyondHD + * BIT-HDTV + * BitMeTV + * BlueTigers + * BTN + * EuTorrents + * FileList + * Freshon + * HD-Space + * HD-Torrents + * Immortalseed + * IPTorrents + * MoreThan + * NextGen + * Pretome + * PrivateHD + * SceneAccess + * SceneTime + * Shazbat + * Strike + * TehConnection + * TorrentBytes + * TorrentDay + * TorrentLeech + * TorrentShack + * TV Chaos UK #### Installation on Windows @@ -97,7 +86,7 @@ Try running with the "--SSLFix true" if you are on Redhat/Fedora/NNS based libcu You can get additional logging with the switches "-t -l". Please post logs if you are unable to resolve your issue with these switches ensuring to remove your username/password/cookies. ### Contributing -All contributions are welcome just send a pull request. Jackett's framework allows our team (and any other volunteering dev) to implement new trackers in an hour or two. If you'd like support for a new tracker but are not a developer then feel free to leave a request on the [issues page](https://github.com/zone117x/Jackett/issues). It is recommended to use Visual studio 2015 when making code changes in this project. +All contributions are welcome just send a pull request. Jackett's framework allows our team (and any other volunteering dev) to implement new trackers in an hour or two. If you'd like support for a new tracker but are not a developer then feel free to leave a request on the [issues page](https://github.com/zone117x/Jackett/issues). It is recommended to use Visual studio 2015 when making code changes in this project. We currently only support private trackers. ### Screenshots diff --git a/src/Jackett/Content/logos/animetorrents.png b/src/Jackett/Content/logos/animetorrents.png deleted file mode 100644 index d49d1da91..000000000 Binary files a/src/Jackett/Content/logos/animetorrents.png and /dev/null differ diff --git a/src/Jackett/Content/logos/bakabt.png b/src/Jackett/Content/logos/bakabt.png deleted file mode 100644 index 9754ce3e3..000000000 Binary files a/src/Jackett/Content/logos/bakabt.png and /dev/null differ diff --git a/src/Jackett/Content/logos/rarbg.png b/src/Jackett/Content/logos/rarbg.png deleted file mode 100644 index ba5b6539b..000000000 Binary files a/src/Jackett/Content/logos/rarbg.png and /dev/null differ diff --git a/src/Jackett/Content/logos/rutor.png b/src/Jackett/Content/logos/rutor.png deleted file mode 100644 index ea60a0b54..000000000 Binary files a/src/Jackett/Content/logos/rutor.png and /dev/null differ diff --git a/src/Jackett/Content/logos/showrss.png b/src/Jackett/Content/logos/showrss.png deleted file mode 100644 index 77b8ed46f..000000000 Binary files a/src/Jackett/Content/logos/showrss.png and /dev/null differ diff --git a/src/Jackett/Content/logos/strike.png b/src/Jackett/Content/logos/strike.png deleted file mode 100644 index f0570aa7a..000000000 Binary files a/src/Jackett/Content/logos/strike.png and /dev/null differ diff --git a/src/Jackett/Content/logos/t411.png b/src/Jackett/Content/logos/t411.png deleted file mode 100644 index fd7c09505..000000000 Binary files a/src/Jackett/Content/logos/t411.png and /dev/null differ diff --git a/src/Jackett/Content/logos/thepiratebay.png b/src/Jackett/Content/logos/thepiratebay.png deleted file mode 100644 index fa6f61d38..000000000 Binary files a/src/Jackett/Content/logos/thepiratebay.png and /dev/null differ diff --git a/src/Jackett/Content/logos/torrentz.png b/src/Jackett/Content/logos/torrentz.png deleted file mode 100644 index bf987f3f1..000000000 Binary files a/src/Jackett/Content/logos/torrentz.png and /dev/null differ diff --git a/src/Jackett/Indexers/AnimeTorrents.cs b/src/Jackett/Indexers/AnimeTorrents.cs deleted file mode 100644 index 48a1fa95d..000000000 --- a/src/Jackett/Indexers/AnimeTorrents.cs +++ /dev/null @@ -1,176 +0,0 @@ -using CsQuery; -using Jackett.Models; -using Jackett.Services; -using Jackett.Utils; -using Jackett.Utils.Clients; -using Newtonsoft.Json.Linq; -using NLog; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using System.Web; -using Jackett.Models.IndexerConfig; -using System.Collections.Specialized; -using System.Globalization; - -namespace Jackett.Indexers -{ - public class AnimeTorrents : BaseIndexer, IIndexer - { - private string LoginUrl { get { return SiteLink + "login.php"; } } - private string SearchUrl { get { return SiteLink + "ajax/torrents_data.php"; } } - private string SearchUrlReferer { get { return SiteLink + "torrents.php?cat=0&searchin=filename&search="; } } - - new ConfigurationDataBasicLogin configData - { - get { return (ConfigurationDataBasicLogin)base.configData; } - set { base.configData = value; } - } - - public AnimeTorrents(IIndexerManagerService i, HttpWebClient c, Logger l, IProtectionService ps) - : base(name: "AnimeTorrents", - description: "Definitive source for anime and manga", - link: "http://animetorrents.me/", - caps: new TorznabCapabilities(), - manager: i, - client: c, // Forced HTTP client for custom headers - logger: l, - p: ps, - configData: new ConfigurationDataBasicLogin()) - { - AddCategoryMapping(1, TorznabCatType.MoviesSD); // Anime Movie - AddCategoryMapping(6, TorznabCatType.MoviesHD); // Anime Movie HD - AddCategoryMapping(2, TorznabCatType.TVAnime); // Anime Series - AddCategoryMapping(7, TorznabCatType.TVAnime); // Anime Series HD - AddCategoryMapping(5, TorznabCatType.XXXDVD); // Hentai (censored) - AddCategoryMapping(9, TorznabCatType.XXXDVD); // Hentai (censored) HD - AddCategoryMapping(4, TorznabCatType.XXXDVD); // Hentai (un-censored) - AddCategoryMapping(8, TorznabCatType.XXXDVD); // Hentai (un-censored) HD - AddCategoryMapping(13, TorznabCatType.BooksForeign); // Light Novel - AddCategoryMapping(3, TorznabCatType.BooksComics); // Manga - AddCategoryMapping(10, TorznabCatType.BooksComics); // Manga 18+ - AddCategoryMapping(11, TorznabCatType.TVAnime); // OVA - AddCategoryMapping(12, TorznabCatType.TVAnime); // OVA HD - AddCategoryMapping(14, TorznabCatType.BooksComics); // Doujin Anime - AddCategoryMapping(15, TorznabCatType.XXXDVD); // Doujin Anime 18+ - AddCategoryMapping(16, TorznabCatType.AudioForeign); // Doujin Music - AddCategoryMapping(17, TorznabCatType.BooksComics); // Doujinshi - AddCategoryMapping(18, TorznabCatType.BooksComics); // Doujinshi 18+ - AddCategoryMapping(19, TorznabCatType.Audio); // OST - } - - public async Task ApplyConfiguration(JToken configJson) - { - configData.LoadValuesFromJson(configJson); - var pairs = new Dictionary { - { "username", configData.Username.Value }, - { "password", configData.Password.Value }, - { "form", "login" }, - { "rememberme[]", "1" } - }; - - var loginPage = await RequestStringWithCookiesAndRetry(LoginUrl, null, null); - - var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, loginPage.Cookies, true, SearchUrl, SiteLink); - await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("logout.php"), () => - { - CQ dom = result.Content; - var errorMessage = dom[".ui-state-error"].Text().Trim(); - throw new ExceptionWithConfigData(errorMessage, configData); - }); - - return IndexerConfigurationStatus.RequiresTesting; - } - - public async Task> PerformQuery(TorznabQuery query) - { - var releases = new List(); - var searchString = query.GetQueryString(); - var searchUrl = SearchUrl; - var queryCollection = new NameValueCollection(); - - queryCollection.Add("total", "146"); // Not sure what this is about but its required! - - var cat = "0"; - var queryCats = MapTorznabCapsToTrackers(query); - if (queryCats.Count == 1) - { - cat = queryCats.First().ToString(); - } - - queryCollection.Add("cat", cat); - queryCollection.Add("searchin", "filename"); - queryCollection.Add("search", searchString); - queryCollection.Add("page", "1"); - searchUrl += "?" + queryCollection.GetQueryString(); - - var extraHeaders = new Dictionary() - { - { "X-Requested-With", "XMLHttpRequest" } - }; - - var response = await RequestStringWithCookiesAndRetry(searchUrl, null, SearchUrlReferer, extraHeaders); - - var results = response.Content; - try - { - CQ dom = results; - - var rows = dom["tr"]; - foreach (var row in rows.Skip(1)) - { - var release = new ReleaseInfo(); - var qRow = row.Cq(); - var qTitleLink = qRow.Find("td:eq(1) a:eq(0)").First(); - release.Title = qTitleLink.Find("strong").Text().Trim(); - - // If we search an get no results, we still get a table just with no info. - if (string.IsNullOrWhiteSpace(release.Title)) - { - break; - } - - release.Description = release.Title; - release.Guid = new Uri(qTitleLink.Attr("href")); - release.Comments = release.Guid; - - var dateString = qRow.Find("td:eq(4)").Text(); - release.PublishDate = DateTime.ParseExact(dateString, "dd MMM yy", CultureInfo.InvariantCulture); - - var qLink = qRow.Find("td:eq(2) a"); - release.Link = new Uri(qLink.Attr("href")); - - var sizeStr = qRow.Find("td:eq(5)").Text(); - release.Size = ReleaseInfo.GetBytes(sizeStr); - - var connections = qRow.Find("td:eq(7)").Text().Trim().Split("/".ToCharArray(),StringSplitOptions.RemoveEmptyEntries); - - release.Seeders = ParseUtil.CoerceInt(connections[0].Trim()); - release.Peers = ParseUtil.CoerceInt(connections[1].Trim()) + release.Seeders; - - var rCat = row.Cq().Find("td:eq(0) a").First().Attr("href"); - var rCatIdx = rCat.IndexOf("cat="); - if (rCatIdx > -1) - { - rCat = rCat.Substring(rCatIdx + 4); - } - - release.Category = MapTrackerCatToNewznab(rCat); - - releases.Add(release); - } - } - catch (Exception ex) - { - OnParseError(results, ex); - } - - return releases; - } - } -} diff --git a/src/Jackett/Indexers/BakaBT.cs b/src/Jackett/Indexers/BakaBT.cs deleted file mode 100644 index 5c89fd31c..000000000 --- a/src/Jackett/Indexers/BakaBT.cs +++ /dev/null @@ -1,196 +0,0 @@ -using CsQuery; -using Jackett.Models; -using Jackett.Services; -using Jackett.Utils; -using Jackett.Utils.Clients; -using Newtonsoft.Json.Linq; -using NLog; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Net; -using System.Text; -using System.Threading.Tasks; -using System.Web; -using Jackett.Models.IndexerConfig; - -namespace Jackett.Indexers -{ - public class BakaBT : BaseIndexer, IIndexer - { - public string SearchUrl { get { return SiteLink + "browse.php?only=0&hentai=1&incomplete=1&lossless=1&hd=1&multiaudio=1&bonus=1&c1=1&reorder=1&q="; } } - public string LoginUrl { get { return SiteLink + "login.php"; } } - - new ConfigurationDataBasicLogin configData - { - get { return (ConfigurationDataBasicLogin)base.configData; } - set { base.configData = value; } - } - - public BakaBT(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps) - : base(name: "BakaBT", - description: "Anime Community", - link: "http://bakabt.me/", - caps: new TorznabCapabilities(TorznabCatType.TVAnime), - manager: i, - client: wc, - logger: l, - p: ps, - configData: new ConfigurationDataBasicLogin()) - { - } - - public async Task ApplyConfiguration(JToken configJson) - { - configData.LoadValuesFromJson(configJson); - - var loginForm = await webclient.GetString(new Utils.Clients.WebRequest() - { - Url = LoginUrl, - Type = RequestType.GET - }); - - var pairs = new Dictionary { - { "username", configData.Username.Value }, - { "password", configData.Password.Value }, - { "returnto", "/index.php" } - }; - - var response = await RequestLoginAndFollowRedirect(LoginUrl, pairs, loginForm.Cookies, true, null, SiteLink); - var responseContent = response.Content; - await ConfigureIfOK(response.Cookies, responseContent.Contains("Logout"), () => - { - CQ dom = responseContent; - var messageEl = dom[".error"].First(); - var errorMessage = messageEl.Text().Trim(); - throw new ExceptionWithConfigData(errorMessage, configData); - }); - - return IndexerConfigurationStatus.RequiresTesting; - } - - public async Task> PerformQuery(TorznabQuery query) - { - - // This tracker only deals with full seasons so chop off the episode/season number if we have it D: - if (!string.IsNullOrWhiteSpace(query.SearchTerm)) - { - var splitindex = query.SearchTerm.LastIndexOf(' '); - if (splitindex > -1) - query.SearchTerm = query.SearchTerm.Substring(0, splitindex); - } - - var releases = new List(); - var searchString = query.SanitizedSearchTerm; - var episodeSearchUrl = SearchUrl + HttpUtility.UrlEncode(searchString); - var response = await RequestStringWithCookiesAndRetry(episodeSearchUrl); - - try - { - CQ dom = response.Content; - var rows = dom[".torrents tr.torrent"]; - - foreach (var row in rows) - { - - var qRow = row.Cq(); - var qTitleLink = qRow.Find("a.title").First(); - var title = qTitleLink.Text().Trim(); - - // Insert before the release info - var taidx = title.IndexOf('('); - var tbidx = title.IndexOf('['); - - if (taidx == -1) - taidx = title.Length; - - if (tbidx == -1) - tbidx = title.Length; - var titleSplit = Math.Min(taidx, tbidx); - var titleSeries = title.Substring(0, titleSplit); - var releaseInfo = title.Substring(titleSplit); - - // For each over each pipe deliminated name - foreach (var name in titleSeries.Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)) - { - var release = new ReleaseInfo(); - - release.Title = (name + releaseInfo).Trim(); - // Ensure the season is defined as this tracker only deals with full seasons - if (release.Title.IndexOf("Season") == -1) - { - // Insert before the release info - var aidx = release.Title.IndexOf('('); - var bidx = release.Title.IndexOf('['); - - if (aidx == -1) - aidx = release.Title.Length; - - if (bidx == -1) - bidx = release.Title.Length; - - var insertPoint = Math.Min(aidx, bidx); - release.Title = release.Title.Substring(0, insertPoint) + "Season 1 " + release.Title.Substring(insertPoint); - } - - release.Description = release.Title; - release.Guid = new Uri(SiteLink + qTitleLink.Attr("href")); - release.Comments = release.Guid; - - release.Link = new Uri(SiteLink + qRow.Find(".peers a").First().Attr("href")); - - release.Seeders = int.Parse(qRow.Find(".peers a").Get(0).InnerText); - release.Peers = release.Seeders + int.Parse(qRow.Find(".peers a").Get(1).InnerText); - - release.MinimumRatio = 1; - - var size = qRow.Find(".size").First().Text(); - release.Size = ReleaseInfo.GetBytes(size); - - //22 Jul 15 - var dateStr = qRow.Find(".added").First().Text().Replace("'", string.Empty); - if (dateStr.Split(' ')[0].Length == 1) - dateStr = "0" + dateStr; - - if (string.Equals(dateStr, "yesterday", StringComparison.InvariantCultureIgnoreCase)) - { - release.PublishDate = DateTime.Now.AddDays(-1); - } - else if (string.Equals(dateStr, "today", StringComparison.InvariantCultureIgnoreCase)) - { - release.PublishDate = DateTime.Now; - } - else - { - release.PublishDate = DateTime.ParseExact(dateStr, "dd MMM yy", CultureInfo.InvariantCulture); - } - - releases.Add(release); - } - } - } - catch (Exception ex) - { - OnParseError(response.Content, ex); - } - - return releases; - } - - public override async Task Download(Uri link) - { - var downloadPage = await RequestStringWithCookies(link.ToString()); - CQ dom = downloadPage.Content; - var downloadLink = dom.Find(".download_link").First().Attr("href"); - - if (string.IsNullOrWhiteSpace(downloadLink)) - { - throw new Exception("Unable to find download link."); - } - - var response = await RequestBytesWithCookies(SiteLink + downloadLink); - return response.Content; - } - } -} diff --git a/src/Jackett/Indexers/RUTor.cs b/src/Jackett/Indexers/RUTor.cs deleted file mode 100644 index 6d7d77e14..000000000 --- a/src/Jackett/Indexers/RUTor.cs +++ /dev/null @@ -1,233 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Jackett.Models; -using Newtonsoft.Json.Linq; -using NLog; -using Jackett.Utils; -using System.Net; -using System.Net.Http; -using CsQuery; -using System.Web; -using Jackett.Services; -using Jackett.Utils.Clients; -using System.Text.RegularExpressions; -using Jackett.Models.IndexerConfig; -using System.Globalization; -using Newtonsoft.Json; -using Jackett.Models.IndexerConfig.Bespoke; - -namespace Jackett.Indexers -{ - public class RuTor : BaseIndexer, IIndexer - { - private string SearchUrl { get { return SiteLink + "search/0/{0}/000/0/{1}"; } } - private string BrowseUrl { get { return SiteLink + "browse/0/{0}/0/0"; } } - readonly static string defaultSiteLink = "http://rutor.org/"; - - new ConfigurationDataRuTor configData - { - get { return (ConfigurationDataRuTor)base.configData; } - set { base.configData = value; } - } - - public RuTor(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps) - : base(name: "RUTor", - description: "Свободный торрент трекер", - link: "http://rutor.org/", - caps: TorznabUtil.CreateDefaultTorznabTVCaps(), - manager: i, - client: wc, - logger: l, - p: ps, - configData: new ConfigurationDataRuTor(defaultSiteLink)) - { - TorznabCaps.Categories.Add(TorznabCatType.TVAnime); - TorznabCaps.Categories.Add(TorznabCatType.Movies); - TorznabCaps.Categories.Add(TorznabCatType.Audio); - TorznabCaps.Categories.Add(TorznabCatType.Books); - } - - public async Task ApplyConfiguration(JToken configJson) - { - configData.LoadValuesFromJson(configJson); - var oldConfig = configData; - var releases = await PerformQuery(new TorznabQuery()); - - await ConfigureIfOK(string.Empty, releases.Count() > 0, () => - { - configData = oldConfig; - throw new Exception("Could not find releases from this URL"); - }); - - return IndexerConfigurationStatus.RequiresTesting; - } - - - protected override void SaveConfig() - { - indexerService.SaveConfig(this as IIndexer, JsonConvert.SerializeObject(configData)); - } - - // Override to load legacy config format - public override void LoadFromSavedConfiguration(JToken jsonConfig) - { - var json = jsonConfig.ToString(); - configData = JsonConvert.DeserializeObject(json); - IsConfigured = true; - } - - private readonly int CAT_ANY = 0; - private readonly int CAT_FOREIGN_MOVIE = 1; - // private readonly int CAT_OUR_MOVIES = 5; - // private readonly int CAT_POP_SCIFI_MOVIES = 12; - private readonly int CAT_TV_SERIES = 4; - // private readonly int CAT_TV = 6; - // private readonly int CAT_ANIMATION = 7; - private readonly int CAT_ANIME = 10; - private readonly int CAT_MUSIC = 2; - // private readonly int CAT_GAMES = 8; - // private readonly int CAT_SOFTWARE = 9; - // private readonly int CAT_SPORTS_HEALTH = 13; - // private readonly int CAT_HUMOR = 15; - // private readonly int CAT_ECONOMY_LIFE = 14; - private readonly int CAT_BOOKS = 11; - // private readonly int CAT_OTHER = 3; - - public async Task> PerformQuery(TorznabQuery query) - { - var releases = new List(); - var searchString = query.GetQueryString(); - var searchCategory = CAT_ANY; - - if (query.Categories.Contains(TorznabCatType.TV.ID) || - query.Categories.Contains(TorznabCatType.TVHD.ID) || - query.Categories.Contains(TorznabCatType.TVSD.ID)) - { - searchCategory = CAT_TV_SERIES; - } - - if ((searchCategory == CAT_ANY) && - (query.Categories.Contains(TorznabCatType.Movies.ID) || - query.Categories.Contains(TorznabCatType.MoviesForeign.ID) || - query.Categories.Contains(TorznabCatType.MoviesHD.ID) || - query.Categories.Contains(TorznabCatType.MoviesSD.ID))) - { - searchCategory = CAT_FOREIGN_MOVIE; - } - - if ((searchCategory == CAT_ANY) && - (query.Categories.Contains(TorznabCatType.TVAnime.ID))) - { - searchCategory = CAT_ANIME; - } - - if ((searchCategory == CAT_ANY) && - (query.Categories.Contains(TorznabCatType.Books.ID))) - { - searchCategory = CAT_BOOKS; - } - - if ((searchCategory == CAT_ANY) && - (query.Categories.Contains(TorznabCatType.Audio.ID) || - query.Categories.Contains(TorznabCatType.AudioLossless.ID) || - query.Categories.Contains(TorznabCatType.AudioMP3.ID))) - { - searchCategory = CAT_MUSIC; - } - - string queryUrl = string.Empty; - if (string.IsNullOrWhiteSpace(searchString)) - { - queryUrl = string.Format(BrowseUrl, searchCategory); - } - else - { - queryUrl = string.Format(SearchUrl, searchCategory, HttpUtility.UrlEncode(searchString.Trim())); - } - - var results = await RequestStringWithCookiesAndRetry(queryUrl, string.Empty); - try - { - CQ dom = results.Content; - var rows = dom["#index table tr"]; - foreach (var row in rows.Skip(1)) - { - var release = new ReleaseInfo(); - - release.MinimumRatio = 1; - release.MinimumSeedTime = 172800; - - var date = StringUtil.StripNonAlphaNumeric(row.Cq().Find("td:eq(0)").Text().Trim() - .Replace("Янв", "01") - .Replace("Фев", "02") - .Replace("Мар", "03") - .Replace("Апр", "04") - .Replace("Май", "05") - .Replace("Июн", "06") - .Replace("Июл", "07") - .Replace("Авг", "08") - .Replace("Сен", "09") - .Replace("Окт", "10") - .Replace("Ноя", "11") - .Replace("Дек", "12")); - - release.PublishDate = DateTime.ParseExact(date, "ddMMyy", CultureInfo.InvariantCulture); - - var hasTorrent = row.Cq().Find("td:eq(1) a").Length == 3; - var titleIndex = 1; - if (hasTorrent) - titleIndex++; - - release.Title = row.Cq().Find("td:eq(1) a:eq(" + titleIndex + ")").Text().Trim(); - if (configData.StripRussian.Value) - { - var split = release.Title.IndexOf('/'); - if (split > -1) - { - release.Title = release.Title.Substring(split + 1).Trim(); - } - } - - release.Description = release.Title; - - var hasComments = row.Cq().Find("td:eq(2) img").Length > 0; - var sizeCol = 2; - - if (hasComments) - sizeCol++; - - var sizeStr = StringUtil.StripRegex(row.Cq().Find("td:eq(" + sizeCol + ")").Text(), "[^a-zA-Z0-9\\. -]", " ").Trim(); - string[] sizeSplit = sizeStr.Split(' '); - release.Size = ReleaseInfo.GetBytes(sizeSplit[1].ToLower(), ParseUtil.CoerceFloat(sizeSplit[0])); - - release.Seeders = ParseUtil.CoerceInt(row.Cq().Find(".green").Text().Trim()); - release.Peers = ParseUtil.CoerceInt(row.Cq().Find(".red").Text().Trim()) + release.Seeders; - - release.Guid = new Uri(configData.Url.Value + row.Cq().Find("td:eq(1) a:eq(" + titleIndex + ")").Attr("href").Substring(1)); - release.Comments = release.Guid; - - if (hasTorrent) - { - release.Link = new Uri(row.Cq().Find("td:eq(1) a:eq(0)").Attr("href")); - release.MagnetUri = new Uri(row.Cq().Find("td:eq(1) a:eq(1)").Attr("href")); - } - else - { - release.MagnetUri = new Uri(row.Cq().Find("td:eq(1) a:eq(0)").Attr("href")); - } - - releases.Add(release); - } - } - catch (Exception ex) - { - OnParseError(results.Content, ex); - } - - return releases; - } - } -} diff --git a/src/Jackett/Indexers/Rarbg.cs b/src/Jackett/Indexers/Rarbg.cs deleted file mode 100644 index 5e35e85bb..000000000 --- a/src/Jackett/Indexers/Rarbg.cs +++ /dev/null @@ -1,187 +0,0 @@ -using Jackett.Models; -using Jackett.Models.IndexerConfig; -using Jackett.Services; -using Jackett.Utils.Clients; -using Newtonsoft.Json.Linq; -using NLog; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Threading.Tasks; -using System.Web; - -namespace Jackett.Indexers -{ - public class Rarbg : BaseIndexer, IIndexer - { - readonly static string defaultSiteLink = "https://torrentapi.org/"; - - private Uri BaseUri - { - get { return new Uri(configData.Url.Value); } - set { configData.Url.Value = value.ToString(); } - } - - private string ApiEndpoint { get { return BaseUri + "pubapi_v2.php"; } } - private string TokenUrl { get { return ApiEndpoint + "?get_token=get_token"; } } - private string SearchUrl { get { return ApiEndpoint + "?app_id=jackett_v{0}&mode={1}&format=json_extended&search_string={2}&token={3}"; } } - - - new ConfigurationDataUrl configData - { - get { return (ConfigurationDataUrl)base.configData; } - set { base.configData = value; } - } - - private DateTime lastTokenFetch; - private string token; - - readonly TimeSpan TOKEN_DURATION = TimeSpan.FromMinutes(10); - - private bool HasValidToken { get { return !string.IsNullOrEmpty(token) && lastTokenFetch > DateTime.Now - TOKEN_DURATION; } } - - Dictionary categoryLabels; - - public Rarbg(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps) - : base(name: "RARBG", - description: "RARBG", - link: defaultSiteLink, - caps: new TorznabCapabilities(), - manager: i, - client: wc, - logger: l, - p: ps, - configData: new ConfigurationDataUrl(defaultSiteLink)) - { - categoryLabels = new Dictionary(); - - AddCat(4, TorznabCatType.XXX, "XXX (18+)"); - AddCat(14, TorznabCatType.MoviesSD, "Movies/XVID"); - AddCat(48, TorznabCatType.MoviesHD, "Movies/XVID/720"); - AddCat(17, TorznabCatType.MoviesSD, "Movies/x264"); - AddCat(44, TorznabCatType.MoviesHD, "Movies/x264/1080"); - AddCat(45, TorznabCatType.MoviesHD, "Movies/x264/720"); - AddCat(47, TorznabCatType.Movies3D, "Movies/x264/3D"); - AddCat(42, TorznabCatType.MoviesBluRay, "Movies/Full BD"); - AddCat(46, TorznabCatType.MoviesBluRay, "Movies/BD Remux"); - AddCat(18, TorznabCatType.TVSD, "TV Episodes"); - AddCat(41, TorznabCatType.TVHD, "TV HD Episodes"); - AddCat(23, TorznabCatType.AudioMP3, "Music/MP3"); - AddCat(25, TorznabCatType.AudioLossless, "Music/FLAC"); - AddCat(27, TorznabCatType.PCGames, "Games/PC ISO"); - AddCat(28, TorznabCatType.PCGames, "Games/PC RIP"); - AddCat(40, TorznabCatType.ConsolePS3, "Games/PS3"); - AddCat(32, TorznabCatType.ConsoleXbox360, "Games/XBOX-360"); - AddCat(33, TorznabCatType.PCISO, "Software/PC ISO"); - AddCat(35, TorznabCatType.BooksEbook, "e-Books"); - } - - void AddCat(int cat, TorznabCategory catType, string label) - { - AddCategoryMapping(cat, catType); - categoryLabels.Add(label, cat); - } - - async Task CheckToken() - { - if (!HasValidToken) - { - var result = await RequestStringWithCookiesAndRetry(TokenUrl); - var json = JObject.Parse(result.Content); - token = json.Value("token"); - lastTokenFetch = DateTime.Now; - } - } - - public async Task ApplyConfiguration(JToken configJson) - { - configData.LoadValuesFromJson(configJson); - var releases = await PerformQuery(new TorznabQuery()); - - await ConfigureIfOK(string.Empty, releases.Count() > 0, () => - { - throw new Exception("Could not find releases from this URL"); - }); - - return IndexerConfigurationStatus.Completed; - } - - public Task> PerformQuery(TorznabQuery query) - { - return PerformQuery(query, 0); - } - - public async Task> PerformQuery(TorznabQuery query, int attempts = 0) - { - await CheckToken(); - var releases = new List(); - var queryStr = HttpUtility.UrlEncode(query.GetQueryString()); - - var mode = string.IsNullOrEmpty(queryStr) ? "list" : "search"; - var episodeSearchUrl = string.Format(SearchUrl, Engine.ConfigService.GetVersion(), mode, queryStr, token); - var cats = string.Join(";", MapTorznabCapsToTrackers(query)); - if (!string.IsNullOrEmpty(cats)) - { - episodeSearchUrl += "&category=" + cats; - } - - var response = await RequestStringWithCookiesAndRetry(episodeSearchUrl, string.Empty); - - try - { - var jsonContent = JObject.Parse(response.Content); - - int errorCode = jsonContent.Value("error_code"); - if (errorCode == 20) // no results found - { - return releases.ToArray(); - } - - if (errorCode > 0) // too many requests per second - { - if (attempts < 3) - { - await Task.Delay(TimeSpan.FromSeconds(2)); - return await PerformQuery(query, ++attempts); - } - else - { - throw new Exception(jsonContent.Value("error")); - } - } - - foreach (var item in jsonContent.Value("torrent_results")) - { - var release = new ReleaseInfo(); - release.Title = item.Value("title"); - release.Description = release.Title; - release.Category = MapTrackerCatToNewznab(categoryLabels[item.Value("category")].ToString()); - - release.MagnetUri = new Uri(item.Value("download")); - release.InfoHash = release.MagnetUri.ToString().Split(':')[3].Split('&')[0]; - - release.Comments = new Uri(item.Value("info_page")); - release.Guid = release.Comments; - - // ex: 2015-08-16 21:25:08 +0000 - var dateStr = item.Value("pubdate").Replace(" +0000", ""); - var dateTime = DateTime.ParseExact(dateStr, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); - release.PublishDate = DateTime.SpecifyKind(dateTime, DateTimeKind.Utc).ToLocalTime(); - - release.Seeders = item.Value("seeders"); - release.Peers = item.Value("leechers") + release.Seeders; - release.Size = item.Value("size"); - releases.Add(release); - } - } - catch (Exception ex) - { - OnParseError(response.Content, ex); - } - - return releases.ToArray(); - } - - } -} diff --git a/src/Jackett/Indexers/ShowRSS.cs b/src/Jackett/Indexers/ShowRSS.cs deleted file mode 100644 index 62638a65d..000000000 --- a/src/Jackett/Indexers/ShowRSS.cs +++ /dev/null @@ -1,132 +0,0 @@ -using Jackett.Models; -using Jackett.Services; -using Jackett.Utils; -using Jackett.Utils.Clients; -using Newtonsoft.Json.Linq; -using NLog; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using System.Web; -using System.Xml; -using Jackett.Models.IndexerConfig; - -namespace Jackett.Indexers -{ - public class ShowRSS : BaseIndexer, IIndexer - { - readonly static string defaultSiteLink = "http://showrss.info/"; - - private Uri BaseUri - { - get { return new Uri(configData.Url.Value); } - set { configData.Url.Value = value.ToString(); } - } - - private string SearchAllUrl { get { return BaseUri + "feeds/all.rss"; } } - - new ConfigurationDataUrl configData - { - get { return (ConfigurationDataUrl)base.configData; } - set { base.configData = value; } - } - - public ShowRSS(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps) - : base(name: "ShowRSS", - description: "showRSS is a service that allows you to keep track of your favorite TV shows", - link: defaultSiteLink, - caps: TorznabUtil.CreateDefaultTorznabTVCaps(), - manager: i, - client: wc, - logger: l, - p: ps, - configData: new ConfigurationDataUrl(defaultSiteLink)) - { - } - - public async Task ApplyConfiguration(JToken configJson) - { - configData.LoadValuesFromJson(configJson); - var releases = await PerformQuery(new TorznabQuery()); - - await ConfigureIfOK(string.Empty, releases.Count() > 0, () => - { - throw new Exception("Could not find releases from this URL"); - }); - - return IndexerConfigurationStatus.RequiresTesting; - } - - // Override to load legacy config format - public override void LoadFromSavedConfiguration(JToken jsonConfig) - { - if (jsonConfig is JObject) - { - BaseUri = new Uri(jsonConfig.Value("base_url")); - SaveConfig(); - IsConfigured = true; - return; - } - - base.LoadFromSavedConfiguration(jsonConfig); - } - - public override Task Download(Uri link) - { - throw new NotImplementedException(); - } - - public async Task> PerformQuery(TorznabQuery query) - { - var releases = new List(); - var episodeSearchUrl = string.Format(SearchAllUrl); - var result = await RequestStringWithCookiesAndRetry(episodeSearchUrl, string.Empty); - var xmlDoc = new XmlDocument(); - - try - { - xmlDoc.LoadXml(result.Content); - ReleaseInfo release; - string serie_title; - - foreach (XmlNode node in xmlDoc.GetElementsByTagName("item")) - { - release = new ReleaseInfo(); - - release.MinimumRatio = 1; - release.MinimumSeedTime = 172800; - - serie_title = node.SelectSingleNode(".//*[local-name()='rawtitle']").InnerText; - release.Title = serie_title; - - release.Comments = new Uri(node.SelectSingleNode("link").InnerText); - int category = 0; - int.TryParse(node.SelectSingleNode("title").InnerText, out category); - release.Category = category; - var test = node.SelectSingleNode("enclosure"); - release.Guid = new Uri(test.Attributes["url"].Value); - release.PublishDate = DateTime.Parse(node.SelectSingleNode("pubDate").InnerText, CultureInfo.InvariantCulture); - - release.Description = node.SelectSingleNode("description").InnerText; - release.InfoHash = node.SelectSingleNode("description").InnerText; - release.Size = 0; - release.Seeders = 1; - release.Peers = 1; - release.MagnetUri = new Uri(node.SelectSingleNode("link").InnerText); - releases.Add(release); - } - } - catch (Exception ex) - { - OnParseError(result.Content, ex); - } - - return releases; - } - } -} diff --git a/src/Jackett/Indexers/Strike.cs b/src/Jackett/Indexers/Strike.cs deleted file mode 100644 index 74bdf59cd..000000000 --- a/src/Jackett/Indexers/Strike.cs +++ /dev/null @@ -1,173 +0,0 @@ -using Jackett.Models; -using Jackett.Services; -using Jackett.Utils; -using Jackett.Utils.Clients; -using Newtonsoft.Json.Linq; -using NLog; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Text; -using System.Threading.Tasks; -using System.Web; -using Jackett.Models.IndexerConfig; -using System.Collections.Specialized; -using Jackett.Models.IndexerConfig.Bespoke; - -namespace Jackett.Indexers -{ - public class Strike : BaseIndexer, IIndexer - { - readonly static string defaultSiteLink = "https://getstrike.net/"; - - private Uri BaseUri - { - get { return new Uri(configData.Url.Value); } - set { configData.Url.Value = value.ToString(); } - } - - private string SearchUrl { get { return BaseUri + "api/v2/torrents/search/?phrase={0}"; } } - private string DownloadUrl { get { return BaseUri + "torrents/api/download/{0}.torrent"; } } - - new ConfigurationDataStrike configData - { - get { return (ConfigurationDataStrike)base.configData; } - set { base.configData = value; } - } - - - public Strike(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps) - : base(name: "Strike", - description: "Torrent search engine", - link: defaultSiteLink, - caps: new TorznabCapabilities(), - manager: i, - client: wc, - logger: l, - p: ps, - configData: new ConfigurationDataStrike(defaultSiteLink)) - { - AddCategoryMapping("Anime", TorznabCatType.TVAnime); - AddCategoryMapping("Applications", TorznabCatType.PC); - AddCategoryMapping("Books", TorznabCatType.Books); - AddCategoryMapping("Games", TorznabCatType.PCGames); - AddCategoryMapping("Movies", TorznabCatType.Movies); - AddCategoryMapping("TV", TorznabCatType.TV); - AddCategoryMapping("XXX", TorznabCatType.XXX); - AddCategoryMapping("Music", TorznabCatType.Audio); - - /*AddCategoryMapping("Movies:Highres Movies", TorznabCatType.MoviesHD); - AddCategoryMapping("Movies:3D Movies", TorznabCatType.Movies3D); - AddCategoryMapping("Books:Ebooks", TorznabCatType.BooksEbook); - AddCategoryMapping("Books:Comics", TorznabCatType.BooksComics); - AddCategoryMapping("Books:Audio Books", TorznabCatType.AudioAudiobook); - AddCategoryMapping("Games:XBOX360", TorznabCatType.ConsoleXbox360); - AddCategoryMapping("Games:Wii", TorznabCatType.ConsoleWii); - AddCategoryMapping("Games:PSP", TorznabCatType.ConsolePSP); - AddCategoryMapping("Games:PS3", TorznabCatType.ConsolePS3); - AddCategoryMapping("Games:PC", TorznabCatType.PCGames); - AddCategoryMapping("Games:Android", TorznabCatType.PCPhoneAndroid); - AddCategoryMapping("Music:Mp3", TorznabCatType.AudioMP3);*/ - } - - public async Task ApplyConfiguration(JToken configJson) - { - configData.LoadValuesFromJson(configJson); - var releases = await PerformQuery(new TorznabQuery()); - - await ConfigureIfOK(string.Empty, releases.Count() > 0, () => - { - throw new Exception("Could not find releases from this URL"); - }); - - return IndexerConfigurationStatus.Completed; - } - - // Override to load legacy config format - public override void LoadFromSavedConfiguration(JToken jsonConfig) - { - if (jsonConfig is JObject) - { - BaseUri = new Uri(jsonConfig.Value("base_url")); - SaveConfig(); - IsConfigured = true; - return; - } - - base.LoadFromSavedConfiguration(jsonConfig); - } - - public async Task> PerformQuery(TorznabQuery query) - { - List releases = new List(); - var queryString = query.GetQueryString(); - var searchTerm = string.IsNullOrEmpty(queryString) ? DateTime.Now.Year.ToString() : queryString; - var episodeSearchUrl = string.Format(SearchUrl, HttpUtility.UrlEncode(searchTerm)); - - var trackerCategories = MapTorznabCapsToTrackers(query, mapChildrenCatsToParent: true); - - // This tracker can only search one cat at a time, otherwise search all and filter results - if (trackerCategories.Count == 1) - { - episodeSearchUrl += "&category=" + trackerCategories[0]; - } - - var results = await RequestStringWithCookiesAndRetry(episodeSearchUrl, string.Empty); - try - { - var jResults = JObject.Parse(results.Content); - foreach (JObject result in (JArray)jResults["torrents"]) - { - var release = new ReleaseInfo(); - - release.MinimumRatio = 1; - release.MinimumSeedTime = 172800; - - if (trackerCategories.Count > 0 && !trackerCategories.Contains((string)result["torrent_category"])) - { - continue; - } - release.Category = MapTrackerCatToNewznab((string)result["torrent_category"]); - - release.Title = (string)result["torrent_title"]; - release.Description = release.Title; - release.Seeders = (int)result["seeds"]; - release.Peers = (int)result["leeches"] + release.Seeders; - release.Size = (long)result["size"]; - - // "Apr 2, 2015", "Apr 12, 2015" (note the spacing) - // some are unix timestamps, some are not.. :/ - var dateString = string.Join(" ", ((string)result["upload_date"]).Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)); - float dateVal; - if (ParseUtil.TryCoerceFloat(dateString, out dateVal)) - release.PublishDate = DateTimeUtil.UnixTimestampToDateTime(dateVal); - else - release.PublishDate = DateTime.ParseExact(dateString, "MMM d, yyyy", CultureInfo.InvariantCulture); - - release.Guid = new Uri((string)result["page"]); - release.Comments = release.Guid; - - release.InfoHash = (string)result["torrent_hash"]; - release.MagnetUri = new Uri((string)result["magnet_uri"]); - release.Link = new Uri(string.Format(DownloadUrl, release.InfoHash)); - - releases.Add(release); - } - } - catch (Exception ex) - { - OnParseError(results.Content, ex); - } - - return releases; - } - - public override Task Download(Uri link) - { - throw new NotImplementedException(); - } - } -} diff --git a/src/Jackett/Indexers/T411.cs b/src/Jackett/Indexers/T411.cs deleted file mode 100644 index bc59c9fdc..000000000 --- a/src/Jackett/Indexers/T411.cs +++ /dev/null @@ -1,249 +0,0 @@ -using Jackett.Models; -using Jackett.Services; -using Jackett.Utils; -using Jackett.Utils.Clients; -using Newtonsoft.Json.Linq; -using NLog; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Text; -using System.Threading.Tasks; -using System.Web; -using Jackett.Models.IndexerConfig; - -namespace Jackett.Indexers -{ - public class T411 : BaseIndexer, IIndexer - { - private readonly string CommentsUrl = ""; - const string ApiUrl = "http://api.t411.in"; - const string AuthUrl = ApiUrl + "/auth"; - const string SearchUrl = ApiUrl + "/torrents/search/{0}"; - const string DownloadUrl = ApiUrl + "/torrents/download/{0}"; - - HttpClientHandler handler; - HttpClient client; - - new ConfigurationDataLoginTokin configData - { - get { return (ConfigurationDataLoginTokin)base.configData; } - set { base.configData = value; } - } - - public T411(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps) - : base(name: "T411", - description: "French Torrent Tracker", - link: "http://www.t411.in/", - caps: TorznabUtil.CreateDefaultTorznabTVCaps(), - manager: i, - client: wc, - logger: l, - p: ps, - configData: new ConfigurationDataLoginTokin()) - { - CommentsUrl = SiteLink + "/torrents/{0}"; - IsConfigured = false; - handler = new HttpClientHandler - { - AllowAutoRedirect = true - }; - client = new HttpClient(handler); - - - - AddCategoryMapping("Film\\/Vidéo", TorznabCatType.Movies); - AddCategoryMapping("Vidéo-clips", TorznabCatType.Other); - AddCategoryMapping("Série TV", TorznabCatType.TV); - AddCategoryMapping("Animation", TorznabCatType.TVAnime); - AddCategoryMapping("Film", TorznabCatType.Movies); - AddCategoryMapping("Concert", TorznabCatType.AudioVideo); - AddCategoryMapping("Documentaire", TorznabCatType.Audio); - AddCategoryMapping("Spectacle", TorznabCatType.TV); - AddCategoryMapping("Sport", TorznabCatType.TVSport); - AddCategoryMapping("Animation Série", TorznabCatType.TVAnime); - AddCategoryMapping("Emission TV", TorznabCatType.TV); - - - AddCategoryMapping("Application", TorznabCatType.PC0day); - AddCategoryMapping("Linux", TorznabCatType.PC); - AddCategoryMapping("MacOS", TorznabCatType.PCMac); - AddCategoryMapping("Windows", TorznabCatType.PC); - AddCategoryMapping("Smartphone", TorznabCatType.PCPhoneOther); - AddCategoryMapping("Tablette", TorznabCatType.PCPhoneOther); - AddCategoryMapping("Autre", TorznabCatType.PC); - AddCategoryMapping("Formation", TorznabCatType.PC); - - AddCategoryMapping("Emulation", TorznabCatType.PC); - AddCategoryMapping("Emulateurs", TorznabCatType.PC); - AddCategoryMapping("Roms", TorznabCatType.PC); - - AddCategoryMapping("GPS", TorznabCatType.Other); - AddCategoryMapping("Applications", TorznabCatType.Other); - AddCategoryMapping("Cartes", TorznabCatType.Other); - AddCategoryMapping("Divers", TorznabCatType.Other); - - AddCategoryMapping("Audio", TorznabCatType.Audio); - AddCategoryMapping("Karaoke", TorznabCatType.Audio); - AddCategoryMapping("Samples", TorznabCatType.Audio); - AddCategoryMapping("Musique", TorznabCatType.Audio); - AddCategoryMapping("Podcast Radio", TorznabCatType.Audio); - - AddCategoryMapping("eBook", TorznabCatType.BooksEbook); - AddCategoryMapping("Audio", TorznabCatType.AudioAudiobook); - AddCategoryMapping("Bds", TorznabCatType.AudioVideo); - AddCategoryMapping("Comics", TorznabCatType.BooksComics); - AddCategoryMapping("Livres", TorznabCatType.Books); - AddCategoryMapping("Mangas", TorznabCatType.BooksForeign); - AddCategoryMapping("Presse", TorznabCatType.BooksMagazines); - - AddCategoryMapping("xXx", TorznabCatType.XXX); - AddCategoryMapping("eBooks", TorznabCatType.XXXImageset); - AddCategoryMapping("Jeux vidéo", TorznabCatType.XXX); - AddCategoryMapping("Video", TorznabCatType.XXXDVD); - //AddCategoryMapping("Animation", TorznabCatType.XXX); Used above :/ - - AddCategoryMapping("Jeu vidéo", TorznabCatType.PCGames); - AddCategoryMapping("Linux", TorznabCatType.PCGames); - AddCategoryMapping("MacOS", TorznabCatType.PCGames); - // AddCategoryMapping("Windows", TorznabCatType.PCGames); Used above :/ - AddCategoryMapping("Nintendo", TorznabCatType.Console); - AddCategoryMapping("Sony", TorznabCatType.Console); - AddCategoryMapping("Microsoft", TorznabCatType.PCGames); - AddCategoryMapping("Smartphone", TorznabCatType.PCPhoneOther); - AddCategoryMapping("Tablette", TorznabCatType.PCPhoneOther); - AddCategoryMapping("Autre", TorznabCatType.Other); - - AddCategoryMapping("Jeux vidéo", TorznabCatType.Other); - } - - async Task GetAuthToken(bool forceFetch = false) - { - if (!forceFetch && configData.LastTokenFetchDateTime > DateTime.Now - TimeSpan.FromHours(48)) - { - return configData.ApiToken.Value; - } - - var pairs = new Dictionary { - { "username", configData.Username.Value }, - { "password", configData.Password.Value } - }; - - var content = new FormUrlEncodedContent(pairs); - - var response = await client.PostAsync(AuthUrl, content); - var responseContent = await response.Content.ReadAsStringAsync(); - var jsonResponse = JObject.Parse(responseContent); - if (jsonResponse["error"] != null) - { - throw new ApplicationException((string)jsonResponse["error"]); - } - configData.ApiToken.Value = (string)jsonResponse["token"]; - configData.LastTokenFetchDateTime = DateTime.Now; - return configData.ApiToken.Value; - } - - public async Task ApplyConfiguration(JToken configJson) - { - configData.LoadValuesFromJson(configJson); - - Exception tokenFetchEx = null; - try - { - await GetAuthToken(true); - } - catch (Exception ex) - { - tokenFetchEx = new ExceptionWithConfigData(ex.Message, configData); - } - - await ConfigureIfOK(string.Empty, tokenFetchEx == null, () => - { - throw tokenFetchEx; - }); - - return IndexerConfigurationStatus.RequiresTesting; - } - - // Override to load legacy config format - public override void LoadFromSavedConfiguration(JToken jsonConfig) - { - if (jsonConfig is JObject) - { - configData.ApiToken.Value = jsonConfig.Value("token"); ; - configData.Username.Value = jsonConfig.Value("username"); - configData.Password.Value = jsonConfig.Value("password"); - SaveConfig(); - IsConfigured = true; - return; - } - - base.LoadFromSavedConfiguration(jsonConfig); - } - - public async Task> PerformQuery(TorznabQuery query) - { - var releases = new List(); - var searchTerm = string.IsNullOrEmpty(query.SanitizedSearchTerm) ? "%20" : query.SanitizedSearchTerm; - var searchString = searchTerm + " " + query.GetEpisodeSearchString(); - var episodeSearchUrl = string.Format(SearchUrl, HttpUtility.UrlEncode(searchString)); - - var message = new HttpRequestMessage(); - message.Method = HttpMethod.Get; - message.RequestUri = new Uri(episodeSearchUrl); - message.Headers.TryAddWithoutValidation("Authorization", await GetAuthToken()); - - var response = await client.SendAsync(message); - var results = await response.Content.ReadAsStringAsync(); - - var jsonResult = JObject.Parse(results); - try - { - var items = (JArray)jsonResult["torrents"]; - foreach (var item in items) - { - var release = new ReleaseInfo(); - - release.MinimumRatio = 1; - release.MinimumSeedTime = 172800; - var torrentId = (string)item["id"]; - release.Link = new Uri(string.Format(DownloadUrl, torrentId)); - release.Title = (string)item["name"]; - release.Description = release.Title; - release.Comments = new Uri(string.Format(CommentsUrl, (string)item["rewritename"])); - release.Guid = release.Comments; - - var dateUtc = DateTime.ParseExact((string)item["added"], "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); - release.PublishDate = DateTime.SpecifyKind(dateUtc, DateTimeKind.Utc).ToLocalTime(); - - release.Seeders = ParseUtil.CoerceInt((string)item["seeders"]); - release.Peers = ParseUtil.CoerceInt((string)item["leechers"]) + release.Seeders; - release.Size = ParseUtil.CoerceLong((string)item["size"]); - release.Category = MapTrackerCatToNewznab((string)item["categoryname"]); - - releases.Add(release); - } - } - catch (Exception ex) - { - OnParseError(results, ex); - } - return releases; - } - - public override async Task Download(Uri link) - { - var message = new HttpRequestMessage(); - message.Method = HttpMethod.Get; - message.RequestUri = link; - message.Headers.TryAddWithoutValidation("Authorization", await GetAuthToken()); - - var response = await client.SendAsync(message); - return await response.Content.ReadAsByteArrayAsync(); - } - } -} diff --git a/src/Jackett/Indexers/ThePirateBay.cs b/src/Jackett/Indexers/ThePirateBay.cs deleted file mode 100644 index 2135442cd..000000000 --- a/src/Jackett/Indexers/ThePirateBay.cs +++ /dev/null @@ -1,161 +0,0 @@ -using CsQuery; -using Jackett.Models; -using Jackett.Services; -using Jackett.Utils; -using Jackett.Utils.Clients; -using Newtonsoft.Json.Linq; -using NLog; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using System.Web; -using Jackett.Models.IndexerConfig; - -namespace Jackett.Indexers -{ - public class ThePirateBay : BaseIndexer, IIndexer - { - readonly static string defaultSiteLink = "https://thepiratebay.mn/"; - - private Uri BaseUri - { - get { return new Uri(configData.Url.Value); } - set { configData.Url.Value = value.ToString(); } - } - - private string SearchUrl { get { return BaseUri + "search/{0}/0/99/208,205"; } } - private string RecentUrl { get { return BaseUri + "recent"; } } - - new ConfigurationDataUrl configData - { - get { return (ConfigurationDataUrl)base.configData; } - set { base.configData = value; } - } - - public ThePirateBay(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps) - : base(name: "The Pirate Bay", - description: "The worlds largest bittorrent indexer", - link: defaultSiteLink, - caps: TorznabUtil.CreateDefaultTorznabTVCaps(), - manager: i, - client: wc, - logger: l, - p: ps, - configData: new ConfigurationDataUrl(defaultSiteLink)) - { - } - - public async Task ApplyConfiguration(JToken configJson) - { - configData.LoadValuesFromJson(configJson); - var releases = await PerformQuery(new TorznabQuery()); - - await ConfigureIfOK(string.Empty, releases.Count() > 0, () => - { - throw new Exception("Could not find releases from this URL"); - }); - - return IndexerConfigurationStatus.Completed; - } - - // Override to load legacy config format - public override void LoadFromSavedConfiguration(JToken jsonConfig) - { - if (jsonConfig is JObject) - { - BaseUri = new Uri(jsonConfig.Value("base_url")); - SaveConfig(); - IsConfigured = true; - return; - } - - base.LoadFromSavedConfiguration(jsonConfig); - } - - public async Task> PerformQuery(TorznabQuery query) - { - var releases = new List(); - var queryStr = HttpUtility.UrlEncode(query.GetQueryString()); - var episodeSearchUrl = string.IsNullOrWhiteSpace(queryStr) ? RecentUrl : string.Format(SearchUrl, queryStr); - var response = await RequestStringWithCookiesAndRetry(episodeSearchUrl, string.Empty); - - try - { - CQ dom = response.Content; - - var rows = dom["#searchResult > tbody > tr"]; - foreach (var row in rows) - { - if (row.ChildElements.Count() < 2) - continue; - - var release = new ReleaseInfo(); - CQ qRow = row.Cq(); - CQ qLink = qRow.Find(".detName > .detLink").First(); - - release.MinimumRatio = 1; - release.MinimumSeedTime = 172800; - release.Title = qLink.Text().Trim(); - release.Description = release.Title; - release.Comments = new Uri(BaseUri + qLink.Attr("href").TrimStart('/')); - release.Guid = release.Comments; - - var downloadCol = row.ChildElements.ElementAt(1).Cq().Children("a"); - release.MagnetUri = new Uri(downloadCol.Attr("href")); - release.InfoHash = release.MagnetUri.ToString().Split(':')[3].Split('&')[0]; - - var descString = qRow.Find(".detDesc").Text().Trim(); - var descParts = descString.Split(','); - - var timeString = descParts[0].Split(' ')[1]; - - if (timeString.Contains(" ago")) - { - release.PublishDate = (DateTime.Now - TimeSpan.FromMinutes(ParseUtil.CoerceInt(timeString.Split(' ')[0]))); - } - else if (timeString.Contains("Today")) - { - release.PublishDate = (DateTime.UtcNow - TimeSpan.FromHours(2) - TimeSpan.Parse(timeString.Split(' ')[1])).ToLocalTime(); - } - else if (timeString.Contains("Y-day")) - { - release.PublishDate = (DateTime.UtcNow - TimeSpan.FromHours(26) - TimeSpan.Parse(timeString.Split(' ')[1])).ToLocalTime(); - } - else if (timeString.Contains(':')) - { - var utc = DateTime.ParseExact(timeString, "MM-dd HH:mm", CultureInfo.InvariantCulture) - TimeSpan.FromHours(2); - release.PublishDate = DateTime.SpecifyKind(utc, DateTimeKind.Utc).ToLocalTime(); - } - else - { - var utc = DateTime.ParseExact(timeString, "MM-dd yyyy", CultureInfo.InvariantCulture) - TimeSpan.FromHours(2); - release.PublishDate = DateTime.SpecifyKind(utc, DateTimeKind.Utc).ToLocalTime(); - } - - release.Size = ReleaseInfo.GetBytes(descParts[1]); - - release.Seeders = ParseUtil.CoerceInt(row.ChildElements.ElementAt(2).Cq().Text()); - release.Peers = ParseUtil.CoerceInt(row.ChildElements.ElementAt(3).Cq().Text()) + release.Seeders; - - releases.Add(release); - } - } - catch (Exception ex) - { - OnParseError(response.Content, ex); - } - return releases.ToArray(); - } - - public override Task Download(Uri link) - { - throw new NotImplementedException(); - } - } -} diff --git a/src/Jackett/Indexers/Torrentz.cs b/src/Jackett/Indexers/Torrentz.cs deleted file mode 100644 index ed7640726..000000000 --- a/src/Jackett/Indexers/Torrentz.cs +++ /dev/null @@ -1,212 +0,0 @@ -using Jackett.Models; -using Jackett.Services; -using Jackett.Utils; -using Jackett.Utils.Clients; -using Newtonsoft.Json.Linq; -using NLog; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Net; -using System.Net.Http; -using System.Threading.Tasks; -using System.Web; -using System.Windows.Forms; -using System.Xml; -using System.Linq; -using Jackett.Models.IndexerConfig; - -namespace Jackett.Indexers -{ - public class Torrentz : BaseIndexer, IIndexer - { - readonly static string defaultSiteLink = "https://torrentz.eu/"; - - private Uri BaseUri - { - get { return new Uri(configData.Url.Value); } - set { configData.Url.Value = value.ToString(); } - } - - private string SearchUrl { get { return BaseUri + "feed_verifiedP?f={0}"; } } - - new ConfigurationDataUrl configData - { - get { return (ConfigurationDataUrl)base.configData; } - set { base.configData = value; } - } - - - public Torrentz(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps) - : base(name: "Torrentz", - description: "Torrentz is a meta-search engine and a Multisearch. This means we just search other search engines.", - link: defaultSiteLink, - caps: TorznabUtil.CreateDefaultTorznabTVCaps(), - manager: i, - client: wc, - logger: l, - p: ps, - configData: new ConfigurationDataUrl(defaultSiteLink)) - { - } - - public async Task ApplyConfiguration(JToken configJson) - { - configData.LoadValuesFromJson(configJson); - var releases = await PerformQuery(new TorznabQuery()); - - await ConfigureIfOK(string.Empty, releases.Count() > 0, () => - { - throw new Exception("Could not find releases from this URL"); - }); - return IndexerConfigurationStatus.Completed; - } - - // Override to load legacy config format - public override void LoadFromSavedConfiguration(JToken jsonConfig) - { - if (jsonConfig is JObject) - { - BaseUri = new Uri(jsonConfig.Value("base_url")); - SaveConfig(); - IsConfigured = true; - return; - } - - base.LoadFromSavedConfiguration(jsonConfig); - } - - public async Task> PerformQuery(TorznabQuery query) - { - var releases = new List(); - var searchString = query.GetQueryString(); - var episodeSearchUrl = string.Format(SearchUrl, HttpUtility.UrlEncode(searchString.Trim())); - var xmlDoc = new XmlDocument(); - string xml = string.Empty; - var result = await RequestStringWithCookiesAndRetry(episodeSearchUrl); - - try - { - xmlDoc.LoadXml(result.Content); - - ReleaseInfo release; - TorrentzHelper td; - string serie_title; - - foreach (XmlNode node in xmlDoc.GetElementsByTagName("item")) - { - release = new ReleaseInfo(); - - release.MinimumRatio = 1; - release.MinimumSeedTime = 172800; - serie_title = node.SelectSingleNode("title").InnerText; - release.Title = serie_title; - - release.Comments = new Uri(node.SelectSingleNode("link").InnerText); - int category = 0; - int.TryParse(node.SelectSingleNode("category").InnerText, out category); - release.Category = category; - release.Guid = new Uri(node.SelectSingleNode("guid").InnerText); - release.PublishDate = DateTime.Parse(node.SelectSingleNode("pubDate").InnerText, CultureInfo.InvariantCulture); - - td = new TorrentzHelper(node.SelectSingleNode("description").InnerText); - release.Description = td.Description; - release.InfoHash = td.hash; - release.Size = td.Size; - release.Seeders = td.Seeders; - release.Peers = td.Peers + release.Seeders; - release.MagnetUri = TorrentzHelper.createMagnetLink(td.hash, serie_title); - releases.Add(release); - } - } - catch (Exception ex) - { - OnParseError(xml, ex); - } - - return releases; - } - - public override Task Download(Uri link) - { - throw new NotImplementedException(); - } - } - - public class TorrentzHelper - { - public TorrentzHelper(string description) - { - this.Description = description; - if (null == description) - { - this.Description = ""; - this.Size = 0; - this.Peers = 0; - this.Seeders = 0; - this.hash = ""; - } - else - FillProperties(); - } - - public static Uri createMagnetLink(string hash, string title) - { - string MagnetLink = "magnet:?xt=urn:btih:{0}&dn={1}&tr={2}"; - string Trackers = WebUtility.UrlEncode("udp://tracker.publicbt.com:80&tr=udp://tracker.openbittorrent.com:80&tr=udp://tracker.ccc.de:80&tr=udp://tracker.istole.it:80"); - title = WebUtility.UrlEncode(title); - - return new Uri(string.Format(MagnetLink, hash, title, Trackers)); - } - - private void FillProperties() - { - string description = this.Description; - int counter = 0; - while (description.Contains(" ")) - { - int nextSpace = description.IndexOf(": ") + 1; - int secondSpace; - if (counter != 0) - secondSpace = description.IndexOf(" ", nextSpace + 1); - else - secondSpace = description.IndexOf(": ", nextSpace + 2) - description.IndexOf(" ", nextSpace); - - string val; - if (secondSpace == -1) - { - val = description.Substring(nextSpace).Trim(); - description = string.Empty; - } - else - { - val = description.Substring(nextSpace, secondSpace - nextSpace).Trim(); - description = description.Substring(secondSpace); - } - - switch (counter) - { - case 0: - this.Size = ReleaseInfo.GetBytes(val); - break; - case 1: - this.Seeders = ParseUtil.CoerceInt(val.Contains(",") ? val.Remove(val.IndexOf(","), 1) : val); - break; - case 2: - this.Peers = ParseUtil.CoerceInt(val.Contains(",") ? val.Remove(val.IndexOf(","), 1) : val); - break; - case 3: - this.hash = val; - break; - } - counter++; - } - } - - public string Description { get; set; } - public long Size { get; set; } - public int Seeders { get; set; } - public int Peers { get; set; } - public string hash { get; set; } - } -} diff --git a/src/Jackett/Jackett.csproj b/src/Jackett/Jackett.csproj index 84b515891..ad65375f4 100644 --- a/src/Jackett/Jackett.csproj +++ b/src/Jackett/Jackett.csproj @@ -190,7 +190,6 @@ - @@ -212,15 +211,12 @@ - - - @@ -228,15 +224,10 @@ - - - - - @@ -437,15 +428,9 @@ PreserveNewest - - PreserveNewest - PreserveNewest - - PreserveNewest - PreserveNewest @@ -500,12 +485,6 @@ PreserveNewest - - PreserveNewest - - - PreserveNewest - PreserveNewest @@ -515,15 +494,9 @@ PreserveNewest - - PreserveNewest - PreserveNewest - - PreserveNewest - PreserveNewest @@ -584,18 +557,9 @@ PreserveNewest - - PreserveNewest - - - PreserveNewest - PreserveNewest - - PreserveNewest - PreserveNewest