mirror of
https://github.com/Jackett/Jackett.git
synced 2025-09-17 17:34:09 +02:00
[Feature] Filter Meta Indexer by tag and by language (#11662). resolves #8884 resolves #7170 resolves #4787 resolves #2185
* bump to 0.18.* Also partially addresses https://github.com/Jackett/Jackett/issues/661 (if user adds `enabled` and `disabled` tags). Co-authored-by: garfield69 <garfieldsixtynine@gmail.com> Co-authored-by: ilike2burnthing <59480337+ilike2burnthing@users.noreply.github.com>
This commit is contained in:
@@ -3,6 +3,8 @@ var basePath = '';
|
||||
var indexers = [];
|
||||
var configuredIndexers = [];
|
||||
var unconfiguredIndexers = [];
|
||||
var configuredTags = [];
|
||||
var availableFilters = [];
|
||||
|
||||
$.fn.inView = function () {
|
||||
if (!this.length) return false;
|
||||
@@ -58,7 +60,7 @@ function openSearchIfNecessary() {
|
||||
decodeURIComponent(item.split('=')[1].replace(/\+/g, '%20')))
|
||||
}, prev), {});
|
||||
if ("search" in hashArgs) {
|
||||
showSearch(hashArgs.tracker, hashArgs.search, hashArgs.category);
|
||||
showSearch(hashArgs.filter, hashArgs.tracker, hashArgs.search, hashArgs.category);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +69,14 @@ function insertWordWrap(str) {
|
||||
return str.replace(/([\.\-_\/\\])/g, "$1\u200B");
|
||||
}
|
||||
|
||||
function type_filter(indexer) {
|
||||
return indexer.type == this.value;
|
||||
}
|
||||
|
||||
function tag_filter(indexer) {
|
||||
return indexer.tags.map(t => t.toLowerCase()).indexOf(this.value.toLowerCase()) > -1;
|
||||
}
|
||||
|
||||
function getJackettConfig(callback) {
|
||||
api.getServerConfig(callback).fail(function () {
|
||||
doNotify("Error loading Jackett settings, request to Jackett server failed, is server running ?", "danger", "glyphicon glyphicon-alert");
|
||||
@@ -131,11 +141,14 @@ function loadJackettSettings() {
|
||||
}
|
||||
|
||||
function reloadIndexers() {
|
||||
$('#filters').hide();
|
||||
$('#indexers').hide();
|
||||
api.getAllIndexers(function (data) {
|
||||
indexers = data;
|
||||
configuredIndexers = [];
|
||||
unconfiguredIndexers = [];
|
||||
configuredTags = [];
|
||||
availableFilters = [];
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var item = data[i];
|
||||
item.rss_host = resolveUrl(basePath + "/api/v2.0/indexers/" + item.id + "/results/torznab/api?apikey=" + api.key + "&t=search&cat=&q=");
|
||||
@@ -169,7 +182,13 @@ function reloadIndexers() {
|
||||
else
|
||||
unconfiguredIndexers.push(item);
|
||||
}
|
||||
|
||||
configuredTags = configuredIndexers.map(i => i.tags).reduce((a, g) => a.concat(g), []).filter((v, i, a) => a.indexOf(v) === i);
|
||||
|
||||
configureFilters(configuredIndexers);
|
||||
|
||||
displayConfiguredIndexersList(configuredIndexers);
|
||||
|
||||
$('#indexers div.dataTables_filter input').focusWithoutScrolling();
|
||||
openSearchIfNecessary();
|
||||
}).fail(function () {
|
||||
@@ -177,6 +196,23 @@ function reloadIndexers() {
|
||||
});
|
||||
}
|
||||
|
||||
function configureFilters(indexers) {
|
||||
function add(f) {
|
||||
if (availableFilters.find(x => x.id == f.id))
|
||||
return;
|
||||
if (!indexers.every(f.apply, f) && indexers.some(f.apply, f))
|
||||
availableFilters.push(f);
|
||||
}
|
||||
|
||||
["public", "private", "semi-private"]
|
||||
.map(t => { return { id: "type:" + t, apply: type_filter, value: t } })
|
||||
.forEach(add);
|
||||
|
||||
configuredTags.sort()
|
||||
.map(t => { return { id: "tag:" + t.toLowerCase(), apply: tag_filter, value: t }})
|
||||
.forEach(add);
|
||||
}
|
||||
|
||||
function displayConfiguredIndexersList(indexers) {
|
||||
var indexersTemplate = Handlebars.compile($("#configured-indexer-table").html());
|
||||
var indexersTable = $(indexersTemplate({
|
||||
@@ -484,17 +520,20 @@ function prepareSearchButtons(element) {
|
||||
var id = $btn.data("id");
|
||||
$btn.click(function () {
|
||||
window.location.hash = "search&tracker=" + id;
|
||||
showSearch(id);
|
||||
showSearch(null, id);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function prepareSetupButtons(element) {
|
||||
element.find('.indexer-setup').each(function (i, btn) {
|
||||
var indexer = configuredIndexers[i];
|
||||
$(btn).click(function () {
|
||||
displayIndexerSetup(indexer.id, indexer.name, indexer.caps, indexer.link, indexer.alternativesitelinks, indexer.description);
|
||||
});
|
||||
var $btn = $(btn);
|
||||
var id = $btn.data("id");
|
||||
var indexer = configuredIndexers.find(i => i.id === id);
|
||||
if (indexer)
|
||||
$btn.click(function () {
|
||||
displayIndexerSetup(indexer.id, indexer.name, indexer.caps, indexer.link, indexer.alternativesitelinks, indexer.description);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -610,11 +649,32 @@ function populateConfigItems(configForm, config) {
|
||||
var item = config[i];
|
||||
var setupValueTemplate = Handlebars.compile($("#setup-item-" + item.type).html());
|
||||
item.value_element = setupValueTemplate(item);
|
||||
var template = setupItemTemplate(item);
|
||||
var template = $(setupItemTemplate(item));
|
||||
$formItemContainer.append(template);
|
||||
setupConfigItem(template, item);
|
||||
}
|
||||
}
|
||||
|
||||
function setupConfigItem(configItem, item) {
|
||||
switch (item.type) {
|
||||
case "inputtags": {
|
||||
configItem.find("input").tagify({
|
||||
dropdown: {
|
||||
enabled: 0,
|
||||
position: "text"
|
||||
},
|
||||
separator: item.separator || ",",
|
||||
whitelist: item.whitelist || [],
|
||||
blacklist: item.blacklist || [],
|
||||
pattern: item.pattern || null,
|
||||
delimiters: item.delimiters || item.separator || ",",
|
||||
originalInputValueFormat: function (values) { return values.map(item => item.value.toLowerCase()).join(this.separator); }
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function newConfigModal(title, config, caps, link, alternativesitelinks, description) {
|
||||
var configTemplate = Handlebars.compile($("#jackett-config-setup-modal").html());
|
||||
var configForm = $(configTemplate({
|
||||
@@ -638,6 +698,8 @@ function newConfigModal(title, config, caps, link, alternativesitelinks, descrip
|
||||
});
|
||||
}
|
||||
|
||||
$("div[data-id='tags'] input", configForm).data("tagify").settings.whitelist = configuredTags;
|
||||
|
||||
return configForm;
|
||||
}
|
||||
|
||||
@@ -668,9 +730,13 @@ function getConfigModalJson(configForm) {
|
||||
$el.find(".setup-item-inputcheckbox input:checked").each(function () {
|
||||
itemEntry.values.push($(this).val());
|
||||
});
|
||||
break;
|
||||
case "inputselect":
|
||||
itemEntry.value = $el.find(".setup-item-inputselect select").val();
|
||||
break;
|
||||
case "inputtags":
|
||||
itemEntry.value = $el.find(".setup-item-inputtags input").val();
|
||||
break;
|
||||
}
|
||||
configJson.push(itemEntry)
|
||||
});
|
||||
@@ -802,14 +868,15 @@ function updateReleasesRow(row) {
|
||||
}
|
||||
}
|
||||
|
||||
function showSearch(selectedIndexer, query, category) {
|
||||
function showSearch(selectedFilter, selectedIndexer, query, category) {
|
||||
var selectedIndexers = [];
|
||||
if (selectedIndexer)
|
||||
selectedIndexers = selectedIndexer.split(",");
|
||||
selectedIndexers = selectedIndexer.split(",");
|
||||
$('#select-indexer-modal').remove();
|
||||
var releaseTemplate = Handlebars.compile($("#jackett-search").html());
|
||||
var releaseDialog = $(releaseTemplate({
|
||||
indexers: configuredIndexers
|
||||
filters: availableFilters,
|
||||
active: selectedFilter
|
||||
}));
|
||||
|
||||
$("#modals").append(releaseDialog);
|
||||
@@ -823,6 +890,29 @@ function showSearch(selectedIndexer, query, category) {
|
||||
window.location.hash = '';
|
||||
});
|
||||
|
||||
var setTrackers = function (filterId, trackers) {
|
||||
var select = $('#searchTracker');
|
||||
var selected = select.val();
|
||||
var filter = availableFilters.find(f => f.id == filterId);
|
||||
if (filter)
|
||||
trackers = trackers.filter(filter.apply,filter);
|
||||
var options = trackers.map(t => {
|
||||
return {
|
||||
label: t.name,
|
||||
value: t.id
|
||||
}
|
||||
});
|
||||
select.multiselect('dataprovider', options);
|
||||
select.val(selected).multiselect("refresh");
|
||||
};
|
||||
|
||||
$('#searchFilter').change(jQuery.proxy(function () {
|
||||
var filterId = $('#searchFilter').val();
|
||||
setTrackers(filterId, this.items);
|
||||
}, {
|
||||
items: configuredIndexers
|
||||
}));
|
||||
|
||||
var setCategories = function (trackers, items) {
|
||||
var cats = {};
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
@@ -869,6 +959,7 @@ function showSearch(selectedIndexer, query, category) {
|
||||
return;
|
||||
}
|
||||
var searchString = releaseDialog.find('#searchquery').val();
|
||||
var filterId = releaseDialog.find('#searchFilter').val();
|
||||
var queryObj = {
|
||||
Query: searchString,
|
||||
Category: releaseDialog.find('#searchCategory').val(),
|
||||
@@ -878,14 +969,15 @@ function showSearch(selectedIndexer, query, category) {
|
||||
window.location.hash = Object.entries({
|
||||
search: encodeURIComponent(queryObj.Query).replace(/%20/g, '+'),
|
||||
tracker: queryObj.Tracker.join(","),
|
||||
category: queryObj.Category.join(",")
|
||||
}).map(([k, v], i) => k + '=' + v).join('&');
|
||||
category: queryObj.Category.join(","),
|
||||
filter: filterId ? encodeURIComponent(filterId) : ""
|
||||
}).filter(([k, v]) => v).map(([k, v], i) => k + '=' + v).join('&');
|
||||
|
||||
$('#jackett-search-perform').html($('#spinner').html());
|
||||
$('#searchResults div.dataTables_filter input').val("");
|
||||
clearSearchResultTable($('#searchResults'));
|
||||
|
||||
var trackerId = "all";
|
||||
var trackerId = filterId || "all";
|
||||
api.resultsForIndexer(trackerId, queryObj, function (data) {
|
||||
for (var i = 0; i < data.Results.length; i++) {
|
||||
var item = data.Results[i];
|
||||
@@ -906,16 +998,14 @@ function showSearch(selectedIndexer, query, category) {
|
||||
|
||||
var searchTracker = releaseDialog.find("#searchTracker");
|
||||
var searchCategory = releaseDialog.find('#searchCategory');
|
||||
searchCategory.multiselect({
|
||||
var searchFilter = releaseDialog.find('#searchFilter');
|
||||
|
||||
searchFilter.multiselect({
|
||||
maxHeight: 400,
|
||||
enableFiltering: true,
|
||||
includeSelectAllOption: true,
|
||||
enableCaseInsensitiveFiltering: true,
|
||||
nonSelectedText: 'Any'
|
||||
nonSelectedText: 'All'
|
||||
});
|
||||
if (selectedIndexers)
|
||||
searchTracker.val(selectedIndexers);
|
||||
searchTracker.trigger("change");
|
||||
|
||||
updateSearchResultTable($('#searchResults'), []);
|
||||
clearSearchResultTable($('#searchResults'));
|
||||
@@ -928,6 +1018,29 @@ function showSearch(selectedIndexer, query, category) {
|
||||
nonSelectedText: 'All'
|
||||
});
|
||||
|
||||
searchCategory.multiselect({
|
||||
maxHeight: 400,
|
||||
enableFiltering: true,
|
||||
includeSelectAllOption: true,
|
||||
enableCaseInsensitiveFiltering: true,
|
||||
nonSelectedText: 'Any'
|
||||
});
|
||||
|
||||
if (availableFilters.length > 0) {
|
||||
if (selectedFilter) {
|
||||
searchFilter.val(selectedFilter);
|
||||
searchFilter.multiselect("refresh");
|
||||
}
|
||||
searchFilter.trigger("change");
|
||||
}
|
||||
else
|
||||
setTrackers(selectedFilter, configuredIndexers);
|
||||
|
||||
if (selectedIndexers) {
|
||||
searchTracker.val(selectedIndexers);
|
||||
searchTracker.multiselect("refresh");
|
||||
}
|
||||
searchTracker.trigger("change");
|
||||
|
||||
if (category !== undefined) {
|
||||
searchCategory.val(category.split(","));
|
||||
@@ -1231,7 +1344,7 @@ function bindUIButtons() {
|
||||
});
|
||||
|
||||
$("#jackett-show-search").click(function () {
|
||||
showSearch(null);
|
||||
showSearch();
|
||||
window.location.hash = "search";
|
||||
});
|
||||
|
||||
@@ -1348,4 +1461,4 @@ function proxyWarning(input) {
|
||||
} else {
|
||||
$('#proxy-warning').hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user