Compare commits

...

12 Commits

14 changed files with 1838 additions and 60 deletions

View File

@@ -23,9 +23,9 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
### Supported Public Trackers
* Anidex
* Anime Tosho
* AniRena
* cpasbien
* EZTV
* Gay-Torrents.net
* Horrible Subs
* Il Corsaro Nero <!-- maintained by bonny1992 -->
* Isohunt
@@ -39,19 +39,33 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* RARBG
* ShowRSS
* Sky torrents
* T411 v2
* The Pirate Bay
* TNTVillage <!-- maintained by bonny1992 -->
* Tokyo Toshokan
* Torlock
* Torrent Downloads
* Torrent9
* TorrentProject
* Torrentz2
* YTS.ag
* zetorrents
### Supported Semi-Private Trackers
* 7tor
* CzTorrent
* Deildu
* Gay-Torrents.net
* NetHD
* RuTracker
* TorrentBytes
* Xtreme Zone
* YggTorrent
* Ztracker
### Supported Private Trackers
* 2 Fast 4 You
* 3D Torrents
* 7tor
* Abnormal
* Acid-Lounge
* AlphaRatio
@@ -78,6 +92,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* BitMeTV
* BitSoup [![(invite needed)][inviteneeded]](#)
* Bitspyder
* BJ-Share
* Blu-bits
* BlueBird
* Blutopia
@@ -85,21 +100,21 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* BrokenStones
* BTNext
* Carpathians
* CGPeers
* CHDBits
* Cinematik
* Cinemageddon
* CinemaZ
* Classix
* CZTeam
* CzTorrent
* DanishBits
* DataScene
* Deildu
* Demonoid
* Diablo Torrent
* DigitalHive
* Dragonworld Reloaded
* Dream Team
* Elite-Tracker
* EoT-Forum
* eStone
* Ethor.net (Thor's Land)
@@ -111,6 +126,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* FunkyTorrents
* Fuzer
* GayTorrent.ru
* GFTracker
* GFXPeers
* Ghost City
* GigaTorrents [![(invite needed)][inviteneeded]](#)
@@ -120,6 +136,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* Greek Team
* Hardbay
* HD-Forever
* HD-Only
* HD-Space
* HD-Torrents
* HD-Bits.com
@@ -128,6 +145,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* HDChina
* HDClub
* HDHome
* HDME
* HDSky
* HDTorrents.it
* Hebits
@@ -158,9 +176,7 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* MySpleen
* NCore
* Nebulance
* NetHD
* New Real World
* NextGen
* Norbits [![(invite needed)][inviteneeded]](#) <!-- added by DiseaseNO but no longer maintained? -->
* notwhat.cd
* Ourbits
@@ -178,7 +194,6 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* RevolutionTT
* Rockhard Lossless
* RoDVD
* RuTracker
* SceneAccess
* SceneFZ
* SceneTime
@@ -208,23 +223,22 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* TenYardTracker
* Torrent Network
* Torrent Sector Crew
* Torrent9
* TorrentBD
* TorrentBytes
* TorrentCCF [![(invite needed)][inviteneeded]](#)
* TorrentDay
* Torrentech
* TorrentHeaven
* TorrentHR
* Torrenting
* TorrentLeech
* Torrents.Md
* Torrent-Syndikat
* TorViet
* ToTheGlory
* TranceTraffic
* Trezzor
* TV Chaos UK
* TV-Vault
* T411 v2
* u-Torrent
* UHDBits
* Ultimate Gamer Club
@@ -235,11 +249,8 @@ Developer note: The software implements the [Torznab](https://github.com/Sonarr/
* x264
* XSpeeds
* Xthor
* Xtreme Zone
* YggTorrent
* Zamunda.net
* Zelka.org
* Ztracker
Trackers marked with [![(invite needed)][inviteneeded]](#) have no active maintainer and are missing features or are broken. If you have an invite for them please send it to kaso1717 -at- gmail.com to get them fixed/improved.

View File

@@ -0,0 +1 @@
span.multiselect-native-select{position:relative}span.multiselect-native-select select{border:0!important;clip:rect(0 0 0 0)!important;height:1px!important;margin:-1px -1px -1px -3px!important;overflow:hidden!important;padding:0!important;position:absolute!important;width:1px!important;left:50%;top:30px}.multiselect-container{position:absolute;list-style-type:none;margin:0;padding:0}.multiselect-container .input-group{margin:5px}.multiselect-container>li{padding:0}.multiselect-container>li>a.multiselect-all label{font-weight:700}.multiselect-container>li.multiselect-group label{margin:0;padding:3px 20px 3px 20px;height:100%;font-weight:700}.multiselect-container>li.multiselect-group-clickable label{cursor:pointer}.multiselect-container>li>a{padding:0}.multiselect-container>li>a>label{margin:0;height:100%;cursor:pointer;font-weight:400;padding:3px 20px 3px 40px}.multiselect-container>li>a>label.radio,.multiselect-container>li>a>label.checkbox{margin:0}.multiselect-container>li>a>label>input[type=checkbox]{margin-bottom:5px}.btn-group>.btn-group:nth-child(2)>.multiselect.btn{border-top-left-radius:4px;border-bottom-left-radius:4px}.form-inline .multiselect-container label.checkbox,.form-inline .multiselect-container label.radio{padding:3px 20px 3px 40px}.form-inline .multiselect-container li a label.checkbox input[type=checkbox],.form-inline .multiselect-container li a label.radio input[type=radio]{margin-left:-20px;margin-right:0}

View File

@@ -724,6 +724,9 @@ function updateReleasesRow(row)
}
function showSearch(selectedIndexer, query, category) {
var selectedIndexers = []
if (selectedIndexer)
selectedIndexers = selectedIndexer.split(",");
$('#select-indexer-modal').remove();
var releaseTemplate = Handlebars.compile($("#jackett-search").html());
var releaseDialog = $(releaseTemplate({
@@ -741,28 +744,30 @@ function showSearch(selectedIndexer, query, category) {
window.location.hash = '';
}) ;
var setCategories = function (tracker, items) {
var setCategories = function (trackers, items) {
var cats = {};
for (var i = 0; i < items.length; i++) {
if (items[i].configured === true && (items[i].id === tracker || tracker === '')) {
indexers["'" + items[i].id + "'"] = items[i].name;
for (var prop in items[i].caps) {
if (prop < 100000 || tracker)
cats[prop] = items[i].caps[prop];
if (trackers.length == 0 || $.inArray(items[i].id, trackers) !== -1) {
for (var j in items[i].caps) {
var cat = items[i].caps[j]
if (cat.ID < 100000 || trackers.length == 1)
cats[cat.ID] = cat.Name;
}
}
}
var select = $('#searchCategory');
select.html("<option value=''>-- All --</option>");
$.each(cats, function (index, value) {
select.append($("<option></option>")
.attr("value", value["ID"]).text(value["ID"] + ' (' + value["Name"] + ')'));
var selected = select.val();
var options = []
$.each(cats, function (ID, Name) {
options.push({ label: ID + ' (' + Name + ')', value: ID });
});
select.multiselect('dataprovider', options);
select.val(selected).multiselect("refresh");
};
$('#searchTracker').change(jQuery.proxy(function () {
var trackerId = $('#searchTracker').val();
setCategories(trackerId, this.items);
var trackerIds = $('#searchTracker').val();
setCategories(trackerIds, this.items);
}, { items: configuredIndexers }));
var queryField = document.getElementById("searchquery");
@@ -783,18 +788,16 @@ function showSearch(selectedIndexer, query, category) {
var queryObj = {
Query: searchString,
Category: releaseDialog.find('#searchCategory').val(),
Tracker: releaseDialog.find('#searchTracker').val().replace("'", "").replace("'", ""),
Tracker: releaseDialog.find('#searchTracker').val()
};
window.location.hash = $.param({ search: queryObj.Query, tracker: queryObj.Tracker, category: queryObj.Category});
window.location.hash = $.param({ search: queryObj.Query, tracker: queryObj.Tracker.join(","), category: queryObj.Category.join(",") });
$('#jackett-search-perform').html($('#spinner').html());
$('#searchResults div.dataTables_filter input').val("");
clearSearchResultTable($('#searchResults'));
var trackerId = queryObj.Tracker;
if (trackerId == null || trackerId == "")
trackerId = "all";
var trackerId = "all";
api.resultsForIndexer(trackerId, queryObj, function (data) {
for (var i = 0; i < data.Results.length; i++) {
var item = data.Results[i];
@@ -814,18 +817,36 @@ function showSearch(selectedIndexer, query, category) {
});
var searchTracker = releaseDialog.find("#searchTracker");
if (selectedIndexer)
searchTracker.val(selectedIndexer);
var searchCategory = releaseDialog.find('#searchCategory')
searchCategory.multiselect({
maxHeight: 400,
enableFiltering: true,
includeSelectAllOption: true,
enableCaseInsensitiveFiltering: true,
nonSelectedText: 'Any'
});
if (selectedIndexers)
searchTracker.val(selectedIndexers);
searchTracker.trigger("change");
updateSearchResultTable($('#searchResults'), []);
clearSearchResultTable($('#searchResults'));
releaseDialog.modal("show");
searchTracker.multiselect({
maxHeight: 400,
enableFiltering: true,
includeSelectAllOption: true,
enableCaseInsensitiveFiltering: true,
nonSelectedText: 'All'
});
if (category !== undefined) {
$('#searchCategory').val(category);
searchCategory.val(category.split(","));
searchCategory.multiselect("refresh");
}
releaseDialog.modal("show");
if (query !== undefined) {
queryField.value = query;
searchButton.click();
@@ -1111,17 +1132,17 @@ function bindUIButtons() {
omdbkey: jackett_omdb_key
};
api.updateServerConfig(jsonObject, function (data) {
if (data !== undefined && data.result == "error") {
doNotify("Error: " + data.error, "danger", "glyphicon glyphicon-alert");
doNotify("Redirecting you to complete configuration update..", "success", "glyphicon glyphicon-ok");
window.setTimeout(function () {
window.location.reload(true);
}, 3000);
}).fail(function (data) {
if (data.responseJSON !== undefined && data.responseJSON.result == "error") {
doNotify("Error: " + data.responseJSON.error, "danger", "glyphicon glyphicon-alert");
return;
} else {
doNotify("Redirecting you to complete configuration update..", "success", "glyphicon glyphicon-ok");
window.setTimeout(function () {
window.location.reload(true);
}, 3000);
doNotify("Request to Jackett server failed", "danger", "glyphicon glyphicon-alert");
}
}).fail(function () {
doNotify("Request to Jackett server failed", "danger", "glyphicon glyphicon-alert");
});
});

View File

@@ -29,6 +29,7 @@
<script src="../libs/handlebarsextend.js"></script>
<script src="../bootstrap/bootstrap.min.js"></script>
<script src="../libs/bootstrap-notify.js"></script>
<script type="text/javascript" src="../libs/bootstrap-multiselect.js"></script>
<script src="https://www.google.com/recaptcha/api.js?render=explicit" async defer></script>
<link href="../bootstrap/bootstrap.min.css" rel="stylesheet">
@@ -37,6 +38,7 @@
<link rel="stylesheet" href="../custom_mobile.css" media="only screen and (max-device-width: 480px)">
<link href="../css/jquery.dataTables.min.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="../css/bootstrap-multiselect.css" type="text/css" />
<link rel="stylesheet" href="../css/font-awesome.min.css">
<title>Jackett</title>
</head>
@@ -112,7 +114,7 @@
</div>
<div class="input-area">
<span class="input-header">Base Path Override: </span>
<input id="jackett-basepathoverride" class="form-control input-right" type="text" value="" placeholder="/jackett/">
<input id="jackett-basepathoverride" class="form-control input-right" type="text" value="" placeholder="/jackett">
</div>
<div class="input-area">
<span class="input-header">Server port: </span>
@@ -419,14 +421,13 @@
<label for="text">Query</label>
<input type="text" name="query" id="searchquery" />
<label for="tracker">Tracker</label>
<select name="tracker" id="searchTracker">
<option value="">-- All --</option>
<select name="tracker" id="searchTracker" multiple="multiple">
{{#each indexers}}
<option value="{{id}}">{{name}}</option>
<option value="{{id}}" selected>{{name}}</option>
{{/each}}
</select>
<label for="category">Category</label>
<select name="category" id="searchCategory"></select>
<select name="category" id="searchCategory" multiple="multiple"></select>
<button id="jackett-search-perform" class="btn btn-success btn-sm"><span class="fa fa-search"></span></button>
<div id="searchResults"></div>
</div>

File diff suppressed because it is too large Load Diff

View File

@@ -28,9 +28,8 @@ namespace Jackett.Controllers.V20
public override void OnAuthorization(HttpActionContext actionContext)
{
var validApiKey = Engine.Server.Config.APIKey;
var queryParams = actionContext.Request.GetQueryNameValuePairs().ToDictionary();
var queryApiKey = queryParams.ContainsKey("apikey") ? queryParams["apikey"] : null;
queryApiKey = queryParams.ContainsKey("passkey") ? queryParams["passkey"] : queryApiKey;
var queryParams = actionContext.Request.GetQueryNameValuePairs();
var queryApiKey = queryParams.Where(x => x.Key == "apikey" || x.Key == "passkey").Select(x => x.Value).FirstOrDefault();
#if DEBUG
if (Debugger.IsAttached)
@@ -112,6 +111,9 @@ namespace Jackett.Controllers.V20
var torznabQuery = converted as TorznabQuery;
resultController.CurrentQuery = torznabQuery;
if (queryType == typeof(ApiSearch)) // Skip CanHandleQuery() check for manual search (CurrentIndexer isn't used during manul search)
return;
if (!resultController.CurrentIndexer.CanHandleQuery(resultController.CurrentQuery))
actionContext.Response = actionContext.Request.CreateErrorResponse(HttpStatusCode.BadRequest, $"{resultController.CurrentIndexer.ID} does not support the requested query.");
}
@@ -157,8 +159,8 @@ namespace Jackett.Controllers.V20
{
var manualResult = new ManualSearchResult();
var trackers = IndexerService.GetAllIndexers().Where(t => t.IsConfigured);
if (CurrentIndexer.ID != "all")
trackers = trackers.Where(t => t.ID == CurrentIndexer.ID).ToList();
if (request.Tracker != null)
trackers = trackers.Where(t => request.Tracker.Contains(t.ID));
trackers = trackers.Where(t => t.CanHandleQuery(CurrentQuery));
var tasks = trackers.ToList().Select(t => t.ResultsForQuery(CurrentQuery)).ToList();
@@ -231,7 +233,7 @@ namespace Jackett.Controllers.V20
ConfigureCacheResults(manualResult.Results);
logger.Info(string.Format("Manual search for \"{0}\" on {1} with {2} results.", CurrentQuery.SanitizedSearchTerm, string.Join(", ", manualResult.Indexers), manualResult.Results.Count()));
logger.Info(string.Format("Manual search for \"{0}\" on {1} with {2} results.", CurrentQuery.SanitizedSearchTerm, string.Join(", ", manualResult.Indexers.Select(i => i.ID)), manualResult.Results.Count()));
return manualResult;
}

View File

@@ -69,6 +69,13 @@ namespace Jackett.Controllers.V20
bool preRelease = config.prerelease;
bool logging = config.logging;
string basePathOverride = config.basepathoverride;
if (basePathOverride != null)
{
basePathOverride = basePathOverride.TrimEnd('/');
if (!string.IsNullOrWhiteSpace(basePathOverride) && !basePathOverride.StartsWith("/"))
throw new Exception("The Base Path Override must start with a /");
}
string omdbApiKey = config.omdbkey;
Engine.Server.Config.UpdateDisabled = updateDisabled;

View File

@@ -24,6 +24,7 @@ namespace Jackett.Indexers
}
public string SiteLink { get; protected set; }
public string[] LegacySiteLinks { get; protected set; }
public string DefaultSiteLink { get; protected set; }
public string[] AlternativeSiteLinks { get; protected set; } = new string[] { };
public string DisplayDescription { get; protected set; }
@@ -134,9 +135,17 @@ namespace Jackett.Indexers
{
configData.SiteLink.Value = DefaultSiteLink;
}
if (!configData.SiteLink.Value.EndsWith("/", StringComparison.Ordinal))
configData.SiteLink.Value += "/";
// reset site link to default if it's a legacy (defunc link)
if (LegacySiteLinks != null && LegacySiteLinks.Contains(configData.SiteLink.Value))
{
logger.Debug(string.Format("changing legacy site link from {0} to {1}", configData.SiteLink.Value, DefaultSiteLink));
configData.SiteLink.Value = DefaultSiteLink;
}
// check whether the site link is well-formatted
var siteUri = new Uri(configData.SiteLink.Value);
SiteLink = configData.SiteLink.Value;

View File

@@ -78,6 +78,8 @@ namespace Jackett.Indexers
if (Definition.Links.Count > 1)
AlternativeSiteLinks = Definition.Links.ToArray();
DefaultSiteLink = Definition.Links[0];
if (Definition.Legacylinks != null)
LegacySiteLinks = Definition.Legacylinks.ToArray();
Encoding = Encoding.GetEncoding(Definition.Encoding);
if (!DefaultSiteLink.EndsWith("/"))
DefaultSiteLink += "/";

View File

@@ -157,7 +157,7 @@ namespace Jackett.Indexers
var grabs = qRow.Find("td.ttr_snatched").Get(0).FirstChild.ToString();
release.Grabs = ParseUtil.CoerceInt(grabs);
release.DownloadVolumeFactor = 1;
release.DownloadVolumeFactor = 0;
release.UploadVolumeFactor = 1;
releases.Add(release);

View File

@@ -420,6 +420,9 @@
<None Include="CurlSharp.dll.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<Content Include="Content\css\bootstrap-multiselect.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\custom_mobile.css">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -432,6 +435,9 @@
</Content>
</ItemGroup>
<ItemGroup>
<Content Include="Content\libs\bootstrap-multiselect.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\libs\handlebarsextend.js">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
@@ -567,10 +573,7 @@
</ItemGroup>
<ItemGroup />
<ItemGroup />
<ItemGroup>
<Folder Include="Indexers\Feeds\" />
<Folder Include="Models\DTO\" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@@ -6,7 +6,8 @@ namespace Jackett.Models.DTO
public class ApiSearch
{
public string Query { get; set; }
public int Category { get; set; }
public int[] Category { get; set; }
public string[] Tracker { get; set; }
public static TorznabQuery ToTorznabQuery(ApiSearch request)
{
@@ -37,7 +38,9 @@ namespace Jackett.Models.DTO
}
stringQuery.SearchTerm = queryStr;
stringQuery.Categories = request.Category == 0 ? new int[0] : new int[1] { request.Category };
stringQuery.Categories = request.Category;
if (stringQuery.Categories == null)
stringQuery.Categories = new int[0];
stringQuery.ExpandCatsToSubCats();
// try to build an IMDB Query

View File

@@ -67,6 +67,7 @@ namespace Jackett.Models
public string Language { get; set; }
public string Encoding { get; set; }
public List<string> Links { get; set; }
public List<string> Legacylinks { get; set; }
public List<string> Certificates { get; set; }
public capabilitiesBlock Caps { get; set; }
public loginBlock Login { get; set; }

View File

@@ -97,6 +97,7 @@ namespace Jackett.Models
|| c == '\''
|| c == '['
|| c == ']'
|| c == '+'
)).AsString();
return safetitle;
}