mirror of
https://github.com/Jackett/Jackett.git
synced 2025-09-13 23:44:10 +02:00
Compare commits
387 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9f03f8129a | ||
![]() |
51aa6fdf13 | ||
![]() |
f2f602dcc5 | ||
![]() |
a217381668 | ||
![]() |
4bd7befb50 | ||
![]() |
56074155e9 | ||
![]() |
86a5a9cd25 | ||
![]() |
1792ed276e | ||
![]() |
4d1e4b59c8 | ||
![]() |
e1ff4b9e12 | ||
![]() |
86400e1b8a | ||
![]() |
b3d53d1c01 | ||
![]() |
471d494b3b | ||
![]() |
6e7d983fc3 | ||
![]() |
fd1073d0b5 | ||
![]() |
7815615112 | ||
![]() |
a6d8e68ca9 | ||
![]() |
9593ba2414 | ||
![]() |
8c95045a4a | ||
![]() |
667317e513 | ||
![]() |
0026a4f26e | ||
![]() |
2fac90df9f | ||
![]() |
424e7b773d | ||
![]() |
d25506e595 | ||
![]() |
a83e90e9ce | ||
![]() |
ea93182d96 | ||
![]() |
d60ee24111 | ||
![]() |
40e5c999b3 | ||
![]() |
6175b805d2 | ||
![]() |
5b6ba8d75f | ||
![]() |
10b0f0b1ce | ||
![]() |
a81ef63075 | ||
![]() |
2dc5edbb55 | ||
![]() |
636be458a6 | ||
![]() |
64283f137c | ||
![]() |
ec1c9a9461 | ||
![]() |
d9a806d236 | ||
![]() |
ebd294b602 | ||
![]() |
6081094b73 | ||
![]() |
115dfd20e7 | ||
![]() |
038fe2866b | ||
![]() |
aec40373d3 | ||
![]() |
c9b8d27139 | ||
![]() |
d0793ebcba | ||
![]() |
00e4e8109e | ||
![]() |
bcc1dc1948 | ||
![]() |
1e67996df0 | ||
![]() |
947bed0a46 | ||
![]() |
0dd9842e84 | ||
![]() |
42728e2694 | ||
![]() |
44d14dc19c | ||
![]() |
2e95c491a1 | ||
![]() |
acfc776462 | ||
![]() |
b6692a7dab | ||
![]() |
34fc2a0d15 | ||
![]() |
07938dcef8 | ||
![]() |
847c5dfdcb | ||
![]() |
bd47603f0d | ||
![]() |
8b86146715 | ||
![]() |
5343c9109b | ||
![]() |
687acae90b | ||
![]() |
871e540957 | ||
![]() |
b0ce0b5350 | ||
![]() |
bc965b1a0c | ||
![]() |
89b60c4c15 | ||
![]() |
47a84775c5 | ||
![]() |
8de0b0cbad | ||
![]() |
b95fbd76a7 | ||
![]() |
6b44cc9b74 | ||
![]() |
0612c70ca1 | ||
![]() |
060972475f | ||
![]() |
28bbeec462 | ||
![]() |
099adadbdc | ||
![]() |
43511c6ecb | ||
![]() |
aa3e9c6fde | ||
![]() |
e53cdcb909 | ||
![]() |
fd14ad3f93 | ||
![]() |
ca1af97e42 | ||
![]() |
4970219ea7 | ||
![]() |
54c5b66ecf | ||
![]() |
8ae09d453d | ||
![]() |
f2e7ec25c8 | ||
![]() |
7f9fff4683 | ||
![]() |
13f2eea298 | ||
![]() |
d6f5a1b242 | ||
![]() |
ab37f0c2c7 | ||
![]() |
9710b37064 | ||
![]() |
54f7568111 | ||
![]() |
06758964c0 | ||
![]() |
b56552e0f4 | ||
![]() |
ef8653f7d2 | ||
![]() |
d5a6987390 | ||
![]() |
8fb92ca05c | ||
![]() |
11c7015c17 | ||
![]() |
8bc5d813b7 | ||
![]() |
012f5f05cc | ||
![]() |
cd65ec7a71 | ||
![]() |
45826df4fe | ||
![]() |
0645bab613 | ||
![]() |
4e409dfb50 | ||
![]() |
52a39b7a71 | ||
![]() |
5278b9fb47 | ||
![]() |
1ecafe3667 | ||
![]() |
190a415907 | ||
![]() |
ca609a9e62 | ||
![]() |
b72ade7b27 | ||
![]() |
e7098d01c5 | ||
![]() |
b04ee56612 | ||
![]() |
72a18e9b73 | ||
![]() |
6be64bbe36 | ||
![]() |
cf3848a54f | ||
![]() |
1a14e8dd4b | ||
![]() |
a25eb7f951 | ||
![]() |
9437cd54d3 | ||
![]() |
be55c5e4a6 | ||
![]() |
f1d774aa07 | ||
![]() |
c109133fcc | ||
![]() |
3538fdfaf7 | ||
![]() |
3468e7d404 | ||
![]() |
ec4afda184 | ||
![]() |
67b1835264 | ||
![]() |
aee64aa589 | ||
![]() |
687e6e237f | ||
![]() |
b48dd5e930 | ||
![]() |
5ee6833610 | ||
![]() |
c998ba3762 | ||
![]() |
2d4f7ab0e9 | ||
![]() |
676d03eb88 | ||
![]() |
68351a480b | ||
![]() |
33e35f1bd3 | ||
![]() |
e82b54994e | ||
![]() |
6f7ecbfb7b | ||
![]() |
c4aa49eb32 | ||
![]() |
32aae44ffc | ||
![]() |
7883534c5e | ||
![]() |
b58c9fb718 | ||
![]() |
99d8f63f9e | ||
![]() |
635e8240d2 | ||
![]() |
117a670aa3 | ||
![]() |
f49c58a1fa | ||
![]() |
2492f1b797 | ||
![]() |
d6781f67b2 | ||
![]() |
2e0c22eb6d | ||
![]() |
211e152863 | ||
![]() |
f7bf4060ea | ||
![]() |
8c953bbf01 | ||
![]() |
4e91761fdf | ||
![]() |
53f8465e67 | ||
![]() |
5818b914a3 | ||
![]() |
0680d39d90 | ||
![]() |
4ca6676be0 | ||
![]() |
3d85e751b7 | ||
![]() |
965da06214 | ||
![]() |
e8bc2816ef | ||
![]() |
28ed7cc8a5 | ||
![]() |
089d9f2e3d | ||
![]() |
9abce7a586 | ||
![]() |
53162b4bd3 | ||
![]() |
80d78a027b | ||
![]() |
b4eda2ed54 | ||
![]() |
4d8d21a815 | ||
![]() |
f3290800d8 | ||
![]() |
22a858c076 | ||
![]() |
823419c032 | ||
![]() |
908d3f64f4 | ||
![]() |
3843d68766 | ||
![]() |
4b599f391c | ||
![]() |
6d8239caab | ||
![]() |
dae37f273a | ||
![]() |
1615bff2d0 | ||
![]() |
b303befbb9 | ||
![]() |
e243c11cc0 | ||
![]() |
c860bca320 | ||
![]() |
a60c1fca36 | ||
![]() |
23f55ef33a | ||
![]() |
5ad2c7a371 | ||
![]() |
e4c729a588 | ||
![]() |
3df0218347 | ||
![]() |
601783aef6 | ||
![]() |
f09c5722be | ||
![]() |
e73ae99e38 | ||
![]() |
10c5c99385 | ||
![]() |
ac5af81344 | ||
![]() |
823563c84f | ||
![]() |
47410c5eb6 | ||
![]() |
af135f4ae9 | ||
![]() |
3eeced3a04 | ||
![]() |
8ea99b548d | ||
![]() |
ae73e8188d | ||
![]() |
9c5cda72da | ||
![]() |
fb1e24799d | ||
![]() |
5721948434 | ||
![]() |
d7b6f413be | ||
![]() |
959ec4667d | ||
![]() |
20433db169 | ||
![]() |
54465798e9 | ||
![]() |
313147d224 | ||
![]() |
84bd947eca | ||
![]() |
366abc4431 | ||
![]() |
2f7fa2f063 | ||
![]() |
205f6cac12 | ||
![]() |
f602b3db24 | ||
![]() |
0d72f1f228 | ||
![]() |
508125e68f | ||
![]() |
cfb714e13c | ||
![]() |
b9dcfd1b02 | ||
![]() |
a1b2dc67b8 | ||
![]() |
2207c5a961 | ||
![]() |
2caa09bb1e | ||
![]() |
68906f6e40 | ||
![]() |
2cf3cf15e3 | ||
![]() |
88202c1f7f | ||
![]() |
6293c787e7 | ||
![]() |
f67fda3bf4 | ||
![]() |
0a70f91bf1 | ||
![]() |
88945be5d7 | ||
![]() |
c81dd24fe7 | ||
![]() |
af94dd2757 | ||
![]() |
0a07738c5b | ||
![]() |
e05783a25a | ||
![]() |
27d4ab3967 | ||
![]() |
04b3efbbc2 | ||
![]() |
ccd5347be2 | ||
![]() |
e1c5f3ed6d | ||
![]() |
c1fb41204c | ||
![]() |
b50733054f | ||
![]() |
e324773c91 | ||
![]() |
6a4c34d5df | ||
![]() |
bc34b9f176 | ||
![]() |
96af05fbef | ||
![]() |
842d9e79ce | ||
![]() |
086d8b32e9 | ||
![]() |
a6390f2bc5 | ||
![]() |
1ab0827ae7 | ||
![]() |
db0f651f33 | ||
![]() |
7f163c3945 | ||
![]() |
cb53867b37 | ||
![]() |
b5b907c9ed | ||
![]() |
2f8ef4aec2 | ||
![]() |
e5929c850c | ||
![]() |
86771a87c6 | ||
![]() |
5df131140f | ||
![]() |
8002483e68 | ||
![]() |
ce84264490 | ||
![]() |
fca6ac0dbc | ||
![]() |
da61eb8988 | ||
![]() |
ef22d43f46 | ||
![]() |
f63f1361ce | ||
![]() |
547c9174b1 | ||
![]() |
cb292bbf06 | ||
![]() |
784c41b83a | ||
![]() |
42fbe9270a | ||
![]() |
8067f1948e | ||
![]() |
143cc6e8d0 | ||
![]() |
628ab0ca82 | ||
![]() |
cc13d7edf6 | ||
![]() |
6ea2c18384 | ||
![]() |
fb316d9068 | ||
![]() |
fda730dcad | ||
![]() |
8d921202fa | ||
![]() |
615794a4bf | ||
![]() |
5eed9d7038 | ||
![]() |
e6b135e151 | ||
![]() |
dbde3b469a | ||
![]() |
7841bcab06 | ||
![]() |
efe1346d41 | ||
![]() |
f162902b36 | ||
![]() |
a752683965 | ||
![]() |
683bd6e2d4 | ||
![]() |
13426fe7ec | ||
![]() |
d87d0f87b1 | ||
![]() |
85ec169755 | ||
![]() |
9cc40144a9 | ||
![]() |
42beb6018e | ||
![]() |
2d0e82159d | ||
![]() |
08ad94a2f5 | ||
![]() |
0eebea0ef7 | ||
![]() |
e4888b83d8 | ||
![]() |
37f8066901 | ||
![]() |
92f976916f | ||
![]() |
530ad7ecf5 | ||
![]() |
c1bc750059 | ||
![]() |
364061fde0 | ||
![]() |
1b4826f966 | ||
![]() |
580eacdb18 | ||
![]() |
270b8c9041 | ||
![]() |
9f7590783d | ||
![]() |
63dceed010 | ||
![]() |
ee3e0dd0e1 | ||
![]() |
e19d59c4ab | ||
![]() |
d29132a540 | ||
![]() |
0037811fb5 | ||
![]() |
1f1b8d0074 | ||
![]() |
dae6aeb4b5 | ||
![]() |
9bfb249425 | ||
![]() |
0bbcecc1c3 | ||
![]() |
a871e35449 | ||
![]() |
9961031b0e | ||
![]() |
c2d3214c01 | ||
![]() |
13e14f3e62 | ||
![]() |
ffe435051b | ||
![]() |
5e00b2ec33 | ||
![]() |
a73fbccd22 | ||
![]() |
48cdc3bb5e | ||
![]() |
535f71c18c | ||
![]() |
9ceeb71448 | ||
![]() |
457449866e | ||
![]() |
427428d09b | ||
![]() |
82b203c9c3 | ||
![]() |
9677c2deee | ||
![]() |
9000745877 | ||
![]() |
2fb413123c | ||
![]() |
6316b82600 | ||
![]() |
2746d797ee | ||
![]() |
7e5a7ad153 | ||
![]() |
e947059da1 | ||
![]() |
65aaaa3d77 | ||
![]() |
c2b2c94e1b | ||
![]() |
e8465f23b9 | ||
![]() |
09d37ab232 | ||
![]() |
f413355610 | ||
![]() |
5a97cd7dd2 | ||
![]() |
7b354d1582 | ||
![]() |
b964a33ae2 | ||
![]() |
dfa513da24 | ||
![]() |
dcee9128f9 | ||
![]() |
30a8e1b4c5 | ||
![]() |
a5e2e6ef60 | ||
![]() |
772709d46c | ||
![]() |
71f60c612a | ||
![]() |
e6834990ec | ||
![]() |
17d7ed5a2b | ||
![]() |
10bf70c663 | ||
![]() |
8c14820a38 | ||
![]() |
63772f289d | ||
![]() |
8d5aec030c | ||
![]() |
280547ad01 | ||
![]() |
d01d57037e | ||
![]() |
48279699eb | ||
![]() |
b26e287a62 | ||
![]() |
66289cb3f3 | ||
![]() |
5bfe0179b2 | ||
![]() |
b9b5b3a442 | ||
![]() |
402dd9d917 | ||
![]() |
7d332aada4 | ||
![]() |
df8f634ede | ||
![]() |
fcd0167ee7 | ||
![]() |
8cd330e5fb | ||
![]() |
77d8ef50b3 | ||
![]() |
4d480e204a | ||
![]() |
a6486fc233 | ||
![]() |
655bc5c05e | ||
![]() |
3dfd0d22bb | ||
![]() |
c56c2b0dd9 | ||
![]() |
01a43e04e1 | ||
![]() |
2ad2e06754 | ||
![]() |
20d1813793 | ||
![]() |
534e718925 | ||
![]() |
9fc5b97de8 | ||
![]() |
684fadd2d2 | ||
![]() |
b66fd18380 | ||
![]() |
d1d8ef916e | ||
![]() |
c9a53fa2b2 | ||
![]() |
93d1976a14 | ||
![]() |
5b07e6424a | ||
![]() |
ecec3d2006 | ||
![]() |
f99bc5ba41 | ||
![]() |
9aae53bfb7 | ||
![]() |
59700dcd91 | ||
![]() |
13e1ab231f | ||
![]() |
8fd10dd2d1 | ||
![]() |
271036b527 | ||
![]() |
66ca1942b3 | ||
![]() |
87db689ea9 | ||
![]() |
525f78caca | ||
![]() |
0e38b1ada8 | ||
![]() |
50da308553 | ||
![]() |
c11de64a35 | ||
![]() |
d232acb85e | ||
![]() |
9cfbdd3545 | ||
![]() |
cdc6210160 | ||
![]() |
c866748de3 | ||
![]() |
af869583e3 | ||
![]() |
756cf7c0a6 | ||
![]() |
a839f7d56f | ||
![]() |
06bf11b64e | ||
![]() |
626a9cbc6a |
BIN
.github/cookies-chrome.png
vendored
Normal file
BIN
.github/cookies-chrome.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 480 KiB |
BIN
.github/cookies-firefox.png
vendored
Normal file
BIN
.github/cookies-firefox.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 439 KiB |
6
.github/duplicate_issue.md
vendored
6
.github/duplicate_issue.md
vendored
@@ -1,7 +1,7 @@
|
||||
Duplicate of #{{ firstIssueWithTitle }}
|
||||
Duplicate of #{{ chosenIssue.number }}
|
||||
|
||||
Hi @{{ payload.sender.login }},
|
||||
|
||||
This issue looks similar to #{{ firstIssueWithTitle }}.
|
||||
This issue looks similar to #{{ chosenIssue.number }}.
|
||||
|
||||
To prevent issue tracker clutter, this issue will now be closed. If you feel this issue isn't a duplicate of #{{ firstIssueWithTitle }}, then feel free to re-open this issue.
|
||||
To prevent issue tracker clutter, this issue will now be closed. If you feel this issue isn't a duplicate of #{{ chosenIssue.number }}, then feel free to post a comment on this issue stating why it's not a duplicate. Your comment will automatically re-open this issue.
|
||||
|
2
.github/no_information_provided.md
vendored
2
.github/no_information_provided.md
vendored
@@ -1,6 +1,6 @@
|
||||
Hi @{{ payload.sender.login }},
|
||||
|
||||
You've created an issue, but haven't provided any details to allow the community to assist you. To prevent issue tracker clutter, this issue will now be closed. Please provide the information needed below and then re-open the issue.
|
||||
You've created an issue, but haven't provided any details to allow the community to assist you. To prevent issue tracker clutter, this issue will now be closed. Please provide the information needed below and your comment will automatically re-open this issue.
|
||||
|
||||
Provide a description of the feature request or bug, the more details the better.
|
||||
If you are experiencing an issue with a tracker, a **full enhanced log must be included**. Instructions for obtaining logs are here: https://github.com/Jackett/Jackett#troubleshooting
|
||||
|
3
.github/no_response.md
vendored
Normal file
3
.github/no_response.md
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
Hi @{{ payload.data.user.login }},
|
||||
|
||||
No response has been received for {{ days }} days. To prevent issue tracker clutter, this issue will now be closed. To re-open the issue, please provide the information requested and the issue will automatically re-open.
|
7
.github/pull_request_readme.md
vendored
Normal file
7
.github/pull_request_readme.md
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
Hi @{{ payload.pull_request.user.login }},
|
||||
|
||||
Thanks for your contribution to Jackett!
|
||||
|
||||
If you are adding a new indexer, please ensure that you've added it to the readme as well
|
||||
|
||||
A human will be along soon to review
|
2
.gitignore
vendored
2
.gitignore
vendored
@@ -199,3 +199,5 @@ FakesAssemblies/
|
||||
/Artifacts
|
||||
/TestResults
|
||||
*.DS_Store
|
||||
.idea/
|
||||
launchSettings.json
|
||||
|
@@ -2,8 +2,8 @@
|
||||
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
||||
|
||||
#define MyAppName "Jackett"
|
||||
#define MyAppVersion GetFileVersion("BuildOutput\FullFramework\Windows\Jackett\Jackett.Common.dll")
|
||||
#define MyAppPublisher "Jackett Inc."
|
||||
#define MyAppVersion GetFileVersion(MyFileForVersion)
|
||||
#define MyAppPublisher "Jackett"
|
||||
#define MyAppURL "https://github.com/Jackett/Jackett"
|
||||
#define MyAppExeName "JackettTray.exe"
|
||||
|
||||
@@ -22,9 +22,11 @@ AppUpdatesURL={#MyAppURL}
|
||||
DefaultDirName={pf}\{#MyAppName}
|
||||
DefaultGroupName={#MyAppName}
|
||||
DisableProgramGroupPage=yes
|
||||
OutputBaseFilename=Jackett.Installer.Windows
|
||||
SetupIconFile=src\Jackett.Console\jackett.ico
|
||||
UninstallDisplayIcon={commonappdata}\Jackett\JackettConsole.exe
|
||||
OutputBaseFilename={#MyOutputFilename}
|
||||
SetupIconFile=src\Jackett.Tray\jackett.ico
|
||||
UninstallDisplayIcon={commonappdata}\Jackett\{#MyAppExeName}
|
||||
VersionInfoVersion={#MyAppVersion}
|
||||
UninstallDisplayName={#MyAppName}
|
||||
Compression=lzma
|
||||
SolidCompression=yes
|
||||
DisableDirPage=yes
|
||||
@@ -37,9 +39,7 @@ Name: "windowsService"; Description: "Install as a Windows Service"
|
||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
|
||||
|
||||
[Files]
|
||||
Source: "BuildOutput\FullFramework\Windows\Jackett\JackettTray.exe"; DestDir: "{commonappdata}\Jackett"; Flags: ignoreversion
|
||||
Source: "BuildOutput\FullFramework\Windows\Jackett\JackettUpdater.exe"; DestDir: "{commonappdata}\Jackett"; Flags: ignoreversion
|
||||
Source: "BuildOutput\FullFramework\Windows\Jackett\*"; DestDir: "{commonappdata}\Jackett"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
Source: "{#MySourceFolder}\*"; DestDir: "{commonappdata}\Jackett"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
||||
|
||||
[Icons]
|
||||
@@ -48,16 +48,15 @@ Name: "{group}\{cm:UninstallProgram,{#MyAppName}}"; Filename: "{uninstallexe}"
|
||||
Name: "{commondesktop}\{#MyAppName}"; Filename: "{commonappdata}\Jackett\{#MyAppExeName}"; Tasks: desktopicon
|
||||
|
||||
[Run]
|
||||
Filename: "{commonappdata}\Jackett\JackettConsole.exe"; Parameters: "--Uninstall"; Flags: waituntilterminated runhidden;
|
||||
Filename: "{commonappdata}\Jackett\JackettConsole.exe"; Parameters: "--ReserveUrls"; Flags: waituntilterminated runhidden;
|
||||
Filename: "{commonappdata}\Jackett\JackettConsole.exe"; Parameters: "--Install"; Flags: waituntilterminated runhidden; Tasks: windowsService
|
||||
Filename: "{commonappdata}\Jackett\JackettConsole.exe"; Parameters: "--Start"; Flags: waituntilterminated runhidden; Tasks: windowsService
|
||||
Filename: "{commonappdata}\Jackett\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
|
||||
|
||||
[Run]
|
||||
Filename: "{commonappdata}\Jackett\JackettConsole.exe"; Parameters: "--Uninstall"; Flags: waituntilterminated;
|
||||
Filename: "{commonappdata}\Jackett\JackettConsole.exe"; Parameters: "--ReserveUrls"; Flags: waituntilterminated;
|
||||
Filename: "{commonappdata}\Jackett\JackettConsole.exe"; Parameters: "--MigrateSettings"; Flags: waituntilterminated;
|
||||
Filename: "{commonappdata}\Jackett\JackettConsole.exe"; Parameters: "--Install"; Flags: waituntilterminated; Tasks: windowsService
|
||||
Filename: "{commonappdata}\Jackett\JackettConsole.exe"; Parameters: "--Start"; Flags: waituntilterminated; Tasks: windowsService
|
||||
|
||||
[UninstallRun]
|
||||
Filename: "{commonappdata}\Jackett\JackettConsole.exe"; Parameters: "--Uninstall"; Flags: waituntilterminated skipifdoesntexist
|
||||
Filename: "{commonappdata}\Jackett\JackettConsole.exe"; Parameters: "--Uninstall"; Flags: waituntilterminated skipifdoesntexist runhidden
|
||||
Filename: "{sys}\taskkill.exe"; Parameters: "/f /im {#MyAppExeName}"; Flags: waituntilterminated skipifdoesntexist runhidden
|
||||
Filename: "{sys}\taskkill.exe"; Parameters: "/f /im JackettConsole.exe"; Flags: waituntilterminated skipifdoesntexist runhidden
|
||||
|
||||
|
||||
|
60
README.md
60
README.md
@@ -2,7 +2,6 @@
|
||||
|
||||
[](https://github.com/Jackett/Jackett/issues)
|
||||
[](https://github.com/Jackett/Jackett/pulls)
|
||||
[](https://www.bountysource.com/teams/jackett)
|
||||
[](https://ci.appveyor.com/project/Jackett/jackett)
|
||||
[](https://github.com/Jackett/Jackett/releases/latest)
|
||||
[](https://hub.docker.com/r/linuxserver/jackett/)
|
||||
@@ -17,8 +16,8 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
|
||||
|
||||
|
||||
#### Supported Systems
|
||||
* Windows using .NET 4.5.2 [Download here](https://www.microsoft.com/net/framework/versions/net452).
|
||||
* Linux and macOS using Mono 4.6.0 and above. [Download here](http://www.mono-project.com/download/). Earlier versions of mono may work but some trackers may fail to negotiate SSL correctly, and others may cause Jackett to crash when used.
|
||||
* Windows using .NET 4.6.1 or above [Download here](https://www.microsoft.com/net/framework/versions/net461).
|
||||
* Linux and macOS using Mono 5.8 or above. [Download here](http://www.mono-project.com/download/).
|
||||
|
||||
### Supported Public Trackers
|
||||
* 1337x
|
||||
@@ -37,19 +36,23 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
|
||||
* Horrible Subs
|
||||
* Idope
|
||||
* Il Corsaro Nero <!-- maintained by bonny1992 -->
|
||||
* Il Corsaro Blu
|
||||
* Isohunt2
|
||||
* KickAssTorrent
|
||||
* KickAssTorrent (thekat.se clone)
|
||||
* LimeTorrents
|
||||
* MagnetDL
|
||||
* MejorTorrent <!-- maintained by ivandelabeldad -->
|
||||
* NextTorrent
|
||||
* Newpct (aka: tvsinpagar, descargas2020, torrentlocura, torrentrapid, etc)
|
||||
* Nyaa.si
|
||||
* Nyaa-Pantsu
|
||||
* Nyoo
|
||||
* OxTorrent
|
||||
* RARBG
|
||||
* RuTor
|
||||
* ShowRSS
|
||||
* sukebei.Nyaa.si
|
||||
* sukebei-Pantsu
|
||||
* The Pirate Bay
|
||||
* TNTVillage <!-- maintained by bonny1992 -->
|
||||
* Tokyo Toshokan
|
||||
@@ -90,7 +93,6 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
|
||||
* Abnormal
|
||||
* Acid-Lounge
|
||||
* AlphaRatio
|
||||
* Andraste
|
||||
* AnimeBytes
|
||||
* AnimeTorrents
|
||||
* AOX
|
||||
@@ -124,6 +126,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
|
||||
* BroadcastTheNet
|
||||
* BrokenStones
|
||||
* BTNext
|
||||
* BTXpress
|
||||
* Carpathians
|
||||
* CCFBits
|
||||
* CGPeers
|
||||
@@ -157,11 +160,11 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
|
||||
* Fuzer
|
||||
* GayTorrent.ru
|
||||
* GazelleGames
|
||||
* GFTracker
|
||||
* Gfxnews
|
||||
* GFXPeers
|
||||
* GigaTorrents
|
||||
* GimmePeers <!-- maintained by jamesb2147 -->
|
||||
* Girotottent
|
||||
* GODS [![(invite needed)][inviteneeded]](#)
|
||||
* Greek Team
|
||||
* HacheDe
|
||||
@@ -169,6 +172,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
|
||||
* HD-Forever
|
||||
* HD-Only
|
||||
* HD-Space
|
||||
* HD-Spain
|
||||
* HD-Torrents
|
||||
* HD-Bits.com
|
||||
* HDBits
|
||||
@@ -208,7 +212,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
|
||||
* notwhat.cd
|
||||
* Ourbits
|
||||
* Passione Torrent <!-- maintained by bonny1992 -->
|
||||
* PassThePopcorn [![(invite needed)][inviteneeded]](#)
|
||||
* PassThePopcorn
|
||||
* PirateTheNet
|
||||
* PiXELHD
|
||||
* PolishSource
|
||||
@@ -218,8 +222,10 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
|
||||
* Psytorrents
|
||||
* PTFiles
|
||||
* PuntoTorrent
|
||||
* Racing4Everyone (R4E)
|
||||
* Redacted (PassTheHeadphones)
|
||||
* RevolutionTT
|
||||
* RGU
|
||||
* RoDVD
|
||||
* SceneFZ
|
||||
* SceneReactor
|
||||
@@ -236,9 +242,10 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
|
||||
* SportsCult
|
||||
* SportHD
|
||||
* Superbits
|
||||
* Synthesiz3r
|
||||
* Tasmanit
|
||||
* TBPlus
|
||||
* TehConnection.me
|
||||
* TenYardTracker
|
||||
* The Empire
|
||||
* The Geeks
|
||||
* The Horror Charnel
|
||||
@@ -249,7 +256,6 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
|
||||
* The Show
|
||||
* The Vault
|
||||
* The-Torrents
|
||||
* TenYardTracker
|
||||
* Torrent Network
|
||||
* Torrent Sector Crew
|
||||
* Torrent.LT
|
||||
@@ -266,7 +272,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
|
||||
* Torrents.Md
|
||||
* TorrentSeeds
|
||||
* Torrent-Syndikat
|
||||
* TorrentWTF
|
||||
* TOrrent-tuRK (TORK)
|
||||
* TorViet
|
||||
* ToTheGlory
|
||||
* TranceTraffic
|
||||
@@ -289,6 +295,13 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
|
||||
|
||||
Trackers marked with [![(invite needed)][inviteneeded]](#) have no active maintainer and are missing features or are broken. If you have an invite for them please send it to kaso1717 -at- gmail.com to get them fixed/improved.
|
||||
|
||||
### Aggregate indexers
|
||||
|
||||
A special "all" indexer is available at `/api/v2.0/indexers/all/results/torznab/api`.
|
||||
It will query all configured indexers and return the combined results.
|
||||
|
||||
To get all Jackett indexers including their capabilities you can use `t=indexers` on the all indexer. To get only configured/unconfigured indexers you can also add `configured=true/false` as query parameter.
|
||||
|
||||
## Installation on Windows
|
||||
|
||||
We recommend you install Jackett as a Windows service using the supplied installer. You may also download the zipped version if you would like to configure everything manually.
|
||||
@@ -307,7 +320,7 @@ When installed as a service the tray icon acts as a way to open/start/stop Jacke
|
||||
Jackett can also be run from the command line if you would like to see log messages (Ensure the server isn't already running from the tray/service). This can be done by using "JackettConsole.exe" (for Command Prompt), found in the Jackett data folder: "%ProgramData%\Jackett".
|
||||
|
||||
## Installation on Linux
|
||||
1. Install [Mono 4.6](http://www.mono-project.com/download/#download-lin) or better (using the latest stable release for your distribution is recommended)
|
||||
1. Install [Mono 5.8](http://www.mono-project.com/download/#download-lin) or better (using the latest stable release is recommended)
|
||||
* Follow the instructions on the mono website and install the `mono-devel` and the `ca-certificates-mono` packages.
|
||||
* On Red Hat/CentOS/openSUSE/Fedora the `mono-locale-extras` package is also required.
|
||||
2. Install libcurl:
|
||||
@@ -320,10 +333,12 @@ Detailed instructions for [Ubuntu 14.x](http://www.htpcguides.com/install-jacket
|
||||
|
||||
If you want to run it with a user without a /home directory you need to add `Environment=XDG_CONFIG_HOME=/path/to/folder` to your systemd file, this folder will be used to store your config files.
|
||||
|
||||
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 macOS
|
||||
|
||||
### Prerequisites
|
||||
Install [Mono 4.6](http://www.mono-project.com/download/#download-mac) or better (using the latest pkg installer is recommended).
|
||||
Install [Mono 5.8](http://www.mono-project.com/download/#download-mac) or better (using the latest pkg installer is recommended).
|
||||
* Setup ssl support by running `curl -sS https://curl.haxx.se/ca/cacert.pem | cert-sync --user /dev/stdin`
|
||||
|
||||
### Install as service
|
||||
@@ -385,6 +400,27 @@ Please supply as much information about the problem you are experiencing as poss
|
||||
## Contributing
|
||||
All contributions are welcome just send a pull request. Jackett's framework allows our team (and any other volunteering dev) to implement new trackers in an hour or two. If you'd like support for a new tracker but are not a developer then feel free to leave a request on the [issues page](https://github.com/Jackett/Jackett/issues). It is recommended to use Visual Studio 2017 when making code changes in this project. You can download the community version for free [here](https://www.visualstudio.com/downloads/).
|
||||
|
||||
|
||||
## Building from source
|
||||
|
||||
### Windows
|
||||
* Install the .NET Core [SDK](https://www.microsoft.com/net/download/windows)
|
||||
* Open the Jackett solution in Visual Studio 2017 (version 15.7 or above)
|
||||
* Right click on the Jackett solution and click 'Rebuild Solution' to restore nuget packages
|
||||
* Select Jackett.Console as startup project
|
||||
* Build/Start the project
|
||||
|
||||
### Linux
|
||||
|
||||
```bash
|
||||
sudo apt install mono-complete nuget msbuild # install build tools (debian/ubuntu)
|
||||
git clone https://github.com/Jackett/Jackett.git
|
||||
cd Jackett/src
|
||||
nuget restore Jackett.sln # prepare dependencies
|
||||
msbuild Jackett.Console/Jackett.Console.csproj /t:Build /p:Configuration=Debug # compile
|
||||
mono Jackett.Console/bin/Debug/JackettConsole.exe # run jackett
|
||||
```
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||
|
@@ -1,4 +1,4 @@
|
||||
version: 0.8.{build}
|
||||
version: 0.9.{build}
|
||||
skip_tags: true
|
||||
image: Visual Studio 2017
|
||||
configuration: Release
|
||||
@@ -27,6 +27,7 @@ deploy:
|
||||
description: $(release_description)
|
||||
auth_token:
|
||||
secure: hOg+16YTIbq4kO9u4D1YVOTbWDqgCX6mAQYMbnmBBSw2CiUsZh7OKbupoUb3FtWa
|
||||
artifact: /^(?:(?![Ee]xperimental).)*$/
|
||||
draft: true
|
||||
on:
|
||||
branch: master
|
||||
|
170
build.cake
170
build.cake
@@ -6,7 +6,7 @@
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
var target = Argument("target", "Default");
|
||||
var configuration = Argument("configuration", "Release");
|
||||
var configuration = Argument("configuration", "Debug");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// PREPARATION
|
||||
@@ -36,8 +36,8 @@ Task("Clean")
|
||||
.IsDependentOn("Info")
|
||||
.Does(() =>
|
||||
{
|
||||
CleanDirectories("./src/**/obj" + configuration);
|
||||
CleanDirectories("./src/**/bin" + configuration);
|
||||
CleanDirectories("./src/**/obj");
|
||||
CleanDirectories("./src/**/bin");
|
||||
CleanDirectories("./BuildOutput");
|
||||
CleanDirectories("./" + artifactsDirName);
|
||||
CleanDirectories("./" + testResultsDirName);
|
||||
@@ -56,7 +56,11 @@ Task("Build")
|
||||
.IsDependentOn("Restore-NuGet-Packages")
|
||||
.Does(() =>
|
||||
{
|
||||
MSBuild("./src/Jackett.sln", settings => settings.SetConfiguration(configuration));
|
||||
var buildSettings = new MSBuildSettings()
|
||||
.SetConfiguration(configuration)
|
||||
.UseToolVersion(MSBuildToolVersion.VS2017);
|
||||
|
||||
MSBuild("./src/Jackett.sln", buildSettings);
|
||||
});
|
||||
|
||||
Task("Run-Unit-Tests")
|
||||
@@ -84,9 +88,7 @@ Task("Copy-Files-Full-Framework")
|
||||
var windowsOutput = windowsBuildFullFramework + "/Jackett";
|
||||
|
||||
CopyDirectory("./src/Jackett.Console/bin/" + configuration, windowsOutput);
|
||||
CopyFiles("./src/Jackett.Service/bin/" + configuration + "/JackettService.*", windowsOutput);
|
||||
CopyFiles("./src/Jackett.Tray/bin/" + configuration + "/JackettTray.*", windowsOutput);
|
||||
CopyFiles("./src/Jackett.Updater/bin/" + configuration + "/JackettUpdater.*", 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);
|
||||
@@ -115,49 +117,118 @@ Task("Check-Packaging-Platform")
|
||||
}
|
||||
});
|
||||
|
||||
Task("Package-Windows-Installer-Full-Framework")
|
||||
.IsDependentOn("Check-Packaging-Platform")
|
||||
.Does(() =>
|
||||
{
|
||||
InnoSetup("./Installer.iss", new InnoSetupSettings {
|
||||
OutputDirectory = workingDir + "/" + artifactsDirName
|
||||
});
|
||||
});
|
||||
|
||||
Task("Package-Files-Full-Framework-Windows")
|
||||
.IsDependentOn("Check-Packaging-Platform")
|
||||
.Does(() =>
|
||||
{
|
||||
Zip(windowsBuildFullFramework, $"./{artifactsDirName}/Jackett.Binaries.Windows.zip");
|
||||
Information(@"Full Framework Windows Binaries Zipping Completed");
|
||||
});
|
||||
|
||||
Task("Package-Files-Full-Framework-Mono")
|
||||
.IsDependentOn("Check-Packaging-Platform")
|
||||
.Does(() =>
|
||||
{
|
||||
var cygMonoBuildPath = RelativeWinPathToCygPath(monoBuildFullFramework);
|
||||
var tarFileName = "Jackett.Binaries.Mono.tar";
|
||||
var tarArguments = @"-cvf " + cygMonoBuildPath + "/" + tarFileName + " -C " + cygMonoBuildPath + " Jackett --mode ='755'";
|
||||
var gzipArguments = @"-k " + cygMonoBuildPath + "/" + tarFileName;
|
||||
|
||||
RunCygwinCommand("Tar", tarArguments);
|
||||
RunCygwinCommand("Gzip", gzipArguments);
|
||||
|
||||
MoveFile($"{monoBuildFullFramework}/{tarFileName}.gz", $"./{artifactsDirName}/{tarFileName}.gz");
|
||||
Gzip(monoBuildFullFramework, $"./{artifactsDirName}", "Jackett", "Jackett.Binaries.Mono.tar.gz");
|
||||
Information(@"Full Framework Mono Binaries Gzip Completed");
|
||||
});
|
||||
|
||||
Task("Package-Full-Framework")
|
||||
.IsDependentOn("Package-Windows-Installer-Full-Framework")
|
||||
.IsDependentOn("Package-Files-Full-Framework-Windows")
|
||||
.IsDependentOn("Package-Files-Full-Framework-Mono")
|
||||
.Does(() =>
|
||||
{
|
||||
Information("Full Framwork Packaging Completed");
|
||||
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")
|
||||
.Does(() =>
|
||||
{
|
||||
string serverProjectPath = "./src/Jackett.Server/Jackett.Server.csproj";
|
||||
string buildOutputPath = "./BuildOutput/Experimental/net461/win7-x86/Jackett";
|
||||
|
||||
DotNetCorePublish(serverProjectPath, "net461", "win7-x86");
|
||||
|
||||
CopyFiles("./src/Jackett.Service/bin/" + configuration + "/JackettService.*", buildOutputPath);
|
||||
CopyFiles("./src/Jackett.Tray/bin/" + configuration + "/JackettTray.*", buildOutputPath);
|
||||
CopyFiles("./src/Jackett.Updater/bin/" + configuration + "/net461" + "/JackettUpdater.*", buildOutputPath); //builds against multiple frameworks
|
||||
|
||||
Zip("./BuildOutput/Experimental/net461/win7-x86", $"./{artifactsDirName}/Jackett.Binaries.Windows.zip");
|
||||
|
||||
//InnoSetup
|
||||
string sourceFolder = MakeAbsolute(Directory(buildOutputPath)).ToString();
|
||||
|
||||
InnoSetupSettings settings = new InnoSetupSettings();
|
||||
settings.OutputDirectory = workingDir + "/" + artifactsDirName;
|
||||
settings.Defines = new Dictionary<string, string>
|
||||
{
|
||||
{ "MyFileForVersion", sourceFolder + "/Jackett.Common.dll" },
|
||||
{ "MySourceFolder", sourceFolder },
|
||||
{ "MyOutputFilename", "Jackett.Installer.Windows" },
|
||||
};
|
||||
|
||||
InnoSetup("./Installer.iss", settings);
|
||||
});
|
||||
|
||||
Task("Experimental-Kestrel-Mono-Full-Framework")
|
||||
.IsDependentOn("Kestrel-Full-Framework")
|
||||
.Does(() =>
|
||||
{
|
||||
string serverProjectPath = "./src/Jackett.Server/Jackett.Server.csproj";
|
||||
string buildOutputPath = "./BuildOutput/Experimental/net461/linux-x64/Jackett";
|
||||
|
||||
DotNetCorePublish(serverProjectPath, "net461", "linux-x64");
|
||||
|
||||
CopyFiles("./src/Jackett.Updater/bin/" + configuration + "/net461" + "/JackettUpdater.*", buildOutputPath); //builds against multiple frameworks
|
||||
|
||||
//There is an issue with Mono 5.8 (fixed in Mono 5.12) where its expecting to use its own patched version of System.Net.Http.dll, instead of the version supplied in folder
|
||||
//https://github.com/dotnet/corefx/issues/19914
|
||||
//https://bugzilla.xamarin.com/show_bug.cgi?id=60315
|
||||
//The workaround is to delete System.Net.Http.dll and patch the .exe.config file
|
||||
|
||||
DeleteFile(buildOutputPath + "/System.Net.Http.dll");
|
||||
|
||||
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");
|
||||
});
|
||||
|
||||
Task("Experimental-DotNetCore")
|
||||
.IsDependentOn("Kestrel-Full-Framework")
|
||||
.Does(() =>
|
||||
{
|
||||
string serverProjectPath = "./src/Jackett.Server/Jackett.Server.csproj";
|
||||
|
||||
DotNetCorePublish(serverProjectPath, "netcoreapp2.1", "win-x86");
|
||||
DotNetCorePublish(serverProjectPath, "netcoreapp2.1", "linux-x64");
|
||||
DotNetCorePublish(serverProjectPath, "netcoreapp2.1", "osx-x64");
|
||||
|
||||
Zip("./BuildOutput/Experimental/netcoreapp2.1/win-x86", $"./{artifactsDirName}/Experimental.netcoreapp.win-x86.zip");
|
||||
Zip("./BuildOutput/Experimental/netcoreapp2.1/osx-x64", $"./{artifactsDirName}/Experimental.netcoreapp.osx-x64.zip");
|
||||
Gzip("./BuildOutput/Experimental/netcoreapp2.1/linux-x64", $"./{artifactsDirName}", "Jackett", "Experimental.netcoreapp.linux-x64.tar.gz");
|
||||
});
|
||||
|
||||
Task("Experimental")
|
||||
.IsDependentOn("Experimental-Kestrel-Windows-Full-Framework")
|
||||
.IsDependentOn("Experimental-Kestrel-Mono-Full-Framework")
|
||||
//.IsDependentOn("Experimental-DotNetCore")
|
||||
.Does(() =>
|
||||
{
|
||||
Information("Experimental builds completed");
|
||||
});
|
||||
|
||||
Task("Appveyor-Push-Artifacts")
|
||||
.IsDependentOn("Package-Full-Framework")
|
||||
.IsDependentOn("Experimental")
|
||||
.Does(() =>
|
||||
{
|
||||
if (AppVeyor.IsRunningOnAppVeyor)
|
||||
@@ -263,10 +334,35 @@ private void RunCygwinCommand(string utility, string utilityArguments)
|
||||
private string RelativeWinPathToCygPath(string relativePath)
|
||||
{
|
||||
var cygdriveBase = "/cygdrive/" + workingDir.ToString().Replace(":", "").Replace("\\", "/");
|
||||
var cygPath = cygdriveBase + relativePath.Replace(".", "");
|
||||
var cygPath = cygdriveBase + relativePath.TrimStart('.');
|
||||
return cygPath;
|
||||
}
|
||||
|
||||
private void Gzip(string sourceFolder, string outputDirectory, string tarCdirectoryOption, string outputFileName)
|
||||
{
|
||||
var cygSourcePath = RelativeWinPathToCygPath(sourceFolder);
|
||||
var tarFileName = outputFileName.Remove(outputFileName.Length - 3, 3);
|
||||
var tarArguments = @"-cvf " + cygSourcePath + "/" + tarFileName + " -C " + cygSourcePath + $" {tarCdirectoryOption} --mode ='755'";
|
||||
var gzipArguments = @"-k " + cygSourcePath + "/" + tarFileName;
|
||||
|
||||
RunCygwinCommand("Tar", tarArguments);
|
||||
RunCygwinCommand("Gzip", gzipArguments);
|
||||
|
||||
MoveFile($"{sourceFolder}/{tarFileName}.gz", $"{outputDirectory}/{tarFileName}.gz");
|
||||
}
|
||||
|
||||
private void DotNetCorePublish(string projectPath, string framework, string runtime)
|
||||
{
|
||||
var settings = new DotNetCorePublishSettings
|
||||
{
|
||||
Framework = framework,
|
||||
Runtime = runtime,
|
||||
OutputDirectory = $"./BuildOutput/Experimental/{framework}/{runtime}/Jackett"
|
||||
};
|
||||
|
||||
DotNetCorePublish(projectPath, settings);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// TASK TARGETS
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
@@ -87,6 +87,7 @@ function loadJackettSettings() {
|
||||
$("#jackett-prerelease").attr('checked', data.prerelease);
|
||||
$("#jackett-logging").attr('checked', data.logging);
|
||||
$("#jackett-omdbkey").val(data.omdbkey);
|
||||
$("#jackett-omdburl").val(data.omdburl);
|
||||
var password = data.password;
|
||||
$("#jackett-adminpwd").val(password);
|
||||
if (password != null && password != '') {
|
||||
@@ -221,7 +222,7 @@ function displayUnconfiguredIndexersList() {
|
||||
}
|
||||
}).fail(function (data) {
|
||||
if(data.responseJSON.error !== undefined) {
|
||||
doNotify("An error occured while configuring this indexer<br /><b>" + data.responseJSON.error + "</b><br /><i><a href=\"https://github.com/Jackett/Jackett/issues/new?title=[" + indexerId + "] " + data.responseJSON.error + " (Config)\" target=\"_blank\">Click here to open an issue on Github for this indexer.</a><i>", "danger", "glyphicon glyphicon-alert", false);
|
||||
doNotify("An error occured while configuring this indexer<br /><b>" + data.responseJSON.error + "</b><br /><i><a href=\"https://github.com/Jackett/Jackett/issues/new?title=[" + indexerId + "] " + data.responseJSON.error + " (Config)\" target=\"_blank\">Click here to open an issue on GitHub for this indexer.</a><i>", "danger", "glyphicon glyphicon-alert", false);
|
||||
} else {
|
||||
doNotify("An error occured while configuring this indexer, is Jackett server running ?", "danger", "glyphicon glyphicon-alert");
|
||||
}
|
||||
@@ -444,7 +445,7 @@ function testIndexer(id, notifyResult) {
|
||||
}).fail(function (data) {
|
||||
updateTestState(id, "error", data.error, indexers);
|
||||
if(data.responseJSON.error !== undefined && notifyResult) {
|
||||
doNotify("An error occured while testing this indexer<br /><b>" + data.responseJSON.error + "</b><br /><i><a href=\"https://github.com/Jackett/Jackett/issues/new?title=[" + id + "] " + data.responseJSON.error + " (Test)\" target=\"_blank\">Click here to open an issue on Github for this indexer.</a><i>", "danger", "glyphicon glyphicon-alert", false);
|
||||
doNotify("An error occured while testing this indexer<br /><b>" + data.responseJSON.error + "</b><br /><i><a href=\"https://github.com/Jackett/Jackett/issues/new?title=[" + id + "] " + data.responseJSON.error + " (Test)\" target=\"_blank\">Click here to open an issue on GitHub for this indexer.</a><i>", "danger", "glyphicon glyphicon-alert", false);
|
||||
} else {
|
||||
doNotify("An error occured while testing indexers, please take a look at indexers with failed test for more informations.", "danger", "glyphicon glyphicon-alert");
|
||||
}
|
||||
@@ -497,10 +498,14 @@ function populateConfigItems(configForm, config) {
|
||||
hasReacaptcha = true;
|
||||
captchaItem = config[i];
|
||||
}
|
||||
else if (config[i].id === 'cookieheader' && hasReacaptcha) { // inject cookie into captcha item
|
||||
captchaItem.cookieheader = config[i].value;
|
||||
console.log(captchaItem);
|
||||
}
|
||||
}
|
||||
|
||||
var setupItemTemplate = Handlebars.compile($("#setup-item").html());
|
||||
if (hasReacaptcha && !window.jackettIsLocal) {
|
||||
if (hasReacaptcha && !window.jackettIsLocal && false) { // disable this for now, use inline cookie (below)
|
||||
var setupValueTemplate = Handlebars.compile($("#setup-item-nonlocalrecaptcha").html());
|
||||
captchaItem.value_element = setupValueTemplate(captchaItem);
|
||||
var template = setupItemTemplate(captchaItem);
|
||||
@@ -509,11 +514,22 @@ function populateConfigItems(configForm, config) {
|
||||
|
||||
for (var i = 0; i < config.length; i++) {
|
||||
var item = config[i];
|
||||
var setupValueTemplate = Handlebars.compile($("#setup-item-" + item.type).html());
|
||||
item.value_element = setupValueTemplate(item);
|
||||
var template = setupItemTemplate(item);
|
||||
$formItemContainer.append(template);
|
||||
if ((item.id === 'username' || item.id === 'password') && hasReacaptcha) {
|
||||
continue; // skip username/password if there's a recaptcha
|
||||
}
|
||||
if (item.type != 'recaptcha') {
|
||||
var setupValueTemplate = Handlebars.compile($("#setup-item-" + item.type).html());
|
||||
item.value_element = setupValueTemplate(item);
|
||||
var template = setupItemTemplate(item);
|
||||
$formItemContainer.append(template);
|
||||
}
|
||||
if (item.type === 'recaptcha') {
|
||||
// inject cookie dialog until recaptcha can be solved again
|
||||
var setupValueTemplate = Handlebars.compile($("#setup-item-nonlocalrecaptcha").html());
|
||||
captchaItem.value_element = setupValueTemplate(captchaItem);
|
||||
var template = setupItemTemplate(captchaItem);
|
||||
$formItemContainer.append(template);
|
||||
/*
|
||||
var jackettrecaptcha = $('.jackettrecaptcha');
|
||||
jackettrecaptcha.data("version", item.version);
|
||||
switch (item.version) {
|
||||
@@ -543,6 +559,7 @@ function populateConfigItems(configForm, config) {
|
||||
});
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -634,7 +651,7 @@ function populateSetupForm(indexerId, name, config, caps, link, alternativesitel
|
||||
}
|
||||
}).fail(function (data) {
|
||||
if(data.responseJSON.error !== undefined) {
|
||||
doNotify("An error occured while updating this indexer<br /><b>" + data.responseJSON.error + "</b><br /><i><a href=\"https://github.com/Jackett/Jackett/issues/new?title=[" + indexerId + "] " + data.responseJSON.error + " (Config)\" target=\"_blank\">Click here to open an issue on Github for this indexer.</a><i>", "danger", "glyphicon glyphicon-alert", false);
|
||||
doNotify("An error occured while updating this indexer<br /><b>" + data.responseJSON.error + "</b><br /><i><a href=\"https://github.com/Jackett/Jackett/issues/new?title=[" + indexerId + "] " + data.responseJSON.error + " (Config)\" target=\"_blank\">Click here to open an issue on GitHub for this indexer.</a><i>", "danger", "glyphicon glyphicon-alert", false);
|
||||
} else {
|
||||
doNotify("An error occured while updating this indexer, request to Jackett server failed, is server running ?", "danger", "glyphicon glyphicon-alert");
|
||||
}
|
||||
@@ -1134,6 +1151,7 @@ function bindUIButtons() {
|
||||
var jackett_prerelease = $("#jackett-prerelease").is(':checked');
|
||||
var jackett_logging = $("#jackett-logging").is(':checked');
|
||||
var jackett_omdb_key = $("#jackett-omdbkey").val();
|
||||
var jackett_omdb_url = $("#jackett-omdburl").val();
|
||||
|
||||
var jackett_proxy_url = $("#jackett-proxy-url").val();
|
||||
var jackett_proxy_type = $("#jackett-proxy-type").val();
|
||||
@@ -1150,6 +1168,7 @@ function bindUIButtons() {
|
||||
logging: jackett_logging,
|
||||
basepathoverride: jackett_basepathoverride,
|
||||
omdbkey: jackett_omdb_key,
|
||||
omdburl: jackett_omdb_url,
|
||||
proxy_type: jackett_proxy_type,
|
||||
proxy_url: jackett_proxy_url,
|
||||
proxy_port: jackett_proxy_port,
|
||||
|
@@ -30,7 +30,7 @@
|
||||
<script type="text/javascript" src="../bootstrap/bootstrap.min.js?changed=2017083001"></script>
|
||||
<script type="text/javascript" src="../libs/bootstrap-notify.js?changed=2017083001"></script>
|
||||
<script type="text/javascript" src="../libs/bootstrap-multiselect.js?changed=2017083001"></script>
|
||||
<script type="text/javascript" src="https://www.google.com/recaptcha/api.js?render=explicit" async defer></script>
|
||||
<!--<script type="text/javascript" src="https://www.google.com/recaptcha/api.js?render=explicit" async defer></script>-->
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="../bootstrap/bootstrap.min.css?changed=2017083001">
|
||||
<link rel="stylesheet" type="text/css" href="../animate.css?changed=2017083001">
|
||||
@@ -94,11 +94,11 @@
|
||||
<hr />
|
||||
<h3>Jackett Configuration</h3>
|
||||
<div class="text-center">
|
||||
<div class="btn-group">
|
||||
<div class="btn-toolbar">
|
||||
<button id="change-jackett-port" class="btn btn-primary btn-sm">
|
||||
<i class="fa fa-wrench"></i> Apply server settings <span class="glyphicon glyphicon-ok-wrench" aria-hidden="true"></span>
|
||||
</button>
|
||||
<button id="view-jackett-logs" class="btn btn-danger btn-sm">
|
||||
<button id="view-jackett-logs" class="btn btn-success btn-sm">
|
||||
<i class="fa fa-rss"></i> View logs <span class="glyphicon glyphicon-ok-wrench" aria-hidden="true"></span>
|
||||
</button>
|
||||
<button id="trigger-updater" class="btn btn-warning btn-sm">
|
||||
@@ -177,6 +177,10 @@
|
||||
<span class="input-header">OMDB API key: </span>
|
||||
<input id="jackett-omdbkey" class="form-control input-right" type="text" value="" placeholder="">
|
||||
</div>
|
||||
<div class="input-area">
|
||||
<span class="input-header">OMDB API Url: </span>
|
||||
<input id="jackett-omdburl" class="form-control input-right" type="text" value="" placeholder="Blank for default">
|
||||
</div>
|
||||
<hr />
|
||||
<div id="footer">
|
||||
<a href="https://github.com/Jackett/Jackett" target="_blank" title="Jackett on GitHub">Jackett</a> Version <span id="app-version"></span>
|
||||
@@ -189,7 +193,7 @@
|
||||
<div class="setup-item-recaptcha">
|
||||
<p>This site requires you to solve a ReCaptcha. It's no longer possible to solve the captcha in Jackett. Please enter the cookie for the site manually. <a href="https://github.com/Jackett/Jackett/wiki/Finding-cookies" target="_blank">See here</a> on how get the cookies.</p>
|
||||
<div class="setup-item-label">Full cookie header</div>
|
||||
<input class="form-control" type="text" value="" />
|
||||
<input class="form-control" type="text" value="{{cookieheader}}" />
|
||||
</div>
|
||||
</script>
|
||||
<script id="setup-item" type="text/x-handlebars-template">
|
||||
@@ -659,6 +663,6 @@
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="../libs/api.js?changed=2017083001"></script>
|
||||
<script type="text/javascript" src="../custom.js?changed=2017110602"></script>
|
||||
<script type="text/javascript" src="../custom.js?changed=20180709"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@@ -120,11 +120,17 @@
|
||||
paths:
|
||||
# present trending results if there are no search parms supplied
|
||||
- path: "{{if .Keywords}}/search/{{ .Keywords}}/1/{{else}}/trending{{end}}"
|
||||
keywordsfilters:
|
||||
- name: replace # use this as a workaround till #893 is implemented
|
||||
args: ["Greys Anatomy", "Grey's Anatomy"]
|
||||
rows:
|
||||
selector: tr:has(a[href^="/torrent/"])
|
||||
fields:
|
||||
title:
|
||||
selector: td[class^="coll-1"] a[href^="/torrent/"]
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["Grey's Anatomy", "Greys Anatomy"]
|
||||
category:
|
||||
optional: true
|
||||
selector: td[class^="coll-1"] a[href^="/sub/"]
|
||||
|
@@ -48,9 +48,6 @@
|
||||
- selector: span.errormsg
|
||||
test:
|
||||
path: index.php
|
||||
|
||||
download:
|
||||
selector: a[href^="download.php?id="]
|
||||
|
||||
search:
|
||||
paths:
|
||||
|
@@ -1,4 +1,4 @@
|
||||
---
|
||||
---
|
||||
site: Bittorrentfiles
|
||||
name: Bittorrentfiles
|
||||
description: "Bittorrentfiles is a Private GERMAN tracker"
|
||||
@@ -135,22 +135,22 @@
|
||||
selector: a[href^="/download.php"]
|
||||
attribute: href
|
||||
files:
|
||||
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(5) > a
|
||||
selector: td:nth-child(7)
|
||||
grabs:
|
||||
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(2)
|
||||
selector: td:nth-child(6)
|
||||
size:
|
||||
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(6)
|
||||
selector: td:nth-child(8)
|
||||
filters:
|
||||
- name: replace
|
||||
args: [".", ""]
|
||||
- name: replace
|
||||
args: [",", "."]
|
||||
seeders:
|
||||
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(2)
|
||||
selector: td:nth-child(3) > a
|
||||
leechers:
|
||||
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(3)
|
||||
selector: td:nth-child(4)
|
||||
date:
|
||||
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(10)
|
||||
selector: td:nth-child(9)
|
||||
filters:
|
||||
- name: split
|
||||
args: ["by", 0]
|
||||
@@ -168,4 +168,4 @@
|
||||
uploadvolumefactor:
|
||||
case:
|
||||
img[alt="2xU"]: "2"
|
||||
"*": "1"
|
||||
"*": "1"
|
||||
|
@@ -38,10 +38,13 @@
|
||||
type: info
|
||||
label: Category Id Note
|
||||
default: "You can filter your searches by using any of the following category numbers (comma delimited):<br>1 :Anime - Sub<br>2 :Anime - Raw<br>3 :Anime - Dub<br>4 :LA - Sub<br>5 :LA - Raw<br>6 :Light Novel<br>7 :Manga - TLed<br>8 :Manga - Raw<br>9 :♫ - Lossy<br>10 :♫ - Lossless<br>11 :♫ - Video<br>12 :Games<br>13 :Applications<br>14 :Pictures<br>15 :Adult Video<br>16 :Other"
|
||||
|
||||
- name: lang-id
|
||||
type: text
|
||||
label: Language Id
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: "?{{if .Config.cat-id}}id={{.Config.cat-id }}&{{else}}{{end}}q={{if .Keywords}}{{.Keywords}}{{else}}{{end}}"
|
||||
- path: "?{{if .Config.cat-id}}id={{.Config.cat-id }}&{{else}}{{end}}{{if .Config.lang-id}}lang_id={{.Config.lang-id}}&{{else}}{{end}}q={{if .Keywords}}{{.Keywords}}{{else}}{{end}}"
|
||||
rows:
|
||||
selector: div.table-responsive > table > tbody > tr
|
||||
fields:
|
||||
|
@@ -10,23 +10,10 @@
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
# Japanese
|
||||
- {id: 1, cat: Movies, desc: "jMovies"}
|
||||
- {id: 2, cat: TV, desc: "TV Shows"}
|
||||
- {id: 3, cat: TV/Other, desc: "Variety Shows"}
|
||||
|
||||
# Korean
|
||||
- {id: 6, cat: Movies, desc: "kMovies"}
|
||||
- {id: 4, cat: TV, desc: "TV Shows"}
|
||||
- {id: 14, cat: TV/Other, desc: "Variety Shows"}
|
||||
|
||||
# Chinese
|
||||
- {id: 8, cat: Movies, desc: "cMovies"}
|
||||
- {id: 9, cat: TV, desc: "TV Shows"}
|
||||
- {id: 13, cat: TV/Other, desc: "Variety Shows"}
|
||||
|
||||
# Adult
|
||||
- {id: 13, cat: XXX, desc: "Adult"}
|
||||
- {id: 13, cat: Movies, desc: "Movie"}
|
||||
- {id: 11, cat: TV, desc: "TV-Show"}
|
||||
- {id: 5, cat: TV/Other, desc: "Variety Show"}
|
||||
- {id: 24, cat: XXX, desc: "Adult"}
|
||||
|
||||
modes:
|
||||
search: [q]
|
||||
@@ -51,9 +38,6 @@
|
||||
test:
|
||||
path: index.php
|
||||
|
||||
download:
|
||||
selector: a[href^="download.php?id="]
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: index.php
|
||||
@@ -64,19 +48,16 @@
|
||||
options: "0"
|
||||
active: "0"
|
||||
rows:
|
||||
selector: table > tbody > tr > td > table.lista > tbody > tr:has(a[href^="index.php?page=torrent-details&id="])
|
||||
selector: table.table.table-bordered > tbody > tr:has(a[href^="index.php?page=torrent-details&id="])
|
||||
fields:
|
||||
download:
|
||||
selector: a[href^="index.php?page=downloadcheck&id="]
|
||||
selector: a[href^="download.php"]
|
||||
attribute: href
|
||||
title:
|
||||
selector: a[onmouseover][href^="index.php?page=torrent-details&id="]
|
||||
selector: a[title][href^="index.php?page=torrent-details&id="]
|
||||
banner:
|
||||
selector: a[onmouseover][href^="index.php?page=torrent-details&id="]
|
||||
attribute: onmouseover
|
||||
filters:
|
||||
- name: regexp
|
||||
args: "src=(.*?) "
|
||||
selector: img[src^="torrentimg/"]
|
||||
attribute: src
|
||||
category:
|
||||
selector: a[href^="index.php?page=torrents&category="]
|
||||
attribute: href
|
||||
@@ -84,43 +65,42 @@
|
||||
- name: querystring
|
||||
args: category
|
||||
details:
|
||||
selector: a[onmouseover][href^="index.php?page=torrent-details&id="]
|
||||
selector: a[title][href^="index.php?page=torrent-details&id="]
|
||||
attribute: href
|
||||
size:
|
||||
selector: td:nth-child(12)
|
||||
selector: p:has(b:contains("Size:"))
|
||||
remove: b
|
||||
date:
|
||||
selector: td:nth-child(7)
|
||||
selector: p:has(b:contains("Added:"))
|
||||
remove: b
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["@ ", ""]
|
||||
- name: append
|
||||
args: " +01:00"
|
||||
- name: dateparse
|
||||
args: "02/01/2006 -07:00"
|
||||
args: "01/02/2006 15:04:05 -07:00"
|
||||
seeders:
|
||||
selector: b:contains("Seeds:") + a
|
||||
leechers:
|
||||
selector: b:contains("Leechers:") + a
|
||||
grabs:
|
||||
selector: td:nth-child(10)
|
||||
selector: p:has(b:contains("Complete:"))
|
||||
remove: b, a[href^="index.php?page=peers"]
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["---", "0"]
|
||||
seeders:
|
||||
selector: td:nth-child(8)
|
||||
leechers:
|
||||
selector: td:nth-child(9)
|
||||
downloadvolumefactor:
|
||||
case:
|
||||
img[alt="Full Star 100% Free"]: "0"
|
||||
img[alt="Half Star 50% Free"]: "0.5"
|
||||
img[alt="Empty Star 25% Free"]: "0.75"
|
||||
i.fa-star: "0"
|
||||
i.fa-star-half-o: "0.5"
|
||||
i.fa-star-o: "0.75"
|
||||
"*": "1"
|
||||
uploadvolumefactor:
|
||||
case:
|
||||
span[title="2x Upload Multiplier"]: "2"
|
||||
"*": "1"
|
||||
description:
|
||||
selector: td:nth-child(2)
|
||||
remove: a
|
||||
description|append:
|
||||
selector: td:nth-child(3) > img
|
||||
attribute: title
|
||||
filters:
|
||||
- name: prepend
|
||||
args: "<br>Language: "
|
||||
|
||||
selector: p:has(b:contains("Language:"))
|
||||
|
||||
|
||||
|
@@ -40,6 +40,18 @@
|
||||
search: [q]
|
||||
tv-search: [q, season, ep]
|
||||
movie-search: [q]
|
||||
|
||||
settings:
|
||||
- name: username
|
||||
type: text
|
||||
label: Username
|
||||
- name: password
|
||||
type: password
|
||||
label: Password
|
||||
- name: info
|
||||
type: info
|
||||
label: Results Per Page
|
||||
default: For best results, change the 'Torrentliste' setting to "Platzsparendes Layout mit PopUp für zusätzliche Informationen" in your profile.
|
||||
|
||||
login:
|
||||
path: takelogin.php
|
||||
@@ -63,9 +75,13 @@
|
||||
|
||||
rows:
|
||||
selector: table.tableinborder > tbody > tr:has(a[href^="details.php"])
|
||||
fields:
|
||||
fields: # note: two alternative layouts available
|
||||
title:
|
||||
selector: a[href^="details.php"]
|
||||
title:
|
||||
optional: true
|
||||
selector: a[href^="details.php"][title]
|
||||
attribute: title
|
||||
category:
|
||||
selector: a[href^="browse.php?cat="]
|
||||
attribute: href
|
||||
@@ -79,29 +95,31 @@
|
||||
selector: a[href^=" /gettorrent/ssl/"]
|
||||
attribute: href
|
||||
files:
|
||||
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(1) > b:nth-child(2)
|
||||
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(1) > b:nth-child(2), a[href*="&filelist=1"]
|
||||
grabs:
|
||||
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(3) > b:nth-child(1)
|
||||
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(3) > b:nth-child(1), a[href*="&tosnatchers=1"]
|
||||
size:
|
||||
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(1) > b:nth-child(1)
|
||||
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(1) > b:nth-child(1), td:nth-child(7):has(br)
|
||||
filters:
|
||||
- name: replace
|
||||
args: [".", ""]
|
||||
- name: replace
|
||||
args: [",", "."]
|
||||
seeders:
|
||||
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(2) > b:nth-child(1)
|
||||
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(2) > b:nth-child(1), a[href*="&toseeders=1"]
|
||||
leechers:
|
||||
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(2) > b:nth-child(3)
|
||||
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(2) > b:nth-child(3), a[href*="&todlers=1"]
|
||||
date:
|
||||
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(5)
|
||||
selector: td:nth-child(2) > table > tbody > tr:nth-child(2) > td:nth-child(5), td:nth-child(5):has(br)
|
||||
filters:
|
||||
- name: replace
|
||||
args: [" ", ""]
|
||||
- name: append
|
||||
args: " +2:00"
|
||||
- name: replace
|
||||
args: ["\xA0", " "]
|
||||
args: ["\xA0", ""]
|
||||
- name: dateparse
|
||||
args: "02.01.2006 15:04:05 -07:00"
|
||||
args: "02.01.200615:04:05 -07:00"
|
||||
downloadvolumefactor:
|
||||
case:
|
||||
img[src="/pic/free.gif"]: "0"
|
||||
|
@@ -72,7 +72,7 @@
|
||||
rows:
|
||||
selector: tr.browse_color, tr.freeleech_color, tr[id^="kdescr"]
|
||||
after: 1
|
||||
fields:
|
||||
fields: # some users (rank specific?) have an extra column (td:nth-child(4)) with bookmark features
|
||||
banner:
|
||||
selector: a[href^="details.php?id="][onmouseover]
|
||||
attribute: onmouseover
|
||||
@@ -98,20 +98,20 @@
|
||||
selector: a[href^="download.php"]
|
||||
attribute: href
|
||||
files:
|
||||
selector: td:nth-child(4)
|
||||
selector: a[href^="filelist.php"]
|
||||
size:
|
||||
selector: td:nth-child(7)
|
||||
selector: td:nth-last-child(6)
|
||||
grabs:
|
||||
selector: td:nth-child(8)
|
||||
selector: td:nth-last-child(5)
|
||||
filters:
|
||||
- name: regexp
|
||||
args: ([\d,]+)
|
||||
seeders:
|
||||
selector: td:nth-child(9)
|
||||
selector: td:nth-last-child(4)
|
||||
leechers:
|
||||
selector: td:nth-child(10)
|
||||
selector: td:nth-last-child(3)
|
||||
date:
|
||||
selector: td:nth-child(6)
|
||||
selector: td:nth-last-child(7)
|
||||
downloadvolumefactor:
|
||||
case:
|
||||
"a.info > b:contains(\"[FREE]\")": "0"
|
||||
|
@@ -44,15 +44,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/"]
|
||||
@@ -63,37 +56,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
|
||||
imdb:
|
||||
optional: true
|
||||
selector: a[href*="://www.imdb.com/title/"]
|
||||
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"
|
||||
|
@@ -28,7 +28,7 @@
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: "list/{{if .Keywords}}{{.Keywords}}{{else}}movie{{end}}.html"
|
||||
- path: "list/{{if .Keywords}}{{.Keywords}}{{else}}movie{{end}}/1-1-0.html"
|
||||
rows:
|
||||
selector: .rs
|
||||
fields:
|
||||
|
@@ -1,23 +1,18 @@
|
||||
---
|
||||
site: torrentwtf
|
||||
name: Torrentwtf
|
||||
description: "Torrentwtf is a Czech Private site for TV / MOVIES / GENERAL"
|
||||
language: cs-cz
|
||||
site: btxpress
|
||||
name: BTXpress
|
||||
description: "HD Tracker Movies/TV/Music"
|
||||
language: en-us
|
||||
type: private
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- https://torrent.wtf/
|
||||
|
||||
- https://btxpress.org/
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
- {id: 1, cat: Movies, desc: "Filmy"}
|
||||
- {id: 2, cat: TV, desc: "Seriály"}
|
||||
- {id: 3, cat: Audio, desc: "Hudba"}
|
||||
- {id: 5, cat: PC/Games, desc: "Hry"}
|
||||
- {id: 6, cat: Books, desc: "Knihy"}
|
||||
- {id: 8, cat: PC, desc: "Software"}
|
||||
- {id: 9, cat: XXX, desc: "xXx"}
|
||||
- {id: 10, cat: Other, desc: "Ostatní"}
|
||||
- {id: 1, cat: Movies, desc: "Movies"}
|
||||
- {id: 2, cat: TV, desc: "TV"}
|
||||
- {id: 3, cat: Audio, desc: "Music"}
|
||||
|
||||
modes:
|
||||
search: [q]
|
||||
@@ -31,19 +26,22 @@
|
||||
username: "{{ .Config.username }}"
|
||||
password: "{{ .Config.password }}"
|
||||
error:
|
||||
- selector: table.main:contains("Tieto poverenia sa nezhodujú s našimi záznamami.")
|
||||
- selector: table.main:contains("Login Failed!")
|
||||
test:
|
||||
path: /torrents
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: /filter
|
||||
- path: /filterTorrents
|
||||
inputs:
|
||||
$raw: "{{range .Categories}}categories[]={{.}}&{{end}}"
|
||||
search: "{{if .Query.IMDBID}}{{else}}{{ .Keywords }}{{end}}"
|
||||
description: ""
|
||||
uploader: ""
|
||||
imdb: "{{ .Query.IMDBIDShort }}"
|
||||
tvdb: ""
|
||||
tmdb: ""
|
||||
mal: ""
|
||||
sorting: created_at
|
||||
direction: desc
|
||||
qty: 100
|
||||
@@ -65,9 +63,6 @@
|
||||
args: "/categories/.*?\\.(\\d+)"
|
||||
title:
|
||||
selector: a.view-torrent
|
||||
filters:
|
||||
- name: re_replace
|
||||
args: [".*? / ", ""]
|
||||
download:
|
||||
selector: a[href*="/download_check/"]
|
||||
attribute: href
|
||||
@@ -77,10 +72,6 @@
|
||||
details:
|
||||
selector: a.view-torrent
|
||||
attribute: href
|
||||
imdb:
|
||||
optional: true
|
||||
selector: a[href*="://www.imdb.com/title/"]
|
||||
attribute: href
|
||||
size:
|
||||
selector: td:nth-child(5)
|
||||
seeders:
|
||||
@@ -108,4 +99,4 @@
|
||||
uploadvolumefactor:
|
||||
case:
|
||||
"i[data-original-title=\"Double upload\"]": "2"
|
||||
"*": "1"
|
||||
"*": "1"
|
@@ -45,10 +45,7 @@
|
||||
- selector: table:contains("Login failed!")
|
||||
test:
|
||||
path: index.php
|
||||
|
||||
download:
|
||||
selector: a[href^="download.php?id="]
|
||||
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: browse.php
|
||||
|
@@ -6,8 +6,12 @@
|
||||
type: public
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- http://cpasbiens1.com/
|
||||
- http://www.cpabien.io/
|
||||
legacylinks:
|
||||
- http://www.cpasbiens.cc/
|
||||
- http://www.cpabien.cm/
|
||||
- http://cpabien.cm/
|
||||
- http://cpasbiens1.com/
|
||||
- http://cpabien.mx/
|
||||
- https://www.cpabien.bz/
|
||||
- http://www.cpabien.bz/
|
||||
@@ -30,13 +34,13 @@
|
||||
settings: []
|
||||
|
||||
download:
|
||||
selector: "#telecharger a"
|
||||
|
||||
selector: div.btn-download a
|
||||
attribute: href
|
||||
search:
|
||||
paths:
|
||||
- path: "/search.php?t={{ .Keywords }}"
|
||||
- path: "{{ if .Keywords }}recherche/{{ .Keywords }}{{else}}derniers/{{end}}"
|
||||
rows:
|
||||
selector: div[class^='ligne']
|
||||
selector: table.table-corps tbody tr td
|
||||
fields:
|
||||
site_date:
|
||||
selector: a
|
||||
|
@@ -38,16 +38,15 @@
|
||||
tv-search: [q, season, ep]
|
||||
movie-search: [q]
|
||||
|
||||
settings:
|
||||
- name: cookie
|
||||
type: text
|
||||
label: Cookie
|
||||
|
||||
login:
|
||||
path: /login-page
|
||||
method: form
|
||||
form: form[action^="/login"]
|
||||
method: cookie
|
||||
inputs:
|
||||
username: "{{ .Config.username }}"
|
||||
password: "{{ .Config.password }}"
|
||||
persistent_login: "1"
|
||||
error:
|
||||
- selector: div.error
|
||||
cookie: "{{ .Config.cookie }}"
|
||||
test:
|
||||
path: /torrents
|
||||
|
||||
|
@@ -128,7 +128,18 @@
|
||||
"2" : "Argent (Silver)"
|
||||
"3" : "Or (Gold)"
|
||||
"4" : "Argent & Or (Both)"
|
||||
|
||||
- name: multilang
|
||||
type: checkbox
|
||||
label: Replace MULTI by another language in release name
|
||||
default: false
|
||||
- name: multilanguage
|
||||
type: select
|
||||
label: Replace MULTI by this language
|
||||
default: FRENCH
|
||||
options:
|
||||
FRENCH : "FRENCH"
|
||||
MULTI.FRENCH : "MULTI.FRENCH"
|
||||
ENGLISH: "ENGLISH"
|
||||
login:
|
||||
path: tracker/index.php?page=login
|
||||
method: post
|
||||
@@ -168,8 +179,15 @@
|
||||
rows:
|
||||
selector: table > tbody > tr > td > table.lista > tbody > tr:has(td[onmouseover="this.className='post'"])
|
||||
fields:
|
||||
title:
|
||||
title_phase1:
|
||||
selector: a[onmouseover][href^="index.php?page=torrent-details&id="]
|
||||
title_multilang:
|
||||
text: "{{ .Result.title_phase1 }}"
|
||||
filters:
|
||||
- name: re_replace
|
||||
args: ["[\\.\\s\\[\\-][Mm][Uu][Ll][Tt][Ii][\\.\\s\\]\\-]", ".{{ .Config.multilanguage }}."]
|
||||
title:
|
||||
text: "{{if .Config.multilang }}{{ .Result.title_multilang }}{{else}}{{ .Result.title_phase1 }}{{end}}"
|
||||
details:
|
||||
selector: a[onmouseover][href^="index.php?page=torrent-details&id="]
|
||||
attribute: href
|
||||
@@ -189,23 +207,23 @@
|
||||
- name: querystring
|
||||
args: "category"
|
||||
date:
|
||||
selector: td:nth-of-type(4)
|
||||
selector: td:nth-of-type(5)
|
||||
filters:
|
||||
- name: append
|
||||
args: " -04:00"
|
||||
- name: dateparse
|
||||
args: "02/01/2006 15:04:05 -07:00"
|
||||
seeders:
|
||||
selector: td:nth-of-type(6)
|
||||
leechers:
|
||||
selector: td:nth-of-type(7)
|
||||
grabs:
|
||||
leechers:
|
||||
selector: td:nth-of-type(8)
|
||||
grabs:
|
||||
selector: td:nth-of-type(9)
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["---", "0"]
|
||||
size:
|
||||
selector: td:nth-of-type(10)
|
||||
selector: td:nth-of-type(11)
|
||||
downloadvolumefactor:
|
||||
case:
|
||||
img[src="images/freeleech.gif"]: "0"
|
||||
|
@@ -115,6 +115,8 @@
|
||||
|
||||
rows:
|
||||
selector: table > tbody > tr:has(img[src*="/pic/categories/"])
|
||||
filters:
|
||||
- name: andmatch
|
||||
fields:
|
||||
title:
|
||||
# using attribute title from td(3) because the text from td(2) a(2) can be abbreviated
|
||||
|
@@ -52,16 +52,25 @@
|
||||
tv-search: [q, season, ep]
|
||||
movie-search: [q]
|
||||
|
||||
settings: []
|
||||
settings:
|
||||
- name: downloadlink
|
||||
type: select
|
||||
label: Download link
|
||||
default: "magnet:"
|
||||
options:
|
||||
"https://etorrent.click/" : "eTorrent.click"
|
||||
"magnet:": "magnet"
|
||||
|
||||
download:
|
||||
selector: a[href^="magnet:"]
|
||||
selector: a[href^="{{ .Config.downloadlink }}"]
|
||||
|
||||
search:
|
||||
path: torrents-search.php
|
||||
inputs:
|
||||
$raw: "{{range .Categories}}c{{.}}=1&{{end}}"
|
||||
search: "{{ .Keywords }}"
|
||||
sort: "id"
|
||||
order: "desc"
|
||||
incldead: "1"
|
||||
keywordsfilters:
|
||||
- name: replace
|
||||
@@ -103,4 +112,4 @@
|
||||
downloadvolumefactor:
|
||||
text: "0"
|
||||
uploadvolumefactor:
|
||||
text: "1"
|
||||
text: "1"
|
||||
|
@@ -87,6 +87,7 @@
|
||||
- selector: div.myFrame:has(font.error)
|
||||
test:
|
||||
path: torrents-search.php
|
||||
selector: a.logout
|
||||
|
||||
search:
|
||||
paths:
|
||||
|
@@ -47,11 +47,33 @@
|
||||
paths:
|
||||
- path: "{{ if .Keywords }}buscar/descargas/{{ .Config.category }}/{{ .Keywords }}?search=Buscar{{else}}descargas{{end}}"
|
||||
- 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})", ""]
|
||||
rows:
|
||||
selector: table#descargas > tbody > tr:has(td:has(a[href^="magnet:?"]))
|
||||
fields:
|
||||
title:
|
||||
selector: td.tit a
|
||||
filters:
|
||||
- name: re_replace
|
||||
args: ["\\/", " "]
|
||||
- name: re_replace
|
||||
args: ["\\(", ""]
|
||||
- name: re_replace
|
||||
args: ["\\)", ""]
|
||||
- name: re_replace
|
||||
args: ["([A-z]*) temporada", "S$1"]
|
||||
- name: re_replace
|
||||
args: ["S[pP]rimera", "S1"]
|
||||
- name: re_replace
|
||||
args: ["S[sS]egunda", "S2"]
|
||||
- name: re_replace
|
||||
args: ["S[tT]ercera", "S3"]
|
||||
- name: re_replace
|
||||
args: ["S([0-9]+) - Episodio ([0-9]+)", "S$1E$2"]
|
||||
- name: re_replace
|
||||
args: ["- Episodio ([0-9]*)", "E$1"]
|
||||
details:
|
||||
selector: td.tit a
|
||||
attribute: href
|
||||
|
225
src/Jackett.Common/Definitions/girotorrent.yml
Normal file
225
src/Jackett.Common/Definitions/girotorrent.yml
Normal file
@@ -0,0 +1,225 @@
|
||||
---
|
||||
site: girotorrent
|
||||
name: Girotorrent
|
||||
description: "Girotorrent is an ITALIAN Private site for TV / MOVIES / GENERAL"
|
||||
language: it-it
|
||||
type: private
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- http://girotorrent.org/
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
# LIBREDICOLA
|
||||
- {id: 13, cat: Books, desc: "Giornali e Riviste"}
|
||||
- {id: 15, cat: Books, desc: "Ebook"}
|
||||
- {id: 16, cat: Books, desc: "Fumetti"}
|
||||
- {id: 70, cat: Books, desc: "Manuali e Guide"}
|
||||
- {id: 72, cat: Audio/Audiobook, desc: "Audiolibri"}
|
||||
# CINEMA
|
||||
- {id: 17, cat: Movies/Other, desc: "Movie Cam-Ts"}
|
||||
- {id: 18, cat: Movies/Other, desc: "Movie Screener"}
|
||||
- {id: 61, cat: Movies/Other, desc: "Movie R5-R6"}
|
||||
- {id: 19, cat: Movies/Other, desc: "Movie DVDRip"}
|
||||
- {id: 20, cat: Movies/Other, desc: "Movie BDRip"}
|
||||
- {id: 60, cat: Movies/Other, desc: "Movie BluRay"}
|
||||
- {id: 63, cat: Movies/Other, desc: "Movie WEBDLRip"}
|
||||
# VIDEOTECA
|
||||
- {id: 22, cat: Movies/SD, desc: "Movie BDRip"}
|
||||
- {id: 23, cat: Movies/SD, desc: "Movie DvdRip"}
|
||||
- {id: 23, cat: Movies/SD, desc: "Movie WEBRip"}
|
||||
- {id: 24, cat: Movies/DVD, desc: "Movie DVD-R 5"}
|
||||
- {id: 25, cat: Movies/DVD, desc: "Movie DVD-R 9"}
|
||||
- {id: 26, cat: Movies/HD, desc: "Movie Blu-Ray HD"}
|
||||
- {id: 27, cat: Movies/3D, desc: "Movie 3D-SBS"}
|
||||
- {id: 96, cat: Movies/HD, desc: "Movie x265 HEVC"}
|
||||
- {id: 28, cat: Movies/Foreign, desc: "Movie Subbet-ita"}
|
||||
- {id: 73, cat: Movies/SD, desc: "Movie MP4"}
|
||||
- {id: 29, cat: Movies/Foreign, desc: "Movie Ligua Originale"}
|
||||
# ANIMAZIONE
|
||||
- {id: 32, cat: TV/Anime, desc: "Anime Disney"}
|
||||
- {id: 33, cat: TV/Anime, desc: "Anime"}
|
||||
- {id: 34, cat: TV/Anime, desc: "Anime Altri Cartoni"}
|
||||
# TELEVISIONE
|
||||
- {id: 36, cat: TV, desc: "TV Serie TV"}
|
||||
- {id: 77, cat: TV, desc: "TV Reality"}
|
||||
- {id: 37, cat: TV, desc: "TV Film TV"}
|
||||
- {id: 59, cat: TV, desc: "TV Sport"}
|
||||
- {id: 38, cat: TV, desc: "TV Concerti-Spettacoli"}
|
||||
- {id: 39, cat: TV, desc: "TV Teatro-Cabaret"}
|
||||
- {id: 40, cat: TV/Documentary, desc: "Tv Documentario"}
|
||||
# MUSICA
|
||||
- {id: 42, cat: Audio, desc: "Musica CD Singoli"}
|
||||
- {id: 43, cat: Audio, desc: "Musica Italiana"}
|
||||
- {id: 44, cat: Audio, desc: "Musica Straniera"}
|
||||
- {id: 45, cat: Audio, desc: "Musica Compilation"}
|
||||
- {id: 46, cat: Audio, desc: "Musica Video Clip"}
|
||||
- {id: 58, cat: Audio, desc: "Musica Discografie"}
|
||||
# SALA GIOCHI
|
||||
- {id: 47, cat: PC/Games, desc: "PC Games"}
|
||||
- {id: 48, cat: PC/Games, desc: "PC Giochi PS2-PS3"}
|
||||
- {id: 49, cat: PC/Games, desc: "PC Giochi Nintendo Wii"}
|
||||
- {id: 50, cat: PC/Games, desc: "PC Giochi Xbox"}
|
||||
- {id: 52, cat: PC/Games, desc: "PC Giochi DS-DS3"}
|
||||
# SOFTWARE
|
||||
- {id: 54, cat: PC, desc: "PC Programmi Windows"}
|
||||
- {id: 55, cat: PC/Mac, desc: "PC Mac"}
|
||||
- {id: 69, cat: PC, desc: "PC Portable"}
|
||||
- {id: 56, cat: PC, desc: "PC Linux"}
|
||||
# CELLULARI-PALMARI
|
||||
- {id: 71, cat: PC/Phone-Android, desc: "Android APP"}
|
||||
- {id: 74, cat: Other, desc: "Varie"}
|
||||
- {id: 75, cat: Other, desc: "Immagini Wallpaper"}
|
||||
|
||||
modes:
|
||||
search: [q]
|
||||
tv-search: [q, season, ep]
|
||||
movie-search: [q]
|
||||
|
||||
login:
|
||||
path: /index.php?page=login
|
||||
method: post
|
||||
inputs:
|
||||
uid: "{{ .Config.username }}"
|
||||
pwd: "{{ .Config.password }}"
|
||||
error:
|
||||
- selector: div.error
|
||||
test:
|
||||
path: /index.php
|
||||
selector: a[href="logout.php"]
|
||||
|
||||
download:
|
||||
before:
|
||||
path: "thanks.php"
|
||||
method: "post"
|
||||
inputs:
|
||||
infohash: "{{ .DownloadUri.Query.id }}"
|
||||
thanks: "1"
|
||||
rndval: "1487013827343"
|
||||
selector: a[href^="download.php?id="]
|
||||
|
||||
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
|
||||
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]|\\.", " "]
|
||||
# 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
|
||||
category:
|
||||
selector: a[href^="index.php?page=torrents&category="]
|
||||
attribute: href
|
||||
filters:
|
||||
- name: querystring
|
||||
args: category
|
||||
details:
|
||||
selector: a[onmouseover][href^="index.php?page=torrent-details&id="]
|
||||
attribute: href
|
||||
banner:
|
||||
optional: true
|
||||
selector: a[onmouseover][href^="index.php?page=torrent-details&id="]
|
||||
attribute: onmouseover
|
||||
filters:
|
||||
- name: regexp
|
||||
args: "src=(.+?) "
|
||||
size:
|
||||
selector: td:nth-child(11)
|
||||
date:
|
||||
selector: td:nth-child(6)
|
||||
filters:
|
||||
- name: dateparse
|
||||
args: "02/01/2006"
|
||||
grabs:
|
||||
selector: td:nth-child(9)
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["---", "0"]
|
||||
seeders:
|
||||
selector: td:nth-child(7)
|
||||
leechers:
|
||||
selector: td:nth-child(8)
|
||||
downloadvolumefactor:
|
||||
case:
|
||||
img[alt="Free Leech"]: "0"
|
||||
img[alt="Gold 100% Free"]: "0"
|
||||
img[alt="Silver 50% Free"]: "0.5"
|
||||
img[alt="Bronze 25% Free"]: "0.75"
|
||||
"*": "1"
|
||||
uploadvolumefactor:
|
||||
text: "1"
|
||||
uploadvolumefactor:
|
||||
optional: true
|
||||
selector: img[alt$="x Upload Multiplier"]
|
||||
attribute: alt
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["x Upload Multiplier", ""]
|
@@ -6,8 +6,9 @@
|
||||
type: public
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- http://www.gktorrent.net/
|
||||
- https://www.gktorrent.org/
|
||||
legacylinks:
|
||||
- http://www.gktorrent.net/
|
||||
- https://www.gktorrent.com/ # they're forcing http
|
||||
- http://www.gktorrent.com/
|
||||
|
||||
|
@@ -80,12 +80,15 @@
|
||||
|
||||
search:
|
||||
path: /
|
||||
keywordsfilters:
|
||||
- name: re_replace
|
||||
args: ["S0?(\\d{1,2})E(\\d{1,2})", "$1x$2"]
|
||||
inputs:
|
||||
p: "torrents"
|
||||
page: "1"
|
||||
pid: "10"
|
||||
$raw: "{{range .Categories}}&cid[]={{.}}{{end}}"
|
||||
keywords: "{{ .Query.Keywords }}"
|
||||
keywords: "{{ .Keywords }}"
|
||||
search_type: "name"
|
||||
searchin: "title"
|
||||
rows:
|
||||
@@ -93,6 +96,9 @@
|
||||
fields:
|
||||
title:
|
||||
selector: td.torrent_name > a, .newIndicator > a
|
||||
filters:
|
||||
- name: append
|
||||
args: " [spanish]"
|
||||
details:
|
||||
selector: td.torrent_name > a, .newIndicator > a
|
||||
attribute: href
|
||||
|
@@ -33,9 +33,6 @@
|
||||
- selector: table.main:contains("Login Failed!")
|
||||
test:
|
||||
path: my.php
|
||||
|
||||
download:
|
||||
selector: a[href^="/download.php"]
|
||||
|
||||
search:
|
||||
paths:
|
||||
|
@@ -61,7 +61,6 @@
|
||||
search:
|
||||
paths:
|
||||
- path: /torrents.php
|
||||
method: post
|
||||
inputs:
|
||||
$raw: "{{range .Categories}}cat{{.}}=1&{{end}}"
|
||||
search: "{{if .Query.IMDBID}}{{ .Query.IMDBID }}{{else}}{{ .Keywords }}{{end}}"
|
||||
|
@@ -4,7 +4,7 @@
|
||||
description: "HDCity is a SPANISH site for HD content"
|
||||
language: es-es
|
||||
type: private
|
||||
encoding: UTF-8
|
||||
encoding: ISO-8859-1
|
||||
links:
|
||||
- https://hdcity.li/
|
||||
|
||||
@@ -129,11 +129,14 @@
|
||||
|
||||
search:
|
||||
path: index.php
|
||||
keywordsfilters:
|
||||
- name: re_replace
|
||||
args: ["S0?(\\d{1,2})E(\\d{1,2})", "$1x$2"]
|
||||
inputs:
|
||||
page: "torrents"
|
||||
$raw: "&category={{range .Categories}}{{.}};{{end}}"
|
||||
active: "1"
|
||||
search: "{{ .Query.Keywords }}"
|
||||
search: "{{ .Keywords }}"
|
||||
rows:
|
||||
selector: "#category+table table tr:not(:first-child):not(:last-child)"
|
||||
fields:
|
||||
@@ -145,6 +148,9 @@
|
||||
args: category
|
||||
title:
|
||||
selector: td[valign="middle"] a
|
||||
filters:
|
||||
- name: append
|
||||
args: " [spanish]"
|
||||
details:
|
||||
selector: td[valign="middle"] a
|
||||
attribute: href
|
||||
|
@@ -82,7 +82,6 @@
|
||||
search:
|
||||
paths:
|
||||
- path: /torrents.php
|
||||
method: post
|
||||
inputs:
|
||||
$raw: "{{range .Categories}}cat{{.}}=1&{{end}}"
|
||||
search: "{{if .Query.IMDBID}}{{ .Query.IMDBID }}{{else}}{{ .Keywords }}{{end}}"
|
||||
|
@@ -91,6 +91,11 @@
|
||||
download:
|
||||
selector: td:nth-child(11) > a
|
||||
attribute: href
|
||||
filters:
|
||||
- name: prepend
|
||||
args: "{{ .Config.sitelink }}"
|
||||
- name: replace # https download links are redirected to http causing invalid cookies => invalid passkeys
|
||||
args: ["https", "http"]
|
||||
size:
|
||||
selector: td:nth-child(6)
|
||||
remove: br
|
||||
@@ -103,3 +108,9 @@
|
||||
selector: td:nth-child(8)
|
||||
leechers:
|
||||
selector: td:nth-child(9)
|
||||
downloadvolumefactor:
|
||||
case:
|
||||
"font:contains(\"(FreeLeech)\")": "0"
|
||||
"*": "1"
|
||||
uploadvolumefactor:
|
||||
text: "1"
|
||||
|
142
src/Jackett.Common/Definitions/hdspain.yml
Normal file
142
src/Jackett.Common/Definitions/hdspain.yml
Normal file
@@ -0,0 +1,142 @@
|
||||
---
|
||||
site: hdspain
|
||||
name: HD-Spain
|
||||
description: "HD-Spain is a SPANISH site for HD content"
|
||||
language: es-es
|
||||
type: private
|
||||
encoding: ISO-8859-1
|
||||
links:
|
||||
- https://www.hd-spain.com/
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
- {id: 1 , cat: Movies/HD, desc: "Películas"}
|
||||
- {id: 5 , cat: Movies/HD, desc: "Pelíc. Anim."}
|
||||
- {id: 4 , cat: TV/HD, desc: "Series"}
|
||||
- {id: 3 , cat: TV/HD, desc: "Series Anim."}
|
||||
- {id: 6 , cat: TV/Documentary, desc: "Documentales"}
|
||||
- {id: 11, cat: TV/Sport, desc: "Deportes"}
|
||||
- {id: 7 , cat: Audio/Video, desc: "Música/Espec."}
|
||||
- {id: 9 , cat: TV/OTHER, desc: "Programas TV"}
|
||||
- {id: 8 , cat: Audio/Lossless, desc: "Audios"}
|
||||
- {id: 10, cat: XXX/x264, desc: "XXX"}
|
||||
modes:
|
||||
search: [q]
|
||||
|
||||
login:
|
||||
path: index.php
|
||||
method: form
|
||||
inputs:
|
||||
usuario: "{{ .Config.username }}"
|
||||
contrasena: "{{ .Config.password }}"
|
||||
error:
|
||||
- selector: p.error
|
||||
test:
|
||||
path: index.php
|
||||
selector: .tcabecera
|
||||
|
||||
search:
|
||||
path: index.php
|
||||
keywordsfilters:
|
||||
- name: re_replace
|
||||
args: ["S0?(\\d{1,2})E(\\d{1,2})", "$1x$2"]
|
||||
inputs:
|
||||
sec: listado
|
||||
ord: 9
|
||||
b: "{{ .Keywords }}"
|
||||
ver: "0"
|
||||
relanz: "0"
|
||||
$raw: "{{range .Categories}}&cat[]={{.}}{{end}}"
|
||||
rows:
|
||||
selector: "table.listatorrents tr:not(:first-child)"
|
||||
fields:
|
||||
category:
|
||||
selector: td.categorias a
|
||||
attribute: href
|
||||
filters:
|
||||
- name: querystring
|
||||
args: cat
|
||||
title:
|
||||
selector: td.titulo a[id]
|
||||
filters:
|
||||
- name: append
|
||||
args: " [spanish]"
|
||||
details:
|
||||
selector: td.titulo a
|
||||
attribute: href
|
||||
size:
|
||||
selector: td.tamano
|
||||
seeders:
|
||||
selector: td.usuarios.seeds a
|
||||
leechers:
|
||||
selector: td.usuarios.leechers a
|
||||
grabs:
|
||||
selector: td.usuarios.completados
|
||||
date:
|
||||
optional: true
|
||||
selector: td.fecha
|
||||
attribute: title
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["Lunes", "Monday"]
|
||||
- name: replace
|
||||
args: ["Martes", "Tuesday"]
|
||||
- name: re_replace
|
||||
args: ["Miércoles", "Wednesday"]
|
||||
- name: replace
|
||||
args: ["Jueves", "Thursday"]
|
||||
- name: replace
|
||||
args: ["Viernes", "Friday"]
|
||||
- name: re_replace
|
||||
args: ["Sábado", "Saturday"]
|
||||
- name: replace
|
||||
args: ["Domingo", "Sunday"]
|
||||
- name: replace
|
||||
args: ["Enero", "January"]
|
||||
- name: replace
|
||||
args: ["Febrero", "February"]
|
||||
- name: replace
|
||||
args: ["Marzo", "March"]
|
||||
- name: replace
|
||||
args: ["Abril", "April"]
|
||||
- name: replace
|
||||
args: ["Mayo", "May"]
|
||||
- name: replace
|
||||
args: ["Junio", "June"]
|
||||
- name: replace
|
||||
args: ["Julio", "July"]
|
||||
- name: replace
|
||||
args: ["Agosto", "August"]
|
||||
- name: replace
|
||||
args: ["Septiembre", "September"]
|
||||
- name: replace
|
||||
args: ["Octubre", "October"]
|
||||
- name: replace
|
||||
args: ["Noviembre", "November"]
|
||||
- name: replace
|
||||
args: ["Diciembre", "December"]
|
||||
- name: dateparse
|
||||
args: "Monday 2 January 2006, 15:04"
|
||||
download:
|
||||
selector: td.descargar a
|
||||
attribute: href
|
||||
|
||||
downloadvolumefactor:
|
||||
text: "1"
|
||||
downloadvolumefactor:
|
||||
optional: true
|
||||
selector: td.descargar a b strong
|
||||
filters:
|
||||
- name: replace
|
||||
args: [" X2", ""]
|
||||
- name: replace
|
||||
args: ["Freeleech", "0"]
|
||||
|
||||
uploadvolumefactor:
|
||||
text: "1"
|
||||
uploadvolumefactor:
|
||||
optional: true
|
||||
selector: td.descargar a b strong
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["Freeleech X2", "2"]
|
@@ -114,7 +114,7 @@
|
||||
selector: td:has(a[href$="filelist=1#filelist"])
|
||||
remove: a
|
||||
date:
|
||||
selector: td > font:contains("Added on")
|
||||
selector: td > font:has(i.fa-clock-o)
|
||||
remove: b
|
||||
filters:
|
||||
- name: replace
|
||||
|
160
src/Jackett.Common/Definitions/ilcorsaroblu.yml
Normal file
160
src/Jackett.Common/Definitions/ilcorsaroblu.yml
Normal file
@@ -0,0 +1,160 @@
|
||||
---
|
||||
site: ilcorsaroblu
|
||||
name: Il Corsaro Blu
|
||||
description: "Il Corsaro Blu is an ITALIAN Public site for TV / MOVIES / GENERAL"
|
||||
language: it-it
|
||||
type: public
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- https://www.ilcorsaroblu.info/
|
||||
legacylinks:
|
||||
- http://ilcorsaroblu.org/
|
||||
- https://www.ilcorsaroblu.org/
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
# Adult
|
||||
- {id: 12, cat: XXX, desc: "Adult"}
|
||||
# Applicazioni
|
||||
- {id: 5, cat: PC/Phone-Android, desc: "Android"}
|
||||
# Books
|
||||
- {id: 6, cat: Books, desc: "Books"}
|
||||
# Games
|
||||
- {id: 3, cat: Other, desc: "Games"}
|
||||
# Music
|
||||
- {id: 2, cat: Audio, desc: "Music"}
|
||||
# Movies
|
||||
- {id: 17, cat: Movies/SD, desc: "Movie BDRip"}
|
||||
- {id: 21, cat: Movies/Other, desc: "Movies - Films"}
|
||||
- {id: 11, cat: Movies/DVD, desc: "DVD-R"}
|
||||
- {id: 14, cat: Movies/HD, desc: "Movie 720p"}
|
||||
- {id: 13, cat: Movies/HD, desc: "Movie 1080p"}
|
||||
- {id: 15, cat: Movies/3D, desc: "Movie 3D"}
|
||||
- {id: 24, cat: TV/OTHER, desc: "TV Show Standard"}
|
||||
- {id: 19, cat: TV/HD, desc: "Tv Show 1080p"}
|
||||
- {id: 20, cat: TV/HD, desc: "Tv Show 720"}
|
||||
# Various
|
||||
- {id: 4, cat: Other, desc: "Other"}
|
||||
- {id: 7, cat: PC, desc: "Windows"}
|
||||
- {id: 8, cat: Other, desc: "Linux"}
|
||||
- {id: 9, cat: PC/Mac, desc: "Mac"}
|
||||
- {id: 23, cat: Other, desc: "Archive"}
|
||||
|
||||
modes:
|
||||
search: [q]
|
||||
tv-search: [q, season, ep]
|
||||
movie-search: [q]
|
||||
|
||||
settings: []
|
||||
|
||||
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
|
||||
rows:
|
||||
selector: div.b-content > table > tbody > tr > td > table.lista > tbody > tr:has(a[href^="index.php?page=torrents&category="])
|
||||
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]|\\.", " "]
|
||||
# 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
|
||||
download: # handle torrents with normal torrent file download
|
||||
optional: true
|
||||
selector: a[href^="download.php?id="]
|
||||
attribute: href
|
||||
filters:
|
||||
- name: querystring
|
||||
args: id
|
||||
- name: toupper
|
||||
- name: prepend
|
||||
args: http://itorrents.org/torrent/
|
||||
- name: append
|
||||
args: ".torrent"
|
||||
_magnetfilename: # convert title to valid magnet filename
|
||||
text: "{{ .Result.title }}"
|
||||
filters:
|
||||
- name: validfilename
|
||||
- name: urlencode
|
||||
magnet: # generate magnet link from download link
|
||||
optional: true
|
||||
selector: a[href^="download.php?id="]
|
||||
attribute: href
|
||||
filters:
|
||||
- name: querystring
|
||||
args: id
|
||||
- name: prepend
|
||||
args: "magnet:?xt=urn:btih:"
|
||||
- name: append
|
||||
args: "&dn={{ .Result._magnetfilename }}.torrent"
|
||||
- name: append # add some well known public trackers
|
||||
args: "&tr=udp://tracker.openbittorrent.com:80/announce&tr=udp://tracker.opentrackr.org:1337/announce"
|
||||
magnet: # in case a direct magnet link is provided use it
|
||||
optional: true
|
||||
selector: a[href^="magnet:?xt="]
|
||||
attribute: href
|
||||
category:
|
||||
selector: a[href^="index.php?page=torrents&category="]
|
||||
attribute: href
|
||||
filters:
|
||||
- name: querystring
|
||||
args: category
|
||||
details:
|
||||
selector: td:nth-child(2) a
|
||||
attribute: href
|
||||
banner:
|
||||
optional: true
|
||||
selector: td:nth-child(2) > a
|
||||
attribute: onmouseover
|
||||
filters:
|
||||
- name: regexp
|
||||
args: "src=(.+?) "
|
||||
size:
|
||||
selector: td:nth-child(9)
|
||||
date:
|
||||
selector: td:nth-child(5)
|
||||
filters:
|
||||
- name: dateparse
|
||||
args: "02/01/2006"
|
||||
grabs:
|
||||
selector: td:nth-child(8)
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["---", "0"]
|
||||
seeders:
|
||||
selector: td:nth-child(6)
|
||||
leechers:
|
||||
selector: td:nth-child(7)
|
@@ -9,6 +9,7 @@
|
||||
- https://ilcorsaronero.info/
|
||||
certificates:
|
||||
- aa7c40aa360a1cec8a9687312fd50402b912e618 # incomplete CA chain
|
||||
- 83174ec1f92fa13cdef9d51888ea1dfba2166e17 # incomplete CA chain
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
|
@@ -77,6 +77,9 @@
|
||||
attribute: href
|
||||
size:
|
||||
selector: td.size-row
|
||||
filters:
|
||||
- name: re_replace
|
||||
args: ["(\\d+).(?=\\d{3}(\\D|$))", "$1"]
|
||||
seeders:
|
||||
selector: td.sn
|
||||
date:
|
||||
@@ -96,4 +99,4 @@
|
||||
downloadvolumefactor:
|
||||
text: "0"
|
||||
uploadvolumefactor:
|
||||
text: "1"
|
||||
text: "1"
|
||||
|
@@ -1,3 +1,5 @@
|
||||
# looks like gazelle but ajax.php seems to be disabled:
|
||||
# https://jpopsuki.eu/ajax.php?action=browse&order_by=time&order_way=desc => Invalid
|
||||
---
|
||||
site: jpopsuki
|
||||
name: JPopsuki
|
||||
@@ -34,7 +36,7 @@
|
||||
keeplogged: 1
|
||||
login: "Log in"
|
||||
error:
|
||||
- selector: form#loginform > span.warning
|
||||
- selector: form#loginform > span.warning, font[color="red"]
|
||||
test:
|
||||
path: torrents.php
|
||||
|
||||
|
@@ -1,13 +1,15 @@
|
||||
---
|
||||
site: kickasstorrent-kathow
|
||||
name: KickAssTorrent (thekat.io)
|
||||
description: "thekat.nz is a Public KickAssTorrent clone for TV / MOVIES / GENERAL"
|
||||
name: KickAssTorrent (kat.li)
|
||||
description: "kat.li is a Public KickAssTorrent clone for TV / MOVIES / GENERAL"
|
||||
language: en-us
|
||||
type: public
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- https://katcr.io/
|
||||
- https://kat.li/
|
||||
legacylinks:
|
||||
- https://kickass.gg/
|
||||
- https://katcr.io/
|
||||
- https://thekat.nz/
|
||||
- https://thekat.se/
|
||||
- https://kat.how/
|
||||
@@ -36,6 +38,7 @@
|
||||
selector: table[class="data"] tr[id]
|
||||
fields:
|
||||
category:
|
||||
optional: true
|
||||
selector: span[id^="cat_"] > strong > a
|
||||
attribute: href
|
||||
filters:
|
||||
@@ -55,12 +58,23 @@
|
||||
- name: urldecode
|
||||
size:
|
||||
selector: td:nth-child(2)
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["N/A", "0 Bytes"]
|
||||
- name: re_replace # replace all but last dot (They use dots as decimal and thousands separators)
|
||||
args: ["[.](?=.*[.])", ""]
|
||||
date:
|
||||
selector: td:nth-child(3)
|
||||
seeders:
|
||||
selector: td:nth-child(4)
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["N/A", "0"]
|
||||
leechers:
|
||||
selector: td:nth-child(5)
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["N/A", "0"]
|
||||
description:
|
||||
selector: td:nth-child(1) > div > div > span
|
||||
downloadvolumefactor:
|
||||
|
@@ -258,6 +258,8 @@
|
||||
args: ["^Extinct", "Extinct 2017"]
|
||||
- name: re_replace
|
||||
args: ["^The Flash", "The Flash 2014"]
|
||||
- name: replace
|
||||
args: ["Nanatsu no Taizai - Imashime no Fukkatsu - E", "Nanatsu no Taizai - Imashime no Fukkatsu - S02E"]
|
||||
- name: re_replace
|
||||
args: ["^The Magicians", "The Magicians 2015"]
|
||||
# Workaround to remove the translated name from the series, didn't found an better and reliable way to do this, feel free to add more as needed.
|
||||
|
@@ -10,53 +10,20 @@
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
# TV
|
||||
- {id: 23, cat: TV, desc: "TV/HD"}
|
||||
- {id: 47, cat: TV, desc: "TV/PACKS"}
|
||||
- {id: 28, cat: TV, desc: "TV/eps"}
|
||||
- {id: 25, cat: TV, desc: "TV/HDRIP"}
|
||||
- {id: 24, cat: TV, desc: "TV/TV-packs"}
|
||||
- {id: 26, cat: TV/HD, desc: "TV/X264-HD"}
|
||||
- {id: 27, cat: TV/SD, desc: "TV/X264-SD"}
|
||||
# Movies
|
||||
- {id: 10, cat: Movies, desc: "Movies/0DAY"}
|
||||
- {id: 56, cat: Movies/3D, desc: "Movies/3D"}
|
||||
- {id: 16, cat: TV/Anime, desc: "Movies/ANIME"}
|
||||
- {id: 44, cat: Movies, desc: "Movies/CAM"}
|
||||
- {id: 18, cat: Movies/DVD, desc: "Movies/DVDR"}
|
||||
- {id: 49, cat: Movies/HD, desc: "Movies/hd 1080p"}
|
||||
- {id: 48, cat: Movies/HD, desc: "Movies/hd 720p"}
|
||||
- {id: 55, cat: Movies, desc: "Movies/Box Sets"}
|
||||
- {id: 53, cat: Movies, desc: "Movies/Sports"}
|
||||
- {id: 17, cat: Movies, desc: "Movies/X264"}
|
||||
- {id: 57, cat: Movies, desc: "Movies/xmas"}
|
||||
- {id: 15, cat: Movies/SD, desc: "Movies/XVID"}
|
||||
# Music
|
||||
- {id: 54, cat: Audio/Audiobook, desc: "Music/Audio Book"}
|
||||
- {id: 19, cat: Audio/Lossless, desc: "Music/FLAC"}
|
||||
- {id: 20, cat: Audio, desc: "Music/DVDR"}
|
||||
- {id: 21, cat: Audio/MP3, desc: "Music/MP3"}
|
||||
- {id: 42, cat: Audio, desc: "Music/0DAY"}
|
||||
- {id: 22, cat: Audio/Video, desc: "Music/VID"}
|
||||
# Apps
|
||||
- {id: 9, cat: PC/0day, desc: "Apps/APPS"}
|
||||
- {id: 11, cat: Books/Ebook, desc: "Apps/EBOOKS"}
|
||||
- {id: 46, cat: PC/Phone-Other, desc: "Apps/IPHONE/ANDROID"}
|
||||
- {id: 51, cat: PC, desc: "Apps/Linux"}
|
||||
- {id: 52, cat: PC/Mac, desc: "Apps/MAC"}
|
||||
# Games
|
||||
- {id: 58, cat: Console/Other, desc: "Games/Android"}
|
||||
- {id: 45, cat: PC/Games, desc: "Games/GAMES"}
|
||||
- {id: 59, cat: Console/NDS, desc: "Games/NDS"}
|
||||
- {id: 50, cat: Console, desc: "Games/PS2"}
|
||||
- {id: 14, cat: Console/PS3, desc: "Games/PS3"}
|
||||
- {id: 12, cat: Console/Wii, desc: "Games/WII"}
|
||||
- {id: 13, cat: Console/Xbox 360, desc: "Games/XBOX360"}
|
||||
# XXX
|
||||
- {id: 38, cat: XXX, desc: "XXX"}
|
||||
- {id: 39, cat: XXX, desc: "XXX/0DAY"}
|
||||
- {id: 40, cat: XXX/Imageset, desc: "XXX/IMAGESET"}
|
||||
- {id: 41, cat: XXX/Other, desc: "XXX/SITERIPS"}
|
||||
- {id: 9, cat: TV/Anime, desc: "Anime"}
|
||||
- {id: 1, cat: PC/0day, desc: "Apps"}
|
||||
- {id: 13, cat: PC/0day, desc: "Apps"}
|
||||
- {id: 5, cat: TV, desc: "Episodes"}
|
||||
- {id: 2, cat: PC/Games, desc: "Games"}
|
||||
- {id: 12, cat: PC/Games, desc: "Games/PC Rips"}
|
||||
- {id: 8, cat: Console/Other, desc: "Games/PS2"}
|
||||
- {id: 7, cat: Console/PSP, desc: "Games/PSP"}
|
||||
- {id: 3, cat: Movies, desc: "Movies"}
|
||||
- {id: 11, cat: Movies/SD, desc: "Movies/HDTV"}
|
||||
- {id: 10, cat: Movies/SD, desc: "Movies/XviD"}
|
||||
- {id: 4, cat: Audio, desc: "Music"}
|
||||
- {id: 14, cat: Audio, desc: "Music"}
|
||||
- {id: 6, cat: XXX, desc: "XXX"}
|
||||
|
||||
modes:
|
||||
search: [q]
|
||||
@@ -101,13 +68,13 @@
|
||||
selector: table tr td.text
|
||||
test:
|
||||
path: browse.php
|
||||
selector: li a[href^="logout.php?hash_please="]
|
||||
selector: a[href*="logout.php?hash_please="]
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: browse.php
|
||||
inputs:
|
||||
#$raw: "{{range .Categories}}c{{.}}=1&{{end}}" # this should work, untested
|
||||
$raw: "{{range .Categories}}c{{.}}=1&{{end}}"
|
||||
search: "{{ .Keywords }}"
|
||||
searchin: "title"
|
||||
incldead: "{{ .Config.incldead }}"
|
||||
@@ -115,6 +82,8 @@
|
||||
|
||||
rows:
|
||||
selector: tr.browse_color
|
||||
filters:
|
||||
- name: andmatch
|
||||
fields:
|
||||
category:
|
||||
selector: td:nth-of-type(1) a
|
||||
@@ -137,11 +106,7 @@
|
||||
selector: td:nth-of-type(3) a
|
||||
attribute: href
|
||||
files:
|
||||
optional: true
|
||||
selector: td:nth-of-type(5) a
|
||||
files:
|
||||
optional: true
|
||||
selector: td:nth-of-type(5):not(:has(a))
|
||||
selector: td:nth-of-type(5)
|
||||
date:
|
||||
selector: td:nth-of-type(7)
|
||||
filters:
|
||||
@@ -155,12 +120,13 @@
|
||||
- name: regexp
|
||||
args: "([\\d]+)"
|
||||
seeders:
|
||||
selector: td:nth-of-type(10) a font
|
||||
selector: td:nth-of-type(10)
|
||||
leechers:
|
||||
selector: td:nth-of-type(11)
|
||||
downloadvolumefactor:
|
||||
case:
|
||||
"span:contains(\"Unlimited\")": "0"
|
||||
"img[title=\"Free Torrent\"]": "0" # torrent specific free leech (icon)?
|
||||
"a.info:contains(\"Free\")": "0" # global freeleech note?
|
||||
"*": "1"
|
||||
uploadvolumefactor:
|
||||
text: "1"
|
||||
|
@@ -38,7 +38,7 @@
|
||||
- path: /torrents/search.html
|
||||
method: post
|
||||
inputs:
|
||||
"SearchTorrentsForm[nameTorrent]": "{{ .Keywords }}"
|
||||
"SearchTorrentsForm[nameTorrent]": "{{if .Query.Artist}}{{ .Query.Artist }}{{else}}{{ .Keywords }}{{end}}"
|
||||
go-search: "Search"
|
||||
rows:
|
||||
selector: .smallalbum
|
||||
|
@@ -45,6 +45,17 @@
|
||||
search: [q]
|
||||
tv-search: [q, season, ep]
|
||||
|
||||
settings:
|
||||
- name: username
|
||||
type: text
|
||||
label: Username
|
||||
- name: password
|
||||
type: password
|
||||
label: Password
|
||||
- name: pin
|
||||
type: text
|
||||
label: Pin
|
||||
|
||||
login:
|
||||
path: /login.php
|
||||
method: form
|
||||
@@ -52,6 +63,7 @@
|
||||
inputs:
|
||||
username: "{{ .Config.username }}"
|
||||
password: "{{ .Config.password }}"
|
||||
secure_pin: "{{ .Config.pin }}"
|
||||
returnto: "/"
|
||||
error:
|
||||
- selector: table.tableinborder:contains("Anmeldung Gescheitert!") > tbody > tr > td.tablea
|
||||
|
@@ -6,8 +6,10 @@
|
||||
type: public
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- http://www.nextorrent.site/
|
||||
- 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/
|
||||
@@ -16,11 +18,12 @@
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
- {id: Film, cat: Movies, desc: "Movies"}
|
||||
- {id: Films, cat: Movies, desc: "Movies"}
|
||||
- {id: Séries, cat: TV, desc: "TV"}
|
||||
- {id: Animes, cat: TV/Anime, desc: "TV/Anime"}
|
||||
- {id: Jeux, cat: Console, desc: "Games"}
|
||||
- {id: Ebooks, cat: Books, desc: "EBooks"}
|
||||
- {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:
|
||||
@@ -31,24 +34,22 @@
|
||||
settings: []
|
||||
|
||||
download:
|
||||
selector: a[href^="/_get/NexTorrent.pro-"]
|
||||
selector: a[href^="/get_torrent/"]
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: /
|
||||
inputs:
|
||||
s: "{{ .Keywords }}"
|
||||
- path: "recherche/{{ .Query.Keywords }}"
|
||||
rows:
|
||||
selector: article[id^="post-"]
|
||||
selector: div.listing-torrent > table tbody tr:has(a)
|
||||
fields:
|
||||
site_date:
|
||||
selector: h2 a
|
||||
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: h2 a
|
||||
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
|
||||
@@ -61,32 +62,28 @@
|
||||
- name: re_replace
|
||||
args: ["(\\w+)$", ""]
|
||||
details:
|
||||
selector: h2 a
|
||||
selector: td:nth-child(1) a
|
||||
attribute: href
|
||||
download:
|
||||
selector: h2 a
|
||||
selector: td:nth-child(1) a
|
||||
attribute: href
|
||||
banner:
|
||||
selector: div.post_image
|
||||
attribute: src
|
||||
category:
|
||||
selector: p.meta span.post-category a
|
||||
|
||||
selector: td:nth-child(1) i
|
||||
attribute: class
|
||||
size:
|
||||
# there is no size on the primary search results page. defaulting to 500 MB
|
||||
text: "500 MB"
|
||||
selector: td:nth-child(2)
|
||||
date:
|
||||
selector: p.meta span.post-date a time.entry-date
|
||||
attribute: datetime
|
||||
filters:
|
||||
- name: dateparse
|
||||
args: "2006-01-02T15:04:05-07:00"
|
||||
text: now
|
||||
seeders:
|
||||
# there is no seeders on the primary search results page. defaulting to 0
|
||||
text: 0
|
||||
seeders:
|
||||
optional: true
|
||||
selector: td:nth-child(3)
|
||||
leechers:
|
||||
text: 0
|
||||
leechers:
|
||||
# there is no leechers on the primary search results page. defaulting to 0
|
||||
text: 0
|
||||
optional: true
|
||||
selector: td:nth-child(4)
|
||||
downloadvolumefactor:
|
||||
text: "0"
|
||||
uploadvolumefactor:
|
||||
|
@@ -113,3 +113,7 @@
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["Unknown", "0"]
|
||||
downloadvolumefactor:
|
||||
text: "0"
|
||||
uploadvolumefactor:
|
||||
text: "1"
|
||||
|
@@ -122,3 +122,7 @@
|
||||
selector: td:nth-child(7)
|
||||
grabs:
|
||||
selector: td:nth-child(8)
|
||||
downloadvolumefactor:
|
||||
text: "0"
|
||||
uploadvolumefactor:
|
||||
text: "1"
|
||||
|
@@ -1,93 +0,0 @@
|
||||
---
|
||||
site: OxTorrent
|
||||
name: OxTorrent
|
||||
description: "OxTorrent is a FRENCH Public site for TV / MOVIES / GENERAL"
|
||||
language: fr-fr
|
||||
type: public
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- http://www.oxtorrent.com/
|
||||
# legacylinks:
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
- {id: films, cat: Movies, desc: "Movies"}
|
||||
- {id: series, cat: TV, desc: "TV"}
|
||||
|
||||
modes:
|
||||
search: [q]
|
||||
tv-search: [q, season, ep]
|
||||
|
||||
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
|
||||
size:
|
||||
selector: td:nth-child(2)
|
||||
filters:
|
||||
- name: re_replace
|
||||
args: [ "\\.(\\d) Ko", "$1X00"]
|
||||
- name: re_replace
|
||||
args: [ " Ko", "000"]
|
||||
- name: re_replace
|
||||
args: [ "\\.(\\d) Mo", "$1X00000"]
|
||||
- name: re_replace
|
||||
args: [ " Mo", "000000"]
|
||||
- name: re_replace
|
||||
args: [ "\\.(\\d) Go", "$1X00000000"]
|
||||
- name: re_replace
|
||||
args: [ " Go", "000000000"]
|
||||
- name: re_replace
|
||||
args: [ "\\.(\\d) To", "$1X00000000000"]
|
||||
- name: re_replace
|
||||
args: [ " To", "000000000000"]
|
||||
- name: replace
|
||||
args: [ "X", "" ]
|
||||
date:
|
||||
text: "now"
|
||||
seeders:
|
||||
text: 0
|
||||
seeders:
|
||||
selector: td:nth-child(3)
|
||||
optional: true
|
||||
leechers:
|
||||
text: 0
|
||||
leechers:
|
||||
selector: td:nth-child(4)
|
||||
optional: true
|
||||
downloadvolumefactor:
|
||||
text: "0"
|
||||
uploadvolumefactor:
|
||||
text: "1"
|
@@ -44,6 +44,7 @@
|
||||
- selector: td.embedded:has(h2:contains("failed"))
|
||||
- selector: td.embedded:has(h2:contains("Error"))
|
||||
test:
|
||||
selector: a[href^="logout.php"]
|
||||
path: /browse.php
|
||||
|
||||
search:
|
||||
|
@@ -106,11 +106,14 @@
|
||||
|
||||
search:
|
||||
path: index.php
|
||||
keywordsfilters:
|
||||
- name: re_replace
|
||||
args: ["S0?(\\d{1,2})E(\\d{1,2})", "T$1 $2"]
|
||||
inputs:
|
||||
page: "torrents"
|
||||
$raw: "&category={{range .Categories}}{{.}};{{end}}"
|
||||
active: "1"
|
||||
search: "{{ .Query.Keywords }}"
|
||||
search: "{{ .Keywords }}"
|
||||
rows:
|
||||
selector: "#mcol .block-content-l table table.lista > tbody > tr:not(:first-child):not(.descripcion)"
|
||||
fields:
|
||||
@@ -122,6 +125,9 @@
|
||||
args: category
|
||||
title:
|
||||
selector: td:nth-child(2) a
|
||||
filters:
|
||||
- name: append
|
||||
args: " [spanish]"
|
||||
details:
|
||||
selector: td:nth-child(3) a
|
||||
attribute: href
|
||||
|
95
src/Jackett.Common/Definitions/racing4everyone.yml
Normal file
95
src/Jackett.Common/Definitions/racing4everyone.yml
Normal file
@@ -0,0 +1,95 @@
|
||||
---
|
||||
site: racing4everyone
|
||||
name: Racing4Everyone (R4E)
|
||||
description: "Private Torrent Tracker for RACING"
|
||||
language: en-us
|
||||
type: private
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- https://racing4everyone.eu/
|
||||
legacylinks:
|
||||
- https://racing4everyone.jp/
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
- {id: 1, cat: TV/Sport, desc: "BTCC"}
|
||||
- {id: 3, cat: TV/Sport, desc: "DTM"}
|
||||
- {id: 4, cat: TV/Sport, desc: "Formula 1 2018"}
|
||||
- {id: 6, cat: TV/Sport, desc: "Formula 1 2017-1950 (HD)"}
|
||||
- {id: 21, cat: TV/Sport, desc: "Formula 1 2017-1950 (SD)"}
|
||||
- {id: 22, cat: TV/Sport, desc: "Formula 2"}
|
||||
- {id: 23, cat: TV/Sport, desc: "Formula E"}
|
||||
- {id: 24, cat: TV/Sport, desc: "Misc"}
|
||||
- {id: 25, cat: TV/Sport, desc: "Motorbikes"}
|
||||
- {id: 26, cat: TV/Sport, desc: "MotoGP/2/3"}
|
||||
- {id: 31, cat: TV/Sport, desc: "Nascar"}
|
||||
- {id: 32, cat: TV/Sport, desc: "Stockcars"}
|
||||
- {id: 33, cat: TV/Sport, desc: "Touring Cars"}
|
||||
- {id: 50, cat: TV/Sport, desc: "WRC"}
|
||||
- {id: 53, cat: TV/Sport, desc: "Open-Wheelers"}
|
||||
- {id: 54, cat: TV/Sport, desc: "Documentaries/Movies"}
|
||||
- {id: 55, cat: TV/Sport, desc: "Season Reviews"}
|
||||
|
||||
modes:
|
||||
search: [q]
|
||||
|
||||
login:
|
||||
path: /login
|
||||
method: form
|
||||
inputs:
|
||||
username: "{{ .Config.username }}"
|
||||
password: "{{ .Config.password }}"
|
||||
error:
|
||||
- selector: table.main:contains("Login Failed!")
|
||||
test:
|
||||
path: /torrents
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: /filterTorrents
|
||||
inputs:
|
||||
$raw: "{{range .Categories}}categories[]={{.}}&{{end}}"
|
||||
search: "{{ .Keywords }}"
|
||||
uploader: ""
|
||||
sorting: created_at
|
||||
direction: desc
|
||||
qty: 100
|
||||
rows:
|
||||
selector: table > tbody > tr
|
||||
fields:
|
||||
category:
|
||||
selector: a[href*="/categories/"]
|
||||
attribute: href
|
||||
filters:
|
||||
- name: regexp
|
||||
args: "/categories/.*?\\.(\\d+)"
|
||||
title:
|
||||
selector: a.view-torrent
|
||||
download:
|
||||
selector: a[href*="/download/"]
|
||||
attribute: href
|
||||
details:
|
||||
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)
|
||||
filters:
|
||||
- name: regexp
|
||||
args: ([\d\.]+)
|
||||
date:
|
||||
selector: time
|
||||
downloadvolumefactor:
|
||||
case:
|
||||
"i[data-original-title=\"100% Free\"]": "0"
|
||||
"i[data-original-title=\"Global FreeLeech\"]": "0"
|
||||
"*": "1"
|
||||
uploadvolumefactor:
|
||||
case:
|
||||
"i[data-original-title=\"Double upload\"]": "2"
|
||||
"*": "1"
|
152
src/Jackett.Common/Definitions/rgu.yml
Normal file
152
src/Jackett.Common/Definitions/rgu.yml
Normal file
@@ -0,0 +1,152 @@
|
||||
---
|
||||
site: RGU
|
||||
name: RGU
|
||||
description: "RGU is a Private site for MOVIES / TV / GENERAL"
|
||||
language: en-us
|
||||
type: private
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- https://rgu.rgt.life/
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
- {id: 19, cat: Movies/BluRay, desc: "007 Movies"}
|
||||
- {id: 9, cat: TV/Anime, desc: "ANIME/HD"}
|
||||
- {id: 1, cat: PC/0day, desc: "Apps"}
|
||||
- {id: 18, cat: Movies/BluRay, desc: "Dr Who"}
|
||||
- {id: 5, cat: TV, desc: "TV Episodes"}
|
||||
- {id: 2, cat: PC/Games, desc: "Games/PC"}
|
||||
- {id: 11, cat: TV/HD, desc: "TV/HD"}
|
||||
- {id: 30, cat: Console/PS4, desc: "GAMES/PS4"}
|
||||
- {id: 7, cat: Console/PSP, desc: "Games/PSP"}
|
||||
- {id: 17, cat: Movies/BluRay, desc: "Movie Packs"}
|
||||
- {id: 10, cat: Movies, desc: "Movies X264"}
|
||||
- {id: 3, cat: Movies/DVD, desc: "Movies/DVDR"}
|
||||
- {id: 50, cat: Movies/BluRay, desc: "Movies/Bluray-UHD"}
|
||||
- {id: 31, cat: Movies/BluRay, desc: "MOVIES/COMPLETE-BLURAY"}
|
||||
- {id: 3, cat: Movies/DVD, desc: "MOVIES/DVDR"}
|
||||
- {id: 16, cat: TV, desc: "TV Packs"}
|
||||
- {id: 6, cat: XXX, desc: "MOVIES/XXX"}
|
||||
|
||||
|
||||
modes:
|
||||
search: [q]
|
||||
tv-search: [q, season, ep]
|
||||
movie-search: [q]
|
||||
|
||||
settings:
|
||||
- name: username
|
||||
type: text
|
||||
label: Username
|
||||
- name: password
|
||||
type: password
|
||||
label: Password
|
||||
- name: incldead
|
||||
type: select
|
||||
label: "Search Torrents that are:"
|
||||
default: "0"
|
||||
options:
|
||||
"0" : "Active"
|
||||
"1": "Including Dead"
|
||||
"2": "Only Dead"
|
||||
- name: onlyfree
|
||||
type: checkbox
|
||||
label: Show only Free torrents
|
||||
default: false
|
||||
- name: info
|
||||
type: info
|
||||
label: Results Per Page
|
||||
default: For best results, change the 'Torrents per page' setting to 100 on your profile.
|
||||
|
||||
login:
|
||||
path: login.php
|
||||
method: form
|
||||
form: form[action="takelogin.php"]
|
||||
inputs:
|
||||
username: "{{ .Config.username }}"
|
||||
password: "{{ .Config.password }}"
|
||||
submitme: "X"
|
||||
submitme: "X" # two submitme needed?!? shouldn't make a difference
|
||||
error:
|
||||
- selector: h2:contains("Login failed!")
|
||||
message:
|
||||
selector: td.colhead2
|
||||
test:
|
||||
path: browse.php
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: browse.php
|
||||
inputs:
|
||||
$raw: "{{range .Categories}}c{{.}}=1&{{end}}"
|
||||
search: "{{ .Keywords }}"
|
||||
searchin: "title"
|
||||
incldead: "{{ .Config.incldead }}"
|
||||
"only_free": "{{ if .Config.onlyfree }}1{{else}}0{{end}}"
|
||||
keywordsfilters:
|
||||
- name: re_replace
|
||||
args: ["(\\w+)", " +$1"] # prepend + to each word
|
||||
rows:
|
||||
selector: tr.browse_color, tr[id^="kdescr"]
|
||||
after: 1
|
||||
fields:
|
||||
category:
|
||||
selector: td:nth-of-type(1) a
|
||||
attribute: href
|
||||
filters:
|
||||
- name: querystring
|
||||
args: cat
|
||||
title:
|
||||
selector: td:nth-of-type(2) a
|
||||
attribute: onmouseover
|
||||
filters:
|
||||
- name: split
|
||||
args: [">", "1"]
|
||||
- name: replace
|
||||
args: ["</b", ""]
|
||||
details:
|
||||
selector: td:nth-of-type(2) > a[onmouseover]
|
||||
attribute: href
|
||||
banner:
|
||||
selector: td:nth-of-type(2) > a[onmouseover]
|
||||
attribute: onmouseover
|
||||
filters:
|
||||
- name: regexp
|
||||
args: "src=\\\\'(.+?)\\\\'"
|
||||
- name: replace
|
||||
args: ["./pic/noposter.png", ""]
|
||||
download:
|
||||
selector: td:nth-of-type(3) a
|
||||
attribute: href
|
||||
files:
|
||||
selector: td:nth-of-type(5)
|
||||
date:
|
||||
selector: td:nth-of-type(7)
|
||||
filters:
|
||||
- name: dateparse
|
||||
args: "Jan 02 2006 03:04 PM"
|
||||
size:
|
||||
selector: td:nth-of-type(8)
|
||||
grabs:
|
||||
selector: td:nth-of-type(9)
|
||||
filters:
|
||||
- name: regexp
|
||||
args: "([\\d]+)"
|
||||
seeders:
|
||||
selector: td:nth-of-type(10)
|
||||
leechers:
|
||||
selector: td:nth-of-type(11)
|
||||
description:
|
||||
selector: td[colspan="14"]
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["\n", "<br>\n"]
|
||||
downloadvolumefactor:
|
||||
case:
|
||||
"b:contains(\"[Free and Double]\")": "0"
|
||||
"img[alt=\"Free Torrent\"]": "0"
|
||||
"*": "1"
|
||||
uploadvolumefactor:
|
||||
case:
|
||||
"b:contains(\"[Free and Double]\")": "2"
|
||||
"*": "1"
|
@@ -6,58 +6,57 @@
|
||||
type: private
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- http://www.shareisland.org/
|
||||
legacylinks:
|
||||
- https://shareisland.org/
|
||||
- http://shareisland.org/
|
||||
legacylinks:
|
||||
- http://shareisland.org/
|
||||
- http://www.shareisland.org/
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
- {id: 36, cat: Other, desc: "Disclaimer"}
|
||||
# Applications
|
||||
- {id: 21, cat: PC/0day, desc: "PC"}
|
||||
- {id: 33, cat: PC/Phone-Android, desc: "Android applications"}
|
||||
- {id: 7, cat: PC/0day, desc: "PC Applications"}
|
||||
- {id: 8, cat: PC/0day, desc: "Apps Linux"}
|
||||
- {id: 9, cat: PC/MAC, desc: "Apps Mac"}
|
||||
|
||||
# Movies
|
||||
- {id: 11, cat: Movies/DVD, desc: "DVD"}
|
||||
- {id: 16, cat: Movies/SD, desc: "DivX"}
|
||||
- {id: 17, cat: Movies/SD, desc: "Cine News"}
|
||||
- {id: 18, cat: Movies/Other, desc: "Video"}
|
||||
- {id: 23, cat: Movies/SD, desc: "BDRip"}
|
||||
- {id: 27, cat: TV/SD, desc: "TV series"}
|
||||
- {id: 28, cat: Movies/Other, desc: "Rip By ShareIsland "}
|
||||
- {id: 29, cat: Movies/HD, desc: "720p"}
|
||||
- {id: 30, cat: Movies/HD, desc: "1080p"}
|
||||
- {id: 32, cat: Movies/SD, desc: "DVDRip"}
|
||||
- {id: 35, cat: Movies/BluRay, desc: "Blu Ray Disk"}
|
||||
- {id: 38, cat: Movies/HD, desc: "H-264"}
|
||||
- {id: 40, cat: Movies/HD, desc: "H-265"}
|
||||
- {id: 44, cat: Movies/HD, desc: "4K Ultra HD"}
|
||||
- {id: 45, cat: TV/HD, desc: "Series TV HD"}
|
||||
|
||||
- {id: 37, cat: Other, desc: "P2P network"}
|
||||
- {id: 39, cat: Other, desc: "test"}
|
||||
# Music
|
||||
- {id: 19, cat: Audio/MP3, desc: "Mp3"}
|
||||
|
||||
# Games
|
||||
# Vip
|
||||
- {id: 34, cat: XXX, desc: "Adulti"}
|
||||
- {id: 46, cat: Other, desc: "IPTV"}
|
||||
- {id: 57, cat: XXX, desc: "Riviste XXX"}
|
||||
- {id: 58, cat: XXX, desc: "Fumetti XXX"}
|
||||
# Applicazioni
|
||||
- {id: 33, cat: PC/Phone-Android, desc: "Android"}
|
||||
- {id: 8, cat: PC/0day, desc: "Linux"}
|
||||
- {id: 9, cat: PC/Mac, desc: "Mac"}
|
||||
- {id: 7, cat: PC/0day, desc: "PC"}
|
||||
# Books
|
||||
- {id: 43, cat: Books, desc: "Libreria"}
|
||||
- {id: 41, cat: Books, desc: "Quotidiani"}
|
||||
- {id: 59, cat: Books, desc: "Fumetti"}
|
||||
- {id: 60, cat: Books, desc: "Riviste"}
|
||||
- {id: 61, cat: Books, desc: "Audiolibri"}
|
||||
# Games
|
||||
- {id: 47, cat: PC/Games, desc: "Games PC"}
|
||||
- {id: 40, cat: Console/Other, desc: "Nintendo"}
|
||||
- {id: 13, cat: Console/PS4, desc: "Sony PS"}
|
||||
- {id: 33, cat: Console/Xbox, desc: "XboX"}
|
||||
- {id: 14, cat: Console/Wii, desc: "Wii"}
|
||||
- {id: 20, cat: Console/Xbox, desc: "XboX"}
|
||||
- {id: 22, cat: Console/Other, desc: "Nintendo"}
|
||||
# Music
|
||||
- {id: 54, cat: Audio/MP3, desc: "MP3"}
|
||||
- {id: 55, cat: Audio/Lossless, desc: "Flac"}
|
||||
# Movies
|
||||
- {id: 17, cat: Movies/SD, desc: "Cine News"}
|
||||
- {id: 43, cat: Movies/SD, desc: "BDRip"}
|
||||
- {id: 16, cat: Movies/SD, desc: "DivX"}
|
||||
- {id: 20, cat: Movies/SD, desc: "DVDRip"}
|
||||
- {id: 21, cat: Movies/DVD, desc: "DVD"}
|
||||
- {id: 25, cat: Movies/HD, desc: "720p"}
|
||||
- {id: 24, cat: Movies/HD, desc: "1080p"}
|
||||
- {id: 27, cat: Movies/BluRay, desc: "Blu Ray Disk"}
|
||||
- {id: 23, cat: Movies/HD, desc: "H-265"}
|
||||
- {id: 26, cat: Movies/3D, desc: "3D-FullHD"}
|
||||
- {id: 31, cat: TV/SD, desc: "SerieTV"}
|
||||
- {id: 45, cat: TV/HD, desc: "Serie Tv HD"}
|
||||
- {id: 22, cat: Movies/UHD, desc: "4K-Ultra-HD"}
|
||||
- {id: 49, cat: TV/Documentary, desc: "Documentari"}
|
||||
- {id: 50, cat: TV/Other, desc: "Programmi TV"}
|
||||
- {id: 51, cat: Movies/Other, desc: "Mp4"}
|
||||
|
||||
# Anime
|
||||
- {id: 31, cat: TV/Anime, desc: "Cartoons"}
|
||||
|
||||
# Books
|
||||
- {id: 26, cat: Books, desc: "Newsstand"}
|
||||
- {id: 41, cat: Books, desc: "Newspapers"}
|
||||
- {id: 43, cat: Books, desc: "library"}
|
||||
|
||||
- {id: 4, cat: Other, desc: "Other"}
|
||||
- {id: 5, cat: TV/Anime, desc: "Anime"}
|
||||
|
||||
modes:
|
||||
search: [q]
|
||||
@@ -169,29 +168,34 @@
|
||||
- name: regexp
|
||||
args: "src=(.+?) "
|
||||
size:
|
||||
selector: td:nth-child(11)
|
||||
selector: td:nth-child(10)
|
||||
date:
|
||||
selector: td:nth-child(6)
|
||||
selector: td:nth-child(5)
|
||||
filters:
|
||||
- name: dateparse
|
||||
args: "02/01/2006"
|
||||
grabs:
|
||||
selector: td:nth-child(9)
|
||||
selector: td:nth-child(8)
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["---", "0"]
|
||||
seeders:
|
||||
selector: td:nth-child(7)
|
||||
selector: td:nth-child(6)
|
||||
leechers:
|
||||
selector: td:nth-child(8)
|
||||
selector: td:nth-child(7)
|
||||
downloadvolumefactor:
|
||||
case:
|
||||
img[alt="Free Leech"]: "0"
|
||||
img[alt="Gold 100% Free"]: "0"
|
||||
img[alt="Silver 50% Free"]: "0.5"
|
||||
img[alt="Bronze 25% Free"]: "0.25"
|
||||
img[alt="Bronze 25% Free"]: "0.75"
|
||||
"*": "1"
|
||||
uploadvolumefactor:
|
||||
case:
|
||||
img[alt="2x Upload Multiplier"]: "2"
|
||||
"*": "1"
|
||||
text: "1"
|
||||
uploadvolumefactor:
|
||||
optional: true
|
||||
selector: img[alt$="x Upload Multiplier"]
|
||||
attribute: alt
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["x Upload Multiplier", ""]
|
||||
|
@@ -226,7 +226,7 @@
|
||||
selector: a[href^="torrents-details.php?id="]
|
||||
filters:
|
||||
- name: re_replace
|
||||
args: ["(Ep[\\.]?[ ]?)|([S]\\d\\d[Ee])", "E"]
|
||||
args: ["(Ep[\\.]?[ ]?(\\d{1,3}))", "E$2"]
|
||||
title_normal:
|
||||
selector: a[href^="torrents-details.php?id="]
|
||||
filters:
|
||||
@@ -273,11 +273,15 @@
|
||||
- name: replace
|
||||
args: ["Resolução:", ""]
|
||||
- name: re_replace
|
||||
args: ["(\\d{3,4})[ ]?x[ ]?(1[0-9][0-9][0-9])", "1080p"]
|
||||
args: ["(\\d{3,4})[ ]?[xX][ ]?(1[0-9][0-9][0-9])", "1080p"]
|
||||
- name: re_replace
|
||||
args: ["(\\d{3,4})[ ]?x[ ]?([2-9][0-9][0-9][0-9])", "2160p"]
|
||||
args: ["(\\d{3,4})[ ]?[xX][ ]?([2-9][0-9][0-9][0-9])", "2160p"]
|
||||
- name: re_replace
|
||||
args: ["(\\d{3,4})[ ]?x[ ]?([7-9][0-9][0-9])", "720p"]
|
||||
args: ["(\\d{3,4})[ ]?[xX][ ]?([6-9][0-9][0-9])", "720p"]
|
||||
- name: re_replace
|
||||
args: ["(\\d{3,4})[ ]?[xX][ ]?([3-5][0-9][0-9])", "480p"]
|
||||
- name: re_replace
|
||||
args: ["(\\d{3,4})[ ]?[xX][ ]?([1-2][0-9][0-9])", "240p"]
|
||||
download:
|
||||
selector: a[href^="torrents-details.php?id="]
|
||||
attribute: href
|
||||
|
105
src/Jackett.Common/Definitions/sukebei-pantsu.yml
Normal file
105
src/Jackett.Common/Definitions/sukebei-pantsu.yml
Normal file
@@ -0,0 +1,105 @@
|
||||
#,==========,
|
||||
#| | | |
|
||||
#`-./ \.-' - Config'd by Quatroking (05-05-2017), updated by AeonLucid (26-05-2017) -
|
||||
# `.__.'
|
||||
|
||||
---
|
||||
site: sukebei-pantsu
|
||||
name: Sukebei-pantsu
|
||||
description: "Sukebei-pantsu is a Public site dedicated to Adult Asian content"
|
||||
language: en-en
|
||||
type: public
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- https://sukebei.pantsu.cat/
|
||||
|
||||
settings:
|
||||
- name: cat-id
|
||||
type: select
|
||||
label: Category
|
||||
default: "_"
|
||||
options:
|
||||
_: "All categories"
|
||||
1_: "Art"
|
||||
1_1: "Art - Anime"
|
||||
1_2: "Art - Doujinshi"
|
||||
1_3: "Art - Games"
|
||||
1_4: "Art - Manga"
|
||||
1_5: "Art - Pictures"
|
||||
2_: "Real Life"
|
||||
2_1: "Real Life - Photobooks and Pictures"
|
||||
2_2: "Real Life - Videos"
|
||||
- name: filter-id
|
||||
type: select
|
||||
label: Filter
|
||||
default: "0"
|
||||
options:
|
||||
0: "Show all"
|
||||
1: "Filter Remakes"
|
||||
2: "Trusted"
|
||||
3: "A+"
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
# Art
|
||||
- {id: 1_, cat: XXX, desc: "Adult Art"}
|
||||
- {id: 1_1, cat: XXX, desc: "Adult Anime"}
|
||||
- {id: 1_2, cat: XXX, desc: "Doujinshi"}
|
||||
- {id: 1_3, cat: XXX, desc: "Adult Games"}
|
||||
- {id: 1_4, cat: XXX, desc: "Adult Manga"}
|
||||
- {id: 1_5, cat: XXX, desc: "Adult Pictures"}
|
||||
# Real Life
|
||||
- {id: 2_, cat: XXX, desc: "Adult Real Life"}
|
||||
- {id: 2_1, cat: XXX, desc: "Adult Photobooks and Pictures"}
|
||||
- {id: 2_2, cat: XXX, desc: "Adult Videos"}
|
||||
modes:
|
||||
search: [q]
|
||||
tv-search: [q]
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: /search
|
||||
inputs:
|
||||
q: "{{ .Query.Keywords }}"
|
||||
c: "{{ .Config.cat-id }}"
|
||||
s: "{{ .Config.filter-id }}"
|
||||
rows:
|
||||
selector: tr.torrent-info
|
||||
fields:
|
||||
title:
|
||||
selector: td.tr-name a
|
||||
category:
|
||||
selector: td:nth-child(1) a
|
||||
attribute: href
|
||||
filters:
|
||||
- name: split
|
||||
args: [ "=", -1 ]
|
||||
details:
|
||||
selector: td.tr-name a
|
||||
attribute: href
|
||||
download:
|
||||
selector: a[title="Magnet Link"]
|
||||
attribute: href
|
||||
seeders:
|
||||
selector: td.tr-se
|
||||
optional: true
|
||||
leechers:
|
||||
selector: td.tr-le
|
||||
optional: true
|
||||
grabs:
|
||||
selector: td.tr-dl
|
||||
optional: true
|
||||
date:
|
||||
selector: td.date-short
|
||||
filters:
|
||||
- name: dateparse
|
||||
args: "2006-01-02T15:04:05Z"
|
||||
size:
|
||||
selector: td.tr-size
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["Unknown", "0"]
|
||||
downloadvolumefactor:
|
||||
text: "0"
|
||||
uploadvolumefactor:
|
||||
text: "1"
|
98
src/Jackett.Common/Definitions/sukebeinyaasi.yml
Normal file
98
src/Jackett.Common/Definitions/sukebeinyaasi.yml
Normal file
@@ -0,0 +1,98 @@
|
||||
---
|
||||
site: sukebeinyaasi
|
||||
name: sukebei.nyaa.si
|
||||
description: "sukebei.nyaa is a Public torrent site focused on adult Eastern Asian media including anime, manga, games and JAV"
|
||||
language: en-us
|
||||
type: public
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- https://sukebei.nyaa.si
|
||||
|
||||
settings:
|
||||
- name: filter-id
|
||||
type: select
|
||||
label: Filter
|
||||
default: "0"
|
||||
options:
|
||||
0: No filter
|
||||
1: No remakes
|
||||
2: Trusted only
|
||||
- name: cat-id
|
||||
type: select
|
||||
label: Category
|
||||
default: "0_0"
|
||||
options:
|
||||
0_0: "All categories"
|
||||
1_0: "Art"
|
||||
1_1: "Art - Anime"
|
||||
1_2: "Art - Doujinshi"
|
||||
1_3: "Art - Games"
|
||||
1_4: "Art - Manga"
|
||||
1_5: "Art - Pictures"
|
||||
2_0: "Real Life"
|
||||
2_1: "Real Life - Photobooks and Pictures"
|
||||
2_2: "Real Life - Videos"
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
# Art
|
||||
- {id: 1_0, cat: XXX, desc: "Adult Art"}
|
||||
- {id: 1_1, cat: XXX, desc: "Adult Anime"}
|
||||
- {id: 1_2, cat: XXX, desc: "Doujinshi"}
|
||||
- {id: 1_3, cat: XXX, desc: "Adult Games"}
|
||||
- {id: 1_4, cat: XXX, desc: "Adult Manga"}
|
||||
- {id: 1_5, cat: XXX, desc: "Adult Pictures"}
|
||||
# Real Life
|
||||
- {id: 2_0, cat: XXX, desc: "Adult Real Life"}
|
||||
- {id: 2_1, cat: XXX, desc: "Adult Photobooks and Pictures"}
|
||||
- {id: 2_2, cat: XXX, desc: "Adult Videos"}
|
||||
modes:
|
||||
search: [q]
|
||||
tv-search: [q]
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: /
|
||||
inputs:
|
||||
q: "{{ .Query.Keywords}}"
|
||||
f: "{{ .Config.filter-id }}"
|
||||
c: "{{ .Config.cat-id }}"
|
||||
rows:
|
||||
selector: tr.default,tr.danger,tr.success
|
||||
fields:
|
||||
category:
|
||||
selector: td:nth-child(1) a
|
||||
attribute: href
|
||||
filters:
|
||||
- name: split
|
||||
args: [ "=", -1 ]
|
||||
title:
|
||||
selector: td:nth-child(2) a:last-of-type
|
||||
details:
|
||||
selector: td:nth-child(2) a:last-of-type
|
||||
attribute: href
|
||||
download:
|
||||
selector: td:nth-child(3) a[href$=".torrent"]
|
||||
attribute: href
|
||||
magnet:
|
||||
selector: td:nth-child(3) a[href^="magnet:?"]
|
||||
attribute: href
|
||||
size:
|
||||
selector: td:nth-child(4)
|
||||
date:
|
||||
selector: td:nth-child(5)
|
||||
filters:
|
||||
- name: append
|
||||
args: " -00"
|
||||
- name: dateparse
|
||||
args: "2006-01-02 15:04 -07"
|
||||
seeders:
|
||||
selector: td:nth-child(6)
|
||||
leechers:
|
||||
selector: td:nth-child(7)
|
||||
grabs:
|
||||
selector: td:nth-child(8)
|
||||
downloadvolumefactor:
|
||||
text: "0"
|
||||
uploadvolumefactor:
|
||||
text: "1"
|
@@ -14,69 +14,83 @@
|
||||
caps:
|
||||
categorymappings:
|
||||
#Audio
|
||||
- {id: 101, cat: Audio, desc: "Music"}
|
||||
- {id: 102, cat: Audio/Audiobook, desc: "Audio books"}
|
||||
- {id: 103, cat: Audio, desc: "Sound clips"}
|
||||
- {id: 104, cat: Audio/Lossless, desc: "FLAC"}
|
||||
- {id: 199, cat: Audio/Other, desc: "Audio Other"}
|
||||
- {id: 100, cat: Audio, desc: "Audio", default: true}
|
||||
- {id: 101, cat: Audio, desc: "Music", default: true}
|
||||
- {id: 102, cat: Audio/Audiobook, desc: "Audio books", default: true}
|
||||
- {id: 103, cat: Audio, desc: "Sound clips", default: true}
|
||||
- {id: 104, cat: Audio/Lossless, desc: "FLAC", default: true}
|
||||
- {id: 199, cat: Audio/Other, desc: "Audio Other", default: true}
|
||||
|
||||
#Video
|
||||
- {id: 201, cat: Movies, desc: "Movies"}
|
||||
- {id: 202, cat: Movies/DVD, desc: "Movies DVDR"}
|
||||
- {id: 203, cat: Audio/Video, desc: "Music videos"}
|
||||
- {id: 204, cat: Movies/Other, desc: "Movie clips"}
|
||||
- {id: 205, cat: TV, desc: "TV shows"}
|
||||
- {id: 206, cat: TV/Other, desc: "Handheld"}
|
||||
- {id: 207, cat: Movies/HD, desc: "HD - Movies"}
|
||||
- {id: 208, cat: TV/HD, desc: "HD - TV shows"}
|
||||
- {id: 209, cat: Movies/3D, desc: "3D"}
|
||||
- {id: 299, cat: Movies/Other, desc: "Video Other"}
|
||||
- {id: 200, cat: Movies, desc: "Video", default: true}
|
||||
- {id: 201, cat: Movies, desc: "Movies", default: true}
|
||||
- {id: 202, cat: Movies/DVD, desc: "Movies DVDR", default: true}
|
||||
- {id: 203, cat: Audio/Video, desc: "Music videos", default: true}
|
||||
- {id: 204, cat: Movies/Other, desc: "Movie clips", default: true}
|
||||
- {id: 205, cat: TV, desc: "TV shows", default: true}
|
||||
- {id: 206, cat: TV/Other, desc: "Handheld", default: true}
|
||||
- {id: 207, cat: Movies/HD, desc: "HD - Movies", default: true}
|
||||
- {id: 208, cat: TV/HD, desc: "HD - TV shows", default: true}
|
||||
- {id: 209, cat: Movies/3D, desc: "3D", default: true}
|
||||
- {id: 299, cat: Movies/Other, desc: "Video Other", default: true}
|
||||
|
||||
#Applications
|
||||
- {id: 301, cat: PC, desc: "Windows"}
|
||||
- {id: 302, cat: PC/Mac, desc: "Mac"}
|
||||
- {id: 303, cat: PC, desc: "UNIX"}
|
||||
- {id: 304, cat: PC/Phone-Other, desc: "Handheld"}
|
||||
- {id: 305, cat: PC/Phone-IOS, desc: "IOS (iPad/iPhone)"}
|
||||
- {id: 306, cat: PC/Phone-Android, desc: "Android"}
|
||||
- {id: 399, cat: PC, desc: "Other OS"}
|
||||
- {id: 300, cat: PC, desc: "Applications", default: true}
|
||||
- {id: 301, cat: PC, desc: "Windows", default: true}
|
||||
- {id: 302, cat: PC/Mac, desc: "Mac", default: true}
|
||||
- {id: 303, cat: PC, desc: "UNIX", default: true}
|
||||
- {id: 304, cat: PC/Phone-Other, desc: "Handheld", default: true}
|
||||
- {id: 305, cat: PC/Phone-IOS, desc: "IOS (iPad/iPhone)", default: true}
|
||||
- {id: 306, cat: PC/Phone-Android, desc: "Android", default: true}
|
||||
- {id: 399, cat: PC, desc: "Other OS", default: true}
|
||||
|
||||
#Games
|
||||
- {id: 401, cat: PC/Games, desc: "PC"}
|
||||
- {id: 402, cat: PC/Mac, desc: "Mac"}
|
||||
- {id: 403, cat: Console/PS4, desc: "PSx"}
|
||||
- {id: 404, cat: Console/Xbox, desc: "XBOX360"}
|
||||
- {id: 405, cat: Console/Wii, desc: "Wii"}
|
||||
- {id: 406, cat: Console/Other, desc: "Handheld"}
|
||||
- {id: 407, cat: Console/Other, desc: "IOS (iPad/iPhone)"}
|
||||
- {id: 408, cat: Console/Other, desc: "Android"}
|
||||
- {id: 499, cat: Console/Other, desc: "Games Other"}
|
||||
- {id: 401, cat: Console, desc: "Games", default: true}
|
||||
- {id: 401, cat: PC/Games, desc: "PC", default: true}
|
||||
- {id: 402, cat: PC/Mac, desc: "Mac", default: true}
|
||||
- {id: 403, cat: Console/PS4, desc: "PSx", default: true}
|
||||
- {id: 404, cat: Console/Xbox, desc: "XBOX360", default: true}
|
||||
- {id: 405, cat: Console/Wii, desc: "Wii", default: true}
|
||||
- {id: 406, cat: Console/Other, desc: "Handheld", default: true}
|
||||
- {id: 407, cat: Console/Other, desc: "IOS (iPad/iPhone)", default: true}
|
||||
- {id: 408, cat: Console/Other, desc: "Android", default: true}
|
||||
- {id: 499, cat: Console/Other, desc: "Games Other", default: true}
|
||||
|
||||
#Porn
|
||||
- {id: 501, cat: XXX, desc: "Movies"}
|
||||
- {id: 502, cat: XXX/DVD, desc: "Movies DVDR"}
|
||||
- {id: 503, cat: XXX/Imageset, desc: "Pictures"}
|
||||
- {id: 504, cat: XXX, desc: "Games"}
|
||||
- {id: 505, cat: XXX, desc: "HD - Movies"}
|
||||
- {id: 506, cat: XXX, desc: "Movie clips"}
|
||||
- {id: 599, cat: XXX/Other, desc: "Porn Other"}
|
||||
- {id: 500, cat: XXX, desc: "Porn", default: true}
|
||||
- {id: 501, cat: XXX, desc: "Movies", default: true}
|
||||
- {id: 502, cat: XXX/DVD, desc: "Movies DVDR", default: true}
|
||||
- {id: 503, cat: XXX/Imageset, desc: "Pictures", default: true}
|
||||
- {id: 504, cat: XXX, desc: "Games", default: true}
|
||||
- {id: 505, cat: XXX, desc: "HD - Movies", default: true}
|
||||
- {id: 506, cat: XXX, desc: "Movie clips", default: true}
|
||||
- {id: 599, cat: XXX/Other, desc: "Porn Other", default: true}
|
||||
|
||||
#Other
|
||||
- {id: 601, cat: Books, desc: "E-books"}
|
||||
- {id: 602, cat: Books/Comics, desc: "Comics"}
|
||||
- {id: 603, cat: Books, desc: "Pictures"}
|
||||
- {id: 604, cat: Books, desc: "Covers"}
|
||||
- {id: 605, cat: Books, desc: "Physibles"}
|
||||
- {id: 699, cat: Books/Other, desc: "Other Other"}
|
||||
- {id: 600, cat: Other, desc: "Other", default: true}
|
||||
- {id: 601, cat: Books, desc: "E-books", default: true}
|
||||
- {id: 602, cat: Books/Comics, desc: "Comics", default: true}
|
||||
- {id: 603, cat: Books, desc: "Pictures", default: true}
|
||||
- {id: 604, cat: Books, desc: "Covers", default: true}
|
||||
- {id: 605, cat: Books, desc: "Physibles", default: true}
|
||||
- {id: 699, cat: Books/Other, desc: "Other Other", default: true}
|
||||
|
||||
modes:
|
||||
tv-search: [q, season, ep]
|
||||
|
||||
settings: []
|
||||
settings:
|
||||
- name: order
|
||||
type: select
|
||||
label: Order results
|
||||
default: "99"
|
||||
options:
|
||||
"99": "Default"
|
||||
"8": "Seeders"
|
||||
"3": "Time"
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: "{{if .Query.Keywords}}/search/{{ .Keywords}}/0/99/{{range .Categories }}{{.}}{{end}}{{else}}/recent{{end}}"
|
||||
- path: "{{if .Query.Keywords}}/search/{{ .Keywords}}/0/{{ .Config.order }}/{{join .Categories \",\"}}{{else}}/recent{{end}}"
|
||||
keywordsfilters:
|
||||
# currently, the only uploader for General Hospital puts a space between season and episode
|
||||
# this filter searches both formats, so "General Hospital S01E02" becomes "General Hospital S01E02 | (S01 E02)"
|
||||
@@ -86,7 +100,13 @@
|
||||
rows:
|
||||
selector: "#searchResult tbody tr:has(td.vertTh)"
|
||||
fields:
|
||||
category:
|
||||
category: # parent category
|
||||
selector: td:nth-child(1) a:first-child
|
||||
attribute: href
|
||||
filters:
|
||||
- name: split
|
||||
args: [ "/", -1 ]
|
||||
category: # sub category
|
||||
selector: td:nth-child(1) a:last-child
|
||||
attribute: href
|
||||
filters:
|
||||
|
@@ -128,18 +128,18 @@
|
||||
- name: replace
|
||||
args: ["pic/noposter.jpg", ""]
|
||||
files:
|
||||
selector: td:nth-child(5)
|
||||
selector: td:nth-child(4)
|
||||
grabs:
|
||||
selector: td:nth-child(8)
|
||||
selector: td:nth-child(7)
|
||||
filters:
|
||||
- name: regexp
|
||||
args: (\d+)
|
||||
size:
|
||||
selector: td:nth-child(7)
|
||||
selector: td:nth-child(6)
|
||||
seeders:
|
||||
selector: td:nth-child(9)
|
||||
selector: td:nth-child(8)
|
||||
leechers:
|
||||
selector: td:nth-child(10)
|
||||
selector: td:nth-child(9)
|
||||
downloadvolumefactor:
|
||||
case:
|
||||
img[title="FreeLeech"]: "0"
|
||||
|
@@ -34,15 +34,8 @@
|
||||
page: 1
|
||||
srcrel: "{{ .Keywords }}"
|
||||
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 "]
|
||||
rows:
|
||||
selector: div.showrelease_tb table tbody tr:not(tr:nth-child(1))
|
||||
fields:
|
||||
@@ -54,27 +47,9 @@
|
||||
filters:
|
||||
- name: split
|
||||
args: ["=", "-1"]
|
||||
# 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
|
||||
args: ["\\b([s])?(\\d{1,3})[x\\s](\\d{1,3})", "S$2E$3"]
|
||||
details:
|
||||
selector: td:nth-child(7) a
|
||||
attribute: href
|
||||
|
@@ -26,18 +26,42 @@
|
||||
|
||||
modes:
|
||||
search: [q]
|
||||
tv-search: [q, season, ep]
|
||||
|
||||
settings: []
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: "{{if .Keywords}}/all/torrents/{{ .Keywords }}.html{{else}}/fresh.html{{end}}"
|
||||
- path: "{{if .Keywords}}/television/torrents/{{ .Keywords }}.html{{else}}/television/1/added/desc.html{{end}}"
|
||||
categorymappings: [TELEVISION]
|
||||
- path: "{{if .Keywords}}/movies/torrents/{{ .Keywords }}.html{{else}}/movies/1/added/desc.html{{end}}"
|
||||
categorymappings: [MOVIES]
|
||||
- path: "{{if .Keywords}}/music/torrents/{{ .Keywords }}.html{{else}}/music/1/added/desc.html{{end}}"
|
||||
categorymappings: [MUSIC]
|
||||
- path: "{{if .Keywords}}/games/torrents/{{ .Keywords }}.html{{else}}/games/1/added/desc.html{{end}}"
|
||||
categorymappings: [GAMES]
|
||||
- path: "{{if .Keywords}}/software/torrents/{{ .Keywords }}.html{{else}}/software/1/added/desc.html{{end}}"
|
||||
categorymappings: [SOFTWARE]
|
||||
- path: "{{if .Keywords}}/anime/torrents/{{ .Keywords }}.html{{else}}/anime/1/added/desc.html{{end}}"
|
||||
categorymappings: [ANIME]
|
||||
- path: "{{if .Keywords}}/ebooks/torrents/{{ .Keywords }}.html{{else}}/ebooks/1/added/desc.html{{end}}"
|
||||
categorymappings: [EBOOKS]
|
||||
- path: "{{if .Keywords}}/unknown/torrents/{{ .Keywords }}.html{{else}}/unknown.html{{end}}" # sorting is broken for unknown
|
||||
categorymappings: [OTHER]
|
||||
- path: "{{if .Keywords}}/adult/torrents/{{ .Keywords }}.html{{else}}/adult/1/added/desc.html{{end}}"
|
||||
categorymappings: [ADULT]
|
||||
- path: "{{if .Keywords}}/audiobooks/torrents/{{ .Keywords }}.html{{else}}/audiobooks/1/added/desc.html{{end}}"
|
||||
categorymappings: [AUDIOBOOK]
|
||||
- path: "{{if .Keywords}}/images/torrents/{{ .Keywords }}.html{{else}}/images/1/added/desc.html{{end}}"
|
||||
categorymappings: [IMAGES]
|
||||
keywordsfilters:
|
||||
- name: tolower
|
||||
- name: re_replace
|
||||
args: ["[^a-zA-Z0-9]+", "-"]
|
||||
rows:
|
||||
selector: table > tbody > tr:has(td:has(div:has(a[href^="/torrent/"])))
|
||||
filters:
|
||||
- name: andmatch
|
||||
fields:
|
||||
title:
|
||||
selector: td:nth-child(1) > div > a
|
||||
@@ -58,7 +82,7 @@
|
||||
selector: td:nth-child(2)
|
||||
filters:
|
||||
- name: re_replace
|
||||
args: ["(day|hour)s?$", "$0s ago"] # add ago to relative dates (fresh torrents page)
|
||||
args: ["(day|hour|min)s?$", "$0s ago"] # add ago to relative dates (fresh torrents page)
|
||||
size:
|
||||
selector: td:nth-child(3)
|
||||
seeders:
|
||||
@@ -80,6 +104,7 @@
|
||||
span.tv8: EBOOKS
|
||||
span.tv9: IMAGES
|
||||
span.tv12: AUDIOBOOK
|
||||
"*": "" # some torrents have invalid categories
|
||||
downloadvolumefactor:
|
||||
text: "1"
|
||||
uploadvolumefactor:
|
||||
|
111
src/Jackett.Common/Definitions/torrent-turk.yml
Normal file
111
src/Jackett.Common/Definitions/torrent-turk.yml
Normal file
@@ -0,0 +1,111 @@
|
||||
---
|
||||
site: torrent-turk
|
||||
name: TOrrent-tuRK
|
||||
description: "TOrrent-tuRK (TORK) is a Turkish Private Torrent Tracker for HD MOVIES / TV / GENERAL"
|
||||
language: tr-TR
|
||||
type: private
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- https://torrent-turk.org/
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
- {id: 149, cat: Movies, desc: "Movies/Turkish"}
|
||||
- {id: 151, cat: Movies/HD, desc: "Movies/Turkish/1080p"}
|
||||
- {id: 152, cat: Movies/HD, desc: "Movies/Turkish/720p"}
|
||||
|
||||
- {id: 156, cat: Movies, desc: "Movies/Foreign"}
|
||||
- {id: 157, cat: Movies/UHD, desc: "Movies/Foreign/4K"}
|
||||
- {id: 159, cat: Movies/HD, desc: "Movies/Foreign/1080p"}
|
||||
- {id: 160, cat: Movies/HD, desc: "Movies/Foreign/720p"}
|
||||
|
||||
- {id: 164, cat: TV, desc: "TV"}
|
||||
- {id: 165, cat: TV, desc: "TV/Turkish"}
|
||||
- {id: 166, cat: TV, desc: "TV/Foreign"}
|
||||
|
||||
- {id: 171, cat: Audio, desc: "Music"}
|
||||
- {id: 172, cat: Audio, desc: "Music/Turkish"}
|
||||
- {id: 173, cat: Audio, desc: "Music/Foreign"}
|
||||
|
||||
modes:
|
||||
search: [q]
|
||||
tv-search: [q]
|
||||
movie-search: [q]
|
||||
|
||||
login:
|
||||
path: /?p=home&pid=1
|
||||
method: form
|
||||
form: form#loginbox_form
|
||||
submitpath: /ajax/login.php
|
||||
inputs:
|
||||
action: "login"
|
||||
loginbox_membername: "{{ .Config.username }}"
|
||||
loginbox_password: "{{ .Config.password }}"
|
||||
loginbox_remember: "true"
|
||||
selectorinputs:
|
||||
securitytoken:
|
||||
selector: "script:contains(\"stKey: \")"
|
||||
filters:
|
||||
- name: regexp
|
||||
args: "stKey: \"(.+?)\","
|
||||
error:
|
||||
- selector: ":contains(\"-ERROR-\")"
|
||||
test:
|
||||
path: /?p=torrents&type=bookmarks&pid=508
|
||||
selector: a#logout
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: /
|
||||
keywordsfilters:
|
||||
- name: re_replace
|
||||
args: ["[^a-zA-Z0-9]+", "%25"]
|
||||
inputs:
|
||||
p: "torrents"
|
||||
pid: "32"
|
||||
$raw: "{{range .Categories}}cid[]={{.}}&{{end}}"
|
||||
keywords: "{{ .Keywords }}"
|
||||
search_type: "name"
|
||||
searchin: "title"
|
||||
error:
|
||||
- selector: div.error:not(:contains("Hiçbir sonuç bulunamadı."))
|
||||
rows:
|
||||
selector: table#torrents_table_classic > tbody > tr:has(td.torrent_name)
|
||||
fields:
|
||||
title:
|
||||
selector: a[href*="?p=torrents&pid=10&action=details"]
|
||||
category:
|
||||
selector: div.category_image > a
|
||||
attribute: href
|
||||
filters:
|
||||
- name: querystring
|
||||
args: cid
|
||||
details:
|
||||
selector: a[href*="?p=torrents&pid=10&action=details"]
|
||||
attribute: href
|
||||
download:
|
||||
selector: a[href*="?p=torrents&pid=10&action=download"]
|
||||
attribute: href
|
||||
size:
|
||||
selector: a[rel="torrent_size"]
|
||||
seeders:
|
||||
selector: a[rel="torrent_seeders"]
|
||||
leechers:
|
||||
selector: a[rel="torrent_leechers"]
|
||||
grabs:
|
||||
selector: a[rel="times_completed"]
|
||||
banner:
|
||||
selector: a[rel="fancybox"]
|
||||
optional: true
|
||||
attribute: href
|
||||
downloadvolumefactor:
|
||||
case:
|
||||
"img[title=\"FREE!\"]": "0"
|
||||
"*": "1"
|
||||
uploadvolumefactor:
|
||||
case:
|
||||
"*": "1"
|
||||
date:
|
||||
selector: td.torrent_name > abbr.timeago
|
||||
optional: true
|
||||
attribute: data-time
|
@@ -6,8 +6,10 @@
|
||||
type: public
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- http://www.torrent9.red/
|
||||
- http://www.torrent9.blue/
|
||||
legacylinks:
|
||||
- http://www.torrent9.ec/
|
||||
- http://www.torrent9.red/
|
||||
- http://www.torrent9.bz/
|
||||
- http://www.torrents9.pe/
|
||||
- http://www.torrent9.cc/
|
||||
@@ -27,33 +29,12 @@
|
||||
search: [q]
|
||||
tv-search: [q, season, ep]
|
||||
|
||||
settings:
|
||||
- name: category
|
||||
type: select
|
||||
label: Category Filter
|
||||
default: "/"
|
||||
options:
|
||||
"/" : "All"
|
||||
"/films/": "Movies"
|
||||
"/films-french/": "Movies/French"
|
||||
"/films-vostfr/": "Movies/VOSTFR"
|
||||
"/films-dvdrip-x264/": "Movies/DVDRIP .x264"
|
||||
"/720p/": "Movies/BluRay 720p"
|
||||
"/1080p/": "Movies/BluRay 1080p"
|
||||
"/series/": "TV/Series"
|
||||
"/series-vostfr/": "TV/VOSTFR"
|
||||
"/series-francaise/": "TV/French"
|
||||
"/series-dvdrip/": "TV/DVDRIP"
|
||||
"/spectacles/": "Shows"
|
||||
"/musique/": "Music"
|
||||
"/ebook/": "Ebooks"
|
||||
"/logiciels/": "Software"
|
||||
"/jeux-pc/": "PC Games"
|
||||
"/jeux-consoles/": "Console Games"
|
||||
|
||||
download:
|
||||
selector: a[href^="/downloading/"]
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: "{{ if .Keywords }}/search_torrent{{ .Config.category }}{{ .Keywords }}/page-0{{else}}/top_torrent.php{{end}}"
|
||||
- path: "{{ if .Keywords }}/search_torrent/{{ .Keywords }}/page-0{{else}}/top_torrent.php{{end}}"
|
||||
rows:
|
||||
selector: div.table-responsive > table tbody tr
|
||||
fields:
|
||||
@@ -91,11 +72,6 @@
|
||||
download:
|
||||
selector: td:nth-child(1) a
|
||||
attribute: href
|
||||
filters:
|
||||
- name: re_replace
|
||||
args: [ "/torrent/\\d{5,}/", "/get_torrent/"]
|
||||
- name: append
|
||||
args: ".torrent"
|
||||
date:
|
||||
text: "now"
|
||||
size:
|
||||
|
@@ -6,6 +6,8 @@
|
||||
type: private
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- http://et8.org/
|
||||
legacylinks:
|
||||
- https://et8.org/
|
||||
|
||||
caps:
|
||||
|
@@ -22,10 +22,18 @@
|
||||
modes:
|
||||
search: [q]
|
||||
|
||||
settings: []
|
||||
settings:
|
||||
- name: downloadlink
|
||||
type: select
|
||||
label: Download link
|
||||
default: "magnet:"
|
||||
options:
|
||||
"http://itorrents.org/" : "iTorrents.org"
|
||||
"magnet:": "magnet"
|
||||
|
||||
|
||||
download:
|
||||
selector: a[href^="magnet:"]
|
||||
selector: a[href^="{{ .Config.downloadlink }}"]
|
||||
|
||||
search:
|
||||
paths:
|
||||
@@ -44,6 +52,8 @@
|
||||
download:
|
||||
selector: p:nth-child(1) > a[href^="/torrent/"]
|
||||
attribute: href
|
||||
date:
|
||||
text: now
|
||||
size:
|
||||
selector: span:nth-child(5)
|
||||
seeders:
|
||||
|
@@ -30,7 +30,8 @@
|
||||
|
||||
modes:
|
||||
search: [q]
|
||||
tv-search: [q, season, ep]
|
||||
tv-search: [q, season, ep, imdbid]
|
||||
movie-search: [q, imdbid]
|
||||
|
||||
login:
|
||||
path: login.php
|
||||
@@ -42,34 +43,37 @@
|
||||
error:
|
||||
- selector: td.embedded:has(h2:contains("failed"))
|
||||
test:
|
||||
path: browse.php
|
||||
path: t
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: browse.php
|
||||
- path: t
|
||||
inputs:
|
||||
$raw: "{{range .Categories}}c{{.}}=1&{{end}}"
|
||||
search: "{{ .Query.Keywords }}"
|
||||
$raw: "{{range .Categories}}{{.}}=&{{end}}"
|
||||
q: "{{if .Query.IMDBID}}{{ .Query.IMDBID }}{{else}}{{ .Keywords }}{{end}}"
|
||||
incldead: 1
|
||||
rows:
|
||||
selector: table#torrentsTable > tbody > tr.torrentsTableTR
|
||||
selector: table#torrentTable > tbody > tr:has(td.torrentNameInfo)
|
||||
fields:
|
||||
download:
|
||||
selector: a[href^="download.php/"]
|
||||
selector: a[href^="/download.php/"]
|
||||
attribute: href
|
||||
title:
|
||||
selector: a.nameLink
|
||||
selector: a[href^="/details.php?id="]
|
||||
details:
|
||||
selector: a.nameLink
|
||||
selector: a[href^="/details.php?id="]
|
||||
attribute: href
|
||||
category:
|
||||
selector: a[href^="browse.php?cat="]
|
||||
selector: a[href^="?"]
|
||||
attribute: href
|
||||
filters:
|
||||
- name: querystring
|
||||
args: cat
|
||||
- name: replace
|
||||
args: ["?", ""]
|
||||
date:
|
||||
selector: div.uploaded
|
||||
selector: td.torrentNameInfo > div
|
||||
filters:
|
||||
- name: split
|
||||
args: ["|", -1]
|
||||
seeders:
|
||||
selector: td:nth-last-child(2)
|
||||
leechers:
|
||||
|
@@ -55,6 +55,7 @@
|
||||
- {id: 71, cat: XXX/Packs, desc: "pr0n / pack"}
|
||||
- {id: 30, cat: Other, desc: "Kita"}
|
||||
- {id: 41, cat: Books, desc: "E-Books"}
|
||||
- {id: 76, cat: TV, desc: "Animacija / LT"}
|
||||
|
||||
modes:
|
||||
search: [q]
|
||||
@@ -77,6 +78,9 @@
|
||||
inputs:
|
||||
$raw: "{{range .Categories}}cats[]={{.}}&{{end}}"
|
||||
search: "{{ .Keywords }}"
|
||||
keywordsfilters:
|
||||
- name: replace
|
||||
args: [".", " "] # issue #3296
|
||||
rows:
|
||||
selector: table> tbody > tr[class^="torrents_table_row_"]
|
||||
filters:
|
||||
|
@@ -115,6 +115,8 @@
|
||||
rows:
|
||||
selector: tr.browse_color, tr[id^="kdescr"]
|
||||
after: 1
|
||||
filters:
|
||||
- name: andmatch
|
||||
fields:
|
||||
category:
|
||||
selector: td:nth-of-type(1) a
|
||||
|
@@ -76,20 +76,20 @@ search:
|
||||
- name: replace
|
||||
args: ["&hit=", "&aviso="]
|
||||
files:
|
||||
selector: td:nth-child(6)
|
||||
selector: td:nth-last-child(8)
|
||||
size:
|
||||
selector: td:nth-child(9)
|
||||
selector: td:nth-last-child(5)
|
||||
filters:
|
||||
- name: replace
|
||||
args: [",", "."]
|
||||
grabs:
|
||||
selector: td:nth-child(10)
|
||||
selector: td:nth-last-child(4)
|
||||
seeders:
|
||||
selector: td:nth-child(11)
|
||||
selector: td:nth-last-child(3)
|
||||
leechers:
|
||||
selector: td:nth-child(12)
|
||||
selector: td:nth-last-child(2)
|
||||
date:
|
||||
selector: td:nth-child(8)
|
||||
selector: td:nth-last-child(6)
|
||||
filters:
|
||||
- name: timeago
|
||||
downloadvolumefactor:
|
||||
|
@@ -120,7 +120,7 @@
|
||||
selector: table#browsetable > tbody > tr:has(a[href^="/details.php?id="])
|
||||
fields:
|
||||
category:
|
||||
selector: a[href^="/browse.php?q="]
|
||||
selector: a[href^="/browse.php"]
|
||||
attribute: href
|
||||
filters:
|
||||
- name: querystring
|
||||
|
@@ -72,8 +72,8 @@
|
||||
tv-search: [q, season, ep]
|
||||
|
||||
login:
|
||||
path: /takelogin.php
|
||||
method: post
|
||||
path: /login.php
|
||||
method: form
|
||||
form: form
|
||||
inputs:
|
||||
username: "{{ .Config.username }}"
|
||||
|
@@ -162,6 +162,8 @@
|
||||
- path: "torrents-search.php?{{range .Categories}}c{{.}}=1&{{end}}search={{.Keywords}}{{if .Categories}}{{else}}&cat=0{{end}}&incldead=0&lang=0"
|
||||
rows:
|
||||
selector: tr:not(:has(script)):has(a[title][href^="torrents-details.php?id="])
|
||||
filters:
|
||||
- name: andmatch
|
||||
fields:
|
||||
category:
|
||||
optional: true
|
||||
|
@@ -4,7 +4,7 @@
|
||||
description: "xbytesV2 is a SPANISH site for HD content"
|
||||
language: es-es
|
||||
type: private
|
||||
encoding: UTF-8
|
||||
encoding: ISO-8859-1
|
||||
links:
|
||||
- http://xbytesv2.li
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
- {id: 30 , cat: Movies/HD, desc: "Peliculas - MicroHD x265"}
|
||||
- {id: 35 , cat: TV/HD, desc: "TV/Series - 4K"}
|
||||
- {id: 31 , cat: TV/HD, desc: "TV/Series - x265"}
|
||||
- {id: 25 , cat: TV/HD, desc: "TV/Series"}
|
||||
- {id: 25 , cat: TV/HD, desc: "TV/Series - HDTV & WEB-DL 1080p"}
|
||||
- {id: 37 , cat: TV/Documentary, desc: "Documentales"}
|
||||
- {id: 41 , cat: TV/Sport, desc: "Deportes"}
|
||||
- {id: 5 , cat: Movies/HD, desc: "Anime"}
|
||||
@@ -57,6 +57,35 @@
|
||||
args: category
|
||||
title:
|
||||
selector: td[valign="middle"] a
|
||||
filters:
|
||||
- name: re_replace
|
||||
args: ["\\/", " "]
|
||||
- name: re_replace
|
||||
args: ["S(\\d{1,2}) E(\\d{1,2})", "S$1E$2"]
|
||||
- name: re_replace
|
||||
args: ["\\(", ""]
|
||||
- name: re_replace
|
||||
args: ["\\)", ""]
|
||||
- name: re_replace
|
||||
args: ["20[0-2][0-9] [0-9][0-9]", ""]
|
||||
- name: re_replace
|
||||
args: ["20[0-2][0-9]", ""]
|
||||
- name: replace
|
||||
args: ["ESP", "Spanish"]
|
||||
- name: re_replace
|
||||
args: ["[EI]NG", "English"]
|
||||
- name: replace
|
||||
args: ["CAT", "Catalan"]
|
||||
- name: replace
|
||||
args: ["FRA", "French"]
|
||||
- name: replace
|
||||
args: ["JAP", "Japanese"]
|
||||
- name: replace
|
||||
args: ["ITA", "Italian"]
|
||||
- name: replace
|
||||
args: ["RUS", "Russian"]
|
||||
- name: replace
|
||||
args: ["DUAL", "Spanish English"]
|
||||
details:
|
||||
selector: td[valign="middle"] a
|
||||
attribute: href
|
||||
@@ -85,8 +114,8 @@
|
||||
attribute: href
|
||||
downloadvolumefactor:
|
||||
case:
|
||||
img[src$="gold.gif"]: "0"
|
||||
img[src$="silver.gif"]: "0.5"
|
||||
img[src$="gold.png"]: "0"
|
||||
img[src$="silver.png"]: "0.5"
|
||||
"*": "1"
|
||||
uploadvolumefactor:
|
||||
case:
|
||||
|
@@ -6,7 +6,10 @@
|
||||
type: semi-private
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- https://www.myxz.org/
|
||||
- https://www.myxz.eu/
|
||||
# not yet enabled (legitimacy concerns, see #2821)
|
||||
# legacylinks:
|
||||
# - https://www.myxz.org/
|
||||
|
||||
caps:
|
||||
categorymappings:
|
||||
@@ -48,7 +51,7 @@
|
||||
tv-search: [q, season, ep]
|
||||
|
||||
login:
|
||||
path: /login
|
||||
path: /login.php
|
||||
method: form
|
||||
form: form
|
||||
inputs:
|
||||
@@ -57,15 +60,15 @@
|
||||
error:
|
||||
- selector: td.embedded:has(center > h2:contains(failed))
|
||||
test:
|
||||
path: /browse
|
||||
path: /browse.php
|
||||
|
||||
ratio:
|
||||
path: /browse
|
||||
path: /browse.php
|
||||
selector: font:contains("Ratio:")+font
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: /browse
|
||||
- path: /browse.php
|
||||
inputs:
|
||||
$raw: "{{range .Categories}}c{{.}}=1&{{end}}"
|
||||
search: "{{ .Query.Keywords }}"
|
||||
@@ -87,9 +90,6 @@
|
||||
download:
|
||||
selector: a[href^="dwn.php"]
|
||||
attribute: href
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["dwn.php", "dwn"]
|
||||
size:
|
||||
selector: td:nth-child(7)
|
||||
date:
|
||||
|
@@ -6,8 +6,10 @@
|
||||
type: semi-private
|
||||
encoding: UTF-8
|
||||
links:
|
||||
- https://yggtorrent.com/
|
||||
- https://ww1.yggtorrent.is/
|
||||
legacylinks:
|
||||
- https://yggtorrent.is/
|
||||
- https://yggtorrent.com/
|
||||
- https://ww1.yggtorrent.com/
|
||||
|
||||
caps:
|
||||
@@ -95,39 +97,50 @@
|
||||
type: checkbox
|
||||
label: Try to normalize releases names by moving year after the title
|
||||
default: false
|
||||
|
||||
- name: multilang
|
||||
type: checkbox
|
||||
label: Replace MULTI by another language in release name
|
||||
default: false
|
||||
- name: multilanguage
|
||||
type: select
|
||||
label: Replace MULTI by this language
|
||||
default: FRENCH
|
||||
options:
|
||||
FRENCH : "FRENCH"
|
||||
MULTI.FRENCH: "MULTI.FRENCH"
|
||||
ENGLISH: "ENGLISH"
|
||||
login:
|
||||
path: "/user/login"
|
||||
method: post
|
||||
method: form
|
||||
path: /
|
||||
form: form[action$="/user/login"]
|
||||
inputs:
|
||||
id: "{{ .Config.username }}"
|
||||
pass: "{{ .Config.password }}"
|
||||
submit: ""
|
||||
error:
|
||||
- selector: "form > center > span[style=\"color:red\"]"
|
||||
- selector: "#login_msg_pass[style=\"\"][style] > center"
|
||||
test:
|
||||
path: "/"
|
||||
selector: "a[href$=\"user/logout\"]"
|
||||
path: /
|
||||
selector: a[href$="/user/logout"]
|
||||
|
||||
search:
|
||||
paths:
|
||||
- path: "{{ if .Keywords }}/engine/search?category={{ .Config.category }}&q={{ .Keywords }}{{else}}/torrents/today?category=2145{{end}}"
|
||||
- path: "{{ if .Keywords }}/engine/search?category={{ .Config.category }}&q={{ .Keywords }}&page=25{{else}}/torrents/today?category=2145&page=25{{end}}"
|
||||
- path: "{{ if .Keywords }}/engine/search?category={{ .Config.category }}&q={{ .Keywords }}&page=50{{else}}/torrents/today?category=2145&page=50{{end}}"
|
||||
- path: "/engine/search?category={{ .Config.category }}&name={{ .Keywords }}&description=&file=&uploader=&sub_category=&do=search"
|
||||
- path: "/engine/search?category={{ .Config.category }}&name={{ .Keywords }}&description=&file=&uploader=&sub_category=&do=search&page=50"
|
||||
|
||||
rows:
|
||||
selector: "table.table.table-striped > tbody > tr"
|
||||
selector: "table.table > tbody > tr"
|
||||
fields:
|
||||
_id:
|
||||
selector: "a.torrent-name"
|
||||
selector: ":nth-child(2) > a"
|
||||
attribute: href
|
||||
filters:
|
||||
- name: regexp
|
||||
args: "/(\\d+)-"
|
||||
title_normal:
|
||||
selector: "a.torrent-name"
|
||||
selector: ":nth-child(2) > a"
|
||||
title_filtered:
|
||||
selector: "a.torrent-name"
|
||||
selector: ":nth-child(2) > a"
|
||||
filters:
|
||||
- name: re_replace
|
||||
args: ["(?i)^(?:(.+?)((?:[\\.\\-\\s_\\[]+(?:imax|(?:dvd|bd|tv)(?:rip|scr)|bluray(?:\\-?rip)?|720\\s*p?|1080\\s*p?|vof?|vost(?:fr)?|multi|vf(?:f|q)?[1-3]?|(?:true)?french|eng?)[\\.\\-\\s_\\]]*)*)([\\(\\[]?(?:20|1[7-9])\\d{2}[\\)\\]]?)(.*)$|(.*))$", "$1 $3 $2 $4 $5"]
|
||||
@@ -139,13 +152,20 @@
|
||||
- name: re_replace
|
||||
args: ["(\\s{2,5})", " "]
|
||||
- name: trim
|
||||
title:
|
||||
title_phase1:
|
||||
text: "{{if .Config.filter_title }}{{ .Result.title_filtered }}{{else}}{{ .Result.title_normal }}{{end}}"
|
||||
title_multilang:
|
||||
text: "{{ .Result.title_phase1 }}"
|
||||
filters:
|
||||
- name: re_replace
|
||||
args: ["[\\.\\s\\[\\-][Mm][Uu][Ll][Tt][Ii][\\.\\s\\]\\-]", ".{{ .Config.multilanguage }}."]
|
||||
title:
|
||||
text: "{{if .Config.multilang }}{{ .Result.title_multilang }}{{else}}{{ .Result.title_phase1 }}{{end}}"
|
||||
details:
|
||||
selector: "a.torrent-name"
|
||||
selector: ":nth-child(2) > a"
|
||||
attribute: href
|
||||
category:
|
||||
selector: "a.torrent-name"
|
||||
selector: ":nth-child(2) > a"
|
||||
case:
|
||||
"a[href*=\"/filmvidéo/animation/\"]" : 2178
|
||||
"a[href*=\"/filmvidéo/animation-série/\"]" : 2179
|
||||
@@ -198,7 +218,7 @@
|
||||
download:
|
||||
text: "/engine/download_torrent?id={{ .Result._id }}"
|
||||
date:
|
||||
selector: "td:nth-child(3)"
|
||||
selector: "td:nth-child(5)"
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["il y a ", ""]
|
||||
@@ -223,16 +243,21 @@
|
||||
- name: append
|
||||
args: " ago"
|
||||
size:
|
||||
selector: "td:nth-child(4)"
|
||||
selector: "td:nth-child(6)"
|
||||
filters:
|
||||
- name: replace
|
||||
args: ["o", "B"]
|
||||
grabs:
|
||||
selector: "td:nth-child(7)"
|
||||
seeders:
|
||||
text: 0
|
||||
seeders:
|
||||
selector: "td:nth-child(5)"
|
||||
selector: "td:nth-child(8)"
|
||||
optional: true
|
||||
leechers:
|
||||
text: 0
|
||||
leechers:
|
||||
selector: "td:nth-child(6)"
|
||||
selector: "td:nth-child(*)"
|
||||
optional: true
|
||||
downloadvolumefactor:
|
||||
text: "1"
|
||||
|
@@ -48,7 +48,11 @@
|
||||
selector: .responsetop > tbody > tr:has(td.td_newborder)
|
||||
fields:
|
||||
title:
|
||||
selector: td:nth-child(2) > a:nth-child(1)
|
||||
selector: td:nth-child(2) > a[href^="/download.php"]
|
||||
attribute: href
|
||||
filters:
|
||||
- name: re_replace
|
||||
args: ["^(.*?)download\\.php\\/[0-9]{1,10}\\/|\\.torrent(?=[^.]*$)", ""]
|
||||
details:
|
||||
selector: td:nth-child(2) > a:nth-child(1)
|
||||
attribute: href
|
||||
|
@@ -33,6 +33,8 @@
|
||||
- path: "/search?{{if .Keywords}}s=ns&v=t&sd=d&q={{ .Keywords}}{{else}}s=dt&v=t&sd=d&q= *{{end}}{{if .Categories}} category:{{range .Categories}}{{.}},{{end}}{{else}}{{end}}"
|
||||
rows:
|
||||
selector: tr:has(td[class^="text-muted3"])
|
||||
filters:
|
||||
- name: andmatch
|
||||
fields:
|
||||
title:
|
||||
selector: td:nth-child(2) a
|
||||
|
@@ -13,7 +13,6 @@ using Jackett.Common.Services.Interfaces;
|
||||
using Jackett.Common.Utils.Clients;
|
||||
using NLog;
|
||||
using NLog.Config;
|
||||
using NLog.LayoutRenderers;
|
||||
using NLog.Targets;
|
||||
|
||||
namespace Jackett.Common
|
||||
@@ -179,7 +178,7 @@ namespace Jackett.Common
|
||||
var logFileName = settings.CustomLogFileName ?? "log.txt";
|
||||
var logLevel = settings.TracingEnabled ? LogLevel.Debug : LogLevel.Info;
|
||||
// Add custom date time format renderer as the default is too long
|
||||
ConfigurationItemFactory.Default.LayoutRenderers.RegisterDefinition("simpledatetime", typeof(SimpleDateTimeRenderer));
|
||||
ConfigurationItemFactory.Default.LayoutRenderers.RegisterDefinition("simpledatetime", typeof(Utils.LoggingSetup.SimpleDateTimeRenderer));
|
||||
|
||||
var logConfig = new LoggingConfiguration();
|
||||
var logFile = new FileTarget();
|
||||
@@ -265,13 +264,4 @@ namespace Jackett.Common
|
||||
ConfigService.SaveConfig(ServerConfig);
|
||||
}
|
||||
}
|
||||
|
||||
[LayoutRenderer("simpledatetime")]
|
||||
public class SimpleDateTimeRenderer : LayoutRenderer
|
||||
{
|
||||
protected override void Append(StringBuilder builder, LogEventInfo logEvent)
|
||||
{
|
||||
builder.Append(DateTime.Now.ToString("MM-dd HH:mm:ss"));
|
||||
}
|
||||
}
|
||||
}
|
@@ -26,6 +26,12 @@ namespace Jackett.Common.Indexers.Abstract
|
||||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
// hook to adjust the search term
|
||||
protected virtual string GetSearchTerm(TorznabQuery query)
|
||||
{
|
||||
return query.GetQueryString();
|
||||
}
|
||||
|
||||
public AvistazTracker(IIndexerConfigurationService configService, Utils.Clients.WebClient webClient, Logger logger, IProtectionService protectionService, string name, string desc, string link)
|
||||
: base(name: name,
|
||||
description: desc,
|
||||
@@ -84,7 +90,7 @@ namespace Jackett.Common.Indexers.Abstract
|
||||
}
|
||||
|
||||
|
||||
var episodeSearchUrl = string.Format(SearchUrl, category, WebUtility.UrlEncode(query.GetQueryString()));
|
||||
var episodeSearchUrl = string.Format(SearchUrl, category, WebUtility.UrlEncode(GetSearchTerm(query)));
|
||||
|
||||
var response = await RequestStringWithCookiesAndRetry(episodeSearchUrl);
|
||||
if (response.IsRedirect)
|
||||
|
@@ -53,15 +53,20 @@ namespace Jackett.Common.Indexers.Abstract
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||
public override void LoadValuesFromJson(JToken jsonConfig, bool useProtectionService = false)
|
||||
{
|
||||
LoadValuesFromJson(configJson);
|
||||
base.LoadValuesFromJson(jsonConfig, useProtectionService);
|
||||
|
||||
var useTokenItem = (ConfigurationData.BoolItem)configData.GetDynamic("usetoken");
|
||||
if (useTokenItem != null)
|
||||
{
|
||||
useTokens = useTokenItem.Value;
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||
{
|
||||
LoadValuesFromJson(configJson);
|
||||
|
||||
var pairs = new Dictionary<string, string> {
|
||||
{ "username", configData.Username.Value },
|
||||
@@ -84,10 +89,16 @@ namespace Jackett.Common.Indexers.Abstract
|
||||
return IndexerConfigurationStatus.RequiresTesting;
|
||||
}
|
||||
|
||||
// hook to adjust the search term
|
||||
protected virtual string GetSearchTerm(TorznabQuery query)
|
||||
{
|
||||
return query.GetQueryString();
|
||||
}
|
||||
|
||||
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
|
||||
{
|
||||
var releases = new List<ReleaseInfo>();
|
||||
var searchString = query.GetQueryString();
|
||||
var searchString = GetSearchTerm(query);
|
||||
|
||||
var searchUrl = APIUrl;
|
||||
var queryCollection = new NameValueCollection();
|
||||
@@ -228,10 +239,40 @@ namespace Jackett.Common.Indexers.Abstract
|
||||
if (torrent["hasCue"] != null && (bool)torrent["hasCue"])
|
||||
flags.Add("Cue");
|
||||
|
||||
// tehconnection.me specific?
|
||||
var lang = (string)torrent["lang"];
|
||||
if (!string.IsNullOrEmpty(lang) && lang != "---")
|
||||
flags.Add(lang);
|
||||
|
||||
var media = (string)torrent["media"];
|
||||
if (!string.IsNullOrEmpty(media))
|
||||
flags.Add(media);
|
||||
|
||||
// tehconnection.me specific?
|
||||
var resolution = (string)torrent["resolution"];
|
||||
if (!string.IsNullOrEmpty(resolution))
|
||||
flags.Add(resolution);
|
||||
|
||||
// tehconnection.me specific?
|
||||
var container = (string)torrent["container"];
|
||||
if (!string.IsNullOrEmpty(container))
|
||||
flags.Add(container);
|
||||
|
||||
// tehconnection.me specific?
|
||||
var codec = (string)torrent["codec"];
|
||||
if (!string.IsNullOrEmpty(codec))
|
||||
flags.Add(codec);
|
||||
|
||||
// tehconnection.me specific?
|
||||
var audio = (string)torrent["audio"];
|
||||
if (!string.IsNullOrEmpty(audio))
|
||||
flags.Add(audio);
|
||||
|
||||
// tehconnection.me specific?
|
||||
var subbing = (string)torrent["subbing"];
|
||||
if (!string.IsNullOrEmpty(subbing) && subbing != "---")
|
||||
flags.Add(subbing);
|
||||
|
||||
if (torrent["remastered"] != null && (bool)torrent["remastered"])
|
||||
{
|
||||
var remasterYear = (string)torrent["remasterYear"];
|
||||
@@ -272,5 +313,28 @@ namespace Jackett.Common.Indexers.Abstract
|
||||
release.UploadVolumeFactor = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<byte[]> Download(Uri link)
|
||||
{
|
||||
var content = await base.Download(link);
|
||||
|
||||
// Check if we're out of FL tokens
|
||||
// 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
|
||||
&& content[0] != 'd' // simple test for torrent vs HTML content
|
||||
&& requestLink.Contains("usetoken=1"))
|
||||
{
|
||||
var html = Encoding.GetString(content);
|
||||
if (html.Contains("You do not have any freeleech tokens left."))
|
||||
{
|
||||
// download again with usetoken=0
|
||||
var requestLinkNew = requestLink.Replace("usetoken=1", "usetoken=0");
|
||||
content = await base.Download(new Uri(requestLinkNew));
|
||||
}
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -47,5 +47,10 @@ namespace Jackett.Common.Indexers
|
||||
AddCategoryMapping(23, TorznabCatType.AudioOther, "Music");
|
||||
AddCategoryMapping(24, TorznabCatType.Other, "Misc");
|
||||
}
|
||||
|
||||
protected override string GetSearchTerm(TorznabQuery query)
|
||||
{
|
||||
return query.GetQueryString().Replace(".", " "); // Alpharatio can't handle dots in the searchstr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,211 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using CsQuery;
|
||||
using Jackett.Common.Models;
|
||||
using Jackett.Common.Models.IndexerConfig;
|
||||
using Jackett.Common.Services.Interfaces;
|
||||
using Jackett.Common.Utils;
|
||||
using Jackett.Common.Utils.Clients;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NLog;
|
||||
|
||||
namespace Jackett.Common.Indexers
|
||||
{
|
||||
public class Andraste : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||
private string BrowseUrl { get { return SiteLink + "browse.php"; } }
|
||||
|
||||
private new ConfigurationDataBasicLoginWithRSSAndDisplay configData
|
||||
{
|
||||
get { return (ConfigurationDataBasicLoginWithRSSAndDisplay)base.configData; }
|
||||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public Andraste(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "Andraste",
|
||||
description: "A German general tracker.",
|
||||
link: "https://andraste.io/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
configService: configService,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
configData: new ConfigurationDataBasicLoginWithRSSAndDisplay())
|
||||
{
|
||||
Encoding = Encoding.GetEncoding("iso-8859-1");
|
||||
Language = "de-de";
|
||||
Type = "private";
|
||||
|
||||
AddCategoryMapping(9, TorznabCatType.Other); // Anderes
|
||||
AddCategoryMapping(23, TorznabCatType.TVAnime); // Animation - Film &; Serie
|
||||
AddCategoryMapping(1, TorznabCatType.PC); // Appz
|
||||
AddCategoryMapping(52, TorznabCatType.Other); // Botuploads
|
||||
AddCategoryMapping(25, TorznabCatType.TVDocumentary); // Doku - Alle Formate
|
||||
AddCategoryMapping(27, TorznabCatType.Books); // E-Books
|
||||
AddCategoryMapping(51, TorznabCatType.Movies3D); // Film/3D
|
||||
AddCategoryMapping(20, TorznabCatType.MoviesDVD); // Film/DVDr
|
||||
AddCategoryMapping(37, TorznabCatType.MoviesHD); // Film/HD 1080p++
|
||||
AddCategoryMapping(38, TorznabCatType.MoviesSD); // Film/HD 720p
|
||||
AddCategoryMapping(36, TorznabCatType.Movies); // Film/im Kino
|
||||
AddCategoryMapping(19, TorznabCatType.Movies); // Film/XviD,DivX,x264
|
||||
AddCategoryMapping(4, TorznabCatType.PCGames); // Games/PC
|
||||
AddCategoryMapping(12, TorznabCatType.ConsolePS4); // Games/Playstation
|
||||
AddCategoryMapping(22, TorznabCatType.ConsoleWii); // Games/Wii & DS
|
||||
AddCategoryMapping(21, TorznabCatType.ConsoleXbox); // Games/Xbox & 360
|
||||
AddCategoryMapping(48, TorznabCatType.PCPhoneAndroid); // Handy & PDA/Android
|
||||
AddCategoryMapping(47, TorznabCatType.PCPhoneIOS); // Handy & PDA/iOS
|
||||
AddCategoryMapping(44, TorznabCatType.PCMac); // Macintosh
|
||||
AddCategoryMapping(41, TorznabCatType.Other); // MegaPack
|
||||
AddCategoryMapping(24, TorznabCatType.AudioAudiobook); // Musik/Hörbuch & Hörspiel
|
||||
AddCategoryMapping(46, TorznabCatType.Audio); // Musik/HQ 320++
|
||||
AddCategoryMapping(6, TorznabCatType.Audio); // Musik/Musik
|
||||
AddCategoryMapping(26, TorznabCatType.AudioVideo); // Musik/Musikvideos
|
||||
AddCategoryMapping(29, TorznabCatType.TVSD); // Serien/DVDr
|
||||
AddCategoryMapping(35, TorznabCatType.TVHD); // Serien/HD 720p++
|
||||
AddCategoryMapping(7, TorznabCatType.TV); // Serien/XviD,DivX,x264
|
||||
AddCategoryMapping(45, TorznabCatType.TV); // Shows
|
||||
AddCategoryMapping(40, TorznabCatType.TVSport); // Sport
|
||||
AddCategoryMapping(32, TorznabCatType.XXX); // XXX
|
||||
}
|
||||
|
||||
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||
{
|
||||
LoadValuesFromJson(configJson);
|
||||
|
||||
var pairs = new Dictionary<string, string>
|
||||
{
|
||||
{ "username", configData.Username.Value },
|
||||
{ "password", configData.Password.Value }
|
||||
};
|
||||
|
||||
var result = await RequestLoginAndFollowRedirect(LoginUrl, pairs, null, true, null, LoginUrl, true);
|
||||
await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("logout.php"), () =>
|
||||
{
|
||||
CQ dom = result.Content;
|
||||
var errorMessage = dom["table.tableinborder"].Html();
|
||||
errorMessage = result.Content;
|
||||
throw new ExceptionWithConfigData(errorMessage, configData);
|
||||
});
|
||||
return IndexerConfigurationStatus.RequiresTesting;
|
||||
}
|
||||
|
||||
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
|
||||
{
|
||||
TimeZoneInfo.TransitionTime startTransition = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 3, 0, 0), 3, 5, DayOfWeek.Sunday);
|
||||
TimeZoneInfo.TransitionTime endTransition = TimeZoneInfo.TransitionTime.CreateFloatingDateRule(new DateTime(1, 1, 1, 4, 0, 0), 10, 5, DayOfWeek.Sunday);
|
||||
TimeSpan delta = new TimeSpan(1, 0, 0);
|
||||
TimeZoneInfo.AdjustmentRule adjustment = TimeZoneInfo.AdjustmentRule.CreateAdjustmentRule(new DateTime(1999, 10, 1), DateTime.MaxValue.Date, delta, startTransition, endTransition);
|
||||
TimeZoneInfo.AdjustmentRule[] adjustments = { adjustment };
|
||||
TimeZoneInfo germanyTz = TimeZoneInfo.CreateCustomTimeZone("W. Europe Standard Time", new TimeSpan(1, 0, 0), "(GMT+01:00) W. Europe Standard Time", "W. Europe Standard Time", "W. Europe DST Time", adjustments);
|
||||
|
||||
var releases = new List<ReleaseInfo>();
|
||||
|
||||
var searchString = query.GetQueryString();
|
||||
var searchUrl = BrowseUrl;
|
||||
var queryCollection = new NameValueCollection();
|
||||
queryCollection.Add("showsearch", "1");
|
||||
queryCollection.Add("incldead", "1");
|
||||
queryCollection.Add("orderby", "added");
|
||||
queryCollection.Add("sort", "desc");
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(searchString))
|
||||
{
|
||||
queryCollection.Add("search", searchString);
|
||||
}
|
||||
|
||||
foreach (var cat in MapTorznabCapsToTrackers(query))
|
||||
{
|
||||
queryCollection.Add("c" + cat, "1");
|
||||
}
|
||||
searchUrl += "?" + queryCollection.GetQueryString();
|
||||
|
||||
var response = await RequestStringWithCookies(searchUrl);
|
||||
var results = response.Content;
|
||||
try
|
||||
{
|
||||
CQ dom = results;
|
||||
var globalFreeleech = dom.Find("div > img[alt=\"Only Upload\"][title^=\"ONLY UPLOAD \"]").Any();
|
||||
var rows = dom["table.tableinborder > tbody > tr:has(td.tableb)"];
|
||||
|
||||
foreach (var row in rows)
|
||||
{
|
||||
var release = new ReleaseInfo();
|
||||
var qRow = row.Cq();
|
||||
|
||||
var qDetailsLink = qRow.Find("a[href^=details.php?id=]").First();
|
||||
release.Title = qDetailsLink.Attr("title");
|
||||
|
||||
if (!query.MatchQueryStringAND(release.Title))
|
||||
continue;
|
||||
|
||||
var qCatLink = qRow.Find("a[href^=browse.php?cat=]").First();
|
||||
var qDLLink = qRow.Find("a[href^=download.php?torrent=]").First();
|
||||
var qSeeders = qRow.Find("span:contains(Seeder) > b:eq(0)");
|
||||
var qLeechers = qRow.Find("span:contains(Seeder) > b:eq(1)");
|
||||
var qDateStr = qRow.Find("td > table > tbody > tr > td:eq(7)").First();
|
||||
var qSize = qRow.Find("span:contains(Volumen) > b:eq(0)").First();
|
||||
var qOnlyUpload = qRow.Find("img[title=OnlyUpload]");
|
||||
|
||||
if (qOnlyUpload.Any())
|
||||
{
|
||||
release.MinimumRatio = 2;
|
||||
release.MinimumSeedTime = 144 * 60 * 60;
|
||||
}
|
||||
else
|
||||
{
|
||||
release.MinimumRatio = 1;
|
||||
release.MinimumSeedTime = 72 * 60 * 60;
|
||||
}
|
||||
|
||||
var catStr = qCatLink.Attr("href").Split('=')[1];
|
||||
release.Category = MapTrackerCatToNewznab(catStr);
|
||||
|
||||
release.Link = new Uri(SiteLink + qDLLink.Attr("href"));
|
||||
release.Comments = new Uri(SiteLink + qDetailsLink.Attr("href"));
|
||||
release.Guid = release.Link;
|
||||
|
||||
var sizeStr = qSize.Text();
|
||||
release.Size = ReleaseInfo.GetBytes(sizeStr);
|
||||
|
||||
release.Seeders = ParseUtil.CoerceInt(qSeeders.Text());
|
||||
release.Peers = ParseUtil.CoerceInt(qLeechers.Text()) + release.Seeders;
|
||||
|
||||
var dateStr = qDateStr.Text().Trim().Replace('\xA0', ' ');
|
||||
DateTime dateGerman = DateTime.SpecifyKind(DateTime.ParseExact(dateStr, "dd.MM.yyyy HH:mm", CultureInfo.InvariantCulture), DateTimeKind.Unspecified);
|
||||
|
||||
DateTime pubDateUtc = TimeZoneInfo.ConvertTimeToUtc(dateGerman, germanyTz);
|
||||
release.PublishDate = pubDateUtc.ToLocalTime();
|
||||
|
||||
var files = qRow.Find("a[href*=\"&filelist=1\"] ~ font ~ b").Text();
|
||||
release.Files = ParseUtil.CoerceInt(files);
|
||||
|
||||
var grabs = qRow.Find("a[href*=\"&tosnatchers=1\"] ~ font ~ b").Text();
|
||||
release.Grabs = ParseUtil.CoerceInt(grabs);
|
||||
|
||||
if (globalFreeleech)
|
||||
release.DownloadVolumeFactor = 0;
|
||||
else if (qRow.Find("img[alt=\"OU\"]").Length >= 1)
|
||||
release.DownloadVolumeFactor = 0;
|
||||
else
|
||||
release.DownloadVolumeFactor = 1;
|
||||
|
||||
release.UploadVolumeFactor = 1;
|
||||
|
||||
releases.Add(release);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
OnParseError(results, ex);
|
||||
}
|
||||
|
||||
return releases;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,16 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using CsQuery;
|
||||
using Jackett.Common.Models;
|
||||
using Jackett.Common.Models.IndexerConfig;
|
||||
using Jackett.Common.Models.IndexerConfig.Bespoke;
|
||||
using Jackett.Common.Services.Interfaces;
|
||||
using Jackett.Common.Utils;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NLog;
|
||||
|
||||
@@ -18,23 +19,13 @@ namespace Jackett.Common.Indexers
|
||||
{
|
||||
public class AnimeBytes : BaseCachingWebIndexer
|
||||
{
|
||||
private enum SearchType
|
||||
{
|
||||
Video,
|
||||
Audio
|
||||
}
|
||||
|
||||
private string LoginUrl { get { return SiteLink + "user/login"; } }
|
||||
private string SearchUrl { get { return SiteLink + "torrents.php?"; } }
|
||||
private string MusicSearchUrl { get { return SiteLink + "torrents2.php?"; } }
|
||||
private string ScrapeUrl { get { return SiteLink + "scrape.php"; } }
|
||||
private string TorrentsUrl { get { return SiteLink + "torrents.php"; } }
|
||||
public bool AllowRaws { get { return configData.IncludeRaw.Value; } }
|
||||
public bool InsertSeason { get { return configData.InsertSeason != null && configData.InsertSeason.Value; } }
|
||||
public bool AddSynonyms { get { return configData.AddSynonyms.Value; } }
|
||||
public bool FilterSeasonEpisode { get { return configData.FilterSeasonEpisode.Value; } }
|
||||
|
||||
string csrfIndex = null;
|
||||
string csrfToken = null;
|
||||
|
||||
private new ConfigurationDataAnimeBytes configData
|
||||
{
|
||||
get { return (ConfigurationDataAnimeBytes)base.configData; }
|
||||
@@ -58,7 +49,7 @@ namespace Jackett.Common.Indexers
|
||||
TorznabCatType.AudioOther),
|
||||
logger: l,
|
||||
p: ps,
|
||||
configData: new ConfigurationDataAnimeBytes())
|
||||
configData: new ConfigurationDataAnimeBytes("Note: Go to AnimeBytes site and open your account settings. Go to 'Account' tab, move cursor over black part near 'Passkey' and copy its value. Your username is case sensitive."))
|
||||
{
|
||||
Encoding = Encoding.UTF8;
|
||||
Language = "en-us";
|
||||
@@ -73,82 +64,22 @@ namespace Jackett.Common.Indexers
|
||||
return input;
|
||||
}
|
||||
|
||||
public override async Task<ConfigurationData> GetConfigurationForSetup()
|
||||
{
|
||||
// Get the login form as we need the CSRF Token
|
||||
var loginPage = await webclient.GetString(new Utils.Clients.WebRequest()
|
||||
{
|
||||
Url = LoginUrl,
|
||||
Encoding = Encoding,
|
||||
});
|
||||
UpdateCookieHeader(loginPage.Cookies);
|
||||
|
||||
CQ loginPageDom = loginPage.Content;
|
||||
csrfIndex = loginPageDom["input[name=\"_CSRF_INDEX\"]"].Last().Attr("value");
|
||||
csrfToken = loginPageDom["input[name=\"_CSRF_TOKEN\"]"].Last().Attr("value");
|
||||
|
||||
CQ qCaptchaImg = loginPageDom.Find("#captcha_img").First();
|
||||
if (qCaptchaImg.Length == 1)
|
||||
{
|
||||
var CaptchaUrl = SiteLink + qCaptchaImg.Attr("src");
|
||||
var captchaImage = await RequestBytesWithCookies(CaptchaUrl, loginPage.Cookies);
|
||||
configData.CaptchaImage.Value = captchaImage.Content;
|
||||
}
|
||||
else
|
||||
{
|
||||
configData.CaptchaImage.Value = new byte[0];
|
||||
}
|
||||
configData.CaptchaCookie.Value = loginPage.Cookies;
|
||||
return configData;
|
||||
}
|
||||
|
||||
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||
{
|
||||
LoadValuesFromJson(configJson);
|
||||
|
||||
lock (cache)
|
||||
if (configData.Passkey.Value.Length != 32 && configData.Passkey.Value.Length != 48)
|
||||
throw new Exception("invalid passkey configured: expected length: 32 or 48, got " + configData.Passkey.Value.Length.ToString());
|
||||
|
||||
var results = await PerformQuery(new TorznabQuery());
|
||||
if (results.Count() == 0)
|
||||
{
|
||||
cache.Clear();
|
||||
throw new Exception("no results found, please report this bug");
|
||||
}
|
||||
|
||||
// Build login form
|
||||
var pairs = new Dictionary<string, string> {
|
||||
{ "_CSRF_INDEX", csrfIndex },
|
||||
{ "_CSRF_TOKEN", csrfToken },
|
||||
{ "username", configData.Username.Value },
|
||||
{ "password", configData.Password.Value },
|
||||
{ "keeplogged_sent", "true" },
|
||||
{ "keeplogged", "on" },
|
||||
{ "login", "Log In!" }
|
||||
};
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(configData.CaptchaText.Value))
|
||||
{
|
||||
pairs.Add("captcha", configData.CaptchaText.Value);
|
||||
}
|
||||
|
||||
// Do the login
|
||||
var response = await RequestLoginAndFollowRedirect(LoginUrl, pairs, configData.CaptchaCookie.Value, true, null);
|
||||
|
||||
// Follow the redirect
|
||||
await FollowIfRedirect(response, LoginUrl, SearchUrl);
|
||||
|
||||
if (response.Status == HttpStatusCode.Forbidden)
|
||||
throw new ExceptionWithConfigData("Failed to login, your IP seems to be blacklisted (shared VPN/seedbox?). Contact the staff to resolve this.", configData);
|
||||
|
||||
await ConfigureIfOK(response.Cookies, response.Content != null && response.Content.Contains("/user/logout"), () =>
|
||||
{
|
||||
logger.Info(response.Content);
|
||||
CQ responseDom = response.Content;
|
||||
var alert = responseDom.Find("div.alert-danger");
|
||||
if (alert.Any())
|
||||
throw new ExceptionWithConfigData(alert.Text(), configData);
|
||||
|
||||
// Their login page appears to be broken and just gives a 500 error.
|
||||
throw new ExceptionWithConfigData("Failed to login (unknown reason), 6 failed attempts will get you banned for 6 hours.", configData);
|
||||
});
|
||||
|
||||
return IndexerConfigurationStatus.RequiresTesting;
|
||||
IsConfigured = true;
|
||||
SaveConfig();
|
||||
return IndexerConfigurationStatus.Completed;
|
||||
}
|
||||
|
||||
private string StripEpisodeNumber(string term)
|
||||
@@ -166,13 +97,13 @@ namespace Jackett.Common.Indexers
|
||||
|
||||
if (ContainsMusicCategories(query.Categories))
|
||||
{
|
||||
foreach (var result in await GetResults(query, SearchType.Audio, query.SanitizedSearchTerm))
|
||||
foreach (var result in await GetResults(query, "music", query.SanitizedSearchTerm))
|
||||
{
|
||||
releases.Add(result);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var result in await GetResults(query, SearchType.Video, StripEpisodeNumber(query.SanitizedSearchTerm)))
|
||||
foreach (var result in await GetResults(query, "anime", StripEpisodeNumber(query.SanitizedSearchTerm)))
|
||||
{
|
||||
releases.Add(result);
|
||||
}
|
||||
@@ -194,20 +125,26 @@ namespace Jackett.Common.Indexers
|
||||
return categories.Length == 0 || music.Any(categories.Contains);
|
||||
}
|
||||
|
||||
private async Task<IEnumerable<ReleaseInfo>> GetResults(TorznabQuery query, SearchType searchType, string searchTerm)
|
||||
private async Task<IEnumerable<ReleaseInfo>> GetResults(TorznabQuery query, string searchType, string searchTerm)
|
||||
{
|
||||
var cleanSearchTerm = WebUtility.UrlEncode(searchTerm);
|
||||
|
||||
// The result list
|
||||
var releases = new List<ReleaseInfo>();
|
||||
|
||||
var queryUrl = searchType == SearchType.Video ? SearchUrl : MusicSearchUrl;
|
||||
// Only include the query bit if its required as hopefully the site caches the non query page
|
||||
if (!string.IsNullOrWhiteSpace(searchTerm))
|
||||
var queryCollection = new NameValueCollection();
|
||||
|
||||
var cat = "0";
|
||||
var queryCats = MapTorznabCapsToTrackers(query);
|
||||
if (queryCats.Count == 1)
|
||||
{
|
||||
queryUrl += string.Format("searchstr={0}&action=advanced&search_type=title&year=&year2=&tags=&tags_type=0&sort=time_added&way=desc&hentai=2&releasegroup=&epcount=&epcount2=&artbooktitle=", cleanSearchTerm);
|
||||
cat = queryCats.First().ToString();
|
||||
}
|
||||
|
||||
queryCollection.Add("username", configData.Username.Value);
|
||||
queryCollection.Add("torrent_pass", configData.Passkey.Value);
|
||||
queryCollection.Add("type", searchType);
|
||||
queryCollection.Add("searchstr", searchTerm);
|
||||
var queryUrl = ScrapeUrl + "?" + queryCollection.GetQueryString();
|
||||
|
||||
// Check cache first so we don't query the server for each episode when searching for each episode in a series.
|
||||
lock (cache)
|
||||
{
|
||||
@@ -221,263 +158,234 @@ namespace Jackett.Common.Indexers
|
||||
|
||||
// Get the content from the tracker
|
||||
var response = await RequestStringWithCookiesAndRetry(queryUrl);
|
||||
if (response.IsRedirect)
|
||||
{
|
||||
// re-login
|
||||
await GetConfigurationForSetup();
|
||||
await ApplyConfiguration(null);
|
||||
response = await RequestStringWithCookiesAndRetry(queryUrl);
|
||||
}
|
||||
|
||||
CQ dom = response.Content;
|
||||
if (!response.Content.StartsWith("{")) // not JSON => error
|
||||
throw new ExceptionWithConfigData("unexcepted response (not JSON)", configData);
|
||||
dynamic json = JsonConvert.DeserializeObject<dynamic>(response.Content);
|
||||
|
||||
// Parse
|
||||
try
|
||||
{
|
||||
var releaseInfo = "S01";
|
||||
var root = dom.Find(".group_cont");
|
||||
// We may have got redirected to the series page if we have none of these
|
||||
if (root.Count() == 0)
|
||||
root = dom.Find(".torrent_table");
|
||||
if (json["error"] != null)
|
||||
throw new Exception(json["error"].ToString());
|
||||
|
||||
foreach (var series in root)
|
||||
var Matches = (long)json["Matches"];
|
||||
|
||||
if(Matches > 0)
|
||||
{
|
||||
var seriesCq = series.Cq();
|
||||
var groups = (JArray)json.Groups;
|
||||
|
||||
var synonyms = new List<string>();
|
||||
string mainTitle;
|
||||
if (searchType == SearchType.Video)
|
||||
mainTitle = seriesCq.Find(".group_title strong a").First().Text().Trim();
|
||||
else
|
||||
mainTitle = seriesCq.Find(".group_title strong").Text().Trim();
|
||||
|
||||
var yearStr = seriesCq.Find(".group_title strong").First().Text().Trim().Replace("]", "").Trim();
|
||||
int yearIndex = yearStr.LastIndexOf("[");
|
||||
if (yearIndex > -1)
|
||||
yearStr = yearStr.Substring(yearIndex + 1);
|
||||
|
||||
int year = 0;
|
||||
if (!int.TryParse(yearStr, out year))
|
||||
year = DateTime.Now.Year;
|
||||
|
||||
synonyms.Add(mainTitle);
|
||||
|
||||
// If the title contains a comma then we can't use the synonyms as they are comma seperated
|
||||
if (!mainTitle.Contains(",") && AddSynonyms)
|
||||
foreach (JObject group in groups)
|
||||
{
|
||||
var symnomnNames = string.Empty;
|
||||
foreach (var e in seriesCq.Find(".group_statbox li"))
|
||||
var synonyms = new List<string>();
|
||||
var groupID = (long)group["ID"];
|
||||
var Image = (string)group["Image"];
|
||||
var ImageUrl = (string.IsNullOrWhiteSpace(Image) ? null : new Uri(Image));
|
||||
var Year = (int)group["Year"];
|
||||
var GroupName = (string)group["GroupName"];
|
||||
var SeriesName = (string)group["SeriesName"];
|
||||
var Artists = (string)group["Artists"];
|
||||
|
||||
var mainTitle = WebUtility.HtmlDecode((string)group["FullName"]);
|
||||
if (SeriesName != null)
|
||||
mainTitle = SeriesName;
|
||||
|
||||
synonyms.Add(mainTitle);
|
||||
|
||||
// If the title contains a comma then we can't use the synonyms as they are comma seperated
|
||||
if (!mainTitle.Contains(",") && AddSynonyms)
|
||||
{
|
||||
if (e.FirstChild.InnerText == "Synonyms:")
|
||||
var symnomnNames = WebUtility.HtmlDecode((string)group["Synonymns"]);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(symnomnNames))
|
||||
{
|
||||
symnomnNames = e.InnerText;
|
||||
foreach (var name in symnomnNames.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
var theName = name.Trim();
|
||||
if (!theName.Contains("&#") && !string.IsNullOrWhiteSpace(theName))
|
||||
{
|
||||
synonyms.Add(theName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(symnomnNames))
|
||||
List<int> Category = null;
|
||||
var category = (string)group["CategoryName"];
|
||||
|
||||
var Description = (string)group["Description"];
|
||||
|
||||
foreach (JObject torrent in group["Torrents"])
|
||||
{
|
||||
foreach (var name in symnomnNames.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries))
|
||||
var releaseInfo = "S01";
|
||||
string episode = null;
|
||||
int? season = null;
|
||||
var EditionTitle = (string)torrent["EditionData"]["EditionTitle"];
|
||||
if (!string.IsNullOrWhiteSpace(EditionTitle))
|
||||
releaseInfo = WebUtility.HtmlDecode(EditionTitle);
|
||||
|
||||
Regex SeasonRegEx = new Regex(@"Season (\d+)", RegexOptions.Compiled);
|
||||
var SeasonRegExMatch = SeasonRegEx.Match(releaseInfo);
|
||||
if (SeasonRegExMatch.Success)
|
||||
season = ParseUtil.CoerceInt(SeasonRegExMatch.Groups[1].Value);
|
||||
|
||||
Regex EpisodeRegEx = new Regex(@"Episode (\d+)", RegexOptions.Compiled);
|
||||
var EpisodeRegExMatch = EpisodeRegEx.Match(releaseInfo);
|
||||
if (EpisodeRegExMatch.Success)
|
||||
episode = EpisodeRegExMatch.Groups[1].Value;
|
||||
|
||||
releaseInfo = releaseInfo.Replace("Episode ", "");
|
||||
releaseInfo = releaseInfo.Replace("Season ", "S");
|
||||
releaseInfo = releaseInfo.Trim();
|
||||
|
||||
int test = 0;
|
||||
if (InsertSeason && int.TryParse(releaseInfo, out test) && releaseInfo.Length <= 3)
|
||||
{
|
||||
var theName = name.Trim();
|
||||
if (!theName.Contains("&#") && !string.IsNullOrWhiteSpace(theName))
|
||||
releaseInfo = "E0" + releaseInfo;
|
||||
}
|
||||
|
||||
if (FilterSeasonEpisode)
|
||||
{
|
||||
if (query.Season != 0 && season != null && season != query.Season) // skip if season doesn't match
|
||||
continue;
|
||||
if (query.Episode != null && episode != null && episode != query.Episode) // skip if episode doesn't match
|
||||
continue;
|
||||
}
|
||||
var torrentID = (long)torrent["ID"];
|
||||
var Property = (string)torrent["Property"];
|
||||
Property = Property.Replace(" | Freeleech", "");
|
||||
var Link = (string)torrent["Link"];
|
||||
var LinkUri = new Uri(Link);
|
||||
var UploadTimeString = (string)torrent["UploadTime"];
|
||||
var UploadTime = DateTime.ParseExact(UploadTimeString, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
|
||||
var PublushDate = DateTime.SpecifyKind(UploadTime, DateTimeKind.Utc).ToLocalTime();
|
||||
var CommentsLink = TorrentsUrl + "?id=" + groupID.ToString() + "&torrentid=" + torrentID.ToString();
|
||||
var CommentsLinkUri = new Uri(CommentsLink);
|
||||
var Size = (long)torrent["Size"];
|
||||
var Snatched = (long)torrent["Snatched"];
|
||||
var Seeders = (int)torrent["Seeders"];
|
||||
var Leechers = (int)torrent["Leechers"];
|
||||
var FileCount = (long)torrent["FileCount"];
|
||||
var Peers = Seeders + Leechers;
|
||||
|
||||
var RawDownMultiplier = (int?)torrent["RawDownMultiplier"];
|
||||
if (RawDownMultiplier == null)
|
||||
RawDownMultiplier = 0;
|
||||
var RawUpMultiplier = (int?)torrent["RawUpMultiplier"];
|
||||
if (RawUpMultiplier == null)
|
||||
RawDownMultiplier = 0;
|
||||
|
||||
if (searchType == "anime")
|
||||
{
|
||||
if (GroupName == "TV Series")
|
||||
Category = new List<int> { TorznabCatType.TVAnime.ID };
|
||||
|
||||
// Ignore these categories as they'll cause hell with the matcher
|
||||
// TV Special, OVA, ONA, DVD Special, BD Special
|
||||
|
||||
if (GroupName == "Movie")
|
||||
Category = new List<int> { TorznabCatType.Movies.ID };
|
||||
|
||||
if (category == "Manga" || category == "Oneshot" || category == "Anthology" || category == "Manhwa" || category == "Manhua" || category == "Light Novel")
|
||||
Category = new List<int> { TorznabCatType.BooksComics.ID };
|
||||
|
||||
if (category == "Novel" || category == "Artbook")
|
||||
Category = new List<int> { TorznabCatType.BooksComics.ID };
|
||||
|
||||
if (category == "Game" || category == "Visual Novel")
|
||||
{
|
||||
synonyms.Add(theName);
|
||||
if (Property.Contains(" PSP "))
|
||||
Category = new List<int> { TorznabCatType.ConsolePSP.ID };
|
||||
if (Property.Contains("PSX"))
|
||||
Category = new List<int> { TorznabCatType.ConsoleOther.ID };
|
||||
if (Property.Contains(" NES "))
|
||||
Category = new List<int> { TorznabCatType.ConsoleOther.ID };
|
||||
if (Property.Contains(" PC "))
|
||||
Category = new List<int> { TorznabCatType.PCGames.ID };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var title in synonyms)
|
||||
{
|
||||
var releaseRows = seriesCq.Find(".torrent_group tr");
|
||||
string episode = null;
|
||||
int? season = null;
|
||||
|
||||
// Skip the first two info rows
|
||||
for (int r = 1; r < releaseRows.Count(); r++)
|
||||
{
|
||||
var row = releaseRows.Get(r);
|
||||
var rowCq = row.Cq();
|
||||
if (rowCq.HasClass("edition_info"))
|
||||
else if (searchType == "music")
|
||||
{
|
||||
episode = null;
|
||||
season = null;
|
||||
releaseInfo = rowCq.Find("td").Text();
|
||||
if (string.IsNullOrWhiteSpace(releaseInfo))
|
||||
if (category == "Single" || category == "EP" || category == "Album" || category == "Compilation" || category == "Soundtrack" || category == "Remix CD" || category == "PV" || category == "Live Album" || category == "Image CD" || category == "Drama CD" || category == "Vocal CD")
|
||||
{
|
||||
// Single episodes alpha - Reported that this info is missing.
|
||||
// It should self correct when availible
|
||||
break;
|
||||
}
|
||||
|
||||
Regex SeasonRegEx = new Regex(@"Season (\d+)", RegexOptions.Compiled);
|
||||
var SeasonRegExMatch = SeasonRegEx.Match(releaseInfo);
|
||||
if (SeasonRegExMatch.Success)
|
||||
season = ParseUtil.CoerceInt(SeasonRegExMatch.Groups[1].Value);
|
||||
|
||||
Regex EpisodeRegEx = new Regex(@"Episode (\d+)", RegexOptions.Compiled);
|
||||
var EpisodeRegExMatch = EpisodeRegEx.Match(releaseInfo);
|
||||
if (EpisodeRegExMatch.Success)
|
||||
episode = EpisodeRegExMatch.Groups[1].Value;
|
||||
|
||||
releaseInfo = releaseInfo.Replace("Episode ", "");
|
||||
releaseInfo = releaseInfo.Replace("Season ", "S");
|
||||
releaseInfo = releaseInfo.Trim();
|
||||
int test = 0;
|
||||
if (InsertSeason && int.TryParse(releaseInfo, out test) && releaseInfo.Length <= 3)
|
||||
{
|
||||
releaseInfo = "E0" + releaseInfo;
|
||||
if (Property.Contains(" Lossless "))
|
||||
Category = new List<int> { TorznabCatType.AudioLossless.ID };
|
||||
else if (Property.Contains("MP3"))
|
||||
Category = new List<int> { TorznabCatType.AudioMP3.ID };
|
||||
else
|
||||
Category = new List<int> { TorznabCatType.AudioOther.ID };
|
||||
}
|
||||
}
|
||||
else if (rowCq.HasClass("torrent"))
|
||||
|
||||
// We dont actually have a release name >.> so try to create one
|
||||
var releaseTags = Property.Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||
for (int i = releaseTags.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var links = rowCq.Find("a");
|
||||
// Protect against format changes
|
||||
if (links.Count() != 2)
|
||||
releaseTags[i] = releaseTags[i].Trim();
|
||||
if (string.IsNullOrWhiteSpace(releaseTags[i]))
|
||||
releaseTags.RemoveAt(i);
|
||||
}
|
||||
|
||||
var releasegroup = releaseTags.LastOrDefault();
|
||||
if (releasegroup != null && releasegroup.Contains("(") && releasegroup.Contains(")"))
|
||||
{
|
||||
// Skip raws if set
|
||||
if (releasegroup.ToLowerInvariant().StartsWith("raw") && !AllowRaws)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (FilterSeasonEpisode)
|
||||
var start = releasegroup.IndexOf("(");
|
||||
releasegroup = "[" + releasegroup.Substring(start + 1, (releasegroup.IndexOf(")") - 1) - start) + "] ";
|
||||
}
|
||||
else
|
||||
{
|
||||
releasegroup = string.Empty;
|
||||
}
|
||||
|
||||
var infoString = "";
|
||||
|
||||
for (int i = 0; i + 1 < releaseTags.Count(); i++)
|
||||
{
|
||||
if (releaseTags[i] == "Raw" && !AllowRaws)
|
||||
continue;
|
||||
infoString += "[" + releaseTags[i] + "]";
|
||||
}
|
||||
|
||||
var MinimumSeedTime = 259200;
|
||||
// Additional 5 hours per GB
|
||||
MinimumSeedTime += (int)((Size / 1000000000) * 18000);
|
||||
|
||||
foreach (var title in synonyms)
|
||||
{
|
||||
string releaseTitle = null;
|
||||
if (GroupName == "Movie")
|
||||
{
|
||||
if (query.Season != 0 && season != null && season != query.Season) // skip if season doesn't match
|
||||
continue;
|
||||
if (query.Episode != null && episode != null && episode != query.Episode) // skip if episode doesn't match
|
||||
continue;
|
||||
releaseTitle = string.Format("{0} {1} {2}{3}", title, Year, releasegroup, infoString);
|
||||
}
|
||||
else
|
||||
{
|
||||
releaseTitle = string.Format("{0}{1} {2} {3}", releasegroup, title, releaseInfo, infoString);
|
||||
}
|
||||
|
||||
var release = new ReleaseInfo();
|
||||
release.MinimumRatio = 1;
|
||||
release.MinimumSeedTime = 259200;
|
||||
var downloadLink = links.Get(0);
|
||||
release.MinimumSeedTime = MinimumSeedTime;
|
||||
release.Title = releaseTitle;
|
||||
release.Comments = CommentsLinkUri;
|
||||
release.Guid = new Uri(CommentsLinkUri + "&nh=" + StringUtil.Hash(title)); // Sonarr should dedupe on this url - allow a url per name.
|
||||
release.Link = LinkUri;
|
||||
release.BannerUrl = ImageUrl;
|
||||
release.PublishDate = PublushDate;
|
||||
release.Category = Category;
|
||||
release.Description = Description;
|
||||
release.Size = Size;
|
||||
release.Seeders = Seeders;
|
||||
release.Peers = Peers;
|
||||
release.Grabs = Snatched;
|
||||
release.Files = FileCount;
|
||||
release.DownloadVolumeFactor = RawDownMultiplier;
|
||||
release.UploadVolumeFactor = RawUpMultiplier;
|
||||
|
||||
// We dont know this so try to fake based on the release year
|
||||
release.PublishDate = new DateTime(year, 1, 1);
|
||||
release.PublishDate = release.PublishDate.AddDays(Math.Min(DateTime.Now.DayOfYear, 365) - 1);
|
||||
|
||||
var infoLink = links.Get(1);
|
||||
release.Comments = new Uri(SiteLink + infoLink.Attributes.GetAttribute("href"));
|
||||
release.Guid = new Uri(SiteLink + infoLink.Attributes.GetAttribute("href") + "&nh=" + StringUtil.Hash(title)); // Sonarr should dedupe on this url - allow a url per name.
|
||||
release.Link = new Uri(downloadLink.Attributes.GetAttribute("href"));
|
||||
|
||||
string category = null;
|
||||
if (searchType == SearchType.Video)
|
||||
{
|
||||
category = seriesCq.Find("a[title=\"View Torrent\"]").Text().Trim();
|
||||
if (category == "TV Series")
|
||||
release.Category = new List<int> { TorznabCatType.TVAnime.ID };
|
||||
|
||||
// Ignore these categories as they'll cause hell with the matcher
|
||||
// TV Special, OVA, ONA, DVD Special, BD Special
|
||||
|
||||
if (category == "Movie")
|
||||
release.Category = new List<int> { TorznabCatType.Movies.ID };
|
||||
|
||||
if (category == "Manga" || category == "Oneshot" || category == "Anthology" || category == "Manhwa" || category == "Manhua" || category == "Light Novel")
|
||||
release.Category = new List<int> { TorznabCatType.BooksComics.ID };
|
||||
|
||||
if (category == "Novel" || category == "Artbook")
|
||||
release.Category = new List<int> { TorznabCatType.BooksComics.ID };
|
||||
|
||||
if (category == "Game" || category == "Visual Novel")
|
||||
{
|
||||
var description = rowCq.Find(".torrent_properties a:eq(1)").Text();
|
||||
if (description.Contains(" PSP "))
|
||||
release.Category = new List<int> { TorznabCatType.ConsolePSP.ID };
|
||||
if (description.Contains("PSX"))
|
||||
release.Category = new List<int> { TorznabCatType.ConsoleOther.ID };
|
||||
if (description.Contains(" NES "))
|
||||
release.Category = new List<int> { TorznabCatType.ConsoleOther.ID };
|
||||
if (description.Contains(" PC "))
|
||||
release.Category = new List<int> { TorznabCatType.PCGames.ID };
|
||||
}
|
||||
}
|
||||
|
||||
if (searchType == SearchType.Audio)
|
||||
{
|
||||
category = seriesCq.Find(".group_img .cat a").Text();
|
||||
if (category == "Single" || category == "EP" || category == "Album" || category == "Compilation" || category == "Soundtrack" || category == "Remix CD" || category == "PV" || category == "Live Album" || category == "Image CD" || category == "Drama CD" || category == "Vocal CD")
|
||||
{
|
||||
var description = rowCq.Find(".torrent_properties a:eq(1)").Text();
|
||||
if (description.Contains(" Lossless "))
|
||||
release.Category = new List<int> { TorznabCatType.AudioLossless.ID };
|
||||
else if (description.Contains("MP3"))
|
||||
release.Category = new List<int> { TorznabCatType.AudioMP3.ID };
|
||||
else
|
||||
release.Category = new List<int> { TorznabCatType.AudioOther.ID };
|
||||
}
|
||||
}
|
||||
|
||||
// We dont actually have a release name >.> so try to create one
|
||||
var releaseTags = infoLink.InnerText.Split("|".ToCharArray(), StringSplitOptions.RemoveEmptyEntries).ToList();
|
||||
for (int i = releaseTags.Count - 1; i >= 0; i--)
|
||||
{
|
||||
releaseTags[i] = releaseTags[i].Trim();
|
||||
if (string.IsNullOrWhiteSpace(releaseTags[i]))
|
||||
releaseTags.RemoveAt(i);
|
||||
}
|
||||
|
||||
var group = releaseTags.LastOrDefault();
|
||||
if (group != null && group.Contains("(") && group.Contains(")"))
|
||||
{
|
||||
// Skip raws if set
|
||||
if (group.ToLowerInvariant().StartsWith("raw") && !AllowRaws)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var start = group.IndexOf("(");
|
||||
group = "[" + group.Substring(start + 1, (group.IndexOf(")") - 1) - start) + "] ";
|
||||
}
|
||||
else
|
||||
{
|
||||
group = string.Empty;
|
||||
}
|
||||
|
||||
var infoString = "";
|
||||
|
||||
for (int i = 0; i + 1 < releaseTags.Count(); i++)
|
||||
{
|
||||
if (releaseTags[i] == "Raw" && !AllowRaws)
|
||||
continue;
|
||||
infoString += "[" + releaseTags[i] + "]";
|
||||
}
|
||||
|
||||
if (category == "Movie")
|
||||
{
|
||||
release.Title = string.Format("{0} {1} {2}{3}", title, year, group, infoString);
|
||||
}
|
||||
else
|
||||
{
|
||||
release.Title = string.Format("{0}{1} {2} {3}", group, title, releaseInfo, infoString);
|
||||
}
|
||||
release.Description = title;
|
||||
|
||||
var size = rowCq.Find(".torrent_size");
|
||||
if (size.Count() > 0)
|
||||
{
|
||||
release.Size = ReleaseInfo.GetBytes(size.First().Text());
|
||||
}
|
||||
|
||||
// Additional 5 hours per GB
|
||||
release.MinimumSeedTime += (release.Size / 1000000000) * 18000;
|
||||
|
||||
// Peer info
|
||||
release.Seeders = ParseUtil.CoerceInt(rowCq.Find(".torrent_seeders").Text());
|
||||
release.Peers = release.Seeders + ParseUtil.CoerceInt(rowCq.Find(".torrent_leechers").Text());
|
||||
|
||||
// grabs
|
||||
var grabs = rowCq.Find("td.torrent_snatched").Text();
|
||||
release.Grabs = ParseUtil.CoerceInt(grabs);
|
||||
|
||||
// freeleech
|
||||
if (rowCq.Find("img[alt=\"Freeleech!\"]").Length >= 1)
|
||||
release.DownloadVolumeFactor = 0;
|
||||
else
|
||||
release.DownloadVolumeFactor = 1;
|
||||
release.UploadVolumeFactor = 1;
|
||||
|
||||
//if (release.Category != null)
|
||||
releases.Add(release);
|
||||
}
|
||||
}
|
||||
|
@@ -1,4 +1,5 @@
|
||||
using Jackett.Common.Indexers.Abstract;
|
||||
using Jackett.Common.Models;
|
||||
using Jackett.Common.Services.Interfaces;
|
||||
using Jackett.Common.Utils.Clients;
|
||||
using NLog;
|
||||
@@ -19,5 +20,11 @@ namespace Jackett.Common.Indexers
|
||||
{
|
||||
Type = "private";
|
||||
}
|
||||
|
||||
// hook to adjust the search term
|
||||
protected override string GetSearchTerm(TorznabQuery query)
|
||||
{
|
||||
return query.SanitizedSearchTerm;
|
||||
}
|
||||
}
|
||||
}
|
@@ -20,21 +20,29 @@ namespace Jackett.Common.Indexers
|
||||
{
|
||||
public class BJShare : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
private string BrowseUrl { get { return SiteLink + "torrents.php"; } }
|
||||
private string TodayUrl { get { return SiteLink + "torrents.php?action=today"; } }
|
||||
private char[] digits = new[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
|
||||
|
||||
private new ConfigurationDataBasicLoginWithRSSAndDisplay configData
|
||||
private string LoginUrl => SiteLink + "login.php";
|
||||
private string BrowseUrl => SiteLink + "torrents.php";
|
||||
private string TodayUrl => SiteLink + "torrents.php?action=today";
|
||||
private readonly char[] _digits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
|
||||
private readonly Dictionary<string, string> _commonSearchTerms = new Dictionary<string, string>
|
||||
{
|
||||
get { return (ConfigurationDataBasicLoginWithRSSAndDisplay)base.configData; }
|
||||
set { base.configData = value; }
|
||||
{ "agents of shield", "Agents of S.H.I.E.L.D."}
|
||||
};
|
||||
|
||||
public override string[] LegacySiteLinks { get; protected set; } = new string[] {
|
||||
"https://bj-share.me/"
|
||||
};
|
||||
|
||||
private ConfigurationDataBasicLoginWithRSSAndDisplay ConfigData
|
||||
{
|
||||
get => (ConfigurationDataBasicLoginWithRSSAndDisplay)configData;
|
||||
set => configData = value;
|
||||
}
|
||||
|
||||
public BJShare(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "BJ-Share",
|
||||
: base("BJ-Share",
|
||||
description: "A brazilian tracker.",
|
||||
link: "https://bj-share.me/",
|
||||
link: "https://bj-share.info/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
configService: configService,
|
||||
client: wc,
|
||||
@@ -42,32 +50,32 @@ namespace Jackett.Common.Indexers
|
||||
p: ps,
|
||||
configData: new ConfigurationDataBasicLoginWithRSSAndDisplay())
|
||||
{
|
||||
Encoding = Encoding.UTF8;
|
||||
Encoding = Encoding.UTF8;
|
||||
Language = "pt-br";
|
||||
Type = "private";
|
||||
|
||||
AddCategoryMapping(14, TorznabCatType.TVAnime); // Anime
|
||||
AddCategoryMapping(3, TorznabCatType.PC0day); // Aplicativos
|
||||
AddCategoryMapping(8, TorznabCatType.Other); // Apostilas/Tutoriais
|
||||
AddCategoryMapping(19, TorznabCatType.AudioAudiobook); // Audiobook
|
||||
AddCategoryMapping(16, TorznabCatType.TVOTHER); // Desenho Animado
|
||||
AddCategoryMapping(18, TorznabCatType.TVDocumentary); // Documentários
|
||||
AddCategoryMapping(10, TorznabCatType.Books); // E-Books
|
||||
AddCategoryMapping(20, TorznabCatType.TVSport); // Esportes
|
||||
AddCategoryMapping(1, TorznabCatType.Movies); // Filmes
|
||||
AddCategoryMapping(12, TorznabCatType.MoviesOther); // Histórias em Quadrinhos
|
||||
AddCategoryMapping(5, TorznabCatType.Audio); // Músicas
|
||||
AddCategoryMapping(7, TorznabCatType.Other); // Outros
|
||||
AddCategoryMapping(9, TorznabCatType.BooksMagazines); // Revistas
|
||||
AddCategoryMapping(2, TorznabCatType.TV); // Seriados
|
||||
AddCategoryMapping(17, TorznabCatType.TV); // Shows
|
||||
AddCategoryMapping(13, TorznabCatType.TV); // Stand Up Comedy
|
||||
AddCategoryMapping(11, TorznabCatType.Other); // Video-Aula
|
||||
AddCategoryMapping(6, TorznabCatType.TV); // Vídeos de TV
|
||||
AddCategoryMapping(4, TorznabCatType.Other); // Jogos
|
||||
AddCategoryMapping(199, TorznabCatType.XXX); // Filmes Adultos
|
||||
AddCategoryMapping(200, TorznabCatType.XXX); // Jogos Adultos
|
||||
AddCategoryMapping(201, TorznabCatType.XXXImageset); // Fotos Adultas
|
||||
AddCategoryMapping(14, TorznabCatType.TVAnime, "Anime");
|
||||
AddCategoryMapping(3, TorznabCatType.PC0day, "Aplicativos");
|
||||
AddCategoryMapping(8, TorznabCatType.Other, "Apostilas/Tutoriais");
|
||||
AddCategoryMapping(19, TorznabCatType.AudioAudiobook, "Audiobook");
|
||||
AddCategoryMapping(16, TorznabCatType.TVOTHER, "Desenho Animado");
|
||||
AddCategoryMapping(18, TorznabCatType.TVDocumentary, "Documentários");
|
||||
AddCategoryMapping(10, TorznabCatType.Books, "E-Books");
|
||||
AddCategoryMapping(20, TorznabCatType.TVSport, "Esportes");
|
||||
AddCategoryMapping(1, TorznabCatType.Movies, "Filmes");
|
||||
AddCategoryMapping(12, TorznabCatType.MoviesOther, "Histórias em Quadrinhos");
|
||||
AddCategoryMapping(5, TorznabCatType.Audio, "Músicas");
|
||||
AddCategoryMapping(7, TorznabCatType.Other, "Outros");
|
||||
AddCategoryMapping(9, TorznabCatType.BooksMagazines, "Revistas");
|
||||
AddCategoryMapping(2, TorznabCatType.TV, "Seriados");
|
||||
AddCategoryMapping(17, TorznabCatType.TV, "Shows");
|
||||
AddCategoryMapping(13, TorznabCatType.TV, "Stand Up Comedy");
|
||||
AddCategoryMapping(11, TorznabCatType.Other, "Video-Aula");
|
||||
AddCategoryMapping(6, TorznabCatType.TV, "Vídeos de TV");
|
||||
AddCategoryMapping(4, TorznabCatType.Other, "Jogos");
|
||||
AddCategoryMapping(199, TorznabCatType.XXX, "Filmes Adultos");
|
||||
AddCategoryMapping(200, TorznabCatType.XXX, "Jogos Adultos");
|
||||
AddCategoryMapping(201, TorznabCatType.XXXImageset, "Fotos Adultas");
|
||||
}
|
||||
|
||||
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||
@@ -76,8 +84,8 @@ Encoding = Encoding.UTF8;
|
||||
|
||||
var pairs = new Dictionary<string, string>
|
||||
{
|
||||
{ "username", configData.Username.Value },
|
||||
{ "password", configData.Password.Value },
|
||||
{ "username", ConfigData.Username.Value },
|
||||
{ "password", ConfigData.Password.Value },
|
||||
{ "keeplogged", "1" }
|
||||
};
|
||||
|
||||
@@ -85,7 +93,7 @@ Encoding = Encoding.UTF8;
|
||||
await ConfigureIfOK(result.Cookies, result.Content != null && result.Content.Contains("logout.php"), () =>
|
||||
{
|
||||
var errorMessage = result.Content;
|
||||
throw new ExceptionWithConfigData(errorMessage, configData);
|
||||
throw new ExceptionWithConfigData(errorMessage, ConfigData);
|
||||
});
|
||||
return IndexerConfigurationStatus.RequiresTesting;
|
||||
}
|
||||
@@ -94,13 +102,24 @@ Encoding = Encoding.UTF8;
|
||||
{
|
||||
// Search does not support searching with episode numbers so strip it if we have one
|
||||
// Ww AND filter the result later to archive the proper result
|
||||
if (isAnime)
|
||||
{
|
||||
return term.TrimEnd(digits);
|
||||
}
|
||||
|
||||
var ret = Regex.Replace(term, @"[S|E]\d\d", string.Empty).Trim();
|
||||
return ret.Replace("Agents of SHIELD", "Agents of S.H.I.E.L.D.");
|
||||
return isAnime ? term.TrimEnd(_digits) : Regex.Replace(term, @"[S|E]\d\d", string.Empty).Trim();
|
||||
}
|
||||
|
||||
private static string FixAbsoluteNumbering(string title)
|
||||
{
|
||||
// if result is One piece, convert title from SXXEXX to EXX
|
||||
// One piece is the only anime that i'm aware that is in "absolute" numbering, the problem is that they include
|
||||
// the season (wrong season) and episode as absolute, eg: One Piece - S08E836
|
||||
// 836 is the latest episode in absolute numbering, that is correct, but S08 is not the current season...
|
||||
// So for this show, i don't see a other way to make it work...
|
||||
//
|
||||
// All others animes that i tested is with correct season and episode set, so i can't remove the season from all
|
||||
// or will break everything else
|
||||
//
|
||||
// In this indexer, it looks that it is added "automatically", so all current and new releases will be broken
|
||||
// until they or the source from where they get that info fix it...
|
||||
|
||||
return title.Contains("One Piece") ? Regex.Replace(title, @"(Ep[\.]?[ ]?)|([S]\d\d[Ee])", "E") : title;
|
||||
}
|
||||
|
||||
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
|
||||
@@ -113,50 +132,53 @@ Encoding = Encoding.UTF8;
|
||||
var results = await RequestStringWithCookies(TodayUrl);
|
||||
try
|
||||
{
|
||||
string RowsSelector = "table.torrent_table > tbody > tr:not(tr.colhead)";
|
||||
const string rowsSelector = "table.torrent_table > tbody > tr:not(tr.colhead)";
|
||||
|
||||
var SearchResultParser = new HtmlParser();
|
||||
var SearchResultDocument = SearchResultParser.Parse(results.Content);
|
||||
var Rows = SearchResultDocument.QuerySelectorAll(RowsSelector);
|
||||
foreach (var Row in Rows)
|
||||
var searchResultParser = new HtmlParser();
|
||||
var searchResultDocument = searchResultParser.Parse(results.Content);
|
||||
var rows = searchResultDocument.QuerySelectorAll(rowsSelector);
|
||||
foreach (var row in rows)
|
||||
{
|
||||
try
|
||||
{
|
||||
var release = new ReleaseInfo();
|
||||
var release = new ReleaseInfo
|
||||
{
|
||||
MinimumRatio = 1,
|
||||
MinimumSeedTime = 0
|
||||
};
|
||||
|
||||
release.MinimumRatio = 1;
|
||||
release.MinimumSeedTime = 0;
|
||||
|
||||
var qDetailsLink = Row.QuerySelector("a.BJinfoBox");
|
||||
var qTitle = qDetailsLink.QuerySelector("font");
|
||||
release.Title = qTitle.TextContent;
|
||||
|
||||
var qDetailsLink = row.QuerySelector("a.BJinfoBox");
|
||||
var qBJinfoBox = qDetailsLink.QuerySelector("span");
|
||||
var qCatLink = Row.QuerySelector("a[href^=\"/torrents.php?filter_cat\"]");
|
||||
var qDLLink = Row.QuerySelector("a[href^=\"torrents.php?action=download\"]");
|
||||
var qSeeders = Row.QuerySelector("td:nth-child(4)");
|
||||
var qLeechers = Row.QuerySelector("td:nth-child(5)");
|
||||
var qFreeLeech = Row.QuerySelector("font[color=\"green\"]:contains(Free)");
|
||||
var qCatLink = row.QuerySelector("a[href^=\"/torrents.php?filter_cat\"]");
|
||||
var qDlLink = row.QuerySelector("a[href^=\"torrents.php?action=download\"]");
|
||||
var qSeeders = row.QuerySelector("td:nth-child(4)");
|
||||
var qLeechers = row.QuerySelector("td:nth-child(5)");
|
||||
var qQuality = row.QuerySelector("font[color=\"red\"]");
|
||||
var qFreeLeech = row.QuerySelector("font[color=\"green\"]:contains(Free)");
|
||||
var qTitle = qDetailsLink.QuerySelector("font");
|
||||
// Get international title if available, or use the full title if not
|
||||
release.Title = Regex.Replace(qTitle.TextContent, @".* \[(.*?)\](.*)", "$1$2");
|
||||
|
||||
release.Description = "";
|
||||
foreach (var Child in qBJinfoBox.ChildNodes)
|
||||
foreach (var child in qBJinfoBox.ChildNodes)
|
||||
{
|
||||
var type = Child.NodeType;
|
||||
var type = child.NodeType;
|
||||
if (type != NodeType.Text)
|
||||
continue;
|
||||
|
||||
var line = Child.TextContent;
|
||||
var line = child.TextContent;
|
||||
if (line.StartsWith("Tamanho:"))
|
||||
{
|
||||
string Size = line.Substring("Tamanho: ".Length); ;
|
||||
release.Size = ReleaseInfo.GetBytes(Size);
|
||||
var size = line.Substring("Tamanho: ".Length); ;
|
||||
release.Size = ReleaseInfo.GetBytes(size);
|
||||
}
|
||||
else if (line.StartsWith("Lançado em: "))
|
||||
{
|
||||
string PublishDateStr = line.Substring("Lançado em: ".Length).Replace("às ", "");
|
||||
PublishDateStr += " +0";
|
||||
var PublishDate = DateTime.SpecifyKind(DateTime.ParseExact(PublishDateStr, "dd/MM/yyyy HH:mm z", CultureInfo.InvariantCulture), DateTimeKind.Unspecified);
|
||||
release.PublishDate = PublishDate.ToLocalTime();
|
||||
var publishDateStr = line.Substring("Lançado em: ".Length).Replace("às ", "");
|
||||
publishDateStr += " +0";
|
||||
var publishDate = DateTime.SpecifyKind(DateTime.ParseExact(publishDateStr, "dd/MM/yyyy HH:mm z", CultureInfo.InvariantCulture), DateTimeKind.Unspecified);
|
||||
release.PublishDate = publishDate.ToLocalTime();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -165,32 +187,36 @@ Encoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
var catStr = qCatLink.GetAttribute("href").Split('=')[1];
|
||||
// if result is an anime, convert title from SXXEXX to EXX
|
||||
if (catStr == "14")
|
||||
{
|
||||
release.Title = Regex.Replace(release.Title, @"(Ep[\.]?[ ]?)|([S]\d\d[Ee])", "E");
|
||||
}
|
||||
release.Category = MapTrackerCatToNewznab(catStr);
|
||||
release.Title = FixAbsoluteNumbering(release.Title);
|
||||
|
||||
release.Link = new Uri(SiteLink + qDLLink.GetAttribute("href"));
|
||||
var quality = qQuality.TextContent;
|
||||
switch (quality)
|
||||
{
|
||||
case "Full HD":
|
||||
release.Title += " 1080p";
|
||||
break;
|
||||
case "HD":
|
||||
release.Title += " 720p";
|
||||
break;
|
||||
default:
|
||||
release.Title += " 480p";
|
||||
break;
|
||||
}
|
||||
|
||||
release.Category = MapTrackerCatToNewznab(catStr);
|
||||
release.Link = new Uri(SiteLink + qDlLink.GetAttribute("href"));
|
||||
release.Comments = new Uri(SiteLink + qDetailsLink.GetAttribute("href"));
|
||||
release.Guid = release.Link;
|
||||
|
||||
release.Seeders = ParseUtil.CoerceInt(qSeeders.TextContent);
|
||||
release.Peers = ParseUtil.CoerceInt(qLeechers.TextContent) + release.Seeders;
|
||||
|
||||
if (qFreeLeech != null)
|
||||
release.DownloadVolumeFactor = 0;
|
||||
else
|
||||
release.DownloadVolumeFactor = 1;
|
||||
|
||||
release.DownloadVolumeFactor = qFreeLeech != null ? 0 : 1;
|
||||
release.UploadVolumeFactor = 1;
|
||||
|
||||
releases.Add(release);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error(string.Format("{0}: Error while parsing row '{1}': {2}", ID, Row.OuterHtml, ex.Message));
|
||||
logger.Error($"{ID}: Error while parsing row '{row.OuterHtml}': {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -203,10 +229,13 @@ Encoding = Encoding.UTF8;
|
||||
{
|
||||
var searchUrl = BrowseUrl;
|
||||
var isSearchAnime = query.Categories.Any(s => s == TorznabCatType.TVAnime.ID);
|
||||
|
||||
query.SearchTerm = query.SearchTerm.Replace("Agents of SHIELD", "Agents of S.H.I.E.L.D.");
|
||||
var searchString = query.GetQueryString();
|
||||
|
||||
foreach (var searchTerm in _commonSearchTerms)
|
||||
{
|
||||
query.SearchTerm = query.SearchTerm.ToLower().Replace(searchTerm.Key.ToLower(), searchTerm.Value);
|
||||
}
|
||||
|
||||
var searchString = query.GetQueryString();
|
||||
var queryCollection = new NameValueCollection
|
||||
{
|
||||
{"searchstr", StripSearchString(searchString, isSearchAnime)},
|
||||
@@ -227,132 +256,134 @@ Encoding = Encoding.UTF8;
|
||||
var results = await RequestStringWithCookies(searchUrl);
|
||||
try
|
||||
{
|
||||
string RowsSelector = "table.torrent_table > tbody > tr:not(tr.colhead)";
|
||||
const string rowsSelector = "table.torrent_table > tbody > tr:not(tr.colhead)";
|
||||
|
||||
var SearchResultParser = new HtmlParser();
|
||||
var SearchResultDocument = SearchResultParser.Parse(results.Content);
|
||||
var Rows = SearchResultDocument.QuerySelectorAll(RowsSelector);
|
||||
var searchResultParser = new HtmlParser();
|
||||
var searchResultDocument = searchResultParser.Parse(results.Content);
|
||||
var rows = searchResultDocument.QuerySelectorAll(rowsSelector);
|
||||
|
||||
ICollection<int> GroupCategory = null;
|
||||
string GroupTitle = null;
|
||||
string GroupYearStr = null;
|
||||
Nullable<DateTime> GroupPublishDate = null;
|
||||
ICollection<int> groupCategory = null;
|
||||
string groupTitle = null;
|
||||
string groupYearStr = null;
|
||||
var categoryStr = "";
|
||||
|
||||
foreach (var Row in Rows)
|
||||
foreach (var row in rows)
|
||||
{
|
||||
try
|
||||
{
|
||||
var qDetailsLink = Row.QuerySelector("a[href^=\"torrents.php?id=\"]");
|
||||
string Title = qDetailsLink.TextContent;
|
||||
ICollection<int> Category = null;
|
||||
string YearStr = null;
|
||||
Nullable<DateTime> YearPublishDate = null;
|
||||
string CategoryStr = "";
|
||||
var qDetailsLink = row.QuerySelector("a[href^=\"torrents.php?id=\"]");
|
||||
var title = qDetailsLink.TextContent;
|
||||
ICollection<int> category = null;
|
||||
string yearStr = null;
|
||||
|
||||
|
||||
if (Row.ClassList.Contains("group") || Row.ClassList.Contains("torrent")) // group/ungrouped headers
|
||||
if (row.ClassList.Contains("group") || row.ClassList.Contains("torrent")) // group/ungrouped headers
|
||||
{
|
||||
var qCatLink = Row.QuerySelector("a[href^=\"/torrents.php?filter_cat\"]");
|
||||
CategoryStr = qCatLink.GetAttribute("href").Split('=')[1].Split('&')[0];
|
||||
Category = MapTrackerCatToNewznab(CategoryStr);
|
||||
var qCatLink = row.QuerySelector("a[href^=\"/torrents.php?filter_cat\"]");
|
||||
categoryStr = qCatLink.GetAttribute("href").Split('=')[1].Split('&')[0];
|
||||
category = MapTrackerCatToNewznab(categoryStr);
|
||||
|
||||
YearStr = qDetailsLink.NextSibling.TextContent.Trim().TrimStart('[').TrimEnd(']');
|
||||
YearPublishDate = DateTime.SpecifyKind(DateTime.ParseExact(YearStr, "yyyy", CultureInfo.InvariantCulture), DateTimeKind.Unspecified);
|
||||
yearStr = qDetailsLink.NextSibling.TextContent.Trim().TrimStart('[').TrimEnd(']');
|
||||
|
||||
// if result is an anime, convert title from SXXEXX to EXX
|
||||
if (CategoryStr == "14")
|
||||
{
|
||||
Title = Regex.Replace(Title, @"(Ep[\.]?[ ]?)|([S]\d\d[Ee])", "E");
|
||||
}
|
||||
title = FixAbsoluteNumbering(title);
|
||||
|
||||
if (Row.ClassList.Contains("group")) // group headers
|
||||
if (row.ClassList.Contains("group")) // group headers
|
||||
{
|
||||
GroupCategory = Category;
|
||||
GroupTitle = Title;
|
||||
GroupYearStr = YearStr;
|
||||
GroupPublishDate = YearPublishDate;
|
||||
groupCategory = category;
|
||||
groupTitle = title;
|
||||
groupYearStr = yearStr;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
var release = new ReleaseInfo();
|
||||
|
||||
release.MinimumRatio = 1;
|
||||
release.MinimumSeedTime = 0;
|
||||
|
||||
var qDLLink = Row.QuerySelector("a[href^=\"torrents.php?action=download\"]");
|
||||
var qSize = Row.QuerySelector("td:nth-last-child(4)");
|
||||
var qGrabs = Row.QuerySelector("td:nth-last-child(3)");
|
||||
var qSeeders = Row.QuerySelector("td:nth-last-child(2)");
|
||||
var qLeechers = Row.QuerySelector("td:nth-last-child(1)");
|
||||
var qFreeLeech = Row.QuerySelector("strong[title=\"Free\"]");
|
||||
|
||||
if (Row.ClassList.Contains("group_torrent")) // torrents belonging to a group
|
||||
var release = new ReleaseInfo
|
||||
{
|
||||
release.Description = qDetailsLink.TextContent;
|
||||
MinimumRatio = 1,
|
||||
MinimumSeedTime = 0
|
||||
};
|
||||
|
||||
string cleanTitle = Regex.Replace(GroupTitle, @" - S?(?<season>\d{1,2})?E?(?<episode>\d{1,4})?", "");
|
||||
string seasonEp = Regex.Replace(GroupTitle, @"^(.*?) - (S?(\d{1,2})?E?(\d{1,4})?)?", "$2");
|
||||
release.Title = CategoryStr == "14" ? GroupTitle : cleanTitle + " " + GroupYearStr + " " + seasonEp;
|
||||
var qDlLink = row.QuerySelector("a[href^=\"torrents.php?action=download\"]");
|
||||
var qSize = row.QuerySelector("td:nth-last-child(4)");
|
||||
var qGrabs = row.QuerySelector("td:nth-last-child(3)");
|
||||
var qSeeders = row.QuerySelector("td:nth-last-child(2)");
|
||||
var qLeechers = row.QuerySelector("td:nth-last-child(1)");
|
||||
var qFreeLeech = row.QuerySelector("strong[title=\"Free\"]");
|
||||
|
||||
release.PublishDate = GroupPublishDate.Value;
|
||||
release.Category = GroupCategory;
|
||||
if (row.ClassList.Contains("group_torrent")) // torrents belonging to a group
|
||||
{
|
||||
var description = Regex.Replace(qDetailsLink.TextContent.Trim(), @"\s+", " ");
|
||||
description = Regex.Replace(description, @"((S\d{2})(E\d{2,4})?) (.*)", "$4");
|
||||
release.Description = description;
|
||||
|
||||
var cleanTitle = Regex.Replace(groupTitle, @" - ((S(\d{2}))?E(\d{1,4}))", "");
|
||||
title = Regex.Replace(title.Trim(), @"\s+", " ");
|
||||
var seasonEp = Regex.Replace(title, @"((S\d{2})?(E\d{2,4})?) .*", "$1");
|
||||
|
||||
// do not include year to animes
|
||||
if (categoryStr == "14")
|
||||
{
|
||||
release.Title = cleanTitle + " " + seasonEp;
|
||||
}
|
||||
else
|
||||
{
|
||||
release.Title = cleanTitle + " " + groupYearStr + " " + seasonEp;
|
||||
}
|
||||
release.Category = groupCategory;
|
||||
}
|
||||
else if (Row.ClassList.Contains("torrent")) // standalone/un grouped torrents
|
||||
else if (row.ClassList.Contains("torrent")) // standalone/un grouped torrents
|
||||
{
|
||||
var qDescription = Row.QuerySelector("div.torrent_info");
|
||||
var qDescription = row.QuerySelector("div.torrent_info");
|
||||
release.Description = qDescription.TextContent;
|
||||
|
||||
string cleanTitle = Regex.Replace(Title, @" - ((S(\d{1,2}))?E(\d{1,4}))", "");
|
||||
string seasonEp = Regex.Replace(Title, @"^(.*?) - ((S(\d{1,2}))?E(\d{1,4}))", "$2");
|
||||
release.Title = CategoryStr == "14" ? Title : cleanTitle + " " + YearStr + " " + seasonEp;
|
||||
var cleanTitle = Regex.Replace(title, @" - ((S\d{2})?(E\d{2,4})?)", "");
|
||||
var seasonEp = Regex.Replace(title, @"^(.*?) - ((S\d{2})?(E\d{2,4})?)", "$2");
|
||||
|
||||
release.PublishDate = YearPublishDate.Value;
|
||||
release.Category = Category;
|
||||
// do not include year to animes
|
||||
if (categoryStr == "14")
|
||||
{
|
||||
release.Title = cleanTitle + " " + seasonEp;
|
||||
}
|
||||
else
|
||||
{
|
||||
release.Title = cleanTitle + " " + yearStr + " " + seasonEp;
|
||||
}
|
||||
|
||||
release.Category = category;
|
||||
}
|
||||
|
||||
release.Description = release.Description.Replace(" / Free", ""); // Remove Free Tag
|
||||
|
||||
release.Description = release.Description.Replace("Full HD", "1080p");
|
||||
release.Description = release.Description.Replace("/ HD / ", "/ 720p /");
|
||||
release.Description = release.Description.Replace(" / HD]", " / 720p]");
|
||||
release.Description = release.Description.Replace("4K", "2160p");
|
||||
|
||||
int nBarra = release.Title.IndexOf("[");
|
||||
if (nBarra != -1)
|
||||
{
|
||||
release.Title = release.Title.Substring(nBarra + 1);
|
||||
release.Title = release.Title.Replace("]", "");
|
||||
}
|
||||
|
||||
// Get international title if available, or use the full title if not
|
||||
release.Title = Regex.Replace(release.Title, @".* \[(.*?)\](.*)", "$1$2");
|
||||
release.Title += " " + release.Description; // add year and Description to the release Title to add some meaning to it
|
||||
|
||||
// This tracker does not provide an publish date to search terms (only on last 24h page)
|
||||
release.PublishDate = DateTime.Today;
|
||||
|
||||
// check for previously stripped search terms
|
||||
if (!query.MatchQueryStringAND(release.Title))
|
||||
continue;
|
||||
|
||||
var Size = qSize.TextContent;
|
||||
release.Size = ReleaseInfo.GetBytes(Size);
|
||||
|
||||
release.Link = new Uri(SiteLink + qDLLink.GetAttribute("href"));
|
||||
var size = qSize.TextContent;
|
||||
release.Size = ReleaseInfo.GetBytes(size);
|
||||
release.Link = new Uri(SiteLink + qDlLink.GetAttribute("href"));
|
||||
release.Comments = new Uri(SiteLink + qDetailsLink.GetAttribute("href"));
|
||||
release.Guid = release.Link;
|
||||
|
||||
release.Grabs = ParseUtil.CoerceLong(qGrabs.TextContent);
|
||||
release.Seeders = ParseUtil.CoerceInt(qSeeders.TextContent);
|
||||
release.Peers = ParseUtil.CoerceInt(qLeechers.TextContent) + release.Seeders;
|
||||
|
||||
if (qFreeLeech != null)
|
||||
release.DownloadVolumeFactor = 0;
|
||||
else
|
||||
release.DownloadVolumeFactor = 1;
|
||||
|
||||
release.DownloadVolumeFactor = qFreeLeech != null ? 0 : 1;
|
||||
release.UploadVolumeFactor = 1;
|
||||
|
||||
releases.Add(release);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.Error(string.Format("{0}: Error while parsing row '{1}': {2}", ID, Row.OuterHtml, ex.Message));
|
||||
logger.Error($"{ID}: Error while parsing row '{row.OuterHtml}': {ex.Message}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using AutoMapper;
|
||||
using AutoMapper;
|
||||
using Jackett.Common.Models;
|
||||
using Jackett.Common.Models.IndexerConfig;
|
||||
using Jackett.Common.Services.Interfaces;
|
||||
@@ -12,6 +7,13 @@ using Jackett.Common.Utils.Clients;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static Jackett.Common.Models.IndexerConfig.ConfigurationData;
|
||||
|
||||
namespace Jackett.Common.Indexers
|
||||
{
|
||||
@@ -32,6 +34,9 @@ namespace Jackett.Common.Indexers
|
||||
public string Type { get; protected set; }
|
||||
public virtual string ID { get { return GetIndexerID(GetType()); } }
|
||||
|
||||
[JsonConverter(typeof(EncodingJsonConverter))]
|
||||
public Encoding Encoding { get; protected set; }
|
||||
|
||||
public virtual bool IsConfigured { get; protected set; }
|
||||
protected Logger logger;
|
||||
protected IIndexerConfigurationService configurationService;
|
||||
@@ -154,8 +159,11 @@ namespace Jackett.Common.Indexers
|
||||
{
|
||||
if (jsonConfig is JArray)
|
||||
{
|
||||
LoadValuesFromJson(jsonConfig, true);
|
||||
IsConfigured = true;
|
||||
if (!MigratedFromDPAPI(jsonConfig))
|
||||
{
|
||||
LoadValuesFromJson(jsonConfig, true);
|
||||
IsConfigured = true;
|
||||
}
|
||||
}
|
||||
// read and upgrade old settings file format
|
||||
else if (jsonConfig is Object)
|
||||
@@ -166,6 +174,95 @@ namespace Jackett.Common.Indexers
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Remove this section once users have moved off DPAPI
|
||||
private bool MigratedFromDPAPI(JToken jsonConfig)
|
||||
{
|
||||
if (EnvironmentUtil.IsRunningLegacyOwin)
|
||||
{
|
||||
//Still running legacy Owin and using the DPAPI, we don't want to migrate
|
||||
logger.Debug(ID + " - Running Owin, no need to migrate from DPAPI");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool runningOnDotNetCore = RuntimeInformation.FrameworkDescription.IndexOf("core", StringComparison.OrdinalIgnoreCase) >= 0;
|
||||
bool isWindows = Environment.OSVersion.Platform == PlatformID.Win32NT;
|
||||
|
||||
if (!isWindows && runningOnDotNetCore)
|
||||
{
|
||||
// User isn't running Windows, but is running on .NET Core framework, no access to the DPAPI, so don't bother trying to migrate
|
||||
return false;
|
||||
}
|
||||
|
||||
LoadValuesFromJson(jsonConfig, false);
|
||||
|
||||
StringItem passwordPropertyValue = null;
|
||||
string passwordValue = "";
|
||||
|
||||
try
|
||||
{
|
||||
// try dynamic items first (e.g. all cardigann indexers)
|
||||
passwordPropertyValue = (StringItem)configData.GetDynamicByName("password");
|
||||
|
||||
if (passwordPropertyValue == null) // if there's no dynamic password try the static property
|
||||
{
|
||||
passwordPropertyValue = (StringItem)configData.GetType().GetProperty("Password").GetValue(configData, null);
|
||||
|
||||
// protection is based on the item.Name value (property name might be different, example: Abnormal), so check the Name again
|
||||
if (!string.Equals(passwordPropertyValue.Name, "password", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
logger.Debug($"Skipping non default password property (unencrpyted password) for [{ID}] while attempting migration");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
passwordValue = passwordPropertyValue.Value;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
logger.Debug($"Unable to source password for [{ID}] while attempting migration, likely a tracker without a password setting");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(passwordValue))
|
||||
{
|
||||
try
|
||||
{
|
||||
protectionService.UnProtect(passwordValue);
|
||||
//Password successfully unprotected using Microsoft.AspNetCore.DataProtection, no further action needed as we've already converted the password previously
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
if (ex.Message != "The provided payload cannot be decrypted because it was not protected with this protection provider.")
|
||||
{
|
||||
logger.Info($"Password could not be unprotected using Microsoft.AspNetCore.DataProtection - {ID} : " + ex);
|
||||
}
|
||||
|
||||
logger.Info($"Attempting legacy Unprotect - {ID} : ");
|
||||
|
||||
try
|
||||
{
|
||||
string unprotectedPassword = protectionService.LegacyUnProtect(passwordValue);
|
||||
//Password successfully unprotected using Windows/Mono DPAPI
|
||||
|
||||
passwordPropertyValue.Value = unprotectedPassword;
|
||||
SaveConfig();
|
||||
IsConfigured = true;
|
||||
|
||||
logger.Info($"Password successfully migrated for {ID}");
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
logger.Info($"Password could not be unprotected using legacy DPAPI - {ID} : " + exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected async Task ConfigureIfOK(string cookies, bool isLoggedin, Func<Task> onError)
|
||||
{
|
||||
if (isLoggedin)
|
||||
@@ -193,7 +290,7 @@ namespace Jackett.Common.Indexers
|
||||
return filteredResults;
|
||||
}
|
||||
|
||||
public bool CanHandleQuery(TorznabQuery query)
|
||||
public virtual bool CanHandleQuery(TorznabQuery query)
|
||||
{
|
||||
if (query == null)
|
||||
return false;
|
||||
@@ -205,7 +302,10 @@ namespace Jackett.Common.Indexers
|
||||
if (query.HasSpecifiedCategories)
|
||||
if (!caps.SupportsCategories(query.Categories))
|
||||
return false;
|
||||
|
||||
if (caps.SupportsImdbSearch && query.IsImdbQuery)
|
||||
return true;
|
||||
else if (!caps.SupportsImdbSearch && query.IsImdbQuery && query.QueryType != "TorrentPotato") // potato query should always contain imdb+search term
|
||||
return false;
|
||||
if (caps.SearchAvailable && query.IsSearch)
|
||||
return true;
|
||||
if (caps.TVSearchAvailable && query.IsTVSearch)
|
||||
@@ -239,6 +339,10 @@ namespace Jackett.Common.Indexers
|
||||
return new IndexerResult(this, new ReleaseInfo[0]);
|
||||
var results = await PerformQuery(query);
|
||||
results = FilterResults(query, results);
|
||||
if (query.Limit > 0)
|
||||
{
|
||||
results = results.Take(query.Limit);
|
||||
}
|
||||
results = results.Select(r =>
|
||||
{
|
||||
r.Origin = this;
|
||||
@@ -473,6 +577,7 @@ namespace Jackett.Common.Indexers
|
||||
|| response.Status == System.Net.HttpStatusCode.GatewayTimeout
|
||||
|| (int)response.Status == 521 // used by cloudflare to signal the original webserver is refusing the connection
|
||||
|| (int)response.Status == 522 // used by cloudflare to signal the original webserver is not reachable at all (timeout)
|
||||
|| (int)response.Status == 523 // used by cloudflare to signal the original webserver is not reachable at all (Origin is unreachable)
|
||||
)
|
||||
{
|
||||
throw new Exception("Request to " + response.Request.Url + " failed (Error " + response.Status + ") - The tracker seems to be down.");
|
||||
@@ -747,9 +852,6 @@ namespace Jackett.Common.Indexers
|
||||
|
||||
public override TorznabCapabilities TorznabCaps { get; protected set; }
|
||||
|
||||
[JsonConverter(typeof(EncodingJsonConverter))]
|
||||
public Encoding Encoding { get; protected set; }
|
||||
|
||||
private List<CategoryMapping> categoryMapping = new List<CategoryMapping>();
|
||||
protected WebClient webclient;
|
||||
protected readonly string downloadUrlBase = "";
|
||||
|
@@ -43,45 +43,46 @@ namespace Jackett.Common.Indexers
|
||||
|
||||
configData.DisplayText.Value = "Go to the general tab of your BeyondHD user profile and create/copy the Login Link.";
|
||||
|
||||
AddCategoryMapping(37, TorznabCatType.MoviesBluRay); // Movie / Blu-ray
|
||||
AddMultiCategoryMapping(TorznabCatType.Movies3D,
|
||||
71, // Movie / 3D
|
||||
83 // FraMeSToR 3D
|
||||
);
|
||||
AddMultiCategoryMapping(TorznabCatType.MoviesHD,
|
||||
77, // Movie / 1080p/i
|
||||
94, // Movie / 4K
|
||||
78, // Movie / 720p
|
||||
54, // Movie / MP4
|
||||
17, // Movie / Remux
|
||||
50, // Internal / FraMeSToR 1080p
|
||||
75, // Internal / FraMeSToR 720p
|
||||
49, // Internal / FraMeSToR REMUX
|
||||
101, // Internal / FraMeSToR 4K REMUX
|
||||
61, // Internal / HDX REMUX
|
||||
86, // Internal / SC4R
|
||||
95, // Nightripper 1080p
|
||||
96, // Nightripper 720p
|
||||
98 // Nightripper MicroHD
|
||||
);
|
||||
AddCategoryMapping(37, TorznabCatType.MoviesBluRay, "Movie / Blu-ray");
|
||||
AddCategoryMapping(71, TorznabCatType.Movies3D, "Movie / 3D");
|
||||
AddCategoryMapping(83, TorznabCatType.Movies3D, "FraMeSToR 3D");
|
||||
|
||||
AddMultiCategoryMapping(TorznabCatType.TVHD,
|
||||
40, // TV Show / Blu-ray
|
||||
44, // TV Show / Encodes
|
||||
48, // TV Show / HDTV
|
||||
89, // TV Show / Packs
|
||||
46, // TV Show / Remux
|
||||
45, // TV Show / WEB-DL
|
||||
97 // Nightripper TV Show Encodes
|
||||
);
|
||||
AddCategoryMapping(77, TorznabCatType.MoviesHD, "Movie / 1080p/i");
|
||||
AddCategoryMapping(102, TorznabCatType.MoviesUHD, "Movie / 4K Disk");
|
||||
AddCategoryMapping(94, TorznabCatType.MoviesUHD, "Movie / 4K Other");
|
||||
AddCategoryMapping(103, TorznabCatType.MoviesUHD, "Movie / 4K Remux");
|
||||
AddCategoryMapping(78, TorznabCatType.MoviesHD, "Movie / 720p");
|
||||
AddCategoryMapping(54, TorznabCatType.MoviesHD, "Movie / MP4");
|
||||
AddCategoryMapping(17, TorznabCatType.MoviesHD, "Movie / Remux");
|
||||
AddCategoryMapping(38, TorznabCatType.MoviesHD, "Movie / WEB-DL");
|
||||
AddCategoryMapping(106, TorznabCatType.MoviesHD, "Internal / BHDStudio 1080p");
|
||||
AddCategoryMapping(105, TorznabCatType.MoviesHD, "Internal / BHDStudio 720p");
|
||||
AddCategoryMapping(50, TorznabCatType.MoviesHD, "Internal / FraMeSToR 1080p");
|
||||
AddCategoryMapping(75, TorznabCatType.MoviesHD, "Internal / FraMeSToR 720p");
|
||||
AddCategoryMapping(49, TorznabCatType.MoviesHD, "Internal / FraMeSToR REMUX");
|
||||
AddCategoryMapping(101, TorznabCatType.MoviesHD, "Internal / FraMeSToR 4K REMUX");
|
||||
AddCategoryMapping(61, TorznabCatType.MoviesHD, "Internal / HDX REMUX");
|
||||
AddCategoryMapping(86, TorznabCatType.MoviesHD, "Internal / SC4R");
|
||||
AddCategoryMapping(95, TorznabCatType.MoviesHD, "Nightripper 1080p");
|
||||
AddCategoryMapping(96, TorznabCatType.MoviesHD, "Nightripper 720p");
|
||||
AddCategoryMapping(98, TorznabCatType.MoviesHD, "Nightripper MicroHD");
|
||||
|
||||
AddCategoryMapping(36, TorznabCatType.AudioLossless); // Music / Lossless
|
||||
AddCategoryMapping(69, TorznabCatType.AudioMP3); // Music / MP3
|
||||
AddMultiCategoryMapping(TorznabCatType.AudioVideo,
|
||||
55, // Music / 1080p/i
|
||||
56, // Music / 720p
|
||||
42 // Music / Blu-ray
|
||||
);
|
||||
AddCategoryMapping(104, TorznabCatType.TVUHD, "TV Show / 4K");
|
||||
AddCategoryMapping(40, TorznabCatType.TVHD, "TV Show / Blu-ray");
|
||||
AddCategoryMapping(44, TorznabCatType.TVHD, "TV Show / Encodes");
|
||||
AddCategoryMapping(48, TorznabCatType.TVHD, "TV Show / HDTV");
|
||||
AddCategoryMapping(89, TorznabCatType.TVHD, "TV Show / Packs");
|
||||
AddCategoryMapping(46, TorznabCatType.TVHD, "TV Show / Remux");
|
||||
AddCategoryMapping(99, TorznabCatType.TVHD, "TV Show / Sports");
|
||||
AddCategoryMapping(100, TorznabCatType.TVHD, "TV Show / Sports / WEB-DL");
|
||||
AddCategoryMapping(45, TorznabCatType.TVHD, "TV Show / WEB-DL");
|
||||
AddCategoryMapping(97, TorznabCatType.TVHD, "Nightripper TV Show Encodes");
|
||||
|
||||
AddCategoryMapping(36, TorznabCatType.AudioLossless, "Music / Lossless");
|
||||
AddCategoryMapping(69, TorznabCatType.AudioMP3, "Music / MP3");
|
||||
AddCategoryMapping(55, TorznabCatType.AudioVideo, "Music / 1080p/i");
|
||||
AddCategoryMapping(56, TorznabCatType.AudioVideo, "Music / 720p");
|
||||
AddCategoryMapping(42, TorznabCatType.AudioVideo, "Music / Blu-ray");
|
||||
}
|
||||
|
||||
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||
|
@@ -17,7 +17,7 @@ namespace Jackett.Common.Indexers
|
||||
{
|
||||
public class BitCityReloaded : BaseWebIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
private string LoginUrl { get { return SiteLink + "login/index.php"; } }
|
||||
private string BrowseUrl { get { return SiteLink + "uebersicht.php"; } }
|
||||
private TimeZoneInfo germanyTz = TimeZoneInfo.CreateCustomTimeZone("W. Europe Standard Time", new TimeSpan(1, 0, 0), "W. Europe Standard Time", "W. Europe Standard Time");
|
||||
|
||||
|
@@ -31,6 +31,8 @@ namespace Jackett.Common.Indexers
|
||||
protected WebClientStringResult landingResult;
|
||||
protected IHtmlDocument landingResultDocument;
|
||||
|
||||
protected List<string> DefaultCategories = new List<string>();
|
||||
|
||||
new ConfigurationData configData
|
||||
{
|
||||
get { return (ConfigurationData)base.configData; }
|
||||
@@ -172,6 +174,8 @@ namespace Jackett.Common.Indexers
|
||||
}
|
||||
}
|
||||
AddCategoryMapping(Categorymapping.id, TorznabCat, Categorymapping.desc);
|
||||
if (Categorymapping.Default)
|
||||
DefaultCategories.Add(Categorymapping.id);
|
||||
}
|
||||
}
|
||||
LoadValuesFromJson(null);
|
||||
@@ -193,6 +197,7 @@ namespace Jackett.Common.Indexers
|
||||
{
|
||||
Dictionary<string, object> variables = new Dictionary<string, object>();
|
||||
|
||||
variables[".Config.sitelink"] = SiteLink;
|
||||
foreach (settingsField Setting in Definition.Settings)
|
||||
{
|
||||
string value;
|
||||
@@ -247,6 +252,27 @@ namespace Jackett.Common.Indexers
|
||||
ReReplaceRegexMatches = ReReplaceRegexMatches.NextMatch();
|
||||
}
|
||||
|
||||
// handle join expression
|
||||
// Example: {{ join .Categories "," }}
|
||||
Regex JoinRegex = new Regex(@"{{\s*join\s+(\..+?)\s+""(.*?)""\s*}}");
|
||||
var JoinMatches = JoinRegex.Match(template);
|
||||
|
||||
while (JoinMatches.Success)
|
||||
{
|
||||
string all = JoinMatches.Groups[0].Value;
|
||||
string variable = JoinMatches.Groups[1].Value;
|
||||
string delimiter = JoinMatches.Groups[2].Value;
|
||||
|
||||
var input = (ICollection<string>)variables[variable];
|
||||
var expanded = string.Join(delimiter, input);
|
||||
|
||||
if (modifier != null)
|
||||
expanded = modifier(expanded);
|
||||
|
||||
template = template.Replace(all, expanded);
|
||||
JoinMatches = JoinMatches.NextMatch();
|
||||
}
|
||||
|
||||
// handle if ... else ... expression
|
||||
Regex IfElseRegex = new Regex(@"{{\s*if\s*(.+?)\s*}}(.*?){{\s*else\s*}}(.*?){{\s*end\s*}}");
|
||||
var IfElseRegexMatches = IfElseRegex.Match(template);
|
||||
@@ -338,6 +364,9 @@ namespace Jackett.Common.Indexers
|
||||
|
||||
protected bool checkForError(WebClientStringResult loginResult, IList<errorBlock> errorBlocks)
|
||||
{
|
||||
if(loginResult.Status == HttpStatusCode.Unauthorized) // e.g. used by YGGtorrent
|
||||
throw new ExceptionWithConfigData("401 Unauthorized, check your credentials", configData);
|
||||
|
||||
if (errorBlocks == null)
|
||||
return true; // no error
|
||||
|
||||
@@ -1082,6 +1111,11 @@ namespace Jackett.Common.Indexers
|
||||
variables[".Query.Episode"] = query.GetEpisodeSearchString();
|
||||
|
||||
var mappedCategories = MapTorznabCapsToTrackers(query);
|
||||
if (mappedCategories.Count == 0)
|
||||
{
|
||||
mappedCategories = this.DefaultCategories;
|
||||
}
|
||||
|
||||
variables[".Categories"] = mappedCategories;
|
||||
|
||||
var KeywordTokens = new List<string>();
|
||||
@@ -1317,7 +1351,19 @@ namespace Jackett.Common.Indexers
|
||||
value = release.Description;
|
||||
break;
|
||||
case "category":
|
||||
release.Category = MapTrackerCatToNewznab(value);
|
||||
var cats = MapTrackerCatToNewznab(value);
|
||||
if (release.Category == null)
|
||||
{
|
||||
release.Category = cats;
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var cat in cats)
|
||||
{
|
||||
if (!release.Category.Contains(cat))
|
||||
release.Category.Add(cat);
|
||||
}
|
||||
}
|
||||
value = release.Category.ToString();
|
||||
break;
|
||||
case "size":
|
||||
|
@@ -40,7 +40,7 @@ namespace Jackett.Common.Indexers
|
||||
{
|
||||
Encoding = Encoding.UTF8;
|
||||
Language = "en-us";
|
||||
Type = "private";
|
||||
Type = "public";
|
||||
|
||||
AddCategoryMapping(5, TorznabCatType.PC0day, "Applications");
|
||||
AddCategoryMapping(17, TorznabCatType.AudioAudiobook, "Audio Books");
|
||||
@@ -135,6 +135,11 @@ namespace Jackett.Common.Indexers
|
||||
var episodeSearchUrl = string.Format(SearchUrl, cat, WebUtility.UrlEncode(query.GetQueryString()));
|
||||
var results = await RequestStringWithCookiesAndRetry(episodeSearchUrl);
|
||||
|
||||
if (results.IsRedirect)
|
||||
{
|
||||
throw new ExceptionWithConfigData("Unexpected redirect to " + results.RedirectingTo + ". Check your credentials.", configData);
|
||||
}
|
||||
|
||||
if (results.Content.Contains("No torrents found"))
|
||||
{
|
||||
return releases;
|
||||
@@ -197,19 +202,17 @@ namespace Jackett.Common.Indexers
|
||||
release.Category = new List<int> { TorznabCatType.AudioOther.ID };
|
||||
}
|
||||
|
||||
release.Comments = new Uri(SiteLink + qLink.Attr("href"));
|
||||
release.Comments = new Uri(new Uri(SiteLink), qLink.Attr("href"));
|
||||
release.Guid = release.Comments;
|
||||
release.Link = release.Comments; // indirect download see Download() method
|
||||
|
||||
var qDownload = rowB.ChildElements.ElementAt(2).ChildElements.ElementAt(0).Cq();
|
||||
release.Link = new Uri(qDownload.Attr("href"));
|
||||
|
||||
var sizeStr = rowB.ChildElements.ElementAt(3).Cq().Text();
|
||||
var sizeStr = rowB.ChildElements.ElementAt(2).Cq().Text();
|
||||
release.Size = ReleaseInfo.GetBytes(sizeStr);
|
||||
|
||||
release.Seeders = ParseUtil.CoerceInt(rowB.ChildElements.ElementAt(6).Cq().Text());
|
||||
release.Seeders = ParseUtil.CoerceInt(rowB.ChildElements.ElementAt(5).Cq().Text());
|
||||
release.Peers = ParseUtil.CoerceInt(rowB.ChildElements.ElementAt(6).Cq().Text()) + release.Seeders;
|
||||
|
||||
var grabs = rowB.Cq().Find("td:nth-child(6)").Text();
|
||||
var grabs = rowB.Cq().Find("td:nth-child(5)").Text();
|
||||
release.Grabs = ParseUtil.CoerceInt(grabs);
|
||||
|
||||
release.DownloadVolumeFactor = 0; // ratioless
|
||||
@@ -224,5 +227,19 @@ namespace Jackett.Common.Indexers
|
||||
}
|
||||
return releases;
|
||||
}
|
||||
|
||||
public override async Task<byte[]> Download(Uri link)
|
||||
{
|
||||
var results = await RequestStringWithCookies(link.AbsoluteUri);
|
||||
//await FollowIfRedirect(results); // manual follow for better debugging (string)
|
||||
if (results.IsRedirect)
|
||||
results = await RequestStringWithCookies(results.RedirectingTo);
|
||||
CQ dom = results.Content;
|
||||
var dl = dom.Find("a:has(font:contains(\"Download torrent file\"))");
|
||||
|
||||
link = new Uri(dl.Attr("href"));
|
||||
|
||||
return await base.Download(link);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using AngleSharp.Parser.Html;
|
||||
using Jackett.Common.Models.IndexerConfig.Bespoke;
|
||||
using Jackett.Common.Models;
|
||||
using Jackett.Common.Models.IndexerConfig;
|
||||
using Jackett.Common.Services.Interfaces;
|
||||
@@ -22,10 +23,11 @@ namespace Jackett.Common.Indexers
|
||||
{ get { return SiteLink + "takelogin.php"; } }
|
||||
private string BrowseUrl
|
||||
{ get { return SiteLink + "browse.php"; } }
|
||||
private bool TorrentHTTPSMode => configData.TorrentHTTPSMode.Value;
|
||||
|
||||
private new ConfigurationDataBasicLogin configData
|
||||
private new ConfigurationDataEliteTracker configData
|
||||
{
|
||||
get { return (ConfigurationDataBasicLogin)base.configData; }
|
||||
get { return (ConfigurationDataEliteTracker)base.configData; }
|
||||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
@@ -37,10 +39,10 @@ namespace Jackett.Common.Indexers
|
||||
logger: logger,
|
||||
p: protectionService,
|
||||
client: webClient,
|
||||
configData: new ConfigurationDataBasicLogin()
|
||||
configData: new ConfigurationDataEliteTracker()
|
||||
)
|
||||
{
|
||||
Encoding = Encoding.UTF8;
|
||||
Encoding = Encoding.UTF8;
|
||||
Language = "fr-fr";
|
||||
Type = "private";
|
||||
|
||||
@@ -206,6 +208,13 @@ Encoding = Encoding.UTF8;
|
||||
release.Peers = ParseUtil.CoerceInt(Leechers.TextContent) + release.Seeders;
|
||||
release.Grabs = ParseUtil.CoerceLong(Grabs.TextContent);
|
||||
|
||||
if (TorrentHTTPSMode)
|
||||
{
|
||||
var linkHttps = Row.QuerySelector("td:nth-child(4)").QuerySelector("a").GetAttribute("href");
|
||||
var idTorrent = ParseUtil.GetArgumentFromQueryString(linkHttps, "id");
|
||||
release.Link = new Uri($"{SiteLink}download.php?id={idTorrent}&type=ssl");
|
||||
}
|
||||
|
||||
if (added.QuerySelector("img[alt^=\"TORRENT GRATUIT\"]") != null)
|
||||
release.DownloadVolumeFactor = 0;
|
||||
else if (added.QuerySelector("img[alt^=\"TORRENT SILVER\"]") != null)
|
||||
|
@@ -19,6 +19,10 @@ namespace Jackett.Common.Indexers
|
||||
{
|
||||
public class FileList : BaseWebIndexer
|
||||
{
|
||||
public override string[] LegacySiteLinks { get; protected set; } = new string[] {
|
||||
"http://filelist.ro/",
|
||||
};
|
||||
|
||||
private string LoginUrl { get { return SiteLink + "takelogin.php"; } }
|
||||
private string BrowseUrl { get { return SiteLink + "browse.php"; } }
|
||||
|
||||
@@ -31,7 +35,7 @@ namespace Jackett.Common.Indexers
|
||||
public FileList(IIndexerConfigurationService configService, WebClient wc, Logger l, IProtectionService ps)
|
||||
: base(name: "FileList",
|
||||
description: "The best Romanian site.",
|
||||
link: "http://filelist.ro/",
|
||||
link: "https://filelist.ro/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
configService: configService,
|
||||
client: wc,
|
||||
|
@@ -23,9 +23,9 @@ namespace Jackett.Common.Indexers
|
||||
private string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
private const int MAXPAGES = 3;
|
||||
|
||||
private new ConfigurationDataBasicLogin configData
|
||||
private new ConfigurationDataRecaptchaLogin configData
|
||||
{
|
||||
get { return (ConfigurationDataBasicLogin)base.configData; }
|
||||
get { return (ConfigurationDataRecaptchaLogin)base.configData; }
|
||||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Jackett.Common.Indexers
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
configData: new ConfigurationDataBasicLogin())
|
||||
configData: new ConfigurationDataRecaptchaLogin())
|
||||
{
|
||||
Encoding = Encoding.GetEncoding("windows-1255");
|
||||
Language = "he-il";
|
||||
@@ -95,9 +95,57 @@ namespace Jackett.Common.Indexers
|
||||
AddCategoryMapping(76, TorznabCatType.TV, "סדרות");
|
||||
}
|
||||
|
||||
public override async Task<ConfigurationData> GetConfigurationForSetup()
|
||||
{
|
||||
var loginPage = await RequestStringWithCookies(LoginUrl, string.Empty);
|
||||
CQ cq = loginPage.Content;
|
||||
var captcha = cq.Find(".g-recaptcha"); // invisible recaptcha
|
||||
if (captcha.Any())
|
||||
{
|
||||
var result = this.configData;
|
||||
result.CookieHeader.Value = loginPage.Cookies;
|
||||
result.Captcha.SiteKey = captcha.Attr("data-sitekey");
|
||||
result.Captcha.Version = "2";
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = new ConfigurationDataBasicLogin();
|
||||
result.SiteLink.Value = configData.SiteLink.Value;
|
||||
result.Instructions.Value = configData.Instructions.Value;
|
||||
result.Username.Value = configData.Username.Value;
|
||||
result.Password.Value = configData.Password.Value;
|
||||
result.CookieHeader.Value = loginPage.Cookies;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||
{
|
||||
LoadValuesFromJson(configJson);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(configData.Captcha.Cookie))
|
||||
{
|
||||
CookieHeader = configData.Captcha.Cookie;
|
||||
try
|
||||
{
|
||||
var results = await PerformQuery(new TorznabQuery());
|
||||
if (results.Count() == 0)
|
||||
{
|
||||
throw new Exception("Your cookie did not work");
|
||||
}
|
||||
|
||||
IsConfigured = true;
|
||||
SaveConfig();
|
||||
return IndexerConfigurationStatus.Completed;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
IsConfigured = false;
|
||||
throw new Exception("Your cookie did not work: " + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
var loginPage = await RequestStringWithCookies(LoginUrl, string.Empty);
|
||||
|
||||
var pairs = new Dictionary<string, string> {
|
||||
|
@@ -1,245 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using CsQuery;
|
||||
using Jackett.Common.Models;
|
||||
using Jackett.Common.Models.IndexerConfig;
|
||||
using Jackett.Common.Services.Interfaces;
|
||||
using Jackett.Common.Utils;
|
||||
using Jackett.Common.Utils.Clients;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NLog;
|
||||
|
||||
namespace Jackett.Common.Indexers
|
||||
{
|
||||
//
|
||||
// Quick and dirty indexer for GFTracker.
|
||||
//
|
||||
public class GFTracker : BaseWebIndexer
|
||||
{
|
||||
private string StartPageUrl { get { return SiteLink + "login.php?returnto=%2F"; } }
|
||||
private string LoginUrl { get { return SiteLink + "loginsite.php"; } }
|
||||
private string SearchUrl { get { return SiteLink + "browse.php"; } }
|
||||
|
||||
private new ConfigurationDataRecaptchaLogin configData
|
||||
{
|
||||
get { return (ConfigurationDataRecaptchaLogin)base.configData; }
|
||||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public GFTracker(IIndexerConfigurationService configService, WebClient w, Logger l, IProtectionService ps)
|
||||
: base(name: "GFTracker",
|
||||
description: "Home of user happiness",
|
||||
link: "https://www.thegft.org/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
configService: configService,
|
||||
client: w,
|
||||
logger: l,
|
||||
p: ps,
|
||||
configData: new ConfigurationDataRecaptchaLogin())
|
||||
{
|
||||
Encoding = Encoding.UTF8;
|
||||
Language = "en-us";
|
||||
Type = "private";
|
||||
|
||||
AddCategoryMapping(2, TorznabCatType.PC0day, "0DAY");
|
||||
AddCategoryMapping(16, TorznabCatType.TVAnime, "Anime");
|
||||
AddCategoryMapping(1, TorznabCatType.PC0day, "APPS");
|
||||
AddCategoryMapping(9, TorznabCatType.Other, "E-Learning");
|
||||
AddCategoryMapping(35, TorznabCatType.TVFOREIGN, "Foreign");
|
||||
AddCategoryMapping(32, TorznabCatType.ConsoleNDS, "Games/NDS");
|
||||
AddCategoryMapping(6, TorznabCatType.PCGames, "Games/PC");
|
||||
AddCategoryMapping(36, TorznabCatType.ConsolePS4, "Games/Playstation");
|
||||
AddCategoryMapping(29, TorznabCatType.ConsolePSP, "Games/PSP");
|
||||
AddCategoryMapping(23, TorznabCatType.ConsoleWii, "Games/WII");
|
||||
AddCategoryMapping(12, TorznabCatType.ConsoleXbox, "Games/XBOX");
|
||||
AddCategoryMapping(11, TorznabCatType.Other, "Misc");
|
||||
AddCategoryMapping(48, TorznabCatType.MoviesBluRay, "Movies/BLURAY");
|
||||
AddCategoryMapping(8, TorznabCatType.MoviesDVD, "Movies/DVDR");
|
||||
AddCategoryMapping(18, TorznabCatType.MoviesHD, "Movies/X264-HD");
|
||||
AddCategoryMapping(49, TorznabCatType.MoviesSD, "Movies/X264-SD");
|
||||
AddCategoryMapping(7, TorznabCatType.MoviesSD, "Movies/XVID");
|
||||
AddCategoryMapping(38, TorznabCatType.AudioOther, "Music/DVDR");
|
||||
AddCategoryMapping(46, TorznabCatType.AudioLossless, "Music/FLAC");
|
||||
AddCategoryMapping(5, TorznabCatType.AudioMP3, "Music/MP3");
|
||||
AddCategoryMapping(13, TorznabCatType.AudioVideo, "Music/Vids");
|
||||
AddCategoryMapping(26, TorznabCatType.TVHD, "TV/BLURAY");
|
||||
AddCategoryMapping(37, TorznabCatType.TVSD, "TV/DVDR");
|
||||
AddCategoryMapping(19, TorznabCatType.TVSD, "TV/DVDRIP");
|
||||
AddCategoryMapping(47, TorznabCatType.TVSD, "TV/SD");
|
||||
AddCategoryMapping(17, TorznabCatType.TVHD, "TV/X264");
|
||||
AddCategoryMapping(4, TorznabCatType.TVSD, "TV/XVID");
|
||||
AddCategoryMapping(22, TorznabCatType.XXX, "XXX/0DAY");
|
||||
AddCategoryMapping(25, TorznabCatType.XXXDVD, "XXX/DVDR");
|
||||
AddCategoryMapping(20, TorznabCatType.XXX, "XXX/HD");
|
||||
AddCategoryMapping(3, TorznabCatType.XXXXviD, "XXX/XVID");
|
||||
}
|
||||
|
||||
public override async Task<ConfigurationData> GetConfigurationForSetup()
|
||||
{
|
||||
var loginPage = await RequestStringWithCookies(StartPageUrl, string.Empty);
|
||||
CQ cq = loginPage.Content;
|
||||
var result = this.configData;
|
||||
CQ recaptcha = cq.Find(".g-recaptcha").Attr("data-sitekey");
|
||||
if (recaptcha.Length != 0) // recaptcha not always present in login form, perhaps based on cloudflare uid or just phase of the moon
|
||||
{
|
||||
result.CookieHeader.Value = loginPage.Cookies;
|
||||
result.Captcha.SiteKey = cq.Find(".g-recaptcha").Attr("data-sitekey");
|
||||
result.Captcha.Version = "2";
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
var stdResult = new ConfigurationDataBasicLogin();
|
||||
stdResult.SiteLink.Value = configData.SiteLink.Value;
|
||||
stdResult.Username.Value = configData.Username.Value;
|
||||
stdResult.Password.Value = configData.Password.Value;
|
||||
stdResult.CookieHeader.Value = loginPage.Cookies;
|
||||
return stdResult;
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||
{
|
||||
LoadValuesFromJson(configJson);
|
||||
var pairs = new Dictionary<string, string> {
|
||||
{ "username", configData.Username.Value },
|
||||
{ "password", configData.Password.Value },
|
||||
{ "g-recaptcha-response", configData.Captcha.Value }
|
||||
};
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(configData.Captcha.Cookie))
|
||||
{
|
||||
CookieHeader = configData.Captcha.Cookie;
|
||||
try
|
||||
{
|
||||
var results = await PerformQuery(new TorznabQuery());
|
||||
if (results.Count() == 0)
|
||||
{
|
||||
throw new Exception("Your cookie did not work");
|
||||
}
|
||||
|
||||
IsConfigured = true;
|
||||
SaveConfig();
|
||||
return IndexerConfigurationStatus.Completed;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
IsConfigured = false;
|
||||
throw new Exception("Your cookie did not work: " + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
var response = await RequestLoginAndFollowRedirect(LoginUrl, pairs, configData.CookieHeader.Value, true, SearchUrl, StartPageUrl);
|
||||
UpdateCookieHeader(response.Cookies);
|
||||
UpdateCookieHeader("mybbuser=;"); // add dummy cookie, otherwise we get logged out after each request
|
||||
|
||||
await ConfigureIfOK(configData.CookieHeader.Value, response.Content != null && response.Content.Contains("logout.php"), () =>
|
||||
{
|
||||
CQ dom = response.Content;
|
||||
var messageEl = dom["div:has(h2)"].Last();
|
||||
messageEl.Children("a").Remove();
|
||||
messageEl.Children("style").Remove();
|
||||
var errorMessage = messageEl.Text().Trim();
|
||||
IsConfigured = false;
|
||||
throw new ExceptionWithConfigData(errorMessage, configData);
|
||||
});
|
||||
return IndexerConfigurationStatus.RequiresTesting;
|
||||
}
|
||||
|
||||
protected override async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
|
||||
{
|
||||
var releases = new List<ReleaseInfo>();
|
||||
var searchString = query.GetQueryString();
|
||||
|
||||
// search in normal + gems view
|
||||
foreach (var view in new string[] { "0", "1" })
|
||||
{
|
||||
var queryCollection = new NameValueCollection();
|
||||
|
||||
queryCollection.Add("view", view);
|
||||
queryCollection.Add("searchtype", "1");
|
||||
queryCollection.Add("incldead", "1");
|
||||
if (!string.IsNullOrWhiteSpace(searchString))
|
||||
{
|
||||
queryCollection.Add("search", searchString);
|
||||
}
|
||||
|
||||
foreach (var cat in MapTorznabCapsToTrackers(query))
|
||||
{
|
||||
queryCollection.Add(string.Format("c{0}", cat), "1");
|
||||
}
|
||||
|
||||
var searchUrl = SearchUrl + "?" + queryCollection.GetQueryString();
|
||||
|
||||
var results = await RequestStringWithCookiesAndRetry(searchUrl);
|
||||
if (results.IsRedirect)
|
||||
{
|
||||
// re-login
|
||||
await ApplyConfiguration(null);
|
||||
results = await RequestStringWithCookiesAndRetry(searchUrl);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
CQ dom = results.Content;
|
||||
var rows = dom["#torrentBrowse > table > tbody > tr"];
|
||||
foreach (var row in rows.Skip(1))
|
||||
{
|
||||
var release = new ReleaseInfo();
|
||||
CQ qRow = row.Cq();
|
||||
|
||||
release.MinimumRatio = 0;
|
||||
release.MinimumSeedTime = 2 * 24 * 60 * 60;
|
||||
|
||||
var qLink = qRow.Find("a[title][href^=\"details.php?id=\"]");
|
||||
release.Title = qLink.Attr("title");
|
||||
release.Guid = new Uri(SiteLink + qLink.Attr("href").TrimStart('/'));
|
||||
release.Comments = release.Guid;
|
||||
|
||||
qLink = qRow.Children().ElementAt(3).Cq().Children("a").First();
|
||||
release.Link = new Uri(string.Format("{0}{1}", SiteLink, qLink.Attr("href")));
|
||||
|
||||
var catUrl = qRow.Children().ElementAt(0).FirstElementChild.Cq().Attr("href");
|
||||
var catNum = catUrl.Split(new char[] { '=', '&' })[2].Replace("c", "");
|
||||
release.Category = MapTrackerCatToNewznab(catNum);
|
||||
|
||||
var dateString = qRow.Children().ElementAt(6).Cq().Text().Trim();
|
||||
if (dateString.Contains("ago"))
|
||||
release.PublishDate = DateTimeUtil.FromTimeAgo(dateString);
|
||||
else
|
||||
release.PublishDate = DateTime.ParseExact(dateString, "yyyy-MM-ddHH:mm:ss", CultureInfo.InvariantCulture);
|
||||
|
||||
var sizeStr = qRow.Children().ElementAt(7).Cq().Text().Split(new char[] { '/' })[0];
|
||||
release.Size = ReleaseInfo.GetBytes(sizeStr);
|
||||
|
||||
release.Seeders = ParseUtil.CoerceInt(qRow.Children().ElementAt(8).Cq().Text().Split(new char[] { '/' })[0].Trim());
|
||||
release.Peers = ParseUtil.CoerceInt(qRow.Children().ElementAt(8).Cq().Text().Split(new char[] { '/' })[1].Trim()) + release.Seeders;
|
||||
release.Files = ParseUtil.CoerceLong(qRow.Find("td:nth-child(5)").Text());
|
||||
release.Grabs = ParseUtil.CoerceLong(qRow.Find("a[href^=\"snatches.php?id=\"]").Text().Split(' ')[0]);
|
||||
|
||||
release.DownloadVolumeFactor = 0;
|
||||
release.UploadVolumeFactor = 1;
|
||||
|
||||
var desc = qRow.Find("td:nth-child(2)");
|
||||
desc.Find("a").Remove();
|
||||
desc.Find("small").Remove(); // Remove release name (if enabled in the user cp)
|
||||
release.Description = desc.Text().Trim(new char[] { '-', ' ' });
|
||||
|
||||
releases.Add(release);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
OnParseError(results.Content, ex);
|
||||
}
|
||||
}
|
||||
|
||||
return releases;
|
||||
}
|
||||
}
|
||||
}
|
@@ -219,6 +219,11 @@ namespace Jackett.Common.Indexers
|
||||
searchUrl += "?" + queryCollection.GetQueryString();
|
||||
|
||||
var results = await RequestStringWithCookies(searchUrl);
|
||||
if (results.IsRedirect && results.RedirectingTo.EndsWith("login.php"))
|
||||
{
|
||||
throw new Exception("relogin needed, please update your cookie");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
string RowsSelector = ".torrent_table > tbody > tr";
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user