data-manager

process html, store and filter data

目前為 2024-09-13 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name data-manager
  3. // @namespace Violentmonkey Scripts
  4. // @version 1.34
  5. // @license MIT
  6. // @description process html, store and filter data
  7. // @author smartacephale
  8. // @match *://*/*
  9. // @grant unsafeWindow
  10. // @grant GM_addStyle
  11. // ==/UserScript==
  12.  
  13. class DataManager {
  14. constructor(rules, state) {
  15. this.rules = rules;
  16. this.state = state;
  17. this.data = new Map();
  18. this.setupFilters();
  19. this.lazyImgLoader = new unsafeWindow.bhutils.LazyImgLoader((target) => !this.isFiltered(target));
  20. }
  21.  
  22. dataFilters = {
  23. filterPublic: {
  24. tag: 'filtered-public',
  25. createFilter() {
  26. return (v) => [this.tag, !this.rules.IS_PRIVATE(v.element) && this.state.filterPublic];
  27. }
  28. },
  29. filterPrivate: {
  30. tag: 'filtered-private',
  31. createFilter() {
  32. return (v) => [this.tag, this.rules.IS_PRIVATE(v.element) && this.state.filterPrivate];
  33. }
  34. },
  35. filterDuration: {
  36. tag: 'filtered-duration',
  37. createFilter() {
  38. return (v) => {
  39. const notInRange = v.duration < this.state.filterDurationFrom || v.duration > this.state.filterDurationTo;
  40. return [this.tag, this.state.filterDuration && notInRange];
  41. }
  42. }
  43. },
  44. filterExclude: {
  45. tag: 'filtered-exclude',
  46. createFilter() {
  47. const tags = DataManager.filterDSLToRegex(this.state.filterExcludeWords);
  48. return (v) => {
  49. const containTags = tags.some(tag => tag.test(v.title));
  50. return [this.tag, this.state.filterExclude && containTags];
  51. }
  52. }
  53. },
  54. filterInclude: {
  55. tag: 'filtered-include',
  56. createFilter() {
  57. const tags = DataManager.filterDSLToRegex(this.state.filterIncludeWords);
  58. return (v) => {
  59. const containTagsNot = tags.some(tag => !tag.test(v.title));
  60. return [this.tag, this.state.filterInclude && containTagsNot];
  61. }
  62. }
  63. }
  64. }
  65.  
  66. static filterDSLToRegex(str) {
  67. const toFullWord = w => `(^|\ )${w}($|\ )`;
  68. const str_ = str.replace(/f\:(\w+)/g, (_, w) => toFullWord(w));
  69. return unsafeWindow.bhutils.stringToWords(str_).map(expr => new RegExp(expr, 'i'));
  70. }
  71.  
  72. setupFilters() {
  73. Object.keys(this.dataFilters).forEach(k => {
  74. if (!Object.hasOwn(this.state, k)) {
  75. delete this.dataFilters[k];
  76. } else {
  77. Object.assign(this.dataFilters[k], { state: this.state, rules: this.rules });
  78. GM_addStyle(`${this.dataFilters[k].tag} { display: none !important; }`);
  79. }
  80. });
  81. }
  82.  
  83. isFiltered(el) {
  84. return el.className.includes('filtered');
  85. }
  86.  
  87. applyFilters = (filters, offset = 0) => {
  88. const filtersToApply = Object.keys(filters)
  89. .filter(k => Object.hasOwn(this.dataFilters, k))
  90. .map(k => this.dataFilters[k].createFilter());
  91.  
  92. if (filtersToApply.length === 0) return;
  93.  
  94. let offset_counter = 1;
  95. for (const v of this.data.values()) {
  96. if (++offset_counter > offset) {
  97. for (const f of filtersToApply) {
  98. const [tag, condition] = f(v);
  99. v.element.classList.toggle(tag, condition);
  100. }
  101. }
  102. }
  103. }
  104.  
  105. filterAll = (offset) => {
  106. const filters = Object.assign({}, ...Object.keys(this.dataFilters).map(f => ({ [f]: this.state[f] })));
  107. this.applyFilters(filters, offset);
  108. }
  109.  
  110. handleLoadedHTML = (html, container, removeDuplicates = false, shouldLazify = true) => {
  111. const thumbs = this.rules.GET_THUMBS(html);
  112. const data_offset = this.data.size;
  113.  
  114. for (const thumbElement of thumbs) {
  115. const url = this.rules.THUMB_URL(thumbElement);
  116. if (!url || this.data.has(url)) {
  117. if (removeDuplicates) thumbElement.remove();
  118. continue;
  119. }
  120.  
  121. const { title, duration } = this.rules.THUMB_DATA(thumbElement);
  122. this.data.set(url, { element: thumbElement, duration, title });
  123.  
  124. if (shouldLazify) {
  125. const { img, imgSrc } = this.rules.THUMB_IMG_DATA(thumbElement);
  126. this.lazyImgLoader.lazify(thumbElement, img, imgSrc);
  127. }
  128.  
  129. const parent = container || this.rules.CONTAINER;
  130. if (!parent.contains(thumbElement)) parent.appendChild(thumbElement);
  131. }
  132.  
  133. this.filterAll(data_offset);
  134. };
  135. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址