diff --git a/src/Jackett.Common/Definitions/fuzer.yml b/src/Jackett.Common/Definitions/fuzer.yml
new file mode 100644
index 000000000..b26701c48
--- /dev/null
+++ b/src/Jackett.Common/Definitions/fuzer.yml
@@ -0,0 +1,181 @@
+---
+id: fuzer
+name: Fuzer
+description: "Fuzer is a private torrent website with israeli torrents."
+language: he-IL
+type: private
+encoding: windows-1255
+links:
+ - https://www.fuzer.me/
+legacylinks:
+ - https://fuzer.me/
+
+caps:
+ categorymappings:
+ # Movies
+ - {id: 73, cat: Movies, desc: "סרטים"}
+ - {id: 7, cat: Movies/SD, desc: "סרטים"}
+ - {id: 60, cat: Movies/SD, desc: "סרטים ישראליים"}
+ - {id: 9, cat: Movies/HD, desc: "סרטים HD"}
+ - {id: 101, cat: Movies/HD, desc: "סרטים x265"}
+ - {id: 59, cat: Movies/HD, desc: "סרטי BDRIP-BRRip"}
+ - {id: 61, cat: Movies/HD, desc: "סרטים ישראליים HD"}
+ - {id: 97, cat: Movies/UHD, desc: "סרטים UHD"}
+ - {id: 58, cat: Movies/DVD, desc: "סרטים DVD-R"}
+ - {id: 83, cat: Movies/Other, desc: "סרטים מדובבים"}
+ # TV
+ - {id: 76, cat: TV, desc: "סדרות"}
+ - {id: 8, cat: TV/SD, desc: "סדרות"}
+ - {id: 62, cat: TV/SD, desc: "סדרות ישראליות"}
+ - {id: 10, cat: TV/HD, desc: "Tסדרות HD"}
+ - {id: 63, cat: TV/HD, desc: "סדרות ישראליות HD"}
+ - {id: 100, cat: TV/UHD, desc: "סדרות UHD"}
+ - {id: 84, cat: TV/Other, desc: "סדרות מדובבות"}
+ - {id: 65, cat: TV/Anime, desc: "אנימה"}
+ - {id: 64, cat: TV/Sport, desc: "ספורט"}
+ # PC
+ - {id: 74, cat: PC, desc: "תוכנות"}
+ - {id: 15, cat: PC/0day, desc: "תוכנות PC"}
+ - {id: 11, cat: PC/Games, desc: "משחקים PC"}
+ - {id: 13, cat: PC/Mobile-Android, desc: "אפליקציות לאנדרואיד"}
+ - {id: 70, cat: PC/Mobile-iOS, desc: "אפליקציות לאייפון"}
+ - {id: 71, cat: PC/Mac, desc: "תוכנות MAC"}
+ # XXX
+ - {id: 16, cat: XXX, desc: "למבוגרים בלבד"}
+ # Games
+ - {id: 72, cat: Console, desc: "משחקים"}
+ - {id: 55, cat: Console/XBox, desc: "משחקים XBOX"}
+ - {id: 12, cat: Console/PSP, desc: "משחקים PS"}
+ - {id: 56, cat: Console/Wii, desc: "משחקים WII"}
+ - {id: 57, cat: PC/Mobile-Other, desc: "משחקי קונסולות ניידות"}
+ # Music
+ - {id: 75, cat: Audio, desc: "שירים"}
+ - {id: 14, cat: Audio, desc: "מוזיקה עולמית"}
+ - {id: 66, cat: Audio, desc: "מוזיקה ישראלית"}
+ - {id: 68, cat: Audio, desc: "פסקולים"}
+ - {id: 67, cat: Audio/Lossless, desc: "FLAC"}
+ # Books
+ - {id: 69, cat: Books, desc: "Ebooks"}
+ # Other
+ - {id: 17, cat: Other, desc: "שונות"}
+
+ modes:
+ search: [q]
+ tv-search: [q, season, ep, imdbid]
+ movie-search: [q, imdbid]
+ music-search: [q]
+ book-search: [q]
+
+settings:
+ - name: cookie
+ type: text
+ label: Cookie
+ - name: info
+ type: info
+ label: How to get the Cookie
+ default: "
- Login to this tracker with your browser
- Open the DevTools panel by pressing F12
- Select the Network tab
- Click on the Doc button (Chrome Browser) or HTML button (FireFox)
- Refresh the page by pressing F5
- Click on the first row entry
- Select the Headers tab on the Right panel
- Find 'cookie:' in the Request Headers section
- Select and Copy the whole cookie string (everything after 'cookie: ') and Paste here.
"
+ - name: freeleech
+ type: checkbox
+ label: Search freeleech only
+ default: false
+ - name: sort
+ type: select
+ label: Sort requested from site
+ default: dateadded
+ options:
+ dateadded: created
+ seeders: seeders
+ size: size
+ name: title
+ - name: type
+ type: select
+ label: Order requested from site
+ default: desc
+ options:
+ desc: desc
+ asc: asc
+
+login:
+ method: cookie
+ inputs:
+ cookie: "{{ .Config.cookie }}"
+ test:
+ path: browse.php
+
+search:
+ paths:
+ - path: browse.php
+ inputs:
+ query: "{{ if .Query.IMDBID }}{{ .Query.IMDBID }}{{ else }}{{ .Keywords }}{{ end }}"
+ order: "{{ .Config.sort }}"
+ sort: "{{ .Config.type }}"
+ matchquery: any
+ freeleech: "{{ if .Config.freeleech }}1{{ else }}0{{ end }}"
+ # on, off, only_dead
+ dead: on
+ $raw: "{{ range .Categories }}c[]={{.}}&{{end}}"
+
+ rows:
+ selector: .box_torrent
+
+ fields:
+ category:
+ selector: a[href^="/browse.php?cat="]
+ attribute: href
+ filters:
+ - name: querystring
+ args: cat
+ title:
+ selector: .main_title
+ details:
+ selector: a[href^="/showthread.php?t="]
+ attribute: href
+ download:
+ selector: a[href^="/attachment.php?attachmentid="]
+ attribute: href
+ imdbid:
+ selector: span.imdb-inline > a
+ attribute: href
+ poster:
+ selector: a[imgsrc]
+ attribute: imgsrc
+ size:
+ selector: td:nth-child(4)
+ grabs:
+ selector: td:nth-child(5)
+ filters:
+ - name: replace
+ args: [",", ""]
+ seeders:
+ selector: td:nth-child(6)
+ filters:
+ - name: replace
+ args: [",", ""]
+ leechers:
+ selector: td:nth-child(7)
+ filters:
+ - name: replace
+ args: [",", ""]
+ date:
+ selector: .up_info2
+ filters:
+ - name: append
+ args: " +02:00" # EET
+ - name: re_replace
+ args: ["[^:]+: ", ""]
+ - name: dateparse
+ args: "02/01/06 15:04 -07:00"
+ description:
+ selector: div.sub_title
+ downloadvolumefactor:
+ case:
+ a[href*="freeleech=1"]: 0
+ "*": 1
+ uploadvolumefactor:
+ text: 1
+ minimumratio:
+ text: 1.0
+ minimumseedtime:
+ # 2 days (as seconds = 2 x 24 x 60 x 60)
+ text: 172800
+# engine n/a
diff --git a/src/Jackett.Common/Indexers/Fuzer.cs b/src/Jackett.Common/Indexers/Fuzer.cs
deleted file mode 100644
index 325ff9c03..000000000
--- a/src/Jackett.Common/Indexers/Fuzer.cs
+++ /dev/null
@@ -1,269 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Collections.Specialized;
-using System.Diagnostics.CodeAnalysis;
-using System.Globalization;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using AngleSharp.Html.Parser;
-using Jackett.Common.Helpers;
-using Jackett.Common.Models;
-using Jackett.Common.Models.IndexerConfig;
-using Jackett.Common.Services.Interfaces;
-using Jackett.Common.Utils;
-using Jackett.Common.Utils.Clients;
-using Newtonsoft.Json.Linq;
-using NLog;
-
-namespace Jackett.Common.Indexers
-{
- [ExcludeFromCodeCoverage]
- public class Fuzer : BaseWebIndexer
- {
- public override string[] LegacySiteLinks { get; protected set; } =
- {
- "https://fuzer.me/"
- };
-
- private string SearchUrl => SiteLink + "browse.php";
-
- private new ConfigurationDataCookie configData => (ConfigurationDataCookie)base.configData;
-
- public Fuzer(IIndexerConfigurationService configService, WebClient w, Logger l, IProtectionService ps,
- ICacheService cs)
- : base(id: "fuzer",
- name: "Fuzer",
- description: "Fuzer is a private torrent website with israeli torrents.",
- link: "https://www.fuzer.me/",
- caps: new TorznabCapabilities
- {
- TvSearchParams = new List
- {
- TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep
- },
- MovieSearchParams = new List
- {
- MovieSearchParam.Q, MovieSearchParam.ImdbId
- },
- MusicSearchParams = new List
- {
- MusicSearchParam.Q
- },
- BookSearchParams = new List
- {
- BookSearchParam.Q
- }
- },
- configService: configService,
- client: w,
- logger: l,
- p: ps,
- cacheService: cs,
- configData: new ConfigurationDataCookie())
- {
- Encoding = Encoding.GetEncoding("windows-1255");
- Language = "he-IL";
- Type = "private";
-
- // סרטים
- AddCategoryMapping(7, TorznabCatType.MoviesSD, "סרטים");
- AddCategoryMapping(9, TorznabCatType.MoviesHD, "סרטים HD");
- AddCategoryMapping(97, TorznabCatType.MoviesUHD, "סרטים UHD");
- AddCategoryMapping(101, TorznabCatType.MoviesHD, "סרטים x265");
- AddCategoryMapping(58, TorznabCatType.MoviesDVD, "סרטים DVD-R");
- AddCategoryMapping(59, TorznabCatType.MoviesHD, "סרטי BDRIP-BRRip");
- AddCategoryMapping(60, TorznabCatType.MoviesSD, "סרטים ישראליים");
- AddCategoryMapping(61, TorznabCatType.MoviesHD, "סרטים ישראליים HD");
- AddCategoryMapping(83, TorznabCatType.MoviesOther, "סרטים מדובבים");
-
- // סדרות
- AddCategoryMapping(8, TorznabCatType.TVSD, "סדרות");
- AddCategoryMapping(10, TorznabCatType.TVHD, "סדרות HD");
- AddCategoryMapping(100, TorznabCatType.TVUHD, "סדרות UHD");
- AddCategoryMapping(62, TorznabCatType.TVSD, "סדרות ישראליות");
- AddCategoryMapping(63, TorznabCatType.TVHD, "סדרות ישראליות HD");
- AddCategoryMapping(84, TorznabCatType.TVOther, "סדרות מדובבות");
-
- // מוזיקה
- AddCategoryMapping(14, TorznabCatType.Audio, "מוזיקה עולמית");
- AddCategoryMapping(66, TorznabCatType.Audio, "מוזיקה ישראלית");
- AddCategoryMapping(67, TorznabCatType.AudioLossless, "FLAC");
- AddCategoryMapping(68, TorznabCatType.Audio, "פסקולים");
-
- // משחקים
- AddCategoryMapping(11, TorznabCatType.PCGames, "משחקים PC");
- AddCategoryMapping(12, TorznabCatType.ConsolePSP, "משחקים PS");
- AddCategoryMapping(55, TorznabCatType.ConsoleXBox, "משחקים XBOX");
- AddCategoryMapping(56, TorznabCatType.ConsoleWii, "משחקים WII");
- AddCategoryMapping(57, TorznabCatType.PCMobileOther, "משחקי קונסולות ניידות");
-
- // תוכנה
- AddCategoryMapping(13, TorznabCatType.PCMobileAndroid, "אפליקציות לאנדרואיד");
- AddCategoryMapping(15, TorznabCatType.PC0day, "תוכנות PC");
- AddCategoryMapping(70, TorznabCatType.PCMobileiOS, "אפליקציות לאייפון");
- AddCategoryMapping(71, TorznabCatType.PCMac, "תוכנות MAC");
-
- // שונות
- AddCategoryMapping(16, TorznabCatType.XXX, "למבוגרים בלבד");
- AddCategoryMapping(17, TorznabCatType.Other, "שונות");
- AddCategoryMapping(64, TorznabCatType.TVSport, "ספורט");
- AddCategoryMapping(65, TorznabCatType.TVAnime, "אנימה");
- AddCategoryMapping(69, TorznabCatType.Books, "Ebooks");
-
- // FuzePacks
- AddCategoryMapping(72, TorznabCatType.Console, "משחקים");
- AddCategoryMapping(73, TorznabCatType.Movies, "סרטים");
- AddCategoryMapping(74, TorznabCatType.PC, "תוכנות");
- AddCategoryMapping(75, TorznabCatType.Audio, "שירים");
- AddCategoryMapping(76, TorznabCatType.TV, "סדרות");
- }
-
- public override async Task ApplyConfiguration(JToken configJson)
- {
- LoadValuesFromJson(configJson);
-
- CookieHeader = configData.Cookie.Value;
- try
- {
- var results = await PerformQuery(new TorznabQuery());
- if (!results.Any())
- throw new Exception("Found 0 results in the tracker");
-
- IsConfigured = true;
- SaveConfig();
- return IndexerConfigurationStatus.Completed;
- }
- catch (Exception e)
- {
- IsConfigured = false;
- throw new Exception("Your cookie did not work: " + e.Message);
- }
- }
-
- protected override async Task> PerformQuery(TorznabQuery query)
- {
- var results = await PerformRegularQueryAsync(query);
- if (!results.Any() && !query.IsImdbQuery)
- return await PerformHebrewQueryAsync(query);
- return results;
- }
-
- private async Task> PerformHebrewQueryAsync(TorznabQuery query)
- {
- var name = await GetHebNameAsync(query.SearchTerm);
- if (string.IsNullOrEmpty(name))
- return new List();
- return await PerformRegularQueryAsync(query, name);
- }
-
- private async Task> PerformRegularQueryAsync(TorznabQuery query, string hebName = null)
- {
- var releases = new List();
- var searchUrl = SearchUrl;
- var searchString = query.GetQueryString();
- if (query.IsImdbQuery)
- searchString = query.ImdbID;
- if (hebName != null)
- searchString = hebName + " - עונה " + query.Season + " פרק " + query.Episode;
- searchUrl += "?";
- if (!string.IsNullOrWhiteSpace(searchString))
- {
- var strEncoded = WebUtilityHelpers.UrlEncode(searchString, Encoding);
- searchUrl += "&query=" + strEncoded + "&matchquery=any";
- }
-
- searchUrl = MapTorznabCapsToTrackers(query).Aggregate(searchUrl, (current, cat) => $"{current}&c[]={cat}");
- var data = await RequestWithCookiesAndRetryAsync(searchUrl);
- try
- {
- var parser = new HtmlParser();
- var dom = parser.ParseDocument(data.ContentString);
- var rows = dom.QuerySelectorAll("tr.box_torrent");
- foreach (var row in rows)
- {
- var release = new ReleaseInfo();
- var mainTitleLink = row.QuerySelector("div.main_title > a");
- release.Title = mainTitleLink.GetAttribute("longtitle");
- if (string.IsNullOrWhiteSpace(release.Title))
- release.Title = mainTitleLink.TextContent;
- release.MinimumRatio = 1;
- release.MinimumSeedTime = 172800; // 48 hours
- release.Grabs = ParseUtil.CoerceLong(row.QuerySelector("td:nth-child(5)").TextContent.Replace(",", ""));
- release.Seeders = ParseUtil.CoerceInt(row.QuerySelector("td:nth-child(6)").TextContent.Replace(",", ""));
- release.Peers = ParseUtil.CoerceInt(row.QuerySelector("td:nth-child(7)").TextContent.Replace(",", "")) +
- release.Seeders;
- var fullSize = row.QuerySelector("td:nth-child(4)").TextContent;
- release.Size = ReleaseInfo.GetBytes(fullSize);
- release.Details = new Uri(SiteLink + row.QuerySelector("a.threadlink[href]").GetAttribute("href"));
- release.Link = new Uri(SiteLink + row.QuerySelector("a:has(div.dlimg)").GetAttribute("href"));
- release.Guid = release.Details;
- //some releases have invalid poster URLs, ignore the posters in this case
- if (Uri.TryCreate(row.QuerySelector("a[imgsrc]").GetAttribute("imgsrc"),
- UriKind.Absolute, out var poster))
- release.Poster = poster;
- var dateStringAll = row.QuerySelector("div.up_info2").ChildNodes.Last().TextContent;
- var dateParts = dateStringAll.Split(' ');
- var dateString = dateParts[dateParts.Length - 2] + " " + dateParts[dateParts.Length - 1];
- release.PublishDate = DateTime.ParseExact(dateString, "dd/MM/yy HH:mm", CultureInfo.InvariantCulture);
- var categoryLink = row.QuerySelector("a[href^=\"/browse.php?cat=\"]").GetAttribute("href");
- var catid = ParseUtil.GetArgumentFromQueryString(categoryLink, "cat");
- release.Category = MapTrackerCatToNewznab(catid);
- if (row.QuerySelector("a[href^=\"?freeleech=1\"]") != null)
- release.DownloadVolumeFactor = 0;
- else
- release.DownloadVolumeFactor = 1;
- release.UploadVolumeFactor = 1;
- var subTitle = row.QuerySelector("div.sub_title");
- var imdbLink = subTitle.QuerySelector("span.imdb-inline > a");
- if (imdbLink != null)
- release.Imdb = ParseUtil.GetLongFromString(imdbLink.GetAttribute("href"));
- release.Description = subTitle.FirstChild.TextContent;
- releases.Add(release);
- }
- }
- catch (Exception ex)
- {
- OnParseError(data.ContentString, ex);
- }
-
- return releases;
- }
-
- private async Task GetHebNameAsync(string searchTerm)
- {
- var queryString = new NameValueCollection
- {
- {"searchseriesid", ""},
- {"tab", "listseries"},
- {"function", "Search"},
- {"string", searchTerm} // eretz + nehedert
- };
- var site = new UriBuilder
- {
- Scheme = "http",
- Host = "thetvdb.com",
- Path = "index.php",
- Query = queryString.GetQueryString()
- };
- var results = await RequestWithCookiesAsync(site.ToString());
- var parser = new HtmlParser();
- var dom = parser.ParseDocument(results.ContentString);
- var rows = dom.QuerySelectorAll("#listtable > tbody > tr");
- foreach (var row in rows.Skip(1))
- {
- var link = row.QuerySelector("td:nth-child(1) > a");
- if (string.Equals(link.TextContent.Trim(), searchTerm.Trim(), StringComparison.CurrentCultureIgnoreCase))
- {
- var address = link.GetAttribute("href");
- if (string.IsNullOrEmpty(address))
- continue;
- var realDom = parser.ParseDocument(results.ContentString);
- return realDom.QuerySelector("#content:nth-child(1) > h1").TextContent;
- }
- }
-
- return string.Empty;
- }
- }
-}