Compare commits

...

36 Commits

Author SHA1 Message Date
kaso17
81c9828e4c Add ShareSpaceDB tracker 2017-01-10 19:06:47 +01:00
kaso17
23b0378d2a Revert "Remove Tspate"
This reverts commit ecf295873f.
2017-01-10 18:55:10 +01:00
kaso17
dd029db392 Add FunkyTorrents tracker 2017-01-10 18:52:13 +01:00
kaso17
40978fbce1 BeyondHD: strip and filter for specific keywords later 2017-01-10 17:54:45 +01:00
kaso17
2cc451ebef Shareisland: fix categories and use url encoded wildcard 2017-01-10 16:58:45 +01:00
kaso17
2f6e1e29b1 nCore: set DL/UL factors 2017-01-10 16:18:10 +01:00
kaso17
99c0de285e Revert "Remove nostream"
This reverts commit 1215548b31.
2017-01-09 13:47:53 +01:00
Ashleigh Hopkins
d9afee215d Add support for gzip'd content (affects an IPTorrents alt URL) (#1) (#920) 2017-01-09 13:12:31 +01:00
kaso17
dc8f85d33d Add Superbits tracker 2017-01-06 19:04:46 +01:00
kaso17
1134ef71da Cardigann: add support for GET login 2017-01-06 19:04:26 +01:00
kaso17
c9e5f14687 Add Torrenting tracker 2017-01-06 17:07:52 +01:00
kaso17
dbe7561642 BeyondHD: replace special characters with wildcards 2017-01-06 16:09:22 +01:00
kaso17
9fcb16e535 Remove Freaks Tracking System 2017-01-06 15:17:47 +01:00
kaso17
1215548b31 Remove nostream 2017-01-06 15:16:30 +01:00
kaso17
ecf295873f Remove Tspate 2017-01-06 15:15:07 +01:00
kaso17
8dcc2aedc9 Cardigann: improve resolvePath usage 2017-01-06 15:05:51 +01:00
kaso17
08b3ba0f02 Elite Tracker: Add support for releases without tooltip and guess time for releases with PRE time 2017-01-06 13:30:21 +01:00
kaso17
f587ae3084 Cardigann: add optional field modifier 2017-01-05 19:15:39 +01:00
kaso17
58206b0d33 Add BitHUmen tracker 2017-01-05 19:14:41 +01:00
kaso17
8e5538a11e Avoid concurrent config file writes 2017-01-05 18:08:10 +01:00
kaso17
175bea9269 Automatically load the backup config if the primary one is corrupted 2017-01-05 18:05:14 +01:00
kaso17
33cbc71817 Add RuTracker 2017-01-05 17:36:49 +01:00
kaso17
f7014f4ca2 Add RuTracker 2017-01-05 17:36:36 +01:00
kaso17
874e14018e Add RuTracker 2017-01-05 17:36:05 +01:00
kaso17
922c08da19 Add support for empty captcha images 2017-01-05 17:31:52 +01:00
adamwinn
5fe89a85e9 tenyardtracker: minor changes (#827)
* minor changes for tenyardtracker
2017-01-04 16:20:52 +01:00
kaso17
0bcf922f37 Elite Tracker: improve search 2017-01-04 15:09:58 +01:00
Tentacule
eb485bfa60 Implement Elite-Tracker (#911)
Fixes #782
2017-01-04 12:35:49 +01:00
kaso17
74d0e022ae 7tor: add category mapping 2017-01-04 12:21:43 +01:00
kaso17
0a8675ea7c Add 7tor tracker 2017-01-03 19:01:05 +01:00
kaso17
eed8cb70a3 GFTracker: fix and improve search 2017-01-03 16:09:07 +01:00
kaso17
e476233f07 HttpWebClient: add support for Referrer 2017-01-03 15:04:49 +01:00
kaso17
b8d40b5259 Add M-Team - TP tracker 2017-01-03 14:54:36 +01:00
kaso17
a399e8d0a5 Demonoid: add more detailed audio category mapping 2017-01-03 14:01:11 +01:00
kaso17
db049b2478 Add HDSky tracker 2017-01-03 13:21:07 +01:00
kaso17
03ab411d68 Cardigann: make download method configurable 2017-01-03 13:19:23 +01:00
26 changed files with 4643 additions and 211 deletions

View File

@@ -14,6 +14,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
#### Supported Private Trackers
* 7tor
* Abnormal
* AlphaRatio
* AlphaReign
@@ -29,6 +30,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* Bit-City Reloaded
* BIT-HDTV
* BitHQ
* BitHUmen
* BitMeTV
* BitSoup
* Blu-bits
@@ -43,9 +45,9 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* Ethor.net (Thor's Land)
* FANO.IN
* FileList
* Freaks Tracking System
* Freshon
* FunFile
* FunkyTorrents
* Fuzer
* Ghost City
* Gormogon
@@ -53,6 +55,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* HD-Space
* HD-Torrents
* HDClub
* HDSky
* Hebits
* New Real World
* Hounddawgs
@@ -61,6 +64,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* ILoveTorrents
* Immortalseed
* IPTorrents
* M-Team - TP
* MoreThanTV
* MyAnonamouse
* myAmity
@@ -79,14 +83,17 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* QcTorrent
* RapideTracker
* RevolutionTT
* RuTracker
* SceneAccess
* SceneFZ
* SceneTime
* SDBits
* Secret Cinema
* Shareisland
* ShareSpaceDB
* Shazbat
* SpeedCD
* Superbits
* The Horror Charnel
* The New Retro
* The Shinning
@@ -98,6 +105,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* TorrentBytes
* TorrentDay
* TorrentHeaven
* Torrenting
* TorrentLeech
* Torrents.Md
* TorrentShack
@@ -105,7 +113,6 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* ToTheGlory
* TranceTraffic
* TransmitheNet
* Tspate
* TV Chaos UK
* TV-Vault
* u-Torrent

View File

@@ -165,7 +165,7 @@
</div>
</script>
<script id="setup-item-displayimage" type="text/x-handlebars-template">
<img class="setup-item-displayimage" src="{{{value}}}" />
<img class="setup-item-displayimage" src="{{{value}}}" alt="No image available" />
</script>
<script id="setup-item-displayinfo" type="text/x-handlebars-template">
<div class="setup-item-displayinfo alert alert-info" role="alert">{{{value}}}</div>

View File

@@ -0,0 +1,132 @@
---
site: bithumen
name: BitHUmen
language: hu-hu
encoding: ISO-8859-2
links:
- https://bithumen.be/
caps:
categories:
23: Movies/SD # Film/Hun/SD
24: Movies/DVD # Film/Hun/DVD-R
25: Movies/HD # Film/Hun/720p
37: Movies/HD # Film/Hun/1080p
33: Movies/BluRay # Film/Hun/Blu-ray
30: XXX # XXX/SD
19: Movies/SD # Film/Eng/SD
20: Movies/DVD # Film/Eng/DVD-R
5: Movies/HD # Film/Eng/720p
39: Movies/HD # Film/Eng/1080p
40: Movies/BluRay # Film/Eng/Blu-ray
34: XXX # XXX/HD
7: TV/SD # Sorozat/Hun/SD
41: TV/HD # Sorozat/Hun/HD
26: TV/SD # Sorozat/Eng/SD
42: TV/HD # Sorozat/Eng/HD
28: Books # eBook/Hun
29: Books # eBook/Eng
9: Audio/MP3 # Mp3/Hun
35: Audio/Lossless # Lossless/Hun
1: PC/0day # Programok/ISO
4: PC/Games # Játékok/ISO
31: Console/PS4 # Játékok/PS
36: Console/Wii # Játékok/Wii
6: Audio/MP3 # Mp3/Eng
38: Audio/Lossless # Lossless/Eng
22: PC # Programok/egyéb
21: PC # Játékok/Rip/Dox
32: Console/Xbox360 # Játékok/Xbox360
27: Other # Klipek
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("bejelentkezés"))
test:
path: browse.php
search:
path: browse.php
inputs:
$raw: "{{range .Categories}}c{{.}}=1&{{end}}"
search: "{{ .Query.Keywords }}"
incldead: 1
rows:
selector: table#torrenttable > tbody > tr:has(a[href^="details.php?id="])
filters:
- name: andmatch
fields:
download:
selector: a[href^="download.php/"]
attribute: href
title:
selector: a[href^="details.php?id="]
title|optional:
selector: a[href^="details.php?id="]
attribute: title
details:
selector: a[href^="details.php?id="]
attribute: href
imdb:
selector: a[href^="http://anonym.to/?http://www.imdb.com/title/"]
attribute: href
banner:
selector: a[onmouseover^="bithumen.UI.images.coverShow"]
attribute: onmouseover
filters:
- name: regexp
args: "\"(.*?)\""
category:
selector: a[href^="?cat="]
attribute: href
filters:
- name: querystring
args: cat
seeders:
selector: td:nth-child(8)
leechers:
selector: td:nth-child(9)
filters:
- name: regexp
args: /\s*([\d,]+)
grabs:
selector: td:nth-child(7)
files:
selector: td:nth-child(3)
size:
selector: td:nth-child(6) > u
downloadvolumefactor:
text: "1"
downloadvolumefactor|optional:
selector: td:nth-child(6) > nobr > font:contains(" × ")
filters:
- name: replace
args: ["×", ""]
uploadvolumefactor:
text: "1"
uploadvolumefactor|optional:
selector: td:nth-child(5) > nobr > font:contains(" × ")
filters:
- name: replace
args: ["×", ""]
date:
selector: td:nth-child(5)
remove: font
filters:
- name: replace
args: ["ma", "today"]
- name: replace
args: ["tegnap", "yesterday"]
description:
selector: td:nth-child(2) > div

View File

@@ -1,101 +0,0 @@
---
site: freakstrackingsystem
name: Freaks Tracking System
description: "A German gerneral tracker"
language: de-de
encoding: UTF-8
links:
- https://fts.to
caps:
categories:
1: Movies
2: TV
modes:
search: [q]
tv-search: [q, season, ep]
login:
path: /index.php?form=UserLogin
method: form
inputs:
loginUsername: "{{ .Config.username }}"
loginPassword: "{{ .Config.password }}"
error:
- selector: p.innerError
test:
path: index.php?page=FTSAttachmentList
selector: "span:contains(\"Freaks-Punkte:\") > span"
ratio:
path: index.php?page=FTSAttachmentList
selector: "span:contains(\"Freaks-Punkte:\") > span"
search:
path: index.php
inputs:
page: "FTSAttachmentList"
sortField: "uploadTime"
sortOrder: "DESC"
filename: "{{ .Query.Keywords }}"
rows:
selector: table.tableList > tbody > tr[class^="container-"]:has(td:nth-child(5) > a, td:nth-child(6) > a) # has makes sure that we can build a download link
fields:
download:
selector: td:nth-child(5) > a, td:nth-child(6) > a
attribute: href
filters:
- name: replace
args: ["page=FTSPeerList&torrentID=", "page=Attachment&attachmentID="]
title:
selector: td:nth-child(4) > a
category:
text: 2
details:
selector: td:nth-child(4) > a
attribute: href
size:
selector: td:nth-child(8)
filters:
- name: replace
args: [".", ""]
- name: replace
args: [",", "."]
grabs:
selector: td:nth-child(7)
seeders:
selector: td:nth-child(5)
leechers:
selector: td:nth-child(6)
date:
selector: td:nth-child(3)
filters:
- name: replace
args: ["Heute", "Today"]
- name: replace
args: ["Gestern", "Yesterday"]
- name: replace
args: ["Januar", "January"]
- name: replace
args: ["Februar", "February"]
- name: replace
args: ["März", "March"]
- name: replace
args: ["Mai", "May"]
- name: replace
args: ["Juni", "June"]
- name: replace
args: ["Juli", "July"]
- name: replace
args: ["Oktober", "October"]
- name: replace
args: ["Dezember", "December"]
- name: dateparse
args: "2. January 2006, 15:04"
downloadvolumefactor:
case:
"*": "1"
uploadvolumefactor:
case:
"*": "1"

View File

@@ -0,0 +1,112 @@
---
site: funkytorrents
name: FunkyTorrents
language: en-us
encoding: UTF-8
links:
- http://funkytorrents.com
caps:
categories:
1: PC # (Apps)
2: Books # (eBooks)
3: Movies # (Movie)
33: Audio # (Music DVDs)
5: Audio/Video # (Music Vids)
4: Audio # (OST)
19: Audio # Alternative
28: Audio # Ambient
12: Audio # Classical
17: Audio # Dance
16: Audio # Drum 'n' Bass
20: Audio # Electronic
14: Audio # Emo
23: Audio # Experimental
34: Audio # Funk
18: Audio # Hardcore
13: Audio # House
31: Audio # IDM
21: Audio # Indie
26: Audio # Industrial
25: Audio # Jazz/Blues/Soul
37: Audio # Lo-Fi
6: Audio # Metal
22: Audio # Misc
7: Audio # Pop/RnB
29: Audio # Post-Rock
30: Audio # Psychedelic
8: Audio # Punk
9: Audio # Rap/Hip-Hop
35: Audio # Reggae
10: Audio # Rock
15: Audio # Ska
32: Audio # Techno
11: Audio # Trance
36: Audio # Trip-Hop
24: Audio # World/Ethnic
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: table.mainouter > tbody > tr > td.outer > table > tbody > tr.mouse_out
fields:
description|optional:
selector: td:nth-child(2) > font
title:
selector: td:nth-child(2)
remove: font
category:
selector: a[href^="browse.php?cat="]
attribute: href
filters:
- name: querystring
args: cat
details:
selector: a[href^="details.php?id="]
attribute: href
download:
selector: a[href^="download.php"]
attribute: href
files:
selector: td:nth-child(5)
size:
selector: td:nth-child(8)
seeders:
selector: td:nth-child(10)
leechers:
selector: td:nth-child(11)
date:
selector: td:nth-child(7)
filters:
- name: append
args: " +0000"
- name: dateparse
args: "2006-01-0215:04:05 -0700"
grabs:
selector: td:nth-child(9)
downloadvolumefactor:
case:
img[alt="Free Leech"]: "0"
"*": "1"
uploadvolumefactor:
case:
"*": "1"

View File

@@ -0,0 +1,117 @@
---
site: hdsky
name: HDSky
description: "A chinese tracker"
language: zh-cn
encoding: UTF-8
links:
- https://hdsky.me
caps:
categories:
401: Movies # Movies/电影
404: TV/Documentary # Documentaries/纪录片
410: Movies # iPad/iPad影视
405: TV/Anime # Animations/动漫
402: TV # TV Series/剧集
403: TV # TV Shows/综艺
406: Audio/Video # Music Videos/音乐MV
407: TV/Sport # Sports/体育
408: Audio # HQ Audio/无损音乐
409: Other # Misc/其他
modes:
search: [q]
tv-search: [q, season, ep]
login:
path: login.php
method: form
form: form[action="takelogin.php"]
captcha:
type: image
image: img[alt="CAPTCHA"]
input: imagestring
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"
download:
method: post
search:
path: /torrents.php
method: post
inputs:
$raw: "{{range .Categories}}cat{{.}}=1&{{end}}"
search: "{{ .Query.Keywords }}"
incldead: "1"
spstate: "0"
inclbookmarked: "0"
search_area: "0"
search_mode: "0"
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: form[action^="download.php?id="]
attribute: action
imdb:
selector: a[href^="http://www.imdb.com/title/tt"]
attribute: href
size:
selector: td.rowfollow:nth-child(5)
grabs:
selector: td.rowfollow:nth-child(8)
seeders:
selector: td.rowfollow:nth-child(6)
leechers:
selector: td.rowfollow:nth-child(7)
date:
selector: td.rowfollow:nth-child(4) > span[title]
attribute: title
filters:
- name: append
args: " +08:00"
- name: dateparse
args: "2006-01-02 15:04:05 -07:00"
downloadvolumefactor:
case:
img.pro_free: "0"
img.pro_free2up: "0"
img.pro_50pctdown: "0.5"
img.pro_50pctdown2up: "0.5"
img.pro_30pctdown: "0.3"
"*": "1"
uploadvolumefactor:
case:
img.pro_50pctdown2up: "2"
img.pro_free2up: "2"
img.pro_2up: "2"
"*": "1"
description:
selector: td:nth-child(2)
remove: a, img

View File

@@ -0,0 +1,121 @@
---
site: mteamtp
name: M-Team - TP
description: "A chinese tracker"
language: zh-cn
encoding: UTF-8
links:
- https://tp.m-team.cc
caps:
categories:
401: Movies/SD # Movie(電影)/SD
419: Movies/HD # Movie(電影)/HD
420: Movies/DVD # Movie(電影)/DVDiSo
421: Movies/BluRay # Movie(電影)/Blu-Ray
439: Movies/Other # Movie(電影)/Remux
403: TV/SD # TV Series(影劇/綜藝)/SD
402: TV/HD # TV Series(影劇/綜藝)/HD
435: TV/SD # TV Series(影劇/綜藝)/DVDiSo
438: TV/HD # TV Series(影劇/綜藝)/BD
404: TV/Documentary # 紀錄教育
405: TV/Anime # Anime(動畫)
406: Audio/Video # MV(演唱)
408: Audio/Other # Music(AAC/ALAC)
434: Audio # Music(無損)
407: TV/Sport # Sports(運動)
422: PC/0day # Software(軟體)
423: PC/Games # PCGame(PC遊戲)
427: Books # eBook(電子書)
409: Other # Misc(其他)
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"
spstate: "0"
inclbookmarked: "0"
search_area: "0"
search_mode: "0"
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
banner:
selector: img[alt="torrent thumbnail"]
attribute: src
filters:
- name: replace
args: ["pic/nopic.jpg", ""]
size:
selector: td.rowfollow:nth-child(5)
grabs:
selector: td.rowfollow:nth-child(8)
seeders:
selector: td.rowfollow:nth-child(6)
leechers:
selector: td.rowfollow:nth-child(7)
date:
selector: td.rowfollow:nth-child(4) > span[title]
attribute: title
filters:
- name: append
args: " +08:00"
- name: dateparse
args: "2006-01-02 15:04:05 -07:00"
downloadvolumefactor:
case:
img.pro_free: "0"
img.pro_free2up: "0"
img.pro_50pctdown: "0.5"
img.pro_50pctdown2up: "0.5"
img.pro_30pctdown: "0.3"
"*": "1"
uploadvolumefactor:
case:
img.pro_50pctdown2up: "2"
img.pro_free2up: "2"
img.pro_2up: "2"
"*": "1"
description:
selector: td:nth-child(2)
remove: a, img

View File

@@ -74,8 +74,8 @@
inputs:
p: "torrents"
pid: "32"
$raw: "{{range .Categories}}cid[]:{{.}}&{{end}}"
keywords: "{{ re_replace .Query.Keywords \"[^a-zA-Z0-9]+\" \"%\" }}"
$raw: "{{range .Categories}}cid[]={{.}}&{{end}}"
keywords: "{{ re_replace .Query.Keywords \"[^a-zA-Z0-9]+\" \"%25\" }}"
search_type: "name"
searchin: "title"

View File

@@ -1,11 +1,11 @@
---
site: tspate
name: Tspate
site: sharespacedb
name: ShareSpaceDB
description: "A French gerneral tracker"
language: fr-fr
encoding: UTF-8
links:
- https://www.tspate.me/
- https://www.sharespacedb.me/
caps:
categories:
@@ -117,9 +117,18 @@
filters:
- name: querystring
args: cat
details:
selector: a[href^="torrents-details.php?id="]
attribute: href
comments:
selector: a[href^="comments.php"]
attribute: href
banner:
selector: a[onmouseover][href^="torrents-details.php?id="]
attribute: onmouseover
filters:
- name: regexp
args: <td align=left><img src=(.*?) width
size:
selector: td:nth-child(7)
grabs:

View File

@@ -12,6 +12,7 @@
1: TV # Sports
modes:
search: [q]
tv-search: [q, season, ep]
login:
path: members.php?action=takelogin
@@ -19,12 +20,16 @@
inputs:
username: "{{ .Config.username }}"
password: "{{ .Config.password }}"
error:
- selector: div:contains("Login Failed")
test:
path: my.php
#error:
#- path: members.php?action=takelogin
test:
path: my.php
#selector: a[href="members.php?action=logout"]
ratio:
path: browse.php
selector: #status_bar
@@ -37,6 +42,8 @@
rows:
selector: table[border="1"] tr:not(:first-child)
fields:
category:
text: 1
title:
selector: td:nth-child(2)
download:

View File

@@ -0,0 +1,86 @@
---
site: torrenting
name: Torrenting
language: en-us
encoding: windows-1252
links:
- https://torrenting.com
caps:
categories:
1: Movies # Movies
2: Movies/DVD # Movies/DVD-R
3: Movies/BluRay # BluRay Movies
4: TV/SD # TV/SD-x264
5: TV/HD # TV/X264 HD
11: Movies/HD # Movies/HD
18: TV # TV/Packs
21: Console # Games/Consoles
26: Audio/Video # Music/Videos
27: Audio # Music/Audio
29: TV/Anime # Anime/Toons
30: Books # Books
34: PC/0day # Applications/0-day
35: PC/Games # Games/PC
40: XXX # XXX
47: Movies # Movies/Packs
49: Movies/HD # x265 (HEVC)
modes:
search: [q]
tv-search: [q, season, ep]
login:
path: login.php
method: form
form: form[action="secure.php"]
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: table#torrentsTable > tbody > tr.torrentsTableTR
fields:
download:
selector: a[href^="download.php/"]
attribute: href
title:
selector: a.nameLink
details:
selector: a.nameLink
attribute: href
category:
selector: a[href^="browse.php?cat="]
attribute: href
filters:
- name: querystring
args: cat
date:
selector: div.uploaded
seeders:
selector: td:nth-child(7)
leechers:
selector: td:nth-child(8)
size:
selector: td:nth-child(6)
downloadvolumefactor:
text: "1"
downloadvolumefactor:
case:
"span:contains(\"Freeleech\")": "0"
"*": "1"
uploadvolumefactor:
case:
"*": "1"

1728
src/Jackett/Indexers/7tor.cs Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -161,7 +161,7 @@ namespace Jackett.Indexers
IsConfigured = false;
}
protected virtual void SaveConfig()
public virtual void SaveConfig()
{
indexerService.SaveConfig(this as IIndexer, configData.ToJson(protectionService, forDisplay: false));
}
@@ -334,13 +334,18 @@ namespace Jackett.Indexers
}
public async virtual Task<byte[]> Download(Uri link)
{
return await Download(link, RequestType.GET);
}
public async virtual Task<byte[]> Download(Uri link, RequestType method = RequestType.GET)
{
// do some extra escaping, needed for HD-Torrents
var requestLink = link.ToString()
.Replace("(", "%28")
.Replace(")", "%29")
.Replace("'", "%27");
var response = await RequestBytesWithCookiesAndRetry(requestLink);
var response = await RequestBytesWithCookiesAndRetry(requestLink, null, method);
if (response.Status != System.Net.HttpStatusCode.OK && response.Status != System.Net.HttpStatusCode.Continue && response.Status != System.Net.HttpStatusCode.PartialContent)
{
logger.Error("Failed download cookies: " + this.CookieHeader);
@@ -352,14 +357,14 @@ namespace Jackett.Indexers
return response.Content;
}
protected async Task<WebClientByteResult> RequestBytesWithCookiesAndRetry(string url, string cookieOverride = null)
protected async Task<WebClientByteResult> RequestBytesWithCookiesAndRetry(string url, string cookieOverride = null, RequestType method = RequestType.GET)
{
Exception lastException = null;
for (int i = 0; i < 3; i++)
{
try
{
return await RequestBytesWithCookies(url, cookieOverride);
return await RequestBytesWithCookies(url, cookieOverride, method);
}
catch (Exception e)
{
@@ -411,12 +416,12 @@ namespace Jackett.Indexers
throw lastException;
}
protected async Task<WebClientByteResult> RequestBytesWithCookies(string url, string cookieOverride = null)
protected async Task<WebClientByteResult> RequestBytesWithCookies(string url, string cookieOverride = null, RequestType method = RequestType.GET)
{
var request = new Utils.Clients.WebRequest()
{
Url = url,
Type = RequestType.GET,
Type = method,
Cookies = cookieOverride ?? CookieHeader,
Encoding = Encoding
};

File diff suppressed because one or more lines are too long

View File

@@ -136,6 +136,7 @@ namespace Jackett.Indexers
public class downloadBlock
{
public string Selector { get; set; }
public string Method { get; set; }
}
protected readonly string[] OptionalFileds = new string[] { "imdb", "rageid", "tvdbid", "banner" };
@@ -367,7 +368,7 @@ namespace Jackett.Indexers
pairs.Add(Input.Key, value);
}
var LoginUrl = SiteLink + Login.Path;
var LoginUrl = resolvePath(Login.Path).ToString();
configData.CookieHeader.Value = null;
var loginResult = await RequestLoginAndFollowRedirect(LoginUrl, pairs, null, true, null, SiteLink, true);
configData.CookieHeader.Value = loginResult.Cookies;
@@ -376,7 +377,7 @@ namespace Jackett.Indexers
}
else if (Login.Method == "form")
{
var LoginUrl = SiteLink + Login.Path;
var LoginUrl = resolvePath(Login.Path).ToString();
var pairs = new Dictionary<string, string>();
@@ -524,6 +525,22 @@ namespace Jackett.Indexers
{
configData.CookieHeader.Value = ((StringItem)configData.GetDynamic("cookie")).Value;
}
else if (Login.Method == "get")
{
var queryCollection = new NameValueCollection();
foreach (var Input in Definition.Login.Inputs)
{
var value = applyGoTemplateText(Input.Value);
queryCollection.Add(Input.Key, value);
}
var LoginUrl = resolvePath(Login.Path + "?" + queryCollection.GetQueryString()).ToString();
configData.CookieHeader.Value = null;
var loginResult = await RequestStringWithCookies(LoginUrl, null, SiteLink);
configData.CookieHeader.Value = loginResult.Cookies;
checkForLoginError(loginResult);
}
else
{
throw new NotImplementedException("Login method " + Definition.Login.Method + " not implemented");
@@ -539,7 +556,7 @@ namespace Jackett.Indexers
return false;
// test if login was successful
var LoginTestUrl = SiteLink + Login.Test.Path;
var LoginTestUrl = resolvePath(Login.Test.Path).ToString();
var testResult = await RequestStringWithCookies(LoginTestUrl);
if (testResult.IsRedirect)
@@ -588,7 +605,7 @@ namespace Jackett.Indexers
if (Login == null || Login.Method != "form")
return configData;
var LoginUrl = SiteLink + Login.Path;
var LoginUrl = resolvePath(Login.Path).ToString();
configData.CookieHeader.Value = null;
landingResult = await RequestStringWithCookies(LoginUrl, null, SiteLink);
@@ -781,6 +798,8 @@ namespace Jackett.Indexers
else if (Selector.Attribute != null)
{
value = selection.GetAttribute(Selector.Attribute);
if (value == null)
throw new Exception(string.Format("Attribute \"{0}\" is not set for element {1}", Selector.Attribute, selection.OuterHtml));
}
else
{
@@ -796,6 +815,11 @@ namespace Jackett.Indexers
{
return new Uri(path);
}
else if (path.StartsWith("//"))
{
var basepath = new Uri(SiteLink);
return new Uri(basepath.Scheme + ":" + path);
}
else if(path.StartsWith("/"))
{
var basepath = new Uri(SiteLink);
@@ -805,7 +829,6 @@ namespace Jackett.Indexers
{
return new Uri(SiteLink + path);
}
}
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
@@ -853,7 +876,7 @@ namespace Jackett.Indexers
variables[".Keywords"] = variables[".Query.Keywords"];
// build search URL
var searchUrl = SiteLink + applyGoTemplateText(Search.Path, variables) + "?";
var searchUrl = resolvePath(applyGoTemplateText(Search.Path, variables) + "?").ToString();
var queryCollection = new NameValueCollection();
if (Search.Inputs != null)
{
@@ -928,12 +951,18 @@ namespace Jackett.Indexers
// Parse fields
foreach (var Field in Search.Fields)
{
var FieldParts = Field.Key.Split('|');
var FieldName = FieldParts[0];
var FieldModifier = "";
if (FieldParts.Length >= 2)
FieldModifier = FieldParts[1];
string value = null;
try
{
value = handleSelector(Field.Value, Row);
value = ParseUtil.NormalizeSpace(value);
switch (Field.Key)
switch (FieldName)
{
case "download":
if (value.StartsWith("magnet:"))
@@ -1036,7 +1065,7 @@ namespace Jackett.Indexers
}
catch (Exception ex)
{
if (OptionalFileds.Contains(Field.Key))
if (OptionalFileds.Contains(Field.Key) || FieldModifier == "optional")
continue;
throw new Exception(string.Format("Error while parsing field={0}, selector={1}, value={2}: {3}", Field.Key, Field.Value.Selector, value, ex.Message));
}
@@ -1115,9 +1144,15 @@ namespace Jackett.Indexers
public override async Task<byte[]> Download(Uri link)
{
if(Definition.Download != null)
var method = RequestType.GET;
if (Definition.Download != null)
{
var Download = Definition.Download;
if (Download.Method != null)
{
if (Download.Method == "post")
method = RequestType.POST;
}
if (Download.Selector != null)
{
var response = await RequestStringWithCookies(link.ToString());
@@ -1138,7 +1173,7 @@ namespace Jackett.Indexers
}
}
}
return await base.Download(link);
return await base.Download(link, method);
}
}
}

View File

@@ -130,6 +130,16 @@ namespace Jackett.Indexers
release.Title = qLink.Text().Trim();
release.Description = rowB.ChildElements.ElementAt(0).Cq().Text();
if (release.Category == TorznabCatType.Audio.ID)
{
if (release.Description.Contains("Lossless"))
release.Category = TorznabCatType.AudioLossless.ID;
else if (release.Description.Contains("MP3"))
release.Category = TorznabCatType.AudioMP3.ID;
else
release.Category = TorznabCatType.AudioOther.ID;
}
release.Comments = new Uri(SiteLink + qLink.Attr("href"));
release.Guid = release.Comments;

View File

@@ -0,0 +1,264 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using AngleSharp.Parser.Html;
using Newtonsoft.Json.Linq;
using NLog;
using Jackett.Models;
using Jackett.Models.IndexerConfig;
using Jackett.Services;
using Jackett.Utils;
using Jackett.Utils.Clients;
namespace Jackett.Indexers
{
class EliteTracker : BaseIndexer, IIndexer
{
string LoginUrl { get { return SiteLink + "takelogin.php"; } }
string BrowseUrl { get { return SiteLink + "browse.php"; } }
new ConfigurationDataBasicLogin configData
{
get { return (ConfigurationDataBasicLogin)base.configData; }
set { base.configData = value; }
}
public EliteTracker(IIndexerManagerService indexerManager, IWebClient webClient, Logger logger, IProtectionService protectionService)
: base(name: "Elite-Tracker",
description: "French Torrent Tracker",
link: "https://elite-tracker.net/",
manager: indexerManager,
logger: logger,
p: protectionService,
client: webClient,
configData: new ConfigurationDataBasicLogin()
)
{
Encoding = Encoding.GetEncoding("UTF-8");
Language = "fr-fr";
AddCategoryMapping(27, TorznabCatType.TVAnime, "Animation/Animes");
AddCategoryMapping(63, TorznabCatType.TVAnime, "Animes DVD");
AddCategoryMapping(56, TorznabCatType.TVAnime, "Animes HD");
AddCategoryMapping(59, TorznabCatType.TVAnime, "Animes Serie");
AddCategoryMapping(3, TorznabCatType.PC0day, "APPLICATION");
AddCategoryMapping(74, TorznabCatType.PCPhoneAndroid, "ANDROID");
AddCategoryMapping(57, TorznabCatType.PCPhoneIOS, "IPHONE");
AddCategoryMapping(6, TorznabCatType.PC0day, "LINUX");
AddCategoryMapping(5, TorznabCatType.PCMac, "MAC");
AddCategoryMapping(4, TorznabCatType.PC0day, "WINDOWS");
AddCategoryMapping(38, TorznabCatType.TVDocumentary, "DOCUMENTAIRES");
AddCategoryMapping(34, TorznabCatType.Books, "EBOOKS");
AddCategoryMapping(7, TorznabCatType.Movies, "FILMS");
AddCategoryMapping(11, TorznabCatType.MoviesDVD, "DVD");
AddCategoryMapping(10, TorznabCatType.MoviesSD, "DVD-RIP/BD-RIP");
AddCategoryMapping(53, TorznabCatType.MoviesSD, "DVD-SCREENER");
AddCategoryMapping(9, TorznabCatType.MoviesDVD, "R5");
AddCategoryMapping(8, TorznabCatType.MoviesSD, "SCREENER");
AddCategoryMapping(40, TorznabCatType.Movies, "VO");
AddCategoryMapping(39, TorznabCatType.Movies, "VOSTFR");
AddCategoryMapping(48, TorznabCatType.MoviesHD, "HD");
AddCategoryMapping(51, TorznabCatType.MoviesHD, "1080P");
AddCategoryMapping(70, TorznabCatType.Movies3D, "3D");
AddCategoryMapping(50, TorznabCatType.MoviesHD, "720P");
AddCategoryMapping(49, TorznabCatType.MoviesBluRay, "BluRay");
AddCategoryMapping(78, TorznabCatType.MoviesHD, "M - HD");
AddCategoryMapping(15, TorznabCatType.Console, "JEUX VIDEO");
AddCategoryMapping(76, TorznabCatType.Console3DS, "3DS");
AddCategoryMapping(18, TorznabCatType.ConsoleNDS, "DS");
AddCategoryMapping(55, TorznabCatType.PCPhoneIOS, "IPHONE");
AddCategoryMapping(80, TorznabCatType.PCGames, "LINUX");
AddCategoryMapping(79, TorznabCatType.PCMac, "OSX");
AddCategoryMapping(22, TorznabCatType.PCGames, "PC");
AddCategoryMapping(66, TorznabCatType.ConsolePS3, "PS2");
AddCategoryMapping(58, TorznabCatType.ConsolePS3, "PS3");
AddCategoryMapping(81, TorznabCatType.ConsolePS4, "PS4");
AddCategoryMapping(20, TorznabCatType.ConsolePSP, "PSP");
AddCategoryMapping(75, TorznabCatType.ConsolePS3, "PSX");
AddCategoryMapping(19, TorznabCatType.ConsoleWii, "WII");
AddCategoryMapping(83, TorznabCatType.ConsoleWiiU, "WiiU");
AddCategoryMapping(16, TorznabCatType.ConsoleXbox, "XBOX");
AddCategoryMapping(82, TorznabCatType.ConsoleXboxOne, "XBOX ONE");
AddCategoryMapping(17, TorznabCatType.ConsoleXbox360, "XBOX360");
AddCategoryMapping(44, TorznabCatType.ConsoleXbox360, "XBOX360.E");
AddCategoryMapping(54, TorznabCatType.ConsoleXbox360, "XBOX360.JTAG");
AddCategoryMapping(43, TorznabCatType.ConsoleXbox360, "XBOX360.NTSC");
AddCategoryMapping(23, TorznabCatType.Audio, "MUSIQUES");
AddCategoryMapping(26, TorznabCatType.Audio, "CLIP/CONCERT");
AddCategoryMapping(61, TorznabCatType.AudioLossless, "FLAC");
AddCategoryMapping(60, TorznabCatType.AudioMP3, "MP3");
AddCategoryMapping(30, TorznabCatType.TV, "SERIES");
AddCategoryMapping(73, TorznabCatType.TV, "Pack TV");
AddCategoryMapping(31, TorznabCatType.TV, "Series FR");
AddCategoryMapping(32, TorznabCatType.TV, "Series VO");
AddCategoryMapping(33, TorznabCatType.TV, "Series VO-STFR");
AddCategoryMapping(77, TorznabCatType.TVSD, "Series.DVD");
AddCategoryMapping(67, TorznabCatType.TVHD, "Series.FR.HD");
AddCategoryMapping(68, TorznabCatType.TVHD, "Series.VO.HD");
AddCategoryMapping(69, TorznabCatType.TVHD, "Series.VOSTFR.HD");
AddCategoryMapping(47, TorznabCatType.TV, "SPECTACLES/EMISSIONS");
AddCategoryMapping(71, TorznabCatType.TV, "Emissions");
AddCategoryMapping(72, TorznabCatType.TV, "Spectacles");
AddCategoryMapping(35, TorznabCatType.TVSport, "SPORT");
AddCategoryMapping(36, TorznabCatType.TVSport, "CATCH");
AddCategoryMapping(65, TorznabCatType.TVSport, "UFC");
AddCategoryMapping(37, TorznabCatType.XXX, "XXX");
}
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 PostDataWithCookies(LoginUrl, pairs);
await ConfigureIfOK(result.Cookies, result.Cookies != null, () =>
{
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();
var queryCollection = new Dictionary<string, string>();
queryCollection.Add("search_type", "t_name");
queryCollection.Add("do", "search");
queryCollection.Add("keywords", searchString);
queryCollection.Add("category", "0"); // multi cat search not supported
var results = await PostDataWithCookies(BrowseUrl, queryCollection);
try
{
var RowsSelector = "table[id='sortabletable'] > tbody > tr";
var SearchResultParser = new HtmlParser();
var SearchResultDocument = SearchResultParser.Parse(results.Content);
var Rows = SearchResultDocument.QuerySelectorAll(RowsSelector);
var lastDate = DateTime.Now;
foreach (var Row in Rows.Skip(1))
{
var release = new ReleaseInfo();
release.MinimumRatio = 1;
release.MinimumSeedTime = 0;
var category = Row.QuerySelector("td:nth-child(1) > a");
var title = Row.QuerySelector("td:nth-child(2) a");
var added = Row.QuerySelector("td:nth-child(2) > div:has(span[style=\"float: right;\"])");
var pretime = added.QuerySelector("font.mkprettytime");
var tooltip = Row.QuerySelector("td:nth-child(2) > div.tooltip-content");
var link = Row.QuerySelector("td:nth-child(3)").QuerySelector("a");
var comments = Row.QuerySelector("td:nth-child(2)").QuerySelector("a");
var Size = Row.QuerySelector("td:nth-child(5)");
var Grabs = Row.QuerySelector("td:nth-child(6)").QuerySelector("a");
var Seeders = Row.QuerySelector("td:nth-child(7)").QuerySelector("a");
var Leechers = Row.QuerySelector("td:nth-child(8)").QuerySelector("a");
var categoryIdparts = category.GetAttribute("href").Split('-');
var categoryId = categoryIdparts[categoryIdparts.Length-1].Replace(".ts", "");
release.Title = title.TextContent;
release.Category = MapTrackerCatToNewznab(categoryId);
release.Link = new Uri(link.GetAttribute("href"));
release.Comments = new Uri(comments.GetAttribute("href"));
release.Guid = release.Link;
release.Size = ReleaseInfo.GetBytes(Size.TextContent);
release.Seeders = ParseUtil.CoerceInt(Seeders.TextContent);
release.Peers = ParseUtil.CoerceInt(Leechers.TextContent) + release.Seeders;
release.Grabs = ParseUtil.CoerceLong(Grabs.TextContent);
if (added.QuerySelector("img[alt^=\"TORRENT GRATUIT\"]") != null)
release.DownloadVolumeFactor = 0;
else if (added.QuerySelector("img[alt^=\"TORRENT SILVER\"]") != null)
release.DownloadVolumeFactor = 0.5;
else
release.DownloadVolumeFactor = 1;
if (added.QuerySelector("img[alt^=\"TORRENT X2\"]") != null)
release.UploadVolumeFactor = 2;
else
release.UploadVolumeFactor = 1;
if (tooltip != null)
{
var banner = tooltip.QuerySelector("img");
if (banner != null)
{
release.BannerUrl = new Uri(banner.GetAttribute("src"));
banner.Remove();
}
tooltip.QuerySelector("div:contains(\"Total Hits: \")").Remove();
var longtitle = tooltip.QuerySelectorAll("div").First();
release.Title = longtitle.TextContent;
longtitle.Remove();
var desc = tooltip.TextContent.Trim();
if (!string.IsNullOrWhiteSpace(desc))
release.Description = desc;
}
// if even the tooltip title is shortened we use the URL
if (release.Title.EndsWith("..."))
{
var tregex = new Regex(@"/([^/]+)-s-\d+\.ts");
var tmatch = tregex.Match(release.Comments.ToString());
release.Title = tmatch.Groups[1].Value;
}
if (pretime != null)
{
if (release.Description == null)
release.Description = pretime.TextContent;
else
release.Description += "<br>\n" + pretime.TextContent;
release.PublishDate = lastDate;
}
else
{
release.PublishDate = DateTime.ParseExact(added.TextContent.Trim(), "dd.M.yyyy HH:mm", CultureInfo.InvariantCulture);
lastDate = release.PublishDate;
}
releases.Add(release);
}
}
catch (Exception ex)
{
OnParseError(results.Content, ex);
}
return releases;
}
}
}

View File

@@ -48,18 +48,37 @@ namespace Jackett.Indexers
Encoding = Encoding.UTF8;
Language = "en-us";
AddCategoryMapping(4, TorznabCatType.TV); // TV/XVID
AddCategoryMapping(17, TorznabCatType.TVHD); // TV/X264
AddCategoryMapping(19, TorznabCatType.TV); // TV/DVDRIP
AddCategoryMapping(26, TorznabCatType.TVHD); // TV/BLURAY
AddCategoryMapping(37, TorznabCatType.TV); // TV/DVDR
AddCategoryMapping(47, TorznabCatType.TV); // TV/SD
AddCategoryMapping(7, TorznabCatType.Movies); // Movies/XVID
AddCategoryMapping(8, TorznabCatType.MoviesDVD); // Movies/DVDR
AddCategoryMapping(12, TorznabCatType.MoviesBluRay); // Movies/BLURAY
AddCategoryMapping(18, TorznabCatType.MoviesHD); // Movies/X264-HD
AddCategoryMapping(49, TorznabCatType.MoviesSD); // Movies/X264-SD
AddCategoryMapping(2, TorznabCatType.PC0day, "0DAY");
AddCategoryMapping(16, TorznabCatType.TVAnime, "Anime");
AddCategoryMapping(1, TorznabCatType.PC0day, "APPS");
AddCategoryMapping(9, TorznabCatType.Other, "E-Learning");
AddCategoryMapping(35, TorznabCatType.TVFOREIGN, "Foreign");
AddCategoryMapping(32, TorznabCatType.ConsoleNDS, "Games/NDS");
AddCategoryMapping(6, TorznabCatType.PCGames, "Games/PC");
AddCategoryMapping(36, TorznabCatType.ConsolePS4, "Games/Playstation");
AddCategoryMapping(29, TorznabCatType.ConsolePSP, "Games/PSP");
AddCategoryMapping(23, TorznabCatType.ConsoleWii, "Games/WII");
AddCategoryMapping(12, TorznabCatType.ConsoleXbox, "Games/XBOX");
AddCategoryMapping(11, TorznabCatType.Other, "Misc");
AddCategoryMapping(48, TorznabCatType.MoviesBluRay, "Movies/BLURAY");
AddCategoryMapping(8, TorznabCatType.MoviesDVD, "Movies/DVDR");
AddCategoryMapping(18, TorznabCatType.MoviesHD, "Movies/X264-HD");
AddCategoryMapping(49, TorznabCatType.MoviesSD, "Movies/X264-SD");
AddCategoryMapping(7, TorznabCatType.MoviesSD, "Movies/XVID");
AddCategoryMapping(38, TorznabCatType.AudioOther, "Music/DVDR");
AddCategoryMapping(46, TorznabCatType.AudioLossless, "Music/FLAC");
AddCategoryMapping(5, TorznabCatType.AudioMP3, "Music/MP3");
AddCategoryMapping(13, TorznabCatType.AudioVideo, "Music/Vids");
AddCategoryMapping(26, TorznabCatType.TVHD, "TV/BLURAY");
AddCategoryMapping(37, TorznabCatType.TVSD, "TV/DVDR");
AddCategoryMapping(19, TorznabCatType.TVSD, "TV/DVDRIP");
AddCategoryMapping(47, TorznabCatType.TVSD, "TV/SD");
AddCategoryMapping(17, TorznabCatType.TVHD, "TV/X264");
AddCategoryMapping(4, TorznabCatType.TVSD, "TV/XVID");
AddCategoryMapping(22, TorznabCatType.XXX, "XXX/0DAY");
AddCategoryMapping(25, TorznabCatType.XXXDVD, "XXX/DVDR");
AddCategoryMapping(20, TorznabCatType.XXX, "XXX/HD");
AddCategoryMapping(3, TorznabCatType.XXXXviD, "XXX/XVID");
}
public override async Task<ConfigurationData> GetConfigurationForSetup()
@@ -116,18 +135,17 @@ namespace Jackett.Indexers
}
}
var cookieJar = configData.CookieHeader.Value;
var response = await RequestLoginAndFollowRedirect(LoginUrl, pairs, configData.CookieHeader.Value, true, null, StartPageUrl);
cookieJar += response.Cookies.ToString();
response = await RequestStringWithCookiesAndRetry(SearchUrl, cookieJar);
var response = await RequestLoginAndFollowRedirect(LoginUrl, pairs, configData.CookieHeader.Value, true, SearchUrl, StartPageUrl);
UpdateCookieHeader(response.Cookies);
await ConfigureIfOK(cookieJar, response.Content != null && response.Content.Contains("logout.php"), () =>
await ConfigureIfOK(configData.CookieHeader.Value, response.Content != null && response.Content.Contains("logout.php"), () =>
{
CQ dom = response.Content;
var messageEl = dom["h2"].Last();
var messageEl = dom["div:has(h2)"].Last();
messageEl.Children("a").Remove();
messageEl.Children("style").Remove();
var errorMessage = messageEl.Text().Trim();
IsConfigured = false;
throw new ExceptionWithConfigData(errorMessage, configData);
});
return IndexerConfigurationStatus.RequiresTesting;
@@ -140,6 +158,8 @@ namespace Jackett.Indexers
var queryCollection = new NameValueCollection();
queryCollection.Add("view", "0");
queryCollection.Add("searchtype", "1");
queryCollection.Add("incldead", "1");
if (!string.IsNullOrWhiteSpace(searchString))
{
queryCollection.Add("search", searchString);
@@ -152,7 +172,14 @@ namespace Jackett.Indexers
var searchUrl = SearchUrl + "?" + queryCollection.GetQueryString();
var results = await RequestStringWithCookiesAndRetry(searchUrl, CookieHeader);
var results = await RequestStringWithCookiesAndRetry(searchUrl);
if (results.IsRedirect)
{
// re-login
await ApplyConfiguration(null);
results = await RequestStringWithCookiesAndRetry(searchUrl);
}
try
{
CQ dom = results.Content;
@@ -162,19 +189,11 @@ namespace Jackett.Indexers
var release = new ReleaseInfo();
CQ qRow = row.Cq();
//CQ qLink = qRow.Children().ElementAt(1).Cq().Children("a").ElementAt(1).Cq();
CQ qLink;
CQ qTmp = qRow.Children().ElementAt(1).Cq().Find("a");
if (qTmp.Length < 2) {
qLink = qRow.Children().ElementAt(1).Cq().Find("a").ElementAt(0).Cq();
} else {
qLink = qRow.Children().ElementAt(1).Cq().Find("a").ElementAt(1).Cq();
}
release.MinimumRatio = 0;
release.MinimumSeedTime = 2 * 24 * 60 * 60;
release.MinimumRatio = 1;
release.MinimumSeedTime = 172800;
var qLink = qRow.Find("a[title][href^=\"details.php?id=\"]");
release.Title = qLink.Attr("title");
release.Description = release.Title;
release.Guid = new Uri(SiteLink + qLink.Attr("href").TrimStart('/'));
release.Comments = release.Guid;
@@ -186,14 +205,22 @@ namespace Jackett.Indexers
release.Category = MapTrackerCatToNewznab(catNum);
var dateString = qRow.Children().ElementAt(6).Cq().Text().Trim();
//var pubDate = DateTime.ParseExact(dateString, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
release.PublishDate = Jackett.Utils.DateTimeUtil.FromTimeAgo(dateString);
release.PublishDate = DateTime.ParseExact(dateString, "yyyy-MM-ddHH:mm:ss", CultureInfo.InvariantCulture);
var sizeStr = qRow.Children().ElementAt(7).Cq().Text().Split(new char[] { '/' })[0];
release.Size = ReleaseInfo.GetBytes(sizeStr);
release.Seeders = ParseUtil.CoerceInt(qRow.Children().ElementAt(8).Cq().Text().Split(new char[] { '/' })[0].Trim());
release.Peers = ParseUtil.CoerceInt(qRow.Children().ElementAt(8).Cq().Text().Split(new char[] { '/' })[1].Trim()) + release.Seeders;
release.Files = ParseUtil.CoerceLong(qRow.Find("td:nth-child(5)").Text());
release.Grabs = ParseUtil.CoerceLong(qRow.Find("a[href^=\"snatches.php?id=\"]").Text().Split(' ')[0]);
release.DownloadVolumeFactor = 0;
release.UploadVolumeFactor = 1;
var desc = qRow.Find("td:nth-child(2)");
desc.Find("a").Remove();
release.Description = desc.Text();
releases.Add(release);
}

View File

@@ -34,6 +34,7 @@ namespace Jackett.Indexers
// Called on startup when initializing indexers from saved configuration
void LoadFromSavedConfiguration(JToken jsonConfig);
void SaveConfig();
Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query);

View File

@@ -194,6 +194,8 @@ namespace Jackett.Indexers
release.Description = release.Title;
release.MinimumRatio = 1;
release.MinimumSeedTime = 172800;
release.DownloadVolumeFactor = 0;
release.UploadVolumeFactor = 1;
string downloadLink = SiteLink + torrentTxt.GetAttribute("href");
string downloadId = downloadLink.Substring(downloadLink.IndexOf("&id=") + 4);

View File

@@ -0,0 +1,194 @@
using Jackett.Models;
using Jackett.Services;
using Jackett.Utils;
using Jackett.Utils.Clients;
using Newtonsoft.Json.Linq;
using NLog;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Jackett.Models.IndexerConfig;
using System.Collections.Specialized;
using Newtonsoft.Json;
using System.Globalization;
namespace Jackett.Indexers
{
public class Superbits : BaseIndexer, IIndexer
{
private string SearchUrl { get { return SiteLink + "api/v1/torrents"; } }
private string LoginUrl { get { return SiteLink + "api/v1/auth"; } }
new ConfigurationDataBasicLogin configData
{
get { return (ConfigurationDataBasicLogin)base.configData; }
set { base.configData = value; }
}
public Superbits(IIndexerManagerService i, Logger l, IWebClient w, IProtectionService ps)
: base(name: "Superbits",
description: null,
link: "https://superbits.org/",
caps: new TorznabCapabilities(),
manager: i,
client: w,
logger: l,
p: ps,
configData: new ConfigurationDataBasicLogin())
{
Encoding = Encoding.GetEncoding("UTF-8");
Language = "sv-sw";
AddCategoryMapping(1, TorznabCatType.MoviesDVD, "DVD-R Swesub");
AddCategoryMapping(2, TorznabCatType.TV, "DVD-R TV");
AddCategoryMapping(3, TorznabCatType.BooksEbook, "eBok");
AddCategoryMapping(4, TorznabCatType.MoviesHD, "Film 1080");
AddCategoryMapping(5, TorznabCatType.Movies3D, "Film 3D");
AddCategoryMapping(6, TorznabCatType.MoviesHD, "Film 720");
AddCategoryMapping(7, TorznabCatType.MoviesBluRay, "Film Bluray");
AddCategoryMapping(8, TorznabCatType.TV, "Svensk TV");
AddCategoryMapping(9, TorznabCatType.AudioAudiobook, "Ljudböcker");
AddCategoryMapping(10, TorznabCatType.AudioVideo, "Musikvideos");
AddCategoryMapping(11, TorznabCatType.BooksMagazines, "E-tidningar");
AddCategoryMapping(12, TorznabCatType.Audio, "Musik");
AddCategoryMapping(13, TorznabCatType.Other, "Omslag");
AddCategoryMapping(14, TorznabCatType.Other, "Övrigt");
AddCategoryMapping(15, TorznabCatType.PCGames, "PC-Spel");
AddCategoryMapping(16, TorznabCatType.PC0day, "Program");
AddCategoryMapping(17, TorznabCatType.ConsolePS3, "PS3");
AddCategoryMapping(18, TorznabCatType.TV, "TV");
AddCategoryMapping(19, TorznabCatType.ConsoleWii, "Wii");
AddCategoryMapping(20, TorznabCatType.ConsoleXbox, "Xbox");
AddCategoryMapping(21, TorznabCatType.MoviesOther, "Xvid");
AddCategoryMapping(22, TorznabCatType.XXX, "XXX");
}
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
{
LoadValuesFromJson(configJson);
var queryCollection = new NameValueCollection();
queryCollection.Add("username", configData.Username.Value);
queryCollection.Add("password", configData.Password.Value);
var loginUrl = LoginUrl + "?" + queryCollection.GetQueryString();
var loginResult = await RequestStringWithCookies(loginUrl, null, SiteLink);
await ConfigureIfOK(loginResult.Cookies, loginResult.Content.Contains("\"user\""), () =>
{
throw new ExceptionWithConfigData(loginResult.Content, configData);
});
return IndexerConfigurationStatus.RequiresTesting;
}
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
{
List<ReleaseInfo> releases = new List<ReleaseInfo>();
var queryCollection = new NameValueCollection();
var searchString = query.GetQueryString();
var searchUrl = SearchUrl;
queryCollection.Add("extendedSearch", "false");
queryCollection.Add("freeleech", "false");
queryCollection.Add("index", "0");
queryCollection.Add("limit", "100");
queryCollection.Add("order", "desc");
queryCollection.Add("page", "search");
queryCollection.Add("searchText", searchString);
queryCollection.Add("section", "all");
queryCollection.Add("sort", "d");
queryCollection.Add("section", "all");
queryCollection.Add("stereoscopic", "false");
queryCollection.Add("sweaudio", "false");
queryCollection.Add("swesub", "false");
queryCollection.Add("watchview", "false");
foreach (var cat in MapTorznabCapsToTrackers(query))
queryCollection.Add("categories[]", cat);
searchUrl += "?" + queryCollection.GetQueryString();
var results = await RequestStringWithCookies(searchUrl, null, SiteLink);
try
{
//var json = JArray.Parse(results.Content);
dynamic json = JsonConvert.DeserializeObject<dynamic>(results.Content);
foreach (var row in json)
{
var release = new ReleaseInfo();
var descriptions = new List<string>();
var tags = new List<string>();
release.MinimumRatio = 1.1;
release.MinimumSeedTime = 48 * 60 * 60;
release.Title = row.name;
release.Category = MapTrackerCatToNewznab(row.category.ToString());
release.Size = row.size;
release.Seeders = row.seeders;
release.Peers = row.leechers + release.Seeders;
release.PublishDate = DateTime.ParseExact(row.added.ToString() + " +01:00", "yyyy-MM-dd HH:mm:ss zzz", CultureInfo.InvariantCulture);
release.Files = row.numfiles;
release.Grabs = row.times_completed;
release.Comments = new Uri(SiteLink + "torrent/" + row.id.ToString() + "/");
release.Link = new Uri(SiteLink + "api/v1/torrents/download/" + row.id.ToString());
if (row.frileech == 1)
release.DownloadVolumeFactor = 0;
else
release.DownloadVolumeFactor = 1;
release.UploadVolumeFactor = 1;
if (!string.IsNullOrWhiteSpace(row.customcover.ToString()))
release.BannerUrl = new Uri(SiteLink + row.customcover);
if (row.imdbid2 != null && row.imdbid2.ToString().StartsWith("tt"))
{
https://superbits.org/img/imdb/tt5288312.jpg
release.Imdb = ParseUtil.CoerceLong(row.imdbid2.ToString().Substring(2));
descriptions.Add("Title: " + row.title);
descriptions.Add("Year: " + row.year);
descriptions.Add("Genres: " + row.genres);
descriptions.Add("Tagline: " + row.tagline);
descriptions.Add("Cast: " + row.cast);
descriptions.Add("Rating: " + row.rating);
descriptions.Add("Plot: " + row.plot);
release.BannerUrl = new Uri(SiteLink + "img/imdb/" + row.imdbid2 + ".jpg");
}
if ((int)row.p2p == 1)
tags.Add("P2P");
if ((int)row.pack == 1)
tags.Add("Pack");
if ((int)row.reqid != 0)
tags.Add("Request");
if ((int)row.sweaudio != 0)
tags.Add("Swedish audio");
if ((int)row.swesub != 0)
tags.Add("Swedish subtitles");
if (tags.Count > 0)
descriptions.Add("Tags: " + string.Join(", ", tags));
var preDate = row.preDate.ToString();
if (!string.IsNullOrWhiteSpace(preDate) && preDate != "1970-01-01 01:00:00")
descriptions.Add("PRE: " + preDate);
descriptions.Add("Section: " + row.section);
release.Description = string.Join("<br>\n", descriptions);
releases.Add(release);
}
}
catch (Exception ex)
{
OnParseError(results.Content, ex);
}
return releases;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -165,8 +165,12 @@
<Compile Include="Controllers\TorznabController.cs" />
<Compile Include="Controllers\DownloadController.cs" />
<Compile Include="Engine.cs" />
<Compile Include="Indexers\Superbits.cs" />
<Compile Include="Indexers\rutracker.cs" />
<Compile Include="Indexers\Abstract\GazelleTracker.cs" />
<Compile Include="Indexers\AnimeTorrents.cs" />
<Compile Include="Indexers\7tor.cs" />
<Compile Include="Indexers\EliteTracker.cs" />
<Compile Include="Indexers\Torrentech.cs" />
<Compile Include="Indexers\nostream.cs" />
<Compile Include="Indexers\notwhatcd.cs" />
@@ -401,7 +405,7 @@
<Content Include="Definitions\thehorrorcharnel.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\tspate.yml">
<Content Include="Definitions\sharespacedb.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\eotforum.yml">
@@ -419,9 +423,6 @@
<Content Include="Definitions\blubits.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\freakstrackingsystem.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\theshinning.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -488,6 +489,21 @@
<Content Include="Definitions\chdbits.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\hdsky.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\mteamtp.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\bithumen.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\torrenting.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Definitions\funkytorrents.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Include="packages.config">
<SubType>Designer</SubType>
</None>

View File

@@ -28,6 +28,8 @@ namespace Jackett.Services
public class IndexerManagerService : IIndexerManagerService
{
private static readonly object configWriteLock = new object();
private IContainer container;
private IConfigurationService configService;
private Logger logger;
@@ -55,7 +57,27 @@ namespace Jackett.Services
}
catch (Exception ex)
{
logger.Error(ex, "Failed loading configuration for {0}, you must reconfigure this indexer", idx.DisplayName);
logger.Error(ex, "Failed loading configuration for {0}, trying backup", idx.DisplayName);
var configFilePathBak = configFilePath + ".bak";
if (File.Exists(configFilePathBak))
{
try
{
var fileStrBak = File.ReadAllText(configFilePathBak);
var jsonStringBak = JToken.Parse(fileStrBak);
idx.LoadFromSavedConfiguration(jsonStringBak);
logger.Info("Successfully loaded backup config for {0}", idx.DisplayName);
idx.SaveConfig();
}
catch (Exception exbak)
{
logger.Error(exbak, "Failed loading backup configuration for {0}, you must reconfigure this indexer", idx.DisplayName);
}
}
else
{
logger.Error(ex, "Failed loading backup configuration for {0} (no backup available), you must reconfigure this indexer", idx.DisplayName);
}
}
}
}
@@ -157,59 +179,62 @@ namespace Jackett.Services
public void SaveConfig(IIndexer indexer, JToken obj)
{
var uID = Guid.NewGuid().ToString("N");
var configFilePath = GetIndexerConfigFilePath(indexer);
var configFilePathBak = configFilePath + ".bak";
var configFilePathTmp = configFilePath + "." + uID + ".tmp";
var content = obj.ToString();
lock (configWriteLock)
{
var uID = Guid.NewGuid().ToString("N");
var configFilePath = GetIndexerConfigFilePath(indexer);
var configFilePathBak = configFilePath + ".bak";
var configFilePathTmp = configFilePath + "." + uID + ".tmp";
var content = obj.ToString();
logger.Debug(string.Format("Saving new config file: {0}", configFilePathTmp));
logger.Debug(string.Format("Saving new config file: {0}", configFilePathTmp));
if (string.IsNullOrWhiteSpace(content))
{
throw new Exception(string.Format("New config content for {0} is empty, please report this bug.", indexer.ID));
}
if (string.IsNullOrWhiteSpace(content))
{
throw new Exception(string.Format("New config content for {0} is empty, please report this bug.", indexer.ID));
}
if (content.Contains("\x00"))
{
throw new Exception(string.Format("New config content for {0} contains 0x00, please report this bug. Content: {1}", indexer.ID, content));
}
if (content.Contains("\x00"))
{
throw new Exception(string.Format("New config content for {0} contains 0x00, please report this bug. Content: {1}", indexer.ID, content));
}
// make sure the config directory exists
if (!Directory.Exists(configService.GetIndexerConfigDir()))
Directory.CreateDirectory(configService.GetIndexerConfigDir());
// make sure the config directory exists
if (!Directory.Exists(configService.GetIndexerConfigDir()))
Directory.CreateDirectory(configService.GetIndexerConfigDir());
// create new temporary config file
File.WriteAllText(configFilePathTmp, content);
var fileInfo = new FileInfo(configFilePathTmp);
if (fileInfo.Length == 0)
{
throw new Exception(string.Format("New config file {0} is empty, please report this bug.", configFilePathTmp));
}
// create new temporary config file
File.WriteAllText(configFilePathTmp, content);
var fileInfo = new FileInfo(configFilePathTmp);
if (fileInfo.Length == 0)
{
throw new Exception(string.Format("New config file {0} is empty, please report this bug.", configFilePathTmp));
}
// create backup file
File.Delete(configFilePathBak);
if (File.Exists(configFilePath))
{
// create backup file
File.Delete(configFilePathBak);
if (File.Exists(configFilePath))
{
try
{
File.Move(configFilePath, configFilePathBak);
}
catch (IOException ex)
{
logger.Error(string.Format("Error while moving {0} to {1}: {2}", configFilePath, configFilePathBak, ex.ToString()));
}
}
// replace the actual config file
File.Delete(configFilePath);
try
{
File.Move(configFilePath, configFilePathBak);
File.Move(configFilePathTmp, configFilePath);
}
catch (IOException ex)
{
logger.Error(string.Format("Error while moving {0} to {1}: {2}", configFilePath, configFilePathBak, ex.ToString()));
logger.Error(string.Format("Error while moving {0} to {1}: {2}", configFilePathTmp, configFilePath, ex.ToString()));
}
}
// replace the actual config file
File.Delete(configFilePath);
try
{
File.Move(configFilePathTmp, configFilePath);
}
catch (IOException ex)
{
logger.Error(string.Format("Error while moving {0} to {1}: {2}", configFilePathTmp, configFilePath, ex.ToString()));
}
}

View File

@@ -17,10 +17,10 @@ namespace Jackett.Utils.Clients
public class HttpWebClient : IWebClient
{
public HttpWebClient(IProcessService p, Logger l, IConfigurationService c)
: base(p: p,
l: l,
: base(p: p,
l: l,
c: c)
{
{
}
override public void Init()
@@ -67,7 +67,8 @@ namespace Jackett.Utils.Clients
AllowAutoRedirect = false, // Do not use this - Bugs ahoy! Lost cookies and more.
UseCookies = true,
Proxy = proxyServer,
UseProxy = useProxy
UseProxy = useProxy,
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
};
clearanceHandlr.InnerHandler = clientHandlr;
@@ -94,6 +95,9 @@ namespace Jackett.Utils.Clients
}
}
if (!string.IsNullOrEmpty(webRequest.Referer))
request.Headers.Referrer = new Uri(webRequest.Referer);
if (!string.IsNullOrEmpty(webRequest.RawBody))
{
var type = webRequest.Headers.Where(h => h.Key == "Content-Type").Cast<KeyValuePair<string,string>?>().FirstOrDefault();

View File

@@ -18,6 +18,8 @@ namespace Jackett.Utils
public static string BytesToDataUrl(byte[] bytes, string mimeType = "image/jpg")
{
if (bytes == null)
return null;
return "data:" + mimeType + ";base64," + Convert.ToBase64String(bytes);
}
}