mirror of
https://github.com/Jackett/Jackett.git
synced 2025-12-21 13:52:16 +01:00
Compare commits
90 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
657bb15282 | ||
|
|
069c64f504 | ||
|
|
65c1aed251 | ||
|
|
e8e4289b20 | ||
|
|
0838a0b258 | ||
|
|
8e8f143b02 | ||
|
|
2e56f662cd | ||
|
|
440d59a30e | ||
|
|
286ef8396a | ||
|
|
772df7a4c1 | ||
|
|
134fd3f4cf | ||
|
|
ae8f8f7ccd | ||
|
|
f8637051fa | ||
|
|
eb0e82494c | ||
|
|
265b949de9 | ||
|
|
34acbed7f0 | ||
|
|
42eb68ba76 | ||
|
|
37591c6da6 | ||
|
|
f5a8ad61b9 | ||
|
|
e064fd8ccd | ||
|
|
8a9949ac93 | ||
|
|
40dde036d6 | ||
|
|
171205bdee | ||
|
|
03e0c6d67e | ||
|
|
91500c95e6 | ||
|
|
8a082b0668 | ||
|
|
650b6986f9 | ||
|
|
82fd53226c | ||
|
|
77fd3e206b | ||
|
|
3989f35827 | ||
|
|
82376a508a | ||
|
|
4f9ce14e2f | ||
|
|
60a2ffbe41 | ||
|
|
15598e3d66 | ||
|
|
357be7dda9 | ||
|
|
a0aa77519b | ||
|
|
f3ef590d3f | ||
|
|
d347ea71b8 | ||
|
|
62f0bdc19c | ||
|
|
e92b925eab | ||
|
|
e8239f4899 | ||
|
|
5c855d3b50 | ||
|
|
6dfaff6aad | ||
|
|
849b9e9765 | ||
|
|
eacfd53466 | ||
|
|
4459697fe5 | ||
|
|
94872affa9 | ||
|
|
a29064e7fb | ||
|
|
679cba4297 | ||
|
|
f155a21ee8 | ||
|
|
0913ee4934 | ||
|
|
1fa0384eb8 | ||
|
|
59727fe8fc | ||
|
|
28707fa146 | ||
|
|
f408abe7a4 | ||
|
|
42434c35a1 | ||
|
|
df941c54ce | ||
|
|
f2eb4dacd0 | ||
|
|
9795587e4d | ||
|
|
15064810f8 | ||
|
|
fbfee66c7b | ||
|
|
53e2d9e9cd | ||
|
|
49fd078a4c | ||
|
|
3dfba7c204 | ||
|
|
0e59621650 | ||
|
|
c2f4cc97ab | ||
|
|
5fc7fca5c6 | ||
|
|
7b2dd93f2f | ||
|
|
a8ddf21081 | ||
|
|
7db50dba49 | ||
|
|
9d30f833da | ||
|
|
bf959f1c29 | ||
|
|
1cde5c5142 | ||
|
|
58a7de145a | ||
|
|
9a66289a26 | ||
|
|
6201712ce9 | ||
|
|
f921df948c | ||
|
|
059701fbf6 | ||
|
|
addf98e9a3 | ||
|
|
f124b7e30b | ||
|
|
0fc2a3083c | ||
|
|
01141b8cc1 | ||
|
|
be542272d1 | ||
|
|
2c4f18128a | ||
|
|
adbd6c9d0d | ||
|
|
a854771950 | ||
|
|
b4fafe2845 | ||
|
|
1050157546 | ||
|
|
6f54958ec0 | ||
|
|
a53fc1e8cb |
16
README.md
16
README.md
@@ -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
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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>');
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
downloadvolumefactor:
|
||||
case:
|
||||
":root div.alertbar:contains(\"freeleech\")": "0"
|
||||
":root div.alertbar:contains(\"FREELEECH\")": "0"
|
||||
"*": "1"
|
||||
uploadvolumefactor:
|
||||
case:
|
||||
|
||||
92
src/Jackett/Definitions/bithq.yml
Normal file
92
src/Jackett/Definitions/bithq.yml
Normal 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"
|
||||
101
src/Jackett/Definitions/chdbits.yml
Normal file
101
src/Jackett/Definitions/chdbits.yml
Normal 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
|
||||
118
src/Jackett/Definitions/datascene.yml
Normal file
118
src/Jackett/Definitions/datascene.yml
Normal 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
|
||||
129
src/Jackett/Definitions/fanoin.yml
Normal file
129
src/Jackett/Definitions/fanoin.yml
Normal 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="]
|
||||
@@ -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"
|
||||
192
src/Jackett/Definitions/gormogon.yml
Normal file
192
src/Jackett/Definitions/gormogon.yml
Normal 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"
|
||||
97
src/Jackett/Definitions/hdclub.yml
Normal file
97
src/Jackett/Definitions/hdclub.yml
Normal 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"
|
||||
129
src/Jackett/Definitions/icetorrent.yml
Normal file
129
src/Jackett/Definitions/icetorrent.yml
Normal 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"
|
||||
@@ -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:
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -77,6 +77,8 @@
|
||||
|
||||
rows:
|
||||
selector: table.tableinborder[summary] > tbody > tr
|
||||
filters:
|
||||
- name: andmatch
|
||||
fields:
|
||||
download:
|
||||
selector: a[href^="download.php?torrent="]
|
||||
|
||||
106
src/Jackett/Definitions/qctorrent.yml
Normal file
106
src/Jackett/Definitions/qctorrent.yml
Normal 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
|
||||
167
src/Jackett/Definitions/rapidetracker.yml
Normal file
167
src/Jackett/Definitions/rapidetracker.yml
Normal 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"
|
||||
@@ -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:
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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="]
|
||||
|
||||
@@ -122,7 +122,7 @@
|
||||
details:
|
||||
selector: a[onmouseover][href^="torrents-details.php?id="]
|
||||
attribute: href
|
||||
details:
|
||||
comments:
|
||||
selector: a[href*="#comments"]
|
||||
attribute: href
|
||||
size:
|
||||
|
||||
93
src/Jackett/Definitions/torrentsmd.yml
Normal file
93
src/Jackett/Definitions/torrentsmd.yml
Normal 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"
|
||||
129
src/Jackett/Definitions/torviet.yml
Normal file
129
src/Jackett/Definitions/torviet.yml
Normal 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"
|
||||
70
src/Jackett/Definitions/trancetraffic.yml
Normal file
70
src/Jackett/Definitions/trancetraffic.yml
Normal 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"
|
||||
@@ -101,6 +101,8 @@
|
||||
|
||||
rows:
|
||||
selector: table.ttable_headinner > tbody > tr.t-row
|
||||
filters:
|
||||
- name: andmatch
|
||||
after: 1
|
||||
fields:
|
||||
download:
|
||||
|
||||
127
src/Jackett/Definitions/utorrents.yml
Normal file
127
src/Jackett/Definitions/utorrents.yml
Normal 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="]
|
||||
@@ -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="]
|
||||
|
||||
122
src/Jackett/Definitions/xtremezone.yml
Normal file
122
src/Jackett/Definitions/xtremezone.yml
Normal 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
|
||||
@@ -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
|
||||
|
||||
234
src/Jackett/Indexers/Abstract/GazelleTracker.cs
Normal file
234
src/Jackett/Indexers/Abstract/GazelleTracker.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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"];
|
||||
|
||||
@@ -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);
|
||||
|
||||
32
src/Jackett/Indexers/PassTheHeadphones.cs
Normal file
32
src/Jackett/Indexers/PassTheHeadphones.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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}¶m_val=0&complex_search=0&incldead={1}&orderby=added&sort=desc", HttpUtility.UrlEncode(searchString), cat);
|
||||
searchUrl += string.Format("?search={0}¶m_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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
219
src/Jackett/Indexers/Torrentech.cs
Normal file
219
src/Jackett/Indexers/Torrentech.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
32
src/Jackett/Indexers/nostream.cs
Normal file
32
src/Jackett/Indexers/nostream.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
32
src/Jackett/Indexers/notwhatcd.cs
Normal file
32
src/Jackett/Indexers/notwhatcd.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user