Search Filters & UI Manipulations
Pada tanggal
// ==UserScript==
// @name Hitomi - Search & UI Tweaks
// @namespace brazenvoid
// @version 2.5.0
// @author brazenvoid
// @license GPL-3.0-only
// @description Search Filters & UI Manipulations
// @include https://hitomi.la/*
// @run-at document-idle
// ==/UserScript==
// Define languages to keep and tags to exclude here
let settings = {
allowedGallleryTypes: [
'artist cg',
'doujinshi',
'game cg',
'manga',
],
allowedLanguages: [
"japanese",
"english"
],
excludedTags: [
"female:loli",
"sample",
"male:yaoi"
],
removeRelatedGalleries: false,
}
// Translate gallery types to css selectors
let allowedGallerySelectors = [], allowedGalleryTypeSelector
for (let allowedGalleryType of settings.allowedGallleryTypes) {
switch (allowedGalleryType) {
case 'anime':
allowedGalleryTypeSelector = 'anime'
break
case 'artist cg':
allowedGalleryTypeSelector = 'acg'
break
case 'doujinshi':
allowedGalleryTypeSelector = 'dj'
break
case 'game cg':
allowedGalleryTypeSelector = 'cg'
break
case 'manga':
allowedGalleryTypeSelector = 'manga'
break
default:
continue;
}
allowedGallerySelectors.push(allowedGalleryTypeSelector)
}
// Formatting filters
let formatFilters = function (filters, prefix, suffix) {
for (let index = 0; index < filters.length; index++) {
filters[index] = '[href="'+ prefix + encodeURIComponent(filters[index]) + suffix +'.html"]'
}
return filters.join(", ")
}
let languageFiltersSelector = formatFilters(settings.allowedLanguages, "/index-", "-1")
let tagFiltersSelector = formatFilters(settings.excludedTags, "/tag/", "-all-1")
// Filteration logic
let validateLanguage = function (gallery) {
let validationCheck = true
if (settings.allowedLanguages.length > 0) {
let languageTD = gallery.querySelector('tr:nth-child(3) > td:nth-child(2)')
if (languageTD.querySelector('a') !== null) {
validationCheck = languageTD.querySelectorAll(languageFiltersSelector).length > 0
}
}
return validationCheck
}
let validateTags = function (gallery) {
let validationCheck = true
if (settings.excludedTags.length > 0) {
validationCheck = gallery.querySelectorAll(tagFiltersSelector).length === 0
}
return validationCheck
}
let validateType = function (gallery) {
return allowedGallerySelectors.includes(gallery.className)
}
let complianceCallback = function(target) {
let galleries = target.querySelectorAll('.anime, .manga, .dj, .acg, .cg'), removeGallery = false, languageTD, validationCheck
for (let gallery of galleries) {
validationCheck = validateType(gallery) && validateLanguage(gallery) && validateTags(gallery);
if (!validationCheck) {
gallery.remove()
}
}
}
// Script Run
let galleriesList = document.querySelector('.gallery-content')
let isGalleryPage = document.getElementById('dl-button') !== null;
if (isGalleryPage && settings.removeRelatedGalleries) {
galleriesList.remove();
} else {
let observerConfig = {
attributes: false,
childList: true,
subtree: false
}
complianceCallback(galleriesList)
// Adding observer to check compliance of galleries
let observer = new MutationObserver(function(mutations, observer) {
for(let mutation of mutations) {
complianceCallback(mutation.target)
}
})
observer.observe(galleriesList, observerConfig)
}