Compare commits

..

65 Commits

Author SHA1 Message Date
kaso17
0adb54f4b2 kestrel: attempt to fix XForwardedProto issues 2018-08-12 12:18:14 +02:00
hallengreenn
2e77226f0c Update nordicb.org - categoryList for search (#3568)
I made some copy-paste errors, while building the categoryList.
Because of this - the seach string for Apps & Ebooks won't be builded correctly.
Fixed
2018-08-12 16:50:43 +10:00
flightlevel
31ae08544f Remove System.Runtime.InteropServices.RuntimeInformation.dll from Mono build
https://github.com/Jackett/Jackett/issues/3547
2018-08-12 16:49:52 +10:00
Garfield69
3da6e4ca1b torrent9: domain change. fix #3569 2018-08-12 08:06:21 +12:00
halali
c4cd17ce2d Update cztorrent.yml (#3551)
* Update cztorrent.yml

* Update cztorrent.yml
2018-08-11 12:53:35 +10:00
hallengreenn
ee18368192 Add support for Nordicbits.org/nordicb.org (#3552)
* Create Nordicbits.cs

Add support for Nordicbits / DK Private Tracker

* Create ConfigurationDataNordicbits.cs

Create Nordicbits.cs

Add support for Nordicbits / DK Private Tracker

* Update README.md

Added a new tracker Nordicbits

* Update Nordicbits.cs

The self-tester didn't work, because of the trackers use of 'Today' and 'Yesterday' in releases. Where other releases are "MMM dd yyyy".
This is fixed now.

* Update Nordicbits.cs

Search string wasn't build proberly, due to the catagory of nordicbits.
The images, which we use to determin which catagory the release is from goes like this - 
cat=5
But when we need to search under that catagory and have more than one, it should go like this -
cats2[]=5

Changed the categorieslist, by using replace and changed the query string to match the original search string.

* Update Nordicbits.cs

Should solve the bug - The string was not recognized as a valid DateTime. There is an unknown word starting at index 0.

* Update Nordicbits.cs

Tracker don't support imdb, therefore problems with handling of couchpotato, radarr or similar.
Fixed by setting imdb to false;
2018-08-11 12:53:06 +10:00
kaso17
09a7950c1d x264: add Login Type note 2018-08-06 13:14:44 +02:00
Chris Johnson
847688bae8 Updated Readme to include linux Ansible installations (#3516)
Added reference to a RHEL and Ubuntu ansible galaxy role for installing via Ansible.
2018-08-05 18:48:18 +02:00
Jorman
7fde427731 girotorrent: Update regex for better title parsing... (#3529)
Italian release suck, you can find S01E01 or 01x01 or even S01 E01.
So removed S and E from search (this bring in extra results) then try to parse and reconstruct the results
Hope for now is enough to have a better search, at least on Italian tracker, for the external tracker (where are present Italian release too), only god can tell ... Sonarr will parse the result during a rss sync, but during a search I think no result will present ... There are 2 possible solution
1. Find and eliminate all release that don't respect the standard
2. Make Jackett / Sonarr / Radarr a little smartest and include a kind of regional substitution during a searching phase
2018-08-05 18:45:42 +02:00
Jorman
7319078a5d shareisland: Update regex for better title parsing... (#3530)
Italian release suck, you can find S01E01 or 01x01 or even S01 E01.
So removed S and E from search (this bring in extra results) then try to parse and reconstruct the results
Hope for now is enough to have a better search, at least on Italian tracker, for the external tracker (where are present Italian release too), only god can tell ... Sonarr will parse the result during a rss sync, but during a search I think no result will present ... There are 2 possible solution
1. Find and eliminate all release that don't respect the standard
2. Make Jackett / Sonarr / Radarr a little smartest and include a kind of regional substitution during a searching phase
2018-08-05 18:44:55 +02:00
Jorman
495afb91e9 ilcorsaroblu: Update regex for better title parsing... (#3532)
Italian release suck, you can find S01E01 or 01x01 or even S01 E01.
So removed S and E from search (this bring in extra results) then try to parse and reconstruct the results
Hope for now is enough to have a better search, at least on Italian tracker, for the external tracker (where are present Italian release too), only god can tell ... Sonarr will parse the result during a rss sync, but during a search I think no result will present ... There are 2 possible solution
1. Find and eliminate all release that don't respect the standard
2. Make Jackett / Sonarr / Radarr a little smartest and include a kind of regional substitution during a searching phase
2018-08-05 18:42:17 +02:00
Jorman
aa3fa8717f ilcorsaronero: Update regex for better title parsing... (#3531)
Italian release suck, you can find S01E01 or 01x01 or even S01 E01.
So removed S and E from search (this bring in extra results) then try to parse and reconstruct the results
Hope for now is enough to have a better search, at least on Italian tracker, for the external tracker (where are present Italian release too), only god can tell ... Sonarr will parse the result during a rss sync, but during a search I think no result will present ... There are 2 possible solution
1. Find and eliminate all release that don't respect the standard
2. Make Jackett / Sonarr / Radarr a little smartest and include a kind of regional substitution during a searching phase
2018-08-05 18:41:20 +02:00
flightlevel
052e382d93 Assign webroot for static files
Removes the need for PhysicalFileProvider
2018-08-05 15:31:54 +10:00
flightlevel
db39b6afd9 Prevent cookie expiring after 20 minutes, now sessional 2018-08-05 15:19:31 +10:00
HDVinnie
e05efaeb1d Update blutopia.yml (#3528)
- closes #3523
2018-08-05 15:15:54 +10:00
kaso17
b94501f054 adjust content root path (#3527) 2018-08-05 15:15:23 +10:00
flightlevel
f00d8e192a Set the content root to the application folder
https://github.com/Jackett/Jackett/issues/3522
2018-08-04 16:49:26 +10:00
eric@skrobs
9ca4600eab yggtorrent: fix URL (#3515)
Fix YGGTorrent url
2018-08-03 06:15:08 +02:00
flightlevel
5e8ebd8579 Build script: Use Kestrel web server on Mono 2018-07-31 20:19:25 +10:00
flightlevel
748881ef70 Kestrel: accept imdbid+q
Copy of 0d6830b0aa
2018-07-31 20:14:02 +10:00
kaso17
42e6600c6a NextTorrent: removed (dead) 2018-07-31 11:00:34 +02:00
kaso17
85d17a7763 RGU: update definition 2018-07-30 19:19:17 +02:00
kaso17
b1391b0523 ExoticaZ (Your Exotic Torrents): update definition 2018-07-30 19:07:16 +02:00
Jorman
8510a42d7a Il Corsaro Blu: Update definition (#3493)
Quick fix for parsing
2018-07-30 18:08:17 +02:00
kaso17
e61f6e78b3 EoT-Forum: removed (dead) 2018-07-30 18:06:57 +02:00
kaso17
176ba5a6db AST4u: fix definition 2018-07-30 18:02:54 +02:00
kaso17
ad3c56e83b .NETCore: fix manual search categories 2018-07-30 17:39:28 +02:00
kaso17
2495a2f64e manual search: fix IMDB parsing 2018-07-30 15:18:06 +02:00
kaso17
0d6830b0aa accept imdbid+q 2018-07-30 15:06:05 +02:00
kaso17
ef316590cb support multiple category mappings 2018-07-30 14:25:35 +02:00
kaso17
c3c25190a2 gay-torrents.org: fix and improve definition 2018-07-30 14:23:59 +02:00
kaso17
fc3d8d1aec Gazelle: fix free leech token usage for large torrents 2018-07-30 13:16:13 +02:00
kaso17
bbb7d1c3c7 Karagarga: fix date and uploadvolumefactor 2018-07-30 13:05:01 +02:00
kaso17
89dfac3009 GUI: fix DL/UL factor rounding 2018-07-30 13:02:09 +02:00
kaso17
9610965979 GAYtorrent.ru: fix date 2018-07-30 12:43:00 +02:00
kaso17
8b501403e1 gay-torrents.org: fix type 2018-07-30 12:42:30 +02:00
kaso17
3a88aeb649 Cinematik: fix grabs 2018-07-30 12:42:04 +02:00
kaso17
0a0ba2291b Karagarga: fix grabs 2018-07-30 12:14:46 +02:00
kaso17
2484e22da9 GAYtorrent.ru: fix files 2018-07-30 12:14:30 +02:00
kaso17
e8ca3e6b52 gay-torrents.org: add grabs 2018-07-30 12:14:13 +02:00
natalia2493
d5c7445919 Fix BTXpress (#3488)
Parse error fix and cleanup
2018-07-29 14:14:13 +10:00
flightlevel
72045404d4 Torrent9: Update url
Fixes: https://github.com/Jackett/Jackett/issues/3483
2018-07-28 13:12:05 +10:00
flightlevel
1a6e1a8c60 Yggtorrent: Add missing slash 2018-07-28 13:11:24 +10:00
flightlevel
540dc0fad4 Proxy password: Change type to password
Fixes https://github.com/Jackett/Jackett/issues/3485
2018-07-28 13:10:56 +10:00
flightlevel
1db3e93ce1 Allow cookie cross site as per legacy
https://github.com/Jackett/Jackett/issues/3440
2018-07-28 13:10:01 +10:00
kaso17
a5ec65bff3 README: add nginx reverse proxy config example 2018-07-27 18:08:42 +02:00
kaso17
c4e3aa8a64 add x-ite.me indexer
Thank you LA5T
2018-07-27 16:04:11 +02:00
kaso17
e3e183d86b Karagarga: improve definition
Thank you LA5T
2018-07-27 16:00:22 +02:00
kaso17
bfe892f2c8 GAYtorrent.ru: improve definition
Thank you LA5T
2018-07-27 15:55:19 +02:00
kaso17
b28116c10f gay-torrents.org: use username/password input names 2018-07-27 15:52:05 +02:00
kaso17
52c408fce7 Add gay-torrents.org indexer
Thank you LA5T
2018-07-27 15:49:27 +02:00
kaso17
a70997ad7f Cinematik: improve definition
Thank you @LA5T
2018-07-27 15:46:25 +02:00
kaso17
8840de316d Merge branch 'master' of https://github.com/Jackett/Jackett 2018-07-26 17:34:34 +02:00
kaso17
409483e680 Kapaki: add support for modern style 2018-07-26 17:34:24 +02:00
flightlevel
b19d690305 Jackett.Tray: Hide form 2018-07-26 22:07:04 +10:00
natalia2493
0fabaf2fe0 Update BTXpress (#3404)
- Removed IMDB Description as it is not needed
- Removed Audio Category
2018-07-26 20:49:19 +10:00
Jorman
3035d8b901 Domain changed (#3459) 2018-07-25 16:20:34 +12:00
betamax2021
f3d73b5661 Build From Source OSX (#3456)
* Update README.md

Added OS X steps to build from source

* Update README.md

Formating Fix
2018-07-23 21:16:49 +10:00
flightlevel
f335dbf7bc Jackett Tray: Hide from ALT + TAB
https://github.com/Jackett/Jackett/issues/1959
2018-07-22 22:03:04 +10:00
flightlevel
b5178dc7b8 YggTorrent; Update Url
Fixes https://github.com/Jackett/Jackett/issues/3229
2018-07-21 21:47:45 +10:00
flightlevel
ad09a4dd77 Limetorrent: Url update
Fixes https://github.com/Jackett/Jackett/issues/3431
2018-07-21 21:46:55 +10:00
flightlevel
da0ead13f4 MejorTorrent: Update Url
https://github.com/Jackett/Jackett/issues/1468
2018-07-19 20:48:56 +10:00
ATAlgaba
4b6a9376de Update anidex.yml (#3411)
Remove anidb id - sorting names was acting weird as episode numbers were mistaken with the anidb id
2018-07-17 19:45:49 +10:00
ATAlgaba
3eab605423 Update frozenlayer.yml (#3401)
* Update frozenlayer.yml

Better filtering for Absolute Episode Searching.

* Update frozenlayer.yml

Append Spanish language
2018-07-17 19:45:25 +10:00
flightlevel
7fc37f1156 IlCorsaroBlue: Incomplete CA Chain
#3395
2018-07-15 11:02:59 +10:00
45 changed files with 1826 additions and 737 deletions

View File

@@ -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

View File

@@ -1,4 +1,4 @@
version: 0.9.{build}
version: 0.10.{build}
skip_tags: true
image: Visual Studio 2017
configuration: Release

View File

@@ -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(() =>
{

View File

@@ -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>');
}
}
}

View File

@@ -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>

View File

@@ -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

View File

@@ -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"]

View File

@@ -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\.]+)

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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:

View File

@@ -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

View File

@@ -6,6 +6,8 @@
type: public
encoding: UTF-8
links:
- https://www.limetorrents.io/
legacylinks:
- https://www.limetorrents.cc/
caps:

View File

@@ -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"

View File

@@ -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:

View File

@@ -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

View File

@@ -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:

View 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

View File

@@ -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:

View File

@@ -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"

View File

@@ -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");

View File

@@ -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;
}

View File

@@ -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");

View 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, @"<[^>]+>|&nbsp;", "").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);
}
}
}
}

View File

@@ -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;

View File

@@ -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;

View File

@@ -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" };
}
}
}

View File

@@ -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)

View File

@@ -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
});
}

View File

@@ -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" />

View File

@@ -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>()

View File

@@ -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();

View File

@@ -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>

View File

@@ -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"

View File

@@ -39,7 +39,7 @@ namespace Jackett.Tray
}
});
}
catch (Exception e)
catch (Exception)
{
newVersion = "";
}

View File

@@ -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)

View File

@@ -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)