From f968bfe8524e105898b5631070766454c107fd57 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 16 Aug 2015 15:51:15 -0600 Subject: [PATCH 01/19] Added published date to website downloads --- src/Website/App_Data/web.db | Bin 0 -> 36864 bytes src/Website/Content/libs/jquery.timeago.js | 221 +++++++++++++++++++++ src/Website/Scripts/jquery.timeago.js | 221 +++++++++++++++++++++ src/Website/Views/Download/Index.cshtml | 1 + src/Website/Views/Shared/_Layout.cshtml | 8 + src/Website/Web.config | 2 +- src/Website/Website.csproj | 4 + src/Website/packages.config | 1 + 8 files changed, 457 insertions(+), 1 deletion(-) create mode 100644 src/Website/App_Data/web.db create mode 100644 src/Website/Content/libs/jquery.timeago.js create mode 100644 src/Website/Scripts/jquery.timeago.js diff --git a/src/Website/App_Data/web.db b/src/Website/App_Data/web.db new file mode 100644 index 0000000000000000000000000000000000000000..ef741b127f41f7ea9a44b4124a4f09ae19b1be2c GIT binary patch literal 36864 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 svE-!~V!Z literal 0 HcmV?d00001 diff --git a/src/Website/Content/libs/jquery.timeago.js b/src/Website/Content/libs/jquery.timeago.js new file mode 100644 index 000000000..15805a619 --- /dev/null +++ b/src/Website/Content/libs/jquery.timeago.js @@ -0,0 +1,221 @@ +/** + * Timeago is a jQuery plugin that makes it easy to support automatically + * updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago"). + * + * @name timeago + * @version 1.4.1 + * @requires jQuery v1.2.3+ + * @author Ryan McGeary + * @license MIT License - http://www.opensource.org/licenses/mit-license.php + * + * For usage and examples, visit: + * http://timeago.yarp.com/ + * + * Copyright (c) 2008-2015, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org) + */ + +(function (factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['jquery'], factory); + } else { + // Browser globals + factory(jQuery); + } +}(function ($) { + $.timeago = function(timestamp) { + if (timestamp instanceof Date) { + return inWords(timestamp); + } else if (typeof timestamp === "string") { + return inWords($.timeago.parse(timestamp)); + } else if (typeof timestamp === "number") { + return inWords(new Date(timestamp)); + } else { + return inWords($.timeago.datetime(timestamp)); + } + }; + var $t = $.timeago; + + $.extend($.timeago, { + settings: { + refreshMillis: 60000, + allowPast: true, + allowFuture: false, + localeTitle: false, + cutoff: 0, + strings: { + prefixAgo: null, + prefixFromNow: null, + suffixAgo: "ago", + suffixFromNow: "from now", + inPast: 'any moment now', + seconds: "less than a minute", + minute: "about a minute", + minutes: "%d minutes", + hour: "about an hour", + hours: "about %d hours", + day: "a day", + days: "%d days", + month: "about a month", + months: "%d months", + year: "about a year", + years: "%d years", + wordSeparator: " ", + numbers: [] + } + }, + + inWords: function(distanceMillis) { + if(!this.settings.allowPast && ! this.settings.allowFuture) { + throw 'timeago allowPast and allowFuture settings can not both be set to false.'; + } + + var $l = this.settings.strings; + var prefix = $l.prefixAgo; + var suffix = $l.suffixAgo; + if (this.settings.allowFuture) { + if (distanceMillis < 0) { + prefix = $l.prefixFromNow; + suffix = $l.suffixFromNow; + } + } + + if(!this.settings.allowPast && distanceMillis >= 0) { + return this.settings.strings.inPast; + } + + var seconds = Math.abs(distanceMillis) / 1000; + var minutes = seconds / 60; + var hours = minutes / 60; + var days = hours / 24; + var years = days / 365; + + function substitute(stringOrFunction, number) { + var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction; + var value = ($l.numbers && $l.numbers[number]) || number; + return string.replace(/%d/i, value); + } + + var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) || + seconds < 90 && substitute($l.minute, 1) || + minutes < 45 && substitute($l.minutes, Math.round(minutes)) || + minutes < 90 && substitute($l.hour, 1) || + hours < 24 && substitute($l.hours, Math.round(hours)) || + hours < 42 && substitute($l.day, 1) || + days < 30 && substitute($l.days, Math.round(days)) || + days < 45 && substitute($l.month, 1) || + days < 365 && substitute($l.months, Math.round(days / 30)) || + years < 1.5 && substitute($l.year, 1) || + substitute($l.years, Math.round(years)); + + var separator = $l.wordSeparator || ""; + if ($l.wordSeparator === undefined) { separator = " "; } + return $.trim([prefix, words, suffix].join(separator)); + }, + + parse: function(iso8601) { + var s = $.trim(iso8601); + s = s.replace(/\.\d+/,""); // remove milliseconds + s = s.replace(/-/,"/").replace(/-/,"/"); + s = s.replace(/T/," ").replace(/Z/," UTC"); + s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400 + s = s.replace(/([\+\-]\d\d)$/," $100"); // +09 -> +0900 + return new Date(s); + }, + datetime: function(elem) { + var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title"); + return $t.parse(iso8601); + }, + isTime: function(elem) { + // jQuery's `is()` doesn't play well with HTML5 in IE + return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time"); + } + }); + + // functions that can be called via $(el).timeago('action') + // init is default when no action is given + // functions are called with context of a single element + var functions = { + init: function(){ + var refresh_el = $.proxy(refresh, this); + refresh_el(); + var $s = $t.settings; + if ($s.refreshMillis > 0) { + this._timeagoInterval = setInterval(refresh_el, $s.refreshMillis); + } + }, + update: function(time){ + var parsedTime = $t.parse(time); + $(this).data('timeago', { datetime: parsedTime }); + if($t.settings.localeTitle) $(this).attr("title", parsedTime.toLocaleString()); + refresh.apply(this); + }, + updateFromDOM: function(){ + $(this).data('timeago', { datetime: $t.parse( $t.isTime(this) ? $(this).attr("datetime") : $(this).attr("title") ) }); + refresh.apply(this); + }, + dispose: function () { + if (this._timeagoInterval) { + window.clearInterval(this._timeagoInterval); + this._timeagoInterval = null; + } + } + }; + + $.fn.timeago = function(action, options) { + var fn = action ? functions[action] : functions.init; + if(!fn){ + throw new Error("Unknown function name '"+ action +"' for timeago"); + } + // each over objects here and call the requested function + this.each(function(){ + fn.call(this, options); + }); + return this; + }; + + function refresh() { + //check if it's still visible + if(!$.contains(document.documentElement,this)){ + //stop if it has been removed + $(this).timeago("dispose"); + return this; + } + + var data = prepareData(this); + var $s = $t.settings; + + if (!isNaN(data.datetime)) { + if ( $s.cutoff == 0 || Math.abs(distance(data.datetime)) < $s.cutoff) { + $(this).text(inWords(data.datetime)); + } + } + return this; + } + + function prepareData(element) { + element = $(element); + if (!element.data("timeago")) { + element.data("timeago", { datetime: $t.datetime(element) }); + var text = $.trim(element.text()); + if ($t.settings.localeTitle) { + element.attr("title", element.data('timeago').datetime.toLocaleString()); + } else if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) { + element.attr("title", text); + } + } + return element.data("timeago"); + } + + function inWords(date) { + return $t.inWords(distance(date)); + } + + function distance(date) { + return (new Date().getTime() - date.getTime()); + } + + // fix for IE6 suckage + document.createElement("abbr"); + document.createElement("time"); +})); diff --git a/src/Website/Scripts/jquery.timeago.js b/src/Website/Scripts/jquery.timeago.js new file mode 100644 index 000000000..15805a619 --- /dev/null +++ b/src/Website/Scripts/jquery.timeago.js @@ -0,0 +1,221 @@ +/** + * Timeago is a jQuery plugin that makes it easy to support automatically + * updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago"). + * + * @name timeago + * @version 1.4.1 + * @requires jQuery v1.2.3+ + * @author Ryan McGeary + * @license MIT License - http://www.opensource.org/licenses/mit-license.php + * + * For usage and examples, visit: + * http://timeago.yarp.com/ + * + * Copyright (c) 2008-2015, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org) + */ + +(function (factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define(['jquery'], factory); + } else { + // Browser globals + factory(jQuery); + } +}(function ($) { + $.timeago = function(timestamp) { + if (timestamp instanceof Date) { + return inWords(timestamp); + } else if (typeof timestamp === "string") { + return inWords($.timeago.parse(timestamp)); + } else if (typeof timestamp === "number") { + return inWords(new Date(timestamp)); + } else { + return inWords($.timeago.datetime(timestamp)); + } + }; + var $t = $.timeago; + + $.extend($.timeago, { + settings: { + refreshMillis: 60000, + allowPast: true, + allowFuture: false, + localeTitle: false, + cutoff: 0, + strings: { + prefixAgo: null, + prefixFromNow: null, + suffixAgo: "ago", + suffixFromNow: "from now", + inPast: 'any moment now', + seconds: "less than a minute", + minute: "about a minute", + minutes: "%d minutes", + hour: "about an hour", + hours: "about %d hours", + day: "a day", + days: "%d days", + month: "about a month", + months: "%d months", + year: "about a year", + years: "%d years", + wordSeparator: " ", + numbers: [] + } + }, + + inWords: function(distanceMillis) { + if(!this.settings.allowPast && ! this.settings.allowFuture) { + throw 'timeago allowPast and allowFuture settings can not both be set to false.'; + } + + var $l = this.settings.strings; + var prefix = $l.prefixAgo; + var suffix = $l.suffixAgo; + if (this.settings.allowFuture) { + if (distanceMillis < 0) { + prefix = $l.prefixFromNow; + suffix = $l.suffixFromNow; + } + } + + if(!this.settings.allowPast && distanceMillis >= 0) { + return this.settings.strings.inPast; + } + + var seconds = Math.abs(distanceMillis) / 1000; + var minutes = seconds / 60; + var hours = minutes / 60; + var days = hours / 24; + var years = days / 365; + + function substitute(stringOrFunction, number) { + var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction; + var value = ($l.numbers && $l.numbers[number]) || number; + return string.replace(/%d/i, value); + } + + var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) || + seconds < 90 && substitute($l.minute, 1) || + minutes < 45 && substitute($l.minutes, Math.round(minutes)) || + minutes < 90 && substitute($l.hour, 1) || + hours < 24 && substitute($l.hours, Math.round(hours)) || + hours < 42 && substitute($l.day, 1) || + days < 30 && substitute($l.days, Math.round(days)) || + days < 45 && substitute($l.month, 1) || + days < 365 && substitute($l.months, Math.round(days / 30)) || + years < 1.5 && substitute($l.year, 1) || + substitute($l.years, Math.round(years)); + + var separator = $l.wordSeparator || ""; + if ($l.wordSeparator === undefined) { separator = " "; } + return $.trim([prefix, words, suffix].join(separator)); + }, + + parse: function(iso8601) { + var s = $.trim(iso8601); + s = s.replace(/\.\d+/,""); // remove milliseconds + s = s.replace(/-/,"/").replace(/-/,"/"); + s = s.replace(/T/," ").replace(/Z/," UTC"); + s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400 + s = s.replace(/([\+\-]\d\d)$/," $100"); // +09 -> +0900 + return new Date(s); + }, + datetime: function(elem) { + var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title"); + return $t.parse(iso8601); + }, + isTime: function(elem) { + // jQuery's `is()` doesn't play well with HTML5 in IE + return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time"); + } + }); + + // functions that can be called via $(el).timeago('action') + // init is default when no action is given + // functions are called with context of a single element + var functions = { + init: function(){ + var refresh_el = $.proxy(refresh, this); + refresh_el(); + var $s = $t.settings; + if ($s.refreshMillis > 0) { + this._timeagoInterval = setInterval(refresh_el, $s.refreshMillis); + } + }, + update: function(time){ + var parsedTime = $t.parse(time); + $(this).data('timeago', { datetime: parsedTime }); + if($t.settings.localeTitle) $(this).attr("title", parsedTime.toLocaleString()); + refresh.apply(this); + }, + updateFromDOM: function(){ + $(this).data('timeago', { datetime: $t.parse( $t.isTime(this) ? $(this).attr("datetime") : $(this).attr("title") ) }); + refresh.apply(this); + }, + dispose: function () { + if (this._timeagoInterval) { + window.clearInterval(this._timeagoInterval); + this._timeagoInterval = null; + } + } + }; + + $.fn.timeago = function(action, options) { + var fn = action ? functions[action] : functions.init; + if(!fn){ + throw new Error("Unknown function name '"+ action +"' for timeago"); + } + // each over objects here and call the requested function + this.each(function(){ + fn.call(this, options); + }); + return this; + }; + + function refresh() { + //check if it's still visible + if(!$.contains(document.documentElement,this)){ + //stop if it has been removed + $(this).timeago("dispose"); + return this; + } + + var data = prepareData(this); + var $s = $t.settings; + + if (!isNaN(data.datetime)) { + if ( $s.cutoff == 0 || Math.abs(distance(data.datetime)) < $s.cutoff) { + $(this).text(inWords(data.datetime)); + } + } + return this; + } + + function prepareData(element) { + element = $(element); + if (!element.data("timeago")) { + element.data("timeago", { datetime: $t.datetime(element) }); + var text = $.trim(element.text()); + if ($t.settings.localeTitle) { + element.attr("title", element.data('timeago').datetime.toLocaleString()); + } else if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) { + element.attr("title", text); + } + } + return element.data("timeago"); + } + + function inWords(date) { + return $t.inWords(distance(date)); + } + + function distance(date) { + return (new Date().getTime() - date.getTime()); + } + + // fix for IE6 suckage + document.createElement("abbr"); + document.createElement("time"); +})); diff --git a/src/Website/Views/Download/Index.cshtml b/src/Website/Views/Download/Index.cshtml index a3cb09d12..51018c5de 100644 --- a/src/Website/Views/Download/Index.cshtml +++ b/src/Website/Views/Download/Index.cshtml @@ -9,6 +9,7 @@ {

@release.Title - @release.Version

+
Published
var files = Website.Services.FileService.FindFilesForRelease(release.Version); diff --git a/src/Website/Views/Shared/_Layout.cshtml b/src/Website/Views/Shared/_Layout.cshtml index 58497ea4d..d7373becc 100644 --- a/src/Website/Views/Shared/_Layout.cshtml +++ b/src/Website/Views/Shared/_Layout.cshtml @@ -8,6 +8,7 @@ + @@ -36,5 +37,12 @@ + + + \ No newline at end of file diff --git a/src/Website/Web.config b/src/Website/Web.config index 449a64236..f150b78f1 100644 --- a/src/Website/Web.config +++ b/src/Website/Web.config @@ -31,7 +31,7 @@ - + diff --git a/src/Website/Website.csproj b/src/Website/Website.csproj index d0872dadc..0a14a684e 100644 --- a/src/Website/Website.csproj +++ b/src/Website/Website.csproj @@ -293,6 +293,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -345,6 +348,7 @@ + diff --git a/src/Website/packages.config b/src/Website/packages.config index 4215a3659..92b6ef170 100644 --- a/src/Website/packages.config +++ b/src/Website/packages.config @@ -4,6 +4,7 @@ + From 324bb485434fa6810bcac9c47bcae548b3a48ebb Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 16 Aug 2015 17:24:06 -0600 Subject: [PATCH 02/19] Re-implemented RARGB --- README.md | 1 + src/Jackett/Content/logos/rarbg.png | Bin 0 -> 29669 bytes src/Jackett/Indexers/BaseIndexer.cs | 28 ++++- src/Jackett/Indexers/Rarbg.cs | 162 ++++++++++++++++++++++++++++ src/Jackett/Jackett.csproj | 4 + 5 files changed, 192 insertions(+), 3 deletions(-) create mode 100644 src/Jackett/Content/logos/rarbg.png create mode 100644 src/Jackett/Indexers/Rarbg.cs diff --git a/README.md b/README.md index b82168956..ec0adcc26 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ We were previously focused on TV but are working on extending searches to allow * [MoreThan.tv](https://morethan.tv/) * [pretome](https://pretome.info) * [PrivateHD](https://privatehd.to/) + * [RARGB](https://rarbg.to/) * [RuTor](http://rutor.org/) * [SceneAccess](https://sceneaccess.eu/login) * [SceneTime](https://www.scenetime.com/) diff --git a/src/Jackett/Content/logos/rarbg.png b/src/Jackett/Content/logos/rarbg.png new file mode 100644 index 0000000000000000000000000000000000000000..da8bebbbc75833e41f4835d2262de87c6d7b7f3e GIT binary patch literal 29669 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 KzC_mS(f MapTorznabCapsToTrackers(TorznabQuery query) { var result = new List(); foreach (var cat in query.Categories) { - foreach (var mapping in categoryMapping.Where(c => c.NewzNabCategory == cat)) + var queryCats = new List { cat }; + var newznabCat = TorznabCatType.AllCats.FirstOrDefault(c => c.ID == cat); + if (newznabCat != null) + { + queryCats.AddRange(newznabCat.SubCategories.Select(c => c.ID)); + } + foreach (var mapping in categoryMapping.Where(c => queryCats.Contains(c.NewzNabCategory))) { result.Add(mapping.TrackerCategory); } diff --git a/src/Jackett/Indexers/Rarbg.cs b/src/Jackett/Indexers/Rarbg.cs new file mode 100644 index 000000000..7b0334544 --- /dev/null +++ b/src/Jackett/Indexers/Rarbg.cs @@ -0,0 +1,162 @@ +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"); + }); + } + + public async Task> PerformQuery(TorznabQuery query) + { + 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); + + if (jsonContent.Value("error_code") == 20) // no results found + { + return releases.ToArray(); + } + + 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.Link = new Uri(item.Value("download")); + 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/Jackett.csproj b/src/Jackett/Jackett.csproj index 3bb428742..4ea72ab0a 100644 --- a/src/Jackett/Jackett.csproj +++ b/src/Jackett/Jackett.csproj @@ -190,6 +190,7 @@ + @@ -438,6 +439,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest From 95becfd00a28822fc5ebd1e840f9b671c9cdf676 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 18 Aug 2015 20:03:37 -0600 Subject: [PATCH 03/19] Fix for BeyondHD and improved category mapping --- src/Jackett/Indexers/BeyondHD.cs | 59 +++++++++++++++++++------------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/src/Jackett/Indexers/BeyondHD.cs b/src/Jackett/Indexers/BeyondHD.cs index 81f472c19..c24a86877 100644 --- a/src/Jackett/Indexers/BeyondHD.cs +++ b/src/Jackett/Indexers/BeyondHD.cs @@ -40,26 +40,42 @@ namespace Jackett.Indexers p: ps, configData: new ConfigurationDataCookie()) { - AddCategoryMapping("40,44,48,89,46,45", TorznabCatType.TV); - AddCategoryMapping("40", TorznabCatType.TVHD); - AddCategoryMapping("44", TorznabCatType.TVHD); - AddCategoryMapping("48", TorznabCatType.TVHD); - AddCategoryMapping("46", TorznabCatType.TVHD); - AddCategoryMapping("45", TorznabCatType.TVHD); - AddCategoryMapping("44", TorznabCatType.TVSD); - AddCategoryMapping("46", TorznabCatType.TVSD); - AddCategoryMapping("45", TorznabCatType.TVSD); + AddCategoryMapping(37, TorznabCatType.MoviesBluRay); // Movie / Blu-ray + AddMultiCategoryMapping(TorznabCatType.Movies3D, + 71, // Movie / 3D + 83 // FraMeSToR 3D + ); + AddMultiCategoryMapping(TorznabCatType.MoviesHD, + 77, // Movie / 1080p/i + 94, // Movie / 4K + 78, // Movie / 720p + 54, // Movie / MP4 + 17, // Movie / Remux + 50, // Internal / FraMeSToR 1080p + 75, // Internal / FraMeSToR 720p + 49, // Internal / FraMeSToR REMUX + 61, // Internal / HDX REMUX + 86 // Internal / SC4R + ); + + AddMultiCategoryMapping(TorznabCatType.TVHD, + 40, // TV Show / Blu-ray + 44, // TV Show / Encodes + 48, // TV Show / HDTV + 89, // TV Show / Packs + 46, // TV Show / Remux + 45 // TV Show / WEB-DL + ); + + AddCategoryMapping(36, TorznabCatType.AudioLossless); // Music / Lossless + AddCategoryMapping(69, TorznabCatType.AudioMP3); // Music / MP3 + AddMultiCategoryMapping(TorznabCatType.AudioVideo, + 55, // Music / 1080p/i + 56, // Music / 720p + 42 // Music / Blu-ray + ); - AddCategoryMapping("41,77,71,94,78,37,54,17", TorznabCatType.Movies); - AddCategoryMapping("77", TorznabCatType.MoviesHD); - AddCategoryMapping("71", TorznabCatType.Movies3D); - AddCategoryMapping("78", TorznabCatType.MoviesHD); - AddCategoryMapping("37", TorznabCatType.MoviesBluRay); - AddCategoryMapping("54", TorznabCatType.MoviesHD); - AddCategoryMapping("55,56,42,36,69", TorznabCatType.Audio); - AddCategoryMapping("36", TorznabCatType.AudioLossless); - AddCategoryMapping("69", TorznabCatType.AudioMP3); } public async Task ApplyConfiguration(JToken configJson) @@ -83,7 +99,7 @@ namespace Jackett.Indexers { List releases = new List(); - var searchString = query.GetQueryString(); + var searchString = query.GetQueryString(); var searchUrl = SearchUrl; var queryCollection = new NameValueCollection(); @@ -92,12 +108,7 @@ namespace Jackett.Indexers queryCollection.Add("search", searchString); } - var cats = new List(); foreach (var cat in MapTorznabCapsToTrackers(query)) - { - cats.AddRange(cat.Split(',')); - } - foreach (var cat in cats.Distinct()) { queryCollection.Add("c" + cat, "1"); } From 096fb805a8855ff846aef28c6760a50dde17d79b Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 18 Aug 2015 20:05:21 -0600 Subject: [PATCH 04/19] BeyondHD bug fix --- src/Jackett/Indexers/BeyondHD.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Jackett/Indexers/BeyondHD.cs b/src/Jackett/Indexers/BeyondHD.cs index c24a86877..39eca461f 100644 --- a/src/Jackett/Indexers/BeyondHD.cs +++ b/src/Jackett/Indexers/BeyondHD.cs @@ -88,7 +88,7 @@ namespace Jackett.Indexers Cookies = configData.Cookie.Value }); - await ConfigureIfOK(CookieHeader, response.Content.Contains("logout.php"), () => + await ConfigureIfOK(configData.Cookie.Value, response.Content.Contains("logout.php"), () => { CQ dom = response.Content; throw new ExceptionWithConfigData("Invalid cookie header", configData); From 2f680840a7de23da7cb6f024c3d9206156d20581 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 18 Aug 2015 20:19:44 -0600 Subject: [PATCH 05/19] Do not throw exceptions on parse error --- src/Jackett/Indexers/BaseIndexer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Jackett/Indexers/BaseIndexer.cs b/src/Jackett/Indexers/BaseIndexer.cs index f5cd64976..1630a3aca 100644 --- a/src/Jackett/Indexers/BaseIndexer.cs +++ b/src/Jackett/Indexers/BaseIndexer.cs @@ -127,7 +127,6 @@ namespace Jackett.Indexers var spacing = string.Join("", Enumerable.Repeat(Environment.NewLine, 5)); var fileContents = string.Format("{0}{1}{2}", ex, spacing, results); logger.Error(fileName + fileContents); - throw ex; } protected void CleanCache() From 7289d763efe35b3c2f168cbd7dacab009a476289 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 18 Aug 2015 20:21:15 -0600 Subject: [PATCH 06/19] Fix for ThePirateBay --- src/Jackett/Indexers/ThePirateBay.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Jackett/Indexers/ThePirateBay.cs b/src/Jackett/Indexers/ThePirateBay.cs index a4ad92616..871d268e0 100644 --- a/src/Jackett/Indexers/ThePirateBay.cs +++ b/src/Jackett/Indexers/ThePirateBay.cs @@ -30,6 +30,7 @@ namespace Jackett.Indexers } private string SearchUrl { get { return BaseUri + "search/{0}/0/99/208,205"; } } + private string RecentUrl { get { return BaseUri + "recent"; } } new ConfigurationDataUrl configData { @@ -79,7 +80,7 @@ namespace Jackett.Indexers { var releases = new List(); var queryStr = HttpUtility.UrlEncode(query.GetQueryString()); - var episodeSearchUrl = string.Format(SearchUrl, queryStr); + var episodeSearchUrl = string.IsNullOrWhiteSpace(queryStr) ? RecentUrl : string.Format(SearchUrl, queryStr); var response = await RequestStringWithCookiesAndRetry(episodeSearchUrl, string.Empty); try @@ -89,8 +90,10 @@ namespace Jackett.Indexers var rows = dom["#searchResult > tbody > tr"]; foreach (var row in rows) { - var release = new ReleaseInfo(); + if (row.ChildElements.Count() < 2) + continue; + var release = new ReleaseInfo(); CQ qRow = row.Cq(); CQ qLink = qRow.Find(".detName > .detLink").First(); @@ -110,7 +113,7 @@ namespace Jackett.Indexers var timeString = descParts[0].Split(' ')[1]; - if (timeString.Contains("mins ago")) + if (timeString.Contains(" ago")) { release.PublishDate = (DateTime.Now - TimeSpan.FromMinutes(ParseUtil.CoerceInt(timeString.Split(' ')[0]))); } From 25641229b8fb6f2724e3ce470b5b556f6456f0e6 Mon Sep 17 00:00:00 2001 From: KZ Date: Wed, 19 Aug 2015 22:10:47 +0100 Subject: [PATCH 07/19] PreToMe category mapping --- src/Jackett/Indexers/Pretome.cs | 204 +++++++++++++++++++++++++++++++- 1 file changed, 201 insertions(+), 3 deletions(-) diff --git a/src/Jackett/Indexers/Pretome.cs b/src/Jackett/Indexers/Pretome.cs index b24cfc60d..98aaca00a 100644 --- a/src/Jackett/Indexers/Pretome.cs +++ b/src/Jackett/Indexers/Pretome.cs @@ -12,6 +12,7 @@ using Jackett.Utils; using CsQuery; using System.Web; using Jackett.Models.IndexerConfig; +using System.Collections.Specialized; namespace Jackett.Indexers { @@ -19,7 +20,9 @@ namespace Jackett.Indexers { private string LoginUrl { get { return SiteLink + "takelogin.php"; } } private string LoginReferer { get { return SiteLink + "index.php?cat=1"; } } - private string SearchUrl { get { return SiteLink + "browse.php?tags=&st=1&tf=all&cat%5B%5D=7&search={0}"; } } + private string SearchUrl { get { return SiteLink + "browse.php"; } } + + private List resultMapping = new List(); new ConfigurationDataPinNumber configData { @@ -38,6 +41,132 @@ namespace Jackett.Indexers p: ps, configData: new ConfigurationDataPinNumber()) { + + AddCategoryMapping("cat[]=22&tags=Windows", TorznabCatType.PC0day); + AddCategoryMapping("cat[]=22&tags=MAC", TorznabCatType.PCMac); + AddCategoryMapping("cat[]=22&tags=Linux", TorznabCatType.PC); + + AddCategoryMapping("cat[]=27", TorznabCatType.BooksEbook); + + AddCategoryMapping("cat[]=4&tags=PC", TorznabCatType.PCGames); + AddCategoryMapping("cat[]=4&tags=RIP", TorznabCatType.PCGames); + AddCategoryMapping("cat[]=4&tags=ISO", TorznabCatType.PCGames); + AddCategoryMapping("cat[]=4&tags=XBOX360", TorznabCatType.ConsoleXbox360); + AddCategoryMapping("cat[]=4&tags=PS3", TorznabCatType.ConsolePS3); + AddCategoryMapping("cat[]=4&tags=Wii", TorznabCatType.ConsoleWii); + AddCategoryMapping("cat[]=4&tags=PSP", TorznabCatType.ConsolePSP); + AddCategoryMapping("cat[]=4&tags=NSD", TorznabCatType.ConsoleNDS); + AddCategoryMapping("cat[]=4&tags=XBox", TorznabCatType.ConsoleXbox); + AddCategoryMapping("cat[]=4&tags=PS2", TorznabCatType.ConsoleOther); + + AddCategoryMapping("cat[]=31&tags=Ebook", TorznabCatType.BooksEbook); + AddCategoryMapping("cat[]=31&tags=RARFiX", TorznabCatType.Other); + + AddCategoryMapping("cat[]=19&tags=x264", TorznabCatType.Movies); + AddCategoryMapping("cat[]=19&tags=720p", TorznabCatType.MoviesHD); + AddCategoryMapping("cat[]=19&tags=XviD", TorznabCatType.MoviesSD); + AddCategoryMapping("cat[]=19&tags=BluRay", TorznabCatType.MoviesHD); + AddCategoryMapping("cat[]=19&tags=DVDRiP", TorznabCatType.MoviesSD); + AddCategoryMapping("cat[]=19&tags=1080p", TorznabCatType.MoviesHD); + AddCategoryMapping("cat[]=19&tags=DVD", TorznabCatType.MoviesSD); + AddCategoryMapping("cat[]=19&tags=DVDR", TorznabCatType.MoviesSD); + AddCategoryMapping("cat[]=19&tags=WMV", TorznabCatType.Movies); + AddCategoryMapping("cat[]=19&tags=CAM", TorznabCatType.Movies); + + AddCategoryMapping("cat[]=6&tags=MP3", TorznabCatType.AudioMP3); + AddCategoryMapping("cat[]=6&tags=V2", TorznabCatType.AudioMP3); + AddCategoryMapping("cat[]=6&tags=FLAC", TorznabCatType.AudioLossless); + AddCategoryMapping("cat[]=6&tags=320kbps", TorznabCatType.AudioMP3); + + AddCategoryMapping("cat[]=7&tags=x264", TorznabCatType.TVHD); + AddCategoryMapping("cat[]=7&tags=720p", TorznabCatType.TVHD); + AddCategoryMapping("cat[]=7&tags=HDTV", TorznabCatType.TVHD); + AddCategoryMapping("cat[]=7&tags=XviD", TorznabCatType.TVSD); + AddCategoryMapping("cat[]=7&BluRay", TorznabCatType.TVHD); + AddCategoryMapping("cat[]=7&tags=DVDRip", TorznabCatType.TVSD); + AddCategoryMapping("cat[]=7&tags=DVD", TorznabCatType.TVSD); + AddCategoryMapping("cat[]=7&tags=Documentary", TorznabCatType.TVDocumentary); + AddCategoryMapping("cat[]=7&tags=PDTV", TorznabCatType.TVSD); + AddCategoryMapping("cat[]=7&tags=HD-DVD", TorznabCatType.TVSD); + + + AddCategoryMapping("cat[]=51&tags=XviD", TorznabCatType.XXXXviD); + AddCategoryMapping("cat[]=51&tags=DVDRiP", TorznabCatType.XXXDVD); + + // Unfortunately they are tags not categories so return the results + // as the parent category so do not get results removed with the filtering. + + AddResultCategoryMapping("cat[]=22&tags=Windows", TorznabCatType.PC); + AddResultCategoryMapping("cat[]=22&tags=MAC", TorznabCatType.PC); + AddResultCategoryMapping("cat[]=22&tags=Linux", TorznabCatType.PC); + AddResultCategoryMapping("cat[]=22&tags=All", TorznabCatType.PC); + AddResultCategoryMapping("cat[]=22", TorznabCatType.PC); + + AddResultCategoryMapping("cat[]=27&tags=All", TorznabCatType.Books); + AddResultCategoryMapping("cat[]=27", TorznabCatType.Books); + + AddResultCategoryMapping("cat[]=4&tags=PC", TorznabCatType.PC); + AddResultCategoryMapping("cat[]=4&tags=RIP", TorznabCatType.PC); + AddResultCategoryMapping("cat[]=4&tags=ISO", TorznabCatType.PC); + AddResultCategoryMapping("cat[]=4&tags=XBOX360", TorznabCatType.Console); + AddResultCategoryMapping("cat[]=4&tags=PS3", TorznabCatType.Console); + AddResultCategoryMapping("cat[]=4&tags=Wii", TorznabCatType.Console); + AddResultCategoryMapping("cat[]=4&tags=PSP", TorznabCatType.Console); + AddResultCategoryMapping("cat[]=4&tags=NSD", TorznabCatType.Console); + AddResultCategoryMapping("cat[]=4&tags=XBox", TorznabCatType.Console); + AddResultCategoryMapping("cat[]=4&tags=PS2", TorznabCatType.Console); + AddResultCategoryMapping("cat[]=4&tags=All", TorznabCatType.Console); + AddResultCategoryMapping("cat[]=4", TorznabCatType.Console); + + AddResultCategoryMapping("cat[]=31&tags=Ebook", TorznabCatType.Books); + AddResultCategoryMapping("cat[]=31&tags=RARFiX", TorznabCatType.Other); + AddResultCategoryMapping("cat[]=31&tags=All", TorznabCatType.Other); + AddResultCategoryMapping("cat[]=31", TorznabCatType.Other); + + AddResultCategoryMapping("cat[]=19&tags=x264", TorznabCatType.Movies); + AddResultCategoryMapping("cat[]=19&tags=720p", TorznabCatType.Movies); + AddResultCategoryMapping("cat[]=19&tags=XviD", TorznabCatType.Movies); + AddResultCategoryMapping("cat[]=19&tags=BluRay", TorznabCatType.Movies); + AddResultCategoryMapping("cat[]=19&tags=DVDRiP", TorznabCatType.Movies); + AddResultCategoryMapping("cat[]=19&tags=1080p", TorznabCatType.Movies); + AddResultCategoryMapping("cat[]=19&tags=DVD", TorznabCatType.Movies); + AddResultCategoryMapping("cat[]=19&tags=DVDR", TorznabCatType.Movies); + AddResultCategoryMapping("cat[]=19&tags=WMV", TorznabCatType.Movies); + AddResultCategoryMapping("cat[]=19&tags=CAM", TorznabCatType.Movies); + AddResultCategoryMapping("cat[]=19&tags=All", TorznabCatType.Movies); + AddResultCategoryMapping("cat[]=19", TorznabCatType.Movies); + + AddResultCategoryMapping("cat[]=6&tags=MP3", TorznabCatType.Audio); + AddResultCategoryMapping("cat[]=6&tags=V2", TorznabCatType.Audio); + AddResultCategoryMapping("cat[]=6&tags=FLAC", TorznabCatType.Audio); + AddResultCategoryMapping("cat[]=6&tags=320kbps", TorznabCatType.Audio); + AddResultCategoryMapping("cat[]=6&tags=All", TorznabCatType.Audio); + AddResultCategoryMapping("cat[]=6", TorznabCatType.Audio); + + AddResultCategoryMapping("cat[]=7&tags=x264", TorznabCatType.TV); + AddResultCategoryMapping("cat[]=7&tags=720p", TorznabCatType.TV); + AddResultCategoryMapping("cat[]=7&tags=HDTV", TorznabCatType.TV); + AddResultCategoryMapping("cat[]=7&tags=XviD", TorznabCatType.TV); + AddResultCategoryMapping("cat[]=7&BluRay", TorznabCatType.TV); + AddResultCategoryMapping("cat[]=7&tags=DVDRip", TorznabCatType.TV); + AddResultCategoryMapping("cat[]=7&tags=DVD", TorznabCatType.TV); + AddResultCategoryMapping("cat[]=7&tags=Documentary", TorznabCatType.TV); + AddResultCategoryMapping("cat[]=7&tags=PDTV", TorznabCatType.TV); + AddResultCategoryMapping("cat[]=7&tags=HD-DVD", TorznabCatType.TV); + AddResultCategoryMapping("cat[]=7&tags=All", TorznabCatType.TV); + AddResultCategoryMapping("cat[]=7", TorznabCatType.TV); + + AddResultCategoryMapping("cat[]=51&tags=XviD", TorznabCatType.XXX); + AddResultCategoryMapping("cat[]=51&tags=DVDRiP", TorznabCatType.XXX); + AddResultCategoryMapping("cat[]=51&tags=All", TorznabCatType.XXX); + AddResultCategoryMapping("cat[]=51", TorznabCatType.XXX); + } + + protected void AddResultCategoryMapping(string trackerCategory, TorznabCategory newznabCategory) + { + resultMapping.Add(new CategoryMapping(trackerCategory.ToString(), newznabCategory.ID)); + if (!TorznabCaps.Categories.Contains(newznabCategory)) + TorznabCaps.Categories.Add(newznabCategory); } public async Task ApplyConfiguration(JToken configJson) @@ -74,8 +203,60 @@ namespace Jackett.Indexers public async Task> PerformQuery(TorznabQuery query) { var releases = new List(); - var episodeSearchUrl = string.Format(SearchUrl, HttpUtility.UrlEncode(query.GetQueryString())); - var response = await RequestStringWithCookiesAndRetry(episodeSearchUrl); + var queryUrl = SearchUrl; + var queryCollection = new NameValueCollection(); + var cats = MapTorznabCapsToTrackers(query); + var tags = string.Empty; + var catGroups = new List(); + foreach (var cat in cats) + { + //"cat[]=7&tags=x264" + var cSplit = cat.Split('&'); + if (cSplit.Length > 0) + { + var gsplit = cSplit[0].Split('='); + if (gsplit.Length > 1) + { + catGroups.Add(gsplit[1]); + } + } + + if (cSplit.Length > 1) + { + var gsplit = cSplit[1].Split('='); + if (gsplit.Length > 1) + { + if (tags != string.Empty) + tags += ","; + tags += gsplit[1]; + } + } + } + + if (catGroups.Distinct().Count() == 1) + { + queryCollection.Add("cat[]", catGroups.First()); + } + + if (!string.IsNullOrWhiteSpace(query.GetQueryString())) + { + queryCollection.Add("st", "1"); + queryCollection.Add("search", query.GetQueryString()); + } + + // Do not include too many tags as it'll mess with their servers. + if (tags.Split(',').Length < 7) + { + queryCollection.Add("tags", tags); + queryCollection.Add("tf", "any"); + } + + if (queryCollection.Count > 0) + { + queryUrl += "?" + queryCollection.GetQueryString(); + } + + var response = await RequestStringWithCookiesAndRetry(queryUrl); try { @@ -111,6 +292,9 @@ namespace Jackett.Indexers release.Seeders = ParseUtil.CoerceInt(row.ChildElements.ElementAt(9).InnerText); release.Peers = ParseUtil.CoerceInt(row.ChildElements.ElementAt(10).InnerText) + release.Seeders; + var cat = row.ChildElements.ElementAt(0).ChildElements.ElementAt(0).GetAttribute("href").Replace("browse.php?",string.Empty); + release.Category = MapTrackerResultCatToNewznab(cat); + releases.Add(release); } } @@ -120,5 +304,19 @@ namespace Jackett.Indexers } return releases; } + + protected int MapTrackerResultCatToNewznab(string input) + { + if (null != input) + { + input = input.ToLowerInvariant(); + var mapping = resultMapping.Where(m => m.TrackerCategory == input).FirstOrDefault(); + if (mapping != null) + { + return mapping.NewzNabCategory; + } + } + return 0; + } } } From 523929e9075966dc2bfa13d6d90864f4cd8082e0 Mon Sep 17 00:00:00 2001 From: KZ Date: Wed, 19 Aug 2015 22:51:16 +0100 Subject: [PATCH 08/19] HDTorrents category mapping --- src/Jackett/Indexers/HDTorrents.cs | 60 +++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/src/Jackett/Indexers/HDTorrents.cs b/src/Jackett/Indexers/HDTorrents.cs index c4fa18507..7963d4658 100644 --- a/src/Jackett/Indexers/HDTorrents.cs +++ b/src/Jackett/Indexers/HDTorrents.cs @@ -15,12 +15,13 @@ using System.Text; using System.Threading.Tasks; using System.Web; using Jackett.Models.IndexerConfig; +using System.Collections.Specialized; namespace Jackett.Indexers { public class HDTorrents : BaseIndexer, IIndexer { - private string SearchUrl { get { return SiteLink + "torrents.php?search={0}&active=1&options=0&category%5B%5D=59&category%5B%5D=60&category%5B%5D=30&category%5B%5D=38&page=0"; } } + private string SearchUrl { get { return SiteLink + "torrents.php?"; } } private string LoginUrl { get { return SiteLink + "login.php"; } } private const int MAXPAGES = 3; @@ -34,13 +35,34 @@ namespace Jackett.Indexers : base(name: "HD-Torrents", description: "HD-Torrents is a private torrent website with HD torrents and strict rules on their content.", link: "http://hdts.ru/",// Of the accessible domains the .ru seems the most reliable. https://hdts.ru | https://hd-torrents.org | https://hd-torrents.net | https://hd-torrents.me - caps: TorznabUtil.CreateDefaultTorznabTVCaps(), manager: i, client: w, logger: l, p: ps, configData: new ConfigurationDataBasicLogin()) { + TorznabCaps.Categories.Clear(); + + AddCategoryMapping("1", TorznabCatType.MoviesHD);// Movie/Blu-Ray + AddCategoryMapping("2", TorznabCatType.MoviesHD);// Movie/Remux + AddCategoryMapping("5", TorznabCatType.MoviesHD);//Movie/1080p/i + AddCategoryMapping("3", TorznabCatType.MoviesHD);//Movie/720p + AddCategoryMapping("63", TorznabCatType.Audio);//Movie/Audio Track + + AddCategoryMapping("59", TorznabCatType.TVHD);//TV Show/Blu-ray + AddCategoryMapping("60", TorznabCatType.TVHD);//TV Show/Remux + AddCategoryMapping("30", TorznabCatType.TVHD);//TV Show/1080p/i + AddCategoryMapping("38", TorznabCatType.TVHD);//TV Show/720p + + AddCategoryMapping("44", TorznabCatType.Audio);//Music/Album + AddCategoryMapping("61", TorznabCatType.AudioVideo);//Music/Blu-Ray + AddCategoryMapping("62", TorznabCatType.AudioVideo);//Music/Remux + AddCategoryMapping("57", TorznabCatType.AudioVideo);//Music/1080p/i + AddCategoryMapping("45", TorznabCatType.AudioVideo);//Music/720p + + AddCategoryMapping("58", TorznabCatType.XXX);//XXX/Blu-ray + AddCategoryMapping("48", TorznabCatType.XXX);//XXX/1080p/i + AddCategoryMapping("47", TorznabCatType.XXX);//XXX/720p } public async Task ApplyConfiguration(JToken configJson) @@ -66,7 +88,30 @@ namespace Jackett.Indexers { var releases = new List(); var searchurls = new List(); - var searchUrl = string.Format(SearchUrl, HttpUtility.UrlEncode(query.GetQueryString())); + var searchUrl = SearchUrl;// string.Format(SearchUrl, HttpUtility.UrlEncode())); + var queryCollection = new NameValueCollection(); + var searchString = query.GetQueryString(); + + + foreach (var cat in MapTorznabCapsToTrackers(query)) + { + searchUrl += "category%5B%5D=" + cat + "&"; + } + + + if (!string.IsNullOrWhiteSpace(searchString)) + { + queryCollection.Add("search", searchString); + } + + + + queryCollection.Add("active", "1"); + queryCollection.Add("options", "0"); + + searchUrl += queryCollection.GetQueryString(); + + var results = await RequestStringWithCookiesAndRetry(searchUrl); try { @@ -117,14 +162,17 @@ namespace Jackett.Indexers string fullSize = qRow.Find("td.mainblockcontent").Get(6).InnerText; release.Size = ReleaseInfo.GetBytes(fullSize); - release.Guid = new Uri(SiteLink + "/" + qRow.Find("td.mainblockcontent b a").Attr("href")); - release.Link = new Uri(SiteLink + "/" + qRow.Find("td.mainblockcontent").Get(3).FirstChild.GetAttribute("href")); - release.Comments = new Uri(SiteLink + "/" + qRow.Find("td.mainblockcontent b a").Attr("href") + "#comments"); + release.Guid = new Uri(SiteLink + qRow.Find("td.mainblockcontent b a").Attr("href")); + release.Link = new Uri(SiteLink + qRow.Find("td.mainblockcontent").Get(3).FirstChild.GetAttribute("href")); + release.Comments = new Uri(SiteLink + qRow.Find("td.mainblockcontent b a").Attr("href") + "#comments"); string[] dateSplit = qRow.Find("td.mainblockcontent").Get(5).InnerHTML.Split(','); string dateString = dateSplit[1].Substring(0, dateSplit[1].IndexOf('>')); release.PublishDate = DateTime.Parse(dateString, CultureInfo.InvariantCulture); + string category = qRow.Find("td:eq(0) a").Attr("href").Replace("torrents.php?category=", ""); + release.Category = MapTrackerCatToNewznab(category); + releases.Add(release); } } From a4710b43ba53a6c872101aade7891c62e6d45ca5 Mon Sep 17 00:00:00 2001 From: KZ Date: Wed, 19 Aug 2015 22:58:21 +0100 Subject: [PATCH 09/19] PrivateHD category mapping fix --- src/Jackett/Indexers/PrivateHD.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Jackett/Indexers/PrivateHD.cs b/src/Jackett/Indexers/PrivateHD.cs index 99009c507..2bcd15e2d 100644 --- a/src/Jackett/Indexers/PrivateHD.cs +++ b/src/Jackett/Indexers/PrivateHD.cs @@ -118,8 +118,9 @@ namespace Jackett.Indexers var cat = row.Cq().Find("td:eq(0) i").First().Attr("class") .Replace("gi gi-film", "1") .Replace("gi gi-tv", "2") - .Replace("gi gi-music", "3"); - release.Category = MapTrackerCatToNewznab(cat); + .Replace("gi gi-music", "3") + .Replace("text-pink",string.Empty); + release.Category = MapTrackerCatToNewznab(cat.Trim()); releases.Add(release); } } From 30ba1793c0cda3128571bbde43ad0ac9bfdf7c2e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 19 Aug 2015 18:31:44 -0600 Subject: [PATCH 10/19] Fix RARBG magnet link --- src/Jackett/Indexers/Rarbg.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Jackett/Indexers/Rarbg.cs b/src/Jackett/Indexers/Rarbg.cs index 7b0334544..b2a8683f9 100644 --- a/src/Jackett/Indexers/Rarbg.cs +++ b/src/Jackett/Indexers/Rarbg.cs @@ -124,18 +124,27 @@ namespace Jackett.Indexers { var jsonContent = JObject.Parse(response.Content); - if (jsonContent.Value("error_code") == 20) // no results found + int errorCode = jsonContent.Value("error_code"); + if (errorCode == 20) // no results found { return releases.ToArray(); } + if (errorCode > 0) // too many requests per second + { + 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.Link = new Uri(item.Value("download")); + + 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; From 748d85f32fd51a6da0efea2ee269370594a10d5d Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 22 Aug 2015 14:57:13 -0600 Subject: [PATCH 11/19] Implemented indexer configuration result status to prevent double query test on some indexers --- src/Jackett/Controllers/AdminController.cs | 53 ++++++++++++------- src/Jackett/Indexers/AlphaRatio.cs | 3 +- src/Jackett/Indexers/AnimeBytes.cs | 6 ++- src/Jackett/Indexers/BB.cs | 5 +- src/Jackett/Indexers/BakaBT.cs | 4 +- src/Jackett/Indexers/BeyondHD.cs | 3 +- src/Jackett/Indexers/BitHdtv.cs | 3 +- src/Jackett/Indexers/BitMeTV.cs | 3 +- src/Jackett/Indexers/Demonoid.cs | 3 +- src/Jackett/Indexers/FileList.cs | 5 +- src/Jackett/Indexers/FrenchTorrentDb.cs | 3 +- src/Jackett/Indexers/Freshon.cs | 3 +- src/Jackett/Indexers/HDSpace.cs | 3 +- src/Jackett/Indexers/HDTorrents.cs | 5 +- src/Jackett/Indexers/IIndexer.cs | 2 +- src/Jackett/Indexers/IPTorrents.cs | 3 +- src/Jackett/Indexers/ImmortalSeed.cs | 4 +- src/Jackett/Indexers/MoreThanTV.cs | 4 +- src/Jackett/Indexers/Pretome.cs | 6 ++- src/Jackett/Indexers/PrivateHD.cs | 6 ++- src/Jackett/Indexers/RUTor.cs | 4 +- src/Jackett/Indexers/Rarbg.cs | 4 +- src/Jackett/Indexers/SceneAccess.cs | 4 +- src/Jackett/Indexers/SceneTime.cs | 4 +- src/Jackett/Indexers/ShowRSS.cs | 4 +- src/Jackett/Indexers/SpeedCD.cs | 4 +- src/Jackett/Indexers/Strike.cs | 4 +- src/Jackett/Indexers/T411.cs | 4 +- src/Jackett/Indexers/TVChaosUK.cs | 3 +- src/Jackett/Indexers/ThePirateBay.cs | 4 +- src/Jackett/Indexers/TorrentBytes.cs | 3 +- src/Jackett/Indexers/TorrentDay.cs | 3 +- src/Jackett/Indexers/TorrentLeech.cs | 7 +-- src/Jackett/Indexers/TorrentShack.cs | 3 +- src/Jackett/Indexers/Torrentz.cs | 3 +- src/Jackett/Indexers/nCore.cs | 4 +- src/Jackett/Jackett.csproj | 1 + .../Models/IndexerConfigurationStatus.cs | 15 ++++++ 38 files changed, 142 insertions(+), 63 deletions(-) create mode 100644 src/Jackett/Models/IndexerConfigurationStatus.cs diff --git a/src/Jackett/Controllers/AdminController.cs b/src/Jackett/Controllers/AdminController.cs index 47d49fa86..3a091f2ab 100644 --- a/src/Jackett/Controllers/AdminController.cs +++ b/src/Jackett/Controllers/AdminController.cs @@ -67,7 +67,7 @@ namespace Jackett.Controllers result.Content = new StreamContent(stream); result.Content.Headers.ContentType = new MediaTypeHeaderValue(MimeMapping.GetMimeMapping(mappedPath)); - + return result; } @@ -86,7 +86,7 @@ namespace Jackett.Controllers [AllowAnonymous] public async Task Dashboard() { - if(Request.RequestUri.Query!=null && Request.RequestUri.Query.Contains("logout")) + if (Request.RequestUri.Query != null && Request.RequestUri.Query.Contains("logout")) { var file = GetFile("login.html"); securityService.Logout(file); @@ -98,16 +98,18 @@ namespace Jackett.Controllers { return GetFile("index.html"); - } else + } + else { var formData = await Request.Content.ReadAsFormDataAsync(); - - if (formData!=null && securityService.HashPassword(formData["password"]) == serverService.Config.AdminPassword) + + if (formData != null && securityService.HashPassword(formData["password"]) == serverService.Config.AdminPassword) { var file = GetFile("index.html"); securityService.Login(file); return file; - } else + } + else { return GetFile("login.html"); } @@ -180,8 +182,15 @@ namespace Jackett.Controllers string indexerString = (string)postData["indexer"]; indexer = indexerService.GetIndexer((string)postData["indexer"]); jsonReply["name"] = indexer.DisplayName; - await indexer.ApplyConfiguration(postData["config"]); - await indexerService.TestIndexer((string)postData["indexer"]); + var configurationResult = await indexer.ApplyConfiguration(postData["config"]); + if (configurationResult == IndexerConfigurationStatus.RequiresTesting) + { + await indexerService.TestIndexer((string)postData["indexer"]); + } + else if (configurationResult == IndexerConfigurationStatus.Failed) + { + throw new Exception("Configuration Failed"); + } jsonReply["result"] = "success"; } catch (Exception ex) @@ -194,10 +203,11 @@ namespace Jackett.Controllers if (ex is ExceptionWithConfigData) { jsonReply["config"] = ((ExceptionWithConfigData)ex).ConfigData.ToJson(null); - } else + } + else { logger.Error(ex, "Exception in Configure"); - } + } } return Json(jsonReply); } @@ -293,12 +303,13 @@ namespace Jackett.Controllers cfg["external"] = serverService.Config.AllowExternal; cfg["api_key"] = serverService.Config.APIKey; cfg["blackholedir"] = serverService.Config.BlackholeDir; - cfg["password"] = string.IsNullOrEmpty(serverService.Config.AdminPassword )? string.Empty:serverService.Config.AdminPassword.Substring(0,10); + cfg["password"] = string.IsNullOrEmpty(serverService.Config.AdminPassword) ? string.Empty : serverService.Config.AdminPassword.Substring(0, 10); jsonReply["config"] = cfg; jsonReply["app_version"] = config.GetVersion(); jsonReply["result"] = "success"; - }catch (Exception ex) + } + catch (Exception ex) { logger.Error(ex, "Exception in get_jackett_config"); jsonReply["result"] = "error"; @@ -360,7 +371,8 @@ namespace Jackett.Controllers } } - (new Thread(() => { + (new Thread(() => + { Thread.Sleep(500); serverService.Stop(); Engine.BuildContainer(); @@ -370,7 +382,7 @@ namespace Jackett.Controllers } - if(saveDir != Engine.Server.Config.BlackholeDir) + if (saveDir != Engine.Server.Config.BlackholeDir) { if (!string.IsNullOrEmpty(saveDir)) { @@ -435,12 +447,12 @@ namespace Jackett.Controllers var query = new TorznabQuery() { SearchTerm = value.Query, - Categories = value.Category ==0?new int[0]: new int[1] { value.Category } + Categories = value.Category == 0 ? new int[0] : new int[1] { value.Category } }; query.ExpandCatsToSubCats(); - var trackers = indexerService.GetAllIndexers().Where(t=>t.IsConfigured).ToList(); + var trackers = indexerService.GetAllIndexers().Where(t => t.IsConfigured).ToList(); if (!string.IsNullOrWhiteSpace(value.Tracker)) { trackers = trackers.Where(t => t.ID == value.Tracker).ToList(); @@ -453,7 +465,8 @@ namespace Jackett.Controllers Parallel.ForEach(trackers.ToList(), indexer => { - try { + try + { var searchResults = indexer.PerformQuery(query).Result; cacheService.CacheRssResults(indexer, searchResults); searchResults = indexer.FilterResults(query, searchResults); @@ -470,7 +483,7 @@ namespace Jackett.Controllers } } } - catch(Exception e) + catch (Exception e) { logger.Error(e, "An error occured during manual search on " + indexer.DisplayName + ": " + e.Message); } @@ -483,10 +496,10 @@ namespace Jackett.Controllers results = results.OrderByDescending(d => d.PublishDate).ToList(); } - var manualResult = new ManualSearchResult() + var manualResult = new ManualSearchResult() { Results = results, - Indexers = trackers.Select(t=>t.DisplayName).ToList() + Indexers = trackers.Select(t => t.DisplayName).ToList() }; diff --git a/src/Jackett/Indexers/AlphaRatio.cs b/src/Jackett/Indexers/AlphaRatio.cs index f466a50a2..2b1e825f4 100644 --- a/src/Jackett/Indexers/AlphaRatio.cs +++ b/src/Jackett/Indexers/AlphaRatio.cs @@ -56,7 +56,7 @@ namespace Jackett.Indexers AddCategoryMapping(23, TorznabCatType.Audio); } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { var incomingConfig = new ConfigurationDataBasicLogin(); incomingConfig.LoadValuesFromJson(configJson); @@ -76,6 +76,7 @@ namespace Jackett.Indexers var errorMessage = dom["#loginform"].Text().Trim().Replace("\n\t", " "); throw new ExceptionWithConfigData(errorMessage, (ConfigurationData)incomingConfig); }); + return IndexerConfigurationStatus.RequiresTesting; } void FillReleaseInfoFromJson(ReleaseInfo release, JObject r) diff --git a/src/Jackett/Indexers/AnimeBytes.cs b/src/Jackett/Indexers/AnimeBytes.cs index 71bc47b5a..6875324da 100644 --- a/src/Jackett/Indexers/AnimeBytes.cs +++ b/src/Jackett/Indexers/AnimeBytes.cs @@ -49,10 +49,10 @@ namespace Jackett.Indexers p: ps, configData: new ConfigurationDataAnimeBytes()) { - + } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); @@ -99,6 +99,8 @@ namespace Jackett.Indexers // Their login page appears to be broken and just gives a 500 error. throw new ExceptionWithConfigData("Failed to login, 6 failed attempts will get you banned for 6 hours.", configData); }); + + return IndexerConfigurationStatus.RequiresTesting; } // Override to load legacy config format diff --git a/src/Jackett/Indexers/BB.cs b/src/Jackett/Indexers/BB.cs index 8a657bfe9..e1d0cbbb9 100644 --- a/src/Jackett/Indexers/BB.cs +++ b/src/Jackett/Indexers/BB.cs @@ -57,7 +57,7 @@ namespace Jackett.Indexers AddCategoryMapping(11, TorznabCatType.PCGames); } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); var pairs = new Dictionary { @@ -80,8 +80,9 @@ namespace Jackett.Indexers } var message = string.Join(" ", messages); throw new ExceptionWithConfigData(message, configData); - }); + + return IndexerConfigurationStatus.RequiresTesting; } public async Task> PerformQuery(TorznabQuery query) diff --git a/src/Jackett/Indexers/BakaBT.cs b/src/Jackett/Indexers/BakaBT.cs index 4112dd18a..5c89fd31c 100644 --- a/src/Jackett/Indexers/BakaBT.cs +++ b/src/Jackett/Indexers/BakaBT.cs @@ -41,7 +41,7 @@ namespace Jackett.Indexers { } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); @@ -66,6 +66,8 @@ namespace Jackett.Indexers var errorMessage = messageEl.Text().Trim(); throw new ExceptionWithConfigData(errorMessage, configData); }); + + return IndexerConfigurationStatus.RequiresTesting; } public async Task> PerformQuery(TorznabQuery query) diff --git a/src/Jackett/Indexers/BeyondHD.cs b/src/Jackett/Indexers/BeyondHD.cs index 39eca461f..e89ad5930 100644 --- a/src/Jackett/Indexers/BeyondHD.cs +++ b/src/Jackett/Indexers/BeyondHD.cs @@ -78,7 +78,7 @@ namespace Jackett.Indexers } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); @@ -93,6 +93,7 @@ namespace Jackett.Indexers CQ dom = response.Content; throw new ExceptionWithConfigData("Invalid cookie header", configData); }); + return IndexerConfigurationStatus.RequiresTesting; } public async Task> PerformQuery(TorznabQuery query) diff --git a/src/Jackett/Indexers/BitHdtv.cs b/src/Jackett/Indexers/BitHdtv.cs index b01f3f37a..5f50abcea 100644 --- a/src/Jackett/Indexers/BitHdtv.cs +++ b/src/Jackett/Indexers/BitHdtv.cs @@ -43,7 +43,7 @@ namespace Jackett.Indexers { } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); @@ -62,6 +62,7 @@ namespace Jackett.Indexers var errorMessage = messageEl.Text().Trim(); throw new ExceptionWithConfigData(errorMessage, configData); }); + return IndexerConfigurationStatus.RequiresTesting; } public async Task> PerformQuery(TorznabQuery query) diff --git a/src/Jackett/Indexers/BitMeTV.cs b/src/Jackett/Indexers/BitMeTV.cs index 8be342237..bc117d070 100644 --- a/src/Jackett/Indexers/BitMeTV.cs +++ b/src/Jackett/Indexers/BitMeTV.cs @@ -58,7 +58,7 @@ namespace Jackett.Indexers return configData; } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); @@ -80,6 +80,7 @@ namespace Jackett.Indexers configData.CaptchaCookie.Value = captchaImage.Cookies; throw new ExceptionWithConfigData(errorMessage, configData); }); + return IndexerConfigurationStatus.RequiresTesting; } public async Task> PerformQuery(TorznabQuery query) diff --git a/src/Jackett/Indexers/Demonoid.cs b/src/Jackett/Indexers/Demonoid.cs index c99fcbcbe..53400d26f 100644 --- a/src/Jackett/Indexers/Demonoid.cs +++ b/src/Jackett/Indexers/Demonoid.cs @@ -40,7 +40,7 @@ namespace Jackett.Indexers { } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); var pairs = new Dictionary { @@ -58,6 +58,7 @@ namespace Jackett.Indexers var errorMessage = dom[".red"].ElementAt(1).Cq().Text().Trim(); throw new ExceptionWithConfigData(errorMessage, configData); }); + return IndexerConfigurationStatus.RequiresTesting; } public async Task> PerformQuery(TorznabQuery query) diff --git a/src/Jackett/Indexers/FileList.cs b/src/Jackett/Indexers/FileList.cs index 0b03887f5..9ca4e219f 100644 --- a/src/Jackett/Indexers/FileList.cs +++ b/src/Jackett/Indexers/FileList.cs @@ -66,7 +66,7 @@ namespace Jackett.Indexers AddCategoryMapping(7, TorznabCatType.XXX); } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); var pairs = new Dictionary { @@ -81,6 +81,7 @@ namespace Jackett.Indexers var errorMessage = dom[".main"].Text().Trim(); throw new ExceptionWithConfigData(errorMessage, configData); }); + return IndexerConfigurationStatus.RequiresTesting; } public async Task> PerformQuery(TorznabQuery query) @@ -99,7 +100,7 @@ namespace Jackett.Indexers if (!string.IsNullOrWhiteSpace(searchString) || cat != "0") searchUrl += string.Format("?search={0}&cat={1}&searchin=0&sort=0", HttpUtility.UrlEncode(searchString), cat); - + var response = await RequestStringWithCookiesAndRetry(searchUrl, null, BrowseUrl); var results = response.Content; diff --git a/src/Jackett/Indexers/FrenchTorrentDb.cs b/src/Jackett/Indexers/FrenchTorrentDb.cs index 00d1e835a..da7538d93 100644 --- a/src/Jackett/Indexers/FrenchTorrentDb.cs +++ b/src/Jackett/Indexers/FrenchTorrentDb.cs @@ -37,7 +37,7 @@ namespace Jackett.Indexers { } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); var response = await webclient.GetString(new Utils.Clients.WebRequest() @@ -51,6 +51,7 @@ namespace Jackett.Indexers { throw new ExceptionWithConfigData("Failed to login", configData); }); + return IndexerConfigurationStatus.RequiresTesting; } public async Task> PerformQuery(TorznabQuery query) diff --git a/src/Jackett/Indexers/Freshon.cs b/src/Jackett/Indexers/Freshon.cs index 0b298543b..62a4ee61f 100644 --- a/src/Jackett/Indexers/Freshon.cs +++ b/src/Jackett/Indexers/Freshon.cs @@ -46,7 +46,7 @@ namespace Jackett.Indexers { } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); var pairs = new Dictionary { @@ -65,6 +65,7 @@ namespace Jackett.Indexers var errorMessage = messageEl.Text().Trim(); throw new ExceptionWithConfigData(errorMessage, configData); }); + return IndexerConfigurationStatus.RequiresTesting; } public async Task> PerformQuery(TorznabQuery query) diff --git a/src/Jackett/Indexers/HDSpace.cs b/src/Jackett/Indexers/HDSpace.cs index 0b455b78f..cfb4f57ee 100644 --- a/src/Jackett/Indexers/HDSpace.cs +++ b/src/Jackett/Indexers/HDSpace.cs @@ -41,7 +41,7 @@ namespace Jackett.Indexers { } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); @@ -63,6 +63,7 @@ namespace Jackett.Indexers var errorMessage = string.Format(errorStr, attempts); throw new ExceptionWithConfigData(errorMessage, configData); }); + return IndexerConfigurationStatus.RequiresTesting; } public async Task> PerformQuery(TorznabQuery query) diff --git a/src/Jackett/Indexers/HDTorrents.cs b/src/Jackett/Indexers/HDTorrents.cs index 7963d4658..294eafda4 100644 --- a/src/Jackett/Indexers/HDTorrents.cs +++ b/src/Jackett/Indexers/HDTorrents.cs @@ -65,7 +65,7 @@ namespace Jackett.Indexers AddCategoryMapping("47", TorznabCatType.XXX);//XXX/720p } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); var loginPage = await RequestStringWithCookies(LoginUrl, string.Empty); @@ -82,6 +82,7 @@ namespace Jackett.Indexers var errorMessage = "Couldn't login"; throw new ExceptionWithConfigData(errorMessage, configData); }); + return IndexerConfigurationStatus.RequiresTesting; } public async Task> PerformQuery(TorznabQuery query) @@ -104,7 +105,7 @@ namespace Jackett.Indexers queryCollection.Add("search", searchString); } - + queryCollection.Add("active", "1"); queryCollection.Add("options", "0"); diff --git a/src/Jackett/Indexers/IIndexer.cs b/src/Jackett/Indexers/IIndexer.cs index e3dd527dd..c73588910 100644 --- a/src/Jackett/Indexers/IIndexer.cs +++ b/src/Jackett/Indexers/IIndexer.cs @@ -27,7 +27,7 @@ namespace Jackett.Indexers Task GetConfigurationForSetup(); // Called when web API wants to apply setup configuration via web API, usually this is where login and storing cookie happens - Task ApplyConfiguration(JToken configJson); + Task ApplyConfiguration(JToken configJson); // Called on startup when initializing indexers from saved configuration void LoadFromSavedConfiguration(JToken jsonConfig); diff --git a/src/Jackett/Indexers/IPTorrents.cs b/src/Jackett/Indexers/IPTorrents.cs index ebbef2c7d..705576168 100644 --- a/src/Jackett/Indexers/IPTorrents.cs +++ b/src/Jackett/Indexers/IPTorrents.cs @@ -83,7 +83,7 @@ namespace Jackett.Indexers AddCategoryMapping(94, TorznabCatType.BooksComics); } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); var pairs = new Dictionary { @@ -109,6 +109,7 @@ namespace Jackett.Indexers var errorMessage = messageEl.Text().Trim(); throw new ExceptionWithConfigData(errorMessage, configData); }); + return IndexerConfigurationStatus.RequiresTesting; } public async Task> PerformQuery(TorznabQuery query) diff --git a/src/Jackett/Indexers/ImmortalSeed.cs b/src/Jackett/Indexers/ImmortalSeed.cs index e246b03b8..0bb675bf4 100644 --- a/src/Jackett/Indexers/ImmortalSeed.cs +++ b/src/Jackett/Indexers/ImmortalSeed.cs @@ -67,7 +67,7 @@ namespace Jackett.Indexers } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); var pairs = new Dictionary { @@ -93,6 +93,8 @@ namespace Jackett.Indexers var errorMessage = "Incorrect username or password! " + tries + " tries remaining."; throw new ExceptionWithConfigData(errorMessage, configData); }); + + return IndexerConfigurationStatus.RequiresTesting; } public async Task> PerformQuery(TorznabQuery query) diff --git a/src/Jackett/Indexers/MoreThanTV.cs b/src/Jackett/Indexers/MoreThanTV.cs index 8a6111516..e8a809273 100644 --- a/src/Jackett/Indexers/MoreThanTV.cs +++ b/src/Jackett/Indexers/MoreThanTV.cs @@ -45,7 +45,7 @@ namespace Jackett.Indexers { } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); var pairs = new Dictionary { @@ -63,6 +63,8 @@ namespace Jackett.Indexers var errorMessage = dom["#loginform"].Text().Trim().Replace("\n\t", " "); throw new ExceptionWithConfigData(errorMessage, configData); }); + + return IndexerConfigurationStatus.RequiresTesting; } private void FillReleaseInfoFromJson(ReleaseInfo release, JObject r) diff --git a/src/Jackett/Indexers/Pretome.cs b/src/Jackett/Indexers/Pretome.cs index 98aaca00a..e4cc4127f 100644 --- a/src/Jackett/Indexers/Pretome.cs +++ b/src/Jackett/Indexers/Pretome.cs @@ -169,7 +169,7 @@ namespace Jackett.Indexers TorznabCaps.Categories.Add(newznabCategory); } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); @@ -198,6 +198,8 @@ namespace Jackett.Indexers CookieHeader = string.Empty; throw new ExceptionWithConfigData("Failed", configData); }); + + return IndexerConfigurationStatus.RequiresTesting; } public async Task> PerformQuery(TorznabQuery query) @@ -292,7 +294,7 @@ namespace Jackett.Indexers release.Seeders = ParseUtil.CoerceInt(row.ChildElements.ElementAt(9).InnerText); release.Peers = ParseUtil.CoerceInt(row.ChildElements.ElementAt(10).InnerText) + release.Seeders; - var cat = row.ChildElements.ElementAt(0).ChildElements.ElementAt(0).GetAttribute("href").Replace("browse.php?",string.Empty); + var cat = row.ChildElements.ElementAt(0).ChildElements.ElementAt(0).GetAttribute("href").Replace("browse.php?", string.Empty); release.Category = MapTrackerResultCatToNewznab(cat); releases.Add(release); diff --git a/src/Jackett/Indexers/PrivateHD.cs b/src/Jackett/Indexers/PrivateHD.cs index 2bcd15e2d..48393fc65 100644 --- a/src/Jackett/Indexers/PrivateHD.cs +++ b/src/Jackett/Indexers/PrivateHD.cs @@ -48,7 +48,7 @@ namespace Jackett.Indexers AddCategoryMapping(3, TorznabCatType.Audio); } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); var loginPage = await RequestStringWithCookies(LoginUrl, string.Empty); @@ -68,6 +68,8 @@ namespace Jackett.Indexers var errorMessage = messageEl.Text().Trim(); throw new ExceptionWithConfigData(errorMessage, configData); }); + + return IndexerConfigurationStatus.RequiresTesting; } public async Task> PerformQuery(TorznabQuery query) @@ -119,7 +121,7 @@ namespace Jackett.Indexers .Replace("gi gi-film", "1") .Replace("gi gi-tv", "2") .Replace("gi gi-music", "3") - .Replace("text-pink",string.Empty); + .Replace("text-pink", string.Empty); release.Category = MapTrackerCatToNewznab(cat.Trim()); releases.Add(release); } diff --git a/src/Jackett/Indexers/RUTor.cs b/src/Jackett/Indexers/RUTor.cs index 128847a52..91b136437 100644 --- a/src/Jackett/Indexers/RUTor.cs +++ b/src/Jackett/Indexers/RUTor.cs @@ -49,7 +49,7 @@ namespace Jackett.Indexers TorznabCaps.Categories.Add(TorznabCatType.Books); } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); var oldConfig = configData; @@ -60,6 +60,8 @@ namespace Jackett.Indexers configData = oldConfig; throw new Exception("Could not find releases from this URL"); }); + + return IndexerConfigurationStatus.RequiresTesting; } diff --git a/src/Jackett/Indexers/Rarbg.cs b/src/Jackett/Indexers/Rarbg.cs index b2a8683f9..e1a021394 100644 --- a/src/Jackett/Indexers/Rarbg.cs +++ b/src/Jackett/Indexers/Rarbg.cs @@ -94,7 +94,7 @@ namespace Jackett.Indexers } } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); var releases = await PerformQuery(new TorznabQuery()); @@ -103,6 +103,8 @@ namespace Jackett.Indexers { throw new Exception("Could not find releases from this URL"); }); + + return IndexerConfigurationStatus.Completed; } public async Task> PerformQuery(TorznabQuery query) diff --git a/src/Jackett/Indexers/SceneAccess.cs b/src/Jackett/Indexers/SceneAccess.cs index bdad51cf3..2c595e609 100644 --- a/src/Jackett/Indexers/SceneAccess.cs +++ b/src/Jackett/Indexers/SceneAccess.cs @@ -40,7 +40,7 @@ namespace Jackett.Indexers { } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); @@ -60,6 +60,8 @@ namespace Jackett.Indexers var errorMessage = messageEl.Text().Trim(); throw new ExceptionWithConfigData(errorMessage, configData); }); + + return IndexerConfigurationStatus.RequiresTesting; } public async Task> PerformQuery(TorznabQuery query) diff --git a/src/Jackett/Indexers/SceneTime.cs b/src/Jackett/Indexers/SceneTime.cs index d03e186fc..e517bd323 100644 --- a/src/Jackett/Indexers/SceneTime.cs +++ b/src/Jackett/Indexers/SceneTime.cs @@ -43,7 +43,7 @@ namespace Jackett.Indexers { } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); var pairs = new Dictionary { @@ -58,6 +58,8 @@ namespace Jackett.Indexers var errorMessage = dom["td.text"].Text().Trim(); throw new ExceptionWithConfigData(errorMessage, configData); }); + + return IndexerConfigurationStatus.RequiresTesting; } private Dictionary GetSearchFormData(string searchString) diff --git a/src/Jackett/Indexers/ShowRSS.cs b/src/Jackett/Indexers/ShowRSS.cs index 3d29157ad..58d0b52d0 100644 --- a/src/Jackett/Indexers/ShowRSS.cs +++ b/src/Jackett/Indexers/ShowRSS.cs @@ -49,7 +49,7 @@ namespace Jackett.Indexers { } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); var releases = await PerformQuery(new TorznabQuery()); @@ -58,6 +58,8 @@ namespace Jackett.Indexers { throw new Exception("Could not find releases from this URL"); }); + + return IndexerConfigurationStatus.RequiresTesting; } // Override to load legacy config format diff --git a/src/Jackett/Indexers/SpeedCD.cs b/src/Jackett/Indexers/SpeedCD.cs index d6b7f67ca..8c7d456f1 100644 --- a/src/Jackett/Indexers/SpeedCD.cs +++ b/src/Jackett/Indexers/SpeedCD.cs @@ -46,7 +46,7 @@ namespace Jackett.Indexers { } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); var pairs = new Dictionary { @@ -61,6 +61,8 @@ namespace Jackett.Indexers var errorMessage = dom["h5"].First().Text().Trim(); throw new ExceptionWithConfigData(errorMessage, configData); }); + + return IndexerConfigurationStatus.RequiresTesting; } public async Task> PerformQuery(TorznabQuery query) diff --git a/src/Jackett/Indexers/Strike.cs b/src/Jackett/Indexers/Strike.cs index ff3817351..5b3e5bd4d 100644 --- a/src/Jackett/Indexers/Strike.cs +++ b/src/Jackett/Indexers/Strike.cs @@ -50,7 +50,7 @@ namespace Jackett.Indexers { } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); var releases = await PerformQuery(new TorznabQuery()); @@ -59,6 +59,8 @@ namespace Jackett.Indexers { throw new Exception("Could not find releases from this URL"); }); + + return IndexerConfigurationStatus.Completed; } // Override to load legacy config format diff --git a/src/Jackett/Indexers/T411.cs b/src/Jackett/Indexers/T411.cs index a0fc25573..887ad221e 100644 --- a/src/Jackett/Indexers/T411.cs +++ b/src/Jackett/Indexers/T411.cs @@ -81,7 +81,7 @@ namespace Jackett.Indexers return configData.ApiToken.Value; } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); @@ -99,6 +99,8 @@ namespace Jackett.Indexers { throw tokenFetchEx; }); + + return IndexerConfigurationStatus.RequiresTesting; } // Override to load legacy config format diff --git a/src/Jackett/Indexers/TVChaosUK.cs b/src/Jackett/Indexers/TVChaosUK.cs index 3d42a570b..0d439592a 100644 --- a/src/Jackett/Indexers/TVChaosUK.cs +++ b/src/Jackett/Indexers/TVChaosUK.cs @@ -103,7 +103,7 @@ namespace Jackett.Indexers AddCategoryMapping("HD Factual/Reality", TorznabCatType.TVHD); } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); var pairs = new Dictionary { @@ -139,6 +139,7 @@ namespace Jackett.Indexers IsConfigured = false; throw e; } + return IndexerConfigurationStatus.RequiresTesting; } public async Task> PerformQuery(TorznabQuery query) diff --git a/src/Jackett/Indexers/ThePirateBay.cs b/src/Jackett/Indexers/ThePirateBay.cs index 871d268e0..2135442cd 100644 --- a/src/Jackett/Indexers/ThePirateBay.cs +++ b/src/Jackett/Indexers/ThePirateBay.cs @@ -51,7 +51,7 @@ namespace Jackett.Indexers { } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); var releases = await PerformQuery(new TorznabQuery()); @@ -60,6 +60,8 @@ namespace Jackett.Indexers { throw new Exception("Could not find releases from this URL"); }); + + return IndexerConfigurationStatus.Completed; } // Override to load legacy config format diff --git a/src/Jackett/Indexers/TorrentBytes.cs b/src/Jackett/Indexers/TorrentBytes.cs index 4e161ac4e..7ee384627 100644 --- a/src/Jackett/Indexers/TorrentBytes.cs +++ b/src/Jackett/Indexers/TorrentBytes.cs @@ -71,7 +71,7 @@ namespace Jackett.Indexers AddCategoryMapping(24, TorznabCatType.XXXImageset); } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); var pairs = new Dictionary { @@ -91,6 +91,7 @@ namespace Jackett.Indexers var errorMessage = messageEl.Text().Trim(); throw new ExceptionWithConfigData(errorMessage, configData); }); + return IndexerConfigurationStatus.RequiresTesting; } public async Task> PerformQuery(TorznabQuery query) diff --git a/src/Jackett/Indexers/TorrentDay.cs b/src/Jackett/Indexers/TorrentDay.cs index c41511770..c67779d83 100644 --- a/src/Jackett/Indexers/TorrentDay.cs +++ b/src/Jackett/Indexers/TorrentDay.cs @@ -94,7 +94,7 @@ namespace Jackett.Indexers return result; } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); var pairs = new Dictionary { @@ -140,6 +140,7 @@ namespace Jackett.Indexers throw new ExceptionWithConfigData(errorMessage, configData); }); + return IndexerConfigurationStatus.RequiresTesting; } public async Task> PerformQuery(TorznabQuery query) diff --git a/src/Jackett/Indexers/TorrentLeech.cs b/src/Jackett/Indexers/TorrentLeech.cs index b1edcd967..10171ecb3 100644 --- a/src/Jackett/Indexers/TorrentLeech.cs +++ b/src/Jackett/Indexers/TorrentLeech.cs @@ -79,7 +79,7 @@ namespace Jackett.Indexers AddCategoryMapping(33, TorznabCatType.PC0day); } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); var pairs = new Dictionary { @@ -97,6 +97,7 @@ namespace Jackett.Indexers var errorMessage = messageEl.Text().Trim(); throw new ExceptionWithConfigData(errorMessage, configData); }); + return IndexerConfigurationStatus.RequiresTesting; } public async Task> PerformQuery(TorznabQuery query) @@ -107,7 +108,7 @@ namespace Jackett.Indexers if (!string.IsNullOrWhiteSpace(searchString)) { - searchUrl += "query/" + HttpUtility.UrlEncode(searchString) + "/"; + searchUrl += "query/" + HttpUtility.UrlEncode(searchString) + "/"; } string.Format(SearchUrl, HttpUtility.UrlEncode(searchString)); @@ -160,7 +161,7 @@ namespace Jackett.Indexers release.Seeders = ParseUtil.CoerceInt(qRow.Find(".seeders").Text()); release.Peers = release.Seeders + ParseUtil.CoerceInt(qRow.Find(".leechers").Text()); - var category = qRow.Find(".category a").Attr("href").Replace("/torrents/browse/index/categories/",string.Empty); + var category = qRow.Find(".category a").Attr("href").Replace("/torrents/browse/index/categories/", string.Empty); release.Category = MapTrackerCatToNewznab(category); releases.Add(release); diff --git a/src/Jackett/Indexers/TorrentShack.cs b/src/Jackett/Indexers/TorrentShack.cs index e79b7cae6..b34daa839 100644 --- a/src/Jackett/Indexers/TorrentShack.cs +++ b/src/Jackett/Indexers/TorrentShack.cs @@ -42,7 +42,7 @@ namespace Jackett.Indexers { } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); @@ -62,6 +62,7 @@ namespace Jackett.Indexers var errorMessage = messageEl.Text().Trim(); throw new ExceptionWithConfigData(errorMessage, configData); }); + return IndexerConfigurationStatus.RequiresTesting; } public async Task> PerformQuery(TorznabQuery query) diff --git a/src/Jackett/Indexers/Torrentz.cs b/src/Jackett/Indexers/Torrentz.cs index e68b5efef..ed7640726 100644 --- a/src/Jackett/Indexers/Torrentz.cs +++ b/src/Jackett/Indexers/Torrentz.cs @@ -50,7 +50,7 @@ namespace Jackett.Indexers { } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); var releases = await PerformQuery(new TorznabQuery()); @@ -59,6 +59,7 @@ namespace Jackett.Indexers { throw new Exception("Could not find releases from this URL"); }); + return IndexerConfigurationStatus.Completed; } // Override to load legacy config format diff --git a/src/Jackett/Indexers/nCore.cs b/src/Jackett/Indexers/nCore.cs index b86176e30..8f4979896 100644 --- a/src/Jackett/Indexers/nCore.cs +++ b/src/Jackett/Indexers/nCore.cs @@ -43,7 +43,7 @@ namespace Jackett.Indexers { } - public async Task ApplyConfiguration(JToken configJson) + public async Task ApplyConfiguration(JToken configJson) { configData.LoadValuesFromJson(configJson); @@ -69,6 +69,8 @@ namespace Jackett.Indexers var errorMessage = msgContainer != null ? msgContainer.InnerText : "Error while trying to login."; throw new ExceptionWithConfigData(errorMessage, configData); }); + + return IndexerConfigurationStatus.RequiresTesting; } List> CreateKeyValueList(params string[][] keyValues) diff --git a/src/Jackett/Jackett.csproj b/src/Jackett/Jackett.csproj index 4ea72ab0a..bcc8f5e3a 100644 --- a/src/Jackett/Jackett.csproj +++ b/src/Jackett/Jackett.csproj @@ -215,6 +215,7 @@ + diff --git a/src/Jackett/Models/IndexerConfigurationStatus.cs b/src/Jackett/Models/IndexerConfigurationStatus.cs new file mode 100644 index 000000000..2c232f7c9 --- /dev/null +++ b/src/Jackett/Models/IndexerConfigurationStatus.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Jackett.Models +{ + public enum IndexerConfigurationStatus + { + Completed, + RequiresTesting, + Failed + } +} From 28bc720ab3d16abaaa50a7e00250eed173c984a5 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 22 Aug 2015 15:07:08 -0600 Subject: [PATCH 12/19] Fix Strike indexer --- src/Jackett/Indexers/Strike.cs | 12 ++++++------ src/Jackett/Jackett.csproj | 1 + .../IndexerConfig/ConfigurationDataStrike.cs | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+), 6 deletions(-) create mode 100644 src/Jackett/Models/IndexerConfig/ConfigurationDataStrike.cs diff --git a/src/Jackett/Indexers/Strike.cs b/src/Jackett/Indexers/Strike.cs index 5b3e5bd4d..9c4a1505f 100644 --- a/src/Jackett/Indexers/Strike.cs +++ b/src/Jackett/Indexers/Strike.cs @@ -30,9 +30,9 @@ namespace Jackett.Indexers private string SearchUrl { get { return BaseUri + "api/v2/torrents/search/?category=TV&phrase={0}"; } } private string DownloadUrl { get { return BaseUri + "torrents/api/download/{0}.torrent"; } } - new ConfigurationDataUrl configData + new ConfigurationDataStrike configData { - get { return (ConfigurationDataUrl)base.configData; } + get { return (ConfigurationDataStrike)base.configData; } set { base.configData = value; } } @@ -46,7 +46,7 @@ namespace Jackett.Indexers client: wc, logger: l, p: ps, - configData: new ConfigurationDataUrl(defaultSiteLink)) + configData: new ConfigurationDataStrike(defaultSiteLink)) { } @@ -80,9 +80,9 @@ namespace Jackett.Indexers public async Task> PerformQuery(TorznabQuery query) { List releases = new List(); - - var searchTerm = string.IsNullOrEmpty(query.SanitizedSearchTerm) ? "2015" : query.SanitizedSearchTerm; - var episodeSearchUrl = string.Format(SearchUrl, HttpUtility.UrlEncode(query.GetQueryString())); + var queryString = query.GetQueryString(); + var searchTerm = string.IsNullOrEmpty(queryString) ? DateTime.Now.Year.ToString() : queryString; + var episodeSearchUrl = string.Format(SearchUrl, HttpUtility.UrlEncode(searchTerm)); var results = await RequestStringWithCookiesAndRetry(episodeSearchUrl, string.Empty); try { diff --git a/src/Jackett/Jackett.csproj b/src/Jackett/Jackett.csproj index bcc8f5e3a..8a78bd149 100644 --- a/src/Jackett/Jackett.csproj +++ b/src/Jackett/Jackett.csproj @@ -223,6 +223,7 @@ + diff --git a/src/Jackett/Models/IndexerConfig/ConfigurationDataStrike.cs b/src/Jackett/Models/IndexerConfig/ConfigurationDataStrike.cs new file mode 100644 index 000000000..124ed0c2c --- /dev/null +++ b/src/Jackett/Models/IndexerConfig/ConfigurationDataStrike.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Jackett.Models.IndexerConfig +{ + public class ConfigurationDataStrike : ConfigurationDataUrl + { + public DisplayItem StrikeWarning { get; private set; } + + public ConfigurationDataStrike(string url) : base(url) + { + StrikeWarning = new DisplayItem("This indexer does not support RSS Sync, only Search") { Name = "Warning" }; + } + } +} From 674be2843d10de1923b68054f48a1ebb28280e53 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 22 Aug 2015 15:21:29 -0600 Subject: [PATCH 13/19] RARBG API request throttling --- src/Jackett/Indexers/Rarbg.cs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Jackett/Indexers/Rarbg.cs b/src/Jackett/Indexers/Rarbg.cs index e1a021394..5e35e85bb 100644 --- a/src/Jackett/Indexers/Rarbg.cs +++ b/src/Jackett/Indexers/Rarbg.cs @@ -107,7 +107,12 @@ namespace Jackett.Indexers return IndexerConfigurationStatus.Completed; } - public async Task> PerformQuery(TorznabQuery query) + public Task> PerformQuery(TorznabQuery query) + { + return PerformQuery(query, 0); + } + + public async Task> PerformQuery(TorznabQuery query, int attempts = 0) { await CheckToken(); var releases = new List(); @@ -120,6 +125,7 @@ namespace Jackett.Indexers { episodeSearchUrl += "&category=" + cats; } + var response = await RequestStringWithCookiesAndRetry(episodeSearchUrl, string.Empty); try @@ -134,7 +140,15 @@ namespace Jackett.Indexers if (errorCode > 0) // too many requests per second { - throw new Exception(jsonContent.Value("error")); + 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")) From f39e23fbe8f44410021f26c9643cb37b30c997d9 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 22 Aug 2015 16:06:07 -0600 Subject: [PATCH 14/19] Implemented BitHDTV categories --- src/Jackett/Indexers/BaseIndexer.cs | 12 ++++++++- src/Jackett/Indexers/BitHdtv.cs | 38 ++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/src/Jackett/Indexers/BaseIndexer.cs b/src/Jackett/Indexers/BaseIndexer.cs index 1630a3aca..fdc256cc3 100644 --- a/src/Jackett/Indexers/BaseIndexer.cs +++ b/src/Jackett/Indexers/BaseIndexer.cs @@ -418,7 +418,7 @@ namespace Jackett.Indexers } } - protected List MapTorznabCapsToTrackers(TorznabQuery query) + protected List MapTorznabCapsToTrackers(TorznabQuery query, bool mapChildrenCatsToParent = false) { var result = new List(); foreach (var cat in query.Categories) @@ -429,6 +429,16 @@ namespace Jackett.Indexers { queryCats.AddRange(newznabCat.SubCategories.Select(c => c.ID)); } + + if (mapChildrenCatsToParent) + { + var parentNewznabCat = TorznabCatType.AllCats.FirstOrDefault(c => c.SubCategories.Contains(newznabCat)); + if (parentNewznabCat != null) + { + queryCats.Add(parentNewznabCat.ID); + } + } + foreach (var mapping in categoryMapping.Where(c => queryCats.Contains(c.NewzNabCategory))) { result.Add(mapping.TrackerCategory); diff --git a/src/Jackett/Indexers/BitHdtv.cs b/src/Jackett/Indexers/BitHdtv.cs index 5f50abcea..363c7b807 100644 --- a/src/Jackett/Indexers/BitHdtv.cs +++ b/src/Jackett/Indexers/BitHdtv.cs @@ -15,13 +15,14 @@ using System.Text; using System.Threading.Tasks; using System.Web; using Jackett.Models.IndexerConfig; +using System.Collections.Specialized; namespace Jackett.Indexers { public class BitHdtv : BaseIndexer, IIndexer { private string LoginUrl { get { return SiteLink + "takelogin.php"; } } - private string SearchUrl { get { return SiteLink + "torrents.php?cat=0&search="; } } + private string SearchUrl { get { return SiteLink + "torrents.php?"; } } private string DownloadUrl { get { return SiteLink + "download.php?/{0}/dl.torrent"; } } new ConfigurationDataBasicLogin configData @@ -41,6 +42,16 @@ namespace Jackett.Indexers p: ps, configData: new ConfigurationDataBasicLogin()) { + AddCategoryMapping(1, TorznabCatType.TVAnime); // Anime + AddCategoryMapping(2, TorznabCatType.MoviesBluRay); // Blu-ray + AddCategoryMapping(4, TorznabCatType.TVDocumentary); // Documentaries + AddCategoryMapping(6, TorznabCatType.AudioLossless); // HQ Audio + AddCategoryMapping(7, TorznabCatType.Movies); // Movies + AddCategoryMapping(8, TorznabCatType.AudioVideo); // Music Videos + AddCategoryMapping(5, TorznabCatType.TVSport); // Sports + AddCategoryMapping(10, TorznabCatType.TV); // TV + AddCategoryMapping(12, TorznabCatType.TV); // TV/Seasonpack + AddCategoryMapping(11, TorznabCatType.XXX); // XXX } public async Task ApplyConfiguration(JToken configJson) @@ -68,8 +79,19 @@ namespace Jackett.Indexers public async Task> PerformQuery(TorznabQuery query) { var releases = new List(); - var episodeSearchUrl = SearchUrl + HttpUtility.UrlEncode(query.GetQueryString()); - var results = await RequestStringWithCookiesAndRetry(episodeSearchUrl); + var searchString = query.GetQueryString(); + var queryCollection = new NameValueCollection(); + + if (!string.IsNullOrWhiteSpace(searchString)) + { + queryCollection.Add("search", searchString); + } + + var searchUrl = SearchUrl + queryCollection.GetQueryString(); + + var trackerCats = MapTorznabCapsToTrackers(query, mapChildrenCatsToParent: true); + + var results = await RequestStringWithCookiesAndRetry(searchUrl); try { CQ dom = results.Content; @@ -87,10 +109,18 @@ namespace Jackett.Indexers release.MinimumSeedTime = 172800; release.Title = qLink.Attr("title"); release.Description = release.Title; - release.Guid = new Uri(SiteLink + qLink.Attr("href")); + release.Guid = new Uri(SiteLink + qLink.Attr("href").TrimStart('/')); release.Comments = release.Guid; release.Link = new Uri(string.Format(DownloadUrl, qLink.Attr("href").Split('=')[1])); + var catUrl = qRow.Children().ElementAt(1).FirstElementChild.Cq().Attr("href"); + var catNum = catUrl.Split(new char[] { '=', '&' })[1]; + release.Category = MapTrackerCatToNewznab(catNum); + + // This tracker cannot search multiple cats at a time, so search all cats then filter out results from different cats + if (trackerCats.Count > 0 && !trackerCats.Contains(catNum)) + continue; + var dateString = qRow.Children().ElementAt(5).Cq().Text().Trim(); var pubDate = DateTime.ParseExact(dateString, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture); release.PublishDate = DateTime.SpecifyKind(pubDate, DateTimeKind.Local); From e566b409b949feb25a75ad9a9143d54339a212f2 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 22 Aug 2015 18:02:41 -0600 Subject: [PATCH 15/19] Implemented Strike categories --- src/Jackett/Indexers/BB.cs | 2 +- src/Jackett/Indexers/BaseIndexer.cs | 2 +- src/Jackett/Indexers/BeyondHD.cs | 2 +- src/Jackett/Indexers/BitHdtv.cs | 2 +- src/Jackett/Indexers/Pretome.cs | 2 +- src/Jackett/Indexers/Strike.cs | 41 +++++++++++++++++++++++++-- src/Jackett/Models/CategoryMapping.cs | 2 +- 7 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/Jackett/Indexers/BB.cs b/src/Jackett/Indexers/BB.cs index e1d0cbbb9..0f6b30549 100644 --- a/src/Jackett/Indexers/BB.cs +++ b/src/Jackett/Indexers/BB.cs @@ -37,7 +37,7 @@ namespace Jackett.Indexers : base(name: "bB", description: "bB", link: "http://www.reddit.com/r/baconbits/", - caps: TorznabUtil.CreateDefaultTorznabTVCaps(), + caps: new TorznabCapabilities(), manager: i, client: w, logger: l, diff --git a/src/Jackett/Indexers/BaseIndexer.cs b/src/Jackett/Indexers/BaseIndexer.cs index fdc256cc3..71cf91979 100644 --- a/src/Jackett/Indexers/BaseIndexer.cs +++ b/src/Jackett/Indexers/BaseIndexer.cs @@ -91,7 +91,7 @@ namespace Jackett.Indexers if (null != input) { input = input.ToLowerInvariant(); - var mapping = categoryMapping.Where(m => m.TrackerCategory == input).FirstOrDefault(); + var mapping = categoryMapping.Where(m => m.TrackerCategory.ToLowerInvariant() == input.ToLowerInvariant()).FirstOrDefault(); if (mapping != null) { return mapping.NewzNabCategory; diff --git a/src/Jackett/Indexers/BeyondHD.cs b/src/Jackett/Indexers/BeyondHD.cs index e89ad5930..f0f5a635b 100644 --- a/src/Jackett/Indexers/BeyondHD.cs +++ b/src/Jackett/Indexers/BeyondHD.cs @@ -33,7 +33,7 @@ namespace Jackett.Indexers : base(name: "BeyondHD", description: "Without BeyondHD, your HDTV is just a TV", link: "https://beyondhd.me/", - caps: TorznabUtil.CreateDefaultTorznabTVCaps(), + caps: new TorznabCapabilities(), manager: i, client: w, logger: l, diff --git a/src/Jackett/Indexers/BitHdtv.cs b/src/Jackett/Indexers/BitHdtv.cs index 363c7b807..bdead64ec 100644 --- a/src/Jackett/Indexers/BitHdtv.cs +++ b/src/Jackett/Indexers/BitHdtv.cs @@ -35,7 +35,7 @@ namespace Jackett.Indexers : base(name: "BIT-HDTV", description: "Home of high definition invites", link: "https://www.bit-hdtv.com/", - caps: TorznabUtil.CreateDefaultTorznabTVCaps(), + caps: new TorznabCapabilities(), manager: i, client: w, logger: l, diff --git a/src/Jackett/Indexers/Pretome.cs b/src/Jackett/Indexers/Pretome.cs index e4cc4127f..9cd8c3c15 100644 --- a/src/Jackett/Indexers/Pretome.cs +++ b/src/Jackett/Indexers/Pretome.cs @@ -312,7 +312,7 @@ namespace Jackett.Indexers if (null != input) { input = input.ToLowerInvariant(); - var mapping = resultMapping.Where(m => m.TrackerCategory == input).FirstOrDefault(); + var mapping = resultMapping.Where(m => m.TrackerCategory.ToLowerInvariant() == input.ToLowerInvariant()).FirstOrDefault(); if (mapping != null) { return mapping.NewzNabCategory; diff --git a/src/Jackett/Indexers/Strike.cs b/src/Jackett/Indexers/Strike.cs index 9c4a1505f..18986602c 100644 --- a/src/Jackett/Indexers/Strike.cs +++ b/src/Jackett/Indexers/Strike.cs @@ -14,6 +14,7 @@ using System.Text; using System.Threading.Tasks; using System.Web; using Jackett.Models.IndexerConfig; +using System.Collections.Specialized; namespace Jackett.Indexers { @@ -27,7 +28,7 @@ namespace Jackett.Indexers set { configData.Url.Value = value.ToString(); } } - private string SearchUrl { get { return BaseUri + "api/v2/torrents/search/?category=TV&phrase={0}"; } } + 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 @@ -41,13 +42,34 @@ namespace Jackett.Indexers : base(name: "Strike", description: "Torrent search engine", link: defaultSiteLink, - caps: TorznabUtil.CreateDefaultTorznabTVCaps(), + 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) @@ -83,6 +105,15 @@ namespace Jackett.Indexers 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 { @@ -94,6 +125,12 @@ namespace Jackett.Indexers 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"]; diff --git a/src/Jackett/Models/CategoryMapping.cs b/src/Jackett/Models/CategoryMapping.cs index 6ab314c48..3fd22a3e7 100644 --- a/src/Jackett/Models/CategoryMapping.cs +++ b/src/Jackett/Models/CategoryMapping.cs @@ -10,7 +10,7 @@ namespace Jackett.Models { public CategoryMapping(string trackerCat, int newzCat) { - TrackerCategory = trackerCat.ToLowerInvariant(); + TrackerCategory = trackerCat; NewzNabCategory = newzCat; } From f47a5ef13c1fa27b819263a1fadca4b9563bec8f Mon Sep 17 00:00:00 2001 From: KZ Date: Sun, 23 Aug 2015 20:31:12 +0100 Subject: [PATCH 16/19] Update reame --- README.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index ec0adcc26..95efd8faa 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ We were previously focused on TV but are working on extending searches to allow #### Supported Systems * Windows using .NET 4.5 -* Linux and OSX using Mono 4 +* Linux and OSX using Mono 4 (v3 should work but you may experience crashes). #### Supported Trackers @@ -56,21 +56,19 @@ We were previously focused on TV but are working on extending searches to allow 2. Install libcurl: * Debian/Ubunutu: apt-get install libcurl-dev * Redhat/Fedora: yum install libcurl-devel - * Or see the [Curl docs](http://curl.haxx.se/dlwiz/?type=devel). + * For other distros see the [Curl docs](http://curl.haxx.se/dlwiz/?type=devel). +3. Download and extract the latest ```.tar.bz2``` release from the [website](http://jackett.net/Download) and run Jackett using mono with the command "mono JackettConsole.exe". #### Installation on Windows +Grab the latest release from the [web site](http://jackett.net/Download). + We recommend you install Jackett as a Windows service using the supplied installer. When installed as a service the tray icon acts as a way to open/start/stop Jackett. If you opted to not install it as a service then Jackett will run its web server from the tray tool. Jackett can also be run from the command line using JackettConsole.exe if you would like to see log messages (Ensure the server isn't already running from the tray/service). -#### Installation on Linux/OSX - -Run Jackett using mono with the command "mono JackettConsole.exe". - - #### Troubleshooting @@ -88,11 +86,11 @@ You can get additional logging with the switches "-t -l". Please post logs if y ### Additional Trackers -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 then feel free to leave a request on the [issues page](https://github.com/zone117x/Jackett/issues) or contact us on IRC (see below). +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 then feel free to leave a request on the [issues page](https://github.com/zone117x/Jackett/issues) or contact us on IRC (see below). Pull requests must be made to the develop branch. ### Contact & Support Use the github issues pages or talk to us directly at: [irc.freenode.net#jackett](http://webchat.freenode.net/?channels=#jackett). ### Screenshots -![screenshot](http://i.imgur.com/t1sVva6.png "screenshot") +![screenshot](http://i.imgur.com/t1sVva6.png "screenshot") \ No newline at end of file From ccd0e65e66815a4d93fe2053c866c3d581d6e361 Mon Sep 17 00:00:00 2001 From: KZ Date: Sun, 23 Aug 2015 21:28:21 +0100 Subject: [PATCH 17/19] Implement Avistaz --- README.md | 1 + src/Jackett/Content/logos/avistaz.png | Bin 0 -> 4085 bytes .../Indexers/Abstract/AvistazTracker.cs | 136 ++++++++++++++++++ src/Jackett/Indexers/Avistaz.cs | 35 +++++ src/Jackett/Indexers/PrivateHD.cs | 117 ++------------- src/Jackett/Jackett.csproj | 7 +- .../ManualSearchResult.cs | 2 +- 7 files changed, 187 insertions(+), 111 deletions(-) create mode 100644 src/Jackett/Content/logos/avistaz.png create mode 100644 src/Jackett/Indexers/Abstract/AvistazTracker.cs create mode 100644 src/Jackett/Indexers/Avistaz.cs rename src/Jackett/{Indexers => Models}/ManualSearchResult.cs (91%) diff --git a/README.md b/README.md index 95efd8faa..7941d9a74 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ We were previously focused on TV but are working on extending searches to allow #### Supported Trackers * [AlphaRatio](https://alpharatio.cc/) * [AnimeBytes](https://animebytes.tv/) + * [Avistaz](https://avistaz.to/) * [BakaBT](http://bakabt.me/) * [bB](http://reddit.com/r/baconbits) * [BeyondHD](https://beyondhd.me/) diff --git a/src/Jackett/Content/logos/avistaz.png b/src/Jackett/Content/logos/avistaz.png new file mode 100644 index 0000000000000000000000000000000000000000..4944a926ef10f918dc52c4eaf7893c957a21769b GIT binary patch literal 4085 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 literal 0 HcmV?d00001 diff --git a/src/Jackett/Indexers/Abstract/AvistazTracker.cs b/src/Jackett/Indexers/Abstract/AvistazTracker.cs new file mode 100644 index 000000000..72ef2a29e --- /dev/null +++ b/src/Jackett/Indexers/Abstract/AvistazTracker.cs @@ -0,0 +1,136 @@ +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; + +namespace Jackett.Indexers +{ + public abstract class AvistazTracker : BaseIndexer + { + private string LoginUrl { get { return SiteLink + "auth/login"; } } + private string SearchUrl { get { return SiteLink + "torrents?in=1&type={0}&search={1}"; } } + + new ConfigurationDataBasicLogin configData + { + get { return (ConfigurationDataBasicLogin)base.configData; } + set { base.configData = value; } + } + + public AvistazTracker(IIndexerManagerService indexerManager, IWebClient webClient, Logger logger, IProtectionService protectionService, string name, string desc, string link) + : base(name: name, + description: desc, + link: link, + caps: TorznabUtil.CreateDefaultTorznabTVCaps(), + manager: indexerManager, + client: webClient, + logger: logger, + p: protectionService, + configData: new ConfigurationDataBasicLogin()) + { + AddCategoryMapping(1, TorznabCatType.Movies); + AddCategoryMapping(1, TorznabCatType.MoviesForeign); + AddCategoryMapping(1, TorznabCatType.MoviesHD); + AddCategoryMapping(1, TorznabCatType.MoviesSD); + AddCategoryMapping(2, TorznabCatType.TV); + AddCategoryMapping(3, TorznabCatType.Audio); + } + + public async Task ApplyConfiguration(JToken configJson) + { + configData.LoadValuesFromJson(configJson); + var loginPage = await RequestStringWithCookies(LoginUrl, string.Empty); + var token = new Regex("Avz.CSRF_TOKEN = '(.*?)';").Match(loginPage.Content).Groups[1].ToString(); + var pairs = new Dictionary { + { "_token", token }, + { "username_email", configData.Username.Value }, + { "password", configData.Password.Value }, + { "remember", "on" } + }; + + var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, loginPage.Cookies, true, null, LoginUrl); + await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("auth/logout"), () => + { + CQ dom = result.Content; + var messageEl = dom[".form-error"]; + var errorMessage = messageEl.Text().Trim(); + throw new ExceptionWithConfigData(errorMessage, configData); + }); + + return IndexerConfigurationStatus.RequiresTesting; + } + + public async Task> PerformQuery(TorznabQuery query) + { + var releases = new List(); + + var categoryMapping = MapTorznabCapsToTrackers(query).Distinct(); + string category = "0"; // Aka all + if (categoryMapping.Count() == 1) + { + category = categoryMapping.First(); + } + + + var episodeSearchUrl = string.Format(SearchUrl, category, HttpUtility.UrlEncode(query.GetQueryString())); + + var response = await RequestStringWithCookiesAndRetry(episodeSearchUrl); + + try + { + CQ dom = response.Content; + var rows = dom["table > tbody > tr"]; + foreach (var row in rows) + { + CQ qRow = row.Cq(); + var release = new ReleaseInfo(); + + release.MinimumRatio = 1; + release.MinimumSeedTime = 172800; + + var qLink = row.ChildElements.ElementAt(1).FirstElementChild.Cq(); + release.Title = qLink.Text().Trim(); + release.Comments = new Uri(qLink.Attr("href")); + release.Guid = release.Comments; + + var qDownload = row.ChildElements.ElementAt(3).FirstElementChild.Cq(); + release.Link = new Uri(qDownload.Attr("href")); + + var dateStr = row.ChildElements.ElementAt(5).Cq().Text().Trim(); + release.PublishDate = DateTimeUtil.FromTimeAgo(dateStr); + + var sizeStr = row.ChildElements.ElementAt(6).Cq().Text(); + release.Size = ReleaseInfo.GetBytes(sizeStr); + + release.Seeders = ParseUtil.CoerceInt(row.ChildElements.ElementAt(8).Cq().Text()); + release.Peers = ParseUtil.CoerceInt(row.ChildElements.ElementAt(9).Cq().Text()) + release.Seeders; + + var cat = row.Cq().Find("td:eq(0) i").First().Attr("class") + .Replace("gi gi-film", "1") + .Replace("gi gi-tv", "2") + .Replace("gi gi-music", "3") + .Replace("text-pink", string.Empty); + release.Category = MapTrackerCatToNewznab(cat.Trim()); + releases.Add(release); + } + } + catch (Exception ex) + { + OnParseError(response.Content, ex); + } + return releases; + } + } +} \ No newline at end of file diff --git a/src/Jackett/Indexers/Avistaz.cs b/src/Jackett/Indexers/Avistaz.cs new file mode 100644 index 000000000..ea99df3a0 --- /dev/null +++ b/src/Jackett/Indexers/Avistaz.cs @@ -0,0 +1,35 @@ +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; + +namespace Jackett.Indexers +{ + public class Avistaz : AvistazTracker, IIndexer + { + public Avistaz(IIndexerManagerService indexerManager, IWebClient webClient, Logger logger, IProtectionService protectionService) + : base(name: "Avistaz", + desc: "Aka AsiaTorrents", + link: "https://avistaz.to/", + indexerManager: indexerManager, + logger: logger, + protectionService: protectionService, + webClient: webClient + ) + { + } + } +} \ No newline at end of file diff --git a/src/Jackett/Indexers/PrivateHD.cs b/src/Jackett/Indexers/PrivateHD.cs index 48393fc65..6bb387ca1 100644 --- a/src/Jackett/Indexers/PrivateHD.cs +++ b/src/Jackett/Indexers/PrivateHD.cs @@ -18,119 +18,18 @@ using Jackett.Models.IndexerConfig; namespace Jackett.Indexers { - public class PrivateHD : BaseIndexer, IIndexer + public class PrivateHD : AvistazTracker, IIndexer { - private string LoginUrl { get { return SiteLink + "auth/login"; } } - private string SearchUrl { get { return SiteLink + "torrents?in=1&type={0}&search={1}"; } } - - new ConfigurationDataBasicLogin configData - { - get { return (ConfigurationDataBasicLogin)base.configData; } - set { base.configData = value; } - } - - public PrivateHD(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps) + public PrivateHD(IIndexerManagerService indexerManager, IWebClient webClient, Logger logger, IProtectionService protectionService) : base(name: "PrivateHD", - description: "BitTorrent site for High Quality, High Definition (HD) movies and TV Shows", + desc: "BitTorrent site for High Quality, High Definition (HD) movies and TV Shows", link: "https://privatehd.to/", - caps: TorznabUtil.CreateDefaultTorznabTVCaps(), - manager: i, - client: wc, - logger: l, - p: ps, - configData: new ConfigurationDataBasicLogin()) + indexerManager: indexerManager, + logger: logger, + protectionService: protectionService, + webClient: webClient + ) { - AddCategoryMapping(1, TorznabCatType.Movies); - AddCategoryMapping(1, TorznabCatType.MoviesForeign); - AddCategoryMapping(1, TorznabCatType.MoviesHD); - AddCategoryMapping(1, TorznabCatType.MoviesSD); - AddCategoryMapping(2, TorznabCatType.TV); - AddCategoryMapping(3, TorznabCatType.Audio); - } - - public async Task ApplyConfiguration(JToken configJson) - { - configData.LoadValuesFromJson(configJson); - var loginPage = await RequestStringWithCookies(LoginUrl, string.Empty); - var token = new Regex("Avz.CSRF_TOKEN = '(.*?)';").Match(loginPage.Content).Groups[1].ToString(); - var pairs = new Dictionary { - { "_token", token }, - { "username_email", configData.Username.Value }, - { "password", configData.Password.Value }, - { "remember", "on" } - }; - - var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, loginPage.Cookies, true, null, LoginUrl); - await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("auth/logout"), () => - { - CQ dom = result.Content; - var messageEl = dom[".form-error"]; - var errorMessage = messageEl.Text().Trim(); - throw new ExceptionWithConfigData(errorMessage, configData); - }); - - return IndexerConfigurationStatus.RequiresTesting; - } - - public async Task> PerformQuery(TorznabQuery query) - { - var releases = new List(); - - var categoryMapping = MapTorznabCapsToTrackers(query).Distinct(); - string category = "0"; // Aka all - if (categoryMapping.Count() == 1) - { - category = categoryMapping.First(); - } - - - var episodeSearchUrl = string.Format(SearchUrl, category, HttpUtility.UrlEncode(query.GetQueryString())); - - var response = await RequestStringWithCookiesAndRetry(episodeSearchUrl); - - try - { - CQ dom = response.Content; - var rows = dom["table > tbody > tr"]; - foreach (var row in rows) - { - CQ qRow = row.Cq(); - var release = new ReleaseInfo(); - - release.MinimumRatio = 1; - release.MinimumSeedTime = 172800; - - var qLink = row.ChildElements.ElementAt(1).FirstElementChild.Cq(); - release.Title = qLink.Text().Trim(); - release.Comments = new Uri(qLink.Attr("href")); - release.Guid = release.Comments; - - var qDownload = row.ChildElements.ElementAt(3).FirstElementChild.Cq(); - release.Link = new Uri(qDownload.Attr("href")); - - var dateStr = row.ChildElements.ElementAt(5).Cq().Text().Trim(); - release.PublishDate = DateTimeUtil.FromTimeAgo(dateStr); - - var sizeStr = row.ChildElements.ElementAt(6).Cq().Text(); - release.Size = ReleaseInfo.GetBytes(sizeStr); - - release.Seeders = ParseUtil.CoerceInt(row.ChildElements.ElementAt(8).Cq().Text()); - release.Peers = ParseUtil.CoerceInt(row.ChildElements.ElementAt(9).Cq().Text()) + release.Seeders; - - var cat = row.Cq().Find("td:eq(0) i").First().Attr("class") - .Replace("gi gi-film", "1") - .Replace("gi gi-tv", "2") - .Replace("gi gi-music", "3") - .Replace("text-pink", string.Empty); - release.Category = MapTrackerCatToNewznab(cat.Trim()); - releases.Add(release); - } - } - catch (Exception ex) - { - OnParseError(response.Content, ex); - } - return releases; } } } diff --git a/src/Jackett/Jackett.csproj b/src/Jackett/Jackett.csproj index 8a78bd149..e5a39b615 100644 --- a/src/Jackett/Jackett.csproj +++ b/src/Jackett/Jackett.csproj @@ -175,6 +175,7 @@ + @@ -189,7 +190,8 @@ - + + @@ -405,6 +407,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest diff --git a/src/Jackett/Indexers/ManualSearchResult.cs b/src/Jackett/Models/ManualSearchResult.cs similarity index 91% rename from src/Jackett/Indexers/ManualSearchResult.cs rename to src/Jackett/Models/ManualSearchResult.cs index 0831640bf..59e1a35bd 100644 --- a/src/Jackett/Indexers/ManualSearchResult.cs +++ b/src/Jackett/Models/ManualSearchResult.cs @@ -5,7 +5,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; -namespace Jackett.Indexers +namespace Jackett { public class ManualSearchResult { From e1d28b25a80e40bdd2f32601d6a3b3a79f4bbd60 Mon Sep 17 00:00:00 2001 From: KZ Date: Sun, 23 Aug 2015 21:45:52 +0100 Subject: [PATCH 18/19] Implement EuTorrents --- README.md | 1 + src/Jackett/Content/logos/eutorrents.png | Bin 0 -> 2600 bytes src/Jackett/Indexers/EuTorrents.cs | 35 +++++++++++++++++++++++ src/Jackett/Jackett.csproj | 4 +++ 4 files changed, 40 insertions(+) create mode 100644 src/Jackett/Content/logos/eutorrents.png create mode 100644 src/Jackett/Indexers/EuTorrents.cs diff --git a/README.md b/README.md index 7941d9a74..cc30745d4 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ We were previously focused on TV but are working on extending searches to allow * [BIT-HDTV](https://www.bit-hdtv.com) * [BitMeTV](http://www.bitmetv.org/) * [Demonoid](http://www.demonoid.pw/) + * [EuTorrents](https://eutorrents.to/) * [FileList](http://filelist.ro/) * [FrenchTorrentDb](http://www.frenchtorrentdb.com/) * [Freshon](https://freshon.tv/) diff --git a/src/Jackett/Content/logos/eutorrents.png b/src/Jackett/Content/logos/eutorrents.png new file mode 100644 index 0000000000000000000000000000000000000000..3c3983696c5d78e289952627942c8ea96ac04b54 GIT binary patch literal 2600 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

+ @@ -422,6 +423,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest From 5893eacc84f647146718b240587e5a0cd2cfe8e8 Mon Sep 17 00:00:00 2001 From: KZ Date: Sun, 23 Aug 2015 22:11:18 +0100 Subject: [PATCH 19/19] Bump version --- src/Jackett/Properties/AssemblyInfo.cs | 4 ++-- src/Jackett/Utils/BrowserUtil.cs | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Jackett/Properties/AssemblyInfo.cs b/src/Jackett/Properties/AssemblyInfo.cs index 6a6c92c39..6e876de18 100644 --- a/src/Jackett/Properties/AssemblyInfo.cs +++ b/src/Jackett/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.6.2.0")] -[assembly: AssemblyFileVersion("0.6.2.0")] +[assembly: AssemblyVersion("0.6.3.0")] +[assembly: AssemblyFileVersion("0.6.3.0")] diff --git a/src/Jackett/Utils/BrowserUtil.cs b/src/Jackett/Utils/BrowserUtil.cs index cc23d2baa..326a6c7da 100644 --- a/src/Jackett/Utils/BrowserUtil.cs +++ b/src/Jackett/Utils/BrowserUtil.cs @@ -10,7 +10,16 @@ namespace Jackett.Utils { public static string ChromeUserAgent { - get { return "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.89 Safari/537.36"; } + get { + if (System.Environment.OSVersion.Platform == PlatformID.Unix) + { + return "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Ubuntu Chrome/44.0.2403.155 Safari/537.36"; + } + else + { + return "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.155 Safari/537.36"; + } + } } } }