mirror of
https://github.com/Jackett/Jackett.git
synced 2025-09-17 01:14:12 +02:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
49fa67e64e | ||
![]() |
770fc83ee8 | ||
![]() |
e373bb6916 | ||
![]() |
f4a1f69063 | ||
![]() |
ae6504dd62 | ||
![]() |
df4f1ee69f | ||
![]() |
6b503711fd | ||
![]() |
c81bb20684 |
65
Build.bat
65
Build.bat
@@ -1,32 +1,33 @@
|
||||
|
||||
rmdir /s /q build.windows
|
||||
rmdir /s /q build.mono
|
||||
rmdir /s /q Output
|
||||
cd src
|
||||
Msbuild Jackett.sln /t:Clean,Build /p:Configuration=Release /verbosity:minimal
|
||||
cd ..
|
||||
|
||||
xcopy src\Jackett.Console\bin\Release build.windows\ /e /y
|
||||
copy /Y src\Jackett.Service\bin\Release\JackettService.exe build.windows\JackettService.exe
|
||||
copy /Y src\Jackett.Service\bin\Release\JackettService.exe.config build.windows\JackettService.exe.config
|
||||
copy /Y src\Jackett.Tray\bin\Release\JackettTray.exe build.windows\JackettTray.exe
|
||||
copy /Y src\Jackett.Tray\bin\Release\JackettTray.exe.config build.windows\JackettTray.exe.config
|
||||
copy /Y LICENSE build.windows\LICENSE
|
||||
copy /Y README.md build.windows\README.md
|
||||
|
||||
|
||||
cd src
|
||||
Msbuild Jackett.sln /t:Clean
|
||||
call "C:\Program Files (x86)\Mono\bin\xbuild.bat" Jackett.sln /t:Build /p:Configuration=Release /verbosity:minimal
|
||||
cd ..
|
||||
|
||||
xcopy src\Jackett.Console\bin\Release build.mono\ /e /y
|
||||
copy /Y src\Jackett.Service\bin\Release\JackettService.exe build.mono\JackettService.exe
|
||||
copy /Y src\Jackett.Service\bin\Release\JackettService.exe.config build.mono\JackettService.exe.config
|
||||
copy /Y src\Jackett.Tray\bin\Release\JackettTray.exe build.mono\JackettTray.exe
|
||||
copy /Y src\Jackett.Tray\bin\Release\JackettTray.exe.config build.mono\JackettTray.exe.config
|
||||
copy /Y LICENSE build.mono\LICENSE
|
||||
copy /Y README.md build.mono\README.md
|
||||
|
||||
iscc Installer.iss
|
||||
|
||||
|
||||
rmdir /s /q build.windows
|
||||
rmdir /s /q build.mono
|
||||
rmdir /s /q Output
|
||||
cd src
|
||||
Msbuild Jackett.sln /t:Clean,Build /p:Configuration=Release /verbosity:minimal
|
||||
cd ..
|
||||
|
||||
xcopy src\Jackett.Console\bin\Release build.windows\ /e /y
|
||||
copy /Y src\Jackett.Service\bin\Release\JackettService.exe build.windows\JackettService.exe
|
||||
copy /Y src\Jackett.Service\bin\Release\JackettService.exe.config build.windows\JackettService.exe.config
|
||||
copy /Y src\Jackett.Tray\bin\Release\JackettTray.exe build.windows\JackettTray.exe
|
||||
copy /Y src\Jackett.Tray\bin\Release\JackettTray.exe.config build.windows\JackettTray.exe.config
|
||||
copy /Y LICENSE build.windows\LICENSE
|
||||
copy /Y README.md build.windows\README.md
|
||||
|
||||
|
||||
cd src
|
||||
Msbuild Jackett.sln /t:Clean
|
||||
call "C:\Program Files (x86)\Mono\bin\xbuild.bat" Jackett.sln /t:Build /p:Configuration=Release /verbosity:minimal
|
||||
cd ..
|
||||
|
||||
xcopy src\Jackett.Console\bin\Release build.mono\ /e /y
|
||||
copy /Y src\Jackett.Service\bin\Release\JackettService.exe build.mono\JackettService.exe
|
||||
copy /Y src\Jackett.Service\bin\Release\JackettService.exe.config build.mono\JackettService.exe.config
|
||||
copy /Y src\Jackett.Tray\bin\Release\JackettTray.exe build.mono\JackettTray.exe
|
||||
copy /Y src\Jackett.Tray\bin\Release\JackettTray.exe.config build.mono\JackettTray.exe.config
|
||||
copy /Y LICENSE build.mono\LICENSE
|
||||
copy /Y README.md build.mono\README.md
|
||||
copy /Y Upstart.config build.mono\Upstart.config
|
||||
|
||||
iscc Installer.iss
|
||||
|
||||
|
25
README.md
25
README.md
@@ -55,6 +55,14 @@ We were previously focused on TV but are working on extending searches to allow
|
||||
* [Torrentz](https://torrentz.eu/)
|
||||
* [TV Chaos UK](https://tvchaosuk.com/)
|
||||
|
||||
#### Installation on Windows
|
||||
|
||||
Grab the latest release from the [website](http://jackett.net/Download).
|
||||
|
||||
We recommend you install Jackett as a Windows service using the supplied installer. When installed as a service the tray icon acts as a way to open/start/stop Jackett. If you opted to not install it as a service then Jackett will run its web server from the tray tool.
|
||||
|
||||
Jackett can also be run from the command line using JackettConsole.exe if you would like to see log messages (Ensure the server isn't already running from the tray/service).
|
||||
|
||||
#### Installation on Linux/OSX
|
||||
1. Install [Mono 4](http://www.mono-project.com/download/) or better
|
||||
2. Install libcurl:
|
||||
@@ -63,15 +71,14 @@ We were previously focused on TV but are working on extending searches to allow
|
||||
* For other distros see the [Curl docs](http://curl.haxx.se/dlwiz/?type=devel).
|
||||
3. Download and extract the latest ```.tar.bz2``` release from the [website](http://jackett.net/Download) and run Jackett using mono with the command "mono JackettConsole.exe".
|
||||
|
||||
|
||||
#### Installation on Windows
|
||||
|
||||
Grab the latest release from the [web site](http://jackett.net/Download).
|
||||
|
||||
We recommend you install Jackett as a Windows service using the supplied installer. When installed as a service the tray icon acts as a way to open/start/stop Jackett. If you opted to not install it as a service then Jackett will run its web server from the tray tool.
|
||||
|
||||
Jackett can also be run from the command line using JackettConsole.exe if you would like to see log messages (Ensure the server isn't already running from the tray/service).
|
||||
|
||||
#### Installation on Synology
|
||||
1. Install Sonarr & Mono 3.10 from synocommunity.
|
||||
2. Install Mono beta 3.12 from the main Synology repo (Or newer if available).
|
||||
3. Download jackett and place it in /opt/Jackett
|
||||
4. cd /opt
|
||||
5. chown -R {user who will run jackett} Jackett
|
||||
6. Copy Upstart.config to /etc/init/jackett.conf and replace the braces {} in the script with the username that you wish to run Jackett with.
|
||||
9. From anywhere on command line type "start jackett" . You should see output telling you that Jackett is running and you should be able to browse to {IP Address}:9117 . If not you should check /var/log/upstart/jackett.log and see what that says.
|
||||
|
||||
#### Troubleshooting
|
||||
|
||||
|
20
Upstart.config
Normal file
20
Upstart.config
Normal file
@@ -0,0 +1,20 @@
|
||||
author "sea3pea0"
|
||||
description "Upstart Script to run NzbDrone as a service on Ubuntu/Debian based systems, as well as others"
|
||||
|
||||
#Set username for the process. Should probably be what you use for logging in
|
||||
setuid {username to run jackett}
|
||||
setgid users
|
||||
|
||||
#This is the install directory. If you installed using a deb package or the NzbDrone Repository you do not need to change this
|
||||
|
||||
env DIR=/opt/Jackett
|
||||
env LD_LIBRARY_PATH=/usr/local/nzbdrone/lib
|
||||
|
||||
start on runlevel [2345]
|
||||
stop on runlevel [016]
|
||||
|
||||
respawn
|
||||
script
|
||||
chdir $DIR
|
||||
exec /volume1/@appstore/Mono/usr/bin/mono --debug JackettConsole.exe
|
||||
end script
|
File diff suppressed because it is too large
Load Diff
@@ -4,6 +4,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel='shortcut icon' type='image/x-icon' href='/favicon.ico' />
|
||||
<script src="/libs/filesize.min.js"></script>
|
||||
<script src="/libs/jquery.min.js"></script>
|
||||
<script src="/libs/jquery.dataTables.min.js"></script>
|
||||
<script src="/libs/handlebars.min.js"></script>
|
||||
@@ -202,6 +203,8 @@
|
||||
<th>First Seen</th>
|
||||
<th>Tracker</th>
|
||||
<th>Name</th>
|
||||
<th>Size</th>
|
||||
<th>Size</th>
|
||||
<th>Category</th>
|
||||
<th>Seeds</th>
|
||||
<th>Leechers</th>
|
||||
@@ -217,6 +220,8 @@
|
||||
<td>{{jacketTimespan FirstSeen}}</td>
|
||||
<td>{{Tracker}}</td>
|
||||
<td><a href="{{Comments}}">{{Title}}</a></td>
|
||||
<td>{{Size}}</td>
|
||||
<td>{{jacketSize Size}}</td>
|
||||
<td>{{CategoryDesc}}</td>
|
||||
<td>{{Seeders}}</td>
|
||||
<td>{{Peers}}</td>
|
||||
@@ -296,6 +301,8 @@
|
||||
<th>Published</th>
|
||||
<th>Tracker</th>
|
||||
<th>Name</th>
|
||||
<th>Size</th>
|
||||
<th>Size</th>
|
||||
<th>Category</th>
|
||||
<th>Seeds</th>
|
||||
<th>Leechers</th>
|
||||
@@ -309,6 +316,8 @@
|
||||
<td>{{jacketTimespan PublishDate}}</td>
|
||||
<td>{{Tracker}}</td>
|
||||
<td><a href="{{Comments}}">{{Title}}</a></td>
|
||||
<td>{{Size}}</td>
|
||||
<td>{{jacketSize Size}}</td>
|
||||
<td>{{CategoryDesc}}</td>
|
||||
<td>{{Seeders}}</td>
|
||||
<td>{{Peers}}</td>
|
||||
|
6
src/Jackett/Content/libs/filesize.min.js
vendored
Normal file
6
src/Jackett/Content/libs/filesize.min.js
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
/*
|
||||
2015 Jason Mulligan
|
||||
@version 3.1.2
|
||||
*/
|
||||
"use strict"; !function (a) { var b = /b$/, c = { bits: ["B", "kb", "Mb", "Gb", "Tb", "Pb", "Eb", "Zb", "Yb"], bytes: ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"] }, d = function (a) { var d = void 0 === arguments[1] ? {} : arguments[1], e = [], f = !1, g = 0, h = void 0, i = void 0, j = void 0, k = void 0, l = void 0, m = void 0, n = void 0, o = void 0, p = void 0, q = void 0, r = void 0; if (isNaN(a)) throw new Error("Invalid arguments"); return j = d.bits === !0, p = d.unix === !0, i = void 0 !== d.base ? d.base : 2, o = void 0 !== d.round ? d.round : p ? 1 : 2, q = void 0 !== d.spacer ? d.spacer : p ? "" : " ", r = void 0 !== d.suffixes ? d.suffixes : {}, n = void 0 !== d.output ? d.output : "string", h = void 0 !== d.exponent ? d.exponent : -1, m = Number(a), l = 0 > m, k = i > 2 ? 1e3 : 1024, l && (m = -m), 0 === m ? (e[0] = 0, e[1] = p ? "" : "B") : ((-1 === h || isNaN(h)) && (h = Math.floor(Math.log(m) / Math.log(k))), h > 8 && (g = 1e3 * g * (h - 8), h = 8), g = 2 === i ? m / Math.pow(2, 10 * h) : m / Math.pow(1e3, h), j && (g = 8 * g, g > k && (g /= k, h++)), e[0] = Number(g.toFixed(h > 0 ? o : 0)), e[1] = c[j ? "bits" : "bytes"][h], !f && p && (j && b.test(e[1]) && (e[1] = e[1].toLowerCase()), e[1] = e[1].charAt(0), "B" === e[1] ? (e[0] = Math.floor(e[0]), e[1] = "") : j || "k" !== e[1] || (e[1] = "K"))), l && (e[0] = -e[0]), e[1] = r[e[1]] || e[1], "array" === n ? e : "exponent" === n ? h : "object" === n ? { value: e[0], suffix: e[1] } : e.join(q) }; "undefined" != typeof exports ? module.exports = d : "function" == typeof define ? define(function () { return d }) : a.filesize = d }("undefined" != typeof global ? global : window);
|
||||
//# sourceMappingURL=filesize.min.js.map
|
@@ -1,33 +1,37 @@
|
||||
|
||||
Handlebars.registerHelper('dateFormat', function (context, block) {
|
||||
if (window.moment) {
|
||||
var f = block.hash.format || "MMM DD, YYYY hh:mm:ss A";
|
||||
return moment(context).format(f); //had to remove Date(context)
|
||||
} else {
|
||||
return context; // moment plugin not available. return data as is.
|
||||
};
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('jacketTimespan', function (context, block) {
|
||||
var now = moment();
|
||||
var from = moment(context);
|
||||
var timeSpan = moment.duration(now.diff(from));
|
||||
|
||||
var minutes = timeSpan.asMinutes();
|
||||
if (minutes < 120) {
|
||||
return Math.round(minutes) + 'm ago';
|
||||
}
|
||||
|
||||
var hours = timeSpan.asHours();
|
||||
if (hours < 48) {
|
||||
return Math.round(hours) + 'h ago';
|
||||
}
|
||||
|
||||
var days = timeSpan.asDays();
|
||||
if (days < 365) {
|
||||
return Math.round(days) + 'd ago';
|
||||
}
|
||||
|
||||
var years = timeSpan.asYears();
|
||||
return Math.round(years) + 'y ago';
|
||||
|
||||
Handlebars.registerHelper('dateFormat', function (context, block) {
|
||||
if (window.moment) {
|
||||
var f = block.hash.format || "MMM DD, YYYY hh:mm:ss A";
|
||||
return moment(context).format(f); //had to remove Date(context)
|
||||
} else {
|
||||
return context; // moment plugin not available. return data as is.
|
||||
};
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('jacketTimespan', function (context, block) {
|
||||
var now = moment();
|
||||
var from = moment(context);
|
||||
var timeSpan = moment.duration(now.diff(from));
|
||||
|
||||
var minutes = timeSpan.asMinutes();
|
||||
if (minutes < 120) {
|
||||
return Math.round(minutes) + 'm ago';
|
||||
}
|
||||
|
||||
var hours = timeSpan.asHours();
|
||||
if (hours < 48) {
|
||||
return Math.round(hours) + 'h ago';
|
||||
}
|
||||
|
||||
var days = timeSpan.asDays();
|
||||
if (days < 365) {
|
||||
return Math.round(days) + 'd ago';
|
||||
}
|
||||
|
||||
var years = timeSpan.asYears();
|
||||
return Math.round(years) + 'y ago';
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('jacketSize', function (context, block) {
|
||||
return filesize(context, { round: 1 });
|
||||
});
|
File diff suppressed because it is too large
Load Diff
@@ -83,6 +83,11 @@ namespace Jackett.Indexers
|
||||
|
||||
public Uri UncleanLink(Uri link)
|
||||
{
|
||||
if (link.ToString().StartsWith(downloadUrlBase))
|
||||
{
|
||||
return link;
|
||||
}
|
||||
|
||||
return new Uri(downloadUrlBase + link.ToString(), UriKind.RelativeOrAbsolute);
|
||||
}
|
||||
|
||||
@@ -223,6 +228,11 @@ namespace Jackett.Indexers
|
||||
public async virtual Task<byte[]> Download(Uri link)
|
||||
{
|
||||
var response = await RequestBytesWithCookiesAndRetry(link.ToString());
|
||||
if(response.Status != System.Net.HttpStatusCode.OK && response.Status != System.Net.HttpStatusCode.Continue && response.Status != System.Net.HttpStatusCode.PartialContent)
|
||||
{
|
||||
throw new Exception($"Remote server returned {response.Status.ToString()}");
|
||||
}
|
||||
|
||||
return response.Content;
|
||||
}
|
||||
|
||||
|
@@ -1,135 +1,135 @@
|
||||
using CsQuery;
|
||||
using Jackett.Indexers;
|
||||
using Jackett.Models;
|
||||
using Jackett.Services;
|
||||
using Jackett.Utils;
|
||||
using Jackett.Utils.Clients;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Web.UI.WebControls;
|
||||
using Jackett.Models.IndexerConfig;
|
||||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class NxtGn : BaseIndexer, IIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
private string SearchUrl { get { return SiteLink + "browse.php"; } }
|
||||
private string ProfileUrl { get { return SiteLink + "my.php"; } }
|
||||
|
||||
new ConfigurationDataBasicLoginWithRSS configData
|
||||
{
|
||||
get { return (ConfigurationDataBasicLoginWithRSS)base.configData; }
|
||||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public NxtGn(IIndexerManagerService i, Logger l, IWebClient c, IProtectionService ps)
|
||||
: base(name: "NextGen",
|
||||
description: "A danish closed torrent tracker",
|
||||
link: "https://nxtgn.org/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
client: c,
|
||||
logger: l,
|
||||
p: ps,
|
||||
configData: new ConfigurationDataBasicLoginWithRSS())
|
||||
{
|
||||
AddCategoryMapping(47, TorznabCatType.Movies3D);
|
||||
AddCategoryMapping(38, TorznabCatType.MoviesHD);
|
||||
AddCategoryMapping(38, TorznabCatType.MoviesWEBDL);
|
||||
AddCategoryMapping(38, TorznabCatType.MoviesBluRay);
|
||||
AddCategoryMapping(5, TorznabCatType.MoviesSD);
|
||||
AddCategoryMapping(23, TorznabCatType.MoviesForeign);
|
||||
AddCategoryMapping(22, TorznabCatType.MoviesSD);
|
||||
//AddCategoryMapping(4, TorznabCatType.TVFOREIGN);
|
||||
//AddCategoryMapping(4, TorznabCatType.TVSD);
|
||||
//AddCategoryMapping(4, TorznabCatType.TVDocumentary);
|
||||
//AddCategoryMapping(4, TorznabCatType.TVSport);
|
||||
//AddCategoryMapping(4, TorznabCatType.TV);
|
||||
//AddCategoryMapping(31, TorznabCatType.TVHD);
|
||||
//AddCategoryMapping(21, TorznabCatType.TVFOREIGN);
|
||||
AddCategoryMapping(46, TorznabCatType.TV);
|
||||
AddCategoryMapping(46, TorznabCatType.TVHD);
|
||||
//AddCategoryMapping(45, TorznabCatType.TV);
|
||||
//AddCategoryMapping(45, TorznabCatType.TVSD);
|
||||
//AddCategoryMapping(24, TorznabCatType.TVFOREIGN);
|
||||
AddCategoryMapping(26, TorznabCatType.TV);
|
||||
AddCategoryMapping(26, TorznabCatType.TVHD);
|
||||
AddCategoryMapping(26, TorznabCatType.TVWEBDL);
|
||||
AddCategoryMapping(33, TorznabCatType.MoviesHD);
|
||||
AddCategoryMapping(33, TorznabCatType.Movies);
|
||||
AddCategoryMapping(17, TorznabCatType.MoviesForeign);
|
||||
AddCategoryMapping(17, TorznabCatType.MoviesDVD);
|
||||
AddCategoryMapping(9, TorznabCatType.MoviesHD);
|
||||
AddCategoryMapping(9, TorznabCatType.Movies);
|
||||
AddCategoryMapping(9, TorznabCatType.MoviesBluRay);
|
||||
AddCategoryMapping(43, TorznabCatType.TV);
|
||||
AddCategoryMapping(43, TorznabCatType.TVHD);
|
||||
AddCategoryMapping(43, TorznabCatType.TVWEBDL);
|
||||
}
|
||||
|
||||
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||
{
|
||||
var loginPage = await RequestStringWithCookies(LoginUrl);
|
||||
CQ loginDom = loginPage.Content;
|
||||
using CsQuery;
|
||||
using Jackett.Indexers;
|
||||
using Jackett.Models;
|
||||
using Jackett.Services;
|
||||
using Jackett.Utils;
|
||||
using Jackett.Utils.Clients;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Web.UI.WebControls;
|
||||
using Jackett.Models.IndexerConfig;
|
||||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class NxtGn : BaseIndexer, IIndexer
|
||||
{
|
||||
private string LoginUrl { get { return SiteLink + "login.php"; } }
|
||||
private string SearchUrl { get { return SiteLink + "browse.php"; } }
|
||||
private string ProfileUrl { get { return SiteLink + "my.php"; } }
|
||||
|
||||
new ConfigurationDataBasicLoginWithRSS configData
|
||||
{
|
||||
get { return (ConfigurationDataBasicLoginWithRSS)base.configData; }
|
||||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public NxtGn(IIndexerManagerService i, Logger l, IWebClient c, IProtectionService ps)
|
||||
: base(name: "NextGen",
|
||||
description: "A danish closed torrent tracker",
|
||||
link: "https://nxgn.org/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
client: c,
|
||||
logger: l,
|
||||
p: ps,
|
||||
configData: new ConfigurationDataBasicLoginWithRSS())
|
||||
{
|
||||
AddCategoryMapping(47, TorznabCatType.Movies3D);
|
||||
AddCategoryMapping(38, TorznabCatType.MoviesHD);
|
||||
AddCategoryMapping(38, TorznabCatType.MoviesWEBDL);
|
||||
AddCategoryMapping(38, TorznabCatType.MoviesBluRay);
|
||||
AddCategoryMapping(5, TorznabCatType.MoviesSD);
|
||||
AddCategoryMapping(23, TorznabCatType.MoviesForeign);
|
||||
AddCategoryMapping(22, TorznabCatType.MoviesSD);
|
||||
AddCategoryMapping(4, TorznabCatType.TVFOREIGN);
|
||||
AddCategoryMapping(4, TorznabCatType.TVSD);
|
||||
AddCategoryMapping(4, TorznabCatType.TVDocumentary);
|
||||
AddCategoryMapping(4, TorznabCatType.TVSport);
|
||||
AddCategoryMapping(4, TorznabCatType.TV);
|
||||
AddCategoryMapping(31, TorznabCatType.TVHD);
|
||||
AddCategoryMapping(21, TorznabCatType.TVFOREIGN);
|
||||
AddCategoryMapping(46, TorznabCatType.TV);
|
||||
AddCategoryMapping(46, TorznabCatType.TVHD);
|
||||
//AddCategoryMapping(45, TorznabCatType.TV);
|
||||
//AddCategoryMapping(45, TorznabCatType.TVSD);
|
||||
//AddCategoryMapping(24, TorznabCatType.TVFOREIGN);
|
||||
AddCategoryMapping(26, TorznabCatType.TV);
|
||||
AddCategoryMapping(26, TorznabCatType.TVHD);
|
||||
AddCategoryMapping(26, TorznabCatType.TVWEBDL);
|
||||
AddCategoryMapping(33, TorznabCatType.MoviesHD);
|
||||
AddCategoryMapping(33, TorznabCatType.Movies);
|
||||
AddCategoryMapping(17, TorznabCatType.MoviesForeign);
|
||||
AddCategoryMapping(17, TorznabCatType.MoviesDVD);
|
||||
AddCategoryMapping(9, TorznabCatType.MoviesHD);
|
||||
AddCategoryMapping(9, TorznabCatType.Movies);
|
||||
AddCategoryMapping(9, TorznabCatType.MoviesBluRay);
|
||||
AddCategoryMapping(43, TorznabCatType.TV);
|
||||
AddCategoryMapping(43, TorznabCatType.TVHD);
|
||||
AddCategoryMapping(43, TorznabCatType.TVWEBDL);
|
||||
}
|
||||
|
||||
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||
{
|
||||
var loginPage = await RequestStringWithCookies(LoginUrl);
|
||||
CQ loginDom = loginPage.Content;
|
||||
var loginPostUrl = loginDom["#login"].Attr("action");
|
||||
|
||||
configData.LoadValuesFromJson(configJson);
|
||||
var pairs = new Dictionary<string, string> {
|
||||
{ "username", configData.Username.Value },
|
||||
{ "password", configData.Password.Value }
|
||||
};
|
||||
// Get inital cookies
|
||||
CookieHeader = string.Empty;
|
||||
var response = await RequestLoginAndFollowRedirect(SiteLink + loginPostUrl, pairs, CookieHeader, true, null, LoginUrl);
|
||||
|
||||
await ConfigureIfOK(response.Cookies, response.Content != null && response.Content.Contains("Velkommen tilbage"), () =>
|
||||
{
|
||||
CQ dom = response.Content;
|
||||
var messageEl = dom["inputs"];
|
||||
var errorMessage = messageEl.Text().Trim();
|
||||
throw new ExceptionWithConfigData(errorMessage, configData);
|
||||
});
|
||||
|
||||
var profilePage = await RequestStringWithCookies(ProfileUrl, response.Cookies);
|
||||
CQ profileDom = profilePage.Content;
|
||||
var passKey = profileDom["input[name=resetkey]"].Parent().Text();
|
||||
passKey = passKey.Substring(0, passKey.IndexOf(' '));
|
||||
configData.RSSKey.Value = passKey;
|
||||
SaveConfig();
|
||||
return IndexerConfigurationStatus.RequiresTesting;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
|
||||
{
|
||||
var releases = new List<ReleaseInfo>();
|
||||
var breakWhile = false;
|
||||
var page = 0;
|
||||
while (page < 3)
|
||||
{
|
||||
string episodeSearchUrl;
|
||||
if (string.IsNullOrEmpty(query.GetQueryString()))
|
||||
{
|
||||
episodeSearchUrl = SearchUrl + "?page=" + page;
|
||||
breakWhile = true;
|
||||
configData.LoadValuesFromJson(configJson);
|
||||
var pairs = new Dictionary<string, string> {
|
||||
{ "username", configData.Username.Value },
|
||||
{ "password", configData.Password.Value }
|
||||
};
|
||||
// Get inital cookies
|
||||
CookieHeader = string.Empty;
|
||||
var response = await RequestLoginAndFollowRedirect(SiteLink + loginPostUrl, pairs, CookieHeader, true, null, LoginUrl);
|
||||
|
||||
await ConfigureIfOK(response.Cookies, response.Content != null && response.Content.Contains("Velkommen tilbage"), () =>
|
||||
{
|
||||
CQ dom = response.Content;
|
||||
var messageEl = dom["inputs"];
|
||||
var errorMessage = messageEl.Text().Trim();
|
||||
throw new ExceptionWithConfigData(errorMessage, configData);
|
||||
});
|
||||
|
||||
var profilePage = await RequestStringWithCookies(ProfileUrl, response.Cookies);
|
||||
CQ profileDom = profilePage.Content;
|
||||
var passKey = profileDom["input[name=resetkey]"].Parent().Text();
|
||||
passKey = passKey.Substring(0, passKey.IndexOf(' '));
|
||||
configData.RSSKey.Value = passKey;
|
||||
SaveConfig();
|
||||
return IndexerConfigurationStatus.RequiresTesting;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
|
||||
{
|
||||
var releases = new List<ReleaseInfo>();
|
||||
var breakWhile = false;
|
||||
var page = 0;
|
||||
while (page < 3)
|
||||
{
|
||||
string episodeSearchUrl;
|
||||
if (string.IsNullOrEmpty(query.GetQueryString()))
|
||||
{
|
||||
episodeSearchUrl = SearchUrl + "?page=" + page;
|
||||
breakWhile = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var cats = MapTorznabCapsToTrackers(query);
|
||||
var catsUrlPart = string.Join("&", cats.Select(c => $"c{c}=1"));
|
||||
episodeSearchUrl = string.Format("{0}?search={1}&cat=0&incldead=0&{2}&page={3}", SearchUrl, HttpUtility.UrlEncode(query.GetQueryString()), catsUrlPart, page);
|
||||
}
|
||||
page++;
|
||||
}
|
||||
page++;
|
||||
var results = await RequestStringWithCookiesAndRetry(episodeSearchUrl);
|
||||
try
|
||||
{
|
||||
@@ -145,16 +145,16 @@ namespace Jackett.Indexers
|
||||
var qLink = qRow.Find("#torrent-udgivelse2-users > a").First();
|
||||
var qDesc = qRow.Find("#torrent-udgivelse2-users > p").FirstOrDefault();
|
||||
|
||||
var moviesCats = new[] { 47, 38, 5, 23, 22, 33, 17, 9 };
|
||||
var seriesCats = new[] { 46, 26, 43 };
|
||||
var catUrl = qRow.Find(".torrent-icon > a").Attr("href");
|
||||
var cat = catUrl.Substring(catUrl.LastIndexOf('=') + 1);
|
||||
var catNo = int.Parse(cat);
|
||||
if (moviesCats.Contains(catNo))
|
||||
var moviesCats = new[] { 47, 38, 5, 23, 22, 33, 17, 9 };
|
||||
var seriesCats = new[] { 46, 26, 43 };
|
||||
var catUrl = qRow.Find(".torrent-icon > a").Attr("href");
|
||||
var cat = catUrl.Substring(catUrl.LastIndexOf('=') + 1);
|
||||
var catNo = int.Parse(cat);
|
||||
if (moviesCats.Contains(catNo))
|
||||
release.Category = TorznabCatType.Movies.ID;
|
||||
else if (seriesCats.Contains(catNo))
|
||||
release.Category = TorznabCatType.TV.ID;
|
||||
else
|
||||
else if (seriesCats.Contains(catNo))
|
||||
release.Category = TorznabCatType.TV.ID;
|
||||
else
|
||||
continue;
|
||||
|
||||
releases.Add(release);
|
||||
@@ -174,27 +174,27 @@ namespace Jackett.Indexers
|
||||
|
||||
var qAdded = qRow.Find("#torrent-added").First();
|
||||
var addedStr = qAdded.Text().Trim();
|
||||
release.PublishDate = DateTime.ParseExact(addedStr, "dd-MM-yyyyHH:mm:ss", CultureInfo.InvariantCulture);
|
||||
|
||||
release.Seeders = ParseUtil.CoerceInt(qRow.Find("#torrent-seeders").Text().Trim());
|
||||
release.PublishDate = DateTime.ParseExact(addedStr, "dd-MM-yyyyHH:mm:ss", CultureInfo.InvariantCulture);
|
||||
|
||||
release.Seeders = ParseUtil.CoerceInt(qRow.Find("#torrent-seeders").Text().Trim());
|
||||
release.Peers = ParseUtil.CoerceInt(qRow.Find("#torrent-leechers").Text().Trim()) + release.Seeders;
|
||||
|
||||
var sizeStr = qRow.Find("#torrent-size").First().Text();
|
||||
release.Size = ReleaseInfo.GetBytes(sizeStr);
|
||||
|
||||
var infoLink = qRow.Find("#infolink");
|
||||
var linkContainer = infoLink.Children().First().Children().First();
|
||||
var url = linkContainer.Attr("href");
|
||||
var img = linkContainer.Children().First();
|
||||
var imgUrl = img.Attr("src");
|
||||
if (imgUrl == "/pic/imdb.png")
|
||||
var sizeStr = qRow.Find("#torrent-size").First().Text();
|
||||
release.Size = ReleaseInfo.GetBytes(sizeStr);
|
||||
|
||||
var infoLink = qRow.Find("#infolink");
|
||||
var linkContainer = infoLink.Children().First().Children().First();
|
||||
var url = linkContainer.Attr("href");
|
||||
var img = linkContainer.Children().First();
|
||||
var imgUrl = img.Attr("src");
|
||||
if (imgUrl == "/pic/imdb.png")
|
||||
{
|
||||
release.Imdb = long.Parse(url.Substring(url.LastIndexOf('t') + 1));
|
||||
}
|
||||
else if (imgUrl == "/pic/TV.png")
|
||||
{
|
||||
release.TheTvDbId = long.Parse(url.Substring(url.LastIndexOf('=') + 1));
|
||||
}
|
||||
release.Imdb = long.Parse(url.Substring(url.LastIndexOf('t') + 1));
|
||||
}
|
||||
else if (imgUrl == "/pic/TV.png")
|
||||
{
|
||||
release.TheTvDbId = long.Parse(url.Substring(url.LastIndexOf('=') + 1));
|
||||
}
|
||||
}
|
||||
var nextPage = dom["#torrent-table-wrapper + p[align=center]"].Children().Last();
|
||||
if (!nextPage.Is("a"))
|
||||
@@ -203,11 +203,11 @@ namespace Jackett.Indexers
|
||||
catch (Exception ex)
|
||||
{
|
||||
OnParseError(results.Content, ex);
|
||||
}
|
||||
if (breakWhile)
|
||||
break;
|
||||
}
|
||||
return releases;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (breakWhile)
|
||||
break;
|
||||
}
|
||||
return releases;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,132 +1,132 @@
|
||||
using Jackett.Models;
|
||||
using Jackett.Services;
|
||||
using Jackett.Utils;
|
||||
using Jackett.Utils.Clients;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Xml;
|
||||
using Jackett.Models.IndexerConfig;
|
||||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class ShowRSS : BaseIndexer, IIndexer
|
||||
{
|
||||
readonly static string defaultSiteLink = "http://showrss.info/";
|
||||
|
||||
private Uri BaseUri
|
||||
{
|
||||
get { return new Uri(configData.Url.Value); }
|
||||
set { configData.Url.Value = value.ToString(); }
|
||||
}
|
||||
|
||||
private string SearchAllUrl { get { return BaseUri + "feeds/all.rss"; } }
|
||||
|
||||
new ConfigurationDataUrl configData
|
||||
{
|
||||
get { return (ConfigurationDataUrl)base.configData; }
|
||||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public ShowRSS(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
|
||||
: base(name: "ShowRSS",
|
||||
description: "showRSS is a service that allows you to keep track of your favorite TV shows",
|
||||
link: defaultSiteLink,
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
configData: new ConfigurationDataUrl(defaultSiteLink))
|
||||
{
|
||||
}
|
||||
|
||||
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||
{
|
||||
configData.LoadValuesFromJson(configJson);
|
||||
var releases = await PerformQuery(new TorznabQuery());
|
||||
|
||||
await ConfigureIfOK(string.Empty, releases.Count() > 0, () =>
|
||||
{
|
||||
throw new Exception("Could not find releases from this URL");
|
||||
});
|
||||
|
||||
return IndexerConfigurationStatus.RequiresTesting;
|
||||
}
|
||||
|
||||
// Override to load legacy config format
|
||||
public override void LoadFromSavedConfiguration(JToken jsonConfig)
|
||||
{
|
||||
if (jsonConfig is JObject)
|
||||
{
|
||||
BaseUri = new Uri(jsonConfig.Value<string>("base_url"));
|
||||
SaveConfig();
|
||||
IsConfigured = true;
|
||||
return;
|
||||
}
|
||||
|
||||
base.LoadFromSavedConfiguration(jsonConfig);
|
||||
}
|
||||
|
||||
public override Task<byte[]> Download(Uri link)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
|
||||
{
|
||||
var releases = new List<ReleaseInfo>();
|
||||
var episodeSearchUrl = string.Format(SearchAllUrl);
|
||||
var result = await RequestStringWithCookiesAndRetry(episodeSearchUrl, string.Empty);
|
||||
var xmlDoc = new XmlDocument();
|
||||
|
||||
try
|
||||
{
|
||||
xmlDoc.LoadXml(result.Content);
|
||||
ReleaseInfo release;
|
||||
string serie_title;
|
||||
|
||||
foreach (XmlNode node in xmlDoc.GetElementsByTagName("item"))
|
||||
{
|
||||
release = new ReleaseInfo();
|
||||
|
||||
release.MinimumRatio = 1;
|
||||
release.MinimumSeedTime = 172800;
|
||||
|
||||
serie_title = node.SelectSingleNode("title").InnerText;
|
||||
release.Title = serie_title;
|
||||
|
||||
release.Comments = new Uri(node.SelectSingleNode("link").InnerText);
|
||||
int category = 0;
|
||||
int.TryParse(node.SelectSingleNode("title").InnerText, out category);
|
||||
release.Category = category;
|
||||
var test = node.SelectSingleNode("enclosure");
|
||||
release.Guid = new Uri(test.Attributes["url"].Value);
|
||||
release.PublishDate = DateTime.Parse(node.SelectSingleNode("pubDate").InnerText, CultureInfo.InvariantCulture);
|
||||
|
||||
release.Description = node.SelectSingleNode("description").InnerText;
|
||||
release.InfoHash = node.SelectSingleNode("description").InnerText;
|
||||
release.Size = 0;
|
||||
release.Seeders = 1;
|
||||
release.Peers = 1;
|
||||
release.MagnetUri = new Uri(node.SelectSingleNode("link").InnerText);
|
||||
releases.Add(release);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
OnParseError(result.Content, ex);
|
||||
}
|
||||
|
||||
return releases;
|
||||
}
|
||||
}
|
||||
}
|
||||
using Jackett.Models;
|
||||
using Jackett.Services;
|
||||
using Jackett.Utils;
|
||||
using Jackett.Utils.Clients;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using System.Xml;
|
||||
using Jackett.Models.IndexerConfig;
|
||||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class ShowRSS : BaseIndexer, IIndexer
|
||||
{
|
||||
readonly static string defaultSiteLink = "http://showrss.info/";
|
||||
|
||||
private Uri BaseUri
|
||||
{
|
||||
get { return new Uri(configData.Url.Value); }
|
||||
set { configData.Url.Value = value.ToString(); }
|
||||
}
|
||||
|
||||
private string SearchAllUrl { get { return BaseUri + "feeds/all.rss"; } }
|
||||
|
||||
new ConfigurationDataUrl configData
|
||||
{
|
||||
get { return (ConfigurationDataUrl)base.configData; }
|
||||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public ShowRSS(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
|
||||
: base(name: "ShowRSS",
|
||||
description: "showRSS is a service that allows you to keep track of your favorite TV shows",
|
||||
link: defaultSiteLink,
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
configData: new ConfigurationDataUrl(defaultSiteLink))
|
||||
{
|
||||
}
|
||||
|
||||
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||
{
|
||||
configData.LoadValuesFromJson(configJson);
|
||||
var releases = await PerformQuery(new TorznabQuery());
|
||||
|
||||
await ConfigureIfOK(string.Empty, releases.Count() > 0, () =>
|
||||
{
|
||||
throw new Exception("Could not find releases from this URL");
|
||||
});
|
||||
|
||||
return IndexerConfigurationStatus.RequiresTesting;
|
||||
}
|
||||
|
||||
// Override to load legacy config format
|
||||
public override void LoadFromSavedConfiguration(JToken jsonConfig)
|
||||
{
|
||||
if (jsonConfig is JObject)
|
||||
{
|
||||
BaseUri = new Uri(jsonConfig.Value<string>("base_url"));
|
||||
SaveConfig();
|
||||
IsConfigured = true;
|
||||
return;
|
||||
}
|
||||
|
||||
base.LoadFromSavedConfiguration(jsonConfig);
|
||||
}
|
||||
|
||||
public override Task<byte[]> Download(Uri link)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
|
||||
{
|
||||
var releases = new List<ReleaseInfo>();
|
||||
var episodeSearchUrl = string.Format(SearchAllUrl);
|
||||
var result = await RequestStringWithCookiesAndRetry(episodeSearchUrl, string.Empty);
|
||||
var xmlDoc = new XmlDocument();
|
||||
|
||||
try
|
||||
{
|
||||
xmlDoc.LoadXml(result.Content);
|
||||
ReleaseInfo release;
|
||||
string serie_title;
|
||||
|
||||
foreach (XmlNode node in xmlDoc.GetElementsByTagName("item"))
|
||||
{
|
||||
release = new ReleaseInfo();
|
||||
|
||||
release.MinimumRatio = 1;
|
||||
release.MinimumSeedTime = 172800;
|
||||
|
||||
serie_title = node.SelectSingleNode(".//*[local-name()='rawtitle']").InnerText;
|
||||
release.Title = serie_title;
|
||||
|
||||
release.Comments = new Uri(node.SelectSingleNode("link").InnerText);
|
||||
int category = 0;
|
||||
int.TryParse(node.SelectSingleNode("title").InnerText, out category);
|
||||
release.Category = category;
|
||||
var test = node.SelectSingleNode("enclosure");
|
||||
release.Guid = new Uri(test.Attributes["url"].Value);
|
||||
release.PublishDate = DateTime.Parse(node.SelectSingleNode("pubDate").InnerText, CultureInfo.InvariantCulture);
|
||||
|
||||
release.Description = node.SelectSingleNode("description").InnerText;
|
||||
release.InfoHash = node.SelectSingleNode("description").InnerText;
|
||||
release.Size = 0;
|
||||
release.Seeders = 1;
|
||||
release.Peers = 1;
|
||||
release.MagnetUri = new Uri(node.SelectSingleNode("link").InnerText);
|
||||
releases.Add(release);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
OnParseError(result.Content, ex);
|
||||
}
|
||||
|
||||
return releases;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,183 +1,249 @@
|
||||
using Jackett.Models;
|
||||
using Jackett.Services;
|
||||
using Jackett.Utils;
|
||||
using Jackett.Utils.Clients;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using Jackett.Models.IndexerConfig;
|
||||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class T411 : BaseIndexer, IIndexer
|
||||
{
|
||||
private readonly string CommentsUrl = "";
|
||||
const string ApiUrl = "http://api.t411.io";
|
||||
const string AuthUrl = ApiUrl + "/auth";
|
||||
const string SearchUrl = ApiUrl + "/torrents/search/{0}";
|
||||
const string DownloadUrl = ApiUrl + "/torrents/download/{0}";
|
||||
|
||||
HttpClientHandler handler;
|
||||
HttpClient client;
|
||||
|
||||
new ConfigurationDataLoginTokin configData
|
||||
{
|
||||
get { return (ConfigurationDataLoginTokin)base.configData; }
|
||||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public T411(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
|
||||
: base(name: "T411",
|
||||
description: "French Torrent Tracker",
|
||||
link: "http://www.t411.io/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
configData: new ConfigurationDataLoginTokin())
|
||||
{
|
||||
CommentsUrl = SiteLink + "/torrents/{0}";
|
||||
IsConfigured = false;
|
||||
handler = new HttpClientHandler
|
||||
{
|
||||
AllowAutoRedirect = true
|
||||
};
|
||||
client = new HttpClient(handler);
|
||||
}
|
||||
|
||||
async Task<string> GetAuthToken(bool forceFetch = false)
|
||||
{
|
||||
if (!forceFetch && configData.LastTokenFetchDateTime > DateTime.Now - TimeSpan.FromHours(48))
|
||||
{
|
||||
return configData.ApiToken.Value;
|
||||
}
|
||||
|
||||
var pairs = new Dictionary<string, string> {
|
||||
{ "username", configData.Username.Value },
|
||||
{ "password", configData.Password.Value }
|
||||
};
|
||||
|
||||
var content = new FormUrlEncodedContent(pairs);
|
||||
|
||||
var response = await client.PostAsync(AuthUrl, content);
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
var jsonResponse = JObject.Parse(responseContent);
|
||||
if (jsonResponse["error"] != null)
|
||||
{
|
||||
throw new ApplicationException((string)jsonResponse["error"]);
|
||||
}
|
||||
configData.ApiToken.Value = (string)jsonResponse["token"];
|
||||
configData.LastTokenFetchDateTime = DateTime.Now;
|
||||
return configData.ApiToken.Value;
|
||||
}
|
||||
|
||||
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||
{
|
||||
configData.LoadValuesFromJson(configJson);
|
||||
|
||||
Exception tokenFetchEx = null;
|
||||
try
|
||||
{
|
||||
await GetAuthToken(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
tokenFetchEx = new ExceptionWithConfigData(ex.Message, configData);
|
||||
}
|
||||
|
||||
await ConfigureIfOK(string.Empty, tokenFetchEx == null, () =>
|
||||
{
|
||||
throw tokenFetchEx;
|
||||
});
|
||||
|
||||
return IndexerConfigurationStatus.RequiresTesting;
|
||||
}
|
||||
|
||||
// Override to load legacy config format
|
||||
public override void LoadFromSavedConfiguration(JToken jsonConfig)
|
||||
{
|
||||
if (jsonConfig is JObject)
|
||||
{
|
||||
configData.ApiToken.Value = jsonConfig.Value<string>("token"); ;
|
||||
configData.Username.Value = jsonConfig.Value<string>("username");
|
||||
configData.Password.Value = jsonConfig.Value<string>("password");
|
||||
SaveConfig();
|
||||
IsConfigured = true;
|
||||
return;
|
||||
}
|
||||
|
||||
base.LoadFromSavedConfiguration(jsonConfig);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
|
||||
{
|
||||
var releases = new List<ReleaseInfo>();
|
||||
var searchTerm = string.IsNullOrEmpty(query.SanitizedSearchTerm) ? "%20" : query.SanitizedSearchTerm;
|
||||
var searchString = searchTerm + " " + query.GetEpisodeSearchString();
|
||||
var episodeSearchUrl = string.Format(SearchUrl, HttpUtility.UrlEncode(searchString));
|
||||
|
||||
var message = new HttpRequestMessage();
|
||||
message.Method = HttpMethod.Get;
|
||||
message.RequestUri = new Uri(episodeSearchUrl);
|
||||
message.Headers.TryAddWithoutValidation("Authorization", await GetAuthToken());
|
||||
|
||||
var response = await client.SendAsync(message);
|
||||
var results = await response.Content.ReadAsStringAsync();
|
||||
|
||||
var jsonResult = JObject.Parse(results);
|
||||
try
|
||||
{
|
||||
var items = (JArray)jsonResult["torrents"];
|
||||
foreach (var item in items)
|
||||
{
|
||||
var release = new ReleaseInfo();
|
||||
|
||||
release.MinimumRatio = 1;
|
||||
release.MinimumSeedTime = 172800;
|
||||
var torrentId = (string)item["id"];
|
||||
release.Link = new Uri(string.Format(DownloadUrl, torrentId));
|
||||
release.Title = (string)item["name"];
|
||||
release.Description = release.Title;
|
||||
release.Comments = new Uri(string.Format(CommentsUrl, (string)item["rewritename"]));
|
||||
release.Guid = release.Comments;
|
||||
|
||||
var dateUtc = DateTime.ParseExact((string)item["added"], "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
|
||||
release.PublishDate = DateTime.SpecifyKind(dateUtc, DateTimeKind.Utc).ToLocalTime();
|
||||
|
||||
release.Seeders = ParseUtil.CoerceInt((string)item["seeders"]);
|
||||
release.Peers = ParseUtil.CoerceInt((string)item["leechers"]) + release.Seeders;
|
||||
|
||||
release.Size = ParseUtil.CoerceLong((string)item["size"]);
|
||||
|
||||
releases.Add(release);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
OnParseError(results, ex);
|
||||
}
|
||||
return releases;
|
||||
}
|
||||
|
||||
public override async Task<byte[]> Download(Uri link)
|
||||
{
|
||||
var message = new HttpRequestMessage();
|
||||
message.Method = HttpMethod.Get;
|
||||
message.RequestUri = link;
|
||||
message.Headers.TryAddWithoutValidation("Authorization", await GetAuthToken());
|
||||
|
||||
var response = await client.SendAsync(message);
|
||||
return await response.Content.ReadAsByteArrayAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
using Jackett.Models;
|
||||
using Jackett.Services;
|
||||
using Jackett.Utils;
|
||||
using Jackett.Utils.Clients;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using Jackett.Models.IndexerConfig;
|
||||
|
||||
namespace Jackett.Indexers
|
||||
{
|
||||
public class T411 : BaseIndexer, IIndexer
|
||||
{
|
||||
private readonly string CommentsUrl = "";
|
||||
const string ApiUrl = "http://api.t411.io";
|
||||
const string AuthUrl = ApiUrl + "/auth";
|
||||
const string SearchUrl = ApiUrl + "/torrents/search/{0}";
|
||||
const string DownloadUrl = ApiUrl + "/torrents/download/{0}";
|
||||
|
||||
HttpClientHandler handler;
|
||||
HttpClient client;
|
||||
|
||||
new ConfigurationDataLoginTokin configData
|
||||
{
|
||||
get { return (ConfigurationDataLoginTokin)base.configData; }
|
||||
set { base.configData = value; }
|
||||
}
|
||||
|
||||
public T411(IIndexerManagerService i, Logger l, IWebClient wc, IProtectionService ps)
|
||||
: base(name: "T411",
|
||||
description: "French Torrent Tracker",
|
||||
link: "http://www.t411.io/",
|
||||
caps: TorznabUtil.CreateDefaultTorznabTVCaps(),
|
||||
manager: i,
|
||||
client: wc,
|
||||
logger: l,
|
||||
p: ps,
|
||||
configData: new ConfigurationDataLoginTokin())
|
||||
{
|
||||
CommentsUrl = SiteLink + "/torrents/{0}";
|
||||
IsConfigured = false;
|
||||
handler = new HttpClientHandler
|
||||
{
|
||||
AllowAutoRedirect = true
|
||||
};
|
||||
client = new HttpClient(handler);
|
||||
|
||||
|
||||
|
||||
AddCategoryMapping("Film\\/Vidéo", TorznabCatType.Movies);
|
||||
AddCategoryMapping("Vidéo-clips", TorznabCatType.Other);
|
||||
AddCategoryMapping("Série TV", TorznabCatType.TV);
|
||||
AddCategoryMapping("Animation", TorznabCatType.TVAnime);
|
||||
AddCategoryMapping("Film", TorznabCatType.Movies);
|
||||
AddCategoryMapping("Concert", TorznabCatType.AudioVideo);
|
||||
AddCategoryMapping("Documentaire", TorznabCatType.Audio);
|
||||
AddCategoryMapping("Spectacle", TorznabCatType.TV);
|
||||
AddCategoryMapping("Sport", TorznabCatType.TVSport);
|
||||
AddCategoryMapping("Animation Série", TorznabCatType.TVAnime);
|
||||
AddCategoryMapping("Emission TV", TorznabCatType.TV);
|
||||
|
||||
|
||||
AddCategoryMapping("Application", TorznabCatType.PC0day);
|
||||
AddCategoryMapping("Linux", TorznabCatType.PC);
|
||||
AddCategoryMapping("MacOS", TorznabCatType.PCMac);
|
||||
AddCategoryMapping("Windows", TorznabCatType.PC);
|
||||
AddCategoryMapping("Smartphone", TorznabCatType.PCPhoneOther);
|
||||
AddCategoryMapping("Tablette", TorznabCatType.PCPhoneOther);
|
||||
AddCategoryMapping("Autre", TorznabCatType.PC);
|
||||
AddCategoryMapping("Formation", TorznabCatType.PC);
|
||||
|
||||
AddCategoryMapping("Emulation", TorznabCatType.PC);
|
||||
AddCategoryMapping("Emulateurs", TorznabCatType.PC);
|
||||
AddCategoryMapping("Roms", TorznabCatType.PC);
|
||||
|
||||
AddCategoryMapping("GPS", TorznabCatType.Other);
|
||||
AddCategoryMapping("Applications", TorznabCatType.Other);
|
||||
AddCategoryMapping("Cartes", TorznabCatType.Other);
|
||||
AddCategoryMapping("Divers", TorznabCatType.Other);
|
||||
|
||||
AddCategoryMapping("Audio", TorznabCatType.Audio);
|
||||
AddCategoryMapping("Karaoke", TorznabCatType.Audio);
|
||||
AddCategoryMapping("Samples", TorznabCatType.Audio);
|
||||
AddCategoryMapping("Musique", TorznabCatType.Audio);
|
||||
AddCategoryMapping("Podcast Radio", TorznabCatType.Audio);
|
||||
|
||||
AddCategoryMapping("eBook", TorznabCatType.BooksEbook);
|
||||
AddCategoryMapping("Audio", TorznabCatType.AudioAudiobook);
|
||||
AddCategoryMapping("Bds", TorznabCatType.AudioVideo);
|
||||
AddCategoryMapping("Comics", TorznabCatType.BooksComics);
|
||||
AddCategoryMapping("Livres", TorznabCatType.Books);
|
||||
AddCategoryMapping("Mangas", TorznabCatType.BooksForeign);
|
||||
AddCategoryMapping("Presse", TorznabCatType.BooksMagazines);
|
||||
|
||||
AddCategoryMapping("xXx", TorznabCatType.XXX);
|
||||
AddCategoryMapping("eBooks", TorznabCatType.XXXImageset);
|
||||
AddCategoryMapping("Jeux vidéo", TorznabCatType.XXX);
|
||||
AddCategoryMapping("Video", TorznabCatType.XXXDVD);
|
||||
//AddCategoryMapping("Animation", TorznabCatType.XXX); Used above :/
|
||||
|
||||
AddCategoryMapping("Jeu vidéo", TorznabCatType.PCGames);
|
||||
AddCategoryMapping("Linux", TorznabCatType.PCGames);
|
||||
AddCategoryMapping("MacOS", TorznabCatType.PCGames);
|
||||
// AddCategoryMapping("Windows", TorznabCatType.PCGames); Used above :/
|
||||
AddCategoryMapping("Nintendo", TorznabCatType.Console);
|
||||
AddCategoryMapping("Sony", TorznabCatType.Console);
|
||||
AddCategoryMapping("Microsoft", TorznabCatType.PCGames);
|
||||
AddCategoryMapping("Smartphone", TorznabCatType.PCPhoneOther);
|
||||
AddCategoryMapping("Tablette", TorznabCatType.PCPhoneOther);
|
||||
AddCategoryMapping("Autre", TorznabCatType.Other);
|
||||
|
||||
AddCategoryMapping("Jeux vidéo", TorznabCatType.Other);
|
||||
}
|
||||
|
||||
async Task<string> GetAuthToken(bool forceFetch = false)
|
||||
{
|
||||
if (!forceFetch && configData.LastTokenFetchDateTime > DateTime.Now - TimeSpan.FromHours(48))
|
||||
{
|
||||
return configData.ApiToken.Value;
|
||||
}
|
||||
|
||||
var pairs = new Dictionary<string, string> {
|
||||
{ "username", configData.Username.Value },
|
||||
{ "password", configData.Password.Value }
|
||||
};
|
||||
|
||||
var content = new FormUrlEncodedContent(pairs);
|
||||
|
||||
var response = await client.PostAsync(AuthUrl, content);
|
||||
var responseContent = await response.Content.ReadAsStringAsync();
|
||||
var jsonResponse = JObject.Parse(responseContent);
|
||||
if (jsonResponse["error"] != null)
|
||||
{
|
||||
throw new ApplicationException((string)jsonResponse["error"]);
|
||||
}
|
||||
configData.ApiToken.Value = (string)jsonResponse["token"];
|
||||
configData.LastTokenFetchDateTime = DateTime.Now;
|
||||
return configData.ApiToken.Value;
|
||||
}
|
||||
|
||||
public async Task<IndexerConfigurationStatus> ApplyConfiguration(JToken configJson)
|
||||
{
|
||||
configData.LoadValuesFromJson(configJson);
|
||||
|
||||
Exception tokenFetchEx = null;
|
||||
try
|
||||
{
|
||||
await GetAuthToken(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
tokenFetchEx = new ExceptionWithConfigData(ex.Message, configData);
|
||||
}
|
||||
|
||||
await ConfigureIfOK(string.Empty, tokenFetchEx == null, () =>
|
||||
{
|
||||
throw tokenFetchEx;
|
||||
});
|
||||
|
||||
return IndexerConfigurationStatus.RequiresTesting;
|
||||
}
|
||||
|
||||
// Override to load legacy config format
|
||||
public override void LoadFromSavedConfiguration(JToken jsonConfig)
|
||||
{
|
||||
if (jsonConfig is JObject)
|
||||
{
|
||||
configData.ApiToken.Value = jsonConfig.Value<string>("token"); ;
|
||||
configData.Username.Value = jsonConfig.Value<string>("username");
|
||||
configData.Password.Value = jsonConfig.Value<string>("password");
|
||||
SaveConfig();
|
||||
IsConfigured = true;
|
||||
return;
|
||||
}
|
||||
|
||||
base.LoadFromSavedConfiguration(jsonConfig);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<ReleaseInfo>> PerformQuery(TorznabQuery query)
|
||||
{
|
||||
var releases = new List<ReleaseInfo>();
|
||||
var searchTerm = string.IsNullOrEmpty(query.SanitizedSearchTerm) ? "%20" : query.SanitizedSearchTerm;
|
||||
var searchString = searchTerm + " " + query.GetEpisodeSearchString();
|
||||
var episodeSearchUrl = string.Format(SearchUrl, HttpUtility.UrlEncode(searchString));
|
||||
|
||||
var message = new HttpRequestMessage();
|
||||
message.Method = HttpMethod.Get;
|
||||
message.RequestUri = new Uri(episodeSearchUrl);
|
||||
message.Headers.TryAddWithoutValidation("Authorization", await GetAuthToken());
|
||||
|
||||
var response = await client.SendAsync(message);
|
||||
var results = await response.Content.ReadAsStringAsync();
|
||||
|
||||
var jsonResult = JObject.Parse(results);
|
||||
try
|
||||
{
|
||||
var items = (JArray)jsonResult["torrents"];
|
||||
foreach (var item in items)
|
||||
{
|
||||
var release = new ReleaseInfo();
|
||||
|
||||
release.MinimumRatio = 1;
|
||||
release.MinimumSeedTime = 172800;
|
||||
var torrentId = (string)item["id"];
|
||||
release.Link = new Uri(string.Format(DownloadUrl, torrentId));
|
||||
release.Title = (string)item["name"];
|
||||
release.Description = release.Title;
|
||||
release.Comments = new Uri(string.Format(CommentsUrl, (string)item["rewritename"]));
|
||||
release.Guid = release.Comments;
|
||||
|
||||
var dateUtc = DateTime.ParseExact((string)item["added"], "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
|
||||
release.PublishDate = DateTime.SpecifyKind(dateUtc, DateTimeKind.Utc).ToLocalTime();
|
||||
|
||||
release.Seeders = ParseUtil.CoerceInt((string)item["seeders"]);
|
||||
release.Peers = ParseUtil.CoerceInt((string)item["leechers"]) + release.Seeders;
|
||||
release.Size = ParseUtil.CoerceLong((string)item["size"]);
|
||||
release.Category = MapTrackerCatToNewznab((string)item["categoryname"]);
|
||||
|
||||
releases.Add(release);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
OnParseError(results, ex);
|
||||
}
|
||||
return releases;
|
||||
}
|
||||
|
||||
public override async Task<byte[]> Download(Uri link)
|
||||
{
|
||||
var message = new HttpRequestMessage();
|
||||
message.Method = HttpMethod.Get;
|
||||
message.RequestUri = link;
|
||||
message.Headers.TryAddWithoutValidation("Authorization", await GetAuthToken());
|
||||
|
||||
var response = await client.SendAsync(message);
|
||||
return await response.Content.ReadAsByteArrayAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -368,6 +368,7 @@
|
||||
<Content Include="Content\custom.js">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Content\libs\filesize.min.js" />
|
||||
<Content Include="Content\fonts\fontawesome-webfont.svg">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("0.6.4.0")]
|
||||
[assembly: AssemblyFileVersion("0.6.4.0")]
|
||||
[assembly: AssemblyVersion("0.6.5.0")]
|
||||
[assembly: AssemblyFileVersion("0.6.5.0")]
|
||||
|
Reference in New Issue
Block a user