E-Hentai - UX Tweaks

Complex tag highlights and blacklisting

2023/09/26のページです。最新版はこちら。

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください。
  1. // ==UserScript==
  2. // @name E-Hentai - UX Tweaks
  3. // @namespace brazenvoid
  4. // @version 1.2.0
  5. // @author brazenvoid
  6. // @license GPL-3.0-only
  7. // @description Complex tag highlights and blacklisting
  8. // @match https://e-hentai.org/*
  9. // @match https://exhentai.org/*
  10. // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js
  11. // @require https://greasyfork.org/scripts/375557-base-brazen-resource/code/Base%20Brazen%20Resource.js?version=1244990
  12. // @require https://greasyfork.org/scripts/416104-brazen-ui-generator/code/Brazen%20UI%20Generator.js?version=1245460
  13. // @require https://greasyfork.org/scripts/418665-brazen-configuration-manager/code/Brazen%20Configuration%20Manager.js?version=1245040
  14. // @require https://greasyfork.org/scripts/429587-brazen-item-attributes-resolver/code/Brazen%20Item%20Attributes%20Resolver.js?version=1244644
  15. // @require https://greasyfork.org/scripts/416105-brazen-base-search-enhancer/code/Brazen%20Base%20Search%20Enhancer.js?version=1245401
  16. // @grant GM_addStyle
  17. // @run-at document-end
  18. // ==/UserScript==
  19.  
  20. GM_addStyle(
  21. `#settings-wrapper{min-width:270px;width:270px}.disliked-tag{background-color:lightcoral !important;color:white !important}.disliked-tag:hover{background-color:indianred !important}.disliked-tag > a{color:white !important}.disliked-tag.favourite-tag{background-color:orange !important}.disliked-tag.favourite-tag:hover{background-color:darkorange !important}.favourite-tag{background-color:mediumseagreen !important;color:white !important}.favourite-tag:hover{background-color:forestgreen !important}.favourite-tag > a{color:white !important}`)
  22.  
  23. const IS_GALLERY_PAGE = $('#gdt').length
  24. const IS_SMALL_WINDOW = $('.stuffbox').length
  25.  
  26. const UI_FAVOURITE_TAGS = 'Favourite Tags'
  27. const UI_DISLIKED_TAGS = 'Disliked Tags'
  28. const UI_VISITED_HIGHLIGHT = 'Highlight Visited'
  29. const UI_AUTO_NEXT_ON_OPEN_ALL_IMAGES = 'Auto Next Page'
  30.  
  31. class EHentaiSearchAndUITweaks extends BrazenBaseSearchEnhancer
  32. {
  33. constructor()
  34. {
  35. super({
  36. isUserLoggedIn: false,
  37. itemDeepAnalysisSelector: '',
  38. itemLinkSelector: 'td.gl3m.glname > a, td.gl3c.glname > a, div.gl2e > div > a, a',
  39. itemListSelectors: 'table.itg, div.itg',
  40. itemNameSelector: 'td.gl3m.glname > a > div.glink, td.gl3c.glname > a > div.glink, div.gl4e.glname > div.glink, div.gl4t.glname.glink',
  41. itemSelectors: 'td.gl2e, div.gl1t',
  42. requestDelay: 0,
  43. scriptPrefix: 'e-hentai-ux-',
  44. tagSelectorGenerator: (tag) => {
  45. tag = tag.trim()
  46. if (IS_GALLERY_PAGE) {
  47. return 'div[id="td_' + tag.replace(' ', '_') + '"]'
  48. }
  49. return 'div.gt[title="' + tag + '"], div.gtl[title="' + tag + '"]'
  50. },
  51. })
  52. this._setupFeatures()
  53. this._setupUI()
  54. this._setupEvents()
  55. }
  56.  
  57. _setupEvents()
  58. {
  59. this._onValidateInit = () => !IS_SMALL_WINDOW
  60.  
  61. this._onBeforeUIBuild.push(() => this._performOperation(
  62. UI_VISITED_HIGHLIGHT, () => GM_addStyle(`td.gl2e > div > a:visited > .glname > .glink {color: black;}`)))
  63.  
  64. this._onAfterUIBuild.push(() => this._uiGen.getSelectedSection()[0].userScript = this)
  65.  
  66. this._onItemHide = (item) => {
  67. if (item.is('td.gl2e')) {
  68. item.parent().addClass('noncompliant-item')
  69. item.parent().hide()
  70. } else {
  71. item.removeClass('noncompliant-item')
  72. item.hide()
  73. }
  74. }
  75.  
  76. this._onItemShow = (item) => {
  77. if (item.is('td.gl2e')) {
  78. item.parent().removeClass('noncompliant-item')
  79. item.parent().show()
  80. } else {
  81. item.removeClass('noncompliant-item')
  82. item.show()
  83. }
  84. }
  85. }
  86.  
  87. /**
  88. * @private
  89. */
  90. _setupFeatures()
  91. {
  92. this._configurationManager
  93. .addFlagField(UI_AUTO_NEXT_ON_OPEN_ALL_IMAGES, 'Automatically navigates to the next page after opening all images.')
  94. .addFlagField(UI_VISITED_HIGHLIGHT, 'Colours the visited gallery links black, to make them distinct.')
  95.  
  96. let otherTagSections = IS_GALLERY_PAGE ? $('#taglist') : null
  97.  
  98. this._addItemTagHighlights(UI_FAVOURITE_TAGS, otherTagSections, 'favourite-tag', 'Specify favourite tags to highlight.', 10)
  99. this._addItemTagHighlights(UI_DISLIKED_TAGS, otherTagSections, 'disliked-tag', 'Specify disliked tags to highlight.', 10)
  100. this._addItemTagBlacklistFilter(20)
  101. }
  102.  
  103. /**
  104. * @private
  105. */
  106. _setupUI()
  107. {
  108. let openGalleryPages = []
  109. if (IS_GALLERY_PAGE) {
  110. openGalleryPages = [
  111. this._uiGen.createSeparator(),
  112. this._uiGen.createFormButton(
  113. 'Open Gallery Images',
  114. 'Opens all images on current page of this gallery.',
  115. () => {
  116.  
  117. let images = $('div.gdtl a > img, div.gdtm a > img')
  118. let firstPage = images.first().attr('alt')
  119. let firstPageNumber = Number(firstPage)
  120. let paddedPageLength = firstPage.length
  121. let maxPages = firstPageNumber + images.length - 1
  122.  
  123. for (let page = maxPages; page >= firstPageNumber; page--) {
  124.  
  125. let paddedPage = page.toString().padStart(paddedPageLength, '0')
  126. window.open(images.filter('[alt="' + paddedPage + '"]').parent().attr('href'))
  127. }
  128.  
  129. if (this._getConfig(UI_AUTO_NEXT_ON_OPEN_ALL_IMAGES)) {
  130.  
  131. let page = window.location.href.split('=')[1]
  132. if (typeof page === 'undefined') {
  133. page = 0
  134. }
  135.  
  136. let maxPages = $('.ptt td').length - 2
  137. if (maxPages > 1 && page < (maxPages - 1)) {
  138.  
  139. let uri = window.location.href
  140. if (page === 0) {
  141. uri += '?p=1'
  142. } else {
  143. uri = uri.replace('?p=' + page++, '?p=' + page)
  144. }
  145. window.location = uri
  146. }
  147. }
  148. }),
  149. this._uiGen.createBreakSeparator(),
  150. this._configurationManager.createElement(UI_AUTO_NEXT_ON_OPEN_ALL_IMAGES),
  151. ]
  152. }
  153.  
  154. this._userInterface = [
  155. this._uiGen.createTabsSection(['Filters', 'Highlights', 'Global'], [
  156. this._uiGen.createTabPanel('Filters', true).append([
  157. this._configurationManager.createElement(OPTION_ENABLE_BLACKLIST),
  158. this._configurationManager.createElement(FILTER_TAG_BLACKLIST),
  159. // this._uiGen.createSeparator(),
  160. // this._configurationManager.createElement(OPTION_DISABLE_COMPLIANCE_VALIDATION),
  161. ]),
  162. this._uiGen.createTabPanel('Highlights').append([
  163. this._configurationManager.createElement(UI_FAVOURITE_TAGS),
  164. this._configurationManager.createElement(UI_DISLIKED_TAGS),
  165. ]),
  166. this._uiGen.createTabPanel('Global').append([
  167. this._configurationManager.createElement(UI_VISITED_HIGHLIGHT),
  168. this._configurationManager.createElement(OPTION_ALWAYS_SHOW_SETTINGS_PANE),
  169. this._uiGen.createSeparator(),
  170. this._createSettingsBackupRestoreFormActions(),
  171. ]),
  172. ]),
  173. this._uiGen.createStatisticsFormGroup(FILTER_TAG_BLACKLIST),
  174. ...openGalleryPages,
  175. this._uiGen.createSeparator(),
  176. // this._uiGen.createStatisticsTotalsGroup(),
  177. this._createSettingsFormActions(),
  178. this._uiGen.createSeparator(),
  179. this._uiGen.createStatusSection(),
  180. ]
  181. }
  182. }
  183.  
  184. (new EHentaiSearchAndUITweaks).init()