diff --git a/src/Jackett.Common/Definitions/icetorrent.yml b/src/Jackett.Common/Definitions/icetorrent.yml
deleted file mode 100644
index aa2f08dc7..000000000
--- a/src/Jackett.Common/Definitions/icetorrent.yml
+++ /dev/null
@@ -1,186 +0,0 @@
----
-id: icetorrent
-name: ICE Torrent
-description: "ICE Torrent is a ratioless ROMANIAN Private Torrent Tracker for 0DAY / GENERAL"
-language: ro-ro
-type: private
-encoding: UTF-8
-links:
- - https://icetorrent.org/
-legacylinks:
- - https://www.icetorrent.org/
-
-caps:
- categorymappings:
- - {id: 38, cat: Movies, desc: "Movie Packs"}
- - {id: 10, cat: Movies/SD, desc: "Movies: SD"}
- - {id: 35, cat: Movies/SD, desc: "Movies: SD Ro"}
- - {id: 8, cat: Movies/HD, desc: "Movies: HD"}
- - {id: 29, cat: Movies/HD, desc: "Movies: HD Ro"}
- - {id: 7, cat: Movies/DVD, desc: "Movies: DVD"}
- - {id: 2, cat: Movies/DVD, desc: "Movies: DVD Ro"}
- - {id: 17, cat: Movies/BluRay, desc: "Movies: BluRay"}
- - {id: 24, cat: Movies/BluRay, desc: "Movies: BluRay Ro"}
- - {id: 59, cat: Movies, desc: "Movies: Ro"}
- - {id: 57, cat: Movies/UHD, desc: "Movies: 4K (2160p) Ro"}
- - {id: 61, cat: Movies/UHD, desc: "Movies: 4K (2160p)"}
- - {id: 41, cat: TV, desc: "TV Packs"}
- - {id: 66, cat: TV, desc: "TV Packs Ro"}
- - {id: 45, cat: TV, desc: "TV Episodes"}
- - {id: 46, cat: TV, desc: "TV Episodes Ro"}
- - {id: 43, cat: TV/HD, desc: "TV Episodes HD"}
- - {id: 44, cat: TV/HD, desc: "TV Episodes HD Ro"}
- - {id: 60, cat: TV, desc: "TV Ro"}
- - {id: 11, cat: PC/Games, desc: "Games: PC-ISO"}
- - {id: 52, cat: Console, desc: "Games: Console"}
- - {id: 1, cat: PC/0day, desc: "Applications"}
- - {id: 14, cat: PC, desc: "Applications: Linux"}
- - {id: 37, cat: PC/Mac, desc: "Applications: Mac"}
- - {id: 19, cat: PC/Phone-Other, desc: "Applications: Mobile"}
- - {id: 62, cat: TV, desc: "TV Cartoons"}
- - {id: 3, cat: TV/Anime, desc: "TV Anime / Hentai"}
- - {id: 6, cat: Books/Ebook, desc: "E-books"}
- - {id: 5, cat: Audio, desc: "Music"}
- - {id: 64, cat: Audio/Video, desc: "Music Video"}
- - {id: 18, cat: Other, desc: "Images"}
- - {id: 22, cat: TV/Sport, desc: "TV Sports"}
- - {id: 58, cat: TV/Sport, desc: "TV Sports Ro"}
- - {id: 9, cat: TV/Documentary, desc: "TV Documentary"}
- - {id: 63, cat: TV/Documentary, desc: "TV Documentary Ro"}
- - {id: 65, cat: Other, desc: "Tutorial"}
- - {id: 67, cat: Other, desc: "Miscellaneous"}
- - {id: 15, cat: XXX, desc: "XXX Movies"}
- - {id: 47, cat: XXX, desc: "XXX DVD"}
- - {id: 48, cat: XXX, desc: "XXX HD"}
- - {id: 49, cat: XXX, desc: "XXX Images"}
- - {id: 50, cat: XXX, desc: "XXX Packs"}
- - {id: 51, cat: XXX, desc: "XXX SD"}
-
- modes:
- search: [q, imdbid]
- tv-search: [q, season, ep, imdbid]
- movie-search: [q, imdbid]
- music-search: [q]
-
-settings:
- - name: username
- type: text
- label: Username
- - name: password
- type: password
- label: Password
- - name: sort
- type: select
- label: Sort requested from site
- default: "refreshAt"
- options:
- "refreshAt": "created"
- "seeders": "seeders"
- "size": "size"
- - name: type
- type: select
- label: Order requested from site
- default: "desc"
- options:
- "desc": "desc"
- "asc": "asc"
- - name: browseadult
- type: checkbox
- label: Use the Adult search engine
- default: false
- - name: info_browseadult
- type: info
- label: "About the Adult search engine"
- default: "The Adult search engine only returns Adult category results.And Vice Versa."
- - name: info_Search
- type: info
- label: "About Search results"
- default: "This indexer supports only the English language. Choosing non-English languages will cause incorrect dates to be returned.For best results edit your profile and set your Torrents per page to 100. The Default is 50."
-
-login:
- path: login
- method: form
- form: form
- inputs:
- username: "{{ .Config.username }}"
- password: "{{ .Config.password }}"
- _remember_me: on
- selectorinputs:
- _csrf_token:
- selector: input[name="_csrf_token"]
- attribute: value
- error:
- - selector: span:contains("Error")
- - selector: div.alert:contains("failed")
- test:
- path: /
- selector: a[href*="/logout?_csrf_token="]
-
-ratio:
- text: -1
-
-search:
- paths:
- # https://icetorrent.org/browse?search=&submit=&sort=torrent.size&direction=desc&page=1
- - path: "{{ if .Config.browseadult }}adult{{else}}browse{{end}}"
- inputs:
- $raw: "{{ range .Categories }}categories[]={{.}}&{{end}}"
- search: "{{ if .Query.IMDBID }}{{ .Query.IMDBID }}{{else}}{{ .Keywords }}{{end}}"
- sort: "torrent.{{ .Config.sort }}"
- direction: "{{ .Config.type }}"
-
- rows:
- selector: div.kt-portlet--mobile > div.kt-portlet__body--fit > div.mr-0
-
- fields:
- category:
- selector: a[href^="/browse?categories"]
- attribute: href
- filters:
- - name: regexp
- args: (\d+)$
- title:
- selector: a[href^="/browse/"]
- details:
- selector: a[href^="/browse/"]
- attribute: href
- download:
- selector: a[href^="/torrents/"]
- attribute: href
- imdb:
- optional: true
- selector: a[href*="imdb.com/title/tt"]
- attribute: href
- date:
- selector: div[data-toggle="kt-tooltip"]
- attribute: title
- filters:
- - name: dateparse
- args: "Jan 2, 2006, 3:04:05 PM"
- size:
- selector: div[data-toggle="kt-tooltip"] + div + div
- grabs:
- selector: div[data-toggle="kt-tooltip"] + div
- filters:
- - name: regexp
- args: (\d+)
- seeders:
- selector: div[data-toggle="kt-tooltip"] + div + div + div > div div:nth-child(1)
- filters:
- - name: regexp
- args: (\d+)
- leechers:
- selector: div[data-toggle="kt-tooltip"] + div + div + div > div div:nth-child(2)
- filters:
- - name: regexp
- args: (\d+)
- downloadvolumefactor:
- case:
- "span.kt-badge--success:contains(\"free\")": 0
- "span.kt-badge--dark:contains(\"half\")": 0.5
- "*": 1
- uploadvolumefactor:
- case:
- "span.kt-badge--info:contains(\"double\")": 2
- "*": 1
-# engine n/a
diff --git a/src/Jackett.Common/Definitions/scenefz.yml b/src/Jackett.Common/Definitions/scenefz.yml
deleted file mode 100644
index 363aa8c4b..000000000
--- a/src/Jackett.Common/Definitions/scenefz.yml
+++ /dev/null
@@ -1,165 +0,0 @@
----
-id: scenefz
-name: SceneFZ
-description: "SceneFZ is a ratioless ROMANIAN Private Torrent Tracker for MOVIES / TV / GENERAL"
-language: ro-ro
-type: private
-encoding: UTF-8
-links:
- - https://scenefz.me/
-legacylinks:
- - https://www.scenefz.me/
- - https://www.u-torrents.ro/
-
-caps:
- categorymappings:
- - {id: 62, cat: TV, desc: "Cartoons"}
- - {id: 3, cat: TV/Anime, desc: "Anime/Hentai"}
- - {id: 1, cat: PC/0day, desc: "Appz"}
- - {id: 9, cat: TV/Documentary, desc: "Documentary"}
- - {id: 63, cat: TV/Documentary, desc: "Documentary-RO"}
- - {id: 6, cat: Books, desc: "eBooks"}
- - {id: 52, cat: Console, desc: "Games-Console"}
- - {id: 11, cat: PC/Games, desc: "Games-PC"}
- - {id: 18, cat: Other, desc: "Images"}
- - {id: 65, cat: Other, desc: "Tutorial"}
- - {id: 14, cat: PC, desc: "Linux"}
- - {id: 37, cat: PC/Mac, desc: "Mac"}
- - {id: 19, cat: PC/Phone-Other, desc: "Mobile"}
- - {id: 17, cat: Movies/BluRay, desc: "Movies-BluRay"}
- - {id: 24, cat: Movies/BluRay, desc: "Movies-BluRayRO"}
- - {id: 7, cat: Movies/DVD, desc: "Movies-DVD"}
- - {id: 2, cat: Movies/DVD, desc: "Movies-DVD-RO"}
- - {id: 8, cat: Movies/HD, desc: "Movies-HD"}
- - {id: 29, cat: Movies/HD, desc: "Movies-HD-RO"}
- - {id: 59, cat: Movies/Foreign, desc: "Movies-RO"}
- - {id: 57, cat: Movies/UHD, desc: "Movies-UHD-RO"}
- - {id: 61, cat: Movies/UHD, desc: "Movies-UHD"}
- - {id: 38, cat: Movies, desc: "Movies-Packs"}
- - {id: 10, cat: Movies/SD, desc: "Movies-SD"}
- - {id: 35, cat: Movies/SD, desc: "Movies-SD-RO"}
- - {id: 5, cat: Audio, desc: "Music"}
- - {id: 64, cat: Audio/Video, desc: "Music Videos"}
- - {id: 22, cat: TV/Sport, desc: "Sport"}
- - {id: 58, cat: TV/Sport, desc: "Sports-RO"}
- - {id: 43, cat: TV/HD, desc: "TV-HD"}
- - {id: 44, cat: TV/HD, desc: "TV-HD-RO"}
- - {id: 41, cat: TV, desc: "TV-Packs"}
- - {id: 45, cat: TV/SD, desc: "TV-SD"}
- - {id: 46, cat: TV/SD, desc: "TV-SD-RO"}
- - {id: 60, cat: TV/FOREIGN, desc: "TV-RO"}
- - {id: 66, cat: TV/FOREIGN, desc: "TV-Packs-RO"}
- - {id: 15, cat: XXX, desc: "XXX"}
- - {id: 47, cat: XXX, desc: "XXX-DVD"}
- - {id: 48, cat: XXX, desc: "XXX-HD"}
- - {id: 49, cat: XXX/Imageset, desc: "XXX-IMGSet"}
- - {id: 50, cat: XXX, desc: "XXX-Packs"}
- - {id: 51, cat: XXX, desc: "XXX-SD"}
-
- modes:
- search: [q, imdbid]
- tv-search: [q, season, ep, imdbid]
- movie-search: [q, imdbid]
- music-search: [q]
-
-settings:
- - name: username
- type: text
- label: Username
- - name: password
- type: password
- label: Password
- - name: sort
- type: select
- label: Sort requested from site
- default: "torrent.refreshAt"
- options:
- "torrent.refreshAt": "created"
- "torrent.seeders": "seeders"
- "torrent.size": "size"
- - name: type
- type: select
- label: Order requested from site
- default: "desc"
- options:
- "desc": "desc"
- "asc": "asc"
-
-login:
- path: login
- method: form
- form: form:has(input[name="_remember_me"])
- inputs:
- username: "{{ .Config.username }}"
- password: "{{ .Config.password }}"
- _remember_me: on
- error:
- - selector: td.embedded:has(center > h2:contains(failed))
- - selector: span:contains("Error")
- test:
- path: browse
-
-search:
- paths:
- - path: browse
- inputs:
- $raw: "{{ range .Categories }}categories[]={{.}}&{{end}}"
- search: "{{ if .Query.IMDBID }}{{ .Query.IMDBID }}{{else}}{{ .Keywords }}{{end}}"
- sort: "{{ .Config.sort }}"
- direction: "{{ .Config.type }}"
-
- rows:
- selector: div.kt-portlet--mobile > div.kt-portlet__body--fit > div.mr-0
-
- fields:
- category:
- selector: a[href^="/browse?categories"]
- attribute: href
- filters:
- - name: regexp
- args: (\d+)$
- title:
- selector: a[href^="/browse/"]
- details:
- selector: a[href^="/browse/"]
- attribute: href
- download:
- selector: a[href^="/torrents/"]
- attribute: href
- imdb:
- optional: true
- selector: a[href*="imdb.com/title/tt"]
- attribute: href
- date:
- selector: div[data-toggle="kt-tooltip"]
- attribute: title
- filters:
- - name: dateparse
- args: "Jan 2, 2006, 03:04:05 PM"
- size:
- selector: div[data-toggle="kt-tooltip"] + div + div
- grabs:
- selector: div[data-toggle="kt-tooltip"] + div
- filters:
- - name: regexp
- args: (\d+)
- seeders:
- selector: div[data-toggle="kt-tooltip"] + div + div + div > div div:nth-child(1)
- filters:
- - name: regexp
- args: (\d+)
- leechers:
- selector: div[data-toggle="kt-tooltip"] + div + div + div > div div:nth-child(2)
- filters:
- - name: regexp
- args: (\d+)
- downloadvolumefactor:
- case:
- "span.kt-badge--success:contains(\"free\")": 0
- "span.kt-badge--dark:contains(\"half\")": 0.5
- "*": 1
- uploadvolumefactor:
- case:
- "span.kt-badge--info:contains(\"double\")": 2
- "*": 1
-# engine n/a
diff --git a/src/Jackett.Common/Definitions/xtremezone.yml b/src/Jackett.Common/Definitions/xtremezone.yml
deleted file mode 100644
index 2d1d3b6e0..000000000
--- a/src/Jackett.Common/Definitions/xtremezone.yml
+++ /dev/null
@@ -1,169 +0,0 @@
----
-id: xtremezone
-name: Xtreme Zone
-description: "XtreMeZone (MYXZ) is a ROMANIAN Private Torrent Tracker for MOVIES / TV / GENERAL"
-language: ro-ro
-type: private
-encoding: UTF-8
-links:
- - https://myxz.eu/
-legacylinks:
- - https://www.myxz.eu/
- - https://www.myxz.org/
-
-caps:
- categorymappings:
- - {id: 62, cat: TV, desc: "Cartoons"}
- - {id: 3, cat: TV/Anime, desc: "Anime/Hentai"}
- - {id: 1, cat: PC/0day, desc: "Appz"}
- - {id: 9, cat: TV/Documentary, desc: "Documentary"}
- - {id: 63, cat: TV/Documentary, desc: "Documentary-RO"}
- - {id: 6, cat: Books, desc: "eBooks"}
- - {id: 52, cat: Console, desc: "Games-Console"}
- - {id: 11, cat: PC/Games, desc: "Games-PC"}
- - {id: 18, cat: Other, desc: "Images"}
- - {id: 65, cat: Other, desc: "Tutorial"}
- - {id: 14, cat: PC, desc: "Linux"}
- - {id: 37, cat: PC/Mac, desc: "Mac"}
- - {id: 19, cat: PC/Phone-Other, desc: "Mobile"}
- - {id: 17, cat: Movies/BluRay, desc: "Movies-BluRay"}
- - {id: 24, cat: Movies/BluRay, desc: "Movies-BluRayRO"}
- - {id: 7, cat: Movies/DVD, desc: "Movies-DVD"}
- - {id: 2, cat: Movies/DVD, desc: "Movies-DVD-RO"}
- - {id: 8, cat: Movies/HD, desc: "Movies-HD"}
- - {id: 29, cat: Movies/HD, desc: "Movies-HD-RO"}
- - {id: 59, cat: Movies/Foreign, desc: "Movies-RO"}
- - {id: 57, cat: Movies/UHD, desc: "Movies-UHD-RO"}
- - {id: 61, cat: Movies/UHD, desc: "Movies-UHD"}
- - {id: 38, cat: Movies, desc: "Movies-Packs"}
- - {id: 10, cat: Movies/SD, desc: "Movies-SD"}
- - {id: 35, cat: Movies/SD, desc: "Movies-SD-RO"}
- - {id: 5, cat: Audio, desc: "Music"}
- - {id: 64, cat: Audio/Video, desc: "Music Videos"}
- - {id: 22, cat: TV/Sport, desc: "Sport"}
- - {id: 58, cat: TV/Sport, desc: "Sports-RO"}
- - {id: 43, cat: TV/HD, desc: "TV-HD"}
- - {id: 44, cat: TV/HD, desc: "TV-HD-RO"}
- - {id: 41, cat: TV, desc: "TV-Packs"}
- - {id: 45, cat: TV/SD, desc: "TV-SD"}
- - {id: 46, cat: TV/SD, desc: "TV-SD-RO"}
- - {id: 60, cat: TV/FOREIGN, desc: "TV-RO"}
- - {id: 66, cat: TV/FOREIGN, desc: "TV-Packs-RO"}
- - {id: 15, cat: XXX, desc: "XXX"}
- - {id: 47, cat: XXX, desc: "XXX-DVD"}
- - {id: 48, cat: XXX, desc: "XXX-HD"}
- - {id: 49, cat: XXX/Imageset, desc: "XXX-IMGSet"}
- - {id: 50, cat: XXX, desc: "XXX-Packs"}
- - {id: 51, cat: XXX, desc: "XXX-SD"}
-
- modes:
- search: [q, imdbid]
- tv-search: [q, season, ep, imdbid]
- movie-search: [q, imdbid]
- music-search: [q]
-
-settings:
- - name: username
- type: text
- label: Username
- - name: password
- type: password
- label: Password
- - name: sort
- type: select
- label: Sort requested from site
- default: "torrent.refreshAt"
- options:
- "torrent.refreshAt": "created"
- "torrent.seeders": "seeders"
- "torrent.size": "size"
- - name: type
- type: select
- label: Order requested from site
- default: "desc"
- options:
- "desc": "desc"
- "asc": "asc"
-
-login:
- path: login
- method: form
- form: form:has(input[name="_remember_me"])
- inputs:
- username: "{{ .Config.username }}"
- password: "{{ .Config.password }}"
- _remember_me: on
- error:
- - selector: td.embedded:has(center > h2:contains(failed))
- - selector: span:contains("Error")
- test:
- path: browse
-
-ratio:
- path: browse
- selector: font:contains("Ratio:")+font
-
-search:
- paths:
- - path: browse
- inputs:
- $raw: "{{ range .Categories }}categories[]={{.}}&{{end}}"
- search: "{{ if .Query.IMDBID }}{{ .Query.IMDBID }}{{else}}{{ .Keywords }}{{end}}"
- sort: "{{ .Config.sort }}"
- direction: "{{ .Config.type }}"
-
- rows:
- selector: div.kt-portlet--mobile > div.kt-portlet__body--fit > div.mr-0
-
- fields:
- category:
- selector: a[href^="/browse?categories"]
- attribute: href
- filters:
- - name: regexp
- args: (\d+)$
- title:
- selector: a[href^="/browse/"]
- details:
- selector: a[href^="/browse/"]
- attribute: href
- download:
- selector: a[href^="/torrents/"]
- attribute: href
- imdb:
- optional: true
- selector: a[href*="imdb.com/title/tt"]
- attribute: href
- date:
- selector: div[data-toggle="kt-tooltip"]
- attribute: title
- filters:
- - name: dateparse
- args: "Jan 2, 2006, 03:04:05 PM"
- size:
- selector: div[data-toggle="kt-tooltip"] + div + div
- grabs:
- selector: div[data-toggle="kt-tooltip"] + div
- filters:
- - name: regexp
- args: (\d+)
- seeders:
- selector: div[data-toggle="kt-tooltip"] + div + div + div > div div:nth-child(1)
- filters:
- - name: regexp
- args: (\d+)
- leechers:
- selector: div[data-toggle="kt-tooltip"] + div + div + div > div div:nth-child(2)
- filters:
- - name: regexp
- args: (\d+)
- downloadvolumefactor:
- case:
- "span.kt-badge--success:contains(\"free\")": 0
- "span.kt-badge--dark:contains(\"half\")": 0.5
- "*": 1
- uploadvolumefactor:
- case:
- "span.kt-badge--info:contains(\"double\")": 2
- "*": 1
-# engine n/a
diff --git a/src/Jackett.Common/Indexers/Abstract/XtremeZoneTracker.cs b/src/Jackett.Common/Indexers/Abstract/XtremeZoneTracker.cs
new file mode 100644
index 000000000..11b6635b8
--- /dev/null
+++ b/src/Jackett.Common/Indexers/Abstract/XtremeZoneTracker.cs
@@ -0,0 +1,186 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+using Jackett.Common.Models;
+using Jackett.Common.Models.IndexerConfig;
+using Jackett.Common.Services.Interfaces;
+using Jackett.Common.Utils;
+using Newtonsoft.Json;
+using Newtonsoft.Json.Linq;
+using NLog;
+using WebClient = Jackett.Common.Utils.Clients.WebClient;
+
+namespace Jackett.Common.Indexers.Abstract
+{
+ [ExcludeFromCodeCoverage]
+ public abstract class XtremeZoneTracker : BaseWebIndexer
+ {
+ private readonly Dictionary ApiHeaders = new Dictionary
+ {
+ {"Accept", "application/json"},
+ {"Content-Type", "application/json"}
+ };
+ private string LoginUrl => SiteLink + "api/login";
+ private string SearchUrl => SiteLink + "api/torrent";
+ private string _token;
+
+ private new ConfigurationDataBasicLogin configData => (ConfigurationDataBasicLogin)base.configData;
+
+ protected XtremeZoneTracker(string link, string id, string name, string description,
+ IIndexerConfigurationService configService, WebClient client, Logger logger,
+ IProtectionService p, TorznabCapabilities caps)
+ : base(id: id,
+ name: name,
+ description: description,
+ link: link,
+ caps: caps,
+ configService: configService,
+ client: client,
+ logger: logger,
+ p: p,
+ configData: new ConfigurationDataBasicLogin())
+ {
+ Encoding = Encoding.UTF8;
+ Language = "ro-ro";
+ Type = "private";
+
+ // requestDelay for API Limit (1 request per 2 seconds)
+ webclient.requestDelay = 2.1;
+ }
+
+ public override async Task ApplyConfiguration(JToken configJson)
+ {
+ LoadValuesFromJson(configJson);
+
+ await RenewalTokenAsync();
+
+ var releases = await PerformQuery(new TorznabQuery());
+ await ConfigureIfOK(string.Empty, releases.Any(),
+ () => throw new Exception("Could not find releases."));
+
+ return IndexerConfigurationStatus.Completed;
+ }
+
+ private async Task RenewalTokenAsync()
+ {
+ var body = new Dictionary
+ {
+ { "username", configData.Username.Value.Trim() },
+ { "password", configData.Password.Value.Trim() }
+ };
+ var jsonData = JsonConvert.SerializeObject(body);
+ var result = await PostDataWithCookies(LoginUrl, null, headers: ApiHeaders, rawbody: jsonData);
+ var json = JObject.Parse(result.Content);
+ _token = json.Value("token");
+ if (_token == null)
+ throw new Exception(json.Value("message"));
+ }
+
+ protected override async Task> PerformQuery(TorznabQuery query)
+ {
+ var releases = new List();
+
+ //var categoryMapping = MapTorznabCapsToTrackers(query).Distinct().ToList();
+ var qc = new List> // NameValueCollection don't support cat[]=19&cat[]=6
+ {
+ {"itemsPerPage", "100"},
+ {"sort", "torrent.createdAt"},
+ {"direction", "desc"}
+ };
+
+ foreach (var cat in MapTorznabCapsToTrackers(query))
+ qc.Add("categories[]", cat);
+
+ if (query.IsImdbQuery)
+ qc.Add("imdbId", query.ImdbID);
+ else
+ qc.Add("search", query.GetQueryString());
+
+ if (string.IsNullOrWhiteSpace(_token)) // fist time login
+ await RenewalTokenAsync();
+
+ var searchUrl = SearchUrl + "?" + qc.GetQueryString();
+ var response = await RequestStringWithCookies(searchUrl, headers: GetSearchHeaders());
+ if (response.Status == HttpStatusCode.Unauthorized)
+ {
+ await RenewalTokenAsync(); // re-login
+ response = await RequestStringWithCookies(searchUrl, headers: GetSearchHeaders());
+ }
+ else if (response.Status != HttpStatusCode.OK)
+ throw new Exception($"Unknown error in search: {response.Content}");
+
+ try
+ {
+ var rows = JArray.Parse(response.Content);
+ foreach (var row in rows)
+ {
+ var id = row.Value("id");
+ var comments = new Uri($"{SiteLink}browse/{id}");
+ var link = new Uri($"{SiteLink}api/torrent/{id}/download");
+ var publishDate = DateTime.Parse(row.Value("created_at"), CultureInfo.InvariantCulture);
+ var cat = row.Value("category").Value("id");
+
+ // "description" field in API has too much HTML code
+ var description = row.Value("short_description");
+
+ var jBanner = row.Value("poster");
+ var banner = string.IsNullOrEmpty(jBanner) ? null : new Uri(jBanner);
+
+ var dlVolumeFactor = row.Value("is_half_download") ? 0.5: 1.0;
+ dlVolumeFactor = row.Value("is_freeleech") ? 0.0 : dlVolumeFactor;
+ var ulVolumeFactor = row.Value("is_double_upload") ? 2.0: 1.0;
+
+ var release = new ReleaseInfo
+ {
+ Title = row.Value("name"),
+ Link = link,
+ Comments = comments,
+ Guid = comments,
+ Category = MapTrackerCatToNewznab(cat),
+ PublishDate = publishDate,
+ Description = description,
+ BannerUrl = banner,
+ Size = row.Value("size"),
+ Grabs = row.Value("times_completed"),
+ Seeders = row.Value("seeders"),
+ Peers = row.Value("leechers") + row.Value("seeders"),
+ DownloadVolumeFactor = dlVolumeFactor,
+ UploadVolumeFactor = ulVolumeFactor,
+ MinimumRatio = 1,
+ MinimumSeedTime = 172800 // 48 hours
+ };
+
+ releases.Add(release);
+ }
+ }
+ catch (Exception ex)
+ {
+ OnParseError(response.Content, ex);
+ }
+ return releases;
+ }
+
+ public override async Task Download(Uri link)
+ {
+ var response = await RequestBytesWithCookies(link.ToString(), headers: GetSearchHeaders());
+ if (response.Status == HttpStatusCode.Unauthorized)
+ {
+ await RenewalTokenAsync();
+ response = await RequestBytesWithCookies(link.ToString(), headers: GetSearchHeaders());
+ }
+ else if (response.Status != HttpStatusCode.OK)
+ throw new Exception($"Unknown error in download: {response.Content}");
+ return response.Content;
+ }
+
+ private Dictionary GetSearchHeaders() => new Dictionary
+ {
+ {"Authorization", $"Bearer {_token}"}
+ };
+ }
+}
diff --git a/src/Jackett.Common/Indexers/IceTorrent.cs b/src/Jackett.Common/Indexers/IceTorrent.cs
new file mode 100644
index 000000000..339466384
--- /dev/null
+++ b/src/Jackett.Common/Indexers/IceTorrent.cs
@@ -0,0 +1,78 @@
+using System.Diagnostics.CodeAnalysis;
+using Jackett.Common.Indexers.Abstract;
+using Jackett.Common.Models;
+using Jackett.Common.Services.Interfaces;
+using Jackett.Common.Utils.Clients;
+using NLog;
+
+namespace Jackett.Common.Indexers
+{
+ [ExcludeFromCodeCoverage]
+ public class IceTorrent : XtremeZoneTracker
+ {
+ public override string[] LegacySiteLinks { get; protected set; } = {
+ "https://www.icetorrent.org/"
+ };
+
+ public IceTorrent(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)
+ : base(
+ id: "icetorrent",
+ name: "ICE Torrent",
+ description: "ICE Torrent is a ratioless ROMANIAN Private Torrent Tracker for 0DAY / GENERAL",
+ link: "https://icetorrent.org/",
+ caps: new TorznabCapabilities
+ {
+ SupportsImdbMovieSearch = true
+ // SupportsImdbTVSearch = true (supported by the site but disabled due to #8107)
+ },
+ configService: configService,
+ client: wc,
+ logger: l,
+ p: ps)
+ {
+ AddCategoryMapping(38, TorznabCatType.Movies, "Movie Packs");
+ AddCategoryMapping(10, TorznabCatType.MoviesSD, "Movies: SD");
+ AddCategoryMapping(35, TorznabCatType.MoviesSD, "Movies: SD Ro");
+ AddCategoryMapping(8, TorznabCatType.MoviesHD, "Movies: HD");
+ AddCategoryMapping(29, TorznabCatType.MoviesHD, "Movies: HD Ro");
+ AddCategoryMapping(7, TorznabCatType.MoviesDVD, "Movies: DVD");
+ AddCategoryMapping(2, TorznabCatType.MoviesDVD, "Movies: DVD Ro");
+ AddCategoryMapping(17, TorznabCatType.MoviesBluRay, "Movies: BluRay");
+ AddCategoryMapping(24, TorznabCatType.MoviesBluRay, "Movies: BluRay Ro");
+ AddCategoryMapping(59, TorznabCatType.Movies, "Movies: Ro");
+ AddCategoryMapping(57, TorznabCatType.MoviesUHD, "Movies: 4K (2160p) Ro");
+ AddCategoryMapping(61, TorznabCatType.MoviesUHD, "Movies: 4K (2160p)");
+ AddCategoryMapping(41, TorznabCatType.TV, "TV Packs");
+ AddCategoryMapping(66, TorznabCatType.TV, "TV Packs Ro");
+ AddCategoryMapping(45, TorznabCatType.TV, "TV Episodes");
+ AddCategoryMapping(46, TorznabCatType.TV, "TV Episodes Ro");
+ AddCategoryMapping(43, TorznabCatType.TVHD, "TV Episodes HD");
+ AddCategoryMapping(44, TorznabCatType.TVHD, "TV Episodes HD Ro");
+ AddCategoryMapping(60, TorznabCatType.TV, "TV Ro");
+ AddCategoryMapping(11, TorznabCatType.PCGames, "Games: PC-ISO");
+ AddCategoryMapping(52, TorznabCatType.Console, "Games: Console");
+ AddCategoryMapping(1, TorznabCatType.PC0day, "Applications");
+ AddCategoryMapping(14, TorznabCatType.PC, "Applications: Linux");
+ AddCategoryMapping(37, TorznabCatType.PCMac, "Applications: Mac");
+ AddCategoryMapping(19, TorznabCatType.PCPhoneOther, "Applications: Mobile");
+ AddCategoryMapping(62, TorznabCatType.TV, "TV Cartoons");
+ AddCategoryMapping(3, TorznabCatType.TVAnime, "TV Anime / Hentai");
+ AddCategoryMapping(6, TorznabCatType.BooksEbook, "E-books");
+ AddCategoryMapping(5, TorznabCatType.Audio, "Music");
+ AddCategoryMapping(64, TorznabCatType.AudioVideo, "Music Video");
+ AddCategoryMapping(18, TorznabCatType.Other, "Images");
+ AddCategoryMapping(22, TorznabCatType.TVSport, "TV Sports");
+ AddCategoryMapping(58, TorznabCatType.TVSport, "TV Sports Ro");
+ AddCategoryMapping(9, TorznabCatType.TVDocumentary, "TV Documentary");
+ AddCategoryMapping(63, TorznabCatType.TVDocumentary, "TV Documentary Ro");
+ AddCategoryMapping(65, TorznabCatType.Other, "Tutorial");
+ AddCategoryMapping(67, TorznabCatType.Other, "Miscellaneous");
+ AddCategoryMapping(15, TorznabCatType.XXX, "XXX Movies");
+ AddCategoryMapping(47, TorznabCatType.XXX, "XXX DVD");
+ AddCategoryMapping(48, TorznabCatType.XXX, "XXX HD");
+ AddCategoryMapping(49, TorznabCatType.XXX, "XXX Images");
+ AddCategoryMapping(50, TorznabCatType.XXX, "XXX Packs");
+ AddCategoryMapping(51, TorznabCatType.XXX, "XXX SD");
+ }
+ }
+}
diff --git a/src/Jackett.Common/Indexers/SceneFZ.cs b/src/Jackett.Common/Indexers/SceneFZ.cs
new file mode 100644
index 000000000..2ed337c21
--- /dev/null
+++ b/src/Jackett.Common/Indexers/SceneFZ.cs
@@ -0,0 +1,78 @@
+using System.Diagnostics.CodeAnalysis;
+using Jackett.Common.Indexers.Abstract;
+using Jackett.Common.Models;
+using Jackett.Common.Services.Interfaces;
+using Jackett.Common.Utils.Clients;
+using NLog;
+
+namespace Jackett.Common.Indexers
+{
+ [ExcludeFromCodeCoverage]
+ public class SceneFZ : XtremeZoneTracker
+ {
+ public override string[] LegacySiteLinks { get; protected set; } = {
+ "https://www.scenefz.me/",
+ "https://www.u-torrents.ro/"
+ };
+
+ public SceneFZ(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)
+ : base(
+ id: "scenefz",
+ name: "SceneFZ",
+ description: "SceneFZ is a ratioless ROMANIAN Private Torrent Tracker for MOVIES / TV / GENERAL",
+ link: "https://scenefz.me/",
+ caps: new TorznabCapabilities
+ {
+ SupportsImdbMovieSearch = true
+ // SupportsImdbTVSearch = true (supported by the site but disabled due to #8107)
+ },
+ configService: configService,
+ client: wc,
+ logger: l,
+ p: ps)
+ {
+ AddCategoryMapping(62, TorznabCatType.TV, "Cartoons");
+ AddCategoryMapping(3, TorznabCatType.TVAnime, "Anime/Hentai");
+ AddCategoryMapping(1, TorznabCatType.PC0day, "Appz");
+ AddCategoryMapping(9, TorznabCatType.TVDocumentary, "Documentary");
+ AddCategoryMapping(63, TorznabCatType.TVDocumentary, "Documentary-RO");
+ AddCategoryMapping(6, TorznabCatType.Books, "eBooks");
+ AddCategoryMapping(52, TorznabCatType.Console, "Games-Console");
+ AddCategoryMapping(11, TorznabCatType.PCGames, "Games-PC");
+ AddCategoryMapping(18, TorznabCatType.Other, "Images");
+ AddCategoryMapping(65, TorznabCatType.Other, "Tutorial");
+ AddCategoryMapping(14, TorznabCatType.PC, "Linux");
+ AddCategoryMapping(37, TorznabCatType.PCMac, "Mac");
+ AddCategoryMapping(19, TorznabCatType.PCPhoneOther, "Mobile");
+ AddCategoryMapping(17, TorznabCatType.MoviesBluRay, "Movies-BluRay");
+ AddCategoryMapping(24, TorznabCatType.MoviesBluRay, "Movies-BluRayRO");
+ AddCategoryMapping(7, TorznabCatType.MoviesDVD, "Movies-DVD");
+ AddCategoryMapping(2, TorznabCatType.MoviesDVD, "Movies-DVD-RO");
+ AddCategoryMapping(8, TorznabCatType.MoviesHD, "Movies-HD");
+ AddCategoryMapping(29, TorznabCatType.MoviesHD, "Movies-HD-RO");
+ AddCategoryMapping(59, TorznabCatType.MoviesForeign, "Movies-RO");
+ AddCategoryMapping(57, TorznabCatType.MoviesUHD, "Movies-UHD-RO");
+ AddCategoryMapping(61, TorznabCatType.MoviesUHD, "Movies-UHD");
+ AddCategoryMapping(38, TorznabCatType.Movies, "Movies-Packs");
+ AddCategoryMapping(10, TorznabCatType.MoviesSD, "Movies-SD");
+ AddCategoryMapping(35, TorznabCatType.MoviesSD, "Movies-SD-RO");
+ AddCategoryMapping(5, TorznabCatType.Audio, "Music");
+ AddCategoryMapping(64, TorznabCatType.AudioVideo, "Music Videos");
+ AddCategoryMapping(22, TorznabCatType.TVSport, "Sport");
+ AddCategoryMapping(58, TorznabCatType.TVSport, "Sports-RO");
+ AddCategoryMapping(43, TorznabCatType.TVHD, "TV-HD");
+ AddCategoryMapping(44, TorznabCatType.TVHD, "TV-HD-RO");
+ AddCategoryMapping(41, TorznabCatType.TV, "TV-Packs");
+ AddCategoryMapping(45, TorznabCatType.TVSD, "TV-SD");
+ AddCategoryMapping(46, TorznabCatType.TVSD, "TV-SD-RO");
+ AddCategoryMapping(60, TorznabCatType.TVFOREIGN, "TV-RO");
+ AddCategoryMapping(66, TorznabCatType.TVFOREIGN, "TV-Packs-RO");
+ AddCategoryMapping(15, TorznabCatType.XXX, "XXX");
+ AddCategoryMapping(47, TorznabCatType.XXX, "XXX-DVD");
+ AddCategoryMapping(48, TorznabCatType.XXX, "XXX-HD");
+ AddCategoryMapping(49, TorznabCatType.XXXImageset, "XXX-IMGSet");
+ AddCategoryMapping(50, TorznabCatType.XXX, "XXX-Packs");
+ AddCategoryMapping(51, TorznabCatType.XXX, "XXX-SD");
+ }
+ }
+}
diff --git a/src/Jackett.Common/Indexers/XtremeZone.cs b/src/Jackett.Common/Indexers/XtremeZone.cs
new file mode 100644
index 000000000..fc1370f03
--- /dev/null
+++ b/src/Jackett.Common/Indexers/XtremeZone.cs
@@ -0,0 +1,78 @@
+using System.Diagnostics.CodeAnalysis;
+using Jackett.Common.Indexers.Abstract;
+using Jackett.Common.Models;
+using Jackett.Common.Services.Interfaces;
+using Jackett.Common.Utils.Clients;
+using NLog;
+
+namespace Jackett.Common.Indexers
+{
+ [ExcludeFromCodeCoverage]
+ public class XtremeZone : XtremeZoneTracker
+ {
+ public override string[] LegacySiteLinks { get; protected set; } = {
+ "https://www.myxz.eu/",
+ "https://www.myxz.org/"
+ };
+
+ public XtremeZone(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)
+ : base(
+ id: "xtremezone",
+ name: "Xtreme Zone",
+ description: "Xtreme Zone (MYXZ) is a ROMANIAN Private Torrent Tracker for MOVIES / TV / GENERAL",
+ link: "https://myxz.eu/",
+ caps: new TorznabCapabilities
+ {
+ SupportsImdbMovieSearch = true
+ // SupportsImdbTVSearch = true (supported by the site but disabled due to #8107)
+ },
+ configService: configService,
+ client: wc,
+ logger: l,
+ p: ps)
+ {
+ AddCategoryMapping(62, TorznabCatType.TV, "Cartoons");
+ AddCategoryMapping(3, TorznabCatType.TVAnime, "Anime/Hentai");
+ AddCategoryMapping(1, TorznabCatType.PC0day, "Appz");
+ AddCategoryMapping(9, TorznabCatType.TVDocumentary, "Documentary");
+ AddCategoryMapping(63, TorznabCatType.TVDocumentary, "Documentary-RO");
+ AddCategoryMapping(6, TorznabCatType.Books, "eBooks");
+ AddCategoryMapping(52, TorznabCatType.Console, "Games-Console");
+ AddCategoryMapping(11, TorznabCatType.PCGames, "Games-PC");
+ AddCategoryMapping(18, TorznabCatType.Other, "Images");
+ AddCategoryMapping(65, TorznabCatType.Other, "Tutorial");
+ AddCategoryMapping(14, TorznabCatType.PC, "Linux");
+ AddCategoryMapping(37, TorznabCatType.PCMac, "Mac");
+ AddCategoryMapping(19, TorznabCatType.PCPhoneOther, "Mobile");
+ AddCategoryMapping(17, TorznabCatType.MoviesBluRay, "Movies-BluRay");
+ AddCategoryMapping(24, TorznabCatType.MoviesBluRay, "Movies-BluRayRO");
+ AddCategoryMapping(7, TorznabCatType.MoviesDVD, "Movies-DVD");
+ AddCategoryMapping(2, TorznabCatType.MoviesDVD, "Movies-DVD-RO");
+ AddCategoryMapping(8, TorznabCatType.MoviesHD, "Movies-HD");
+ AddCategoryMapping(29, TorznabCatType.MoviesHD, "Movies-HD-RO");
+ AddCategoryMapping(59, TorznabCatType.MoviesForeign, "Movies-RO");
+ AddCategoryMapping(57, TorznabCatType.MoviesUHD, "Movies-UHD-RO");
+ AddCategoryMapping(61, TorznabCatType.MoviesUHD, "Movies-UHD");
+ AddCategoryMapping(38, TorznabCatType.Movies, "Movies-Packs");
+ AddCategoryMapping(10, TorznabCatType.MoviesSD, "Movies-SD");
+ AddCategoryMapping(35, TorznabCatType.MoviesSD, "Movies-SD-RO");
+ AddCategoryMapping(5, TorznabCatType.Audio, "Music");
+ AddCategoryMapping(64, TorznabCatType.AudioVideo, "Music Videos");
+ AddCategoryMapping(22, TorznabCatType.TVSport, "Sport");
+ AddCategoryMapping(58, TorznabCatType.TVSport, "Sports-RO");
+ AddCategoryMapping(43, TorznabCatType.TVHD, "TV-HD");
+ AddCategoryMapping(44, TorznabCatType.TVHD, "TV-HD-RO");
+ AddCategoryMapping(41, TorznabCatType.TV, "TV-Packs");
+ AddCategoryMapping(45, TorznabCatType.TVSD, "TV-SD");
+ AddCategoryMapping(46, TorznabCatType.TVSD, "TV-SD-RO");
+ AddCategoryMapping(60, TorznabCatType.TVFOREIGN, "TV-RO");
+ AddCategoryMapping(66, TorznabCatType.TVFOREIGN, "TV-Packs-RO");
+ AddCategoryMapping(15, TorznabCatType.XXX, "XXX");
+ AddCategoryMapping(47, TorznabCatType.XXX, "XXX-DVD");
+ AddCategoryMapping(48, TorznabCatType.XXX, "XXX-HD");
+ AddCategoryMapping(49, TorznabCatType.XXXImageset, "XXX-IMGSet");
+ AddCategoryMapping(50, TorznabCatType.XXX, "XXX-Packs");
+ AddCategoryMapping(51, TorznabCatType.XXX, "XXX-SD");
+ }
+ }
+}
diff --git a/src/Jackett.Updater/Program.cs b/src/Jackett.Updater/Program.cs
index 8db9575a4..a9269c63d 100644
--- a/src/Jackett.Updater/Program.cs
+++ b/src/Jackett.Updater/Program.cs
@@ -322,6 +322,7 @@ namespace Jackett.Updater
"Definitions/hon3yhd-net.yml",
"Definitions/horriblesubs.yml",
"Definitions/hyperay.yml",
+ "Definitions/icetorrent.yml", // migrated to C# XtremeZone base tracker
"Definitions/idopeclone.yml",
"Definitions/iloveclassics.yml",
"Definitions/infinityt.yml",
@@ -352,6 +353,7 @@ namespace Jackett.Updater
"Definitions/rns.yml", // site merged with audiobooktorrents
"Definitions/rockethd.yml",
"Definitions/rockhardlossless.yml",
+ "Definitions/scenefz.yml", // migrated to C# XtremeZone base tracker
"Definitions/scenehd.yml", // migrated to C# (use JSON API)
"Definitions/scenereactor.yml",
"Definitions/scenexpress.yml",
@@ -393,6 +395,7 @@ namespace Jackett.Updater
"Definitions/worldofp2p.yml",
"Definitions/worldwidetorrents.yml",
"Definitions/xktorrent.yml",
+ "Definitions/xtremezone.yml", // migrated to C# XtremeZone base tracker
"Definitions/yourexotic.yml", // renamed to exoticaz.yml
"Microsoft.Owin.dll",
"Microsoft.Owin.FileSystems.dll",