diff --git a/src/Jackett.Common/Definitions/partis.yml b/src/Jackett.Common/Definitions/partis.yml new file mode 100644 index 000000000..a9d1ea839 --- /dev/null +++ b/src/Jackett.Common/Definitions/partis.yml @@ -0,0 +1,168 @@ +--- +id: partis +name: Partis +description: "Partis is a Private SLOVENIAN Torrent Tracker for MOVIES / TV / BOOKS / GENERAL" +language: sl-SI +type: private +encoding: UTF-8 +links: + - https://www.partis.si/ + +caps: + categorymappings: + # Movies / Filmi + - {id: 7, cat: Movies, desc: "Xvid"} + - {id: 20, cat: Movies/HD, desc: "HD"} + - {id: 55, cat: Movies/UHD, desc: "UHD 4K Remux"} + - {id: 32, cat: Movies/UHD, desc: "UHD 4K Disc"} + - {id: 40, cat: Movies/BluRay, desc: "Blu-ray 1080p/i"} + - {id: 41, cat: Movies/3D, desc: "Blu-ray 3D"} + - {id: 42, cat: Movies/BluRay, desc: "Blu-ray 720p/i"} + - {id: 43, cat: Movies/BluRay, desc: "Blu-ray B-Disc"} + - {id: 44, cat: Movies/BluRay, desc: "Blu-ray Remux"} + - {id: 45, cat: Movies/BluRay, desc: "Blu-ray"} + - {id: 4, cat: Movies/DVD, desc: "DVD-R"} + - {id: 54, cat: Movies/WEB-DL, desc: "WEBRip"} + - {id: 59, cat: Movies/WEB-DL, desc: "WEB-DL"} + - {id: 30, cat: Movies/Other, desc: "Risanke"} + # TV + - {id: 17, cat: TV/HD, desc: "HD-TV"} + - {id: 31, cat: TV/HD, desc: "HD-TV"} + - {id: 38, cat: TV/SD, desc: "SD-TV"} + - {id: 51, cat: TV/HD, desc: "TV 1080p/i"} + - {id: 52, cat: TV/SD, desc: "TV 720p/i"} + - {id: 53, cat: TV/WEB-DL, desc: "TV WEB-DL"} + - {id: 5, cat: TV/Sport, desc: "Sport"} + - {id: 2, cat: TV/Anime, desc: "Anime"} + - {id: 24, cat: TV/Documentary, desc: "Dokumentarci"} + # Games / Igre + - {id: 10, cat: PC/Games, desc: "PC igre/ISO"} + - {id: 11, cat: PC/Games, desc: "PC igre/Rips/Repack"} + - {id: 13, cat: Console, desc: "PS2"} + - {id: 12, cat: Console/PSP, desc: "PSP"} + - {id: 28, cat: Console/PS3, desc: "PS3"} + - {id: 63, cat: Console/PS4, desc: "PS4"} + - {id: 27, cat: Console/Wii, desc: "Wii"} + - {id: 14, cat: Console/XBox, desc: "XboX"} + - {id: 49, cat: PC/Games, desc: "Mac Igre"} + - {id: 48, cat: PC/Games, desc: "Linux Igre"} + - {id: 64, cat: PC/Games, desc: "PC igre/Update & Patch"} + # Music / Glasba + - {id: 8, cat: Audio, desc: "Glasba/Ostalo"} + - {id: 47, cat: Audio/MP3, desc: "Glasba/Mp3"} + - {id: 46, cat: Audio/Lossless, desc: "Glasba/Flac"} + - {id: 23, cat: Audio/Video, desc: "Videospoti"} + - {id: 22, cat: Audio/Video, desc: "Music DVD"} + # Programs / Programi + - {id: 15, cat: PC, desc: "PC programi/drugo"} + - {id: 16, cat: PC/ISO, desc: "PC programi/ISO"} + - {id: 58, cat: PC/Mac, desc: "Mac programi"} + - {id: 50, cat: PC, desc: "Linux programi"} + # XXX +# only works for exactly categories cat=18,36,35,37,56,39 in this order +# - {id: 18, cat: XXX, desc: "XXX-HD"} +# - {id: 36, cat: XXX/XviD, desc: "XXX-XviD"} +# - {id: 35, cat: XXX, desc: "XXX-Clip"} +# - {id: 37, cat: XXX, desc: "XXX 37"} +# - {id: 39, cat: XXX, desc: "XXX 39"} +# - {id: 56, cat: XXX, desc: "XXX 56"} + # Other / Ostalo + - {id: 3, cat: Books/EBook, desc: "eKnjige"} + - {id: 19, cat: Other, desc: "Slike"} + - {id: 21, cat: Audio/Audiobook, desc: "AudioBook"} + - {id: 9, cat: PC/Mobile-Other, desc: "GBA"} + - {id: 25, cat: PC/Mobile-Other, desc: "GSM/Igre"} + - {id: 26, cat: PC/Mobile-Android, desc: "PDA"} + - {id: 29, cat: PC/Mobile-iOS, desc: "Ipod"} + - {id: 61, cat: PC/Mobile-Other, desc: "GSM/Programi"} + - {id: 62, cat: PC/Mobile-Other, desc: "GSM/Ostalo"} + + modes: + search: [q] + tv-search: [q, season, ep] + movie-search: [q] + music-search: [q] + book-search: [q] + +settings: + - name: username + type: text + label: Username + - name: password + type: password + label: Password +# broken on website +# - name: freeleech +# type: checkbox +# label: Search freeleech only +# default: false + - name: sort + type: select + label: Sort results + default: " " + options: + " ": "Added descending" + "seeders ASC": "Seeders ascending" + "seeders DESC": "Seeders descending" + "leechers ASC": "Leechers ascending" + "leechers DESC": "Leechers descending" + "size ASC": "Size ascending" + "size DESC": "Size descending" + +login: + method: post + path: user/login + inputs: + user: "{{ .Config.username }}" + pass: "{{ .Config.password }}" + test: + path: torrent/search + +search: + paths: + - path: /torrent/search + inputs: + q: "{{ .Keywords }}" + cat: "{{ join .Categories \",\" }}" + order: "{{ if eq .Config.sort \" \" }}{{ else }}{{ .Config.sort }}{{ end }}" + preprocessingfilters: + # Extract torrent information from the json array that is part of the response and transform it into html form + - name: re_replace + args: ["\\[(\\d+),(\\d+),(\\d+),\"([^\"]+?)\",(\\d+),(\\d+),\"([^\"]+?)\",(\\d+),([\\d.]+?),\"([^\"]+?)\",\"([^\"]+?)\",\"([^\"]+?)\".*?\\],?", "$1$2$3$4$5$6$7$8$9$10$11$12"] + # Remove javascript and keep only ... + - name: re_replace + args: ["^.*?(.*<\\\/torrent>).*|.*", "$1"] + + rows: + selector: torrent + + fields: + category: + selector: torrent_category_id + title: + selector: title + _id: + selector: fid + details: + text: "{{ .Config.sitelink }}portal#torrent/{{ .Result._id }}" + download: + text: "{{ .Config.sitelink }}torrent/download/{{ .Result._id }}" + poster: + selector: poster + date: + selector: created_at + size: + selector: size + leechers: + selector: leechers + seeders: + selector: seeders + downloadvolumefactor: + text: 1 + uploadvolumefactor: + text: 1 + minimumratio: + text: 1.0 + description: + selector: short_description +# engine n/a diff --git a/src/Jackett.Common/Indexers/Partis.cs b/src/Jackett.Common/Indexers/Partis.cs deleted file mode 100644 index dd96e421e..000000000 --- a/src/Jackett.Common/Indexers/Partis.cs +++ /dev/null @@ -1,265 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Diagnostics.CodeAnalysis; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -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; -using Newtonsoft.Json.Linq; -using NLog; - -namespace Jackett.Common.Indexers -{ - [ExcludeFromCodeCoverage] - public class Partis : BaseWebIndexer - { - private string LoginUrl => SiteLink + "user/login/"; - private string SearchUrl => SiteLink + "torrent/search/"; - - private new ConfigurationDataBasicLogin configData - { - get => (ConfigurationDataBasicLogin)base.configData; - set => base.configData = value; - } - - public Partis(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps, - ICacheService cs) - : base(id: "partis", - name: "Partis", - description: "Partis is a SLOVENIAN Private Torrent Tracker", - link: "https://www.partis.si/", - caps: new TorznabCapabilities - { - TvSearchParams = new List - { - TvSearchParam.Q, TvSearchParam.Season, TvSearchParam.Ep - }, - MovieSearchParams = new List - { - MovieSearchParam.Q - }, - MusicSearchParams = new List - { - MusicSearchParam.Q - }, - BookSearchParams = new List - { - BookSearchParam.Q - } - }, - configService: configService, - client: wc, - logger: l, - p: ps, - cacheService: cs, - configData: new ConfigurationDataBasicLogin()) - { - Encoding = Encoding.UTF8; - Language = "sl-SL"; - Type = "private"; - - // Movies - AddCategoryMapping(40, TorznabCatType.MoviesHD, "Blu-ray 1080p/i"); - AddCategoryMapping(42, TorznabCatType.MoviesHD, "Blu-ray 720p/i"); - AddCategoryMapping(43, TorznabCatType.MoviesBluRay, "Blu-ray B-Disc"); - AddCategoryMapping(41, TorznabCatType.Movies3D, "Blu-ray 3D"); - AddCategoryMapping(44, TorznabCatType.MoviesHD, "Blu-ray Remux"); - AddCategoryMapping(45, TorznabCatType.MoviesBluRay, "Blu-ray Remux/Disc"); - AddCategoryMapping(32, TorznabCatType.MoviesBluRay, "UHD 4K Disc"); - AddCategoryMapping(55, TorznabCatType.MoviesUHD, "UHD 4K Remux"); - AddCategoryMapping(20, TorznabCatType.MoviesHD, "HD"); - AddCategoryMapping(4, TorznabCatType.MoviesDVD, "DVD-R"); - AddCategoryMapping(7, TorznabCatType.MoviesSD, "XviD"); - AddCategoryMapping(30, TorznabCatType.MoviesOther, "Risanke"); - AddCategoryMapping(54, TorznabCatType.MoviesWEBDL, "WEBRip"); - AddCategoryMapping(59, TorznabCatType.MoviesWEBDL, "WEB-DL"); - AddCategoryMapping(24, TorznabCatType.TVDocumentary, "Dokumentarci"); - - // TV - AddCategoryMapping(53, TorznabCatType.TVWEBDL, "TV WEB-DL"); - AddCategoryMapping(60, TorznabCatType.TVSD, "TV-XviD"); - AddCategoryMapping(38, TorznabCatType.TVSD, "SD-TV"); - AddCategoryMapping(17, TorznabCatType.TVHD, "HD-TV (1)"); - AddCategoryMapping(31, TorznabCatType.TVHD, "HD-TV (2)"); - AddCategoryMapping(51, TorznabCatType.TVHD, "TV 1080p/i"); - AddCategoryMapping(52, TorznabCatType.TVHD, "TV 720p/i"); - AddCategoryMapping(5, TorznabCatType.TVSport, "Sport"); - AddCategoryMapping(2, TorznabCatType.TVAnime, "Anime"); - - // Games - AddCategoryMapping(10, TorznabCatType.PCGames, "PC igre/ISO"); - AddCategoryMapping(11, TorznabCatType.PCGames, "PC igre/Rips/Repack"); - AddCategoryMapping(64, TorznabCatType.PCGames, "PC igre/Update & Patch"); - AddCategoryMapping(13, TorznabCatType.ConsolePSP, "PSP"); - AddCategoryMapping(12, TorznabCatType.ConsoleOther, "PS2"); - AddCategoryMapping(28, TorznabCatType.ConsolePS3, "PS3"); - AddCategoryMapping(63, TorznabCatType.ConsolePS4, "PS4"); - AddCategoryMapping(27, TorznabCatType.ConsoleWii, "Wii"); - AddCategoryMapping(14, TorznabCatType.ConsoleXBox, "XboX"); - AddCategoryMapping(49, TorznabCatType.PCGames, "Mac Igre"); - AddCategoryMapping(48, TorznabCatType.PCGames, "Linux Igre"); - - // Music - AddCategoryMapping(46, TorznabCatType.AudioLossless, "Glasba/Flac"); - AddCategoryMapping(8, TorznabCatType.AudioOther, "Glasba/Ostalo"); - AddCategoryMapping(47, TorznabCatType.AudioMP3, "Glasba/Mp3"); - AddCategoryMapping(22, TorznabCatType.AudioVideo, "Music DVD"); - AddCategoryMapping(23, TorznabCatType.AudioVideo, "Videospoti"); - - // Programs - AddCategoryMapping(15, TorznabCatType.PC, "PC programi/drugo"); - AddCategoryMapping(58, TorznabCatType.PCMac, "Mac Programi"); - AddCategoryMapping(16, TorznabCatType.PCISO, "PC programi/ISO"); - AddCategoryMapping(50, TorznabCatType.PC, "Linux programi"); - - // Other - AddCategoryMapping(21, TorznabCatType.AudioAudiobook, "AudioBook"); - AddCategoryMapping(3, TorznabCatType.BooksEBook, "eKnjige"); - AddCategoryMapping(19, TorznabCatType.Other, "Slike"); - AddCategoryMapping(9, TorznabCatType.ConsoleNDS, "GBA"); - AddCategoryMapping(25, TorznabCatType.PCMobileAndroid, "GSM/Igre"); - AddCategoryMapping(26, TorznabCatType.PCMobileAndroid, "PDA"); - AddCategoryMapping(61, TorznabCatType.PCMobileAndroid, "GSM/Programi"); - AddCategoryMapping(62, TorznabCatType.PCMobileAndroid, "GSM/Ostalo"); - AddCategoryMapping(29, TorznabCatType.PCMobileiOS, "iPOD"); - } - - public override async Task ApplyConfiguration(JToken configJson) - { - LoadValuesFromJson(configJson); - - var pairs = new Dictionary - { - { "user", configData.Username.Value }, - { "pass", configData.Password.Value } - }; - - var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, string.Empty, false, null, null, true); - await ConfigureIfOK(result.Cookies, result.ContentString != null && result.Cookies.Contains("udata"), () => - { - var errorMessage = "Login failed. Invalid username or password."; - throw new ExceptionWithConfigData(errorMessage, configData); - }); - return IndexerConfigurationStatus.RequiresTesting; - } - - protected override async Task> PerformQuery(TorznabQuery query) - { - var releases = new List(); //List of releases initialization - var searchString = query.GetQueryString(); //get search string from query - - WebResult results = null; - var queryCollection = new NameValueCollection(); - var catList = MapTorznabCapsToTrackers(query); // map categories from query to indexer specific - var categ = string.Join(",", catList); - - // create GET request - search URI - if (!string.IsNullOrEmpty(searchString)) - queryCollection.Add("q", searchString); - queryCollection.Add("cat", categ.TrimStart(',')); - - // concatenate base search url with query - var searchUrl = $"{SearchUrl}?{queryCollection.GetQueryString()}"; - - // add necessary headers - var header = new Dictionary - { - { "X-requested-with", "XMLHttpRequest" } - }; - - // get results and follow redirect - results = await RequestWithCookiesAsync(searchUrl, referer: SearchUrl, headers: header); - if (results.ContentString.Contains("Internal server error")) - throw new Exception("Partis is offline, returning an Internal server error"); - // parse results - try - { - // successful search returns javascript code containing 'data' variable with actual torrent descriptions. - // find this variable and extract its value - var resultDataJson = Regex.Match(results.ContentString, @"data( |=)*(?\{.*\})").Groups["json"]; - - var resultsData = JsonConvert.DeserializeObject(resultDataJson.Value); - - foreach (var torrent in resultsData.sets.torrent_list.data) - { - var release = ParseRelease(torrent); - if (release != null) - releases.Add(release); - } - } - catch (Exception ex) - { - OnParseError(results.ContentString, ex); - } - - return releases; - } - - private ReleaseInfo ParseRelease(dynamic torrent) - { - /* Single torrent is represented with array: - [ - 600934, -- id - 4571, -- ? - 1636450141, -- added timestamp - "No.Time.To.Die.2021.ENGSubs.REPACK.HDRip.", -- title (max 41 chars) - 677, -- leechers - 30, -- seeders - "NI ČAS ZA SMRT/ NOVI JAMES BOND | Akcijski | HDRip...", -- description - 7, -- category - 54.9014462385559, -- health? scaled 0-100 - "1.7 GB", -- size - "/img/ics/xvid.gif", -- icon - "/torrent/image/600/600934/coverflow/james-bond.jpg" -- thumbnail - ] - */ - try - { - // initialize ReleaseInfo - var release = new ReleaseInfo - { - MinimumRatio = 1, - MinimumSeedTime = 0, - // Get Category - Category = MapTrackerCatToNewznab(torrent[7].ToString()), - // Title, description and details link - Title = torrent[3].ToString(), - Description = torrent[6].ToString(), - Details = new Uri($"{SiteLink}index.html#torrent/{torrent[0]}") - }; - release.Guid = release.Details; - - // Date of torrent creation - release.PublishDate = DateTimeUtil.UnixTimestampToDateTime((long)torrent[2]); - - // Download link - release.Link = new Uri($"{SiteLink}torrent/download/{torrent[0]}"); - - // Various data - size, seeders, leechers, download count - release.Size = ReleaseInfo.GetBytes(torrent[9].ToString()); - release.Seeders = ParseUtil.CoerceInt(torrent[4].ToString()); - release.Peers = ParseUtil.CoerceInt(torrent[5].ToString()) + release.Seeders; - - // Poster - release.Poster = new Uri($"{SiteLink}{torrent[11]}"); - - // // Set download/upload factor - release.DownloadVolumeFactor = 1; //No way to determine if torrent is freeleech from single request. - release.UploadVolumeFactor = 1; - - return release; - } - catch (Exception ex) - { - logger.Error(string.Format("{0}: Error while parsing torrent '{1}':\n\n{2}", Id, torrent, ex)); - return null; - } - } - } -}