- // ==UserScript==
- // @name Hitomi - Search & UI Tweaks
- // @namespace brazenvoid
- // @version 3.0.0
- // @author brazenvoid
- // @license GPL-3.0-only
- // @description Various search filters and user experience enhancers
- // @match https://hitomi.la/*
- // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js
- // @require https://greasyfork.org/scripts/375557-base-resource/code/Base%20Resource.js?version=884246
- // @require https://greasyfork.org/scripts/418665-brazen-configuration-manager/code/Brazen%20Configuration%20Manager.js?version=880818
- // @require https://greasyfork.org/scripts/416104-brazen-ui-generator/code/Brazen%20UI%20Generator.js?version=880816
- // @require https://greasyfork.org/scripts/416105-brazen-base-search-enhancer/code/Brazen%20Base%20Search%20Enhancer.js?version=884245
- // @grant GM_addStyle
- // @run-at document-end
- // ==/UserScript==
-
- GM_addStyle(
- `#settings-wrapper{font-family:Open Sans;font-size:12px;font-weight:700;line-height:1;background-color:rgb(216, 210, 234);top:5vh;width:220px}button{font-family:Open Sans;font-size:12px;font-weight:700}.bg-brand{background-color:rgb(216, 210, 234)}`)
-
- const PAGE_PATH_NAME = window.location.pathname
-
- const IS_GALLERY_PAGE = $('#dl-button').length
-
- const ITEM_CLASSES = ['acg', 'anime', 'cg', 'dj', 'manga']
- const ITEM_CLASSES_SELECTOR = '.acg,.anime,.cg,.dj,.manga'
-
- const FILTER_GALLERY_TYPES = 'Show Gallery Types'
- const FILTER_TAG_BLACKLIST = 'Tag Blacklist'
- const FILTER_COMPLEX_TAG_BLACKLIST = 'Complex Blacklist'
- const FILTER_LANGUAGES = 'Languages'
-
- const OPTION_REMOVE_RELATED_GALLERIES = 'Remove Related Galleries'
-
- class HitomiSearchAndUITweaks extends BrazenBaseSearchEnhancer
- {
- constructor ()
- {
- super('hitomi-sui-', ITEM_CLASSES)
-
- this._configurationManager.
- addCheckboxesGroup(FILTER_GALLERY_TYPES, [
- ['Anime', 'anime'],
- ['Artist CG', 'acg'],
- ['Doujinshi', 'dj'],
- ['Game CG', 'cg'],
- ['Manga', 'manga'],
- ], 'Show only selected gallery types.').
- addCheckboxesGroup(FILTER_LANGUAGES, [
- ['N/A', 'not-applicable'],
- ['Japanese', 'japanese'],
- ['Chinese', 'chinese'],
- ['English', 'english'],
- ['Albanian', 'albanian'],
- ['Arabic', 'arabic'],
- ['Bulgarian', 'bulgarian'],
- ['Catalan', 'catalan'],
- ['Cebuano', 'cebuano'],
- ['Czech', 'czech'],
- ['Danish', 'danish'],
- ['Dutch', 'dutch'],
- ['Esperanto', 'esperanto'],
- ['Estonian', 'estonian'],
- ['Finnish', 'finnish'],
- ['French', 'french'],
- ['German', 'german'],
- ['Greek', 'greek'],
- ['Hebrew', 'hebrew'],
- ['Hungarian', 'hungarian'],
- ['Indonesian', 'indonesian'],
- ['Italian', 'italian'],
- ['Korean', 'korean'],
- ['Latin', 'latin'],
- ['Mongolian', 'mongolian'],
- ['Norwegian', 'norwegian'],
- ['Persian', 'persian'],
- ['Polish', 'polish'],
- ['Portuguese', 'portuguese'],
- ['Romanian', 'romanian'],
- ['Russian', 'russian'],
- ['Slovak', 'slovak'],
- ['Spanish', 'spanish'],
- ['Swedish', 'swedish'],
- ['Tagalog', 'tagalog'],
- ['Thai', 'thai'],
- ['Turkish', 'turkish'],
- ['Ukrainian', 'ukrainian'],
- ['Unspecified', 'unspecified'],
- ['Vietnamese', 'vietnamese'],
- ], 'Select languages to show').
- addFlagField(OPTION_REMOVE_RELATED_GALLERIES, 'Remove related galleries section from gallery pages.').
- addRulesetField(
- FILTER_TAG_BLACKLIST,
- 'Specify the tags blacklist with one tag on each line.',
- (values) => {
- for (let i = 0; i < values.length; i++) {
- values[i] = decodeURIComponent(values[i])
- }
- return values
- },
- (values) => {
- for (let i = 0; i < values.length; i++) {
- values[i] = encodeURIComponent(values[i])
- }
- return values
- },
- ).
- addRulesetField(FILTER_COMPLEX_TAG_BLACKLIST, 'Set complex tag blacklist rules on each line.')
-
- this._setupUI()
- this._setupCompliance()
- this._setupComplianceFilters()
- }
-
- /**
- * @param {string} str
- * @return {string}
- * @private
- */
- _encodeURIComponentRFC3986 (str)
- {
- return encodeURIComponent(str).replace(/[-!'()*]/g, (c) => '%' + c.charCodeAt(0).toString(16).toUpperCase())
- }
-
- _formatFilter (prefix, filter, suffix)
- {
- return '[href="' + prefix + this._encodeURIComponentRFC3986(filter) + suffix + '.html"]'
- }
-
- /**
- * @param filters
- * @param prefix
- * @param suffix
- * @param join
- * @return {*}
- * @private
- */
- _formatFilters (filters, prefix, suffix, join)
- {
- let formattedFilters = [], index2
- for (let index = 0; index < filters.length; index++) {
- if (Array.isArray(filters[index])) {
- for (index2 = 0; index2 < filters[index].length; index2++) {
- formattedFilters[index][index2] = this._formatFilter(prefix, filters[index][index2], suffix)
- }
- } else {
- formattedFilters[index] = this._formatFilter(prefix, filters[index], suffix)
- }
- }
- return join ? formattedFilters.join(', ') : formattedFilters
- }
-
- /**
- * @private
- */
- _removeRelatedGalleries ()
- {
- if (IS_GALLERY_PAGE && this._configurationManager.getValue(OPTION_REMOVE_RELATED_GALLERIES)) {
- $('.gallery-content').remove()
- }
- }
-
- _setupCompliance ()
- {
- this._onGetItemLists = () => $('.gallery-content')
-
- this._onGetItemName = (item) => item.find('h1.lillie a').text()
- }
-
- _setupComplianceFilters ()
- {
- this._addItemComplianceFilter(FILTER_LANGUAGES, (valueKeys) => valueKeys.length, (item, valueKeys) => {
- let languageLink = item.find('tr:nth-child(3) > td:nth-child(2) a')
- if (languageLink.length) {
-
- languageLink = languageLink.attr('href')
- for (let key of valueKeys) {
-
- if (languageLink.includes(key)) {
- return true
- }
- }
- return false
- }
- return valueKeys.includes('not-applicable')
- })
- this._addItemComplianceFilter(FILTER_GALLERY_TYPES, (valueKeys) => valueKeys.length, (item, valueKeys) => {
- for (let galleryClass of valueKeys) {
- if (item.hasClass(galleryClass)) {
- return true
- }
- }
- return false
- })
- this._addItemComplianceFilter(FILTER_TAG_BLACKLIST, (blacklistedTags) => blacklistedTags.length, (item, blacklistedTags) => {
- let relatedTagsWrapper = item.find('.relatedtags')
- for (let blacklistedTag of blacklistedTags) {
- if (relatedTagsWrapper.find('a[href*="' + blacklistedTag + '"]').length) {
- return false
- }
- }
- return true
- })
- this._addItemComplianceFilter(
- FILTER_COMPLEX_TAG_BLACKLIST, (complexBlacklist) => complexBlacklist.length, (item, complexBlacklist) => {
- for (let tagGroupFilterSelectors of complexBlacklist) {
- if (!item.find(tagGroupFilterSelectors.join(', ')).length < tagGroupFilterSelectors.length) {
- return false
- }
- }
- return true
- })
- }
-
- _setupUI ()
- {
- this._onBeforeUIBuild = () => {
- if (IS_GALLERY_PAGE) {
- this._removeRelatedGalleries()
- }
- }
-
- this._onUIBuild = () =>
- this._uiGen.createSettingsSection().append([
- this._uiGen.createTabsSection(['Filters', 'Languages', 'Statistics'], [
- this._uiGen.createTabPanel('Filters', true).append([
- this._configurationManager.createElement(FILTER_GALLERY_TYPES),
- this._uiGen.createSeparator(),
- this._configurationManager.createElement(FILTER_TAG_BLACKLIST),
- // this._configurationManager.createElement(FILTER_COMPLEX_TAG_BLACKLIST),
- this._uiGen.createSeparator(),
- this._configurationManager.createElement(OPTION_DISABLE_COMPLIANCE_VALIDATION),
- this._uiGen.createSeparator(),
- this._configurationManager.createElement(OPTION_ALWAYS_SHOW_SETTINGS_PANE),
- ]),
- this._uiGen.createTabPanel('Languages').append([
- this._configurationManager.createElement(FILTER_LANGUAGES),
- ]),
- this._uiGen.createTabPanel('Statistics').append([
- this._uiGen.createStatisticsFormGroup(FILTER_GALLERY_TYPES),
- this._uiGen.createStatisticsFormGroup(FILTER_LANGUAGES),
- this._uiGen.createStatisticsFormGroup(FILTER_TAG_BLACKLIST),
- // this._uiGen.createStatisticsFormGroup(FILTER_COMPLEX_TAG_BLACKLIST),
- this._uiGen.createSeparator(),
- this._uiGen.createStatisticsTotalsGroup(),
- ]),
- ]),
- this._createSettingsFormActions(),
- this._uiGen.createSeparator(),
- this._uiGen.createStatusSection(),
- ])
-
- this._onAfterUIBuild = () => {
- this._uiGen.getSelectedSection()[0].userScript = this
- }
- }
- }
-
- (new HitomiSearchAndUITweaks).init()