mirror of
https://github.com/Jackett/Jackett.git
synced 2025-12-21 05:42:21 +01:00
Compare commits
65 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0adb54f4b2 | ||
|
|
2e77226f0c | ||
|
|
31ae08544f | ||
|
|
3da6e4ca1b | ||
|
|
c4cd17ce2d | ||
|
|
ee18368192 | ||
|
|
09a7950c1d | ||
|
|
847688bae8 | ||
|
|
7fde427731 | ||
|
|
7319078a5d | ||
|
|
495afb91e9 | ||
|
|
aa3fa8717f | ||
|
|
052e382d93 | ||
|
|
db39b6afd9 | ||
|
|
e05efaeb1d | ||
|
|
b94501f054 | ||
|
|
f00d8e192a | ||
|
|
9ca4600eab | ||
|
|
5e8ebd8579 | ||
|
|
748881ef70 | ||
|
|
42e6600c6a | ||
|
|
85d17a7763 | ||
|
|
b1391b0523 | ||
|
|
8510a42d7a | ||
|
|
e61f6e78b3 | ||
|
|
176ba5a6db | ||
|
|
ad3c56e83b | ||
|
|
2495a2f64e | ||
|
|
0d6830b0aa | ||
|
|
ef316590cb | ||
|
|
c3c25190a2 | ||
|
|
fc3d8d1aec | ||
|
|
bbb7d1c3c7 | ||
|
|
89dfac3009 | ||
|
|
9610965979 | ||
|
|
8b501403e1 | ||
|
|
3a88aeb649 | ||
|
|
0a0ba2291b | ||
|
|
2484e22da9 | ||
|
|
e8ca3e6b52 | ||
|
|
d5c7445919 | ||
|
|
72045404d4 | ||
|
|
1a6e1a8c60 | ||
|
|
540dc0fad4 | ||
|
|
1db3e93ce1 | ||
|
|
a5ec65bff3 | ||
|
|
c4e3aa8a64 | ||
|
|
e3e183d86b | ||
|
|
bfe892f2c8 | ||
|
|
b28116c10f | ||
|
|
52c408fce7 | ||
|
|
a70997ad7f | ||
|
|
8840de316d | ||
|
|
409483e680 | ||
|
|
b19d690305 | ||
|
|
0fabaf2fe0 | ||
|
|
3035d8b901 | ||
|
|
f3d73b5661 | ||
|
|
f335dbf7bc | ||
|
|
b5178dc7b8 | ||
|
|
ad09a4dd77 | ||
|
|
da0ead13f4 | ||
|
|
4b6a9376de | ||
|
|
3eab605423 | ||
|
|
7fc37f1156 |
44
README.md
44
README.md
@@ -43,7 +43,6 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
|
||||
* LimeTorrents
|
||||
* MagnetDL
|
||||
* MejorTorrent <!-- maintained by ivandelabeldad -->
|
||||
* NextTorrent
|
||||
* Newpct (aka: tvsinpagar, descargas2020, torrentlocura, torrentrapid, etc)
|
||||
* Nyaa.si
|
||||
* Nyaa-Pantsu
|
||||
@@ -71,6 +70,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
|
||||
* CzTorrent
|
||||
* Deildu
|
||||
* Gay-Torrents.net
|
||||
* Gay-Torrents.org
|
||||
* Kinozal
|
||||
* LostFilm.tv
|
||||
* Mega-Bliz
|
||||
@@ -147,7 +147,6 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
|
||||
* Elit Tracker
|
||||
* Elite-Tracker
|
||||
* Empornium
|
||||
* EoT-Forum
|
||||
* eStone
|
||||
* Ethor.net (Thor's Land)
|
||||
* FANO.IN
|
||||
@@ -158,7 +157,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
|
||||
* FunFile
|
||||
* FunkyTorrents
|
||||
* Fuzer
|
||||
* GayTorrent.ru
|
||||
* GAYtorrent.ru
|
||||
* GazelleGames
|
||||
* Gfxnews
|
||||
* GFXPeers
|
||||
@@ -208,6 +207,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
|
||||
* NCore
|
||||
* Nebulance
|
||||
* New Real World
|
||||
* NordicBits
|
||||
* Norbits <!-- added by DiseaseNO but no longer maintained? -->
|
||||
* notwhat.cd
|
||||
* Ourbits
|
||||
@@ -285,11 +285,12 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
|
||||
* Waffles
|
||||
* World-In-HD
|
||||
* WorldOfP2P
|
||||
* x-ite.me
|
||||
* x264
|
||||
* xBytesV2
|
||||
* XSpeeds
|
||||
* Xthor
|
||||
* Your Exotic Torrents
|
||||
* ExoticaZ (Your Exotic Torrents)
|
||||
* Zamunda.net
|
||||
* Zelka.org
|
||||
|
||||
@@ -335,6 +336,12 @@ If you want to run it with a user without a /home directory you need to add `Env
|
||||
|
||||
Mono must be compiled with the Roslyn compiler (default), using MCS will cause "An error has occurred." errors (See https://github.com/Jackett/Jackett/issues/2704).
|
||||
|
||||
### Installation on Linux via Ansible
|
||||
|
||||
On a RHEL/Centos 7 system: [linuxhq.jackett](https://galaxy.ansible.com/linuxhq/jackett)
|
||||
|
||||
On an Ubuntu 16 system: [chrisjohnson00.jackett](https://galaxy.ansible.com/chrisjohnson00/jackett)
|
||||
|
||||
## Installation on macOS
|
||||
|
||||
### Prerequisites
|
||||
@@ -371,6 +378,19 @@ Example config for apache:
|
||||
</Location>
|
||||
```
|
||||
|
||||
Example config for nginx:
|
||||
```
|
||||
location /jackett {
|
||||
proxy_pass http://127.0.0.1:9117;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Forwarded-Host $host;
|
||||
proxy_redirect off;
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
* __Command line switches__
|
||||
@@ -410,6 +430,22 @@ All contributions are welcome just send a pull request. Jackett's framework all
|
||||
* Select Jackett.Console as startup project
|
||||
* Build/Start the project
|
||||
|
||||
### OSX
|
||||
NOTE: msbuild is included in the mono release.
|
||||
* Install Homebrew https://brew.sh
|
||||
* open terminal
|
||||
* brew install nuget mono
|
||||
* git clone https://github.com/Jackett/Jackett.git
|
||||
* cd Jackett/src
|
||||
* nuget restore Jackett.sln
|
||||
|
||||
NOTE: if you get the error "NU1102: Unable to find package Microsoft.AspNetCore with version (>= 2.1.2)" while restoring packages, you'll need to install it manually.https://www.microsoft.com/net/download/thank-you/dotnet-sdk-2.1.302-macos-x64-installer then delete the entire project directory and restart from a new clone
|
||||
|
||||
* msbuild Jackett.Console/Jackett.Console.csproj /t:Build /p:Configuration=Debug
|
||||
* curl -sS https://curl.haxx.se/ca/cacert.pem | cert-sync --user /dev/stdin
|
||||
* mono Jackett.Console/bin/Debug/JackettConsole.exe
|
||||
|
||||
|
||||
### Linux
|
||||
|
||||
```bash
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
version: 0.9.{build}
|
||||
version: 0.10.{build}
|
||||
skip_tags: true
|
||||
image: Visual Studio 2017
|
||||
configuration: Release
|
||||
|
||||
78
build.cake
78
build.cake
@@ -45,17 +45,12 @@ Task("Clean")
|
||||
Information("Clean completed");
|
||||
});
|
||||
|
||||
Task("Restore-NuGet-Packages")
|
||||
Task("Build-Kestrel-Full-Framework")
|
||||
.IsDependentOn("Clean")
|
||||
.Does(() =>
|
||||
{
|
||||
NuGetRestore("./src/Jackett.sln");
|
||||
});
|
||||
|
||||
Task("Build")
|
||||
.IsDependentOn("Restore-NuGet-Packages")
|
||||
.Does(() =>
|
||||
{
|
||||
var buildSettings = new MSBuildSettings()
|
||||
.SetConfiguration(configuration)
|
||||
.UseToolVersion(MSBuildToolVersion.VS2017);
|
||||
@@ -64,7 +59,7 @@ Task("Build")
|
||||
});
|
||||
|
||||
Task("Run-Unit-Tests")
|
||||
.IsDependentOn("Build")
|
||||
.IsDependentOn("Build-Kestrel-Full-Framework")
|
||||
.Does(() =>
|
||||
{
|
||||
CreateDirectory("./" + testResultsDirName);
|
||||
@@ -81,29 +76,8 @@ Task("Run-Unit-Tests")
|
||||
}
|
||||
});
|
||||
|
||||
Task("Copy-Files-Full-Framework")
|
||||
.IsDependentOn("Run-Unit-Tests")
|
||||
.Does(() =>
|
||||
{
|
||||
var windowsOutput = windowsBuildFullFramework + "/Jackett";
|
||||
|
||||
CopyDirectory("./src/Jackett.Console/bin/" + configuration, windowsOutput);
|
||||
CopyFiles("./src/Jackett.Updater/bin/" + configuration + "/net452" + "/JackettUpdater.*", windowsOutput); //builds against multiple frameworks
|
||||
CopyFiles("./Upstart.config", windowsOutput);
|
||||
CopyFiles("./LICENSE", windowsOutput);
|
||||
CopyFiles("./README.md", windowsOutput);
|
||||
|
||||
var monoOutput = monoBuildFullFramework + "/Jackett";
|
||||
|
||||
CopyDirectory(windowsBuildFullFramework, monoBuildFullFramework);
|
||||
DeleteFiles(monoOutput + "/JackettService.*");
|
||||
DeleteFiles(monoOutput + "/JackettTray.*");
|
||||
|
||||
Information("Full framework file copy completed");
|
||||
});
|
||||
|
||||
Task("Check-Packaging-Platform")
|
||||
.IsDependentOn("Copy-Files-Full-Framework")
|
||||
.IsDependentOn("Run-Unit-Tests")
|
||||
.Does(() =>
|
||||
{
|
||||
if (IsRunningOnWindows())
|
||||
@@ -117,39 +91,8 @@ Task("Check-Packaging-Platform")
|
||||
}
|
||||
});
|
||||
|
||||
Task("Package-Files-Full-Framework-Mono")
|
||||
.IsDependentOn("Check-Packaging-Platform")
|
||||
.Does(() =>
|
||||
{
|
||||
Gzip(monoBuildFullFramework, $"./{artifactsDirName}", "Jackett", "Jackett.Binaries.Mono.tar.gz");
|
||||
Information(@"Full Framework Mono Binaries Gzip Completed");
|
||||
});
|
||||
|
||||
Task("Package-Full-Framework")
|
||||
.IsDependentOn("Package-Files-Full-Framework-Mono")
|
||||
.Does(() =>
|
||||
{
|
||||
Information("Full Framework Packaging Completed");
|
||||
});
|
||||
|
||||
Task("Kestrel-Full-Framework")
|
||||
.IsDependentOn("Package-Full-Framework")
|
||||
.Does(() =>
|
||||
{
|
||||
CleanDirectories("./src/**/obj");
|
||||
CleanDirectories("./src/**/bin");
|
||||
|
||||
NuGetRestore("./src/Jackett.sln");
|
||||
|
||||
var buildSettings = new MSBuildSettings()
|
||||
.SetConfiguration(configuration)
|
||||
.UseToolVersion(MSBuildToolVersion.VS2017);
|
||||
|
||||
MSBuild("./src/Jackett.sln", buildSettings);
|
||||
});
|
||||
|
||||
Task("Experimental-Kestrel-Windows-Full-Framework")
|
||||
.IsDependentOn("Kestrel-Full-Framework")
|
||||
.IsDependentOn("Check-Packaging-Platform")
|
||||
.Does(() =>
|
||||
{
|
||||
string serverProjectPath = "./src/Jackett.Server/Jackett.Server.csproj";
|
||||
@@ -179,7 +122,7 @@ Task("Experimental-Kestrel-Windows-Full-Framework")
|
||||
});
|
||||
|
||||
Task("Experimental-Kestrel-Mono-Full-Framework")
|
||||
.IsDependentOn("Kestrel-Full-Framework")
|
||||
.IsDependentOn("Check-Packaging-Platform")
|
||||
.Does(() =>
|
||||
{
|
||||
string serverProjectPath = "./src/Jackett.Server/Jackett.Server.csproj";
|
||||
@@ -199,11 +142,17 @@ Task("Experimental-Kestrel-Mono-Full-Framework")
|
||||
var configFile = File(buildOutputPath + "/JackettConsole.exe.config");
|
||||
XmlPoke(configFile, "configuration/runtime/*[name()='assemblyBinding']/*[name()='dependentAssembly']/*[name()='assemblyIdentity'][@name='System.Net.Http']/../*[name()='bindingRedirect']/@newVersion", "4.0.0.0");
|
||||
|
||||
Gzip("./BuildOutput/Experimental/net461/linux-x64", $"./{artifactsDirName}", "Jackett", "Experimental.Jackett.Binaries.Mono.tar.gz");
|
||||
//Mono on FreeBSD doesn't like the bundled System.Runtime.InteropServices.RuntimeInformation
|
||||
//https://github.com/dotnet/corefx/issues/23989
|
||||
//https://github.com/Jackett/Jackett/issues/3547
|
||||
|
||||
DeleteFile(buildOutputPath + "/System.Runtime.InteropServices.RuntimeInformation.dll");
|
||||
|
||||
Gzip("./BuildOutput/Experimental/net461/linux-x64", $"./{artifactsDirName}", "Jackett", "Jackett.Binaries.Mono.tar.gz");
|
||||
});
|
||||
|
||||
Task("Experimental-DotNetCore")
|
||||
.IsDependentOn("Kestrel-Full-Framework")
|
||||
.IsDependentOn("Check-Packaging-Platform")
|
||||
.Does(() =>
|
||||
{
|
||||
string serverProjectPath = "./src/Jackett.Server/Jackett.Server.csproj";
|
||||
@@ -227,7 +176,6 @@ Task("Experimental")
|
||||
});
|
||||
|
||||
Task("Appveyor-Push-Artifacts")
|
||||
.IsDependentOn("Package-Full-Framework")
|
||||
.IsDependentOn("Experimental")
|
||||
.Does(() =>
|
||||
{
|
||||
|
||||
@@ -738,9 +738,9 @@ function updateReleasesRow(row)
|
||||
if (DownloadVolumeFactor == 0) {
|
||||
labels.append('\n<span class="label label-success">FREELEECH</span>');
|
||||
} else if (DownloadVolumeFactor < 1) {
|
||||
labels.append('\n<span class="label label-primary">' + DownloadVolumeFactor * 100 + '%DL</span>');
|
||||
labels.append('\n<span class="label label-primary">' + (DownloadVolumeFactor * 100).toFixed(0) + '%DL</span>');
|
||||
} else if (DownloadVolumeFactor > 1) {
|
||||
labels.append('\n<span class="label label-danger">' + DownloadVolumeFactor * 100 + '%DL</span>');
|
||||
labels.append('\n<span class="label label-danger">' + (DownloadVolumeFactor * 100).toFixed(0) + '%DL</span>');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -748,7 +748,7 @@ function updateReleasesRow(row)
|
||||
if (UploadVolumeFactor == 0) {
|
||||
labels.append('\n<span class="label label-warning">NO UPLOAD</span>');
|
||||
} else if (UploadVolumeFactor != 1) {
|
||||
labels.append('\n<span class="label label-info">' + UploadVolumeFactor * 100 + '%UL</span>');
|
||||
labels.append('\n<span class="label label-info">' + (UploadVolumeFactor * 100).toFixed(0) + '%UL</span>');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
</div>
|
||||
<div class="input-area">
|
||||
<span class="input-header">Proxy password: </span>
|
||||
<input id="jackett-proxy-password" class="form-control input-right" type="text" value="" placeholder="">
|
||||
<input id="jackett-proxy-password" class="form-control input-right" type="password" value="" placeholder="">
|
||||
</div>
|
||||
|
||||
<div class="input-area">
|
||||
@@ -663,6 +663,6 @@
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="../libs/api.js?changed=2017083001"></script>
|
||||
<script type="text/javascript" src="../custom.js?changed=20180709"></script>
|
||||
<script type="text/javascript" src="../custom.js?changed=20180710"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -56,6 +56,9 @@
|
||||
args: id
|
||||
title:
|
||||
selector: td:nth-child(3) > a.torrent > span.span-1440
|
||||
filters:
|
||||
- name: re_replace # remove anidb id from return string
|
||||
args: ["(\\[[A-Z0-9]*\\])\\.", "."]
|
||||
details:
|
||||
selector: td:nth-child(3) > a.torrent
|
||||
attribute: href
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
selector: a[href^="details.php"]
|
||||
attribute: href
|
||||
download:
|
||||
selector: a[href^=" /gettorrent/ssl/"]
|
||||
selector: a[href^=" /gettorrent/"]
|
||||
attribute: href
|
||||
files:
|
||||
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(1) > b:nth-child(2), a[href*="&filelist=1"]
|
||||
|
||||
@@ -62,13 +62,13 @@
|
||||
selector: a.view-torrent
|
||||
attribute: href
|
||||
size:
|
||||
selector: td:nth-child(4)
|
||||
seeders:
|
||||
selector: td:nth-child(6)
|
||||
leechers:
|
||||
selector: td:nth-child(7)
|
||||
grabs:
|
||||
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\.]+)
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
---
|
||||
site: btxpress
|
||||
name: BTXpress
|
||||
description: "HD Tracker Movies/TV/Music"
|
||||
description: "HD Tracker Movies/TV"
|
||||
language: en-us
|
||||
type: private
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- https://btxpress.org/
|
||||
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
- {id: 1, cat: Movies, desc: "Movies"}
|
||||
- {id: 2, cat: TV, desc: "TV"}
|
||||
- {id: 3, cat: Audio, desc: "Music"}
|
||||
|
||||
modes:
|
||||
search: [q]
|
||||
@@ -36,7 +35,6 @@
|
||||
inputs:
|
||||
$raw: "{{range .Categories}}categories[]={{.}}&{{end}}"
|
||||
search: "{{if .Query.IMDBID}}{{else}}{{ .Keywords }}{{end}}"
|
||||
description: ""
|
||||
uploader: ""
|
||||
imdb: "{{ .Query.IMDBIDShort }}"
|
||||
tvdb: ""
|
||||
@@ -45,15 +43,8 @@
|
||||
sorting: created_at
|
||||
direction: desc
|
||||
qty: 100
|
||||
preprocessingfilters:
|
||||
- name: jsonjoinarray
|
||||
args: ["$.result", ""]
|
||||
- name: prepend
|
||||
args: "<table>"
|
||||
- name: append
|
||||
args: "</table>"
|
||||
rows:
|
||||
selector: tr
|
||||
selector: table > tbody > tr
|
||||
fields:
|
||||
category:
|
||||
selector: a[href*="/categories/"]
|
||||
@@ -64,33 +55,24 @@
|
||||
title:
|
||||
selector: a.view-torrent
|
||||
download:
|
||||
selector: a[href*="/download_check/"]
|
||||
selector: a[href*="/download/"]
|
||||
attribute: href
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["/download_check/", "/download/"]
|
||||
details:
|
||||
selector: a.view-torrent
|
||||
attribute: href
|
||||
size:
|
||||
selector: td:nth-child(5)
|
||||
selector: td:nth-child(4)
|
||||
seeders:
|
||||
selector: td:nth-child(7)
|
||||
leechers:
|
||||
selector: td:nth-child(8)
|
||||
grabs:
|
||||
selector: td:nth-child(6)
|
||||
leechers:
|
||||
selector: td:nth-child(7)
|
||||
grabs:
|
||||
selector: td:nth-child(5)
|
||||
filters:
|
||||
- name: regexp
|
||||
args: ([\d\.]+)
|
||||
date:
|
||||
selector: time
|
||||
attribute: datetime
|
||||
filters:
|
||||
- name: append
|
||||
args: " +00:00"
|
||||
- name: dateparse
|
||||
args: "2006-01-02 15:04:05 -07:00"
|
||||
downloadvolumefactor:
|
||||
case:
|
||||
"i[data-original-title=\"100% Free\"]": "0"
|
||||
|
||||
@@ -1,13 +1,39 @@
|
||||
---
|
||||
# Update by LA5T based on the orignial 'cinematik.yml'
|
||||
# 29.07.2018 22:53 UTC+2
|
||||
#
|
||||
site: cinematik
|
||||
name: Cinematik
|
||||
description: "Non-Hollywood movie tracker"
|
||||
description: "Tracker for non-hollywood movies."
|
||||
language: en-us
|
||||
type: private
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- https://www.cinematik.net
|
||||
|
||||
settings:
|
||||
- name: username
|
||||
type: text
|
||||
label: Username
|
||||
- name: password
|
||||
type: password
|
||||
label: Password
|
||||
- name: incldead
|
||||
type: select
|
||||
label: Status
|
||||
default: 1
|
||||
options:
|
||||
0: Active
|
||||
1: "Active and Inactive"
|
||||
2: Inactive
|
||||
- name: srchdtls
|
||||
type: checkbox
|
||||
label: "Detailed search"
|
||||
- name: info_results
|
||||
type: info
|
||||
label: "Search results"
|
||||
default: "You can increase the number of search results in your profile.<br />Default is 15."
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
- {id: 1, cat: Movies, desc: "Comedy"}
|
||||
@@ -42,13 +68,15 @@
|
||||
- selector: table:contains("Login failed!")
|
||||
test:
|
||||
path: my.php
|
||||
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: browse.php
|
||||
inputs:
|
||||
$raw: "{{range .Categories}}filter_cat[{{.}}]=1&{{end}}"
|
||||
$raw: "{{range .Categories}}c{{.}}=1&{{end}}"
|
||||
search: "{{ .Query.Keywords }}"
|
||||
incldead: "{{ .Config.incldead }}"
|
||||
srchdtls: "{{ if .Config.srchdtls }}1{{ else }}0{{ end }}"
|
||||
rows:
|
||||
selector: table[border="1"] tr:not(:first-child)
|
||||
fields:
|
||||
@@ -82,11 +110,11 @@
|
||||
selector: td:nth-child(11) div.addedtor
|
||||
downloadvolumefactor:
|
||||
case:
|
||||
"img[title=\"Golden Torrent: No Download Stats are Recorded\"]": "0"
|
||||
"img[title=\"Silver Torrent: Download Stats are 25% Recorded\"]": "0.25"
|
||||
"img[title=\"Platinum Torrent: No Download Stats are Recorded, Upload Stats are Doubled!\"]": "0"
|
||||
"*": "1"
|
||||
"img[title=\"Golden Torrent: No Download Stats are Recorded\"]": 0
|
||||
"img[title=\"Silver Torrent: Download Stats are 25% Recorded\"]": 0.25
|
||||
"img[title=\"Platinum Torrent: No Download Stats are Recorded, Upload Stats are Doubled!\"]": 0
|
||||
"*": 1
|
||||
uploadvolumefactor:
|
||||
case:
|
||||
"img[title=\"Platinum Torrent: No Download Stats are Recorded, Upload Stats are Doubled!\"]": "2"
|
||||
"*": "1"
|
||||
"img[title=\"Platinum Torrent: No Download Stats are Recorded, Upload Stats are Doubled!\"]": 2
|
||||
"*": 1
|
||||
@@ -67,6 +67,14 @@
|
||||
args: [".*? / ", ""]
|
||||
- name: diacritics
|
||||
args: replace
|
||||
- name: replace
|
||||
args: ["1080i", "1080p"]
|
||||
- name: replace
|
||||
args: ["720i", "720p"]
|
||||
- name: replace
|
||||
args: ["pLQ", "p"]
|
||||
- name: replace
|
||||
args: ["pHD", "p"]
|
||||
- name: replace
|
||||
args: ["serie", ""]
|
||||
- name: replace
|
||||
|
||||
@@ -1,177 +0,0 @@
|
||||
---
|
||||
site: eotforum
|
||||
name: EoT-Forum
|
||||
description: "A German gerneral tracker"
|
||||
language: de-de
|
||||
type: private
|
||||
encoding: windows-1252
|
||||
links:
|
||||
- https://eot-forum.net
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
# Filme
|
||||
- {id: 14, cat: Movies/SD, desc: "SD XviD"}
|
||||
- {id: 15, cat: Movies/SD, desc: "SD x264"}
|
||||
- {id: 16, cat: Movies/HD, desc: "HD"}
|
||||
- {id: 68, cat: Movies/HD, desc: "UHD"}
|
||||
- {id: 17, cat: Movies/3D, desc: "3D"}
|
||||
- {id: 18, cat: Movies/DVD, desc: "DVD-R"}
|
||||
- {id: 19, cat: Movies, desc: "Pack"}
|
||||
- {id: 20, cat: Movies, desc: "International"}
|
||||
- {id: 21, cat: XXX, desc: "XXX"}
|
||||
|
||||
# Serien/TV
|
||||
- {id: 23, cat: TV/SD, desc: "SD XviD"}
|
||||
- {id: 24, cat: TV/SD, desc: "SD x264"}
|
||||
- {id: 25, cat: TV/HD, desc: "HD"}
|
||||
- {id: 26, cat: TV/SD, desc: "DVD-R"}
|
||||
- {id: 27, cat: TV, desc: "Pack"}
|
||||
- {id: 28, cat: TV, desc: "International"}
|
||||
- {id: 29, cat: TV/Sport, desc: "Sport"}
|
||||
|
||||
# Dokus
|
||||
- {id: 31, cat: TV/Documentary, desc: "SD XviD"}
|
||||
- {id: 32, cat: TV/Documentary, desc: "SD x264"}
|
||||
- {id: 33, cat: TV/Documentary, desc: "HD"}
|
||||
- {id: 34, cat: TV/Documentary, desc: "3D"}
|
||||
- {id: 35, cat: TV/Documentary, desc: "Pack"}
|
||||
- {id: 67, cat: TV/Documentary, desc: "DVD-R"}
|
||||
- {id: 36, cat: TV/Documentary, desc: "International"}
|
||||
|
||||
# Audio
|
||||
- {id: 38, cat: Audio, desc: "Charts"}
|
||||
- {id: 39, cat: Audio/MP3, desc: "MP3"}
|
||||
- {id: 40, cat: Audio/Lossless, desc: "Flac"}
|
||||
- {id: 41, cat: Audio, desc: "Pack"}
|
||||
- {id: 42, cat: Audio/Video, desc: "MusikVideo"}
|
||||
- {id: 43, cat: Audio/Audiobook, desc: "Hörbücher"}
|
||||
|
||||
# Spiele
|
||||
- {id: 45, cat: PC/Games, desc: "Windows"}
|
||||
- {id: 46, cat: PC/Mac, desc: "MacOS"}
|
||||
- {id: 47, cat: Console/PS4, desc: "Sony PS"}
|
||||
- {id: 48, cat: Console/Xbox , desc: "Microsoft XBox"}
|
||||
- {id: 49, cat: Console/NDS, desc: "Nintendo"}
|
||||
- {id: 50, cat: PC/Games, desc: "Linux"}
|
||||
- {id: 51, cat: Console, desc: "Andere"}
|
||||
|
||||
# Software
|
||||
- {id: 53, cat: PC, desc: "Windows"}
|
||||
- {id: 54, cat: PC/Mac, desc: "MacOS"}
|
||||
- {id: 55, cat: PC, desc: "Linux"}
|
||||
- {id: 56, cat: PC/Phone-Android, desc: "Android"}
|
||||
- {id: 57, cat: PC/Phone-IOS, desc: "Apple IOS"}
|
||||
- {id: 58, cat: PC/Phone-Other, desc: "Andere"}
|
||||
|
||||
# Sonstiges
|
||||
- {id: 60, cat: Books, desc: "EBooks"}
|
||||
- {id: 61, cat: Other, desc: "Bilder"}
|
||||
- {id: 62, cat: TV/Anime, desc: "Anime"}
|
||||
- {id: 63, cat: Other, desc: "MISC"}
|
||||
- {id: 64, cat: XXX, desc: "XXX-Bilder/EBooks/Audio"}
|
||||
|
||||
# EOT-Specials
|
||||
- {id: 66, cat: Other, desc: "Special"}
|
||||
|
||||
modes:
|
||||
search: [q]
|
||||
tv-search: [q, season, ep]
|
||||
|
||||
login:
|
||||
path: index.php?page=login
|
||||
method: post
|
||||
inputs:
|
||||
uid: "{{ .Config.username }}"
|
||||
pwd: "{{ .Config.password }}"
|
||||
rememberme: "forever"
|
||||
submit: "Login"
|
||||
error:
|
||||
- selector: td.lista[align="center"][colspan="2"] > span
|
||||
test:
|
||||
path: index.php
|
||||
selector: a[href^="logout.php"]
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: index.php
|
||||
inputs:
|
||||
page: "torrents"
|
||||
search: "{{ .Query.Keywords }}"
|
||||
options: "0"
|
||||
active: "0"
|
||||
gold: "0"
|
||||
rows:
|
||||
selector: table.lista > tbody > tr:has(a[href^="index.php?page=torrent-details&id="])
|
||||
dateheaders:
|
||||
selector: ":has(td.header > b)"
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["Torrents vom ", ""]
|
||||
- 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: "02.January.2006"
|
||||
fields:
|
||||
download:
|
||||
selector: a[href^="download.php?id="]
|
||||
attribute: href
|
||||
title:
|
||||
selector: a[href^="index.php?page=torrent-details&id="]
|
||||
attribute: title
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["Details anzeigen: ", ""]
|
||||
category:
|
||||
selector: a[href^="index.php?page=torrents&category="]
|
||||
attribute: href
|
||||
filters:
|
||||
- name: querystring
|
||||
args: category
|
||||
comments:
|
||||
selector: a[href*="#comments"]
|
||||
attribute: href
|
||||
size:
|
||||
selector: td:nth-child(3)
|
||||
grabs:
|
||||
selector: td:nth-child(5)
|
||||
filters:
|
||||
- name: split
|
||||
args: ["♦", 2]
|
||||
- name: replace
|
||||
args: ["---", "0"]
|
||||
seeders:
|
||||
selector: td:nth-child(5) > a:nth-child(1)
|
||||
leechers:
|
||||
selector: td:nth-child(5) > a:nth-child(2)
|
||||
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"
|
||||
@@ -49,7 +49,13 @@
|
||||
- path: "{{ if .Keywords }}buscar/descargas/{{ .Config.category }}/{{ .Keywords }}?search=Buscar&page=2{{else}}descargas{{end}}"
|
||||
keywordsfilters:
|
||||
- name: re_replace #remove S/EXX from search string
|
||||
args: ["([SE]\\d{1,2})", ""]
|
||||
args: ["(S1)", ""]
|
||||
- name: re_replace #remove S/EXX from search string
|
||||
args: ["(S2)", "segunda temporada"]
|
||||
- name: re_replace #remove S/EXX from search string
|
||||
args: ["(S3)", "tercera temporada"]
|
||||
- name: re_replace #remove S/EXX from search string
|
||||
args: ["E([0-9]+)", "$1"]
|
||||
rows:
|
||||
selector: table#descargas > tbody > tr:has(td:has(a[href^="magnet:?"]))
|
||||
fields:
|
||||
@@ -63,17 +69,19 @@
|
||||
- name: re_replace
|
||||
args: ["\\)", ""]
|
||||
- name: re_replace
|
||||
args: ["([A-z]*) temporada", "S$1"]
|
||||
args: ["([A-z]*) temporada", ""]
|
||||
- name: re_replace
|
||||
args: ["S[pP]rimera", "S1"]
|
||||
args: ["S[pP]rimera", ""]
|
||||
- name: re_replace
|
||||
args: ["S[sS]egunda", "S2"]
|
||||
args: ["S[sS]egunda", ""]
|
||||
- name: re_replace
|
||||
args: ["S[tT]ercera", "S3"]
|
||||
args: ["S[tT]ercera", ""]
|
||||
- name: re_replace
|
||||
args: ["S([0-9]+) - Episodio ([0-9]+)", "S$1E$2"]
|
||||
args: ["S([0-9]+) - Episodio ([0-9]+)", "$2"]
|
||||
- name: re_replace
|
||||
args: ["- Episodio ([0-9]*)", "E$1"]
|
||||
args: ["- Episodio ([0-9]*)", "$1"]
|
||||
- name: append
|
||||
args: " [spanish]"
|
||||
details:
|
||||
selector: td.tit a
|
||||
attribute: href
|
||||
|
||||
151
src/Jackett.Common/Definitions/gay-torrentsorg.yml
Normal file
151
src/Jackett.Common/Definitions/gay-torrentsorg.yml
Normal file
@@ -0,0 +1,151 @@
|
||||
---
|
||||
# By LA5T for https://gay-torrents.org (29.07.2018 22:55 UTC+2)
|
||||
#
|
||||
site: gay-torrentsorg
|
||||
name: gay-torrents.org
|
||||
description: "Tracker for GAY XXX, movies, TV, books and PC."
|
||||
language: en-us
|
||||
type: semi-private
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- https://gay-torrents.org
|
||||
- https://gay-area.org/
|
||||
|
||||
settings:
|
||||
- name: username
|
||||
type: text
|
||||
label: Username
|
||||
- name: password
|
||||
type: password
|
||||
label: Password
|
||||
- name: active
|
||||
type: select
|
||||
label: Status
|
||||
default: 0
|
||||
options:
|
||||
0: "Active and Inactive"
|
||||
1: Active
|
||||
2: Inactive
|
||||
- name: info_categories
|
||||
type: info
|
||||
label: "Hidden categories"
|
||||
default: "Results for categories hidden in profile will not be visible."
|
||||
- name: info_results
|
||||
type: info
|
||||
label: "Search results"
|
||||
default: "You can increase the number of search results in your profile.<br />Default is 15."
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
- {id: 15, cat: XXX, desc: "Amateur"}
|
||||
- {id: 16, cat: XXX, desc: "Anal"}
|
||||
- {id: 42, cat: XXX, desc: "Animation"}
|
||||
- {id: 18, cat: XXX, desc: "Asian"}
|
||||
- {id: 19, cat: XXX, desc: "Bareback"}
|
||||
- {id: 20, cat: XXX, desc: "Bears"}
|
||||
- {id: 22, cat: XXX, desc: "Bisexual"}
|
||||
- {id: 21, cat: XXX, desc: "Black"}
|
||||
- {id: 23, cat: XXX, desc: "Chubs"}
|
||||
- {id: 25, cat: XXX, desc: "Cross Generation"}
|
||||
- {id: 51, cat: XXX, desc: "Doctor/Medical"}
|
||||
- {id: 27, cat: XXX, desc: "Fetish"}
|
||||
- {id: 28, cat: XXX, desc: "Group Sex"}
|
||||
- {id: 30, cat: XXX, desc: "Hunks"}
|
||||
- {id: 52, cat: XXX, desc: "Interracial"}
|
||||
- {id: 68, cat: XXX, desc: "Homo Erotic"}
|
||||
- {id: 68, cat: Movies, desc: "Homo Erotic"}
|
||||
- {id: 68, cat: TV, desc: "Homo Erotic"}
|
||||
- {id: 68, cat: Other, desc: "Homo Erotic"}
|
||||
- {id: 32, cat: XXX, desc: "Latino"}
|
||||
- {id: 50, cat: XXX, desc: "Middle Eastern"}
|
||||
- {id: 33, cat: XXX, desc: "Military"}
|
||||
- {id: 34, cat: XXX, desc: "Oral-Sex"}
|
||||
- {id: 40, cat: Other, desc: "Other"}
|
||||
- {id: 35, cat: XXX, desc: "Solo"}
|
||||
- {id: 36, cat: XXX, desc: "Transsexual"}
|
||||
- {id: 37, cat: XXX, desc: "Twinks"}
|
||||
- {id: 38, cat: XXX, desc: "Vintage"}
|
||||
- {id: 39, cat: XXX, desc: "Wrestling"}
|
||||
- {id: 17, cat: PC, desc: "Applications"}
|
||||
- {id: 31, cat: XXX/Imageset, desc: "Images"}
|
||||
- {id: 49, cat: Books, desc: "Books"}
|
||||
- {id: 41, cat: Movies, desc: "Non-Porn"}
|
||||
- {id: 41, cat: TV, desc: "Non-Porn"}
|
||||
- {id: 41, cat: Other, desc: "Non-Porn"}
|
||||
modes:
|
||||
search: [q]
|
||||
|
||||
login:
|
||||
method: post
|
||||
path: login.php
|
||||
inputs:
|
||||
uid: "{{ .Config.username }}"
|
||||
pwd: "{{ .Config.password }}"
|
||||
error:
|
||||
- selector: div.fixed_width:nth-child(4) > span:contains("Incorrect")
|
||||
test:
|
||||
path: usercp.php
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: torrents_beta.php
|
||||
method: get
|
||||
inputs:
|
||||
$raw: "{{range .Categories}}category[]={{.}}&{{end}}"
|
||||
search: "{{ .Query.Keywords }}"
|
||||
active: "{{ .Config.active }}"
|
||||
rows:
|
||||
selector: div.torrent
|
||||
fields:
|
||||
title:
|
||||
selector: div:nth-child(2) > div:nth-child(1) > a:nth-child(1)
|
||||
category:
|
||||
selector: a[href^="torrents_beta.php?category="]
|
||||
attribute: href
|
||||
filters:
|
||||
- name: querystring
|
||||
args: category
|
||||
details:
|
||||
selector: a[href^="details.php?id="]
|
||||
attribute: href
|
||||
banner:
|
||||
optional: true
|
||||
selector: a.screenshot
|
||||
attribute: rel
|
||||
grabs:
|
||||
selector: div.downloadTimes
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["No downloads yet", "0"]
|
||||
- name: regexp
|
||||
args: ([\d,]+)
|
||||
comments:
|
||||
selector: a[href^="details.php?id="]
|
||||
attribute: href
|
||||
download:
|
||||
selector: a[href^="download.php?id="]
|
||||
attribute: href
|
||||
size:
|
||||
selector: div.size
|
||||
seeders:
|
||||
selector: div.downloadPeers div:nth-child(1) > a
|
||||
leechers:
|
||||
selector: div.downloadPeers > div:nth-child(2) > a
|
||||
date:
|
||||
selector: div.date
|
||||
filters:
|
||||
- name: re_replace
|
||||
args: ["on (\\d{2}:\\d{2}) (\\d{2})-([a-zA-Z]{3})-(\\d{4})", "$2 $3 $4 $1"]
|
||||
- name: append
|
||||
args: " +01:00"
|
||||
- name: dateparse
|
||||
args: "02 Jan 2006 15:04 -07:00"
|
||||
downloadvolumefactor:
|
||||
case:
|
||||
"div:nth-child(2) > div:nth-child(3) > a:contains(\"FREE!\")": 0
|
||||
"div:nth-child(2) > div:nth-child(3) > a:contains(\"-50%\")": 0.5
|
||||
"div:nth-child(2) > div:nth-child(3) > a:contains(\"-25%\")": 0.25
|
||||
"*": 1
|
||||
uploadvolumefactor:
|
||||
case:
|
||||
"*": 1
|
||||
@@ -1,52 +1,80 @@
|
||||
---
|
||||
# Update by LA5T based on the orignial 'gaytorrentru.yml'
|
||||
# 29.07.2018 23:02 UTC+2
|
||||
#
|
||||
site: gaytorrentru
|
||||
name: GayTorrent.ru
|
||||
description: "World largest gay porn library for free with a stunning forum and 24/7 Chat"
|
||||
name: GAYtorrent.ru
|
||||
description: "World largest gay porn library for free with a stunning forum and 24/7 chat."
|
||||
language: en-us
|
||||
type: private
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- https://www.gaytorrent.ru/
|
||||
|
||||
settings:
|
||||
- name: username
|
||||
type: text
|
||||
label: Username
|
||||
- name: password
|
||||
type: password
|
||||
label: Password
|
||||
- name: incldead
|
||||
type: select
|
||||
label: Status
|
||||
default: 1
|
||||
options:
|
||||
0: Active
|
||||
1: "Active and Inactive"
|
||||
2: Inactive
|
||||
- name: info
|
||||
type: info
|
||||
label: "Hidden categories"
|
||||
default: "For results in the following categories you must edit your profile.<br />- Straight<br />- Bisexual<br />- Scat"
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
- {id: 62 , cat: XXX , desc: "Amateur"}
|
||||
- {id: 29 , cat: XXX , desc: "Anal"}
|
||||
- {id: 46 , cat: XXX , desc: "Anime Games"}
|
||||
- {id: 30 , cat: XXX , desc: "Asian"}
|
||||
- {id: 43 , cat: XXX , desc: "Bareback"}
|
||||
- {id: 19 , cat: XXX , desc: "BDSM"}
|
||||
- {id: 17 , cat: XXX , desc: "Bears"}
|
||||
- {id: 44 , cat: XXX , desc: "Black"}
|
||||
- {id: 50 , cat: Books , desc: "Books & Magazines"}
|
||||
- {id: 9 , cat: XXX , desc: "Chubbies"}
|
||||
- {id: 7 , cat: XXX , desc: "Clips"}
|
||||
- {id: 48 , cat: Books/Comics , desc: "Comic & Yaoi"}
|
||||
- {id: 5 , cat: XXX , desc: "Daddies / Sons"}
|
||||
- {id: 34 , cat: XXX , desc: "Fetish"}
|
||||
- {id: 27 , cat: XXX , desc: "Grey / Older"}
|
||||
- {id: 32 , cat: XXX , desc: "Group-Sex"}
|
||||
- {id: 63 , cat: XXX , desc: "Homemade"}
|
||||
- {id: 12 , cat: XXX , desc: "Hunks"}
|
||||
- {id: 33 , cat: XXX , desc: "Images"}
|
||||
- {id: 53 , cat: XXX , desc: "Interracial"}
|
||||
- {id: 57 , cat: XXX , desc: "Jocks"}
|
||||
- {id: 35 , cat: XXX , desc: "Latino"}
|
||||
- {id: 36 , cat: XXX , desc: "Mature"}
|
||||
- {id: 58 , cat: PC , desc: "Media Programs"}
|
||||
- {id: 37 , cat: XXX , desc: "Member"}
|
||||
- {id: 54 , cat: XXX , desc: "Middle Eastern"}
|
||||
- {id: 38 , cat: XXX , desc: "Military"}
|
||||
- {id: 39 , cat: XXX , desc: "Oral-Sex"}
|
||||
- {id: 47 , cat: XXX , desc: "Shemale"}
|
||||
- {id: 56 , cat: XXX , desc: "Softcore"}
|
||||
- {id: 40 , cat: XXX , desc: "Solo"}
|
||||
- {id: 45 , cat: Movies , desc: "Themed Movie"}
|
||||
- {id: 1 , cat: TV , desc: "TV / Episodes"}
|
||||
- {id: 41 , cat: XXX , desc: "Twinks"}
|
||||
- {id: 42 , cat: XXX , desc: "Vintage"}
|
||||
- {id: 51 , cat: XXX , desc: "Voyeur"}
|
||||
- {id: 65 , cat: XXX , desc: "Wrestling and Sports"}
|
||||
- {id: 28 , cat: XXX , desc: "Youngblood"}
|
||||
- {id: 62, cat: XXX, desc: "Amateur"}
|
||||
- {id: 29, cat: XXX, desc: "Anal"}
|
||||
- {id: 46, cat: XXX, desc: "Anime Games"}
|
||||
- {id: 30, cat: XXX, desc: "Asian"}
|
||||
- {id: 43, cat: XXX, desc: "Bareback"}
|
||||
- {id: 19, cat: XXX, desc: "BDSM"}
|
||||
- {id: 17, cat: XXX, desc: "Bears"}
|
||||
- {id: 44, cat: XXX, desc: "Black"}
|
||||
- {id: 50, cat: Books, desc: "Books & Magazines"}
|
||||
- {id: 9, cat: XXX, desc: "Chubbies"}
|
||||
- {id: 7, cat: XXX, desc: "Clips"}
|
||||
- {id: 48, cat: Books/Comics, desc: "Comic & Yaoi"}
|
||||
- {id: 5, cat: XXX, desc: "Daddies / Sons"}
|
||||
- {id: 34, cat: XXX, desc: "Fetish"}
|
||||
- {id: 27, cat: XXX, desc: "Grey / Older"}
|
||||
- {id: 32, cat: XXX, desc: "Group-Sex"}
|
||||
- {id: 63, cat: XXX, desc: "Homemade"}
|
||||
- {id: 12, cat: XXX, desc: "Hunks"}
|
||||
- {id: 33, cat: XXX/Imageset, desc: "Images"}
|
||||
- {id: 53, cat: XXX, desc: "Interracial"}
|
||||
- {id: 57, cat: XXX, desc: "Jocks"}
|
||||
- {id: 35, cat: XXX, desc: "Latino"}
|
||||
- {id: 36, cat: XXX, desc: "Mature"}
|
||||
- {id: 58, cat: PC, desc: "Media Programs"}
|
||||
- {id: 37, cat: XXX, desc: "Member"}
|
||||
- {id: 54, cat: XXX, desc: "Middle Eastern"}
|
||||
- {id: 38, cat: XXX, desc: "Military"}
|
||||
- {id: 39, cat: XXX, desc: "Oral-Sex"}
|
||||
- {id: 47, cat: XXX, desc: "Shemale"}
|
||||
- {id: 56, cat: XXX, desc: "Softcore"}
|
||||
- {id: 40, cat: XXX, desc: "Solo"}
|
||||
- {id: 45, cat: Movies, desc: "Themed Movie"}
|
||||
- {id: 1, cat: TV, desc: "TV / Episodes"}
|
||||
- {id: 41, cat: XXX, desc: "Twinks"}
|
||||
- {id: 42, cat: XXX, desc: "Vintage"}
|
||||
- {id: 51, cat: XXX, desc: "Voyeur"}
|
||||
- {id: 65, cat: XXX, desc: "Wrestling and Sports"}
|
||||
- {id: 28, cat: XXX, desc: "Youngblood"}
|
||||
- {id: 59, cat: XXX, desc: "Bisexual"}
|
||||
- {id: 61, cat: XXX, desc: "Straight older"}
|
||||
- {id: 60, cat: XXX, desc: "Straight younger"}
|
||||
- {id: 64, cat: XXX, desc: "Scat"}
|
||||
modes:
|
||||
search: [q]
|
||||
|
||||
@@ -65,7 +93,7 @@
|
||||
inputs:
|
||||
$raw: "{{range .Categories}}c{{.}}=1&{{end}}"
|
||||
search: "{{ .Query.Keywords }}"
|
||||
incldead: "0" # Searches only for alive torrents
|
||||
incldead: "{{ .Config.incldead }}"
|
||||
rows:
|
||||
selector: table.browse_result > tbody > tr:has(a[href^="details.php?id="])
|
||||
fields:
|
||||
@@ -89,12 +117,12 @@
|
||||
selector: .tfiles
|
||||
filters:
|
||||
- name: regexp
|
||||
args: ([\d]+)
|
||||
args: ([\d,]+)
|
||||
size:
|
||||
selector: .tsize
|
||||
seeders:
|
||||
optional: true
|
||||
selector: a[href$="&toseeders=1"]
|
||||
selector: a[href$="&toseeders=1"], span.red
|
||||
leechers:
|
||||
optional: true
|
||||
selector: a[href$="&todlers=1"]
|
||||
@@ -102,13 +130,13 @@
|
||||
selector: .tadded
|
||||
filters:
|
||||
- name: re_replace
|
||||
args: ["(\\d{4}-\\d{2}-\\d{2})(\\d{2}:\\d{2}:\\d{2})(.*)","$1 $2"]
|
||||
args: ["(\\d{4}-\\d{2}-\\d{2})(\\d{2}:\\d{2}:\\d{2}).*", "$1 $2"]
|
||||
- name: dateparse
|
||||
args: "2006-01-02 15:04:05"
|
||||
downloadvolumefactor:
|
||||
case:
|
||||
"td:nth-child(3) > div > nobr > font[color=\"yellow\"]": "0"
|
||||
"*": "1"
|
||||
"td:nth-child(3) > div > nobr > font[color=\"yellow\"]": 0
|
||||
"*": 1
|
||||
uploadvolumefactor:
|
||||
case:
|
||||
"*": "1"
|
||||
"*": 1
|
||||
@@ -101,80 +101,49 @@
|
||||
search:
|
||||
paths:
|
||||
- path: /index.php
|
||||
keywordsfilters:
|
||||
- name: re_replace
|
||||
args: ["S[0-9]{2}([^E]|$)", ""] # remove season tag without episode (search doesn't support it)
|
||||
- name: diacritics
|
||||
args: replace
|
||||
# most ITA TV torrents are in XXxYY format, so we search without S/E prefixes and filter later
|
||||
- name: re_replace
|
||||
args: ["S0?(\\d{1,2})", " $1 "]
|
||||
- name: re_replace
|
||||
args: ["E(\\d{2,3})", " $1 "]
|
||||
inputs:
|
||||
search: "{{ .Keywords }}"
|
||||
category: "{{range .Categories}}{{.}};{{end}}"
|
||||
page: "torrents"
|
||||
active: 0
|
||||
keywordsfilters:
|
||||
- name: diacritics
|
||||
args: replace
|
||||
- name: re_replace # S01 to 1
|
||||
args: ["\\b[sS]0*(\\d+)\\b", "$1"]
|
||||
- name: re_replace # S01E01 to 1 1
|
||||
args: ["\\b[sS]0*(\\d+)[eE]0*(\\d+)\\b", "$1 $2"]
|
||||
rows:
|
||||
selector: div.b-content > table > tbody > tr > td > table.lista > tbody > tr:has(a[href^="index.php?page=torrent-details&id="])
|
||||
#http://girotorrent.org/index.php?page=torrent-details&id=73d93dccf84ea3a8b614a3113acfd9eea186d730
|
||||
fields:
|
||||
download:
|
||||
selector: a[href^="index.php?page=downloadcheck&id="]
|
||||
attribute: href
|
||||
title: # shortened title?
|
||||
selector: a[onmouseover][href^="index.php?page=torrent-details&id="]
|
||||
# normalize to SXXEYY format
|
||||
filters:
|
||||
- name: re_replace # replace special characters with " " (space)
|
||||
args: ["[^a-zA-Z0-9]|\\.", " "]
|
||||
args: ["[^a-zA-Z0-9\\s]|\\.", " "]
|
||||
- name: re_replace # replace multiple spaces
|
||||
args: ["[ ]{2,}", " "]
|
||||
# normalize to SXXEYY format
|
||||
- name: re_replace
|
||||
args: ["(\\d{2})x(\\d{2})", "S$1E$2"]
|
||||
- name: re_replace
|
||||
args: ["(\\d{1})x(\\d{2})", "S0$1E$2"]
|
||||
- name: re_replace #Stagione X --> S0X
|
||||
args: ["Stagione (\\d{0,1}\\s)", "S0$1"]
|
||||
- name: re_replace #Stagione XX --> SXX
|
||||
args: ["Stagione (\\d{2}\\s)", "S$1"]
|
||||
- name: re_replace #/ Episodio [YY-YY --> EYY-YY
|
||||
args: ["(\\s\\/\\sEpisodio|\\s\\/\\sEpisodi|\\sEpisodio|\\s\\|\\sEpisodio|\\sEpisodi)\\s\\[", "E"]
|
||||
- name: re_replace #/ Completa [episodi YY-YY --> EYY-YY
|
||||
args: ["(\\s\\/\\sCompleta\\s\\[episodi\\s)", "E"]
|
||||
- name: re_replace #remove di YY] | remove /YY]
|
||||
args: ["(\\sdi\\s\\d{1,2}|\\/\\d{1,2})\\]", " "]
|
||||
- name: re_replace #remove various
|
||||
args: ["(Serie completa|Completa|\\[in pausa\\])", ""]
|
||||
# fine prova
|
||||
title: # long titles?
|
||||
optional: true
|
||||
selector: a[title][href^="index.php?page=torrent-details"]
|
||||
attribute: title
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["Vedi Dettagli: ", ""]
|
||||
# inizio prova
|
||||
- name: re_replace # replace special characters with " " (space)
|
||||
args: ["[^a-zA-Z0-9]|\\.", " "]
|
||||
# normalize to SXXEYY format
|
||||
- name: re_replace
|
||||
args: ["(\\d{2})x(\\d{2})", "S$1E$2"]
|
||||
- name: re_replace
|
||||
args: ["(\\d{1})x(\\d{2})", "S0$1E$2"]
|
||||
- name: re_replace #Stagione X --> S0X
|
||||
args: ["Stagione (\\d{0,1}\\s)", "S0$1"]
|
||||
- name: re_replace #Stagione XX --> SXX
|
||||
args: ["Stagione (\\d{2}\\s)", "S$1"]
|
||||
- name: re_replace #/ Episodio [YY-YY --> EYY-YY
|
||||
args: ["(\\s\\/\\sEpisodio|\\s\\/\\sEpisodi|\\sEpisodio|\\s\\|\\sEpisodio|\\sEpisodi)\\s\\[", "E"]
|
||||
- name: re_replace #/ Completa [episodi YY-YY --> EYY-YY
|
||||
args: ["(\\s\\/\\sCompleta\\s\\[episodi\\s)", "E"]
|
||||
- name: re_replace #remove di YY] | remove /YY]
|
||||
args: ["(\\sdi\\s\\d{1,2}|\\/\\d{1,2})\\]", " "]
|
||||
- name: re_replace #remove various
|
||||
args: ["(Serie completa|Completa|\\[in pausa\\])", ""]
|
||||
# fine prova
|
||||
- name: re_replace # S01 E01 to S01E01
|
||||
args: ["\\b[sS](\\d+)\\s[eE](\\d+)\\b", "S$1E$2"]
|
||||
- name: re_replace # 01x01 to S01E01
|
||||
args: ["(\\d{2})x(\\d+)", "S$1E$2"]
|
||||
- name: re_replace # 1x01 to S01E01
|
||||
args: ["\\b(\\d{1})x(\\d+)", "S0$1E$2"]
|
||||
- name: re_replace # Stagione X --> S0X
|
||||
args: ["\\b[sS]tagion[eiEI]\\s?(\\d{1})\\b|\\b[sS]eason\\s?(\\d{1})\\b", "S0$1"]
|
||||
- name: re_replace # Stagione XX --> SXX
|
||||
args: ["\\b[sS]tagion[eiEI]\\s?(\\d{2,})\\b|\\b[sS]easons?\\s?(\\d{2,})\\b", "S$1"]
|
||||
- name: re_replace # Episodio 4 to E4
|
||||
args: ["\\b([\\/\\|]?[eE]pisodio\\s?(\\d+)|[Pp]untata\\s?(\\d+))", "E$2$3"]
|
||||
- name: re_replace # Episodi 4 5 to E04-05
|
||||
args: ["\\b(?:[Pp]untat[eE]\\s*)(\\d+)\\s?(\\d+)", "E0$1-0$2"]
|
||||
- name: re_replace # rimozioni varie
|
||||
args: ["([Ss]erie completa|[cC]ompleta[tT]?[aA]?|COMPLETA[TA]?|in pausa)", ""]
|
||||
- name: andmatch
|
||||
category:
|
||||
selector: a[href^="index.php?page=torrents&category="]
|
||||
attribute: href
|
||||
|
||||
@@ -6,10 +6,12 @@
|
||||
type: public
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- https://www.ilcorsaroblu.info/
|
||||
- https://www.ilcorsaroblu.org/
|
||||
legacylinks:
|
||||
- http://ilcorsaroblu.org/
|
||||
- https://www.ilcorsaroblu.org/
|
||||
- https://www.ilcorsaroblu.info/
|
||||
certificates:
|
||||
- e6dd93ef71f96d04559e2bee8cc8e6fd74957730 # incomplete CA chain
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
@@ -51,15 +53,12 @@
|
||||
paths:
|
||||
- path: /index.php
|
||||
keywordsfilters:
|
||||
- name: re_replace
|
||||
args: ["S[0-9]{2}([^E]|$)", ""] # remove season tag without episode (search doesn't support it)
|
||||
- name: diacritics
|
||||
args: replace
|
||||
# most ITA TV torrents are in XXxYY format, so we search without S/E prefixes and filter later
|
||||
- name: re_replace
|
||||
args: ["S0?(\\d{1,2})", " $1 "]
|
||||
- name: re_replace
|
||||
args: ["E(\\d{2,3})", " $1 "]
|
||||
- name: re_replace # S01 to 1
|
||||
args: ["\\b[sS]0*(\\d+)\\b", "$1"]
|
||||
- name: re_replace # S01E01 to 1 1
|
||||
args: ["\\b[sS]0*(\\d+)[eE]0*(\\d+)\\b", "$1 $2"]
|
||||
inputs:
|
||||
search: "{{ .Keywords }}"
|
||||
category: "{{range .Categories}}{{.}};{{end}}"
|
||||
@@ -70,28 +69,28 @@
|
||||
fields:
|
||||
title:
|
||||
selector: td:nth-child(2) > a
|
||||
# normalize to SXXEYY format
|
||||
filters:
|
||||
- name: re_replace # replace special characters with " " (space)
|
||||
args: ["[^a-zA-Z0-9]|\\.", " "]
|
||||
args: ["[^a-zA-Z0-9\\s]|\\.", " "]
|
||||
- name: re_replace # replace multiple spaces
|
||||
args: ["[ ]{2,}", " "]
|
||||
# normalize to SXXEYY format
|
||||
- name: re_replace
|
||||
args: ["(\\d{2})x(\\d{2})", "S$1E$2"]
|
||||
- name: re_replace
|
||||
args: ["(\\d{1})x(\\d{2})", "S0$1E$2"]
|
||||
- name: re_replace #Stagione X --> S0X
|
||||
args: ["Stagione (\\d{0,1}\\s)", "S0$1"]
|
||||
- name: re_replace #Stagione XX --> SXX
|
||||
args: ["Stagione (\\d{2}\\s)", "S$1"]
|
||||
- name: re_replace #/ Episodio [YY-YY --> EYY-YY
|
||||
args: ["(\\s\\/\\sEpisodio|\\s\\/\\sEpisodi|\\sEpisodio|\\s\\|\\sEpisodio|\\sEpisodi)\\s\\[", "E"]
|
||||
- name: re_replace #/ Completa [episodi YY-YY --> EYY-YY
|
||||
args: ["(\\s\\/\\sCompleta\\s\\[episodi\\s)", "E"]
|
||||
- name: re_replace #remove di YY] | remove /YY]
|
||||
args: ["(\\sdi\\s\\d{1,2}|\\/\\d{1,2})\\]", " "]
|
||||
- name: re_replace #remove various
|
||||
args: ["(Serie completa|Completa|\\[in pausa\\])", ""]
|
||||
# fine prova
|
||||
- name: re_replace # S01 E01 to S01E01
|
||||
args: ["\\b[sS](\\d+)\\s[eE](\\d+)\\b", "S$1E$2"]
|
||||
- name: re_replace # 01x01 to S01E01
|
||||
args: ["(\\d{2})x(\\d+)", "S$1E$2"]
|
||||
- name: re_replace # 1x01 to S01E01
|
||||
args: ["\\b(\\d{1})x(\\d+)", "S0$1E$2"]
|
||||
- name: re_replace # Stagione X --> S0X
|
||||
args: ["\\b[sS]tagion[eiEI]\\s?(\\d{1})\\b|\\b[sS]eason\\s?(\\d{1})\\b", "S0$1"]
|
||||
- name: re_replace # Stagione XX --> SXX
|
||||
args: ["\\b[sS]tagion[eiEI]\\s?(\\d{2,})\\b|\\b[sS]easons?\\s?(\\d{2,})\\b", "S$1"]
|
||||
- name: re_replace # Episodio 4 to E4
|
||||
args: ["\\b([\\/\\|]?[eE]pisodio\\s?(\\d+)|[Pp]untata\\s?(\\d+))", "E$2$3"]
|
||||
- name: re_replace # Episodi 4 5 to E04-05
|
||||
args: ["\\b(?:[Pp]untat[eE]\\s*)(\\d+)\\s?(\\d+)", "E0$1-0$2"]
|
||||
- name: re_replace # rimozioni varie
|
||||
args: ["([Ss]erie completa|[cC]ompleta[tT]?[aA]?|COMPLETA[TA]?|in pausa)", ""]
|
||||
download: # handle torrents with normal torrent file download
|
||||
optional: true
|
||||
selector: a[href^="download.php?id="]
|
||||
@@ -133,7 +132,7 @@
|
||||
- name: querystring
|
||||
args: category
|
||||
details:
|
||||
selector: td:nth-child(2) a
|
||||
selector: td:nth-child(2) > a
|
||||
attribute: href
|
||||
banner:
|
||||
optional: true
|
||||
@@ -143,18 +142,18 @@
|
||||
- name: regexp
|
||||
args: "src=(.+?) "
|
||||
size:
|
||||
selector: td:nth-child(9)
|
||||
selector: td:nth-child(10)
|
||||
date:
|
||||
selector: td:nth-child(5)
|
||||
selector: td:nth-child(6)
|
||||
filters:
|
||||
- name: dateparse
|
||||
args: "02/01/2006"
|
||||
grabs:
|
||||
selector: td:nth-child(8)
|
||||
selector: td:nth-child(9)
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["---", "0"]
|
||||
seeders:
|
||||
selector: td:nth-child(6)
|
||||
leechers:
|
||||
selector: td:nth-child(7)
|
||||
leechers:
|
||||
selector: td:nth-child(8)
|
||||
|
||||
@@ -37,6 +37,9 @@
|
||||
|
||||
search:
|
||||
paths:
|
||||
# FIX DA FARE:
|
||||
# 1. SE CERCO PER CATEGORIA ALLORA DEVO CAMBIARE IL PERCORSO DI RICERCA
|
||||
# 2. CONTROLLARE SE LE RELEASE VANNO FILTRATE COME PER GIROTORRENT
|
||||
##### Are the "not" and "and" functions implemented? Or am I doing it wrong?
|
||||
# path: "{{if and .Query.Keywords .advanced-search}}adv/{{ .Query.Keywords}}.html
|
||||
# {{else if and .Query.Keywords (not .advanced-search)}}argh.php?search={{ .Query.Keywords}}
|
||||
@@ -46,15 +49,12 @@
|
||||
{{else}}/recenti
|
||||
{{end}}"
|
||||
keywordsfilters:
|
||||
- name: re_replace
|
||||
args: ["S[0-9]{2}([^E]|$)", ""] # remove season tag without episode (search doesn't support it)
|
||||
- name: diacritics
|
||||
args: replace
|
||||
# most ITA TV torrents are in XXxYY format, so we search without S/E prefixes and filter later
|
||||
- name: re_replace
|
||||
args: ["S0?(\\d{1,2})", " $1 "]
|
||||
- name: re_replace
|
||||
args: ["E(\\d{2,3})", " $1 "]
|
||||
- name: re_replace # S01 to 1
|
||||
args: ["\\b[sS]0*(\\d+)\\b", "$1"]
|
||||
- name: re_replace # S01E01 to 1 1
|
||||
args: ["\\b[sS]0*(\\d+)[eE]0*(\\d+)\\b", "$1 $2"]
|
||||
rows:
|
||||
selector: "tr.odd,tr.odd2"
|
||||
fields:
|
||||
@@ -65,32 +65,28 @@
|
||||
- name: split
|
||||
args: [ "/", -1 ]
|
||||
- name: urldecode
|
||||
- name: re_replace
|
||||
args: [ "_+", " "]
|
||||
- name: replace
|
||||
args: [ ".", " "]
|
||||
- name: re_replace
|
||||
args: [ "\\s{2,}", " "]
|
||||
- name: re_replace # replace special characters with " " (space)
|
||||
args: ["[^a-zA-Z0-9\\s]|\\.", " "]
|
||||
- name: re_replace # replace multiple spaces
|
||||
args: ["[ ]{2,}", " "]
|
||||
# normalize to SXXEYY format
|
||||
- name: re_replace
|
||||
args: ["(\\d{2})x(\\d{2})", "S$1E$2"]
|
||||
- name: re_replace
|
||||
args: ["(\\d{1})x(\\d{2})", "S0$1E$2"]
|
||||
- name: re_replace #Stagione X --> S0X
|
||||
args: ["Stagione (\\d{0,1}\\s)", "S0$1"]
|
||||
- name: re_replace #Stagione XX --> SXX
|
||||
args: ["Stagione (\\d{2}\\s)", "S$1"]
|
||||
- name: re_replace #/ Episodio [YY-YY --> EYY-YY
|
||||
args: ["(\\s\\/\\sEpisodio|\\s\\/\\sEpisodi|\\sEpisodio|\\s\\|\\sEpisodio|\\sEpisodi)\\s\\[", "E"]
|
||||
- name: re_replace #/ Completa [episodi YY-YY --> EYY-YY
|
||||
args: ["(\\s\\/\\sCompleta\\s\\[episodi\\s)", "E"]
|
||||
- name: re_replace #remove di YY] | remove /YY]
|
||||
args: ["(\\sdi\\s\\d{1,2}|\\/\\d{1,2})\\]", " "]
|
||||
- name: re_replace #remove various
|
||||
args: ["(Serie completa|Completa|\\[in pausa\\])", ""]
|
||||
# fine prova
|
||||
- name: re_replace #try to find multi episode
|
||||
args: ["(S\\d{2}E\\d{2})\\s(\\d{2})", "$1-$2"]
|
||||
- name: re_replace # S01 E01 to S01E01
|
||||
args: ["\\b[sS](\\d+)\\s[eE](\\d+)\\b", "S$1E$2"]
|
||||
- name: re_replace # 01x01 to S01E01
|
||||
args: ["(\\d{2})x(\\d+)", "S$1E$2"]
|
||||
- name: re_replace # 1x01 to S01E01
|
||||
args: ["\\b(\\d{1})x(\\d+)", "S0$1E$2"]
|
||||
- name: re_replace # Stagione X --> S0X
|
||||
args: ["\\b[sS]tagion[eiEI]\\s?(\\d{1})\\b|\\b[sS]eason\\s?(\\d{1})\\b", "S0$1"]
|
||||
- name: re_replace # Stagione XX --> SXX
|
||||
args: ["\\b[sS]tagion[eiEI]\\s?(\\d{2,})\\b|\\b[sS]easons?\\s?(\\d{2,})\\b", "S$1"]
|
||||
- name: re_replace # Episodio 4 to E4
|
||||
args: ["\\b([\\/\\|]?[eE]pisodio\\s?(\\d+)|[Pp]untata\\s?(\\d+))", "E$2$3"]
|
||||
- name: re_replace # Episodi 4 5 to E04-05
|
||||
args: ["\\b(?:[Pp]untat[eE]\\s*)(\\d+)\\s?(\\d+)", "E0$1-0$2"]
|
||||
- name: re_replace # rimozioni varie
|
||||
args: ["([Ss]erie completa|[cC]ompleta[tT]?[aA]?|COMPLETA[TA]?|in pausa)", ""]
|
||||
- name: andmatch
|
||||
category:
|
||||
selector: td:nth-child(1) a
|
||||
attribute: href
|
||||
|
||||
@@ -84,11 +84,12 @@
|
||||
selector: table#torrents_table_classic > tbody > tr:not(:first-child), div#content > div.torrent-box[id^="torrent_"]
|
||||
filters:
|
||||
- name: andmatch
|
||||
# the tracker has two different styles (modern/classic) it should work with both
|
||||
fields:
|
||||
title:
|
||||
selector: a[href*="?p=torrents&pid=10&action=details"]
|
||||
category:
|
||||
selector: div.category_image > a
|
||||
selector: div.category_image > a, div.categoryImage > a
|
||||
attribute: href
|
||||
filters:
|
||||
- name: querystring
|
||||
@@ -117,6 +118,9 @@
|
||||
downloadvolumefactor:
|
||||
case:
|
||||
"img[title=\"ΧΡΥΣΟ!\"]": "0"
|
||||
"img[title=\"100% FREE!\"]": "0"
|
||||
"img[title=\"Πολλαπλασιαστής Κατεβάσματος: 0.5\"]": "0.5"
|
||||
|
||||
"*": "1"
|
||||
uploadvolumefactor:
|
||||
case:
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
---
|
||||
# Update by LA5T based on the orignial 'karagarga.yml'
|
||||
# 29.07.2018 23:15 UTC+2
|
||||
#
|
||||
site: karagarga
|
||||
name: Karagarga
|
||||
description: "Rare and obscure movie tracker"
|
||||
description: "Tracker for non-hollywood, rare and obscure movies, music and literature."
|
||||
language: en-us
|
||||
type: private
|
||||
encoding: UTF-8
|
||||
@@ -11,6 +14,66 @@
|
||||
caps:
|
||||
categorymappings:
|
||||
- {id: 1, cat: Movies, desc: "Movies"}
|
||||
- {id: 2, cat: Audio, desc: "Music"}
|
||||
- {id: 3, cat: Books, desc: "Literature"}
|
||||
- {id: 4, cat: Movies, desc: "Action"}
|
||||
- {id: 55, cat: Movies, desc: "Adventure"}
|
||||
- {id: 5, cat: Movies, desc: "Animation"}
|
||||
- {id: 6, cat: Movies, desc: "Arthouse"}
|
||||
- {id: 7, cat: Movies, desc: "Asian"}
|
||||
- {id: 43, cat: Movies, desc: "Camp"}
|
||||
- {id: 8, cat: Movies, desc: "Classics"}
|
||||
- {id: 9, cat: Movies, desc: "Comedy"}
|
||||
- {id: 10, cat: Movies, desc: "Crime"}
|
||||
- {id: 11, cat: Movies, desc: "Cult"}
|
||||
- {id: 20, cat: Movies, desc: "Documentary"}
|
||||
- {id: 12, cat: Movies, desc: "Drama"}
|
||||
- {id: 44, cat: Movies, desc: "Epic"}
|
||||
- {id: 13, cat: Movies, desc: "Erotica"}
|
||||
- {id: 51, cat: Movies, desc: "Experimental"}
|
||||
- {id: 47, cat: Movies, desc: "Exploitation"}
|
||||
- {id: 14, cat: Movies, desc: "Fantasy"}
|
||||
- {id: 15, cat: Movies, desc: "Film Noir"}
|
||||
- {id: 53, cat: Movies, desc: "Giallo"}
|
||||
- {id: 17, cat: Movies, desc: "Horror"}
|
||||
- {id: 18, cat: Movies, desc: "Martial Arts"}
|
||||
- {id: 19, cat: Movies, desc: "Musical"}
|
||||
- {id: 54, cat: Movies, desc: "Mystery"}
|
||||
- {id: 60, cat: Movies, desc: "Performance"}
|
||||
- {id: 48, cat: Movies, desc: "Philosophy"}
|
||||
- {id: 49, cat: Movies, desc: "Politics"}
|
||||
- {id: 50, cat: Movies, desc: "Romance"}
|
||||
- {id: 21, cat: Movies, desc: "Sci-Fi"}
|
||||
- {id: 22, cat: Movies, desc: "Short"}
|
||||
- {id: 23, cat: Movies, desc: "Silent"}
|
||||
- {id: 24, cat: Movies, desc: "Thriller"}
|
||||
- {id: 25, cat: Movies, desc: "TV"}
|
||||
- {id: 56, cat: Movies, desc: "Video Art"}
|
||||
- {id: 26, cat: Movies, desc: "War"}
|
||||
- {id: 27, cat: Movies, desc: "Western"}
|
||||
- {id: 800, cat: Audio, desc: "Blues"}
|
||||
- {id: 31, cat: Audio, desc: "Classical"}
|
||||
- {id: 600, cat: Audio, desc: "Country"}
|
||||
- {id: 34, cat: Audio, desc: "Electronica"}
|
||||
- {id: 63, cat: Audio, desc: "Exotica"}
|
||||
- {id: 1000, cat: Audio, desc: "Experimental"}
|
||||
- {id: 250, cat: Audio, desc: "Folk"}
|
||||
- {id: 500, cat: Audio, desc: "Funk"}
|
||||
- {id: 700, cat: Audio, desc: "Indie"}
|
||||
- {id: 32, cat: Audio, desc: "Jazz"}
|
||||
- {id: 1200, cat: Audio, desc: "Latin"}
|
||||
- {id: 35, cat: Audio, desc: "Live"}
|
||||
- {id: 900, cat: Audio, desc: "Metal"}
|
||||
- {id: 62, cat: Audio, desc: "Punk & Hardcore"}
|
||||
- {id: 52, cat: Audio, desc: "Rap & Hiphop"}
|
||||
- {id: 5000, cat: Audio, desc: "Reggae"}
|
||||
- {id: 36, cat: Audio, desc: "Rock"}
|
||||
- {id: 400, cat: Audio, desc: "Soul"}
|
||||
- {id: 33, cat: Audio, desc: "Soundtrack"}
|
||||
- {id: 30, cat: Audio, desc: "World"}
|
||||
- {id: 40, cat: Audio/Audiobook, desc: "Audiobooks"}
|
||||
- {id: 41, cat: Books, desc: "Books"}
|
||||
- {id: 42, cat: Books/Comics, desc: "Comics"}
|
||||
|
||||
modes:
|
||||
search: [q]
|
||||
@@ -33,15 +96,22 @@
|
||||
search:
|
||||
paths:
|
||||
- path: browse.php
|
||||
keywordsfilters:
|
||||
- name: re_replace
|
||||
args: ["(?<=^| )(?!-|\\+)[^ ]+(?= |$)", "+$&"]
|
||||
inputs:
|
||||
$raw: "{{range .Categories}}filter_cat[{{.}}]=1&{{end}}"
|
||||
search: "\"{{ .Query.Keywords }}\""
|
||||
search_type: "title"
|
||||
$raw: "{{range .Categories}}genre={{.}}&{{end}}"
|
||||
search: "{{ .Keywords }}"
|
||||
search_type: title
|
||||
rows:
|
||||
selector: table#browse > tbody > tr:has(a[href^="browse.php?genre="])
|
||||
fields:
|
||||
category:
|
||||
text: 1
|
||||
selector: a[href^="browse.php?genre="]
|
||||
attribute: href
|
||||
filters:
|
||||
- name: querystring
|
||||
args: genre
|
||||
title:
|
||||
selector: td:nth-child(2) span
|
||||
download:
|
||||
@@ -69,15 +139,16 @@
|
||||
date:
|
||||
selector: td:nth-child(9)
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["'", ""]
|
||||
- name: re_replace
|
||||
args: ["[^a-zA-Z0-9]+", " "]
|
||||
args: ["([a-zA-Z]+)\\s+(\\d{1,2})\\s+'(\\d{2})", "$2 $1 $3"]
|
||||
- name: dateparse
|
||||
args: "Jan 02 06"
|
||||
args: "02 Jan 06"
|
||||
downloadvolumefactor:
|
||||
case:
|
||||
"*": "1"
|
||||
"*": 1
|
||||
uploadvolumefactor:
|
||||
case:
|
||||
"*": "1"
|
||||
":has(img[title^=HD]):has(img[title^=CURRENT])": 1.8
|
||||
"img[title^=CURRENT]": 1.6
|
||||
"img[title^=HD]": 1.3
|
||||
"*": 1.1
|
||||
@@ -6,6 +6,8 @@
|
||||
type: public
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- https://www.limetorrents.io/
|
||||
legacylinks:
|
||||
- https://www.limetorrents.cc/
|
||||
|
||||
caps:
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
---
|
||||
site: nexttorrent
|
||||
name: NextTorrent
|
||||
description: "NextTorrent is a FRENCH Public site for TV / MOVIES / GENERAL"
|
||||
language: fr-fr
|
||||
type: public
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- http://www.nextorrent.tv/
|
||||
legacylinks:
|
||||
- https://www.nextorrent.site/
|
||||
- http://www.nextorrent.site/
|
||||
- http://www.nextorrent.bz/
|
||||
- http://www.nextorrent.pro/
|
||||
- https://www.nextorrent.cc/
|
||||
- https://www.nextorrent.org/
|
||||
- https://www.nextorrent.tv/
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
- {id: Films, cat: Movies, desc: "Movies"}
|
||||
- {id: Séries, cat: TV, desc: "TV"}
|
||||
- {id: Jeux-PC, cat: PC/Games, desc: "Games PC"}
|
||||
- {id: Jeux-Consoles, cat: Console, desc: "Games Console"}
|
||||
- {id: Musique, cat: Audio, desc: "Music"}
|
||||
- {id: Ebook, cat: Books, desc: "EBooks"}
|
||||
- {id: Logiciels, cat: PC, desc: "Software"}
|
||||
|
||||
modes:
|
||||
search: [q]
|
||||
tv-search: [q, season, ep]
|
||||
movie-search: [q]
|
||||
|
||||
settings: []
|
||||
|
||||
download:
|
||||
selector: a[href^="/get_torrent/"]
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: "recherche/{{ .Query.Keywords }}"
|
||||
rows:
|
||||
selector: div.listing-torrent > table tbody tr:has(a)
|
||||
fields:
|
||||
site_date:
|
||||
selector: td:nth-child(1) a
|
||||
filters:
|
||||
# date is at the end of the title, so we get it and name it site_date
|
||||
- name: regexp
|
||||
args: "(\\w+)$"
|
||||
title:
|
||||
selector: td:nth-child(1) a
|
||||
filters:
|
||||
# now we put the date at the right place according scene naming rules using .Result.site_date
|
||||
- name: replace
|
||||
args: ["FRENCH", "{{ .Result.site_date }} FRENCH"]
|
||||
- name: replace
|
||||
args: ["TRUEFRENCH", "{{ .Result.site_date }} TRUEFRENCH"]
|
||||
- name: replace
|
||||
args: ["VOSTFR", "{{ .Result.site_date }} VOSTFR"]
|
||||
# and we delete it at the end
|
||||
- name: re_replace
|
||||
args: ["(\\w+)$", ""]
|
||||
details:
|
||||
selector: td:nth-child(1) a
|
||||
attribute: href
|
||||
download:
|
||||
selector: td:nth-child(1) a
|
||||
attribute: href
|
||||
category:
|
||||
selector: td:nth-child(1) i
|
||||
attribute: class
|
||||
size:
|
||||
selector: td:nth-child(2)
|
||||
date:
|
||||
text: now
|
||||
seeders:
|
||||
text: 0
|
||||
seeders:
|
||||
optional: true
|
||||
selector: td:nth-child(3)
|
||||
leechers:
|
||||
text: 0
|
||||
leechers:
|
||||
optional: true
|
||||
selector: td:nth-child(4)
|
||||
downloadvolumefactor:
|
||||
text: "0"
|
||||
uploadvolumefactor:
|
||||
text: "1"
|
||||
@@ -6,6 +6,8 @@
|
||||
type: private
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- https://v2.rgut.uk/
|
||||
legacylinks:
|
||||
- https://rgu.rgt.life/
|
||||
|
||||
caps:
|
||||
@@ -65,8 +67,7 @@
|
||||
inputs:
|
||||
username: "{{ .Config.username }}"
|
||||
password: "{{ .Config.password }}"
|
||||
submitme: "X"
|
||||
submitme: "X" # two submitme needed?!? shouldn't make a difference
|
||||
use_ssl: "1"
|
||||
error:
|
||||
- selector: h2:contains("Login failed!")
|
||||
message:
|
||||
|
||||
@@ -79,15 +79,12 @@
|
||||
paths:
|
||||
- path: /index.php
|
||||
keywordsfilters:
|
||||
- name: re_replace
|
||||
args: ["S[0-9]{2}([^E]|$)", ""] # remove season tag without episode (search doesn't support it)
|
||||
- name: diacritics
|
||||
args: replace
|
||||
# most ITA TV torrents are in XXxYY format, so we search without S/E prefixes and filter later
|
||||
- name: re_replace
|
||||
args: ["S0?(\\d{1,2})", " $1 "]
|
||||
- name: re_replace
|
||||
args: ["E(\\d{2,3})", " $1 "]
|
||||
- name: re_replace # S01 to 1
|
||||
args: ["\\b[sS]0*(\\d+)\\b", "$1"]
|
||||
- name: re_replace # S01E01 to 1 1
|
||||
args: ["\\b[sS]0*(\\d+)[eE]0*(\\d+)\\b", "$1 $2"]
|
||||
inputs:
|
||||
search: "{{ .Keywords }}"
|
||||
category: "{{range .Categories}}{{.}};{{end}}"
|
||||
@@ -101,56 +98,56 @@
|
||||
attribute: href
|
||||
title: # shortened title?
|
||||
selector: a[href^="index.php?page=torrent-details"]
|
||||
# normalize to SXXEYY format
|
||||
filters:
|
||||
- name: re_replace # replace special characters with " " (space)
|
||||
args: ["[^a-zA-Z0-9]|\\.", " "]
|
||||
args: ["[^a-zA-Z0-9\\s]|\\.", " "]
|
||||
- name: re_replace # replace multiple spaces
|
||||
args: ["[ ]{2,}", " "]
|
||||
# normalize to SXXEYY format
|
||||
- name: re_replace
|
||||
args: ["(\\d{2})x(\\d{2})", "S$1E$2"]
|
||||
- name: re_replace
|
||||
args: ["(\\d{1})x(\\d{2})", "S0$1E$2"]
|
||||
- name: re_replace #Stagione X --> S0X
|
||||
args: ["Stagione (\\d{0,1}\\s)", "S0$1"]
|
||||
- name: re_replace #Stagione XX --> SXX
|
||||
args: ["Stagione (\\d{2}\\s)", "S$1"]
|
||||
- name: re_replace #/ Episodio [YY-YY --> EYY-YY
|
||||
args: ["(\\s\\/\\sEpisodio|\\s\\/\\sEpisodi|\\sEpisodio|\\s\\|\\sEpisodio|\\sEpisodi)\\s\\[", "E"]
|
||||
- name: re_replace #/ Completa [episodi YY-YY --> EYY-YY
|
||||
args: ["(\\s\\/\\sCompleta\\s\\[episodi\\s)", "E"]
|
||||
- name: re_replace #remove di YY] | remove /YY]
|
||||
args: ["(\\sdi\\s\\d{1,2}|\\/\\d{1,2})\\]", " "]
|
||||
- name: re_replace #remove various
|
||||
args: ["(Serie completa|Completa|\\[in pausa\\])", ""]
|
||||
# fine prova
|
||||
- name: re_replace # S01 E01 to S01E01
|
||||
args: ["\\b[sS](\\d+)\\s[eE](\\d+)\\b", "S$1E$2"]
|
||||
- name: re_replace # 01x01 to S01E01
|
||||
args: ["(\\d{2})x(\\d+)", "S$1E$2"]
|
||||
- name: re_replace # 1x01 to S01E01
|
||||
args: ["\\b(\\d{1})x(\\d+)", "S0$1E$2"]
|
||||
- name: re_replace # Stagione X --> S0X
|
||||
args: ["\\b[sS]tagion[eiEI]\\s?(\\d{1})\\b|\\b[sS]eason\\s?(\\d{1})\\b", "S0$1"]
|
||||
- name: re_replace # Stagione XX --> SXX
|
||||
args: ["\\b[sS]tagion[eiEI]\\s?(\\d{2,})\\b|\\b[sS]easons?\\s?(\\d{2,})\\b", "S$1"]
|
||||
- name: re_replace # Episodio 4 to E4
|
||||
args: ["\\b([\\/\\|]?[eE]pisodio\\s?(\\d+)|[Pp]untata\\s?(\\d+))", "E$2$3"]
|
||||
- name: re_replace # Episodi 4 5 to E04-05
|
||||
args: ["\\b(?:[Pp]untat[eE]\\s*)(\\d+)\\s?(\\d+)", "E0$1-0$2"]
|
||||
- name: re_replace # rimozioni varie
|
||||
args: ["([Ss]erie completa|[cC]ompleta[tT]?[aA]?|COMPLETA[TA]?|in pausa)", ""]
|
||||
- name: andmatch
|
||||
title: # long titles?
|
||||
optional: true
|
||||
selector: a[title][href^="index.php?page=torrent-details"]
|
||||
attribute: title
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["Vedi Dettagli: ", ""]
|
||||
# inizio prova
|
||||
- name: re_replace # replace special characters with " " (space)
|
||||
args: ["[^a-zA-Z0-9]|\\.", " "]
|
||||
args: ["[^a-zA-Z0-9\\s]|\\.", " "]
|
||||
- name: re_replace # replace multiple spaces
|
||||
args: ["[ ]{2,}", " "]
|
||||
# normalize to SXXEYY format
|
||||
- name: re_replace
|
||||
args: ["(\\d{2})x(\\d{2})", "S$1E$2"]
|
||||
- name: re_replace
|
||||
args: ["(\\d{1})x(\\d{2})", "S0$1E$2"]
|
||||
- name: re_replace #Stagione X --> S0X
|
||||
args: ["Stagione (\\d{0,1}\\s)", "S0$1"]
|
||||
- name: re_replace #Stagione XX --> SXX
|
||||
args: ["Stagione (\\d{2}\\s)", "S$1"]
|
||||
- name: re_replace #/ Episodio [YY-YY --> EYY-YY
|
||||
args: ["(\\s\\/\\sEpisodio|\\s\\/\\sEpisodi|\\sEpisodio|\\s\\|\\sEpisodio|\\sEpisodi)\\s\\[", "E"]
|
||||
- name: re_replace #/ Completa [episodi YY-YY --> EYY-YY
|
||||
args: ["(\\s\\/\\sCompleta\\s\\[episodi\\s)", "E"]
|
||||
- name: re_replace #remove di YY] | remove /YY]
|
||||
args: ["(\\sdi\\s\\d{1,2}|\\/\\d{1,2})\\]", " "]
|
||||
- name: re_replace #remove various
|
||||
args: ["(Serie completa|Completa|\\[in pausa\\])", ""]
|
||||
# fine prova
|
||||
- name: re_replace # S01 E01 to S01E01
|
||||
args: ["\\b[sS](\\d+)\\s[eE](\\d+)\\b", "S$1E$2"]
|
||||
- name: re_replace # 01x01 to S01E01
|
||||
args: ["(\\d{2})x(\\d+)", "S$1E$2"]
|
||||
- name: re_replace # 1x01 to S01E01
|
||||
args: ["\\b(\\d{1})x(\\d+)", "S0$1E$2"]
|
||||
- name: re_replace # Stagione X --> S0X
|
||||
args: ["\\b[sS]tagion[eiEI]\\s?(\\d{1})\\b|\\b[sS]eason\\s?(\\d{1})\\b", "S0$1"]
|
||||
- name: re_replace # Stagione XX --> SXX
|
||||
args: ["\\b[sS]tagion[eiEI]\\s?(\\d{2,})\\b|\\b[sS]easons?\\s?(\\d{2,})\\b", "S$1"]
|
||||
- name: re_replace # Episodio 4 to E4
|
||||
args: ["\\b([\\/\\|]?[eE]pisodio\\s?(\\d+)|[Pp]untata\\s?(\\d+))", "E$2$3"]
|
||||
- name: re_replace # Episodi 4 5 to E04-05
|
||||
args: ["\\b(?:[Pp]untat[eE]\\s*)(\\d+)\\s?(\\d+)", "E0$1-0$2"]
|
||||
- name: re_replace # rimozioni varie
|
||||
args: ["([Ss]erie completa|[cC]ompleta[tT]?[aA]?|COMPLETA[TA]?|in pausa)", ""]
|
||||
- name: andmatch
|
||||
category:
|
||||
selector: a[href^="index.php?page=torrents&category="]
|
||||
attribute: href
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
type: public
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- http://www.torrent9.blue/
|
||||
- https://ww2.torrent9.blue/
|
||||
legacylinks:
|
||||
- http://www.torrent9.ec/
|
||||
- http://www.torrent9.red/
|
||||
@@ -14,6 +14,8 @@
|
||||
- http://www.torrents9.pe/
|
||||
- http://www.torrent9.cc/
|
||||
- http://www.torrent9.pe/
|
||||
- http://www.torrent9.blue/
|
||||
- https://www.torrent9.blue/
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
|
||||
165
src/Jackett.Common/Definitions/x-ite.me.yml
Normal file
165
src/Jackett.Common/Definitions/x-ite.me.yml
Normal file
@@ -0,0 +1,165 @@
|
||||
---
|
||||
# By LA5T for https://x-ite.me (25.07.2018 17:34 UTC+2)
|
||||
#
|
||||
# TODO:
|
||||
# x-ite.me doesn't support altering the number of results, therefore only the 20 first results are shown (this is hardcoded), Jackett may support pagination in the future tho
|
||||
#
|
||||
site: xiteme
|
||||
name: x-ite.me
|
||||
description: "Tracker for LGBTQ movies, TV, books, magazines, anime, PC and XXX."
|
||||
language: en-us
|
||||
type: private
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- https://x-ite.me
|
||||
|
||||
settings:
|
||||
- name: username
|
||||
type: text
|
||||
label: Username
|
||||
- name: password
|
||||
type: password
|
||||
label: Password
|
||||
- name: incldead
|
||||
type: select
|
||||
label: Status
|
||||
default: 1
|
||||
options:
|
||||
0: Active
|
||||
1: "Active and Inactive"
|
||||
2: Inactive
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
- {id: 6700, cat: TV/Anime, desc: "Animations - Adult"}
|
||||
- {id: 6330, cat: TV/Anime, desc: "Animations - Futanari"}
|
||||
- {id: 6320, cat: TV/Anime, desc: "Animations - Yaoi"}
|
||||
- {id: 9700, cat: Books/Comics, desc: "Comics & Manga - Adult"}
|
||||
- {id: 5000, cat: XXX, desc: "Fetish - All"}
|
||||
- {id: 7700, cat: XXX/Imageset, desc: "Images - Fetish"}
|
||||
- {id: 1050, cat: Movies, desc: "Movies - Biography"}
|
||||
- {id: 1150, cat: Movies, desc: "Movies - Crime"}
|
||||
- {id: 1250, cat: Movies, desc: "Movies - Experimental"}
|
||||
- {id: 1350, cat: Movies, desc: "Movies - History"}
|
||||
- {id: 1450, cat: Movies, desc: "Movies - Mystery"}
|
||||
- {id: 1530, cat: Movies, desc: "Movies - Sport"}
|
||||
- {id: 1630, cat: Movies, desc: "Movies - Western"}
|
||||
- {id: 6100, cat: TV/Anime, desc: "Animations - Anime"}
|
||||
- {id: 6300, cat: TV/Anime, desc: "Animations - Hentai"}
|
||||
- {id: 6310, cat: TV/Anime, desc: "Animations - Yuri"}
|
||||
- {id: 9600, cat: Books/Comics, desc: "Comics & Manga - Cartoon"}
|
||||
- {id: 13000, cat: PC/Games, desc: "Games - All"}
|
||||
- {id: 7900, cat: XXX/Imageset, desc: "Images - Other"}
|
||||
- {id: 1070, cat: Movies, desc: "Movies - Bollywood"}
|
||||
- {id: 1170, cat: Movies, desc: "Movies - Documentary"}
|
||||
- {id: 1270, cat: Movies, desc: "Movies - Family"}
|
||||
- {id: 1370, cat: Movies, desc: "Movies - Horror"}
|
||||
- {id: 1470, cat: Movies, desc: "Movies - News"}
|
||||
- {id: 1550, cat: Movies, desc: "Movies - Suspense"}
|
||||
- {id: 3000, cat: XXX, desc: "Softcore - All"}
|
||||
- {id: 6340, cat: TV/Anime, desc: "Animations - Bara"}
|
||||
- {id: 6900, cat: TV/Anime, desc: "Animations - Other"}
|
||||
- {id: 14000, cat: PC, desc: "Applications - All"}
|
||||
- {id: 9200, cat: Books/Comics, desc: "Comics & Manga - Hentai"}
|
||||
- {id: 4000, cat: XXX, desc: "Hardcore - All"}
|
||||
- {id: 8000, cat: Books/Magazines, desc: "Magazines - All"}
|
||||
- {id: 1090, cat: Movies, desc: "Movies - Comedy"}
|
||||
- {id: 1190, cat: Movies, desc: "Movies - Drama"}
|
||||
- {id: 1290, cat: Movies, desc: "Movies - Fantasy"}
|
||||
- {id: 1390, cat: Movies, desc: "Movies - Indie"}
|
||||
- {id: 1900, cat: Movies, desc: "Movies - Other"}
|
||||
- {id: 1570, cat: Movies, desc: "Movies - Theater"}
|
||||
- {id: 12000, cat: Other, desc: "Subtitles - All"}
|
||||
- {id: 6110, cat: TV/Anime, desc: "Animations - Ecchi"}
|
||||
- {id: 6120, cat: TV/Anime, desc: "Animations - Shoujo Ai"}
|
||||
- {id: 11000, cat: Audio/Audiobook, desc: "Audio Books - All"}
|
||||
- {id: 9100, cat: Books/Comics, desc: "Comics & Manga - Manga"}
|
||||
- {id: 7500, cat: XXX/Imageset, desc: "Images - Adult"}
|
||||
- {id: 1010, cat: Movies, desc: "Movies - Action"}
|
||||
- {id: 1110, cat: Movies, desc: "Movies - Coming of Age"}
|
||||
- {id: 1210, cat: Movies, desc: "Movies - Eastern"}
|
||||
- {id: 1310, cat: Movies, desc: "Movies - Film Noir"}
|
||||
- {id: 1410, cat: Movies, desc: "Movies - Music"}
|
||||
- {id: 1490, cat: Movies, desc: "Movies - Romance"}
|
||||
- {id: 1590, cat: Movies, desc: "Movies - Thriller"}
|
||||
- {id: 6350, cat: TV/Anime, desc: "Animations - Furry"}
|
||||
- {id: 6330, cat: TV/Anime, desc: "Animations - Shounen Ai"}
|
||||
- {id: 10000, cat: Books, desc: "Books - All"}
|
||||
- {id: 9900, cat: Books/Comics, desc: "Comics & Manga - Other"}
|
||||
- {id: 7300, cat: XXX/Imageset, desc: "Images - Erotic"}
|
||||
- {id: 1030, cat: Movies, desc: "Movies - Adventure"}
|
||||
- {id: 1130, cat: Movies, desc: "Movies - Coming Out"}
|
||||
- {id: 1230, cat: Movies, desc: "Movies - Entertainment"}
|
||||
- {id: 1330, cat: Movies, desc: "Movies - Historical"}
|
||||
- {id: 1430, cat: Movies, desc: "Movies - Musical"}
|
||||
- {id: 1510, cat: Movies, desc: "Movies - Sci-Fi"}
|
||||
- {id: 1610, cat: Movies, desc: "Movies - War"}
|
||||
modes:
|
||||
search: [q]
|
||||
|
||||
login:
|
||||
method: post
|
||||
path: account-login.php
|
||||
inputs:
|
||||
username: "{{ .Config.username }}"
|
||||
password: "{{ .Config.password }}"
|
||||
error:
|
||||
- selector: .myF-content > center:nth-child(1) > b:contains("The specified username or password was incorrect.")
|
||||
test:
|
||||
path: account.php
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: torrents-search.php
|
||||
method: get
|
||||
keywordsfilters:
|
||||
- name: re_replace
|
||||
args: ["(?<=^| )(?!-|\\+)[^ ]+(?= |$)", "+$&"]
|
||||
inputs:
|
||||
$raw: "{{range .Categories}}&c{{.}}=1&{{end}}"
|
||||
search: "{{ .Keywords }}"
|
||||
incldead: "{{ .Config.incldead }}"
|
||||
rows:
|
||||
selector: tr.t-row
|
||||
fields:
|
||||
title:
|
||||
selector: td:nth-child(2) > a:nth-child(1) > b:nth-child(1)
|
||||
category:
|
||||
selector: a[href^="torrents.php?cat="]
|
||||
attribute: href
|
||||
filters:
|
||||
- name: querystring
|
||||
args: cat
|
||||
details:
|
||||
selector: a[href^="torrents-details.php?id="]
|
||||
attribute: href
|
||||
comments:
|
||||
selector: a[href^="comments.php?type=torrent&id="]
|
||||
attribute: href
|
||||
download:
|
||||
selector: a[href^="download.php?id="]
|
||||
attribute: href
|
||||
size:
|
||||
selector: td:nth-child(7)
|
||||
files:
|
||||
selector: td:nth-child(6)
|
||||
seeders:
|
||||
selector: td:nth-child(8)
|
||||
leechers:
|
||||
selector: td:nth-child(9)
|
||||
date:
|
||||
selector: td:nth-child(3)
|
||||
filters:
|
||||
- name: re_replace
|
||||
args: ["(\\d{2})-(\\d{2})-(\\d{4}) ((?:\\d{2}:?){3})", "$3-$2-$1 $4"]
|
||||
- name: append
|
||||
args: " +01:00"
|
||||
- name: dateparse
|
||||
args: "2006-01-02 15:04:05 -07:00"
|
||||
downloadvolumefactor:
|
||||
case:
|
||||
"td:nth-child(2) > a:nth-child(1) > span:nth-child(2)": 0
|
||||
"*": 1
|
||||
uploadvolumefactor:
|
||||
case:
|
||||
"*": 1
|
||||
@@ -6,11 +6,13 @@
|
||||
type: semi-private
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- https://ww1.yggtorrent.is/
|
||||
- https://ww3.yggtorrent.is/
|
||||
legacylinks:
|
||||
- https://yggtorrent.is/
|
||||
- https://yggtorrent.com/
|
||||
- https://ww1.yggtorrent.com/
|
||||
- https://ww1.yggtorrent.is/
|
||||
- https://ww2.yggtorrent.is/
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
|
||||
@@ -1,102 +1,80 @@
|
||||
---
|
||||
site: yourexotic
|
||||
name: Your Exotic Torrents
|
||||
name: ExoticaZ
|
||||
description: "a porn tracker"
|
||||
language: en-us
|
||||
type: private
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- https://exoticaz.to/
|
||||
legacylinks:
|
||||
- https://torrents.yourexotic.com/
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
- {id: 11, cat: XXX, desc: "DVDRip"}
|
||||
- {id: 2, cat: XXX, desc: "DVDRip Censored"}
|
||||
- {id: 1, cat: XXX, desc: "Video Clip"}
|
||||
- {id: 20, cat: XXX, desc: "Censored Clips"}
|
||||
- {id: 14, cat: XXX, desc: "Hentai"}
|
||||
- {id: 19, cat: XXX, desc: "Full DVD"}
|
||||
- {id: 16, cat: XXX, desc: "HD 720p"}
|
||||
- {id: 17, cat: XXX, desc: "HD 1080p"}
|
||||
- {id: 18, cat: XXX, desc: "HD Censored"}
|
||||
- {id: 15, cat: XXX, desc: "SVCD/VCD"}
|
||||
- {id: 13, cat: XXX, desc: "Softcore"}
|
||||
- {id: 3, cat: XXX, desc: "Pictures"}
|
||||
- {id: 21, cat: XXX, desc: "Mixed Videos"}
|
||||
- {id: 1, cat: XXX, desc: "DVDRip"}
|
||||
modes:
|
||||
search: [q]
|
||||
tv-search: [q]
|
||||
movie-search: [q]
|
||||
|
||||
login:
|
||||
path: /index.php?page=login
|
||||
method: post
|
||||
path: /login
|
||||
method: form
|
||||
inputs:
|
||||
uid: "{{ .Config.username }}"
|
||||
pwd: "{{ .Config.password }}"
|
||||
username: "{{ .Config.username }}"
|
||||
password: "{{ .Config.password }}"
|
||||
remember: "on"
|
||||
error:
|
||||
- selector: .lista>span
|
||||
- selector: div.invalid-feedback
|
||||
test:
|
||||
path: index.php
|
||||
selector: form[name="jump1"]
|
||||
selector: div.ratio-bar
|
||||
|
||||
search:
|
||||
path: index.php
|
||||
path: /torrents
|
||||
inputs:
|
||||
$raw: "&category={{range .Categories}}{{.}};{{end}}"
|
||||
page: "torrents"
|
||||
active: "0"
|
||||
search: "{{ .Query.Keywords }}"
|
||||
in: 1
|
||||
search: "{{ .Keywords }}"
|
||||
category: 0
|
||||
rows:
|
||||
selector: table.lista > tbody > tr:has(a[href^="index.php?page=torrent-details&id="])
|
||||
selector: div.table-responsive > table > tbody > tr
|
||||
fields:
|
||||
category:
|
||||
selector: td:nth-child(1) a
|
||||
attribute: href
|
||||
filters:
|
||||
- name: querystring
|
||||
args: category
|
||||
text: 1
|
||||
title:
|
||||
selector: a[href^="index.php?page=torrent-details&id="]
|
||||
selector: a.torrent-link
|
||||
attribute: title
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["View details: ", ""]
|
||||
details:
|
||||
selector: a[href^="index.php?page=torrent-details&id="]
|
||||
selector: a.torrent-link
|
||||
attribute: href
|
||||
banner:
|
||||
selector: span.screen-image
|
||||
attribute: data-screens
|
||||
filters:
|
||||
- name: split
|
||||
args: ["|", 0]
|
||||
size:
|
||||
selector: td:nth-child(7)
|
||||
selector: td:nth-child(5)
|
||||
seeders:
|
||||
selector: td:nth-child(9)
|
||||
leechers:
|
||||
selector: td:nth-child(10)
|
||||
grabs:
|
||||
selector: td:nth-child(11)
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["---", "0"]
|
||||
date:
|
||||
selector: td:nth-child(6)
|
||||
leechers:
|
||||
selector: td:nth-child(7)
|
||||
grabs:
|
||||
selector: td:nth-child(8)
|
||||
date:
|
||||
selector: td:nth-child(3)
|
||||
filters:
|
||||
- name: dateparse
|
||||
args: "02/01/2006"
|
||||
- name: append
|
||||
args: " ago"
|
||||
download:
|
||||
selector: a[href^="download.php"]
|
||||
selector: a[href*="/download/"]
|
||||
attribute: href
|
||||
downloadvolumefactor:
|
||||
case:
|
||||
img[src$="freeleech.gif"]: "0"
|
||||
img[src$="silver.gif"]: "0.5"
|
||||
i[title="Free Download"]: "0"
|
||||
i[title="Half Download"]: "0.5"
|
||||
"*": "1"
|
||||
uploadvolumefactor:
|
||||
case:
|
||||
img[src$="2x.gif"]: "2"
|
||||
img[src$="3x.gif"]: "3"
|
||||
img[src$="4x.gif"]: "4"
|
||||
img[src$="5x.gif"]: "5"
|
||||
img[src$="6x.gif"]: "6"
|
||||
img[src$="7x.gif"]: "7"
|
||||
img[src$="8x.gif"]: "8"
|
||||
img[src$="9x.gif"]: "9"
|
||||
i.fa-gem: "2"
|
||||
"*": "1"
|
||||
|
||||
@@ -318,7 +318,7 @@ namespace Jackett.Common.Indexers.Abstract
|
||||
{
|
||||
var content = await base.Download(link);
|
||||
|
||||
// Check if we're out of FL tokens
|
||||
// Check if we're out of FL tokens/torrent is to large
|
||||
// most gazelle trackers will simply return the torrent anyway but e.g. redacted will return an error
|
||||
var requestLink = link.ToString();
|
||||
if (content.Length >= 1
|
||||
@@ -326,7 +326,8 @@ namespace Jackett.Common.Indexers.Abstract
|
||||
&& requestLink.Contains("usetoken=1"))
|
||||
{
|
||||
var html = Encoding.GetString(content);
|
||||
if (html.Contains("You do not have any freeleech tokens left."))
|
||||
if (html.Contains("You do not have any freeleech tokens left.")
|
||||
|| html.Contains("This torrent is too large."))
|
||||
{
|
||||
// download again with usetoken=0
|
||||
var requestLinkNew = requestLink.Replace("usetoken=1", "usetoken=0");
|
||||
|
||||
@@ -752,26 +752,22 @@ namespace Jackett.Common.Indexers
|
||||
|
||||
protected ICollection<int> MapTrackerCatToNewznab(string input)
|
||||
{
|
||||
var cats = new List<int>();
|
||||
if (null != input)
|
||||
{
|
||||
var mapping = categoryMapping.Where(m => m.TrackerCategory != null && m.TrackerCategory.ToLowerInvariant() == input.ToLowerInvariant()).FirstOrDefault();
|
||||
if (mapping != null)
|
||||
{
|
||||
cats.Add(mapping.NewzNabCategory);
|
||||
}
|
||||
if (input == null)
|
||||
return new List<int>();
|
||||
|
||||
// 1:1 category mapping
|
||||
try
|
||||
{
|
||||
var trackerCategoryInt = int.Parse(input);
|
||||
cats.Add(trackerCategoryInt + 100000);
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
// input is not an integer, continue
|
||||
}
|
||||
var cats = categoryMapping.Where(m => m.TrackerCategory != null && m.TrackerCategory.ToLowerInvariant() == input.ToLowerInvariant()).Select(c => c.NewzNabCategory).ToList();
|
||||
|
||||
// 1:1 category mapping
|
||||
try
|
||||
{
|
||||
var trackerCategoryInt = int.Parse(input);
|
||||
cats.Add(trackerCategoryInt + 100000);
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
// input is not an integer, continue
|
||||
}
|
||||
|
||||
return cats;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Jackett.Common.Indexers
|
||||
{
|
||||
class MejorTorrent : BaseWebIndexer
|
||||
{
|
||||
public static Uri WebUri = new Uri("http://www.mejortorrent.com/");
|
||||
public static Uri WebUri = new Uri("http://www.mejortorrent.org/");
|
||||
public static Uri DownloadUri = new Uri(WebUri, "secciones.php?sec=descargas&ap=contar_varios");
|
||||
private static Uri SearchUriBase = new Uri(WebUri, "secciones.php");
|
||||
public static Uri NewTorrentsUri = new Uri(WebUri, "secciones.php?sec=ultimos_torrents");
|
||||
|
||||
917
src/Jackett.Common/Indexers/Nordicbits.cs
Normal file
917
src/Jackett.Common/Indexers/Nordicbits.cs
Normal file
@@ -0,0 +1,917 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using CsQuery;
|
||||
using Jackett.Common.Helpers;
|
||||
using Jackett.Common.Models;
|
||||
using Jackett.Common.Models.IndexerConfig.Bespoke;
|
||||
using Jackett.Common.Services.Interfaces;
|
||||
using Jackett.Common.Utils;
|
||||
using Jackett.Common.Utils.Clients;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NLog;
|
||||
|
||||
namespace Jackett.Common.Indexers
|
||||
{
|
||||
/// <summary>s
|
||||
/// Provider for Nordicbits Private Tracker
|
||||
/// </summary>
|
||||
public class Nordicbits : BaseCachingWebIndexer
|
||||
{
|
||||
private string LoginUrl => SiteLink + "login.php";
|
||||
private string LoginCheckUrl => SiteLink + "takelogin.php";
|
||||
private string SearchUrl => SiteLink + "browse.php";
|
||||
private string TorrentCommentUrl => SiteLink + "details.php?id={id}&comonly=1#page1";
|
||||
private string TorrentDescriptionUrl => SiteLink + "details.php?id={id}";
|
||||
private string TorrentDownloadUrl => SiteLink + "download.php?torrent={id}&torrent_pass={passkey}";
|
||||
private bool Latency => ConfigData.Latency.Value;
|
||||
private bool DevMode => ConfigData.DevMode.Value;
|
||||
private bool CacheMode => ConfigData.HardDriveCache.Value;
|
||||
private static string Directory => Path.Combine(Path.GetTempPath(), "Jackett", MethodBase.GetCurrentMethod().DeclaringType?.Name);
|
||||
|
||||
private readonly Dictionary<string, string> _emulatedBrowserHeaders = new Dictionary<string, string>();
|
||||
private CQ _fDom;
|
||||
private ConfigurationDataNordicbits ConfigData => (ConfigurationDataNordicbits)configData;
|
||||
|
||||
public Nordicbits(IIndexerConfigurationService configService, Utils.Clients.WebClient w, Logger l, IProtectionService ps)
|
||||
: base(
|
||||
name: "Nordicbits",
|
||||
description: "Nordicbits is a Danish Private site for MOVIES / TV / GENERAL",
|
||||
link: "https://nordicb.org/",
|
||||
caps: new TorznabCapabilities(),
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
configData: new ConfigurationDataNordicbits())
|
||||
{
|
||||
Encoding = Encoding.GetEncoding("iso-8859-1");
|
||||
Language = "da-dk";
|
||||
Type = "private";
|
||||
|
||||
TorznabCaps.SupportsImdbSearch = false;
|
||||
|
||||
// Apps
|
||||
AddCategoryMapping("cat=63", TorznabCatType.PCPhoneAndroid, "APPS - Android");
|
||||
AddCategoryMapping("cat=17", TorznabCatType.PC, "APPS - MAC");
|
||||
AddCategoryMapping("cat=12", TorznabCatType.PCMac, "APPS - Windows");
|
||||
AddCategoryMapping("cat=62", TorznabCatType.PCPhoneIOS, "APPS - IOS");
|
||||
AddCategoryMapping("cat=64", TorznabCatType.PC, "APPS - Linux");
|
||||
|
||||
// Books
|
||||
AddCategoryMapping("cat=54", TorznabCatType.AudioAudiobook, "Books - Audiobooks");
|
||||
AddCategoryMapping("cat=9", TorznabCatType.BooksEbook, "Books - E-Books");
|
||||
|
||||
// Games
|
||||
AddCategoryMapping("cat=24", TorznabCatType.PCGames, "Games - PC");
|
||||
AddCategoryMapping("cat=53", TorznabCatType.Console, "Games - Nintendo");
|
||||
AddCategoryMapping("cat=49", TorznabCatType.ConsolePS4, "Games - Playstation");
|
||||
AddCategoryMapping("cat=51", TorznabCatType.ConsoleXbox, "Games - XBOX");
|
||||
|
||||
// Movies
|
||||
AddCategoryMapping("cat=35", TorznabCatType.Movies3D, "Movies - 3D");
|
||||
AddCategoryMapping("cat=42", TorznabCatType.MoviesUHD, "Movies - 4K/2160p");
|
||||
AddCategoryMapping("cat=47", TorznabCatType.MoviesUHD, "Movies - 4k/2160p Boxset");
|
||||
AddCategoryMapping("cat=15", TorznabCatType.MoviesBluRay, "Movies - BluRay");
|
||||
AddCategoryMapping("cat=5", TorznabCatType.MoviesHD, "Movies - Remux");
|
||||
AddCategoryMapping("cat=16", TorznabCatType.MoviesDVD, "Movies - DVD Boxset");
|
||||
AddCategoryMapping("cat=6", TorznabCatType.MoviesDVD, "Movies - DVD");
|
||||
AddCategoryMapping("cat=21", TorznabCatType.MoviesHD, "Movies - HD-1080p");
|
||||
AddCategoryMapping("cat=19", TorznabCatType.MoviesHD, "Movies - HD-1080p Boxset");
|
||||
AddCategoryMapping("cat=22", TorznabCatType.MoviesHD, "Movies - HD-720p");
|
||||
AddCategoryMapping("cat=20", TorznabCatType.MoviesHD, "Movies - HD-720p Boxset");
|
||||
AddCategoryMapping("cat=25", TorznabCatType.MoviesHD, "Movies - Kids");
|
||||
AddCategoryMapping("cat=10", TorznabCatType.MoviesSD, "Movies - SD");
|
||||
AddCategoryMapping("cat=23", TorznabCatType.MoviesSD, "Movies - MP4 Tablet");
|
||||
|
||||
// Music
|
||||
AddCategoryMapping("cat=28", TorznabCatType.AudioLossless, "Music - FLAC");
|
||||
AddCategoryMapping("cat=60", TorznabCatType.AudioLossless, "Music - FLAC Boxset");
|
||||
AddCategoryMapping("cat=4", TorznabCatType.AudioMP3, "Music - MP3");
|
||||
AddCategoryMapping("cat=59", TorznabCatType.AudioMP3, "Music - MP3 Boxset");
|
||||
AddCategoryMapping("cat=1", TorznabCatType.AudioMP3, "Music - Musicvideos");
|
||||
AddCategoryMapping("cat=61", TorznabCatType.AudioMP3, "Music - Musicvideos Boxset");
|
||||
|
||||
// Series
|
||||
AddCategoryMapping("cat=48", TorznabCatType.TVUHD, "TV - HD-4K/2160p");
|
||||
AddCategoryMapping("cat=57", TorznabCatType.TVUHD, "TV - HD-4K/2160p Boxset");
|
||||
AddCategoryMapping("cat=11", TorznabCatType.TVSD, "TV - Boxset");
|
||||
AddCategoryMapping("cat=7", TorznabCatType.TVHD, "TV - HD-1080p");
|
||||
AddCategoryMapping("cat=31", TorznabCatType.TVHD, "TV - HD-1080p Boxset");
|
||||
AddCategoryMapping("cat=30", TorznabCatType.TVHD, "TV - HD-720p");
|
||||
AddCategoryMapping("cat=32", TorznabCatType.TVHD, "TV - HD-720p Boxset");
|
||||
AddCategoryMapping("cat=5", TorznabCatType.TVSD, "TV - SD");
|
||||
AddCategoryMapping("cat=66", TorznabCatType.TVSport, "TV - SD/HD Mixed");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configure our FADN Provider
|
||||
/// </summary>
|
||||
/// <param name="configJson">Our params in Json</param>
|
||||
/// <returns>Configuration state</returns>
|
||||
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||
{
|
||||
// Retrieve config values set by Jackett's user
|
||||
LoadValuesFromJson(configJson);
|
||||
|
||||
// Check & Validate Config
|
||||
ValidateConfig();
|
||||
|
||||
// Setting our data for a better emulated browser (maximum security)
|
||||
// TODO: Encoded Content not supported by Jackett at this time
|
||||
// emulatedBrowserHeaders.Add("Accept-Encoding", "gzip, deflate");
|
||||
|
||||
// If we want to simulate a browser
|
||||
if (ConfigData.Browser.Value)
|
||||
{
|
||||
// Clean headers
|
||||
_emulatedBrowserHeaders.Clear();
|
||||
|
||||
// Inject headers
|
||||
_emulatedBrowserHeaders.Add("Accept", ConfigData.HeaderAccept.Value);
|
||||
_emulatedBrowserHeaders.Add("Accept-Language", ConfigData.HeaderAcceptLang.Value);
|
||||
_emulatedBrowserHeaders.Add("DNT", Convert.ToInt32(ConfigData.HeaderDnt.Value).ToString());
|
||||
_emulatedBrowserHeaders.Add("Upgrade-Insecure-Requests", Convert.ToInt32(ConfigData.HeaderUpgradeInsecure.Value).ToString());
|
||||
_emulatedBrowserHeaders.Add("User-Agent", ConfigData.HeaderUserAgent.Value);
|
||||
_emulatedBrowserHeaders.Add("Referer", LoginUrl);
|
||||
}
|
||||
|
||||
await DoLogin();
|
||||
|
||||
return IndexerConfigurationStatus.RequiresTesting;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Perform login to racker
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task DoLogin()
|
||||
{
|
||||
// Build WebRequest for index
|
||||
var myIndexRequest = new Utils.Clients.WebRequest()
|
||||
{
|
||||
Type = RequestType.GET,
|
||||
Url = SiteLink,
|
||||
Headers = _emulatedBrowserHeaders,
|
||||
Encoding = Encoding
|
||||
};
|
||||
|
||||
// Get index page for cookies
|
||||
Output("\nGetting index page (for cookies).. with " + SiteLink);
|
||||
var indexPage = await webclient.GetString(myIndexRequest);
|
||||
|
||||
// Building login form data
|
||||
var pairs = new Dictionary<string, string> {
|
||||
{ "username", ConfigData.Username.Value },
|
||||
{ "password", ConfigData.Password.Value }
|
||||
};
|
||||
|
||||
// Build WebRequest for login
|
||||
var myRequestLogin = new Utils.Clients.WebRequest()
|
||||
{
|
||||
Type = RequestType.GET,
|
||||
Url = LoginUrl,
|
||||
Headers = _emulatedBrowserHeaders,
|
||||
Cookies = indexPage.Cookies,
|
||||
Referer = SiteLink,
|
||||
Encoding = Encoding
|
||||
};
|
||||
|
||||
// Get login page -- (not used, but simulation needed by tracker security's checks)
|
||||
LatencyNow();
|
||||
Output("\nGetting login page (user simulation).. with " + LoginUrl);
|
||||
await webclient.GetString(myRequestLogin);
|
||||
|
||||
// Build WebRequest for submitting authentification
|
||||
var request = new Utils.Clients.WebRequest()
|
||||
{
|
||||
PostData = pairs,
|
||||
Referer = LoginUrl,
|
||||
Type = RequestType.POST,
|
||||
Url = LoginCheckUrl,
|
||||
Headers = _emulatedBrowserHeaders,
|
||||
Cookies = indexPage.Cookies,
|
||||
Encoding = Encoding
|
||||
};
|
||||
|
||||
// Perform loggin
|
||||
LatencyNow();
|
||||
Output("\nPerform loggin.. with " + LoginCheckUrl);
|
||||
var response = await webclient.GetString(request);
|
||||
|
||||
// Test if we are logged in
|
||||
await ConfigureIfOK(response.Cookies, response.Cookies != null && response.Cookies.Contains("uid="), () =>
|
||||
{
|
||||
// Default error message
|
||||
var message = "Error during attempt !";
|
||||
// Parse redirect header
|
||||
var redirectTo = response.RedirectingTo;
|
||||
|
||||
// Oops, unable to login
|
||||
Output("-> Login failed: " + message, "error");
|
||||
throw new ExceptionWithConfigData("Login failed: " + message, configData);
|
||||
});
|
||||
|
||||
Output("\nCookies saved for future uses...");
|
||||
ConfigData.CookieHeader.Value = indexPage.Cookies + " " + response.Cookies + " ts_username=" + ConfigData.Username.Value;
|
||||
|
||||
Output("\n-> Login Success\n");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check logged-in state for provider
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private async Task CheckLogin()
|
||||
{
|
||||
// Checking ...
|
||||
Output("\n-> Checking logged-in state....");
|
||||
var loggedInCheck = await RequestStringWithCookies(SearchUrl);
|
||||
if (!loggedInCheck.Content.Contains("logout.php"))
|
||||
{
|
||||
// Cookie expired, renew session on provider
|
||||
Output("-> Not logged, login now...\n");
|
||||
|
||||
await DoLogin();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Already logged, session active
|
||||
Output("-> Already logged, continue...\n");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Execute our search query
|
||||
/// </summary>
|
||||
/// <param name="query">Query</param>
|
||||
/// <returns>Releases</returns>
|
||||
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
|
||||
{
|
||||
var releases = new List<ReleaseInfo>();
|
||||
var torrentRowList = new List<CQ>();
|
||||
var exactSearchTerm = query.GetQueryString();
|
||||
var searchUrl = SearchUrl;
|
||||
|
||||
// Check login before performing a query
|
||||
await CheckLogin();
|
||||
|
||||
// Check cache first so we don't query the server (if search term used or not in dev mode)
|
||||
if (!DevMode && !string.IsNullOrEmpty(exactSearchTerm))
|
||||
{
|
||||
lock (cache)
|
||||
{
|
||||
// Remove old cache items
|
||||
CleanCache();
|
||||
|
||||
// Search in cache
|
||||
var cachedResult = cache.FirstOrDefault(i => i.Query == exactSearchTerm);
|
||||
if (cachedResult != null)
|
||||
return cachedResult.Results.Select(s => (ReleaseInfo)s.Clone()).ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
var SearchTerms = new List<string> { exactSearchTerm };
|
||||
|
||||
// duplicate search without diacritics
|
||||
var baseSearchTerm = StringUtil.RemoveDiacritics(exactSearchTerm);
|
||||
if (baseSearchTerm != exactSearchTerm)
|
||||
SearchTerms.Add(baseSearchTerm);
|
||||
|
||||
foreach (var searchTerm in SearchTerms)
|
||||
{
|
||||
// Build our query
|
||||
var request = BuildQuery(searchTerm, query, searchUrl);
|
||||
|
||||
// Getting results & Store content
|
||||
var response = await RequestStringWithCookiesAndRetry(request, ConfigData.CookieHeader.Value);
|
||||
_fDom = response.Content;
|
||||
|
||||
try
|
||||
{
|
||||
var firstPageRows = FindTorrentRows();
|
||||
|
||||
// Add them to torrents list
|
||||
torrentRowList.AddRange(firstPageRows.Select(fRow => fRow.Cq()));
|
||||
|
||||
// If pagination available
|
||||
int nbResults;
|
||||
int pageLinkCount;
|
||||
nbResults = 1;
|
||||
pageLinkCount = 1;
|
||||
|
||||
// Check if we have a minimum of one result
|
||||
if (firstPageRows.Length > 1)
|
||||
{
|
||||
// Retrieve total count on our alone page
|
||||
nbResults = firstPageRows.Count();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if no result
|
||||
if (torrentRowList.Count == 0)
|
||||
{
|
||||
// No results found
|
||||
Output("\nNo result found for your query, please try another search term ...\n", "info");
|
||||
|
||||
// No result found for this query
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Output("\nFound " + nbResults + " result(s) (+/- " + firstPageRows.Length + ") in " + pageLinkCount + " page(s) for this query !");
|
||||
Output("\nThere are " + (firstPageRows.Length -2 ) + " results on the first page !");
|
||||
|
||||
// Loop on results
|
||||
|
||||
foreach (var tRow in torrentRowList.Skip(1).Take(torrentRowList.Count-2))
|
||||
{
|
||||
Output("Torrent #" + (releases.Count + 1));
|
||||
|
||||
// ID
|
||||
var idOrig = tRow.Find("td:eq(1) > a:eq(0)").Attr("href").Split('=')[1];
|
||||
var id = idOrig.Substring(0, idOrig.Length - 4);
|
||||
Output("ID: " + id);
|
||||
|
||||
// Release Name
|
||||
var name = tRow.Find("td:eq(1) > a:eq(0)").Text();
|
||||
|
||||
// Category
|
||||
string categoryID = tRow.Find("td:eq(0) > a:eq(0)").Attr("href").Split('?').Last();
|
||||
var newznab = MapTrackerCatToNewznab(categoryID);
|
||||
Output("Category: " + MapTrackerCatToNewznab(categoryID).First().ToString() + " (" + categoryID + ")");
|
||||
|
||||
// Seeders
|
||||
int seeders = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(9)").Text(), @"\d+").Value);
|
||||
Output("Seeders: " + seeders);
|
||||
|
||||
// Leechers
|
||||
int leechers = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(10)").Text(), @"\d+").Value);
|
||||
Output("Leechers: " + leechers);
|
||||
|
||||
// Files
|
||||
int files = 1;
|
||||
files = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(4)").Text(), @"\d+").Value);
|
||||
Output("Files: " + files);
|
||||
|
||||
// Completed
|
||||
int completed = ParseUtil.CoerceInt(Regex.Match(tRow.Find("td:eq(8)").Text(), @"\d+").Value);
|
||||
Output("Completed: " + completed);
|
||||
|
||||
// Size
|
||||
var humanSize = tRow.Find("td:eq(7)").Text().ToLowerInvariant();
|
||||
var size = ReleaseInfo.GetBytes(humanSize);
|
||||
Output("Size: " + humanSize + " (" + size + " bytes)");
|
||||
|
||||
// Publish DateToString
|
||||
var dateTimeOrig = tRow.Find("td:eq(6)").Text();
|
||||
var datestr = Regex.Replace(dateTimeOrig, @"<[^>]+>| ", "").Trim();
|
||||
datestr = Regex.Replace(datestr, "Today", DateTime.Now.ToString("MMM dd yyyy"), RegexOptions.IgnoreCase);
|
||||
datestr = Regex.Replace(datestr, "Yesterday", DateTime.Now.Date.AddDays(-1).ToString("MMM dd yyyy"), RegexOptions.IgnoreCase);
|
||||
DateTime date = DateTimeUtil.FromUnknown(datestr, "DK");
|
||||
Output("Released on: " + date);
|
||||
|
||||
// Torrent Details URL
|
||||
var detailsLink = new Uri(TorrentDescriptionUrl.Replace("{id}", id.ToString()));
|
||||
Output("Details: " + detailsLink.AbsoluteUri);
|
||||
|
||||
// Torrent Comments URL
|
||||
var commentsLink = new Uri(TorrentCommentUrl.Replace("{id}", id.ToString()));
|
||||
Output("Comments Link: " + commentsLink.AbsoluteUri);
|
||||
|
||||
// Torrent Download URL
|
||||
var passkey = tRow.Find("td:eq(2) > a:eq(0)").Attr("href");
|
||||
var key = Regex.Match(passkey, "(?<=torrent_pass\\=)([a-zA-z0-9]*)");
|
||||
Uri downloadLink = new Uri(TorrentDownloadUrl.Replace("{id}", id.ToString()).Replace("{passkey}", key.ToString()));
|
||||
Output("Download Link: " + downloadLink.AbsoluteUri);
|
||||
|
||||
// Building release infos
|
||||
var release = new ReleaseInfo
|
||||
{
|
||||
Category = MapTrackerCatToNewznab(categoryID.ToString()),
|
||||
Title = name,
|
||||
Seeders = seeders,
|
||||
Peers = seeders + leechers,
|
||||
MinimumRatio = 1,
|
||||
MinimumSeedTime = 172800,
|
||||
PublishDate = date,
|
||||
Size = size,
|
||||
Files = files,
|
||||
Grabs = completed,
|
||||
Guid = detailsLink,
|
||||
Comments = commentsLink,
|
||||
Link = downloadLink
|
||||
};
|
||||
|
||||
// IMDB
|
||||
var imdbLink = tRow.Find("a[href*=\"http://imdb.com/title/\"]").First().Attr("href");
|
||||
release.Imdb = ParseUtil.GetLongFromString(imdbLink);
|
||||
|
||||
if (tRow.Find("img[title=\"Free Torrent\"]").Length >= 1)
|
||||
release.DownloadVolumeFactor = 0;
|
||||
else if (tRow.Find("img[title=\"Halfleech\"]").Length >= 1)
|
||||
release.DownloadVolumeFactor = 0.5;
|
||||
else if (tRow.Find("img[title=\"90% Freeleech\"]").Length >= 1)
|
||||
release.DownloadVolumeFactor = 0.1;
|
||||
else
|
||||
release.DownloadVolumeFactor = 1;
|
||||
|
||||
release.UploadVolumeFactor = 1;
|
||||
|
||||
releases.Add(release);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
OnParseError("Error, unable to parse result \n" + ex.StackTrace, ex);
|
||||
}
|
||||
}
|
||||
// Return found releases
|
||||
return releases;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Build query to process
|
||||
/// </summary>
|
||||
/// <param name="term">Term to search</param>
|
||||
/// <param name="query">Torznab Query for categories mapping</param>
|
||||
/// <param name="url">Search url for provider</param>
|
||||
/// <param name="page">Page number to request</param>
|
||||
/// <returns>URL to query for parsing and processing results</returns>
|
||||
private string BuildQuery(string term, TorznabQuery query, string url, int page = 0)
|
||||
{
|
||||
var parameters = new NameValueCollection();
|
||||
var categoriesList = MapTorznabCapsToTrackers(query);
|
||||
string searchterm = term;
|
||||
|
||||
// Building our tracker query
|
||||
parameters.Add("searchin", "title");
|
||||
parameters.Add("incldead", "0");
|
||||
|
||||
// If search term provided
|
||||
if (!string.IsNullOrWhiteSpace(query.ImdbID))
|
||||
{
|
||||
searchterm = "imdbsearch=" + query.ImdbID;
|
||||
}
|
||||
else if (!string.IsNullOrWhiteSpace(term))
|
||||
{
|
||||
searchterm = "search=" + WebUtilityHelpers.UrlEncode(term, Encoding.GetEncoding(28591));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Showing all torrents (just for output function)
|
||||
searchterm = "search=";
|
||||
term = "all";
|
||||
}
|
||||
|
||||
// Loop on categories and change the catagories for search purposes
|
||||
for (int i = 0; i < categoriesList.Count; i++)
|
||||
{
|
||||
// APPS
|
||||
if (new[] { "63", "17", "12", "62", "64" }.Any(c => categoriesList[i].Contains(categoriesList[i])))
|
||||
{
|
||||
categoriesList[i] = categoriesList[i].Replace("cat=", "cats5[]=");
|
||||
}
|
||||
// Books
|
||||
if (new[] { "54", "9" }.Any(c => categoriesList[i].Contains(categoriesList[i])))
|
||||
{
|
||||
categoriesList[i] = categoriesList[i].Replace("cat=", "cats6[]=");
|
||||
}
|
||||
// Games
|
||||
if (new[] { "24", "53", "49", "51" }.Any(c => categoriesList[i].Contains(categoriesList[i])))
|
||||
{
|
||||
categoriesList[i] = categoriesList[i].Replace("cat=", "cats3[]=");
|
||||
}
|
||||
// Movies
|
||||
if (new[] { "35", "42", "47", "15", "5", "16", "6", "21", "19", "22", "20", "25", "10", "23" }.Any(c => categoriesList[i].Contains(categoriesList[i])))
|
||||
{
|
||||
categoriesList[i] = categoriesList[i].Replace("cat=", "cats1[]=");
|
||||
}
|
||||
// Music
|
||||
if (new[] { "28", "60", "4", "59", "1", "61" }.Any(c => categoriesList[i].Contains(categoriesList[i])))
|
||||
{
|
||||
categoriesList[i] = categoriesList[i].Replace("cat=", "cats4[]=");
|
||||
}
|
||||
// Series
|
||||
if (new[] { "48", "57", "11", "7", "31", "30", "32", "5", "66" }.Any(c => categoriesList[i].Contains(categoriesList[i])))
|
||||
{
|
||||
categoriesList[i] = categoriesList[i].Replace("cat=", "cats2[]=");
|
||||
}
|
||||
}
|
||||
|
||||
// Build category search string
|
||||
var CatQryStr = "";
|
||||
foreach (var cat in categoriesList)
|
||||
CatQryStr += cat + "&";
|
||||
|
||||
// Building our query
|
||||
url += "?" + CatQryStr + searchterm + "&" + parameters.GetQueryString();
|
||||
|
||||
Output("\nBuilded query for \"" + term + "\"... " + url);
|
||||
|
||||
// Return our search url
|
||||
return url;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Switch Method for Querying
|
||||
/// </summary>
|
||||
/// <param name="request">URL created by Query Builder</param>
|
||||
/// <returns>Results from query</returns>
|
||||
private async Task<WebClientStringResult> QueryExec(string request)
|
||||
{
|
||||
WebClientStringResult results;
|
||||
|
||||
// Switch in we are in DEV mode with Hard Drive Cache or not
|
||||
if (DevMode && CacheMode)
|
||||
{
|
||||
// Check Cache before querying and load previous results if available
|
||||
results = await QueryCache(request);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Querying tracker directly
|
||||
results = await QueryTracker(request);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get Torrents Page from Cache by Query Provided
|
||||
/// </summary>
|
||||
/// <param name="request">URL created by Query Builder</param>
|
||||
/// <returns>Results from query</returns>
|
||||
private async Task<WebClientStringResult> QueryCache(string request)
|
||||
{
|
||||
WebClientStringResult results;
|
||||
|
||||
// Create Directory if not exist
|
||||
System.IO.Directory.CreateDirectory(Directory);
|
||||
|
||||
// Clean Storage Provider Directory from outdated cached queries
|
||||
CleanCacheStorage();
|
||||
|
||||
// Create fingerprint for request
|
||||
var file = Directory + request.GetHashCode() + ".json";
|
||||
|
||||
// Checking modes states
|
||||
if (System.IO.File.Exists(file))
|
||||
{
|
||||
// File exist... loading it right now !
|
||||
Output("Loading results from hard drive cache ..." + request.GetHashCode() + ".json");
|
||||
results = JsonConvert.DeserializeObject<WebClientStringResult>(System.IO.File.ReadAllText(file));
|
||||
}
|
||||
else
|
||||
{
|
||||
// No cached file found, querying tracker directly
|
||||
results = await QueryTracker(request);
|
||||
|
||||
// Cached file didn't exist for our query, writing it right now !
|
||||
Output("Writing results to hard drive cache ..." + request.GetHashCode() + ".json");
|
||||
System.IO.File.WriteAllText(file, JsonConvert.SerializeObject(results));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get Torrents Page from Tracker by Query Provided
|
||||
/// </summary>
|
||||
/// <param name="request">URL created by Query Builder</param>
|
||||
/// <returns>Results from query</returns>
|
||||
private async Task<WebClientStringResult> QueryTracker(string request)
|
||||
{
|
||||
// Cache mode not enabled or cached file didn't exist for our query
|
||||
Output("\nQuerying tracker for results....");
|
||||
|
||||
// Request our first page
|
||||
LatencyNow();
|
||||
var results = await RequestStringWithCookiesAndRetry(request, ConfigData.CookieHeader.Value, SearchUrl, _emulatedBrowserHeaders);
|
||||
|
||||
// Return results from tracker
|
||||
return results;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clean Hard Drive Cache Storage
|
||||
/// </summary>
|
||||
/// <param name="force">Force Provider Folder deletion</param>
|
||||
private void CleanCacheStorage(bool force = false)
|
||||
{
|
||||
// Check cleaning method
|
||||
if (force)
|
||||
{
|
||||
// Deleting Provider Storage folder and all files recursively
|
||||
Output("\nDeleting Provider Storage folder and all files recursively ...");
|
||||
|
||||
// Check if directory exist
|
||||
if (System.IO.Directory.Exists(Directory))
|
||||
{
|
||||
// Delete storage directory of provider
|
||||
System.IO.Directory.Delete(Directory, true);
|
||||
Output("-> Storage folder deleted successfully.");
|
||||
}
|
||||
else
|
||||
{
|
||||
// No directory, so nothing to do
|
||||
Output("-> No Storage folder found for this provider !");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var i = 0;
|
||||
// Check if there is file older than ... and delete them
|
||||
Output("\nCleaning Provider Storage folder... in progress.");
|
||||
System.IO.Directory.GetFiles(Directory)
|
||||
.Select(f => new System.IO.FileInfo(f))
|
||||
.Where(f => f.LastAccessTime < DateTime.Now.AddMilliseconds(-Convert.ToInt32(ConfigData.HardDriveCacheKeepTime.Value)))
|
||||
.ToList()
|
||||
.ForEach(f =>
|
||||
{
|
||||
Output("Deleting cached file << " + f.Name + " >> ... done.");
|
||||
f.Delete();
|
||||
i++;
|
||||
});
|
||||
|
||||
// Inform on what was cleaned during process
|
||||
if (i > 0)
|
||||
{
|
||||
Output("-> Deleted " + i + " cached files during cleaning.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Output("-> Nothing deleted during cleaning.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a random fake latency to avoid detection on tracker side
|
||||
/// </summary>
|
||||
private void LatencyNow()
|
||||
{
|
||||
// Need latency ?
|
||||
if (Latency)
|
||||
{
|
||||
var random = new Random(DateTime.Now.Millisecond);
|
||||
var waiting = random.Next(Convert.ToInt32(ConfigData.LatencyStart.Value),
|
||||
Convert.ToInt32(ConfigData.LatencyEnd.Value));
|
||||
Output("\nLatency Faker => Sleeping for " + waiting + " ms...");
|
||||
|
||||
// Sleep now...
|
||||
System.Threading.Thread.Sleep(waiting);
|
||||
}
|
||||
// Generate a random value in our range
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Find torrent rows in search pages
|
||||
/// </summary>
|
||||
/// <returns>JQuery Object</returns>
|
||||
private CQ FindTorrentRows()
|
||||
{
|
||||
// Return all occurencis of torrents found
|
||||
//return _fDom["#content > table > tr"];
|
||||
return _fDom["# base_content > table.mainouter > tbody > tr > td.outer > div.article > table > tbody > tr:not(:first)"];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Download torrent file from tracker
|
||||
/// </summary>
|
||||
/// <param name="link">URL string</param>
|
||||
/// <returns></returns>
|
||||
public override async Task<byte[]> Download(Uri link)
|
||||
{
|
||||
// Retrieving ID from link provided
|
||||
var id = ParseUtil.CoerceInt(Regex.Match(link.AbsoluteUri, @"\d+").Value);
|
||||
Output("Torrent Requested ID: " + id);
|
||||
|
||||
// Building login form data
|
||||
var pairs = new Dictionary<string, string> {
|
||||
{ "torrentid", id.ToString() },
|
||||
{ "_", string.Empty } // ~~ Strange, blank param...
|
||||
};
|
||||
|
||||
// Add emulated XHR request
|
||||
_emulatedBrowserHeaders.Add("X-Prototype-Version", "1.6.0.3");
|
||||
_emulatedBrowserHeaders.Add("X-Requested-With", "XMLHttpRequest");
|
||||
|
||||
// Get torrent file now
|
||||
Output("Getting torrent file now....");
|
||||
var response = await base.Download(link);
|
||||
|
||||
// Remove our XHR request header
|
||||
_emulatedBrowserHeaders.Remove("X-Prototype-Version");
|
||||
_emulatedBrowserHeaders.Remove("X-Requested-With");
|
||||
|
||||
// Return content
|
||||
return response;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Output message for logging or developpment (console)
|
||||
/// </summary>
|
||||
/// <param name="message">Message to output</param>
|
||||
/// <param name="level">Level for Logger</param>
|
||||
private void Output(string message, string level = "debug")
|
||||
{
|
||||
// Check if we are in dev mode
|
||||
if (DevMode)
|
||||
{
|
||||
// Output message to console
|
||||
Console.WriteLine(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Send message to logger with level
|
||||
switch (level)
|
||||
{
|
||||
default:
|
||||
goto case "debug";
|
||||
case "debug":
|
||||
// Only if Debug Level Enabled on Jackett
|
||||
if (logger.IsDebugEnabled)
|
||||
{
|
||||
logger.Debug(message);
|
||||
}
|
||||
break;
|
||||
|
||||
case "info":
|
||||
logger.Info(message);
|
||||
break;
|
||||
|
||||
case "error":
|
||||
logger.Error(message);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate Config entered by user on Jackett
|
||||
/// </summary>
|
||||
private void ValidateConfig()
|
||||
{
|
||||
Output("\nValidating Settings ... \n");
|
||||
|
||||
// Check Username Setting
|
||||
if (string.IsNullOrEmpty(ConfigData.Username.Value))
|
||||
{
|
||||
throw new ExceptionWithConfigData("You must provide a username for this tracker to login !", ConfigData);
|
||||
}
|
||||
else
|
||||
{
|
||||
Output("Validated Setting -- Username (auth) => " + ConfigData.Username.Value);
|
||||
}
|
||||
|
||||
// Check Password Setting
|
||||
if (string.IsNullOrEmpty(ConfigData.Password.Value))
|
||||
{
|
||||
throw new ExceptionWithConfigData("You must provide a password with your username for this tracker to login !", ConfigData);
|
||||
}
|
||||
else
|
||||
{
|
||||
Output("Validated Setting -- Password (auth) => " + ConfigData.Password.Value);
|
||||
}
|
||||
|
||||
// Check Max Page Setting
|
||||
if (!string.IsNullOrEmpty(ConfigData.Pages.Value))
|
||||
{
|
||||
try
|
||||
{
|
||||
Output("Validated Setting -- Max Pages => " + Convert.ToInt32(ConfigData.Pages.Value));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new ExceptionWithConfigData("Please enter a numeric maximum number of pages to crawl !", ConfigData);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ExceptionWithConfigData("Please enter a maximum number of pages to crawl !", ConfigData);
|
||||
}
|
||||
|
||||
// Check Latency Setting
|
||||
if (ConfigData.Latency.Value)
|
||||
{
|
||||
Output("\nValidated Setting -- Latency Simulation enabled");
|
||||
|
||||
// Check Latency Start Setting
|
||||
if (!string.IsNullOrEmpty(ConfigData.LatencyStart.Value))
|
||||
{
|
||||
try
|
||||
{
|
||||
Output("Validated Setting -- Latency Start => " + Convert.ToInt32(ConfigData.LatencyStart.Value));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new ExceptionWithConfigData("Please enter a numeric latency start in ms !", ConfigData);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ExceptionWithConfigData("Latency Simulation enabled, Please enter a start latency !", ConfigData);
|
||||
}
|
||||
|
||||
// Check Latency End Setting
|
||||
if (!string.IsNullOrEmpty(ConfigData.LatencyEnd.Value))
|
||||
{
|
||||
try
|
||||
{
|
||||
Output("Validated Setting -- Latency End => " + Convert.ToInt32(ConfigData.LatencyEnd.Value));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new ExceptionWithConfigData("Please enter a numeric latency end in ms !", ConfigData);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ExceptionWithConfigData("Latency Simulation enabled, Please enter a end latency !", ConfigData);
|
||||
}
|
||||
}
|
||||
|
||||
// Check Browser Setting
|
||||
if (ConfigData.Browser.Value)
|
||||
{
|
||||
Output("\nValidated Setting -- Browser Simulation enabled");
|
||||
|
||||
// Check ACCEPT header Setting
|
||||
if (string.IsNullOrEmpty(ConfigData.HeaderAccept.Value))
|
||||
{
|
||||
throw new ExceptionWithConfigData("Browser Simulation enabled, Please enter an ACCEPT header !", ConfigData);
|
||||
}
|
||||
else
|
||||
{
|
||||
Output("Validated Setting -- ACCEPT (header) => " + ConfigData.HeaderAccept.Value);
|
||||
}
|
||||
|
||||
// Check ACCEPT-LANG header Setting
|
||||
if (string.IsNullOrEmpty(ConfigData.HeaderAcceptLang.Value))
|
||||
{
|
||||
throw new ExceptionWithConfigData("Browser Simulation enabled, Please enter an ACCEPT-LANG header !", ConfigData);
|
||||
}
|
||||
else
|
||||
{
|
||||
Output("Validated Setting -- ACCEPT-LANG (header) => " + ConfigData.HeaderAcceptLang.Value);
|
||||
}
|
||||
|
||||
// Check USER-AGENT header Setting
|
||||
if (string.IsNullOrEmpty(ConfigData.HeaderUserAgent.Value))
|
||||
{
|
||||
throw new ExceptionWithConfigData("Browser Simulation enabled, Please enter an USER-AGENT header !", ConfigData);
|
||||
}
|
||||
else
|
||||
{
|
||||
Output("Validated Setting -- USER-AGENT (header) => " + ConfigData.HeaderUserAgent.Value);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Browser simulation must be enabled (otherwhise, this provider will not work due to tracker's security)
|
||||
throw new ExceptionWithConfigData("Browser Simulation must be enabled for this provider to work, please enable it !", ConfigData);
|
||||
}
|
||||
|
||||
// Check Dev Cache Settings
|
||||
if (ConfigData.HardDriveCache.Value)
|
||||
{
|
||||
Output("\nValidated Setting -- DEV Hard Drive Cache enabled");
|
||||
|
||||
// Check if Dev Mode enabled !
|
||||
if (!ConfigData.DevMode.Value)
|
||||
{
|
||||
throw new ExceptionWithConfigData("Hard Drive is enabled but not in DEV MODE, Please enable DEV MODE !", ConfigData);
|
||||
}
|
||||
|
||||
// Check Cache Keep Time Setting
|
||||
if (!string.IsNullOrEmpty(ConfigData.HardDriveCacheKeepTime.Value))
|
||||
{
|
||||
try
|
||||
{
|
||||
Output("Validated Setting -- Cache Keep Time (ms) => " + Convert.ToInt32(ConfigData.HardDriveCacheKeepTime.Value));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw new ExceptionWithConfigData("Please enter a numeric hard drive keep time in ms !", ConfigData);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ExceptionWithConfigData("Hard Drive Cache enabled, Please enter a maximum keep time for cache !", ConfigData);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Delete cache if previously existed
|
||||
CleanCacheStorage(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -86,7 +86,7 @@ namespace Jackett.Common.Indexers
|
||||
var results = await PerformQuery(new TorznabQuery());
|
||||
if (!results.Any())
|
||||
{
|
||||
throw new Exception("Your cookie did not work");
|
||||
throw new Exception("Your cookie did not work. You might have to change the \"Login Type\" to \"Normal\" in the x264 profile settings.");
|
||||
}
|
||||
|
||||
IsConfigured = true;
|
||||
|
||||
@@ -44,20 +44,23 @@ namespace Jackett.Common.Models.DTO
|
||||
stringQuery.ExpandCatsToSubCats();
|
||||
|
||||
// try to build an IMDB Query
|
||||
var imdbID = ParseUtil.GetFullImdbID(stringQuery.SanitizedSearchTerm);
|
||||
TorznabQuery imdbQuery = null;
|
||||
if (imdbID != null)
|
||||
if (stringQuery.SanitizedSearchTerm.StartsWith("tt") && stringQuery.SanitizedSearchTerm.Length <= 9)
|
||||
{
|
||||
imdbQuery = new TorznabQuery()
|
||||
var imdbID = ParseUtil.GetFullImdbID(stringQuery.SanitizedSearchTerm);
|
||||
TorznabQuery imdbQuery = null;
|
||||
if (imdbID != null)
|
||||
{
|
||||
ImdbID = imdbID,
|
||||
Categories = stringQuery.Categories,
|
||||
Season = stringQuery.Season,
|
||||
Episode = stringQuery.Episode,
|
||||
};
|
||||
imdbQuery.ExpandCatsToSubCats();
|
||||
imdbQuery = new TorznabQuery()
|
||||
{
|
||||
ImdbID = imdbID,
|
||||
Categories = stringQuery.Categories,
|
||||
Season = stringQuery.Season,
|
||||
Episode = stringQuery.Episode,
|
||||
};
|
||||
imdbQuery.ExpandCatsToSubCats();
|
||||
|
||||
return imdbQuery;
|
||||
return imdbQuery;
|
||||
}
|
||||
}
|
||||
|
||||
return stringQuery;
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
namespace Jackett.Common.Models.IndexerConfig.Bespoke
|
||||
{
|
||||
internal class ConfigurationDataNordicbits : ConfigurationData
|
||||
{
|
||||
public DisplayItem CredentialsWarning { get; private set; }
|
||||
public StringItem Username { get; private set; }
|
||||
public StringItem Password { get; private set; }
|
||||
public DisplayItem PagesWarning { get; private set; }
|
||||
public StringItem Pages { get; private set; }
|
||||
public DisplayItem SecurityWarning { get; private set; }
|
||||
public BoolItem Latency { get; private set; }
|
||||
public BoolItem Browser { get; private set; }
|
||||
public DisplayItem LatencyWarning { get; private set; }
|
||||
public StringItem LatencyStart { get; private set; }
|
||||
public StringItem LatencyEnd { get; private set; }
|
||||
public DisplayItem HeadersWarning { get; private set; }
|
||||
public StringItem HeaderAccept { get; private set; }
|
||||
public StringItem HeaderAcceptLang { get; private set; }
|
||||
public BoolItem HeaderDnt { get; private set; }
|
||||
public BoolItem HeaderUpgradeInsecure { get; private set; }
|
||||
public StringItem HeaderUserAgent { get; private set; }
|
||||
public DisplayItem DevWarning { get; private set; }
|
||||
public BoolItem DevMode { get; private set; }
|
||||
public BoolItem HardDriveCache { get; private set; }
|
||||
public StringItem HardDriveCacheKeepTime { get; private set; }
|
||||
|
||||
public ConfigurationDataNordicbits()
|
||||
{
|
||||
CredentialsWarning = new DisplayItem("<b>Credentials Configuration</b> (<i>Private Tracker</i>),<br /><br /> <ul><li><b>Username</b> is your account name on this tracker.</li><li><b>Password</b> is your password associated to your account name.</li></ul>") { Name = "Credentials" };
|
||||
Username = new StringItem { Name = "Username (Required)", Value = "" };
|
||||
Password = new StringItem { Name = "Password (Required)", Value = "" };
|
||||
PagesWarning = new DisplayItem("<b>Preferences Configuration</b> (<i>Tweak your search settings</i>),<br /><br /> <ul><li><b>Max Pages to Process</b> let you specify how many page (max) Jackett can process when doing a search. Setting a value <b>higher than 4 is dangerous</b> for you account ! (<b>Result of too many requests to tracker...that <u>will be suspect</u></b>).</li></ul>") { Name = "Preferences" };
|
||||
Pages = new StringItem { Name = "Max Pages to Process (Required)", Value = "4" };
|
||||
SecurityWarning = new DisplayItem("<b>Security Configuration</b> (<i>Read this area carefully !</i>),<br /><br /> <ul><li><b>Latency Simulation</b> will simulate human browsing with Jacket by pausing Jacket for an random time between each request, to fake a real content browsing.</li><li><b>Browser Simulation</b> will simulate a real human browser by injecting additionals headers when doing requests to tracker.<b>You must enable it to use this provider!</b></li></ul>") { Name = "Security" };
|
||||
Latency = new BoolItem() { Name = "Latency Simulation (Optional)", Value = false };
|
||||
Browser = new BoolItem() { Name = "Browser Simulation (Forced)", Value = true };
|
||||
LatencyWarning = new DisplayItem("<b>Latency Configuration</b> (<i>Required if latency simulation enabled</i>),<br /><br/> <ul><li>By filling this range, <b>Jackett will make a random timed pause</b> <u>between requests</u> to tracker <u>to simulate a real browser</u>.</li><li>MilliSeconds <b>only</b></li></ul>") { Name = "Simulate Latency" };
|
||||
LatencyStart = new StringItem { Name = "Minimum Latency (ms)", Value = "1589" };
|
||||
LatencyEnd = new StringItem { Name = "Maximum Latency (ms)", Value = "3674" };
|
||||
HeadersWarning = new DisplayItem("<b>Browser Headers Configuration</b> (<i>Required if browser simulation enabled</i>),<br /><br /> <ul><li>By filling these fields, <b>Jackett will inject headers</b> with your values <u>to simulate a real browser</u>.</li><li>You can get <b>your browser values</b> here: <a href='https://www.whatismybrowser.com/detect/what-http-headers-is-my-browser-sending' target='blank'>www.whatismybrowser.com</a></li></ul><br /><i><b>Note that</b> some headers are not necessary because they are injected automatically by this provider such as Accept_Encoding, Connection, Host or X-Requested-With</i>") { Name = "Injecting headers" };
|
||||
HeaderAccept = new StringItem { Name = "Accept", Value = "" };
|
||||
HeaderAcceptLang = new StringItem { Name = "Accept-Language", Value = "" };
|
||||
HeaderDnt = new BoolItem { Name = "DNT", Value = false };
|
||||
HeaderUpgradeInsecure = new BoolItem { Name = "Upgrade-Insecure-Requests", Value = false };
|
||||
HeaderUserAgent = new StringItem { Name = "User-Agent", Value = "" };
|
||||
DevWarning = new DisplayItem("<b>Development Facility</b> (<i>For Developers ONLY</i>),<br /><br /> <ul><li>By enabling development mode, <b>Jackett will bypass his cache</b> and will <u>output debug messages to console</u> instead of his log file.</li><li>By enabling Hard Drive Cache, <b>This provider</b> will <u>save each query answers from tracker</u> in temp directory, in fact this reduce drastically HTTP requests when building a provider at parsing step for example. So, <b> Jackett will search for a cached query answer on hard drive before executing query on tracker side !</b> <i>DEV MODE must be enabled to use it !</li></ul>") { Name = "Development" };
|
||||
DevMode = new BoolItem { Name = "Enable DEV MODE (Developers ONLY)", Value = false };
|
||||
HardDriveCache = new BoolItem { Name = "Enable HARD DRIVE CACHE (Developers ONLY)", Value = false };
|
||||
HardDriveCacheKeepTime = new StringItem { Name = "Keep Cached files for (ms)", Value = "300000" };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -202,6 +202,7 @@ namespace Jackett.Server.Controllers
|
||||
if (t.Key == "Category[]")
|
||||
{
|
||||
request.Category = t.Value.ToString().Split(',').Select(Int32.Parse).ToArray();
|
||||
CurrentQuery.Categories = request.Category;
|
||||
}
|
||||
|
||||
if (t.Key == "query")
|
||||
@@ -339,11 +340,13 @@ namespace Jackett.Server.Controllers
|
||||
|
||||
if (CurrentQuery.ImdbID != null)
|
||||
{
|
||||
/* We should allow this (helpful in case of aggregate indexers)
|
||||
if (!string.IsNullOrEmpty(CurrentQuery.SearchTerm))
|
||||
{
|
||||
logger.Warn($"A search request from {Request.HttpContext.Connection.RemoteIpAddress} was made containing q and imdbid.");
|
||||
return GetErrorXML(201, "Incorrect parameter: please specify either imdbid or q");
|
||||
}
|
||||
*/
|
||||
|
||||
CurrentQuery.ImdbID = ParseUtil.GetFullImdbID(CurrentQuery.ImdbID); // normalize ImdbID
|
||||
if (CurrentQuery.ImdbID == null)
|
||||
|
||||
@@ -96,8 +96,8 @@ namespace Jackett.Server.Controllers
|
||||
new ClaimsPrincipal(claimsIdentity),
|
||||
new AuthenticationProperties
|
||||
{
|
||||
ExpiresUtc = DateTime.UtcNow.AddMinutes(20),
|
||||
IsPersistent = false,
|
||||
ExpiresUtc = DateTime.UtcNow.AddDays(14), //Cookie expires at end of session
|
||||
IsPersistent = true,
|
||||
AllowRefresh = true
|
||||
});
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.Rewrite" Version="2.1.1" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.StaticFiles" Version="2.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.1.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.FileProviders.Physical" Version="2.1.1" />
|
||||
<PackageReference Include="NLog" Version="4.5.6" />
|
||||
<PackageReference Include="NLog.Web.AspNetCore" Version="4.5.4" />
|
||||
<PackageReference Include="System.ServiceProcess.ServiceController" Version="4.5.0" />
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace Jackett.Server
|
||||
{
|
||||
//TODO: Remove libcurl once off owin
|
||||
bool runningOnDotNetCore = RuntimeInformation.FrameworkDescription.IndexOf("Core", StringComparison.OrdinalIgnoreCase) >= 0;
|
||||
|
||||
|
||||
if (runningOnDotNetCore)
|
||||
{
|
||||
options.Client = "httpclientnetcore";
|
||||
@@ -130,7 +130,10 @@ namespace Jackett.Server
|
||||
try
|
||||
{
|
||||
logger.Debug("Creating web host...");
|
||||
CreateWebHostBuilder(args, url).Build().Run();
|
||||
string applicationFolder = Path.Combine(configurationService.ApplicationFolder(), "Content");
|
||||
logger.Debug($"Content root path is: {applicationFolder}");
|
||||
|
||||
CreateWebHostBuilder(args, url, applicationFolder).Build().Run();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -174,9 +177,11 @@ namespace Jackett.Server
|
||||
}
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args, string[] urls) =>
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args, string[] urls, string contentRoot) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseConfiguration(Configuration)
|
||||
.UseContentRoot(contentRoot)
|
||||
.UseWebRoot(contentRoot)
|
||||
.UseUrls(urls)
|
||||
.PreferHostingUrls(true)
|
||||
.UseStartup<Startup>()
|
||||
|
||||
@@ -18,7 +18,6 @@ using Microsoft.AspNetCore.Mvc.Authorization;
|
||||
using Microsoft.AspNetCore.Rewrite;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using System;
|
||||
using System.IO;
|
||||
@@ -48,6 +47,7 @@ namespace Jackett.Server
|
||||
options.AccessDeniedPath = new PathString("/UI/Login");
|
||||
options.LogoutPath = new PathString("/UI/Logout");
|
||||
options.Cookie.Name = "Jackett";
|
||||
options.Cookie.SameSite = SameSiteMode.None;
|
||||
});
|
||||
|
||||
services.AddMvc(config =>
|
||||
@@ -117,7 +117,8 @@ namespace Jackett.Server
|
||||
|
||||
app.UseForwardedHeaders(new ForwardedHeadersOptions
|
||||
{
|
||||
ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
|
||||
ForwardLimit = 10,
|
||||
ForwardedHeaders = ForwardedHeaders.XForwardedProto
|
||||
});
|
||||
|
||||
var rewriteOptions = new RewriteOptions()
|
||||
@@ -127,13 +128,7 @@ namespace Jackett.Server
|
||||
|
||||
app.UseRewriter(rewriteOptions);
|
||||
|
||||
app.UseFileServer(new FileServerOptions
|
||||
{
|
||||
FileProvider = new PhysicalFileProvider(Helper.ConfigService.GetContentFolder()),
|
||||
RequestPath = "",
|
||||
EnableDefaultFiles = true,
|
||||
EnableDirectoryBrowsing = false
|
||||
});
|
||||
app.UseStaticFiles();
|
||||
|
||||
app.UseAuthentication();
|
||||
|
||||
|
||||
@@ -42,7 +42,6 @@
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.IO.Compression" />
|
||||
<Reference Include="System.Net.Http.WebRequest" />
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.ServiceModel" />
|
||||
@@ -53,7 +52,6 @@
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -30,6 +30,11 @@ namespace Jackett.Tray
|
||||
Hide();
|
||||
InitializeComponent();
|
||||
|
||||
Opacity = 0;
|
||||
Enabled = false;
|
||||
WindowState = FormWindowState.Minimized;
|
||||
FormBorderStyle = FormBorderStyle.FixedToolWindow;
|
||||
|
||||
RuntimeSettings runtimeSettings = new RuntimeSettings()
|
||||
{
|
||||
CustomLogFileName = "TrayLog.txt"
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Jackett.Tray
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (Exception)
|
||||
{
|
||||
newVersion = "";
|
||||
}
|
||||
|
||||
@@ -231,6 +231,8 @@ namespace Jackett.Updater
|
||||
"Definitions/oxtorrent.yml",
|
||||
"Definitions/tehconnection.yml",
|
||||
"Definitions/torrentwtf.yml",
|
||||
"Definitions/eotforum.yml",
|
||||
"Definitions/nexttorrent.yml",
|
||||
};
|
||||
|
||||
foreach (var oldFile in oldFiles)
|
||||
|
||||
@@ -289,11 +289,13 @@ namespace Jackett.Controllers
|
||||
|
||||
if (CurrentQuery.ImdbID != null)
|
||||
{
|
||||
/* We should allow this (helpful in case of aggregate idnexers)
|
||||
if (!string.IsNullOrEmpty(CurrentQuery.SearchTerm))
|
||||
{
|
||||
logger.Warn($"A search request from {Request.GetOwinContext().Request.RemoteIpAddress} was made containing q and imdbid.");
|
||||
return GetErrorXML(201, "Incorrect parameter: please specify either imdbid or q");
|
||||
}
|
||||
*/
|
||||
|
||||
CurrentQuery.ImdbID = ParseUtil.GetFullImdbID(CurrentQuery.ImdbID); // normalize ImdbID
|
||||
if (CurrentQuery.ImdbID == null)
|
||||
|
||||
Reference in New Issue
Block a user