Compare commits

..

13 Commits

Author SHA1 Message Date
kaso17
7b8f6ccd7f add ETTV 2017-11-09 13:28:44 +01:00
kaso17
a6b5401c0b add support for magnet file download links 2017-11-09 13:28:15 +01:00
kaso17
6d53e486c5 fix Content/Definition folder usage in Debug mode 2017-11-09 12:32:36 +01:00
kaso17
aa35280ca9 Shareisland: force HTTPS 2017-11-09 11:38:42 +01:00
kaso17
b5d846442d Fix tracing/logging options 2017-11-09 11:22:48 +01:00
kaso17
b040187c3f fix null pointer exception 2017-11-08 17:48:27 +01:00
kaso17
804dc12a47 BJShare: fix seeders/leechers 2017-11-08 17:33:40 +01:00
kaso17
5095c543d0 The Horror Charnel: improve rows selector 2017-11-08 16:41:50 +01:00
kaso17
3ae850e69b Cardigann: fix null pointer exception in if template 2017-11-08 16:18:28 +01:00
kaso17
4cd01433b7 fix null pointer 2017-11-08 16:06:13 +01:00
kaso17
06c47ec10a fix null pointer exception during startup 2017-11-08 16:03:38 +01:00
Nathan Holland
e90bf47d8a Move service config service back into shared .NET Framework Library (#2095) 2017-11-08 15:48:47 +01:00
Nathan Holland
52c0179e8e Feature/autofac tidyup (#2096)
* Move service config service back into shared .NET Framework Library

* Move Content files into shared folder. Make autoface load different assembilies depending on what framework is using it.

* Change my mind on what the shared module should be called. Common Module is too bland.

* DotNet4.SocksProxy is not yet publically .NET Standard. Revert to previous SocksWebProxy package.

* Check in unstaged change to test dependency injection setup.
2017-11-08 15:45:21 +01:00
89 changed files with 898 additions and 600 deletions

View File

@@ -29,6 +29,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* BTDB
* BT-Scene
* cpasbien
* ETTV
* EZTV
* Frozen Layer
* GkTorrent

View File

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.5 KiB

View File

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

View File

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 60 KiB

View File

@@ -1,275 +1,275 @@
body {
background-image: url("binding_dark.png");
background-repeat: repeat;
}
#page {
border-radius: 6px;
background-color: white;
max-width: 900px;
margin: 0 auto;
margin-top: 30px;
padding: 20px;
margin-bottom: 100px;
}
.container-fluid {
}
#templates {
display: none;
}
#indexers {
text-align: center;
margin-top: 30px;
}
.indexer-table {
text-align: left;
}
.test-success {
color: #449d44;
}
.test-error {
color: #c9302c;
}
.test-inprogress {
color: #286090;
}
.indexer-buttons {
text-align: center;
}
.indexer-buttons > .btn {
margin-bottom: 2px;
}
.indexer-button-test {
width: 60px;
}
.setup-item-inputstring {
max-width: 255px;
}
.setup-item-inputbool input {
max-width: 100px;
height: 20px;
}
.setup-item-inputselect {
max-width: 255px;
}
[data-type=hiddendata]{
display: none;
}
.spinner {
-webkit-animation: spin 2s infinite linear;
-moz-animation: spin 2s infinite linear;
-o-animation: spin 2s infinite linear;
animation: spin 2s infinite linear;
}
@-moz-keyframes spin {
from {
-moz-transform: rotate(0deg);
}
to {
-moz-transform: rotate(360deg);
}
}
@-webkit-keyframes spin {
from {
-webkit-transform: rotate(0deg);
}
to {
-webkit-transform: rotate(360deg);
}
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
#setup-indexer-go {
width: 70px;
}
hr {
border-top-color: #cdcdcd;
}
.input-area {
margin: 4px 0px;
}
.input-area > * {
vertical-align: middle;
}
.input-area > p {
margin-top: 10px;
}
.input-header {
font-size: 18px;
width: 160px;
display: inline-block;
}
.input-right {
width: 300px;
display: inline-block;
font-family: monospace;
}
#sonarr-warning {
display: none;
}
#logo {
max-width: 50px;
}
#header-title {
font-size: 34px;
vertical-align: middle;
padding-left: 15px;
}
#footer {
color: #444444;
margin: 0 auto;
margin-top: 10px;
text-align: center;
}
#jackett-allowext, #jackett-allowupdate, #jackett-logging, #jackett-prerelease {
width: 25px;
}
.modal-fillwidth {
width: 1200px;
min-width:80%;
}
.indexer-caps {
padding: 0px 15px 15px 15px;
border-top: 1px solid #e5e5e5;
}
.indexer-caps table {
border-bottom: 1px solid #ddd;
}
.jackettlogWarn {
background-color: #FFFF8E !important;
}
.jackettlogError {
background-color: #FF6060 !important;
}
.jackettdownloaded {
color: blueviolet;
}
.jacketdownloadlocal {
padding-left: 10px;
}
.downloadcolumn {
text-align:center;
}
pre {
display: block;
padding: 3px;
margin: 0 0 0px;
font-size: 13px;
line-height: 1.42857143;
color: #333;
word-break: break-all;
word-wrap: break-word;
background-color: transparent;
border: 0px;
border-radius: 0px;
}
.modal-open .modal {
overflow-x: auto; /* Model can be bigger than the screen on mobiles */
}
.dataTables_filter input {
width: 400px
}
#unconfigured-indexers-template {
display: none;
}
.jackett-apikey{
margin-top: 10px;
}
.jackett-apikey .input-header{
width: 80px;
}
.setup-item-displayinfo:empty {
display: none;
}
table td.fit{
white-space: nowrap;
width: 1%;
}
.label-imdb {
background-color: #d0ab44;
}
.tooltip-inner {
max-width: 500px !important;
}
.tooltip-inner img {
max-width: 250px;
height: auto;
}
.type-public {
color: #449d44
}
.type-private {
color: #c9302c
}
.type-semi-private {
color: #ec971f
}
.dataTables_deadfilter {
float: right;
text-align: right;
margin-right: 1em;
}
input#searchquery{
width:400px;
}
body {
background-image: url("binding_dark.png");
background-repeat: repeat;
}
#page {
border-radius: 6px;
background-color: white;
max-width: 900px;
margin: 0 auto;
margin-top: 30px;
padding: 20px;
margin-bottom: 100px;
}
.container-fluid {
}
#templates {
display: none;
}
#indexers {
text-align: center;
margin-top: 30px;
}
.indexer-table {
text-align: left;
}
.test-success {
color: #449d44;
}
.test-error {
color: #c9302c;
}
.test-inprogress {
color: #286090;
}
.indexer-buttons {
text-align: center;
}
.indexer-buttons > .btn {
margin-bottom: 2px;
}
.indexer-button-test {
width: 60px;
}
.setup-item-inputstring {
max-width: 255px;
}
.setup-item-inputbool input {
max-width: 100px;
height: 20px;
}
.setup-item-inputselect {
max-width: 255px;
}
[data-type=hiddendata]{
display: none;
}
.spinner {
-webkit-animation: spin 2s infinite linear;
-moz-animation: spin 2s infinite linear;
-o-animation: spin 2s infinite linear;
animation: spin 2s infinite linear;
}
@-moz-keyframes spin {
from {
-moz-transform: rotate(0deg);
}
to {
-moz-transform: rotate(360deg);
}
}
@-webkit-keyframes spin {
from {
-webkit-transform: rotate(0deg);
}
to {
-webkit-transform: rotate(360deg);
}
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
#setup-indexer-go {
width: 70px;
}
hr {
border-top-color: #cdcdcd;
}
.input-area {
margin: 4px 0px;
}
.input-area > * {
vertical-align: middle;
}
.input-area > p {
margin-top: 10px;
}
.input-header {
font-size: 18px;
width: 160px;
display: inline-block;
}
.input-right {
width: 300px;
display: inline-block;
font-family: monospace;
}
#sonarr-warning {
display: none;
}
#logo {
max-width: 50px;
}
#header-title {
font-size: 34px;
vertical-align: middle;
padding-left: 15px;
}
#footer {
color: #444444;
margin: 0 auto;
margin-top: 10px;
text-align: center;
}
#jackett-allowext, #jackett-allowupdate, #jackett-logging, #jackett-prerelease {
width: 25px;
}
.modal-fillwidth {
width: 1200px;
min-width:80%;
}
.indexer-caps {
padding: 0px 15px 15px 15px;
border-top: 1px solid #e5e5e5;
}
.indexer-caps table {
border-bottom: 1px solid #ddd;
}
.jackettlogWarn {
background-color: #FFFF8E !important;
}
.jackettlogError {
background-color: #FF6060 !important;
}
.jackettdownloaded {
color: blueviolet;
}
.jacketdownloadlocal {
padding-left: 10px;
}
.downloadcolumn {
text-align:center;
}
pre {
display: block;
padding: 3px;
margin: 0 0 0px;
font-size: 13px;
line-height: 1.42857143;
color: #333;
word-break: break-all;
word-wrap: break-word;
background-color: transparent;
border: 0px;
border-radius: 0px;
}
.modal-open .modal {
overflow-x: auto; /* Model can be bigger than the screen on mobiles */
}
.dataTables_filter input {
width: 400px
}
#unconfigured-indexers-template {
display: none;
}
.jackett-apikey{
margin-top: 10px;
}
.jackett-apikey .input-header{
width: 80px;
}
.setup-item-displayinfo:empty {
display: none;
}
table td.fit{
white-space: nowrap;
width: 1%;
}
.label-imdb {
background-color: #d0ab44;
}
.tooltip-inner {
max-width: 500px !important;
}
.tooltip-inner img {
max-width: 250px;
height: auto;
}
.type-public {
color: #449d44
}
.type-private {
color: #c9302c
}
.type-semi-private {
color: #ec971f
}
.dataTables_deadfilter {
float: right;
text-align: right;
margin-right: 1em;
}
input#searchquery{
width:400px;
}

View File

Before

Width:  |  Height:  |  Size: 361 KiB

After

Width:  |  Height:  |  Size: 361 KiB

View File

Before

Width:  |  Height:  |  Size: 306 KiB

After

Width:  |  Height:  |  Size: 306 KiB

View File

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View File

Before

Width:  |  Height:  |  Size: 160 B

After

Width:  |  Height:  |  Size: 160 B

View File

Before

Width:  |  Height:  |  Size: 148 B

After

Width:  |  Height:  |  Size: 148 B

View File

Before

Width:  |  Height:  |  Size: 201 B

After

Width:  |  Height:  |  Size: 201 B

View File

Before

Width:  |  Height:  |  Size: 158 B

After

Width:  |  Height:  |  Size: 158 B

View File

Before

Width:  |  Height:  |  Size: 146 B

After

Width:  |  Height:  |  Size: 146 B

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -1,6 +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);
/*
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

View File

@@ -1,37 +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('jacketSize', function (context, block) {
return filesize(context, { round: 1 });

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

View File

@@ -0,0 +1,70 @@
---
site: ettv
name: ETTV
language: en-us
type: public
encoding: UTF-8
links:
- https://www.ettv.tv
caps:
categorymappings:
- {id: 49, cat: Movies/3D, desc: "Movies - 3D"}
- {id: 1, cat: Movies/HD, desc: "Movies - HD 1080p"}
- {id: 2, cat: Movies/HD, desc: "Movies - HD 720p"}
- {id: 3, cat: Movies/HD, desc: "Movies - UltraHD/4K"}
- {id: 47, cat: Movies/SD, desc: "Movies - X264/H264"}
- {id: 42, cat: Movies/SD, desc: "Movies - XviD"}
- {id: 41, cat: TV/HD, desc: "TV - HD/X264/H264"}
- {id: 5, cat: TV/SD, desc: "TV - SD/X264/H264"}
- {id: 50, cat: TV/SD, desc: "TV - SD/XVID"}
- {id: 7, cat: TV, desc: "TV - TV Packs"}
modes:
search: [q]
tv-search: [q, season, ep]
settings: []
download:
selector: a[href^="magnet:"]
search:
path: torrents-search.php
inputs:
$raw: "{{range .Categories}}c{{.}}=1&{{end}}"
search: "{{ .Query.Keywords }}"
incldead: "1"
order: desc
sort: id
rows:
selector: div.myFrame-content > div > table > tbody > tr[class]
fields:
download:
selector: a[href^="/torrent/"]
attribute: href
title:
selector: a[href^="/torrent/"][title]
attribute: title
category:
selector: a[href^="torrents.php?cat="]
attribute: href
filters:
- name: querystring
args: cat
details:
selector: a[href^="/torrent/"]
attribute: href
date:
selector: td:nth-child(3)
size:
selector: td:nth-child(4)
seeders:
selector: td:nth-child(6)
leechers:
selector: td:nth-child(7)
downloadvolumefactor:
text: "0"
uploadvolumefactor:
text: "1"

View File

@@ -6,7 +6,9 @@
type: private
encoding: UTF-8
links:
- http://shareisland.org
- https://shareisland.org/
legacylinks:
- http://shareisland.org/
caps:
categorymappings:

View File

@@ -60,7 +60,7 @@
incldead: 1
rows:
selector: p + table > tbody > tr:has(a[href^="details.php?id="]), p + table > tbody > tr[id^="kdescr"]
selector: p + table > tbody > tr:has(a[href^="download.php"]), p + table > tbody > tr:has(a[href^="download.php"]) + tr[id^="kdescr"] # sometimes an unexpected tr[id^="kdescr"] row shows up (for unpublished torrents?)
filters:
- name: andmatch
after: 1

View File

@@ -10,44 +10,35 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http.Dependencies;
using Autofac.Integration.WebApi;
using Jackett.Services.Interfaces;
using Jacket.Common;
using Jackett.Models.Config;
using System.Reflection;
namespace Jackett
{
public class Engine
{
private static IContainer container = null;
static Engine()
{
BuildContainer();
}
public static void BuildContainer()
public static void BuildContainer(params Autofac.Module[] ApplicationSpecificModules)
{
var builder = new ContainerBuilder();
builder.RegisterModule<JackettModule>();
foreach(var module in ApplicationSpecificModules)
{
builder.RegisterModule(module);
}
SetupLogging(builder);
container = builder.Build();
// Register the container in itself to allow for late resolves
var secondaryBuilder = new ContainerBuilder();
secondaryBuilder.RegisterInstance(container).SingleInstance();
SetupLogging(secondaryBuilder);
secondaryBuilder.Update(container);
}
public static IDependencyResolver DependencyResolver()
public static IContainer GetContainer()
{
return new AutofacWebApiDependencyResolver(container);
return container;
}
public static IConfigurationService ConfigService
{
get

View File

@@ -257,8 +257,9 @@ Encoding = Encoding.UTF8;
var qDLLink = Row.QuerySelector("a[href^=\"torrents.php?action=download\"]");
var qSize = Row.QuerySelector("td:nth-last-child(4)");
var qSeeders = Row.QuerySelector("td:nth-last-child(3)");
var qLeechers = Row.QuerySelector("td:nth-last-child(2)");
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
@@ -304,6 +305,7 @@ Encoding = Encoding.UTF8;
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;

View File

@@ -286,6 +286,10 @@ namespace Jackett.Indexers
protected async Task<byte[]> Download(Uri link, RequestType method)
{
// return magnet link
if (link.Scheme == "magnet")
return Encoding.UTF8.GetBytes(link.OriginalString);
// do some extra escaping, needed for HD-Torrents
var requestLink = link.ToString()
.Replace("(", "%28")

View File

@@ -266,9 +266,11 @@ namespace Jackett.Indexers
var conditionResultState = false;
var value = variables[condition];
if (value is string)
if (value == null)
conditionResultState = false;
else if (value is string)
conditionResultState = !string.IsNullOrWhiteSpace((string)value);
else if(value is ICollection)
else if (value is ICollection)
conditionResultState = ((ICollection)value).Count > 0;
else
throw new Exception(string.Format("Unexpceted type for variable {0}: {1}", condition, value.GetType()));

View File

@@ -6,11 +6,115 @@
</PropertyGroup>
<ItemGroup>
<Content Include="Content\animate.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\binding_dark.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\bootstrap\bootstrap.min.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\bootstrap\bootstrap.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\common.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\congruent_outline.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\crissXcross.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\css\bootstrap-multiselect.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\css\font-awesome.min.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\css\jquery.dataTables.min.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\custom.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\custom.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\custom_mobile.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\favicon.ico">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\fonts\fontawesome-webfont.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\fonts\glyphicons-halflings-regular.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\images\sort_asc.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\images\sort_asc_disabled.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\images\sort_both.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\images\sort_desc.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\images\sort_desc_disabled.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\index.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\jacket_medium.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\libs\api.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\libs\bootstrap-multiselect.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\libs\bootstrap-notify.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\libs\filesize.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\libs\handlebars.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\libs\handlebarsextend.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\libs\handlebarsmoment.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\libs\jquery.dataTables.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\libs\jquery.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\libs\moment.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\login.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Models\TorznabCatType.tt" />
<Content Include="Resources\validator_reply.xml" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="AngleSharp" Version="0.9.9" />
<PackageReference Include="Autofac" Version="4.6.2" />
<PackageReference Include="AutoMapper" Version="6.1.1" />
<PackageReference Include="BencodeNET" Version="2.2.22" />
<PackageReference Include="CloudFlareUtilities" Version="0.4.0-alpha" />
@@ -39,9 +143,41 @@
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
</Compile>
<Compile Update="Properties\Resources.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Update="Content\fonts\fontawesome-webfont.eot">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Content\fonts\fontawesome-webfont.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Content\fonts\fontawesome-webfont.woff">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Content\fonts\fontawesome-webfont.woff2">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Content\fonts\FontAwesome.otf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Content\fonts\glyphicons-halflings-regular.eot">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Content\fonts\glyphicons-halflings-regular.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Content\fonts\glyphicons-halflings-regular.woff">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Content\fonts\glyphicons-halflings-regular.woff2">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Models\TorznabCatType.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>TorznabCatType.generated.cs</LastGenOutput>
@@ -71,6 +207,13 @@
<Version>2.0.0</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Properties\Resources.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@@ -2,7 +2,6 @@
using System;
using System.Linq;
using System.Text;
using Autofac.Integration.WebApi;
using Jackett.Indexers;
using Jackett.Utils.Clients;
using AutoMapper;
@@ -16,6 +15,7 @@ using Jackett.Models.Config;
using System.IO;
using Newtonsoft.Json.Linq;
using Jackett.Utils;
using System.Collections.Generic;
namespace Jackett
{
@@ -24,10 +24,7 @@ namespace Jackett
protected override void Load(ContainerBuilder builder)
{
// Just register everything! TODO: Something better and more explicit than scanning everything.
var assembliesToScan = new Assembly[] { typeof(JackettModule).Assembly, typeof(JackettStartup).Assembly };
foreach (var assembly in assembliesToScan)
{
builder.RegisterAssemblyTypes(assembly)
builder.RegisterAssemblyTypes(typeof(JackettModule).Assembly)
.Except<IIndexer>()
.Except<IImdbResolver>()
.Except<OmdbResolver>()
@@ -43,8 +40,7 @@ namespace Jackett
.Except<AggregateIndexer>()
.Except<CardigannIndexer>()
.AsImplementedInterfaces().SingleInstance();
}
builder.RegisterApiControllers(typeof(JackettModule).Assembly).InstancePerRequest();
builder.Register(ctx =>
{
return BuildServerConfig(ctx);

View File

@@ -0,0 +1,101 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Jackett.Common.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
public class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Jackett.Common.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;
///&lt;rss version=&quot;1.0&quot; xmlns:atom=&quot;http://www.w3.org/2005/Atom&quot; xmlns:torznab=&quot;http://torznab.com/schemas/2015/feed&quot;&gt;
/// &lt;channel&gt;
/// &lt;atom:link href=&quot;https://hdaccess.net/api&quot; rel=&quot;self&quot; type=&quot;application/rss+xml&quot; /&gt;
/// &lt;title&gt;HDAccess&lt;/title&gt;
/// &lt;description&gt;HDAccess API&lt;/description&gt;
/// &lt;link&gt;https://hdaccess.net&lt;/link&gt;
/// &lt;language&gt;en-us&lt;/language&gt;
/// &lt;webMaster&gt;($email) (HDA Invites)&lt;/webMaster&gt;
/// &lt;category&gt;search&lt;/category&gt;
/// &lt;image&gt;
/// &lt;url&gt;h [rest of string was truncated]&quot;;.
/// </summary>
public static string test {
get {
return ResourceManager.GetString("test", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;
///&lt;rss version=&quot;1.0&quot; xmlns:atom=&quot;http://www.w3.org/2005/Atom&quot; xmlns:torznab=&quot;http://torznab.com/schemas/2015/feed&quot;&gt;
/// &lt;channel&gt;
/// &lt;item&gt;
/// &lt;link&gt;https://example.com&lt;/link&gt;
/// &lt;pubDate&gt;Sat, 14 Mar 2015 17:10:42 -0400&lt;/pubDate&gt;
/// &lt;enclosure url=&quot;https://example.com&quot; length=&quot;1&quot; type=&quot;application/x-bittorrent&quot; /&gt;
/// &lt;/item&gt;
/// &lt;/channel&gt;
///&lt;/rss&gt;.
/// </summary>
public static string validator_reply {
get {
return ResourceManager.GetString("validator_reply", resourceCulture);
}
}
}
}

View File

@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="test" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\test.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
<data name="validator_reply" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\validator_reply.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
</root>

View File

@@ -173,7 +173,7 @@ namespace Jackett.Services
#if DEBUG
// When we are running in debug use the source files
var sourcePath = Path.GetFullPath(Path.Combine(ApplicationFolder(), "..\\..\\..\\Jackett\\Content"));
var sourcePath = Path.GetFullPath(Path.Combine(ApplicationFolder(), "..\\..\\..\\Jackett.Common\\Content"));
if (Directory.Exists(sourcePath))
{
dir = sourcePath;
@@ -202,7 +202,7 @@ namespace Jackett.Services
#if DEBUG
// When we are running in debug use the source files
var sourcePath = Path.GetFullPath(Path.Combine(ApplicationFolder(), "..\\..\\..\\Jackett\\Definitions"));
var sourcePath = Path.GetFullPath(Path.Combine(ApplicationFolder(), "..\\..\\..\\Jackett.Common\\Definitions"));
if (Directory.Exists(sourcePath))
{
dir = sourcePath;

View File

@@ -10,7 +10,7 @@ namespace Jackett.Services.Interfaces
void Start();
void Stop();
void ReserveUrls(bool doInstall = true);
Uri ConvertToProxyLink(Uri link, string serverUrl, string indexerId, string action = "dl", string file = "t.torrent");
Uri ConvertToProxyLink(Uri link, string serverUrl, string indexerId, string action = "dl", string file = "t");
string BasePath();
string GetServerUrl(HttpRequestMessage Request);
List<string> notices { get; }

View File

@@ -51,6 +51,26 @@ namespace JackettConsole
}
else
{
// Logging
if (options.Logging)
JackettStartup.LogRequests = true;
// Tracing
if (options.Tracing)
JackettStartup.TracingEnabled = true;
// Initialize autofac, logger, etc.
Engine.BuildContainer(new WebApi2Module());
// Log after the fact as using the logger will cause the options above to be used
if (options.Logging)
Engine.Logger.Info("Logging enabled.");
if (options.Tracing)
Engine.Logger.Info("Tracing enabled.");
if (options.ListenPublic && options.ListenPrivate)
{
@@ -73,21 +93,6 @@ namespace JackettConsole
JackettStartup.ProxyConnection = options.ProxyConnection.ToLowerInvariant();
Engine.Logger.Info("Proxy enabled. " + JackettStartup.ProxyConnection);
}
// Logging
if (options.Logging)
JackettStartup.LogRequests = true;
// Tracing
if (options.Tracing)
JackettStartup.TracingEnabled = true;
// Log after the fact as using the logger will cause the options above to be used
if (options.Logging)
Engine.Logger.Info("Logging enabled.");
if (options.Tracing)
Engine.Logger.Info("Tracing enabled.");
if (options.SSLFix == true)
Engine.Logger.Info("SSL ECC workaround enabled.");

View File

@@ -66,7 +66,6 @@
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ServiceConfigService.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />

View File

@@ -19,6 +19,7 @@ namespace Jackett.Service
protected override void OnStart(string[] args)
{
Engine.BuildContainer(new WebApi2Module());
Engine.Logger.Info("Service starting");
Engine.Server.Initalize();
Engine.Server.Start();

View File

@@ -22,15 +22,11 @@ namespace Jackett.Test
{
var builder = new ContainerBuilder();
builder.RegisterModule<JackettModule>();
builder.RegisterModule<WebApi2Module>();
builder.RegisterType<TestWebClient>().As<WebClient>().SingleInstance();
builder.RegisterInstance<Logger>(LogManager.GetCurrentClassLogger()).SingleInstance();
builder.RegisterType<TestIndexerManagerServiceHelper>().As<IIndexerManagerService>().SingleInstance();
testContainer = builder.Build();
// Register the container in itself to allow for late resolves
var secondaryBuilder = new ContainerBuilder();
secondaryBuilder.RegisterInstance<IContainer>(testContainer).SingleInstance();
secondaryBuilder.Update(testContainer);
}
public static TestIndexerManagerServiceHelper IndexManager

View File

@@ -28,12 +28,13 @@ namespace JackettTray
toolStripMenuItemWebUI.Click += toolStripMenuItemWebUI_Click;
toolStripMenuItemShutdown.Click += toolStripMenuItemShutdown_Click;
#if __MonoCS__
// No shortcuts on linux
#else
toolStripMenuItemAutoStart.Visible = true;
#endif
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
toolStripMenuItemAutoStart.Visible = true;
}
Engine.BuildContainer(new WebApi2Module());
Engine.Server.Initalize();
if (!Engine.ServiceConfig.ServiceExists())
@@ -104,16 +105,15 @@ namespace JackettTray
private void CreateShortcut()
{
#if __MonoCS__
// No shortcuts on linux
#else
var appPath = Assembly.GetExecutingAssembly().Location;
var shell = new IWshRuntimeLibrary.WshShell();
var shortcut = (IWshRuntimeLibrary.IWshShortcut)shell.CreateShortcut(ShortcutPath);
shortcut.Description = Assembly.GetExecutingAssembly().GetName().Name;
shortcut.TargetPath = appPath;
shortcut.Save();
#endif
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
var appPath = Assembly.GetExecutingAssembly().Location;
var shell = new IWshRuntimeLibrary.WshShell();
var shortcut = (IWshRuntimeLibrary.IWshShortcut)shell.CreateShortcut(ShortcutPath);
shortcut.Description = Assembly.GetExecutingAssembly().GetName().Name;
shortcut.TargetPath = appPath;
shortcut.Save();
}
}
private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)

View File

@@ -10,12 +10,6 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
/*
// no supported by appveyor, disabeling for now
#if __MonoCS__
using Mono.Unix.Native;
#endif
*/
namespace Jackett.Updater
{
@@ -28,6 +22,7 @@ namespace Jackett.Updater
private void Run(string[] args)
{
Engine.BuildContainer();
Engine.SetupLogging(null, "updater.txt");
Engine.Logger.Info("Jackett Updater v" + GetCurrentVersion());
Engine.Logger.Info("Options \"" + string.Join("\" \"", args) + "\"");
@@ -68,13 +63,7 @@ namespace Jackett.Updater
var exited = proc.WaitForExit(5000);
if (!exited)
Engine.Logger.Info("Process " + pid.ToString() + " didn't exit within 5 seconds");
/*
// no supported by appveyor, disabeling for now
#if __MonoCS__
Engine.Logger.Info("Sending SIGKILL to process " + pid.ToString());
Syscall.kill(proc.Id, Signum.SIGKILL);
#endif
*/
}
catch (ArgumentException)
{

View File

@@ -50,8 +50,23 @@ namespace Jackett.Controllers
path = Encoding.UTF8.GetString(HttpServerUtility.UrlTokenDecode(path));
path = protectionService.UnProtect(path);
var remoteFile = new Uri(path, UriKind.RelativeOrAbsolute);
var fileExtension = ".torrent";
var downloadBytes = await indexer.Download(remoteFile);
// handle magnet URLs
if (downloadBytes.Length >= 7
&& downloadBytes[0] == 0x6d // m
&& downloadBytes[1] == 0x61 // a
&& downloadBytes[2] == 0x67 // g
&& downloadBytes[3] == 0x6e // n
&& downloadBytes[4] == 0x65 // e
&& downloadBytes[5] == 0x74 // t
&& downloadBytes[6] == 0x3a // :
)
{
fileExtension = ".magnet";
}
if (string.IsNullOrWhiteSpace(serverConfig.BlackholeDir))
{
throw new Exception("Blackhole directory not set!");
@@ -64,9 +79,9 @@ namespace Jackett.Controllers
var fileName = DateTime.Now.Ticks.ToString() + "-" + StringUtil.MakeValidFileName(indexer.DisplayName, '_', false);
if (string.IsNullOrWhiteSpace(file))
fileName += ".torrent";
fileName += fileExtension;
else
fileName += "-"+StringUtil.MakeValidFileName(file, '_', false); // call MakeValidFileName() again to avoid any possibility of path traversal attacks
fileName += "-"+StringUtil.MakeValidFileName(file + fileExtension, '_', false); // call MakeValidFileName() again to avoid any possibility of path traversal attacks
File.WriteAllBytes(Path.Combine(serverConfig.BlackholeDir, fileName), downloadBytes);
jsonReply["result"] = "success";

View File

@@ -53,6 +53,23 @@ namespace Jackett.Controllers
var target = new Uri(path, UriKind.RelativeOrAbsolute);
var downloadBytes = await indexer.Download(target);
// handle magnet URLs
if (downloadBytes.Length >= 7
&& downloadBytes[0] == 0x6d // m
&& downloadBytes[1] == 0x61 // a
&& downloadBytes[2] == 0x67 // g
&& downloadBytes[3] == 0x6e // n
&& downloadBytes[4] == 0x65 // e
&& downloadBytes[5] == 0x74 // t
&& downloadBytes[6] == 0x3a // :
)
{
var magneturi = Encoding.UTF8.GetString(downloadBytes);
var response = Request.CreateResponse(HttpStatusCode.Moved);
response.Headers.Location = new Uri(magneturi);
return response;
}
// This will fix torrents where the keys are not sorted, and thereby not supported by Sonarr.
var parser = new BencodeParser();
var torrentDictionary = parser.Parse(downloadBytes);
@@ -63,7 +80,7 @@ namespace Jackett.Controllers
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/x-bittorrent");
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = StringUtil.MakeValidFileName(file, '_', false) // call MakeValidFileName again to avoid any kind of injection attack
FileName = StringUtil.MakeValidFileName(file, '_', false) + ".torrent" // call MakeValidFileName again to avoid any kind of injection attack
};
return result;
}

View File

@@ -156,7 +156,7 @@ namespace Jackett.Controllers.V20
foreach (var result in results)
{
var link = result.Link;
var file = StringUtil.MakeValidFileName(result.Title, '_', false) + ".torrent";
var file = StringUtil.MakeValidFileName(result.Title, '_', false);
result.Link = serverService.ConvertToProxyLink(link, serverUrl, result.TrackerId, "dl", file);
if (result.Link != null && result.Link.Scheme != "magnet" && !string.IsNullOrWhiteSpace(Engine.ServerConfig.BlackholeDir))
result.BlackholeLink = serverService.ConvertToProxyLink(link, serverUrl, result.TrackerId, "bh", file);

View File

@@ -319,7 +319,7 @@ namespace Jackett.Controllers.V20
var proxiedReleases = result.Releases.Select(r => AutoMapper.Mapper.Map<ReleaseInfo>(r)).Select(r =>
{
r.Link = serverService.ConvertToProxyLink(r.Link, serverUrl, r.Origin.ID, "dl", r.Title + ".torrent");
r.Link = serverService.ConvertToProxyLink(r.Link, serverUrl, r.Origin.ID, "dl", r.Title);
return r;
});
@@ -371,7 +371,7 @@ namespace Jackett.Controllers.V20
var potatoReleases = result.Releases.Where(r => r.Link != null || r.MagnetUri != null).Select(r =>
{
var release = AutoMapper.Mapper.Map<ReleaseInfo>(r);
release.Link = serverService.ConvertToProxyLink(release.Link, serverUrl, CurrentIndexer.ID, "dl", release.Title + ".torrent");
release.Link = serverService.ConvertToProxyLink(release.Link, serverUrl, CurrentIndexer.ID, "dl", release.Title);
var item = new Models.DTO.TorrentPotatoResponseItem()
{
release_name = release.Title + "[" + CurrentIndexer.DisplayName + "]", // Suffix the indexer so we can see which tracker we are using in CPS as it just says torrentpotato >.>
@@ -403,7 +403,7 @@ namespace Jackett.Controllers.V20
foreach (var result in results)
{
var link = result.Link;
var file = StringUtil.MakeValidFileName(result.Title, '_', false) + ".torrent";
var file = StringUtil.MakeValidFileName(result.Title, '_', false);
result.Link = serverService.ConvertToProxyLink(link, serverUrl, result.TrackerId, "dl", file);
if (result.Link != null && result.Link.Scheme != "magnet" && !string.IsNullOrWhiteSpace(Engine.ServerConfig.BlackholeDir))
result.BlackholeLink = serverService.ConvertToProxyLink(link, serverUrl, result.TrackerId, "bh", file);

View File

@@ -168,7 +168,7 @@ namespace Jackett.Controllers.V20
{
Thread.Sleep(500);
serverService.Stop();
Engine.BuildContainer();
Engine.BuildContainer(new WebApi2Module());
Engine.Server.Initalize();
Engine.Server.Start();
})).Start();

View File

@@ -76,17 +76,13 @@
<Compile Include="CacheControlAttribute.cs" />
<Compile Include="Controllers\BlackholeController.cs" />
<Compile Include="Controllers\DownloadController.cs" />
<Compile Include="Engine.cs" />
<Compile Include="JackettProtectedAttribute.cs" />
<Compile Include="CookieContainerExtensions.cs" />
<Compile Include="HttpClientExtensions.cs" />
<Compile Include="JackettModule.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Services\ServiceConfigService.cs" />
<Compile Include="Services\ProtectionService.cs" />
<Compile Include="Services\SecuityService.cs" />
<Compile Include="Startup.cs" />
@@ -99,58 +95,12 @@
<Compile Include="Services\ServerService.cs" />
<Compile Include="Utils\WebAPIRequestLogger.cs" />
<Compile Include="Utils\WebAPIToNLogTracer.cs" />
<Compile Include="WebApi2Module.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config">
<SubType>Designer</SubType>
</None>
<None Include="Content\fonts\fontawesome-webfont.eot">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\fonts\fontawesome-webfont.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\fonts\fontawesome-webfont.woff">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\fonts\fontawesome-webfont.woff2">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\fonts\FontAwesome.otf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\fonts\glyphicons-halflings-regular.eot">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\fonts\glyphicons-halflings-regular.ttf">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\fonts\glyphicons-halflings-regular.woff2">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Content\fonts\glyphicons-halflings-regular.woff">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Content Include="Content\css\bootstrap-multiselect.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\custom_mobile.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Include="Resources\test.xml" />
<Content Include="Content\libs\api.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="Content\libs\bootstrap-multiselect.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\libs\handlebarsextend.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Properties\Resources.resx">
@@ -158,96 +108,6 @@
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Content Include="Content\css\font-awesome.min.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\css\jquery.dataTables.min.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\custom.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\custom.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\libs\filesize.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\fonts\fontawesome-webfont.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\fonts\glyphicons-halflings-regular.svg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\images\sort_asc.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\images\sort_asc_disabled.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\images\sort_both.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\images\sort_desc.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\images\sort_desc_disabled.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\libs\handlebars.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\libs\handlebarsmoment.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\libs\jquery.dataTables.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\libs\jquery.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\libs\moment.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\login.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\animate.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\binding_dark.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\libs\bootstrap-notify.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\congruent_outline.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\crissXcross.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\favicon.ico">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\jacket_medium.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\bootstrap\bootstrap.min.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\bootstrap\bootstrap.min.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\common.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\index.html">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Resources\validator_reply.xml" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.5.1">
<Visible>False</Visible>
@@ -269,8 +129,8 @@
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Autofac.WebApi2.Owin">
<Version>4.0.0</Version>
<PackageReference Include="Autofac.WebApi2">
<Version>4.1.0</Version>
</PackageReference>
<PackageReference Include="Microsoft.AspNet.WebApi.OwinSelfHost">
<Version>5.2.3</Version>

View File

@@ -59,43 +59,5 @@ namespace Jackett.Properties {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;
///&lt;rss version=&quot;1.0&quot; xmlns:atom=&quot;http://www.w3.org/2005/Atom&quot; xmlns:torznab=&quot;http://torznab.com/schemas/2015/feed&quot;&gt;
/// &lt;channel&gt;
/// &lt;atom:link href=&quot;https://hdaccess.net/api&quot; rel=&quot;self&quot; type=&quot;application/rss+xml&quot; /&gt;
/// &lt;title&gt;HDAccess&lt;/title&gt;
/// &lt;description&gt;HDAccess API&lt;/description&gt;
/// &lt;link&gt;https://hdaccess.net&lt;/link&gt;
/// &lt;language&gt;en-us&lt;/language&gt;
/// &lt;webMaster&gt;($email) (HDA Invites)&lt;/webMaster&gt;
/// &lt;category&gt;search&lt;/category&gt;
/// &lt;image&gt;
/// &lt;url&gt;h [rest of string was truncated]&quot;;.
/// </summary>
internal static string test {
get {
return ResourceManager.GetString("test", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;
///&lt;rss version=&quot;1.0&quot; xmlns:atom=&quot;http://www.w3.org/2005/Atom&quot; xmlns:torznab=&quot;http://torznab.com/schemas/2015/feed&quot;&gt;
/// &lt;channel&gt;
/// &lt;item&gt;
/// &lt;link&gt;https://example.com&lt;/link&gt;
/// &lt;pubDate&gt;Sat, 14 Mar 2015 17:10:42 -0400&lt;/pubDate&gt;
/// &lt;enclosure url=&quot;https://example.com&quot; length=&quot;1&quot; type=&quot;application/x-bittorrent&quot; /&gt;
/// &lt;/item&gt;
/// &lt;/channel&gt;
///&lt;/rss&gt;.
/// </summary>
internal static string validator_reply {
get {
return ResourceManager.GetString("validator_reply", resourceCulture);
}
}
}
}

View File

@@ -117,11 +117,4 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="test" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\test.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
<data name="validator_reply" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\validator_reply.xml;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>
</root>

View File

@@ -59,7 +59,7 @@ namespace Jackett.Services
}
}
public Uri ConvertToProxyLink(Uri link, string serverUrl, string indexerId, string action = "dl", string file = "t.torrent")
public Uri ConvertToProxyLink(Uri link, string serverUrl, string indexerId, string action = "dl", string file = "t")
{
if (link == null || (link.IsAbsoluteUri && link.Scheme == "magnet"))
return link;

View File

@@ -15,6 +15,7 @@ using System.Web.Http.Filters;
using Newtonsoft.Json.Linq;
using Jacket.Common;
using System.Text;
using Autofac.Integration.WebApi;
[assembly: OwinStartup(typeof(Startup))]
namespace Jackett
@@ -134,7 +135,9 @@ namespace Jackett
if (JackettStartup.LogRequests)
config.MessageHandlers.Add(new WebAPIRequestLogger());
config.DependencyResolver = Engine.DependencyResolver();
config.DependencyResolver = new AutofacWebApiDependencyResolver(Engine.GetContainer());
config.MapHttpAttributeRoutes();
// Sonarr appends /api by default to all Torznab indexers, so we need that "ignored"

View File

@@ -0,0 +1,19 @@
using Autofac;
using Autofac.Integration.WebApi;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Jackett
{
public class WebApi2Module : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(typeof(WebApi2Module).Assembly).AsImplementedInterfaces().SingleInstance();
builder.RegisterApiControllers(typeof(WebApi2Module).Assembly).InstancePerRequest();
}
}
}