Compare commits

..

90 Commits

Author SHA1 Message Date
kaso17
657bb15282 CleanTitle: remove brackets 2016-12-30 17:12:32 +01:00
kaso17
069c64f504 TorrentBD: fix comments field 2016-12-30 16:39:48 +01:00
kaso17
65c1aed251 Add CHBits tracker 2016-12-30 15:20:11 +01:00
kaso17
e8e4289b20 Hounddawgs: fix category handling 2016-12-30 14:10:33 +01:00
Frederik Nielsen
0838a0b258 Add movie categories to HoundDawgs (#902) 2016-12-30 13:50:04 +01:00
kaso17
8e8f143b02 Torrentech: Add compatibility for all themes 2016-12-30 13:39:56 +01:00
kaso17
2e56f662cd Shareisland: fix date parsing 2016-12-29 19:56:52 +01:00
kaso17
440d59a30e Add Torrentech indexer 2016-12-29 19:56:35 +01:00
kaso17
286ef8396a Make FuzzyTime date format selectable 2016-12-29 19:56:18 +01:00
kaso17
772df7a4c1 x264: no longer have to set PublishDate 2016-12-29 15:54:27 +01:00
kaso17
134fd3f4cf Torznap feed: always set pubDate 2016-12-29 15:51:08 +01:00
kaso17
ae8f8f7ccd BitHQ: fix definition 2016-12-29 15:47:39 +01:00
kaso17
f8637051fa PotatoController: set freeleech correctly 2016-12-29 15:47:16 +01:00
kaso17
eb0e82494c Add BitHQ tracker 2016-12-29 15:31:12 +01:00
kaso17
265b949de9 SceneFZ: Fix category parsing for parent categories 2016-12-29 14:39:48 +01:00
kaso17
34acbed7f0 Bit-City Reloaded: cleanup 2016-12-29 12:47:58 +01:00
kaso17
42eb68ba76 Bit-City Reloaded: fix category mapping 2016-12-29 12:39:42 +01:00
kaso17
37591c6da6 MySpleen: add global freeleech check 2016-12-29 12:35:05 +01:00
kaso17
f5a8ad61b9 FANO/New Retro/Secret Cinema/Shareisland/Horror Charnel/Shinning/TSpate/WorldOfP2P: use andmatch filter 2016-12-29 12:21:46 +01:00
kaso17
e064fd8ccd Add support for andmatch Rows filter 2016-12-29 12:19:49 +01:00
kaso17
8a9949ac93 MatchQueryStringAND: add support for character limit 2016-12-29 12:19:25 +01:00
kaso17
40dde036d6 Torrent Syndikat: remove articles from search 2016-12-29 12:15:17 +01:00
kaso17
171205bdee TorrentLeech: Update categories 2016-12-29 12:14:35 +01:00
kaso17
03e0c6d67e TorrentLeech: use AND filter 2016-12-29 12:01:42 +01:00
kaso17
91500c95e6 Secret Cinema: Exclude Secret Pills from search results 2016-12-29 11:36:57 +01:00
kaso17
8a082b0668 Remove FunFile definition (use C# implementation) 2016-12-29 11:07:45 +01:00
kaso17
650b6986f9 TranceTraffic: fix selector for single page search results 2016-12-28 06:56:23 +01:00
kaso17
82fd53226c Add TranceTraffic tracker 2016-12-27 19:13:01 +01:00
kaso17
77fd3e206b Cardigann: improve exception readability 2016-12-27 19:07:32 +01:00
kaso17
3989f35827 Cardigann: Don't use any default cats 2016-12-27 19:06:37 +01:00
kaso17
82376a508a RapideTracker: add details link 2016-12-27 17:09:05 +01:00
kaso17
4f9ce14e2f TorrentSyndikat: use long title 2016-12-26 15:52:26 +01:00
kaso17
60a2ffbe41 TorrentSyndikat: Add global freeleech check 2016-12-26 15:50:08 +01:00
kaso17
15598e3d66 Andraste: Add global freeleech check 2016-12-24 13:12:36 +01:00
kaso17
357be7dda9 HDClub: fix links+login 2016-12-24 08:17:27 +01:00
kaso17
a0aa77519b Add HDClub tracker 2016-12-23 17:35:30 +01:00
kaso17
f3ef590d3f Cardigann: Add support for image captchas 2016-12-23 17:18:37 +01:00
kaso17
d347ea71b8 Abnormal: attempt to fix parsing 2016-12-23 14:57:00 +01:00
kaso17
62f0bdc19c Add RapideTracker tracker 2016-12-23 14:56:31 +01:00
kaso17
e92b925eab Add FANO.IN tracker 2016-12-21 18:18:25 +01:00
kaso17
e8239f4899 IPTorrents: use encoding during login 2016-12-21 17:32:24 +01:00
kaso17
5c855d3b50 HD-Torrents: Allow alternative URLs 2016-12-20 19:45:57 +01:00
kaso17
6dfaff6aad Torrent.Md: remove description 2016-12-20 19:44:24 +01:00
kaso17
849b9e9765 Add Torrents.Md tracker 2016-12-20 19:43:08 +01:00
kaso17
eacfd53466 Add u-Torrent tracker 2016-12-20 13:20:12 +01:00
kaso17
4459697fe5 Cardigann: Don't use empty banner URLs 2016-12-20 13:18:48 +01:00
kaso17
94872affa9 Add DataScene tracker 2016-12-20 12:39:57 +01:00
kaso17
a29064e7fb Add imdb/banner/description to cached results view 2016-12-20 12:07:43 +01:00
kaso17
679cba4297 Avoid line wraps in the size column 2016-12-20 12:05:53 +01:00
kaso17
f155a21ee8 Add banner/description tooltip 2016-12-20 11:50:04 +01:00
kaso17
0913ee4934 Xtreme Zone: add banner 2016-12-20 11:48:53 +01:00
kaso17
1fa0384eb8 Add IMDB label 2016-12-20 10:01:53 +01:00
kaso17
59727fe8fc Xtreme Zone: Fix description 2016-12-20 09:40:08 +01:00
kaso17
28707fa146 ICE Torrent: fix seedersm, leechers, description imdb and add banner 2016-12-20 09:39:53 +01:00
kaso17
f408abe7a4 Cardigann: Add support for minimumratio/minimumseedtime/rageid/tvdbid/banner fields 2016-12-20 09:38:01 +01:00
kaso17
42434c35a1 Add Xtreme Zone tracker 2016-12-19 20:57:38 +01:00
kaso17
df941c54ce IPTorrents: change default URL 2016-12-19 20:25:18 +01:00
kaso17
f2eb4dacd0 ICE Torrent: Fix timezone and add details link 2016-12-19 20:24:58 +01:00
kaso17
9795587e4d Add ICE Torrent tracker 2016-12-19 19:51:54 +01:00
kaso17
15064810f8 Add TorViet tracker 2016-12-18 15:32:46 +01:00
kaso17
fbfee66c7b Shareisland: replace special characters with wildcards 2016-12-18 12:21:53 +01:00
kaso17
53e2d9e9cd Cardigann: Add support for re_replace template function
Example: {{ re_replace .Query.Keywords "[^a-zA-Z0-9]+" "%" }}
2016-12-18 12:20:33 +01:00
kaso17
49fd078a4c Add nostream tracker 2016-12-18 11:46:29 +01:00
kaso17
3dfba7c204 Add notwhat.cd tracker 2016-12-18 11:36:11 +01:00
kaso17
0e59621650 Add QcTorrent tracker 2016-12-17 17:33:34 +01:00
kaso17
c2f4cc97ab Add PassTheHeadphones tracker 2016-12-17 16:49:52 +01:00
kaso17
5fc7fca5c6 CategoryMapping: Add support for the tracker category description 2016-12-17 16:42:50 +01:00
kaso17
7b2dd93f2f TVChaosUK: relogin if necessary 2016-12-17 13:57:40 +01:00
kaso17
a8ddf21081 TVChaosUK: test RSS and scrape search 2016-12-17 13:39:52 +01:00
kaso17
7db50dba49 AlphaReign: Fix category selectors 2016-12-17 13:32:54 +01:00
kaso17
9d30f833da TorrentLeech: Fix date selector 2016-12-17 13:24:57 +01:00
kaso17
bf959f1c29 Apollo: Add uppercase global freeleech selector 2016-12-15 09:52:03 +01:00
kaso17
1cde5c5142 Add Gormogon tracker 2016-12-15 09:32:11 +01:00
kaso17
58a7de145a Cardigann: Add support for non-direct download links 2016-12-15 09:12:28 +01:00
kaso17
9a66289a26 Add more debug output on Download error 2016-12-15 06:56:41 +01:00
kaso17
6201712ce9 HD Torrents: add support for NO RATIO label 2016-12-14 08:55:05 +01:00
kaso17
f921df948c House of Torrents: reset cookies on login 2016-12-14 08:45:40 +01:00
kaso17
059701fbf6 Cardigann: fix re-login caching issue for login method=form indexers 2016-12-14 08:44:56 +01:00
kaso17
addf98e9a3 TorrentDay: change default url back to torrentday.it 2016-12-12 08:34:06 +01:00
kaso17
f124b7e30b TorrentLeech: avoid unnecessary login checks 2016-12-12 08:24:18 +01:00
kaso17
0fc2a3083c TorrentLeech: Fix login parameters/error parsing 2016-12-12 08:16:46 +01:00
kaso17
01141b8cc1 NetHD: fix rows selector 2016-12-12 07:34:03 +01:00
kaso17
be542272d1 BitMeTV: include dead torrents 2016-12-12 07:21:30 +01:00
kaso17
2c4f18128a TorrentLeech: fix relogin detection 2016-12-12 06:48:55 +01:00
kaso17
adbd6c9d0d TorrentLeech: fix DL link 2016-12-11 16:41:02 +01:00
kaso17
a854771950 TorrentLeech: adjust to new design 2016-12-11 16:36:48 +01:00
kaso17
b4fafe2845 bB: normalize spaces in title 2016-12-11 16:12:47 +01:00
kaso17
1050157546 Curl: Fix Bad Request errors 2016-12-11 15:43:39 +01:00
kaso17
6f54958ec0 The Horror Charnel: fix rows selector 2016-12-11 06:18:32 +01:00
kaso17
a53fc1e8cb IWebClient: minor cleanup 2016-12-11 05:57:39 +01:00
64 changed files with 2737 additions and 216 deletions

View File

@@ -28,29 +28,36 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* BeyondHD
* Bit-City Reloaded
* BIT-HDTV
* BitHQ
* BitMeTV
* BitSoup
* Blu-bits
* BTN
* CHDBits
* CinemaZ
* DanishBits
* DataScene
* Demonoid
* DigitalHive
* EoT-Forum
* Ethor.net (Thor's Land)
* FANO.IN
* FileList
* Freaks Tracking System
* Freshon
* FunFile
* Fuzer
* Ghost City
* Gormogon
* HD4Free
* HD-Space
* HD-Torrents
* HDClub
* Hebits
* New Real World
* Hounddawgs
* House-of-Torrents
* ICE Torrent
* ILoveTorrents
* Immortalseed
* IPTorrents
@@ -62,10 +69,15 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* NetHD
* NextGen
* Norbits
* nostream
* notwhat.cd
* PassTheHeadphones
* PassThePopcorn
* PirateTheNet
* Pretome
* PrivateHD
* QcTorrent
* RapideTracker
* RevolutionTT
* SceneAccess
* SceneFZ
@@ -87,19 +99,23 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* TorrentDay
* TorrentHeaven
* TorrentLeech
* Torrents.Md
* TorrentShack
* Torrent-Syndikat
* ToTheGlory
* TranceTraffic
* TransmitheNet
* Tspate
* TV Chaos UK
* TV-Vault
* u-Torrent
* UHDBits
* World-In-HD
* WorldOfP2P
* x264
* XSpeeds
* Xthor
* Xtreme Zone
#### Installation on Windows

View File

@@ -227,8 +227,20 @@ pre {
display: none;
}
.table td.fit{
table td.fit{
white-space: nowrap;
width: 1%;
}
.label-imdb {
background-color: #d0ab44;
}
.tooltip-inner {
max-width: 500px !important;
}
.tooltip-inner img {
max-width: 250px;
height: auto;
}

View File

@@ -492,11 +492,33 @@ function clearNotifications() {
function updateReleasesRow(row)
{
var labels = $(row).find("span.release-labels");
var TitleLink = $(row).find("td.Title > a");
var IMDBId = $(row).data("imdb");
var Banner = $(row).data("banner");
var Description = $(row).data("description");
var DownloadVolumeFactor = parseFloat($(row).find("td.DownloadVolumeFactor").html());
var UploadVolumeFactor = parseFloat($(row).find("td.UploadVolumeFactor").html());
var TitleTooltip = "";
if (Banner)
TitleTooltip += "<img src='" + Banner + "' /><br />";
if (Description)
TitleTooltip += Description;
if (TitleTooltip) {
TitleLink.data("toggle", "tooltip");
TitleLink.tooltip({
title: TitleTooltip,
html: true
});
}
labels.empty();
if (IMDBId) {
labels.append('\n<a href="http://www.imdb.com/title/tt' + IMDBId + '/" class="label label-imdb" alt="IMDB" title="IMDB">IMDB</a>');
}
if (!isNaN(DownloadVolumeFactor)) {
if (DownloadVolumeFactor == 0) {
labels.append('\n<span class="label label-success">FREELEECH</span>');

View File

@@ -287,15 +287,15 @@
</thead>
<tbody>
{{#each releases}}
<tr class="jackett-releases-row">
<tr class="jackett-releases-row" data-imdb="{{Imdb}}" data-banner="{{BannerUrl}}" data-description="{{Description}}">
<td>{{PublishDate}}</td>
<td>{{FirstSeen}}</td>
<td>{{jacketTimespan PublishDate}}</td>
<td>{{jacketTimespan FirstSeen}}</td>
<td>{{Tracker}}</td>
<td><a href="{{Comments}}">{{Title}}</a> <span class="release-labels"></span></td>
<td class="Title"><a href="{{Comments}}">{{Title}}</a> <span class="release-labels"></span></td>
<td>{{Size}}</td>
<td>{{jacketSize Size}}</td>
<td class="fit">{{jacketSize Size}}</td>
<td>{{Files}}</td>
<td>{{CategoryDesc}}</td>
<td>{{Grabs}}</td>
@@ -400,13 +400,13 @@
</thead>
<tbody>
{{#each Results}}
<tr class="jackett-search-results-row">
<tr class="jackett-search-results-row" data-imdb="{{Imdb}}" data-banner="{{BannerUrl}}" data-description="{{Description}}">
<td>{{PublishDate}}</td>
<td>{{jacketTimespan PublishDate}}</td>
<td>{{Tracker}}</td>
<td><a href="{{Comments}}">{{Title}}</a> <span class="release-labels"></span></td>
<td class="Title"><a href="{{Comments}}">{{Title}}</a> <span class="release-labels"></span></td>
<td>{{Size}}</td>
<td>{{jacketSize Size}}</td>
<td class="fit">{{jacketSize Size}}</td>
<td>{{Files}}</td>
<td>{{CategoryDesc}}</td>
<td>{{Grabs}}</td>

View File

@@ -140,7 +140,7 @@ namespace Jackett.Controllers
details_url = release.Comments.ToString(),
download_url = release.Link.ToString(),
imdb_id = release.Imdb.HasValue ? "tt" + release.Imdb : null,
freeleech = false,
freeleech = (release.DownloadVolumeFactor == 0 ? true : false),
type = "movie",
size = (long)release.Size / (1024 * 1024), // This is in MB
leechers = (int)release.Peers - (int)release.Seeders,

View File

@@ -30,7 +30,7 @@ namespace Jackett
public CurlRequest(HttpMethod method, string url, string cookies = null, string referer = null, Dictionary<string, string> headers = null, string rawPOSTData = null)
{
Method = method;
Url = url;
Url = url.Replace(" ", "+"); // avoids bad request to cloudflare for urls containing a space followed by H (" H")
Cookies = cookies;
Referer = referer;
Headers = headers;

View File

@@ -71,12 +71,12 @@
"*": "1"
category:
case:
"span[class=\"label label-primary\"]:contains(\"video\") + span[class=\"label label-success\"]:contains(\"movie\") + span[class=\"label label-info\"]:contains(\"HD\")": "Movies/HD"
"span[class=\"label label-primary\"]:contains(\"video\") + span[class=\"label label-success\"]:contains(\"movie\") + span[class=\"label label-info\"]:contains(\"720p\")": "Movies/HD"
"span[class=\"label label-primary\"]:contains(\"video\") + span[class=\"label label-success\"]:contains(\"movie\") + span[class=\"label label-info\"]:contains(\"1080p\")": "Movies/HD"
"span[class=\"label label-primary\"]:contains(\"video\") + span[class=\"label label-success\"]:contains(\"movie\") + span[class=\"label label-info\"]:contains(\"SD\")": "Movies/SD"
"span[class=\"label label-primary\"]:contains(\"video\") + span[class=\"label label-success\"]:contains(\"movie\")": "Movies"
"span[class=\"label label-primary\"]:contains(\"video\") + span[class=\"label label-success\"]:contains(\"show\") + span[class=\"label label-info\"]:contains(\"HD\")": "TV/HD"
"span[class=\"label label-primary\"]:contains(\"video\") + span[class=\"label label-success\"]:contains(\"show\") + span[class=\"label label-info\"]:contains(\"SD\")": "TV/SD"
"span[class=\"label label-primary\"]:contains(\"video\") + span[class=\"label label-success\"]:contains(\"show\")": "TV"
"a[class=\"label label-primary\"]:contains(\"video\") + a[class=\"label label-success\"]:contains(\"movie\") + a[class=\"label label-info\"]:contains(\"HD\")": "Movies/HD"
"a[class=\"label label-primary\"]:contains(\"video\") + a[class=\"label label-success\"]:contains(\"movie\") + a[class=\"label label-info\"]:contains(\"720p\")": "Movies/HD"
"a[class=\"label label-primary\"]:contains(\"video\") + a[class=\"label label-success\"]:contains(\"movie\") + a[class=\"label label-info\"]:contains(\"1080p\")": "Movies/HD"
"a[class=\"label label-primary\"]:contains(\"video\") + a[class=\"label label-success\"]:contains(\"movie\") + a[class=\"label label-info\"]:contains(\"SD\")": "Movies/SD"
"a[class=\"label label-primary\"]:contains(\"video\") + a[class=\"label label-success\"]:contains(\"movie\")": "Movies"
"a[class=\"label label-primary\"]:contains(\"video\") + a[class=\"label label-success\"]:contains(\"show\") + a[class=\"label label-info\"]:contains(\"HD\")": "TV/HD"
"a[class=\"label label-primary\"]:contains(\"video\") + a[class=\"label label-success\"]:contains(\"show\") + a[class=\"label label-info\"]:contains(\"SD\")": "TV/SD"
"a[class=\"label label-primary\"]:contains(\"video\") + a[class=\"label label-success\"]:contains(\"show\")": "TV"
"*": "Other"

View File

@@ -87,6 +87,7 @@
downloadvolumefactor:
case:
":root div.alertbar:contains(\"freeleech\")": "0"
":root div.alertbar:contains(\"FREELEECH\")": "0"
"*": "1"
uploadvolumefactor:
case:

View File

@@ -0,0 +1,92 @@
---
site: bithq
name: BitHQ
language: en-us
encoding: windows-1252
links:
- http://www.bithq.org
caps:
categories:
7: Movies # Approved Film Series
81: TV/HD # BD-MKV
62: Audio # CD-R/OST
51: Movies/DVD # DVD-R/Animation
48: Movies/DVD # DVD-R/Asian Cinema
50: Movies/DVD # DVD-R/Documentaries
64: Movies/DVD # DVD-R/Foreign Films
55: Movies/DVD # DVD-R/Kids
49: Movies/DVD # DVD-R/Movies
52: Audio/Video # DVD-R/Music
53: TV # DVD-R/TV
70: Movies # Empire's 500
80: Movies # Global Lens | trigon-film
65: Other # Hi-Res Covers
66: Movies/HD # High Quality
57: Movies/SD # Low Quality
54: PC/0day # Software/DVD/BD
61: PC/0day # Software/System Utilities
69: TV/Sport # Sporting Events
68: Movies # The Criterion Collection
modes:
search: [q]
tv-search: [q, season, ep]
login:
path: takelogin.php
method: post
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
error:
- selector: td.embedded:has(h2:contains("failed"))
test:
path: browse.php
search:
path: browse.php
inputs:
$raw: "{{range .Categories}}c{{.}}=1&{{end}}"
search: "{{ .Query.Keywords }}"
incldead: 1
rows:
selector: td > table > tbody > tr:has(a[href^="details.php?id="])
fields:
download:
selector: a[href^="download.php/"]
attribute: href
title:
selector: a[href^="details.php?id="]
description:
selector: td:nth-child(2) > strong
details:
selector: a[href^="details.php?id="]
attribute: href
category:
selector: a[href^="browse.php?cat="]
attribute: href
filters:
- name: querystring
args: cat
seeders:
selector: td:nth-child(7)
leechers:
selector: td:nth-child(8)
grabs:
selector: td:nth-child(6)
filters:
- name: regexp
args: ([\d,]+)
files:
selector: td:nth-child(3)
size:
selector: td:nth-child(5)
downloadvolumefactor:
case:
tr[bgcolor="#FFF6CB"]: "0"
img[alt^="Goodie.. Download for free!"]: "0"
"*": "1"
uploadvolumefactor:
case:
"*": "1"

View File

@@ -0,0 +1,101 @@
---
site: chdbits
name: CHDBits
description: "A general tracker"
language: zh-cn
encoding: UTF-8
links:
- https://chdbits.co
caps:
categories:
401: Movies # Movies
404: TV/Documentary # Documentaries
405: TV/Anime # Animations
402: TV # TV Series
403: TV # TV Shows
406: Audio/Video # Music Videos
407: TV/Sport # Sports
409: Other # Misc
408: Audio # HQ Audio
modes:
search: [q]
tv-search: [q, season, ep]
login:
path: /takelogin.php
method: post
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
error:
- selector: td.embedded:has(h2:contains("failed"))
test:
path: /torrents.php
ratio:
path: /torrents.php
selector: table#info_block
filters:
- name: regexp
args: "Ratio:\\s(.*?)\\s\\s"
search:
path: /torrents.php
method: post
inputs:
$raw: "{{range .Categories}}cat{{.}}=1&{{end}}"
search: "{{ .Query.Keywords }}"
incldead: "1"
rows:
selector: table.torrents > tbody > tr:has(table.torrentname)
fields:
title:
selector: a[title][href^="details.php?id="]
attribute: title
category:
selector: a[href^="?cat="]
attribute: href
filters:
- name: querystring
args: cat
details:
selector: a[title][href^="details.php?id="]
attribute: href
download:
selector: a[href^="download.php?id="]
attribute: href
size:
selector: td:nth-child(5)
grabs:
selector: td:nth-child(8)
seeders:
selector: td:nth-child(6)
leechers:
selector: td:nth-child(7)
date:
selector: td:nth-child(4) > span[title]
attribute: title
filters:
- name: append
args: " +08:00"
- name: dateparse
args: "2006-01-02 15:04:05 -07:00"
downloadvolumefactor:
case:
img.pro_free: "0"
img.pro_free2up: "0"
img.pro_50pctdown: "0.5"
img.pro_50pctdown2up: "0.5"
img.pro_30pctdown: "0.3"
"*": "1"
uploadvolumefactor:
case:
img.pro_50pctdown2up: "2"
img.pro_free2up: "2"
img.pro_2up: "2"
"*": "1"
description:
selector: td:nth-child(2)
remove: a, img

View File

@@ -0,0 +1,118 @@
---
site: datascene
name: DataScene
language: ro-ro
encoding: windows-1252
links:
- http://datascene.net/
caps:
categories:
3: TV/Anime # Anime | Cartoon
15: PC/0day # Appz | Win
4: PC/0day # Appz | Linux
6: Books # E-Book
10: PC/Games # Games | PC Iso
9: PC/Games # Games | PC Rips
11: Console # Games | Pack
43: Console # Games | Console
29: Other # Images
2: Other # MiSC
5: PC/Phone-Other # Mobile
27: Movies # Movies | Pack
46: Movies/3D # Movies | 3D
26: Movies/SD # Movies | Cam
25: Movies # Movies | Documentary
24: Movies/DVD # Movies | DVD-R
32: Movies/DVD # Movies | DVD-RO
23: Movies/HD # Movies | HD
31: Movies/HD # Movies | HD-Ro
34: Movies/Foreign # Movies | Hindi
30: Movies/SD # Movies | Xvid
36: Movies/SD # Movies | Xvid-Ro
21: Audio/Video # Music | Video
19: Audio # Music | Mp3/Flac
18: Other # Other
42: Other # Premiera | DsT
14: TV/Sport # Sport
47: TV/SD # Tv | Episodes
28: TV/HD # Tv-HD | Episodes
13: Other # Tutoriale
12: XXX # XxX
modes:
search: [q]
tv-search: [q, season, ep]
login:
path: /takelogin.php
method: post
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
error:
- selector: td.embedded:has(h2:contains("failed"))
test:
path: /browse.php
ratio:
path: /browse.php
selector: font:contains("Ratio:") > span
search:
path: /browse.php
inputs:
$raw: "{{range .Categories}}c{{.}}=1&{{end}}"
search: "{{ .Query.Keywords }}"
incldead: 1
rows:
selector: tr:has(a.tname)
fields:
title:
selector: a.tname
attribute: title
details:
selector: a.tname
attribute: href
category:
selector: a[href^="browse.php?cat="]
attribute: href
filters:
- name: querystring
args: cat
download:
selector: a[href^="/download.php/"]
attribute: href
grabs:
selector: td:nth-child(7)
filters:
- name: regexp
args: (\d+)
size:
selector: td:nth-child(6)
date:
selector: td:nth-child(2) > right > div:has(font:contains("Uploaded"))
remove: div > font
filters:
- name: trim
args: ":"
seeders:
selector: td:nth-child(8)
leechers:
selector: td:nth-child(9)
banner:
selector: a.tname
attribute: onmouseover
filters:
- name: regexp
args: src=([^\s]+)
downloadvolumefactor:
case:
"img[src=\"pic/free.gif\"]": "0"
"*": "1"
uploadvolumefactor:
case:
"*": "1"
description:
selector: td:nth-child(2) > right
remove: div

View File

@@ -0,0 +1,129 @@
---
site: fanoin
name: FANO.IN
language: lv-lv
encoding: UTF-8
links:
- https://www.fano.in
caps:
categories:
20: Movies/SD # Movies/SD
6: TV/SD # TV/SD
7: PC/Games # Games/PC ISO
5: Audio # Music
47: Movies # Packs/Movies
44: Audio/Audiobook # A-Books
27: TV/Anime # Anime
17: Movies/Foreign # Movies/Rus
33: TV/Foreign # TV/Rus
12: PC/Games # Games/PC Rips
31: Audio/Lossless # Music/HQ
49: TV # Packs/TV
41: Books # E-Books
29: Books # Cartoons
24: Movies/Foreign # Movies/Lat
25: TV/Foreign # TV/Lat
34: Console/Xbox # Games/Xbox
19: Audio/Video # Music Videos
46: Console # Packs/Games
42: Other # Study
52: Movies/3D # 3D
37: Movies/HD # Movies/HD
35: TV/HD # TV/HD
43: Console/PS4 # Games/PS
38: PC/Phone-Other # Mobile
48: Audio # Packs/Music
36: Other # X-mas
53: Movies/SD # Movies/CAM
4: Movies/DVD # Movies/DVD-R
32: TV # TV/Facts
40: Console/Wii # Games/Wii
22: PC/0day # Appz/misc
50: XXX/Packs # Packs/XXX
9: XXX # XXX
45: XXX # XXX/HD
54: Movies # Movies/Retro
23: TV/Sport # TV/Sport
51: Console # Games/Misc
1: PC/0day # Appz/PC ISO
modes:
search: [q]
tv-search: [q, season, ep]
login:
path: takelogin.php
method: post
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
error:
- selector: td.embedded:has(h2:contains("failed"))
test:
path: browse_old.php
ratio:
path: browse_old.php
selector: img[title="Reitings:"]+font
search:
path: browse_old.php
inputs:
$raw: "{{range .Categories}}c{{.}}=1&{{end}}"
search: "{{ .Query.Keywords }}"
incldead: 1
rows:
selector: tr.browse_actions
filters:
- name: andmatch
fields:
title:
selector: a[href^="details.php?id="]
details:
selector: a[href^="details.php?id="]
attribute: href
category:
selector: a[href^="browse_old.php?cat="]
attribute: href
filters:
- name: querystring
args: cat
download:
selector: a[href^="details.php?id="]
attribute: href
filters:
- name: replace
args: ["details.php", "download.php"]
imdb:
selector: a[href^="http://www.imdb.com/title/"]
attribute: href
size:
selector: td:nth-child(5)
seeders:
selector: td:nth-child(7)
leechers:
selector: td:nth-child(8)
grabs:
selector: td:nth-child(6)
filters:
- name: regexp
args: (\d+)
date:
selector: td:nth-child(2) > small:nth-last-child(2)
filters:
- name: replace
args: ["Šodien", "Today"]
- name: replace
args: ["Vakar", "Yesterday"]
downloadvolumefactor:
case:
img[alt="Free"]: "0"
"*": "1"
uploadvolumefactor:
case:
img[alt="x2"]: "2"
"*": "1"
description:
selector: td:nth-child(2) > small:nth-last-child(1)
remove: a[href^="details.php?id="]

View File

@@ -1,80 +0,0 @@
---
site: funfile
name: FunFile
description: "A general tracker"
language: en-us
encoding: windows-1252
links:
- https://www.funfile.org/
caps:
categories:
44: TV/Anime # Anime
22: PC # Applications
43: Audio/Audiobook # Audio Books
27: Books # Ebook
4: PC/Games # Games
40: Other/Misc # Miscellaneous
19: Movies # Movies
6: Audio # Music
31: PC/Phone-Other # Portable
7: TV # TV
modes:
search: [q]
tv-search: [q, season, ep]
login:
path: /takelogin.php
method: post
form: form
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
login: "Login"
error:
- selector: mf_content
test:
path: /my.php
ratio:
path: /browse.php
selector: div:has(div#clock) > b + b+ b > span
search:
path: /browse.php
inputs:
$raw: "{{range .Categories}}c{{.}}=1&{{end}}"
search: "{{ .Query.Keywords }}"
incldead: 1
showspam: 1
rows:
selector: table[cellpadding="2"] > tbody > tr:has(td.row3)
fields:
title:
selector: a[title][href^="details.php"]
attribute: title
category:
selector: a[href^="browse.php?cat="]
attribute: href
filters:
- name: querystring
args: cat
comments:
selector: a[href^="details.php?id="]
attribute: href
download:
selector: a[href^="download.php"]
attribute: href
size:
selector: td:nth-child(8)
seeders:
selector: td:nth-child(10)
leechers:
selector: td:nth-child(11)
date:
selector: td:nth-child(6)
filters:
- name: append
args: " ago"

View File

@@ -0,0 +1,192 @@
---
site: gormogon
name: Gormogon
language: en-us
encoding: UTF-8
links:
- http://www.gormogon.com
caps:
categories:
# Movies:
1: Movies/DVD # DVD-R
2: Movies # Action
14: Movies # Adventure
15: Movies # Animation
16: Movies # Biography
17: Movies # Comedy
18: Movies # Crime
19: Movies # Disney
92: Movies # Documentary
20: Movies # Drama
21: Movies # Family
22: Movies # Fantasy
23: Movies # Film Noir
97: Movies # History
24: Movies # Horror
25: Movies # Martial Arts
26: Movies # Musicals
27: Movies # Mystery
28: Movies # Romance
29: Movies # Sci-Fi
30: Movies # Thriller
31: Movies # War
32: Movies # Western
33: Movies # Other
# Classic TV:
34: TV # Action
35: TV # Adventure
36: TV # Animation
37: TV # Biography
38: TV # Comedy
39: TV # Crime
40: TV # Disney
41: TV # Documentary
42: TV # Drama
43: TV # Family
44: TV # Fantasy
45: TV # TV Noir
46: TV # Horror
47: TV # Martial Arts
49: TV # Musicals
50: TV # Mystery
51: TV # Romance
52: TV # Sci-Fi
48: TV # Shows
53: TV # Thriller
54: TV # War
55: TV # Western
56: TV # Other
90: TV # TV Movies
# Old Time Radio
57: Audio # Action
58: Audio # Adventure
59: Audio # Biography
60: Audio # Comedy
61: Audio # Crime
62: Audio # Documentary
63: Audio # Drama
64: Audio # Family
65: Audio # Fantasy
66: Audio # Radio Noir
67: Audio # Horror
68: Audio # Musicals
69: Audio # Mystery
70: Audio # Romance
71: Audio # Sci-Fi
72: Audio # Shows
73: Audio # Thriller
74: Audio # War
75: Audio # Western
76: Audio # Other
# Music:
77: Audio # Official Sountracks
78: Audio # Theme Tunes
79: Audio # Music 30s
80: Audio # Music 40s
81: Audio # Music 50s
85: Audio # Music 60s
86: Audio # Music 70s
87: Audio # Music '80 - '84
# Printed:
82: Books # Books
91: Books # Newspaper
83: Books # Scripts
84: Books # Posters
88: Books # Comics
89: Books # Magazines
# Software:
94: Other # Screensavers
95: PC # Programs
96: Other # Other
modes:
search: [q]
tv-search: [q, season, ep]
login:
path: index.php?page=login&returnto=index.php
method: post
inputs:
uid: "{{ .Config.username }}"
pwd: "{{ .Config.password }}"
error:
- selector: td.lista > span[style="color:#FF0000;"]
test:
path: index.php
selector: form[name="jump1"]
ratio:
path: index.php
selector: form[name="jump1"] > table > tbody > tr > td:contains("SR ")
filters:
- name: trim
args: ")"
- name: split
args: [" ", 1]
download:
selector: a[href^="download.php?id="]
search:
path: index.php
inputs:
search: "{{ .Query.Keywords }}"
category: "{{range .Categories}}{{.}};{{end}}"
page: torrents
active: 0
rows:
selector: table.lista > tbody > tr:has(a[href^="index.php?page=torrents&category="])
fields:
download:
selector: a[href^="index.php?page=downloadcheck&id="]
attribute: href
title:
selector: a[onmouseover][href^="index.php?page=torrent-details&id="]
category:
selector: a[href^="index.php?page=torrents&category="]
attribute: href
filters:
- name: querystring
args: category
details:
selector: a[onmouseover][href^="index.php?page=torrent-details&id="]
attribute: href
size:
selector: td:nth-child(10)
date:
selector: td:nth-child(5)
filters:
- name: dateparse
args: "02/01/2006"
grabs:
selector: td:nth-child(8)
filters:
- name: replace
args: ["---", "0"]
seeders:
selector: td:nth-child(6)
leechers:
selector: td:nth-child(7)
downloadvolumefactor:
case:
img[alt="gold"]: "0"
img[alt="silver"]: "0.5"
"*": "1"
uploadvolumefactor:
case:
img[alt="2x Upload Multiplier"]: "2"
img[alt="3x Upload Multiplier"]: "3"
img[alt="4x Upload Multiplier"]: "4"
img[alt="5x Upload Multiplier"]: "5"
img[alt="6x Upload Multiplier"]: "6"
img[alt="7x Upload Multiplier"]: "7"
img[alt="8x Upload Multiplier"]: "8"
img[alt="9x Upload Multiplier"]: "9"
img[alt="10x Upload Multiplier"]: "10"
"*": "1"

View File

@@ -0,0 +1,97 @@
---
site: hdclub
name: HDClub
language: ru-ru
encoding: windows-1251
links:
- http://hdclub.org
caps:
categories:
70: Movies # Animation
71: Movies # Movie
81: Audio # HD Audio
78: TV/Documentary # Documentary
68: Audio/Video # Music Video
64: TV # TV Show
62: TV/Sport # Sport
82: Other # Demo
modes:
search: [q]
tv-search: [q, season, ep]
login:
path: login.php
method: form
form: form[action="takelogin.php"]
captcha:
type: image
image: img#captcha
input: imagestring
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
error:
- selector: td.embedded > div.error
test:
path: browse.php
selector: td.main_bottom
search:
path: browse.php
inputs:
$raw: "{{range .Categories}}c{{.}}=1&{{end}}"
search: "{{ .Query.Keywords }}"
dsearch: ""
stype: "or"
incldead: "1"
webdl: "0"
3d: "0"
rows:
selector: tbody#highlighted > tr
fields:
download:
selector: a[href^="details.php?id="]
attribute: href
filters:
- name: replace
args: ["details.php", "download.php"]
title:
selector: a[href^="details.php?id="]
details:
selector: a[href^="details.php?id="]
attribute: href
category:
selector: a[href^="browse.php?cat="]
attribute: href
filters:
- name: querystring
args: cat
date:
selector: div#frame > div#cleft > font
filters:
- name: append
args: " +02:00"
- name: dateparse
args: "2006-01-02 15:04:05 -07:00"
seeders:
selector: td:nth-child(5)
leechers:
selector: td:nth-child(6)
grabs:
selector: td:nth-child(7) b
filters:
- name: regexp
args: ([\d,]+)
size:
selector: td:nth-child(7)
remove: a, br, b
downloadvolumefactor:
case:
img[src="pic/freedownload.gif"]: "0"
img[src="pic/silver.gif"]: "0.5"
"*": "1"
uploadvolumefactor:
case:
"*": "1"

View File

@@ -0,0 +1,129 @@
---
site: icetorrent
name: ICE Torrent
language: ro-ro
encoding: UTF-8
links:
- https://www.icetorrent.org
caps:
categories:
1: PC/0day # Appz
85: Audio/Audiobook # AudioBooks
68: Books # Carti/Reviste
23: Books # Cartoons
73: Audio/Video # Concert/Videoclip
75: Other # Diverse
69: Books # Documentare
51: TV/Documentary # Documentaries
43: Books # eBooks
63: Movies/DVD # Filme DVD
65: Movies/HD # Filme HD
64: Movies/SD # Filme Xvid
40: Console # Games/Console
26: PC/Games # Games/PC
38: PC/Phone-Other # Mobile
59: Movies/3D # Movies/3D
92: Movies/HD # Movies/4K-UHD
32: Movies/BluRay # Movies/Blu-Ray
28: Movies/DVD # Movies/DVD
42: Movies/HD # Movies/HD-x264
91: Movies/HD # Movies/HEVC-x265
79: Movies/HD # Movies/microHD
29: Movies/SD # Movies/SD
72: Audio/Lossless # Music/FLAC
6: Audio/MP3 # Music/MP3
37: Audio/Video # Music/Video
70: Audio/Lossless # Muzica FLAC
71: Audio/MP3 # Muzica MP3
74: Other # Other
41: Other # Pictures
67: TV # Seriale TV
48: TV/Sport # Sports
87: Other # TUTS
33: TV/SD # TV Episodes
34: TV/HD # TVHD Episodes
modes:
search: [q]
tv-search: [q, season, ep]
login:
path: /login.php
method: form
form: form
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
error:
- selector: font:contains("failed") + table
test:
path: /browse.php
ratio:
text: -1
search:
path: /browse.php
inputs:
cat: "{{range .Categories}}c{{.}}=1&{{end}}"
search: "{{ .Query.Keywords }}"
incldead: 1
search_by: "name"
rows:
selector: td.torrenttable > table > tbody > tr:has(a[title][href^="details.php?id="])
fields:
title:
selector: a[title][href^="details.php?id="]
attribute: title
details:
selector: a[title][href^="details.php?id="]
attribute: href
category:
selector: a[href^="browse.php?cat="]
attribute: href
filters:
- name: querystring
args: cat
imdb:
selector: a[title="IMDB"]
attribute: href
banner:
attribute: rel
download:
selector: a[href^="download.php"]
attribute: href
files:
selector: td:nth-child(5) > a
filters:
- name: regexp
args: (\d+)
size:
selector: td:nth-child(5)
remove: a
date:
selector: td:nth-child(2) > div
filters:
- name: replace
args: ["Added on: ", ""]
- name: trim
args: "\xA0"
- name: append
args: " +03:00"
- name: dateparse
args: "2006-01-02 15:04:05 -07:00"
grabs:
selector: td:nth-child(6)
downloadvolumefactor:
case:
"*": "0"
uploadvolumefactor:
case:
"*": "1"
description:
selector: td:nth-child(2)
remove: a[title][href^="details.php?id="], div
seeders:
text: "9999"
leechers:
text: "9999"

View File

@@ -91,6 +91,7 @@
case:
span.star: "0"
span.fltime: "0"
":root li[id=\"alert-fl\"][class=\"alert\"]:contains(\"Freeleech ends in \")": 0
"*": "1"
uploadvolumefactor:
case:

View File

@@ -46,7 +46,7 @@
inclbookmarked: 0
incldead: 1
rows:
selector: tr.stickyrow
selector: tr:has(td.name)
fields:
title:
selector: td.name > div > a.poster-preview[title]

View File

@@ -77,6 +77,8 @@
rows:
selector: table.tableinborder[summary] > tbody > tr
filters:
- name: andmatch
fields:
download:
selector: a[href^="download.php?torrent="]

View File

@@ -0,0 +1,106 @@
---
site: qctorrent
name: QcTorrent
description: "A French gerneral tracker"
language: fr-fr
encoding: UTF-8
links:
- http://www.qctorrent.net/
caps:
categories:
30: PC # ++ Applications
1: PC # Applications/Divers
2: PC # Applications/PC ISO
3: PC # Applications/Portable
31: Movies # ++ Films
4: Movies/BluRay # Films/Bluray
5: Movies/DVD # Films/DVDr
6: Movies/HD # Films/HD Rip
7: Movies/SD # Films/SD Rip
8: Movies/SD # Films/VCD
32: Console # ++ Jeux
9: PC/Games # Jeux/PC
10: Console # Jeux/Portable
11: Console/PS4 # Jeux/PS
12: Console/Wii # Jeux/Wii
13: Console/Xbox # Jeux/Xbox
33: Audio # ++ Musique
14: Audio # Musique
15: Audio/Video # Musique/Video
34: TV # ++ Série-Télé
16: TV/HD # Série-Télé/Bluray
17: TV/SD # Série-Télé/DVDr
18: TV/HD # Série-Télé/HD Rip
19: TV/SD # Série-Télé/SD Rip
20: Books # E-Books
21: XXX # XXX
modes:
search: [q]
tv-search: [q, season, ep]
login:
path: login.php
method: post
inputs:
login-username: "{{ .Config.username }}"
login-password: "{{ .Config.password }}"
login-remember-me: "on"
login: ""
error:
- selector: "script[type=\"text/javascript\"]:contains(\"$.ambiance({message: \")"
test:
path: search.php
selector: div.top-bar > div.container > div.textleft > div.hidden-sm > font:contains("Ratio:") > font
ratio:
path: search.php
selector: div.top-bar > div.container > div.textleft > div.hidden-sm > font:contains("Ratio:") > font
search:
path: search.php
inputs:
category: "{{range .Categories}}{{.}};{{end}}"
title: "{{ .Query.Keywords }}"
search: "Recherche"
rows:
selector: tr[data-snatches]
fields:
download:
selector: td.name > a
attribute: href
filters:
- name: replace
args: ["/torrent/", "/dl/"]
title:
selector: td.name > a
category:
selector: td.coll-0 > a
attribute: href
filters:
- name: querystring
args: category
details:
selector: td.name > a
attribute: href
grabs:
attribute: data-snatches
seeders:
selector: td.seeds
leechers:
selector: td.leeches
date:
selector: td[data-date]
attribute: data-date
downloadvolumefactor:
case:
span[title^="Freeleech:"]: "0"
span[title^="Half Freeleech:"]: "0.5"
"*": "1"
uploadvolumefactor:
case:
"*": "1"
size:
selector: td.size
remove: span

View File

@@ -0,0 +1,167 @@
---
site: rapidetracker
name: RapideTracker
language: fr-fr
encoding: UTF-8
links:
- https://rapidetracker.net
caps:
categories:
218: PC/0day # APPLICATION
219: PC/Phone-Android # ANDROID
221: PC/Phone-IOS # APPLE
220: PC/0day # WINDOWS
233: Movies/SD # CAM/SCREENER
234: Movies/SD # CAM-TS
235: Movies/SD # DVD-SCREENER
222: TV/Anime # DESSINS ANIMES
260: TV/Anime # ANIMATION
225: TV/Anime # JAP-ANIM
226: TV/Anime # SERIE-ANIME
206: Books # E-BOOK
240: Books # AUDIO
239: Books # BD
241: Books # LIVRE
208: Books # MANGA
209: Books # PRESSE
207: XXX # XXX
213: TV # EMISSIONS TV
215: TV/Documentary # DOC
214: TV # EMISSIONS
216: TV # SPECTACLE
217: TV/Sport # SPORT
176: Movies/SD # FILMS
178: Movies/SD # BDRIP
179: Movies/SD # BRRIP
245: Movies/SD # COFFRET FILMS
183: Movies/DVD # DVD-R
182: Movies/DVD # DVDRIP
252: Movies/SD # FILMS-VO
246: Movies/SD # FILMS-X265
184: Movies/SD # HORREUR
199: Movies/SD # RETRO
186: Movies/SD # VOSTFR
198: Movies/SD # WEB-RiP
210: XXX # FILMS ADULTE
212: XXX # HENTAI
211: XXX # FILMS XXX
200: Movies/HD # FILMS HD
201: Movies/HD # 1080p
202: Movies/3D # 3D
203: Movies/HD # 720p
242: Movies/BluRay # BLURAY
204: Movies/HD # HD-RIP
238: Movies/HD # M-HD 1080P
237: Movies/HD # M-HD 720P
255: Movies/HD # REMUX
191: Console # JEUX
192: Console/NDS # DS-3DS
193: PC/Games # PC
194: Console/PS3 # PS3
195: Console/Wii # WII
196: Console/Wii # WIIU
197: Console/XBox360 # XBox360
187: Audio # MUSIQUE
189: Audio # CONCERT
190: Audio/Lossless # FLAC
188: Audio/MP3 # MP3
227: TV # SERIE
254: TV # SERIE-VO
229: TV/HD # TV HD FR
230: TV/HD # TV HD VOSTFR
249: TV/HD # TV HD VOSTFR X265
243: TV # TV PACK FR
244: TV # TV PACK VOSTFR
231: TV/SD # TV VF
232: TV/SD # TV VOSTFR
236: Other # SOURD & MALENTENDANT
253: Other # TEAM-RDT
258: TV/Documentary # DOC RDT
257: Movies # FILMS RDT
256: TV # SERIE RDT
259: XXX # XXX RDT
modes:
search: [q]
tv-search: [q, season, ep]
login:
path: takelogin.php
method: post
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
error:
- selector: table:has(td:contains("Une erreur est survenue"))
test:
path: browse.php
search:
path: browse.php
inputs:
do: "chercher"
keywords: "{{ .Query.Keywords }}"
search_type: "t_name"
category: "0" # multi cat search not supported
include_dead_torrents: "yes"
rows:
selector: table#sortabletable > tbody > tr:has(a[href^="https://rapidetracker.net/torrent-details-"])
fields:
download:
selector: a[href^="https://rapidetracker.net/download-torrent-"]
attribute: href
title:
selector: a[href^="https://rapidetracker.net/torrent-details-"]
details:
selector: a[href^="https://rapidetracker.net/torrent-details-"]
attribute: href
category:
selector: a[href^="https://rapidetracker.net/torrent-category-"]
attribute: href
filters:
- name: regexp
args: torrent-category-(\d+)
size:
selector: td:nth-child(4)
date:
selector: td:nth-child(2) > div > font[color="white"]
filters:
- name: replace
args: ["le ", ""]
- name: replace
args: [" à ", " "]
- name: trim
args: "\t"
- name: trim
args: "\n"
- name: append
args: " +01:00"
- name: dateparse
args: "02-01-2006 15:04 -07:00"
grabs:
selector: td:nth-child(5)
seeders:
selector: td:nth-child(6)
leechers:
selector: td:nth-child(7)
downloadvolumefactor:
case:
img[alt^="Free Torrent "]: "0"
img[alt^="Silver Torrent "]: "0.5"
"*": "1"
uploadvolumefactor:
case:
"*": "1"

View File

@@ -63,7 +63,9 @@
tpp: "100"
dirty: "1"
rows:
selector: table[id="large"] > tbody > tr:has(div.browsing)
selector: td > table[id="large"] > tbody > tr:has(div.browsing)
filters:
- name: andmatch
dateheaders:
selector: ":has(td.colhead[title] > b)"
filters:

View File

@@ -75,12 +75,14 @@
p: "torrents"
pid: "32"
$raw: "{{range .Categories}}cid[]:{{.}}&{{end}}"
keywords: "{{ .Query.Keywords }}"
keywords: "{{ re_replace .Query.Keywords \"[^a-zA-Z0-9]+\" \"%\" }}"
search_type: "name"
searchin: "title"
rows:
selector: table#torrents_table_classic > tbody > tr:not([id="torrents_table_classic_head"])
filters:
- name: andmatch
fields:
title:
selector: td.torrent_name > a
@@ -149,3 +151,5 @@
args: ["Domenica", "Sunday"]
- name: replace
args: [" alle", ""]
- name: dateparse
args: "02-01-2006 15:04"

View File

@@ -58,7 +58,9 @@
incldead: 1
rows:
selector: p + table > tbody > tr:has(a[href^="details.php?id="])
selector: p + table > tbody > tr:has(a[href^="details.php?id="]), p + table > tbody > tr[id^="kdescr"]
filters:
- name: andmatch
after: 1
fields:
title:

View File

@@ -106,6 +106,8 @@
sort: "desc"
rows:
selector: table.main > tbody > tr:contains("Alle Torrents") + tr > td > table.tableinborder > tbody > tr
filters:
- name: andmatch
fields:
download:
selector: a[href^="download-ssl.php?torrent="]

View File

@@ -122,7 +122,7 @@
details:
selector: a[onmouseover][href^="torrents-details.php?id="]
attribute: href
details:
comments:
selector: a[href*="#comments"]
attribute: href
size:

View File

@@ -0,0 +1,93 @@
---
site: torrentsmd
name: Torrents.Md
language: ru-mo
encoding: UTF-8
links:
- https://torrentsmd.com/
caps:
categories:
1: Movies # Filme
2: Audio # Muzică
3: PC # Software
4: Console # Jocuri
5: TV # Tv
7: Other # Alte
8: Books # Cărţi
9: Audio/Video # Muzică video
10: TV/Anime # Anime
11: Movies # Filme animate
12: Movies/DVD # DVD
13: Movies # Filme documentare
14: Audio/Audiobook # Cărţi audio
15: Other # Lecţii video
16: Other # Fotografii
17: TV/Sport # Sport
18: TV/HD # HDTV
modes:
search: [q]
tv-search: [q, season, ep]
login:
path: login.php
method: form
form: form
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
error:
- selector: td.embedded:has(h2:contains("eşuată"))
test:
path: browse.php
search:
path: "{{if .Query.Keywords}}search.php{{else}}browse.php{{end}}"
inputs:
search_str: "{{ .Query.Keywords }}"
rows:
selector: table.tableTorrents > tbody > tr:has(a[href^="/details.php?id="])
fields:
title:
selector: a[href^="/details.php?id="]
details:
selector: a[href^="/details.php?id="]
attribute: href
category:
selector: a[href^="browse.php?cat="]
attribute: href
filters:
- name: querystring
args: cat
download:
selector: a[href^="/details.php?id="]
attribute: href
filters:
- name: replace
args: ["/details.php", "/download.php"]
files:
selector: td:nth-child(3)
date:
selector: td:nth-child(5)
filters:
- name: replace
args: ["ore", "hours ago"]
- name: replace
args: ["minute", "minutes ago"]
- name: dateparse
args: "01-02 2006"
- name: dateparse
args: "01-02"
size:
selector: td:nth-child(6)
seeders:
selector: td:nth-child(7)
leechers:
selector: td:nth-child(8)
downloadvolumefactor:
case:
"*": "1"
uploadvolumefactor:
case:
"*": "1"

View File

@@ -0,0 +1,129 @@
---
site: torviet
name: TorViet
language: vi-vn
encoding: UTF-8
links:
- http://torviet.com
caps:
categories:
1: Console # Game
7: PC/Games # PC
133: PC/Phone-Other # Handheld
132: Console # Console
2: Movies # Movie
23: Movies/HD # mHD
24: Movies/SD # SD
124: Movies/HD # 720p
125: Movies/HD # 1080p
127: Movies/BluRay # Blu-ray
3: TV # TV
128: TV/HD # HD
129: TV/SD # SD
4: PC # Software
76: PC/0day # Windows
77: PC/Mac # MAC
78: PC # Linux
79: PC/Phone-Other # Handheld
5: Audio # Music
92: Audio/Video # Music Video
126: Audio/Lossless # Lossless
130: Audio/MP3 # Lossy
131: Audio # Surround
6: Other # Misc
112: Books # Ebook
113: Other # Training Video
117: Audio/Audiobook # Audio book
modes:
search: [q]
tv-search: [q, season, ep]
login:
path: /takelogin.php
method: post
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
error:
- selector: td.embedded:has(h2:contains("failed"))
test:
path: /torrents.php
ratio:
path: /torrents.php
selector: table#info_block
filters:
- name: regexp
args: "Ratio:\\s(.*?)\\s\\s"
search:
path: /torrents.php
inputs:
search: "{{ .Query.Keywords }}"
sltCategory: 0
sltSubCategory: 0 # can't sepcify multiple categorys so we're useing all always
sltGenre: 0
incldead: 1
spstate: 0
inclbookmarked: 0
search_area: 0
search_mode: 0
rows:
selector: div#idtorrent > table.torrents > tbody > tr:has(table.torrentname)
fields:
title:
selector: a[class][title]
attribute: title
details:
selector: a[class][title]
attribute: href
description:
selector: td.embedded:has(a[title])
remove: a[title]
category:
selector: a[href^="/torrents.php?sltSubCategory="]
attribute: href
filters:
- name: querystring
args: sltSubCategory
comments:
selector: td:nth-child(3) a
attribute: href
download:
selector: a[href^="/download.php?"]
attribute: href
size:
selector: td:nth-child(5)
seeders:
selector: td:nth-child(6)
leechers:
selector: td:nth-child(7)
date:
selector: td:nth-child(4)
filters:
- name: append
args: " ago"
grabs:
selector: td:nth-child(8)
downloadvolumefactor:
case:
img.pro_free: "0"
img.pro_free2up: "0"
img.pro_50pctdown: "0.5"
img.pro_50pctdown2up: "0.5"
img.pro_30pctdown: "0.3"
"*": "1"
uploadvolumefactor:
case:
img.pro_50pctdown2up: "2"
img.pro_free2up: "2"
img.pro_2up: "2"
"*": "1"

View File

@@ -0,0 +1,70 @@
---
site: trancetraffic
name: TranceTraffic
language: en-us
encoding: UTF-8
links:
- https://www.trancetraffic.com
caps:
categories:
1: Audio
modes:
search: [q]
tv-search: [q, season, ep]
login:
path: takelogin.php
method: post
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
error:
- selector: td.embedded:has(h2:contains("failed"))
test:
path: browse.php
search:
path: browse.php
inputs:
search: "{{ .Query.Keywords }}"
rows:
selector: table > tbody > tr:has(a[href^="details.php?id="])
fields:
download:
selector: a[href^="download.php/"]
attribute: href
title:
selector: a[href^="details.php?id="]
details:
selector: a[href^="details.php?id="]
attribute: href
category:
text: 1
date:
selector: td:nth-child(6)
filters:
- name: append
args: " +00:00"
- name: dateparse
args: "2006-01-0215:04:05 -07:00"
seeders:
selector: td:nth-child(9)
leechers:
selector: td:nth-child(10)
grabs:
selector: td:nth-child(8)
filters:
- name: regexp
args: ([\d,]+)
files:
selector: td:nth-child(4)
size:
selector: td:nth-child(7)
downloadvolumefactor:
case:
"*": "1"
uploadvolumefactor:
case:
"*": "1"

View File

@@ -101,6 +101,8 @@
rows:
selector: table.ttable_headinner > tbody > tr.t-row
filters:
- name: andmatch
after: 1
fields:
download:

View File

@@ -0,0 +1,127 @@
---
site: utorrents
name: u-Torrent
language: ro-ro
encoding: windows-1252
links:
- http://www.u-torrents.ro/
caps:
categories:
48: Movies/3D # 3D
1: PC/0day # Appz
3: Other # Cartoons
42: TV/Documentary # Documentaries
6: Books # eBooks
11: PC/Games # Games | PC
12: Console/PS3 # Games | PS2
36: Console/PS3 # Games | PS3
40: Console/PSP # Games | PSP
25: Console/Wii # Games | Wii
16: Console/Xbox # Games | XBOX
19: PC/Phone-Other # Mobile
43: Movies/BluRay # Movies | Blu-Ray
49: Movies/BluRay # Movies | Blu-Ray-RO
7: Movies/DVD # Movies | DVD-R
2: Movies/DVD # Movies | DVD-RO
17: Movies/HD # Movies | HD
45: Movies/HD # Movies | HD-RO
21: Movies # Movies | Oldies
38: Movies # Movies | Packs
8: Movies/SD # Movies | x264
4: Movies/SD # Movies | x264-RO
10: Movies/SD # Movies | XviD
44: Movies/SD # Movies | XviD-RO
5: Audio/MP3 # Music | Mp3
39: Audio # Music | Packs
23: Audio/Video # Music | Videos
18: Other # Pictures
46: XXX/Imageset # Pictures | xxx
22: TV/Sport # Sport
50: TV # STAR
20: TV/SD # TV | Episodes
47: TV/HD # TV | Episodes HD
41: TV # TV | Packs
15: XXX # xXx
modes:
search: [q]
tv-search: [q, season, ep]
login:
path: /takelogin.php
method: post
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
error:
- selector: td.embedded:has(h2:contains("failed"))
test:
path: /browse.php
ratio:
path: /browse.php
selector: font:contains("Ratio:") > span
search:
path: /browse.php
inputs:
$raw: "{{range .Categories}}c{{.}}=1&{{end}}"
search: "{{ .Query.Keywords }}"
incldead: 1
rows:
selector: td.outer > table > tbody > tr:has(a[href^="details.php?id="])
fields:
title:
selector: a[href^="details.php?id="]
details:
selector: a[href^="details.php?id="]
attribute: href
category:
selector: a[href^="browse.php?cat="]
attribute: href
filters:
- name: querystring
args: cat
download:
selector: a[href^="download2.php"]
attribute: href
grabs:
selector: td:nth-child(7)
filters:
- name: regexp
args: (\d+)
files:
selector: td:nth-child(3)
size:
selector: td:nth-child(6)
date:
selector: td:nth-child(5)
filters:
- name: trim
args: "\xF0"
- name: append
args: " +02:00"
- name: dateparse
args: "02-01-200615:04:05 -07:00"
seeders:
selector: td:nth-child(8)
leechers:
selector: td:nth-child(9)
banner:
selector: a[onmouseover][href^="details.php?id="]
attribute: onmouseover
filters:
- name: regexp
args: src=([^\s]+)
downloadvolumefactor:
case:
button.btnfree: "0"
"*": "1"
uploadvolumefactor:
case:
button.btn2xup: "2"
"*": "1"
description:
selector: td:nth-child(2)
remove: a[href^="details.php?id="]

View File

@@ -102,6 +102,8 @@
rows:
selector: div#browse > form > div > table.browsewidth100 > tbody > tr:has(a[href^="download.php?torrent="])
filters:
- name: andmatch
fields:
title:
selector: a[href^="details.php?id="]

View File

@@ -0,0 +1,122 @@
---
site: xtremezone
name: Xtreme Zone
language: ro-ro
encoding: UTF-8
links:
- http://myxz.org/
caps:
categories:
3: TV/Anime # Anime/Hentai
1: PC/0day # Appz
9: TV/Documentary # Documentary
6: Books # eBooks
52: Console # Games-Console
11: PC/Games # Games-PC
18: Other # Images
14: PC # Linux
37: PC/Mac # Mac
19: PC/Phone-Other # Mobile
17: Movies/BluRay # Movies-BluRay
24: Movies/BluRay # Movies-BluRayRO
7: Movies/DVD # Movies-DVD
2: Movies/DVD # Movies-DVD-RO
8: Movies/HD # Movies-HD
29: Movies/HD # Movies-HD-RO
38: Movies # Movies-Packs
10: Movies/SD # Movies-SD
35: Movies/SD # Movies-SD-RO
5: Audio # Music
22: TV/Sport # Sport
43: TV/HD # TV-HD
44: TV/HD # TV-HD-RO
41: TV # TV-Packs
45: TV/SD # TV-SD
46: TV/SD # TV-SD-RO
15: XXX # XXX
47: XXX # XXX-DVD
48: XXX # XXX-HD
49: XXX/Imageset # XXX-IMGSet
50: XXX # XXX-Packs
51: XXX # XXX-SD
modes:
search: [q]
tv-search: [q, season, ep]
login:
path: /login.php
method: form
form: form
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
error:
- selector: td.embedded:has(center > h2:contains(failed))
test:
path: /browse.php
ratio:
path: /browse.php
selector: font:contains("Ratio:")+font
search:
path: /browse.php
inputs:
$raw: "{{range .Categories}}c{{.}}=1&{{end}}"
search: "{{ .Query.Keywords }}"
incldead: 1
rows:
selector: table.browser > tbody > tr.browse[style]
fields:
title:
selector: a[href^="details.php?id="]
details:
selector: a[href^="details.php?id="]
attribute: href
category:
selector: a[href^="browse.php?cat="]
attribute: href
filters:
- name: querystring
args: cat
download:
selector: a[href^="dwn.php"]
attribute: href
grabs:
selector: td:nth-child(7)
filters:
- name: regexp
args: (\d+)
size:
selector: td:nth-child(6)
date:
selector: td:nth-child(5)
filters:
- name: append
args: " +00:00"
- name: dateparse
args: "02-01-200615:04:05 -07:00"
seeders:
selector: td:nth-child(8)
leechers:
selector: td:nth-child(9)
banner:
selector: a[onmouseover][href^="details.php?id="]
attribute: onmouseover
filters:
- name: regexp
args: src=([^\s]+)
downloadvolumefactor:
case:
"img[title^=\"FreeLech: \"]": "0"
"img[title^=\"HALF: \"]": "0.5"
"*": "1"
uploadvolumefactor:
case:
"img[title^=\"2xUP: \"]": "2"
"*": "1"
description:
selector: td:nth-child(2)
remove: a, img

View File

@@ -311,11 +311,11 @@ namespace Jackett.Indexers
output("Category: " + MapTrackerCatToNewznab(categoryID) + " (" + categoryID + ")");
// Seeders
int seeders = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(6)").Text(), @"\d+").Value);
int seeders = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(5)").Text(), @"\d+").Value);
output("Seeders: " + seeders);
// Leechers
int leechers = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(7)").Text(), @"\d+").Value);
int leechers = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(6)").Text(), @"\d+").Value);
output("Leechers: " + leechers);
// Completed

View File

@@ -0,0 +1,234 @@
using AngleSharp.Parser.Html;
using Jackett.Models;
using Jackett.Models.IndexerConfig;
using Jackett.Services;
using Jackett.Utils;
using Jackett.Utils.Clients;
using Newtonsoft.Json.Linq;
using NLog;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace Jackett.Indexers.Abstract
{
public abstract class GazelleTracker : BaseIndexer
{
protected string LoginUrl { get { return SiteLink + "login.php"; } }
protected string APIUrl { get { return SiteLink + "ajax.php"; } }
protected string DownloadUrl { get { return SiteLink + "torrents.php?action=download&id="; } }
protected string DetailsUrl { get { return SiteLink + "torrents.php?torrentid="; } }
new ConfigurationDataBasicLogin configData
{
get { return (ConfigurationDataBasicLogin)base.configData; }
set { base.configData = value; }
}
public GazelleTracker(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())
{
Encoding = Encoding.GetEncoding("UTF-8");
}
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
configData.LoadValuesFromJson(configJson);
var pairs = new Dictionary<string, string> {
{ "username", configData.Username.Value },
{ "password", configData.Password.Value },
};
var response = await RequestLoginAndFollowRedirect(LoginUrl, pairs, string.Empty, true, SiteLink);
await ConfigureIfOK(response.Cookies, response.Content != null && response.Content.Contains("logout.php"), () =>
{
var loginResultParser = new HtmlParser();
var loginResultDocument = loginResultParser.Parse(response.Content);
var loginform = loginResultDocument.QuerySelector("#loginform");
if (loginform == null)
throw new ExceptionWithConfigData(response.Content, configData);
loginform.QuerySelector("table").Remove();
var errorMessage = loginform.TextContent.Replace("\n\t", " ").Trim();
throw new ExceptionWithConfigData(errorMessage, configData);
});
return IndexerConfigurationStatus.RequiresTesting;
}
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
var releases = new List<ReleaseInfo>();
var searchString = query.GetQueryString();
var searchUrl = APIUrl;
var queryCollection = new NameValueCollection();
queryCollection.Add("action", "browse");
//queryCollection.Add("group_results", "0"); # results won't include all information
queryCollection.Add("order_by", "time");
queryCollection.Add("order_way", "desc");
if (!string.IsNullOrWhiteSpace(searchString))
{
queryCollection.Add("searchstr", searchString);
}
foreach (var cat in MapTorznabCapsToTrackers(query))
{
queryCollection.Add("filter_cat[" + cat + "]", "1");
}
searchUrl += "?" + queryCollection.GetQueryString();
var response = await RequestStringWithCookiesAndRetry(searchUrl);
if (response.IsRedirect || query.IsTest)
{
// re-login
await ApplyConfiguration(null);
response = await RequestStringWithCookiesAndRetry(searchUrl);
}
try
{
var json = JObject.Parse(response.Content);
foreach (JObject r in json["response"]["results"])
{
var groupTime = DateTimeUtil.UnixTimestampToDateTime(long.Parse((string)r["groupTime"]));
var groupName = HttpUtility.HtmlDecode((string)r["groupName"]);
var artist = (string)r["artist"];
var cover = (string)r["cover"];
var tags = r["tags"].ToList();
var groupYear = (string)r["groupYear"];
var releaseType = (string)r["releaseType"];
var release = new ReleaseInfo();
release.PublishDate = groupTime;
if (!string.IsNullOrEmpty(cover))
release.BannerUrl = new Uri(cover);
release.Title = "";
if (!string.IsNullOrEmpty(artist))
release.Title += artist + " - ";
release.Title += groupName;
if (!string.IsNullOrEmpty(groupYear))
release.Title += " [" + groupYear + "]";
if (!string.IsNullOrEmpty(releaseType))
release.Title += " [" + releaseType + "]";
release.Description = "";
if (tags != null)
release.Description += "Tags: " + string.Join(", ", tags) + "\n";
if (r["torrents"] is JArray)
{
foreach (JObject torrent in r["torrents"])
{
ReleaseInfo release2 = (ReleaseInfo)release.Clone();
FillReleaseInfoFromJson(release2, torrent);
releases.Add(release2);
}
}
else
{
FillReleaseInfoFromJson(release, r);
releases.Add(release);
}
}
}
catch (Exception ex)
{
OnParseError(response.Content, ex);
}
return releases;
}
void FillReleaseInfoFromJson(ReleaseInfo release, JObject torrent)
{
var torrentId = torrent["torrentId"];
var time = (string)torrent["time"];
if (!string.IsNullOrEmpty(time)) {
release.PublishDate = DateTime.ParseExact(time+" +0000", "yyyy-MM-dd HH:mm:ss zzz", CultureInfo.InvariantCulture);
}
var flags = new List<string>();
var format = (string)torrent["format"];
if (!string.IsNullOrEmpty(format))
flags.Add(format);
var encoding = (string)torrent["encoding"];
if (!string.IsNullOrEmpty(encoding))
flags.Add(encoding);
if(torrent["hasLog"] != null && (bool)torrent["hasLog"])
{
var logScore = (string)torrent["logScore"];
flags.Add("Log (" + logScore + "%)");
}
if (torrent["hasCue"] != null && (bool)torrent["hasCue"])
flags.Add("Cue");
var media = (string)torrent["media"];
if (!string.IsNullOrEmpty(media))
flags.Add(media);
if (torrent["remastered"] != null && (bool)torrent["remastered"])
{
var remasterYear = (string)torrent["remasterYear"];
var remasterTitle = HttpUtility.HtmlDecode((string)torrent["remasterTitle"]);
flags.Add(remasterYear + (!string.IsNullOrEmpty(remasterTitle) ? " " + remasterTitle : ""));
}
if (flags.Count > 0)
release.Title += " " + string.Join(" / ", flags);
release.Size = (long)torrent["size"];
release.Seeders = (int)torrent["seeders"];
release.Peers = (int)torrent["leechers"] + release.Seeders;
release.Comments = new Uri(DetailsUrl + torrentId);
release.Guid = release.Comments;
release.Link = new Uri(DownloadUrl + torrentId);
var category = (string)torrent["category"];
if (category == null)
release.Category = MapTrackerCatToNewznab("1");
else
release.Category = MapTrackerCatDescToNewznab(category);
release.Files = (int)torrent["fileCount"];
release.Grabs = (int)torrent["snatches"];
release.DownloadVolumeFactor = 1;
release.UploadVolumeFactor = 1;
if ((bool)torrent["isFreeleech"])
{
release.DownloadVolumeFactor = 0;
}
if ((bool)torrent["isPersonalFreeleech"])
{
release.DownloadVolumeFactor = 0;
}
if ((bool)torrent["isNeutralLeech"])
{
release.DownloadVolumeFactor = 0;
release.UploadVolumeFactor = 0;
}
}
}
}

View File

@@ -129,6 +129,7 @@ namespace Jackett.Indexers
try
{
CQ dom = results;
var globalFreeleech = dom.Find("div > img[alt=\"Only Upload\"][title^=\"ONLY UPLOAD \"]").Any();
var rows = dom["table.tableinborder > tbody > tr:has(td.tableb)"];
foreach (var row in rows)
@@ -186,7 +187,9 @@ namespace Jackett.Indexers
var grabs = qRow.Find("a[href*=\"&tosnatchers=1\"] ~ font ~ b").Text();
release.Grabs = ParseUtil.CoerceInt(grabs);
if (qRow.Find("img[alt=\"OU\"]").Length >= 1)
if (globalFreeleech)
release.DownloadVolumeFactor = 0;
else if (qRow.Find("img[alt=\"OU\"]").Length >= 1)
release.DownloadVolumeFactor = 0;
else
release.DownloadVolumeFactor = 1;

View File

@@ -15,7 +15,7 @@ using System.Threading.Tasks;
using System.Web;
using Jackett.Models.IndexerConfig;
using System.Collections.Specialized;
namespace Jackett.Indexers
{
// To comply with the rules for this tracker, only the acronym is used and no publicly displayed URLs to the site.
@@ -164,7 +164,7 @@ namespace Jackett.Indexers
var title = qRow.Find("td:nth-child(2)");
title.Find("span, strong, div, br").Remove();
release.Title = title.Text().Replace(" - ]", "]");
release.Title = ParseUtil.NormalizeMultiSpaces(title.Text().Replace(" - ]", "]"));
releases.Add(release);
}

View File

@@ -118,7 +118,6 @@ namespace Jackett.Indexers
{
if (null != input)
{
input = input.ToLowerInvariant();
var mapping = categoryMapping.Where(m => m.TrackerCategory.ToLowerInvariant() == input.ToLowerInvariant()).FirstOrDefault();
if (mapping != null)
{
@@ -128,6 +127,19 @@ namespace Jackett.Indexers
return 0;
}
protected int MapTrackerCatDescToNewznab(string input)
{
if (null != input)
{
var mapping = categoryMapping.Where(m => m.TrackerCategoryDesc.ToLowerInvariant() == input.ToLowerInvariant()).FirstOrDefault();
if (mapping != null)
{
return mapping.NewzNabCategory;
}
}
return 0;
}
public static string GetIndexerID(Type type)
{
return StringUtil.StripNonAlphaNumeric(type.Name.ToLowerInvariant());
@@ -304,9 +316,10 @@ namespace Jackett.Indexers
var response = await RequestBytesWithCookiesAndRetry(requestLink);
if (response.Status != System.Net.HttpStatusCode.OK && response.Status != System.Net.HttpStatusCode.Continue && response.Status != System.Net.HttpStatusCode.PartialContent)
{
if(response.Content != null)
logger.Error("Failed download cookies: " + this.CookieHeader);
if (response.Content != null)
logger.Error("Failed download response:\n" + Encoding.UTF8.GetString(response.Content));
throw new Exception($"Remote server returned {response.Status.ToString()}");
throw new Exception($"Remote server returned {response.Status.ToString()}" + (response.IsRedirect ? " => "+response.RedirectingTo : ""));
}
return response.Content;
@@ -483,16 +496,16 @@ namespace Jackett.Indexers
}
}
protected void AddCategoryMapping(string trackerCategory, TorznabCategory newznabCategory)
protected void AddCategoryMapping(string trackerCategory, TorznabCategory newznabCategory, string trackerCategoryDesc = null)
{
categoryMapping.Add(new CategoryMapping(trackerCategory, newznabCategory.ID));
categoryMapping.Add(new CategoryMapping(trackerCategory, trackerCategoryDesc, newznabCategory.ID));
if (!TorznabCaps.Categories.Contains(newznabCategory))
TorznabCaps.Categories.Add(newznabCategory);
}
protected void AddCategoryMapping(int trackerCategory, TorznabCategory newznabCategory)
protected void AddCategoryMapping(int trackerCategory, TorznabCategory newznabCategory, string trackerCategoryDesc = null)
{
AddCategoryMapping(trackerCategory.ToString(), newznabCategory);
AddCategoryMapping(trackerCategory.ToString(), newznabCategory, trackerCategoryDesc);
}
protected void AddMultiCategoryMapping(TorznabCategory newznabCategory, params int[] trackerCategories)

View File

@@ -139,11 +139,18 @@ namespace Jackett.Indexers
var release = new ReleaseInfo();
release.MinimumRatio = 0.7;
release.MinimumSeedTime = 48 * 60 * 60;
release.DownloadVolumeFactor = 1;
release.UploadVolumeFactor = 1;
var qRow = row.Cq();
var flagImgs = qRow.Find("table tbody tr: eq(0) td > img");
List<string> flags = new List<string>();
flagImgs.Each(flagImg => {
flags.Add(flagImg.GetAttribute("src").Replace("pic/torrent_", "").Replace(".gif", "").ToUpper());
var flag = flagImg.GetAttribute("src").Replace("pic/torrent_", "").Replace(".gif", "").ToUpper();
if (flag == "OU")
release.DownloadVolumeFactor = 0;
else
flags.Add(flag);
});
var titleLink = qRow.Find("table tbody tr:eq(0) td a:has(b)").First();
@@ -172,22 +179,12 @@ namespace Jackett.Indexers
var catId = qRow.Find("td:eq(0) a").First().Attr("href").Split('=')[1];
release.Category = MapTrackerCatToNewznab(catId);
var cat = qRow.Find("td:eq(0) a").First().Attr("href").Substring(1);
release.Category = MapTrackerCatToNewznab(cat);
var files = qRow.Find("td:has(a[href*=\"&filelist=1\"])> b:nth-child(2)").Text();
release.Files = ParseUtil.CoerceInt(files);
var grabs = qRow.Find("td:has(a[href*=\"&tosnatchers=1\"])> b:nth-child(1)").Text();
release.Grabs = ParseUtil.CoerceInt(grabs);
if (qRow.Find("img[src=\"pic/torrent_ou.gif\"]").Length >= 1)
release.DownloadVolumeFactor = 0;
else
release.DownloadVolumeFactor = 1;
release.UploadVolumeFactor = 1;
releases.Add(release);
}
}

View File

@@ -89,7 +89,7 @@ namespace Jackett.Indexers
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
var releases = new List<ReleaseInfo>();
var episodeSearchUrl = string.Format("{0}?search={1}&cat=0", SearchUrl, HttpUtility.UrlEncode(query.GetQueryString()));
var episodeSearchUrl = string.Format("{0}?search={1}&cat=0&incldead=1", SearchUrl, HttpUtility.UrlEncode(query.GetQueryString()));
var results = await RequestStringWithCookiesAndRetry(episodeSearchUrl);
try
{

View File

@@ -50,6 +50,7 @@ namespace Jackett.Indexers
public loginBlock Login { get; set; }
public ratioBlock Ratio { get; set; }
public searchBlock Search { get; set; }
public downloadBlock Download { get; set; }
// IndexerDefinitionStats not needed/implemented
}
public class settingsField
@@ -65,6 +66,13 @@ namespace Jackett.Indexers
public Dictionary<string, List<string>> Modes { get; set; }
}
public class captchaBlock
{
public string Type { get; set; }
public string Image { get; set; }
public string Input { get; set; }
}
public class loginBlock
{
public string Path { get; set; }
@@ -73,6 +81,7 @@ namespace Jackett.Indexers
public Dictionary<string, string> Inputs { get; set; }
public List<errorBlock> Error { get; set; }
public pageTestBlock Test { get; set; }
public captchaBlock Captcha { get; set; }
}
public class errorBlock
@@ -124,7 +133,12 @@ namespace Jackett.Indexers
public selectorBlock Dateheaders { get; set; }
}
protected readonly string[] OptionalFileds = new string[] { "imdb" };
public class downloadBlock
{
public string Selector { get; set; }
}
protected readonly string[] OptionalFileds = new string[] { "imdb", "rageid", "tvdbid", "banner" };
public CardigannIndexer(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
: base(manager: i,
@@ -176,7 +190,7 @@ namespace Jackett.Indexers
if (!SiteLink.EndsWith("/"))
SiteLink += "/";
Language = Definition.Language;
TorznabCaps = TorznabUtil.CreateDefaultTorznabTVCaps(); // TODO implement caps
TorznabCaps = new TorznabCapabilities();
// init config Data
configData = new ConfigurationData();
@@ -218,6 +232,26 @@ namespace Jackett.Indexers
variables = getTemplateVariablesFromConfigData();
}
// handle re_replace expression
// Example: {{ re_replace .Query.Keywords "[^a-zA-Z0-9]+" "%" }}
Regex ReReplaceRegex = new Regex(@"{{\s*re_replace\s+(\..+?)\s+""(.+)""\s+""(.+?)""\s*}}");
var ReReplaceRegexMatches = ReReplaceRegex.Match(template);
while (ReReplaceRegexMatches.Success)
{
string all = ReReplaceRegexMatches.Groups[0].Value;
string variable = ReReplaceRegexMatches.Groups[1].Value;
string regexp = ReReplaceRegexMatches.Groups[2].Value;
string newvalue = ReReplaceRegexMatches.Groups[3].Value;
Regex ReplaceRegex = new Regex(regexp);
var input = (string)variables[variable];
var expanded = ReplaceRegex.Replace(input, newvalue);
template = template.Replace(all, expanded);
ReReplaceRegexMatches = ReReplaceRegexMatches.NextMatch();
}
// handle if ... else ... expression
Regex IfElseRegex = new Regex(@"{{if\s*(.+?)\s*}}(.*?){{\s*else\s*}}(.*?){{\s*end\s*}}");
var IfElseRegexMatches = IfElseRegex.Match(template);
@@ -441,6 +475,21 @@ namespace Jackett.Indexers
pairs["submitme"] = "X";
}
if (Login.Captcha != null)
{
var Captcha = Login.Captcha;
if (Captcha.Type == "image")
{
var CaptchaText = (StringItem)configData.GetDynamic("CaptchaText");
if (CaptchaText != null)
pairs[Captcha.Input] = CaptchaText.Value;
}
}
// clear landingResults/Document, otherwise we might use an old version for a new relogin (if GetConfigurationForSetup() wasn't called before)
landingResult = null;
landingResultDocument = null;
WebClientStringResult loginResult = null;
var enctype = form.GetAttribute("enctype");
if (enctype == "multipart/form-data")
@@ -560,6 +609,34 @@ namespace Jackett.Indexers
configData.AddDynamic("Captcha", CaptchaItem);
}
if (Login.Captcha != null)
{
var Captcha = Login.Captcha;
if (Captcha.Type == "image")
{
var captchaElement = landingResultDocument.QuerySelector(Captcha.Image);
if (captchaElement != null) {
var CaptchaUrl = resolvePath(captchaElement.GetAttribute("src"));
var captchaImageData = await RequestBytesWithCookies(CaptchaUrl.ToString(), landingResult.Cookies);
var CaptchaImage = new ImageItem { Name = "Captcha Image" };
var CaptchaText = new StringItem { Name = "Captcha Text" };
logger.Error("captchaImageData Cookies: " + captchaImageData.Cookies);
CaptchaImage.Value = captchaImageData.Content;
configData.AddDynamic("CaptchaImage", CaptchaImage);
configData.AddDynamic("CaptchaText", CaptchaText);
}
else
{
logger.Debug(string.Format("CardigannIndexer ({0}): No captcha image found", ID));
}
}
else
{
throw new NotImplementedException(string.Format("Captcha type \"{0}\" is not implemented", Captcha.Type));
}
}
return configData;
}
@@ -923,12 +1000,36 @@ namespace Jackett.Indexers
case "uploadvolumefactor":
release.UploadVolumeFactor = ParseUtil.CoerceDouble(value);
break;
case "minimumratio":
release.MinimumRatio = ParseUtil.CoerceDouble(value);
break;
case "minimumseedtime":
release.MinimumSeedTime = ParseUtil.CoerceLong(value);
break;
case "imdb":
Regex IMDBRegEx = new Regex(@"(\d+)", RegexOptions.Compiled);
var IMDBMatch = IMDBRegEx.Match(value);
var IMDBId = IMDBMatch.Groups[1].Value;
release.Imdb = ParseUtil.CoerceLong(IMDBId);
break;
case "rageid":
Regex RageIDRegEx = new Regex(@"(\d+)", RegexOptions.Compiled);
var RageIDMatch = RageIDRegEx.Match(value);
var RageID = RageIDMatch.Groups[1].Value;
release.RageID = ParseUtil.CoerceLong(RageID);
break;
case "tvdbid":
Regex TVDBIdRegEx = new Regex(@"(\d+)", RegexOptions.Compiled);
var TVDBIdMatch = TVDBIdRegEx.Match(value);
var TVDBId = TVDBIdMatch.Groups[1].Value;
release.TVDBId = ParseUtil.CoerceLong(TVDBId);
break;
case "banner":
if(!string.IsNullOrWhiteSpace(value)) {
var bannerurl = resolvePath(value);
release.BannerUrl = bannerurl;
}
break;
default:
break;
}
@@ -941,6 +1042,35 @@ namespace Jackett.Indexers
}
}
var Filters = Definition.Search.Rows.Filters;
var SkipRelease = false;
if (Filters != null)
{
foreach (filterBlock Filter in Filters)
{
switch (Filter.Name)
{
case "andmatch":
int CharacterLimit = -1;
if (Filter.Args != null)
CharacterLimit = int.Parse(Filter.Args);
if (!query.MatchQueryStringAND(release.Title, CharacterLimit))
{
logger.Debug(string.Format("CardigannIndexer ({0}): skipping {1} (andmatch filter)", ID, release.Title));
SkipRelease = true;
}
break;
default:
logger.Error(string.Format("CardigannIndexer ({0}): Unsupported rows filter: {1}", ID, Filter.Name));
break;
}
}
}
if (SkipRelease)
continue;
// if DateHeaders is set go through the previous rows and look for the header selector
var DateHeaders = Definition.Search.Rows.Dateheaders;
if (release.PublishDate == null && DateHeaders != null)
@@ -971,7 +1101,7 @@ namespace Jackett.Indexers
}
catch (Exception ex)
{
logger.Error(string.Format("CardigannIndexer ({0}): Error while parsing row '{1}': {2}", ID, Row.OuterHtml, ex));
logger.Error(string.Format("CardigannIndexer ({0}): Error while parsing row '{1}':\n\n{2}", ID, Row.OuterHtml, ex));
}
}
}
@@ -982,6 +1112,34 @@ namespace Jackett.Indexers
return releases;
}
public override async Task<byte[]> Download(Uri link)
{
if(Definition.Download != null)
{
var Download = Definition.Download;
if (Download.Selector != null)
{
var response = await RequestStringWithCookies(link.ToString());
var results = response.Content;
var SearchResultParser = new HtmlParser();
var SearchResultDocument = SearchResultParser.Parse(results);
var DlUri = SearchResultDocument.QuerySelector(Download.Selector);
if (DlUri != null)
{
logger.Debug(string.Format("CardigannIndexer ({0}): Download selector {1} matched:{2}", ID, Download.Selector, DlUri.OuterHtml));
var href = DlUri.GetAttribute("href");
link = resolvePath(href);
}
else
{
logger.Error(string.Format("CardigannIndexer ({0}): Download selector {1} didn't match:\n{2}", ID, Download.Selector, results));
throw new Exception(string.Format("Download selector {0} didn't match", Download.Selector));
}
}
}
return await base.Download(link);
}
}
}

View File

@@ -21,29 +21,35 @@ namespace Jackett.Indexers
{
public class HDTorrents : BaseIndexer, IIndexer
{
private string SearchUrl { get { return SiteLink + "torrents.php?"; } }
private string LoginUrl { get { return SiteLink + "login.php"; } }
private string UseLink { get { return (!String.IsNullOrEmpty(this.configData.AlternateLink.Value) ? this.configData.AlternateLink.Value : SiteLink); } }
private string SearchUrl { get { return UseLink + "torrents.php?"; } }
private string LoginUrl { get { return UseLink + "login.php"; } }
private const int MAXPAGES = 3;
private List<String> KnownURLs = new List<String> { "https://hdts.ru/", "https://hd-torrents.org/", "https://hd-torrents.net/", "https://hd-torrents.me/" };
new ConfigurationDataBasicLogin configData
new ConfigurationDataBasicLoginWithAlternateLink configData
{
get { return (ConfigurationDataBasicLogin)base.configData; }
get { return (ConfigurationDataBasicLoginWithAlternateLink)base.configData; }
set { base.configData = value; }
}
public HDTorrents(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
: 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
link: "https://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
manager: i,
client: w,
logger: l,
p: ps,
configData: new ConfigurationDataBasicLogin())
configData: new ConfigurationDataBasicLoginWithAlternateLink())
{
Encoding = Encoding.GetEncoding("UTF-8");
Language = "en-us";
this.configData.Instructions.Value = this.DisplayName + " has multiple URLs. The default (" + this.SiteLink + ") can be changed by entering a new value in the box below.";
this.configData.Instructions.Value += "The following are some known URLs for " + this.DisplayName;
this.configData.Instructions.Value += "<ul><li>" + String.Join("</li><li>", this.KnownURLs.ToArray()) + "</li></ul>";
TorznabCaps.Categories.Clear();
AddCategoryMapping("1", TorznabCatType.MoviesHD);// Movie/Blu-Ray
@@ -71,6 +77,9 @@ namespace Jackett.Indexers
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
configData.LoadValuesFromJson(configJson);
if (!string.IsNullOrWhiteSpace(configData.AlternateLink.Value) && !configData.AlternateLink.Value.EndsWith("/"))
configData.AlternateLink.Value += "/";
var loginPage = await RequestStringWithCookies(LoginUrl, string.Empty);
var pairs = new Dictionary<string, string> {
@@ -173,7 +182,14 @@ namespace Jackett.Indexers
string category = qRow.Find("td:eq(0) a").Attr("href").Replace("torrents.php?category=", "");
release.Category = MapTrackerCatToNewznab(category);
if (qRow.Find("img[alt=\"Silver Torrent\"]").Length >= 1)
release.UploadVolumeFactor = 1;
if (qRow.Find("img[alt=\"Free Torrent\"]").Length >= 1)
{
release.DownloadVolumeFactor = 0;
release.UploadVolumeFactor = 0;
}
else if (qRow.Find("img[alt=\"Silver Torrent\"]").Length >= 1)
release.DownloadVolumeFactor = 0.5;
else if (qRow.Find("img[alt=\"Bronze Torrent\"]").Length >= 1)
release.DownloadVolumeFactor = 0.75;
@@ -182,8 +198,6 @@ namespace Jackett.Indexers
else
release.DownloadVolumeFactor = 1;
release.UploadVolumeFactor = 1;
releases.Add(release);
}
}

View File

@@ -18,7 +18,8 @@ using System.Threading.Tasks;
using System.Web;
using System.Web.UI.WebControls;
using Jackett.Models.IndexerConfig;
using System.Collections.Specialized;
namespace Jackett.Indexers
{
public class Hounddawgs : BaseIndexer, IIndexer
@@ -46,21 +47,40 @@ namespace Jackett.Indexers
Encoding = Encoding.GetEncoding("UTF-8");
Language = "da-dk";
AddCategoryMapping(92, TorznabCatType.TV);
AddCategoryMapping(92, TorznabCatType.TVHD);
AddCategoryMapping(92, TorznabCatType.TVWEBDL);
AddCategoryMapping(93, TorznabCatType.TVSD);
AddCategoryMapping(93, TorznabCatType.TV);
AddCategoryMapping(57, TorznabCatType.TV);
AddCategoryMapping(57, TorznabCatType.TVHD);
AddCategoryMapping(57, TorznabCatType.TVWEBDL);
AddCategoryMapping(74, TorznabCatType.TVSD);
AddCategoryMapping(74, TorznabCatType.TV);
}
AddCategoryMapping(68, TorznabCatType.Movies3D, "3D");
AddCategoryMapping(80, TorznabCatType.PCPhoneAndroid, "Appz / Android");
AddCategoryMapping(86, TorznabCatType.PC0day, "Appz / Div");
AddCategoryMapping(71, TorznabCatType.PCPhoneIOS, "Appz / iOS");
AddCategoryMapping(70, TorznabCatType.PCMac, "Appz / Mac");
AddCategoryMapping(69, TorznabCatType.PC0day, "Appz / PC");
AddCategoryMapping(72, TorznabCatType.AudioAudiobook, "Audio Books");
AddCategoryMapping(82, TorznabCatType.MoviesBluRay, "BluRay/REMUX");
AddCategoryMapping(78, TorznabCatType.Books, "Books");
AddCategoryMapping(87, TorznabCatType.Other, "Cover");
AddCategoryMapping(90, TorznabCatType.MoviesDVD, "DK DVDr");
AddCategoryMapping(89, TorznabCatType.TVHD, "DK HD");
AddCategoryMapping(91, TorznabCatType.TVSD, "DK SD");
AddCategoryMapping(92, TorznabCatType.TVHD, "DK TV HD");
AddCategoryMapping(93, TorznabCatType.TVSD, "DK TV SD");
AddCategoryMapping(83, TorznabCatType.Other, "ELearning");
AddCategoryMapping(84, TorznabCatType.Movies, "Film Boxset");
AddCategoryMapping(81, TorznabCatType.MoviesSD, "Film CAM/TS");
AddCategoryMapping(60, TorznabCatType.MoviesDVD, "Film DVDr");
AddCategoryMapping(59, TorznabCatType.MoviesHD, "Film HD");
AddCategoryMapping(73, TorznabCatType.MoviesSD, "Film SD");
AddCategoryMapping(77, TorznabCatType.MoviesOther, "Film Tablet");
AddCategoryMapping(61, TorznabCatType.Audio, "Musik");
AddCategoryMapping(76, TorznabCatType.AudioVideo, "MusikVideo/Koncert");
AddCategoryMapping(75, TorznabCatType.Console, "Spil / Konsol");
AddCategoryMapping(79, TorznabCatType.PCMac, "Spil / Mac");
AddCategoryMapping(64, TorznabCatType.PCGames, "Spil / PC");
AddCategoryMapping(85, TorznabCatType.TV, "TV Boxset");
AddCategoryMapping(58, TorznabCatType.TVSD, "TV DVDr");
AddCategoryMapping(57, TorznabCatType.TVHD, "TV HD");
AddCategoryMapping(74, TorznabCatType.TVSD, "TV SD");
AddCategoryMapping(94, TorznabCatType.TVOTHER, "TV Tablet");
AddCategoryMapping(67, TorznabCatType.XXX, "XXX");
}
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
@@ -88,8 +108,25 @@ namespace Jackett.Indexers
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
var releases = new List<ReleaseInfo>();
var episodeSearchUrl = string.Format("{0}?&searchstr={1}", SearchUrl, HttpUtility.UrlEncode(query.GetQueryString()));
var results = await RequestStringWithCookiesAndRetry(episodeSearchUrl);
var searchString = query.GetQueryString();
var searchUrl = SearchUrl;
var queryCollection = new NameValueCollection();
queryCollection.Add("order_by", "time");
queryCollection.Add("order_way", "desc");
if (!string.IsNullOrWhiteSpace(searchString))
{
queryCollection.Add("searchstr", searchString);
}
foreach (var cat in MapTorznabCapsToTrackers(query))
{
queryCollection.Add("filter_cat[" + cat + "]", "1");
}
searchUrl += "?" + queryCollection.GetQueryString();
var results = await RequestStringWithCookiesAndRetry(searchUrl);
if (results.Content.Contains("Din søgning gav intet resultat."))
{
return releases;
@@ -106,17 +143,12 @@ namespace Jackett.Indexers
release.MinimumRatio = 1;
release.MinimumSeedTime = 172800;
var seriesCats = new[] { 92, 93, 57, 74 };
var qCat = row.ChildElements.ElementAt(0).ChildElements.ElementAt(0).Cq();
var catUrl = qCat.Attr("href");
var cat = catUrl.Substring(catUrl.LastIndexOf('[') + 1);
var catNo = int.Parse(cat.Trim(']'));
if (seriesCats.Contains(catNo))
release.Category = TorznabCatType.TV.ID;
else
continue;
var qAdded = row.ChildElements.ElementAt(4).ChildElements.ElementAt(0).Cq();
var cat = catUrl.Substring(catUrl.LastIndexOf('[') + 1).Trim(']');
release.Category = MapTrackerCatToNewznab(cat);
var qAdded = row.ChildElements.ElementAt(4).ChildElements.ElementAt(0).Cq();
var addedStr = qAdded.Attr("title");
release.PublishDate = DateTime.ParseExact(addedStr, "MMM dd yyyy, HH:mm", CultureInfo.InvariantCulture);

View File

@@ -100,6 +100,11 @@ namespace Jackett.Indexers
{
configData.LoadValuesFromJson(configJson);
// reset cookies, if we send expired cookies for a new session their code seems to get confused
// Due to the session not getting initiated correctly it will result in errors like this:
// Notice: Undefined index: simpleCaptchaAnswer in /var/www/html/takelogin.php on line 17
CookieHeader = null;
var result1 = await RequestStringWithCookies(CaptchaUrl);
var json1 = JObject.Parse(result1.Content);
var captchaSelection = json1["images"][0]["hash"];

View File

@@ -36,7 +36,7 @@ namespace Jackett.Indexers
public IPTorrents(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
: base(name: "IPTorrents",
description: "Always a step ahead.",
link: "https://ipt-update.com/",
link: "https://iptorrents.com/",
caps: new TorznabCapabilities(),
manager: i,
client: wc,
@@ -156,6 +156,7 @@ namespace Jackett.Indexers
Url = TakeLoginUrl,
Type = RequestType.POST,
Referer = UseLink,
Encoding = Encoding,
PostData = pairs
};
var response = await webclient.GetString(request);

View File

@@ -0,0 +1,32 @@
using Jackett.Models;
using NLog;
using Jackett.Services;
using Jackett.Utils.Clients;
using Jackett.Indexers.Abstract;
namespace Jackett.Indexers
{
public class PassTheHeadphones : GazelleTracker, IIndexer
{
public PassTheHeadphones(IIndexerManagerService indexerManager, IWebClient webClient, Logger logger, IProtectionService protectionService)
: base(name: "PassTheHeadphones",
desc: "A music tracker",
link: "https://passtheheadphones.me/",
indexerManager: indexerManager,
logger: logger,
protectionService: protectionService,
webClient: webClient
)
{
Language = "en-us";
AddCategoryMapping(1, TorznabCatType.Audio, "Music");
AddCategoryMapping(2, TorznabCatType.PC, "Applications");
AddCategoryMapping(3, TorznabCatType.Books, "E-Books");
AddCategoryMapping(4, TorznabCatType.AudioAudiobook, "Audiobooks");
AddCategoryMapping(5, TorznabCatType.Movies, "E-Learning Videos");
AddCategoryMapping(6, TorznabCatType.TV, "Comedy");
AddCategoryMapping(7, TorznabCatType.Books, "Comics");
}
}
}

View File

@@ -166,7 +166,7 @@ namespace Jackett.Indexers
protected void AddResultCategoryMapping(string trackerCategory, TorznabCategory newznabCategory)
{
resultMapping.Add(new CategoryMapping(trackerCategory.ToString(), newznabCategory.ID));
resultMapping.Add(new CategoryMapping(trackerCategory.ToString(), null, newznabCategory.ID));
if (!TorznabCaps.Categories.Contains(newznabCategory))
TorznabCaps.Categories.Add(newznabCategory);
}

View File

@@ -117,15 +117,14 @@ namespace Jackett.Indexers
var searchString = query.GetQueryString();
var cats = MapTorznabCapsToTrackers(query);
string cat = "0";
string cat = "a1";
if (cats.Count == 1)
{
cat = cats[0];
}
if (!string.IsNullOrWhiteSpace(searchString) || cat != "0")
searchUrl += string.Format("?search={0}&param_val=0&complex_search=0&incldead={1}&orderby=added&sort=desc", HttpUtility.UrlEncode(searchString), cat);
searchUrl += string.Format("?search={0}&param_val=0&complex_search=0&incldead={1}&orderby=added&sort=desc", HttpUtility.UrlEncode(searchString), cat);
var response = await RequestStringWithCookiesAndRetry(searchUrl, null, BrowseUrl);
var results = response.Content;
@@ -165,8 +164,10 @@ namespace Jackett.Indexers
release.DownloadVolumeFactor = 0;
release.UploadVolumeFactor = 1;
var catLink = qRow.Find("a[onclick^=\"bparam('incldead=\"]");
var catLink = qRow.Find("a[onclick^=\"bparam(\"][onclick*=\"cat\"]");
var catId = catLink.Attr("onclick").Split('=')[1].Replace("');", "");
if (!catId.StartsWith("scat"))
catId = "mc" + catId;
release.Category = MapTrackerCatToNewznab(catId);
releases.Add(release);

View File

@@ -151,7 +151,7 @@ namespace Jackett.Indexers
var searchString = query.GetQueryString();
// If we have no query use the RSS Page as their server is slow enough at times!
if (string.IsNullOrWhiteSpace(searchString))
if (query.IsTest || string.IsNullOrWhiteSpace(searchString))
{
var rssPage = await RequestStringWithCookiesAndRetry(string.Format(RSSUrl, configData.RSSKey.Value));
var rssDoc = XDocument.Parse(rssPage.Content);
@@ -195,7 +195,7 @@ namespace Jackett.Indexers
releases.Add(release);
}
}
else
if (query.IsTest || !string.IsNullOrWhiteSpace(searchString))
{
// The TVChaos UK search requires an exact match of the search string.
// But it seems like they just send the unfiltered search to the SQL server in a like query (LIKE '%$searchstring%').
@@ -212,6 +212,13 @@ namespace Jackett.Indexers
};
var searchPage = await PostDataWithCookiesAndRetry(SearchUrl, searchParams);
if (searchPage.IsRedirect)
{
// re-login
await ApplyConfiguration(null);
searchPage = await PostDataWithCookiesAndRetry(SearchUrl, searchParams);
}
try
{
CQ dom = searchPage.Content;

View File

@@ -48,7 +48,7 @@ namespace Jackett.Indexers
public TorrentDay(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
: base(name: "TorrentDay",
description: "TorrentDay",
link: "https://www.torrentday.com/",
link: "https://torrentday.it/",
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
manager: i,
client: wc,

View File

@@ -53,19 +53,27 @@ namespace Jackett.Indexers
AddCategoryMapping(14, TorznabCatType.MoviesHD);
AddCategoryMapping(15, TorznabCatType.Movies); // Boxsets
AddCategoryMapping(29, TorznabCatType.TVDocumentary);
AddCategoryMapping(41, TorznabCatType.MoviesHD, "Movies/4K");
AddCategoryMapping(36, TorznabCatType.MoviesForeign);
AddCategoryMapping(37, TorznabCatType.MoviesWEBDL);
AddCategoryMapping(43, TorznabCatType.MoviesSD, "Movies/HDRip");
AddCategoryMapping(26, TorznabCatType.TVSD);
AddCategoryMapping(27, TorznabCatType.TV); // Boxsets
AddCategoryMapping(32, TorznabCatType.TVHD);
AddCategoryMapping(44, TorznabCatType.TVFOREIGN, "TV/Foreign");
AddCategoryMapping(17, TorznabCatType.PCGames);
AddCategoryMapping(18, TorznabCatType.ConsoleXbox);
AddCategoryMapping(19, TorznabCatType.ConsoleXbox360);
// 20 PS2
AddCategoryMapping(40, TorznabCatType.ConsoleXbox, "Games/XBOXONE");
AddCategoryMapping(20, TorznabCatType.ConsolePS3); // PS2
AddCategoryMapping(21, TorznabCatType.ConsolePS3);
AddCategoryMapping(22, TorznabCatType.ConsolePSP);
AddCategoryMapping(28, TorznabCatType.ConsoleWii);
AddCategoryMapping(30, TorznabCatType.ConsoleNDS);
AddCategoryMapping(39, TorznabCatType.ConsolePS4);
AddCategoryMapping(42, TorznabCatType.PCMac, "Games/Mac");
AddCategoryMapping(16, TorznabCatType.AudioVideo);
AddCategoryMapping(31, TorznabCatType.Audio);
@@ -74,11 +82,15 @@ namespace Jackett.Indexers
AddCategoryMapping(35, TorznabCatType.TV); // Cartoons
AddCategoryMapping(5, TorznabCatType.Books);
AddCategoryMapping(45, TorznabCatType.BooksEbook, "Books/EBooks");
AddCategoryMapping(46, TorznabCatType.BooksComics, "Books/Comics");
AddCategoryMapping(23, TorznabCatType.PCISO);
AddCategoryMapping(24, TorznabCatType.PCMac);
AddCategoryMapping(25, TorznabCatType.PCPhoneOther);
AddCategoryMapping(33, TorznabCatType.PC0day);
AddCategoryMapping(38, TorznabCatType.Other, "Education");
}
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
@@ -92,30 +104,20 @@ namespace Jackett.Indexers
{
var pairs = new Dictionary<string, string> {
{ "username", configData.Username.Value },
{ "password", configData.Password.Value },
{ "remember_me", "on" },
{ "login", "submit" }
{ "password", configData.Password.Value }
};
var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, null, true, null, LoginUrl);
await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("/user/account/logout"), () =>
{
CQ dom = result.Content;
var messageEl = dom[".ui-state-error"].Last();
var errorMessage = messageEl.Text().Trim();
var errorMessage = dom["div#login_heading + div.card-panel-error"].Text();
throw new ExceptionWithConfigData(errorMessage, configData);
});
}
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
var loggedInCheck = await RequestStringWithCookies(SearchUrl);
if (!loggedInCheck.Content.Contains("/logout.php"))
{
//Cookie appears to expire after a period of time or logging in to the site via browser
await DoLogin();
}
var releases = new List<ReleaseInfo>();
var searchString = query.GetQueryString();
searchString = searchString.Replace('-', ' '); // remove dashes as they exclude search strings
@@ -144,6 +146,14 @@ namespace Jackett.Indexers
}
var results = await RequestStringWithCookiesAndRetry(searchUrl);
if (!results.Content.Contains("/user/account/logout"))
{
//Cookie appears to expire after a period of time or logging in to the site via browser
await DoLogin();
results = await RequestStringWithCookiesAndRetry(searchUrl);
}
try
{
CQ dom = results.Content;
@@ -165,18 +175,14 @@ namespace Jackett.Indexers
release.Guid = new Uri(SiteLink + qLink.Attr("href").Substring(1));
release.Comments = release.Guid;
release.Title = qLink.Text();
release.Description = release.Title;
release.Link = new Uri(SiteLink + qRow.Find(".quickdownload > a").Attr("href").Substring(1));
if (!query.MatchQueryStringAND(release.Title))
continue;
var dateString = qRow.Find(".name")[0].InnerText.Trim().Replace(" ", string.Empty).Replace("Addedinon", string.Empty);
release.Link = new Uri(qRow.Find(".quickdownload > a").Attr("href"));
//Fix for issue 2016-04-30
dateString = dateString.Replace("\r", "").Replace("\n", "");
//"2015-04-25 23:38:12"
//"yyyy-MMM-dd hh:mm:ss"
release.PublishDate = DateTime.ParseExact(dateString, "yyyy-MM-ddHH:mm:ss", CultureInfo.InvariantCulture);
var dateString = qRow.Find("span.addedInLine").Get(0).LastChild.NodeValue.Replace("on", string.Empty).Trim(); ;
release.PublishDate = DateTime.ParseExact(dateString, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
var sizeStr = qRow.Children().ElementAt(4).InnerText;
release.Size = ReleaseInfo.GetBytes(sizeStr);

View File

@@ -132,6 +132,7 @@ namespace Jackett.Indexers
// use AND+wildcard operator to avoid getting to many useless results
var searchStringArray = Regex.Split(searchString.Trim(), "[ _.-]+", RegexOptions.Compiled).ToList();
searchStringArray = searchStringArray.Where(x => x.Length >= 3).ToList(); // remove words with less than 3 characters
searchStringArray = searchStringArray.Where(x => !new string[] { "der", "die", "das", "the" }.Contains(x.ToLower())).ToList(); // remove words with less than 3 characters
searchStringArray = searchStringArray.Select(x => "+" + x + "*").ToList(); // add AND operators+wildcards
var searchStringFinal = String.Join(" ", searchStringArray);
queryCollection.Add("search", searchStringFinal);
@@ -149,6 +150,7 @@ namespace Jackett.Indexers
{
CQ dom = results.Content;
var rows = dom["table.torrent_table > tbody > tr"];
var globalFreeleech = dom.Find("legend:contains(\"Freeleech\")+ul > li > b:contains(\"Freeleech\")").Any();
foreach (var row in rows.Skip(1))
{
var release = new ReleaseInfo();
@@ -168,7 +170,7 @@ namespace Jackett.Indexers
var qCommentLink = descCol.FirstElementChild.Cq();
var torrentTag = descCol.Cq().Find("span.torrent-tag");
var torrentTags = torrentTag.Elements.Select(x => x.InnerHTML).ToList();
release.Title = qCommentLink.Text();
release.Title = qCommentLink.Attr("title");
release.Description = String.Join(", ", torrentTags);
release.Comments = new Uri(SiteLink + "/" + qCommentLink.Attr("href").Replace("&hit=1", ""));
release.Guid = release.Comments;
@@ -195,7 +197,9 @@ namespace Jackett.Indexers
var grabs = qRow.Find("td:nth-child(7)").Text();
release.Grabs = ParseUtil.CoerceInt(grabs);
if (qRow.Find("span.torrent-tag-free").Length >= 1)
if (globalFreeleech)
release.DownloadVolumeFactor = 0;
else if (qRow.Find("span.torrent-tag-free").Length >= 1)
release.DownloadVolumeFactor = 0;
else
release.DownloadVolumeFactor = 1;

View File

@@ -0,0 +1,219 @@
using Jackett.Utils.Clients;
using NLog;
using Jackett.Services;
using Jackett.Utils;
using Jackett.Models;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System;
using System.Text;
using System.Globalization;
using Jackett.Models.IndexerConfig;
using System.Collections.Specialized;
using AngleSharp.Parser.Html;
using AngleSharp.Dom;
using System.Text.RegularExpressions;
using System.Web;
namespace Jackett.Indexers
{
public class Torrentech : BaseIndexer, IIndexer
{
string LoginUrl { get { return SiteLink + "index.php?act=Login&CODE=01&CookieDate=1"; } }
string IndexUrl { get { return SiteLink + "index.php"; } }
new ConfigurationDataBasicLoginWithRSSAndDisplay configData
{
get { return (ConfigurationDataBasicLoginWithRSSAndDisplay)base.configData; }
set { base.configData = value; }
}
public Torrentech(IIndexerManagerService i, IWebClient wc, Logger l, IProtectionService ps)
: base(name: "Torrentech",
description: null,
link: "https://www.torrentech.org/",
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
manager: i,
client: wc,
logger: l,
p: ps,
configData: new ConfigurationDataBasicLoginWithRSSAndDisplay())
{
Encoding = Encoding.UTF8;
Language = "en-us";
AddCategoryMapping(1, TorznabCatType.AudioMP3);
AddCategoryMapping(2, TorznabCatType.AudioLossless);
AddCategoryMapping(3, TorznabCatType.AudioOther);
}
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
configData.LoadValuesFromJson(configJson);
var pairs = new Dictionary<string, string>
{
{ "UserName", configData.Username.Value },
{ "PassWord", configData.Password.Value }
};
var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, null, true, null, LoginUrl, true);
await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("Logged in as: "), () =>
{
var errorMessage = result.Content;
throw new ExceptionWithConfigData(errorMessage, configData);
});
return IndexerConfigurationStatus.RequiresTesting;
}
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
var releases = new List<ReleaseInfo>();
var searchString = query.GetQueryString();
WebClientStringResult results = null;
var queryCollection = new NameValueCollection();
queryCollection.Add("act", "search");
queryCollection.Add("forums", "all");
queryCollection.Add("torrents", "1");
queryCollection.Add("search_in", "titles");
queryCollection.Add("result_type", "topics");
// if the search string is empty use the getnew view
if (string.IsNullOrWhiteSpace(searchString))
{
queryCollection.Add("CODE", "getnew");
queryCollection.Add("active", "1");
}
else // use the normal search
{
searchString = searchString.Replace("-", " ");
queryCollection.Add("CODE", "01");
queryCollection.Add("keywords", searchString);
}
var searchUrl = IndexUrl + "?" + queryCollection.GetQueryString();
results = await RequestStringWithCookies(searchUrl);
if (results.IsRedirect && results.RedirectingTo.Contains("CODE=show"))
{
results = await RequestStringWithCookies(results.RedirectingTo);
}
try
{
string RowsSelector = "div.borderwrap:has(div.maintitle) > table > tbody > tr:has(a[href*=\"index.php?showtopic=\"])";
var SearchResultParser = new HtmlParser();
var SearchResultDocument = SearchResultParser.Parse(results.Content);
var Rows = SearchResultDocument.QuerySelectorAll(RowsSelector);
foreach (var Row in Rows)
{
try
{
var release = new ReleaseInfo();
var StatsElements = Row.QuerySelector("td:nth-child(5)");
var stats = StatsElements.TextContent.Split('·');
if (stats.Length != 3) // not a torrent
continue;
release.Seeders = ParseUtil.CoerceInt(stats[0]);
release.Peers = ParseUtil.CoerceInt(stats[1]) + release.Seeders;
release.Grabs = ParseUtil.CoerceInt(stats[2]);
release.MinimumRatio = 0.51;
release.MinimumSeedTime = 0;
var qDetailsLink = Row.QuerySelector("a[onmouseover][href*=\"index.php?showtopic=\"]");
release.Title = qDetailsLink.TextContent;
release.Comments = new Uri(qDetailsLink.GetAttribute("href"));
release.Link = release.Comments;
release.Guid = release.Link;
release.DownloadVolumeFactor = 1;
release.UploadVolumeFactor = 1;
var id = HttpUtility.ParseQueryString(release.Comments.Query).Get("showtopic");
var desc = Row.QuerySelector("span.desc");
var forange = desc.QuerySelector("font.forange");
if (forange != null)
{
var DownloadVolumeFactor = forange.QuerySelector("i:contains(\"freeleech\")");
if (DownloadVolumeFactor != null)
release.DownloadVolumeFactor = 0;
var UploadVolumeFactor = forange.QuerySelector("i:contains(\"x upload]\")");
if (UploadVolumeFactor != null)
release.UploadVolumeFactor = ParseUtil.CoerceDouble(UploadVolumeFactor.TextContent.Split(' ')[0].Substring(1).Replace("x", ""));
forange.Remove();
}
var format = desc.TextContent;
release.Title += " [" + format + "]";
var preview = SearchResultDocument.QuerySelector("div#d21-tph-preview-data-" + id);
if (preview != null)
{
release.Description = "";
foreach (var e in preview.ChildNodes)
{
if (e.NodeType == NodeType.Text)
release.Description += e.NodeValue;
else
release.Description += e.TextContent + "\n";
}
}
release.Description = HttpUtility.HtmlEncode(release.Description.Trim());
release.Description = release.Description.Replace("\n", "<br>");
if (format.Contains("MP3"))
release.Category = TorznabCatType.AudioMP3.ID;
else if (format.Contains("Lossless"))
release.Category = TorznabCatType.AudioLossless.ID;
else
release.Category = TorznabCatType.AudioOther.ID;
var lastAction = Row.QuerySelector("td:nth-child(9) > span").FirstChild.NodeValue;
release.PublishDate = DateTimeUtil.FromUnknown(lastAction, "UK");
releases.Add(release);
}
catch (Exception ex)
{
logger.Error(string.Format("{0}: Error while parsing row '{1}':\n\n{2}", ID, Row.OuterHtml, ex));
}
}
}
catch (Exception ex)
{
OnParseError(results.Content, ex);
}
return releases;
}
public override async Task<byte[]> Download(Uri link)
{
var response = await RequestStringWithCookies(link.ToString());
var results = response.Content;
var SearchResultParser = new HtmlParser();
var SearchResultDocument = SearchResultParser.Parse(results);
var downloadSelector = "a[title=\"Download attachment\"]";
var DlUri = SearchResultDocument.QuerySelector(downloadSelector);
if (DlUri != null)
{
logger.Debug(string.Format("{0}: Download selector {1} matched:{2}", ID, downloadSelector, DlUri.OuterHtml));
var href = DlUri.GetAttribute("href");
link = new Uri(href);
}
else
{
logger.Error(string.Format("{0}: Download selector {1} didn't match:\n{2}", ID, downloadSelector, results));
throw new Exception(string.Format("Download selector {0} didn't match", downloadSelector));
}
return await base.Download(link);
}
}
}

View File

@@ -0,0 +1,32 @@
using Jackett.Models;
using NLog;
using Jackett.Services;
using Jackett.Utils.Clients;
using Jackett.Indexers.Abstract;
namespace Jackett.Indexers
{
public class nostream : GazelleTracker, IIndexer
{
public nostream(IIndexerManagerService indexerManager, IWebClient webClient, Logger logger, IProtectionService protectionService)
: base(name: "nostream",
desc: "A music tracker",
link: "https://nostre.am/",
indexerManager: indexerManager,
logger: logger,
protectionService: protectionService,
webClient: webClient
)
{
Language = "en-us";
AddCategoryMapping(1, TorznabCatType.Audio, "Music");
AddCategoryMapping(2, TorznabCatType.PC, "Applications");
AddCategoryMapping(3, TorznabCatType.Books, "E-Books");
AddCategoryMapping(4, TorznabCatType.AudioAudiobook, "Audiobooks");
AddCategoryMapping(5, TorznabCatType.Movies, "E-Learning Videos");
AddCategoryMapping(6, TorznabCatType.TV, "Comedy");
AddCategoryMapping(7, TorznabCatType.Books, "Comics");
}
}
}

View File

@@ -0,0 +1,32 @@
using Jackett.Models;
using NLog;
using Jackett.Services;
using Jackett.Utils.Clients;
using Jackett.Indexers.Abstract;
namespace Jackett.Indexers
{
public class notwhatcd : GazelleTracker, IIndexer
{
public notwhatcd(IIndexerManagerService indexerManager, IWebClient webClient, Logger logger, IProtectionService protectionService)
: base(name: "notwhat.cd",
desc: "A music tracker",
link: "https://notwhat.cd/",
indexerManager: indexerManager,
logger: logger,
protectionService: protectionService,
webClient: webClient
)
{
Language = "en-us";
AddCategoryMapping(1, TorznabCatType.Audio, "Music");
AddCategoryMapping(2, TorznabCatType.PC, "Applications");
AddCategoryMapping(3, TorznabCatType.Books, "E-Books");
AddCategoryMapping(4, TorznabCatType.AudioAudiobook, "Audiobooks");
AddCategoryMapping(5, TorznabCatType.Movies, "E-Learning Videos");
AddCategoryMapping(6, TorznabCatType.TV, "Comedy");
AddCategoryMapping(7, TorznabCatType.Books, "Comics");
}
}
}

View File

@@ -187,9 +187,6 @@ namespace Jackett.Indexers
release.DownloadVolumeFactor = 1;
release.UploadVolumeFactor = 1;
// time is needed for sonarr, just set it to now
release.PublishDate = DateTime.Now;
releases.Add(release);
}
}

View File

@@ -165,7 +165,12 @@
<Compile Include="Controllers\TorznabController.cs" />
<Compile Include="Controllers\DownloadController.cs" />
<Compile Include="Engine.cs" />
<Compile Include="Indexers\Abstract\GazelleTracker.cs" />
<Compile Include="Indexers\AnimeTorrents.cs" />
<Compile Include="Indexers\Torrentech.cs" />
<Compile Include="Indexers\nostream.cs" />
<Compile Include="Indexers\notwhatcd.cs" />
<Compile Include="Indexers\PassTheHeadphones.cs" />
<Compile Include="Indexers\Norbits.cs" />
<Compile Include="Indexers\TVVault.cs" />
<Compile Include="Indexers\BJShare.cs" />
@@ -443,6 +448,48 @@
<Content Include="Definitions\totheglory.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\gormogon.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\qctorrent.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\torviet.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\icetorrent.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\xtremezone.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\datascene.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\utorrents.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\torrentsmd.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\fanoin.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\rapidetracker.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\hdclub.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\trancetraffic.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\bithq.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\chdbits.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Include="packages.config">
<SubType>Designer</SubType>
</None>

View File

@@ -8,13 +8,15 @@ namespace Jackett.Models
{
class CategoryMapping
{
public CategoryMapping(string trackerCat, int newzCat)
public CategoryMapping(string trackerCat, string trackerCatDesc, int newzCat)
{
TrackerCategory = trackerCat;
TrackerCategoryDesc = trackerCatDesc;
NewzNabCategory = newzCat;
}
public string TrackerCategory { get; private set; }
public string TrackerCategoryDesc { get; private set; }
public int NewzNabCategory { get; private set; }
}
}

View File

@@ -68,7 +68,7 @@ namespace Jackett.Models
new XElement("title", r.Title),
new XElement("guid", r.Guid),
r.Comments == null ? null : new XElement("comments", r.Comments.ToString()),
r.PublishDate == DateTime.MinValue ? null : new XElement("pubDate", xmlDateFormat(r.PublishDate)),
r.PublishDate == DateTime.MinValue ? new XElement("pubDate", DateTime.Now) : new XElement("pubDate", xmlDateFormat(r.PublishDate)),
r.Size == null ? null : new XElement("size", r.Size),
r.Files == null ? null : new XElement("files", r.Files),
r.Grabs == null ? null : new XElement("grabs", r.Grabs),

View File

@@ -68,13 +68,21 @@ namespace Jackett.Models
// Some trackers don't support AND logic for search terms resulting in unwanted results.
// Using this method we can AND filter it within jackett.
public bool MatchQueryStringAND(string title)
// With limit we can limit the amount of characters which should be compared (use it if a tracker doesn't return the full title).
public bool MatchQueryStringAND(string title, int limit = -1)
{
// We cache the regex split results so we have to do it only once for each query.
if (QueryStringParts == null)
{
var queryString = GetQueryString();
if (limit > 0)
{
if (limit > queryString.Length)
limit = queryString.Length;
queryString = queryString.Substring(0, limit);
}
Regex SplitRegex = new Regex("[^a-zA-Z0-9]+");
QueryStringParts = SplitRegex.Split(GetQueryString());
QueryStringParts = SplitRegex.Split(queryString);
}
// Check if each part of the query string is in the given title.

View File

@@ -28,7 +28,7 @@ namespace Jackett.Utils.Clients
{
logger.Debug(string.Format("IWebClient.GetBytes(Url:{0})", request.Url));
var result = await Run(request);
logger.Debug(string.Format("IWebClient: Returning {0} => {1} bytes", result.Status, (result.IsRedirect ? result.RedirectingTo + " " : " ") + (result.Content == null ? "<NULL>" : result.Content.Length.ToString())));
logger.Debug(string.Format("IWebClient: Returning {0} => {1} bytes", result.Status, (result.IsRedirect ? result.RedirectingTo + " " : "") + (result.Content == null ? "<NULL>" : result.Content.Length.ToString())));
return result;
}
@@ -75,7 +75,7 @@ namespace Jackett.Utils.Clients
decodedContent = encoding.GetString(result.Content);
stringResult.Content = decodedContent;
logger.Debug(string.Format("IWebClient: Returning {0} => {1}", result.Status, (result.IsRedirect ? result.RedirectingTo + " " : " ") + (decodedContent == null ? "<NULL>" : decodedContent)));
logger.Debug(string.Format("IWebClient: Returning {0} => {1}", result.Status, (result.IsRedirect ? result.RedirectingTo + " " : "") + (decodedContent == null ? "<NULL>" : decodedContent)));
string[] server;
if (stringResult.Headers.TryGetValue("server", out server))

View File

@@ -13,6 +13,13 @@ namespace Jackett.Utils
{
public static string RFC1123ZPattern = "ddd, dd MMM yyyy HH':'mm':'ss z";
public static DateTime UnixTimestampToDateTime(long unixTime)
{
DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
dt = dt.AddSeconds(unixTime).ToLocalTime();
return dt;
}
public static DateTime UnixTimestampToDateTime(double unixTime)
{
DateTime unixStart = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
@@ -98,10 +105,16 @@ namespace Jackett.Utils
// Uses the DateTimeRoutines library to parse the date
// http://www.codeproject.com/Articles/33298/C-Date-Time-Parser
public static DateTime FromFuzzyTime(string str, DateTimeRoutines.DateTimeFormat format = DateTimeRoutines.DateTimeFormat.USA_DATE)
public static DateTime FromFuzzyTime(string str, string format = null)
{
DateTimeRoutines.DateTimeFormat dt_format = DateTimeRoutines.DateTimeFormat.USA_DATE;
if (format == "UK")
{
dt_format = DateTimeRoutines.DateTimeFormat.UK_DATE;
}
DateTimeRoutines.ParsedDateTime dt;
if (DateTimeRoutines.TryParseDateOrTime(str, format, out dt))
if (DateTimeRoutines.TryParseDateOrTime(str, dt_format, out dt))
{
return dt.DateTime;
}
@@ -115,7 +128,7 @@ namespace Jackett.Utils
public static Regex missingYearRegexp = new Regex(@"^\d{1,2}-\d{1,2}\b", RegexOptions.Compiled);
public static Regex missingYearRegexp2 = new Regex(@"^(\d{1,2}\s+\w{3})\s+(\d{1,2}\:\d{1,2}.*)$", RegexOptions.Compiled); // 1 Jan 10:30
public static DateTime FromUnknown(string str)
public static DateTime FromUnknown(string str, string format = null)
{
try {
str = ParseUtil.NormalizeSpace(str);
@@ -170,9 +183,7 @@ namespace Jackett.Utils
{
// try parsing the str as an unix timestamp
var unixTimeStamp = long.Parse(str);
DateTime dt = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
dt = dt.AddSeconds(unixTimeStamp).ToLocalTime();
return dt;
return UnixTimestampToDateTime(unixTimeStamp);
}
catch (FormatException)
{
@@ -196,7 +207,8 @@ namespace Jackett.Utils
var time = match.Groups[2].Value;
str = date + " " + DateTime.Now.Year.ToString() + " " + time;
}
return FromFuzzyTime(str);
return FromFuzzyTime(str, format);
}
catch (Exception ex)
{

View File

@@ -15,6 +15,11 @@ namespace Jackett.Utils
return s.Trim();
}
public static string NormalizeMultiSpaces(string s)
{
return new Regex(@"\s+").Replace(NormalizeSpace(s), " "); ;
}
public static string NormalizeNumber(string s)
{
var normalized = NormalizeSpace(s);

View File

@@ -79,7 +79,7 @@ namespace Jackett.Utils
private static string CleanTitle(string title)
{
title = title.Replace(':', ' ').Replace('.', ' ').Replace('-', ' ').Replace('_', ' ').Replace('+', ' ').Replace("'", "");
title = title.Replace(':', ' ').Replace('.', ' ').Replace('-', ' ').Replace('_', ' ').Replace('+', ' ').Replace("'", "").Replace("[", "").Replace("]", "").Replace("(", "").Replace(")", "");
return reduceSpacesRegex.Replace(title, " ").ToLowerInvariant();
}
}