pervert-monkey 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +62 -0
  3. package/dist/core/pervertmonkey.core.es.d.ts +391 -0
  4. package/dist/core/pervertmonkey.core.es.js +8497 -0
  5. package/dist/core/pervertmonkey.core.es.js.map +1 -0
  6. package/dist/core/pervertmonkey.core.umd.js +8500 -0
  7. package/dist/core/pervertmonkey.core.umd.js.map +1 -0
  8. package/dist/userscripts/3hentai.user.js +1176 -0
  9. package/dist/userscripts/camgirlfinder.user.js +68 -0
  10. package/dist/userscripts/camwhores.user.js +1602 -0
  11. package/dist/userscripts/e-hentai.user.js +1212 -0
  12. package/dist/userscripts/ebalka.user.js +1231 -0
  13. package/dist/userscripts/eporner.user.js +1265 -0
  14. package/dist/userscripts/erome.user.js +1245 -0
  15. package/dist/userscripts/eroprofile.user.js +1194 -0
  16. package/dist/userscripts/javhdporn.user.js +1178 -0
  17. package/dist/userscripts/missav.user.js +1182 -0
  18. package/dist/userscripts/motherless.user.js +1380 -0
  19. package/dist/userscripts/namethatporn.user.js +1218 -0
  20. package/dist/userscripts/nhentai.user.js +1262 -0
  21. package/dist/userscripts/pornhub.user.js +1199 -0
  22. package/dist/userscripts/spankbang.user.js +1239 -0
  23. package/dist/userscripts/xhamster.user.js +1374 -0
  24. package/dist/userscripts/xvideos.user.js +1254 -0
  25. package/package.json +54 -0
  26. package/src/core/data-control/data-filter.ts +143 -0
  27. package/src/core/data-control/data-manager.ts +144 -0
  28. package/src/core/data-control/index.ts +2 -0
  29. package/src/core/infinite-scroll/index.ts +143 -0
  30. package/src/core/jabroni-config/default-scheme.ts +97 -0
  31. package/src/core/jabroni-config/default-store.ts +9 -0
  32. package/src/core/pagination-parsing/index.ts +55 -0
  33. package/src/core/pagination-parsing/pagination-strategies/PaginationStrategy.ts +44 -0
  34. package/src/core/pagination-parsing/pagination-strategies/PaginationStrategyDataParams.ts +66 -0
  35. package/src/core/pagination-parsing/pagination-strategies/PaginationStrategyPathnameParams.ts +77 -0
  36. package/src/core/pagination-parsing/pagination-strategies/PaginationStrategySearchParams.ts +56 -0
  37. package/src/core/pagination-parsing/pagination-strategies/index.ts +4 -0
  38. package/src/core/pagination-parsing/pagination-utils/index.ts +84 -0
  39. package/src/core/rules/index.ts +385 -0
  40. package/src/index.ts +42 -0
  41. package/src/types/index.ts +7 -0
  42. package/src/userscripts/ascii-logos.js +468 -0
  43. package/src/userscripts/index.ts +1 -0
  44. package/src/userscripts/meta.json +11 -0
  45. package/src/userscripts/scripts/3hentai.ts +20 -0
  46. package/src/userscripts/scripts/camgirlfinder.ts +68 -0
  47. package/src/userscripts/scripts/camwhores.ts +382 -0
  48. package/src/userscripts/scripts/e-hentai.ts +68 -0
  49. package/src/userscripts/scripts/ebalka.ts +58 -0
  50. package/src/userscripts/scripts/eporner.ts +90 -0
  51. package/src/userscripts/scripts/erome.ts +105 -0
  52. package/src/userscripts/scripts/eroprofile.ts +38 -0
  53. package/src/userscripts/scripts/javhdporn.ts +24 -0
  54. package/src/userscripts/scripts/missav.ts +28 -0
  55. package/src/userscripts/scripts/motherless.ts +222 -0
  56. package/src/userscripts/scripts/namethatporn.ts +68 -0
  57. package/src/userscripts/scripts/nhentai.ts +135 -0
  58. package/src/userscripts/scripts/pornhub.ts +53 -0
  59. package/src/userscripts/scripts/spankbang.ts +61 -0
  60. package/src/userscripts/scripts/thisvid.ts +716 -0
  61. package/src/userscripts/scripts/xhamster.ts +179 -0
  62. package/src/userscripts/scripts/xvideos.ts +83 -0
  63. package/src/utils/arrays/index.ts +15 -0
  64. package/src/utils/async/index.ts +3 -0
  65. package/src/utils/dom/dom-observers.ts +76 -0
  66. package/src/utils/dom/index.ts +156 -0
  67. package/src/utils/events/index.ts +2 -0
  68. package/src/utils/events/on-pointer-over-and-leave.ts +35 -0
  69. package/src/utils/events/tick.ts +27 -0
  70. package/src/utils/fetch/index.ts +37 -0
  71. package/src/utils/math/index.ts +3 -0
  72. package/src/utils/objects/index.ts +9 -0
  73. package/src/utils/objects/memoize.ts +25 -0
  74. package/src/utils/observers/index.ts +44 -0
  75. package/src/utils/observers/lazy-image-loader.ts +27 -0
  76. package/src/utils/parsers/index.ts +30 -0
  77. package/src/utils/parsers/time-parser.ts +28 -0
  78. package/src/utils/strings/index.ts +10 -0
  79. package/src/utils/strings/regexes.ts +35 -0
  80. package/src/vite-env.d.ts +4 -0
@@ -0,0 +1,1265 @@
1
+ // ==UserScript==
2
+ // @name Eporner PervertMonkey
3
+ // @namespace pervertmonkey
4
+ // @version 2.0.1
5
+ // @author violent-orangutan
6
+ // @description Infinite scroll [optional], Filter by Title, Duration and HD
7
+ // @license MIT
8
+ // @icon https://www.google.com/s2/favicons?sz=64&domain=eporner.com
9
+ // @homepage https://github.com/smartacephale/sleazy-fork
10
+ // @homepageURL https://github.com/smartacephale/sleazy-fork
11
+ // @source github:smartacephale/sleazy-fork
12
+ // @supportURL https://github.com/smartacephale/sleazy-fork/issues
13
+ // @match https://*.eporner.com/*
14
+ // @match https://*.eporner.*/*
15
+ // @require https://cdn.jsdelivr.net/npm/jabroni-outfit@2.1.1/dist/jabroni-outfit.umd.js
16
+ // @grant GM_addStyle
17
+ // @grant unsafeWindow
18
+ // @run-at document-idle
19
+ // ==/UserScript==
20
+
21
+ (function () {
22
+ 'use strict';
23
+
24
+ (function (jabroniOutfit) {
25
+
26
+ var _GM_addStyle = (() => typeof GM_addStyle != "undefined" ? GM_addStyle : undefined)();
27
+ var _unsafeWindow = (() => typeof unsafeWindow != "undefined" ? unsafeWindow : undefined)();
28
+
29
+ function splitWith(s, c = ",") {
30
+ return s.split(c).map((s2) => s2.trim()).filter(Boolean);
31
+ }
32
+ function sanitizeStr(s) {
33
+ return s?.replace(/\n|\t/g, " ").replace(/ {2,}/g, " ").trim() || "";
34
+ }
35
+
36
+ function waitForElementToDisappear(observable, callback) {
37
+ const observer = new MutationObserver((_mutations) => {
38
+ if (!observable.isConnected) {
39
+ observer.disconnect();
40
+ callback();
41
+ }
42
+ });
43
+ observer.observe(document.body, { childList: true, subtree: true });
44
+ return observer;
45
+ }
46
+
47
+ function querySelectorLast(root = document, selector) {
48
+ const nodes = root.querySelectorAll(selector);
49
+ return nodes.length > 0 ? nodes[nodes.length - 1] : void 0;
50
+ }
51
+ function querySelectorText(e, selector) {
52
+ if (typeof selector !== "string") return "";
53
+ const text = e.querySelector(selector)?.innerText || "";
54
+ return sanitizeStr(text);
55
+ }
56
+ function parseHtml(html) {
57
+ const parsed = new DOMParser().parseFromString(html, "text/html").body;
58
+ if (parsed.children.length > 1) return parsed;
59
+ return parsed.firstElementChild;
60
+ }
61
+ function removeClassesAndDataAttributes(element, keyword) {
62
+ Array.from(element.classList).forEach((className) => {
63
+ if (className.includes(keyword)) {
64
+ element.classList.remove(className);
65
+ }
66
+ });
67
+ Array.from(element.attributes).forEach((attr) => {
68
+ if (attr.name.startsWith("data-") && attr.name.includes(keyword)) {
69
+ element.removeAttribute(attr.name);
70
+ }
71
+ });
72
+ }
73
+ function getCommonParents(elements) {
74
+ const parents = Array.from(elements).map((el) => el.parentElement).filter((parent) => parent !== null);
75
+ return [...new Set(parents)];
76
+ }
77
+ function checkHomogenity(a, b, options) {
78
+ if (!a || !b) return false;
79
+ if (options.id) {
80
+ if (a.id !== b.id) return false;
81
+ }
82
+ if (options.className) {
83
+ const ca = a.className;
84
+ const cb = b.className;
85
+ if (!(ca.length > cb.length ? ca.includes(cb) : cb.includes(ca))) {
86
+ return false;
87
+ }
88
+ }
89
+ return true;
90
+ }
91
+
92
+ function formatTimeToHHMMSS(timeStr) {
93
+ const pad = (num) => num.toString().padStart(2, "0");
94
+ const h = timeStr.match(/(\d+)\s*h/)?.[1] || "0";
95
+ const m = timeStr.match(/(\d+)\s*mi?n/)?.[1] || "0";
96
+ const s = timeStr.match(/(\d+)\s*sec/)?.[1] || "0";
97
+ return `${pad(+h)}:${pad(+m)}:${pad(+s)}`;
98
+ }
99
+ function timeToSeconds(timeStr) {
100
+ const normalized = /[a-zA-Z]/.test(timeStr) ? formatTimeToHHMMSS(timeStr) : timeStr;
101
+ return normalized.split(":").reverse().reduce((total, unit, index) => total + parseInt(unit, 10) * 60 ** index, 0);
102
+ }
103
+
104
+ function parseDataParams(str) {
105
+ const paramsStr = decodeURI(str.trim()).split(";");
106
+ return paramsStr.reduce(
107
+ (acc, s) => {
108
+ const parsed = s.match(/([+\w]+):([\w\- ]+)?/);
109
+ if (parsed) {
110
+ const [, key, value] = parsed;
111
+ if (value) {
112
+ key.split("+").forEach((p) => {
113
+ acc[p] = value;
114
+ });
115
+ }
116
+ }
117
+ return acc;
118
+ },
119
+ {}
120
+ );
121
+ }
122
+
123
+ function memoize(fn) {
124
+ const cache = new Map();
125
+ const memoizedFunction = ((...args) => {
126
+ const key = JSON.stringify(args);
127
+ if (cache.has(key)) {
128
+ return cache.get(key);
129
+ }
130
+ const result = fn(...args);
131
+ cache.set(key, result);
132
+ return result;
133
+ });
134
+ return memoizedFunction;
135
+ }
136
+
137
+ class RegexFilter {
138
+ regexes;
139
+ constructor(str, flags = "gi") {
140
+ this.regexes = memoize(this.compileSearchRegex)(str, flags);
141
+ }
142
+ compileSearchRegex(str, flags) {
143
+ try {
144
+ if (str.startsWith("r:")) return [new RegExp(str.slice(2), flags)];
145
+ const regexes = splitWith(str).map(
146
+ (s) => s.replace(/f:(\w+)/g, (_, w) => `(^|\\ |,)${w}($|\\ |,)`)
147
+ ).map((_) => new RegExp(_, flags));
148
+ return regexes;
149
+ } catch (_) {
150
+ return [];
151
+ }
152
+ }
153
+ hasEvery(str) {
154
+ return this.regexes.every((r) => r.test(str));
155
+ }
156
+ hasNone(str) {
157
+ return this.regexes.every((r) => !r.test(str));
158
+ }
159
+ }
160
+
161
+ class DataFilter {
162
+ constructor(rules) {
163
+ this.rules = rules;
164
+ this.registerFilters(rules.customDataSelectorFns);
165
+ this.applyCSSFilters();
166
+ }
167
+ filters = new Map();
168
+ static isFiltered(el) {
169
+ return el.className.includes("filter-");
170
+ }
171
+ applyCSSFilters(wrapper) {
172
+ this.filters.forEach((_, name) => {
173
+ const cssRule = `.filter-${name} { display: none !important; }`;
174
+ if (wrapper) {
175
+ _GM_addStyle(wrapper(cssRule));
176
+ } else {
177
+ _GM_addStyle(cssRule);
178
+ }
179
+ });
180
+ }
181
+ customDataSelectorFns = {};
182
+ registerFilters(customFilters) {
183
+ customFilters.forEach((o) => {
184
+ if (typeof o === "string") {
185
+ this.customDataSelectorFns[o] = DataFilter.customDataSelectorFnsDefault[o];
186
+ this.registerFilter(o);
187
+ } else {
188
+ const k = Object.keys(o)[0];
189
+ this.customDataSelectorFns[k] = o[k];
190
+ this.registerFilter(k);
191
+ }
192
+ });
193
+ }
194
+ customSelectorParser(name, selector) {
195
+ if ("handle" in selector) {
196
+ return selector;
197
+ } else {
198
+ return { handle: selector, deps: [name] };
199
+ }
200
+ }
201
+ registerFilter(customSelectorName) {
202
+ const handler = this.customSelectorParser(
203
+ customSelectorName,
204
+ this.customDataSelectorFns[customSelectorName]
205
+ );
206
+ const tag = `filter-${customSelectorName}`;
207
+ [customSelectorName, ...handler.deps || []]?.forEach((name) => {
208
+ Object.assign(this.filterMapping, { [name]: customSelectorName });
209
+ });
210
+ const fn = () => {
211
+ const preDefined = handler.$preDefine?.(this.rules.store.state);
212
+ return (v) => {
213
+ const condition = handler.handle(v, this.rules.store.state, preDefined);
214
+ return {
215
+ condition,
216
+ tag
217
+ };
218
+ };
219
+ };
220
+ this.filters.set(customSelectorName, fn);
221
+ }
222
+ filterMapping = {};
223
+ selectFilters(filters) {
224
+ const selectedFilters = Object.keys(filters).filter((k) => k in this.filterMapping).map((k) => this.filterMapping[k]).map((k) => this.filters.get(k));
225
+ return selectedFilters;
226
+ }
227
+ static customDataSelectorFnsDefault = {
228
+ filterDuration: {
229
+ handle(el, state, notInRange) {
230
+ return state.filterDuration && notInRange(el.duration);
231
+ },
232
+ $preDefine: (state) => {
233
+ const from = state.filterDurationFrom;
234
+ const to = state.filterDurationTo;
235
+ function notInRange(d) {
236
+ return d < from || d > to;
237
+ }
238
+ return notInRange;
239
+ },
240
+ deps: ["filterDurationFrom", "filterDurationTo"]
241
+ },
242
+ filterExclude: {
243
+ handle(el, state, searchFilter) {
244
+ if (!state.filterExclude) return false;
245
+ return !searchFilter.hasNone(el.title);
246
+ },
247
+ $preDefine: (state) => new RegexFilter(state.filterExcludeWords),
248
+ deps: ["filterExcludeWords"]
249
+ },
250
+ filterInclude: {
251
+ handle(el, state, searchFilter) {
252
+ if (!state.filterInclude) return false;
253
+ return !searchFilter.hasEvery(el.title);
254
+ },
255
+ $preDefine: (state) => new RegexFilter(state.filterIncludeWords),
256
+ deps: ["filterIncludeWords"]
257
+ }
258
+ };
259
+ }
260
+
261
+ class LazyImgLoader {
262
+ lazyImgObserver;
263
+ attributeName = "data-lazy-load";
264
+ constructor(shouldDelazify) {
265
+ this.lazyImgObserver = new Observer((target) => {
266
+ if (shouldDelazify(target)) {
267
+ this.delazify(target);
268
+ }
269
+ });
270
+ }
271
+ lazify(_target, img, imgSrc) {
272
+ if (!img || !imgSrc) return;
273
+ img.setAttribute(this.attributeName, imgSrc);
274
+ img.src = "";
275
+ this.lazyImgObserver.observe(img);
276
+ }
277
+ delazify = (target) => {
278
+ this.lazyImgObserver.observer.unobserve(target);
279
+ target.src = target.getAttribute(this.attributeName);
280
+ target.removeAttribute(this.attributeName);
281
+ };
282
+ }
283
+
284
+ class Observer {
285
+ constructor(callback) {
286
+ this.callback = callback;
287
+ this.observer = new IntersectionObserver(this.handleIntersection.bind(this));
288
+ }
289
+ observer;
290
+ timeout;
291
+ observe(target) {
292
+ this.observer.observe(target);
293
+ }
294
+ throttle(target, throttleTime) {
295
+ this.observer.unobserve(target);
296
+ this.timeout = window.setTimeout(() => this.observer.observe(target), throttleTime);
297
+ }
298
+ handleIntersection(entries) {
299
+ for (const entry of entries) {
300
+ if (entry.isIntersecting) {
301
+ this.callback(entry.target);
302
+ }
303
+ }
304
+ }
305
+ dispose() {
306
+ if (this.timeout) clearTimeout(this.timeout);
307
+ this.observer.disconnect();
308
+ }
309
+ static observeWhile(target, callback, throttleTime) {
310
+ const observer_ = new Observer(async (target2) => {
311
+ const condition = await callback();
312
+ if (condition) observer_.throttle(target2, throttleTime);
313
+ });
314
+ observer_.observe(target);
315
+ return observer_;
316
+ }
317
+ }
318
+
319
+ class DataManager {
320
+ constructor(rules) {
321
+ this.rules = rules;
322
+ this.dataFilter = new DataFilter(this.rules);
323
+ }
324
+ data = new Map();
325
+ lazyImgLoader = new LazyImgLoader(
326
+ (target) => !DataFilter.isFiltered(target)
327
+ );
328
+ dataFilter;
329
+ applyFilters = async (filters = {}, offset = 0) => {
330
+ const filtersToApply = this.dataFilter.selectFilters(filters);
331
+ if (filtersToApply.length === 0) return;
332
+ const iterator = this.data.values().drop(offset);
333
+ let finished = false;
334
+ await new Promise((resolve) => {
335
+ function runBatch(deadline) {
336
+ const updates = [];
337
+ while (deadline.timeRemaining() > 0) {
338
+ const { value, done } = iterator.next();
339
+ finished = !!done;
340
+ if (done) break;
341
+ for (const f of filtersToApply) {
342
+ const { tag, condition } = f()(value);
343
+ updates.push({ e: value.element, tag, condition });
344
+ }
345
+ }
346
+ if (updates.length > 0) {
347
+ requestAnimationFrame(() => {
348
+ updates.forEach((u) => {
349
+ u.e.classList.toggle(u.tag, u.condition);
350
+ });
351
+ });
352
+ }
353
+ if (!finished) {
354
+ requestIdleCallback(runBatch);
355
+ } else {
356
+ resolve(true);
357
+ }
358
+ }
359
+ requestIdleCallback(runBatch);
360
+ });
361
+ };
362
+ filterAll = async (offset) => {
363
+ const keys = Array.from(this.dataFilter.filters.keys());
364
+ const filters = Object.fromEntries(
365
+ keys.map((k) => [k, this.rules.store.state[k]])
366
+ );
367
+ await this.applyFilters(filters, offset);
368
+ };
369
+ parseDataParentHomogenity;
370
+ parseData = (html, container, removeDuplicates = false, shouldLazify = true) => {
371
+ const thumbs = this.rules.getThumbs(html);
372
+ const dataOffset = this.data.size;
373
+ const fragment = document.createDocumentFragment();
374
+ const parent = container || this.rules.container;
375
+ const homogenity = !!this.parseDataParentHomogenity;
376
+ for (const thumbElement of thumbs) {
377
+ const url = this.rules.getThumbUrl(thumbElement);
378
+ if (!url || this.data.has(url) || parent !== container && parent?.contains(thumbElement) || homogenity && !checkHomogenity(
379
+ parent,
380
+ thumbElement.parentElement,
381
+ this.parseDataParentHomogenity
382
+ )) {
383
+ if (removeDuplicates) thumbElement.remove();
384
+ continue;
385
+ }
386
+ const data = this.rules.getThumbData(thumbElement);
387
+ this.data.set(url, { element: thumbElement, ...data });
388
+ if (shouldLazify) {
389
+ const { img, imgSrc } = this.rules.getThumbImgData(thumbElement);
390
+ this.lazyImgLoader.lazify(thumbElement, img, imgSrc);
391
+ }
392
+ fragment.append(thumbElement);
393
+ }
394
+ this.filterAll(dataOffset).then(() => {
395
+ requestAnimationFrame(() => {
396
+ parent.appendChild(fragment);
397
+ });
398
+ });
399
+ };
400
+ sortBy(key, direction = true) {
401
+ if (this.data.size < 2) return;
402
+ let sorted = this.data.values().toArray().sort((a, b) => {
403
+ return a[key] - b[key];
404
+ });
405
+ if (!direction) sorted = sorted.reverse();
406
+ const container = sorted[0].element.parentElement;
407
+ container.style.visibility = "hidden";
408
+ sorted.forEach((s) => {
409
+ container.append(s.element);
410
+ });
411
+ container.style.visibility = "visible";
412
+ }
413
+ }
414
+
415
+ function wait(milliseconds) {
416
+ return new Promise((resolve) => setTimeout(resolve, milliseconds));
417
+ }
418
+
419
+ const MOBILE_UA = {
420
+ "User-Agent": [
421
+ "Mozilla/5.0 (Linux; Android 10; K)",
422
+ "AppleWebKit/537.36 (KHTML, like Gecko)",
423
+ "Chrome/114.0.0.0 Mobile Safari/537.36"
424
+ ].join(" ")
425
+ };
426
+ async function fetchWith(input, options) {
427
+ const requestInit = options.init || {};
428
+ if (options.mobile) {
429
+ Object.assign(requestInit, { headers: new Headers(MOBILE_UA) });
430
+ }
431
+ const r = await fetch(input, requestInit).then((r2) => r2);
432
+ return parseHtml(await r.text());
433
+ }
434
+ const fetchHtml = (input) => fetchWith(input, { });
435
+
436
+ class InfiniteScroller {
437
+ enabled = true;
438
+ paginationOffset = 1;
439
+ parseData;
440
+ rules;
441
+ observer;
442
+ paginationGenerator;
443
+ constructor(options) {
444
+ this.rules = options.rules;
445
+ this.paginationOffset = this.rules.paginationStrategy.getPaginationOffset();
446
+ Object.assign(this, options);
447
+ if (this.rules.getPaginationData) {
448
+ this.getPaginationData = this.rules.getPaginationData;
449
+ }
450
+ this.paginationGenerator = this.rules.customGenerator || InfiniteScroller.generatorForPaginationStrategy(this.rules.paginationStrategy);
451
+ this.setObserver(this.rules.observable);
452
+ this.setAutoScroll();
453
+ }
454
+ dispose() {
455
+ if (this.observer) this.observer.dispose();
456
+ }
457
+ setObserver(observable) {
458
+ if (this.observer) this.observer.dispose();
459
+ this.observer = Observer.observeWhile(
460
+ observable,
461
+ this.generatorConsumer,
462
+ this.rules.store.state.delay
463
+ );
464
+ return this;
465
+ }
466
+ onScrollCBs = [];
467
+ onScroll(callback, initCall = false) {
468
+ if (initCall) callback(this);
469
+ this.onScrollCBs.push(callback);
470
+ return this;
471
+ }
472
+ _onScroll() {
473
+ this.onScrollCBs.forEach((cb) => {
474
+ cb(this);
475
+ });
476
+ }
477
+ setAutoScroll() {
478
+ const autoScrollWrapper = async () => {
479
+ if (this.rules.store.state.autoScroll) {
480
+ await wait(this.rules.store.state.delay);
481
+ await this.generatorConsumer();
482
+ await autoScrollWrapper();
483
+ }
484
+ };
485
+ autoScrollWrapper();
486
+ this.rules.store.stateSubject.subscribe((type) => {
487
+ if (type?.autoScroll) {
488
+ autoScrollWrapper();
489
+ }
490
+ });
491
+ }
492
+ generatorConsumer = async () => {
493
+ if (!this.enabled) return false;
494
+ const {
495
+ value: { url, offset },
496
+ done
497
+ } = await this.paginationGenerator.next();
498
+ if (!done && url) {
499
+ await this.doScroll(url, offset);
500
+ }
501
+ return !done;
502
+ };
503
+ async getPaginationData(url) {
504
+ return await fetchHtml(url);
505
+ }
506
+ async doScroll(url, offset) {
507
+ const nextPageHtml = await this.getPaginationData(url);
508
+ const prevScrollPos = document.documentElement.scrollTop;
509
+ this.paginationOffset = Math.max(this.paginationOffset, offset);
510
+ this.parseData?.(nextPageHtml);
511
+ this._onScroll();
512
+ window.scrollTo(0, prevScrollPos);
513
+ if (this.rules.store.state.writeHistory) {
514
+ history.replaceState({}, "", url);
515
+ }
516
+ }
517
+ static async *generatorForPaginationStrategy(pstrategy) {
518
+ const _offset = pstrategy.getPaginationOffset();
519
+ const end = pstrategy.getPaginationLast();
520
+ const urlGenerator = pstrategy.getPaginationUrlGenerator();
521
+ for (let offset = _offset; offset <= end; offset++) {
522
+ const url = await urlGenerator(offset);
523
+ yield { url, offset };
524
+ }
525
+ }
526
+ static create(rules) {
527
+ const enabled = rules.store.state.infiniteScrollEnabled;
528
+ rules.store.state.$paginationLast = rules.paginationStrategy.getPaginationLast();
529
+ const infiniteScroller = new InfiniteScroller({
530
+ enabled,
531
+ parseData: rules.dataManager.parseData,
532
+ rules
533
+ }).onScroll(({ paginationOffset }) => {
534
+ rules.store.state.$paginationOffset = paginationOffset;
535
+ }, true);
536
+ rules.store.stateSubject.subscribe(() => {
537
+ infiniteScroller.enabled = rules.store.state.infiniteScrollEnabled;
538
+ });
539
+ return infiniteScroller;
540
+ }
541
+ }
542
+
543
+ const DefaultScheme = [
544
+ {
545
+ title: "Text Filter",
546
+ collapsed: true,
547
+ content: [
548
+ { filterExclude: false, label: "exclude" },
549
+ {
550
+ filterExcludeWords: "",
551
+ label: "keywords",
552
+ watch: "filterExclude",
553
+ placeholder: "word, f:full_word, r:RegEx..."
554
+ },
555
+ { filterInclude: false, label: "include" },
556
+ {
557
+ filterIncludeWords: "",
558
+ label: "keywords",
559
+ watch: "filterInclude",
560
+ placeholder: "word, f:full_word, r:RegEx..."
561
+ }
562
+ ]
563
+ },
564
+ {
565
+ title: "Duration Filter",
566
+ collapsed: true,
567
+ content: [
568
+ { filterDuration: false, label: "enable" },
569
+ {
570
+ filterDurationFrom: 0,
571
+ watch: "filterDuration",
572
+ label: "from",
573
+ type: "time"
574
+ },
575
+ {
576
+ filterDurationTo: 600,
577
+ watch: "filterDuration",
578
+ label: "to",
579
+ type: "time"
580
+ }
581
+ ]
582
+ },
583
+ {
584
+ title: "Sort By",
585
+ content: [
586
+ {
587
+ "sort by views": () => {
588
+ }
589
+ },
590
+ {
591
+ "sort by duration": () => {
592
+ }
593
+ }
594
+ ]
595
+ },
596
+ {
597
+ title: "Privacy Filter",
598
+ content: [
599
+ { filterPrivate: false, label: "private" },
600
+ { filterPublic: false, label: "public" },
601
+ { "check access 🔓": () => {
602
+ } }
603
+ ]
604
+ },
605
+ {
606
+ title: "Advanced",
607
+ content: [
608
+ {
609
+ infiniteScrollEnabled: true,
610
+ label: "infinite scroll"
611
+ },
612
+ {
613
+ autoScroll: false,
614
+ label: "auto scroll"
615
+ },
616
+ {
617
+ delay: 250,
618
+ label: "scroll delay"
619
+ },
620
+ {
621
+ writeHistory: false,
622
+ label: "write history"
623
+ }
624
+ ]
625
+ },
626
+ {
627
+ title: "Badge",
628
+ content: [
629
+ {
630
+ text: "return `${state.$paginationOffset}/${state.$paginationLast}`",
631
+ vif: "return state.$paginationLast > 1"
632
+ }
633
+ ]
634
+ }
635
+ ];
636
+
637
+ const StoreStateDefault = {
638
+ enabled: true,
639
+ collapsed: false,
640
+ darkmode: true,
641
+ $paginationLast: 1,
642
+ $paginationOffset: 1
643
+ };
644
+
645
+ var Pe=Object.defineProperty;var a=(e,t)=>Pe(e,"name",{value:t,configurable:true});var P=class{type=3;name="";prefix="";value="";suffix="";modifier=3;constructor(t,r,n,c,l,f){this.type=t,this.name=r,this.prefix=n,this.value=c,this.suffix=l,this.modifier=f;}hasCustomName(){return this.name!==""&&typeof this.name!="number"}};a(P,"Part");var Re=/[$_\p{ID_Start}]/u,Ee=/[$_\u200C\u200D\p{ID_Continue}]/u,v=".*";function Oe(e,t){return (t?/^[\x00-\xFF]*$/:/^[\x00-\x7F]*$/).test(e)}a(Oe,"isASCII");function D(e,t=false){let r=[],n=0;for(;n<e.length;){let c=e[n],l=a(function(f){if(!t)throw new TypeError(f);r.push({type:"INVALID_CHAR",index:n,value:e[n++]});},"ErrorOrInvalid");if(c==="*"){r.push({type:"ASTERISK",index:n,value:e[n++]});continue}if(c==="+"||c==="?"){r.push({type:"OTHER_MODIFIER",index:n,value:e[n++]});continue}if(c==="\\"){r.push({type:"ESCAPED_CHAR",index:n++,value:e[n++]});continue}if(c==="{"){r.push({type:"OPEN",index:n,value:e[n++]});continue}if(c==="}"){r.push({type:"CLOSE",index:n,value:e[n++]});continue}if(c===":"){let f="",s=n+1;for(;s<e.length;){let i=e.substr(s,1);if(s===n+1&&Re.test(i)||s!==n+1&&Ee.test(i)){f+=e[s++];continue}break}if(!f){l(`Missing parameter name at ${n}`);continue}r.push({type:"NAME",index:n,value:f}),n=s;continue}if(c==="("){let f=1,s="",i=n+1,o=false;if(e[i]==="?"){l(`Pattern cannot start with "?" at ${i}`);continue}for(;i<e.length;){if(!Oe(e[i],false)){l(`Invalid character '${e[i]}' at ${i}.`),o=true;break}if(e[i]==="\\"){s+=e[i++]+e[i++];continue}if(e[i]===")"){if(f--,f===0){i++;break}}else if(e[i]==="("&&(f++,e[i+1]!=="?")){l(`Capturing groups are not allowed at ${i}`),o=true;break}s+=e[i++];}if(o)continue;if(f){l(`Unbalanced pattern at ${n}`);continue}if(!s){l(`Missing pattern at ${n}`);continue}r.push({type:"REGEX",index:n,value:s}),n=i;continue}r.push({type:"CHAR",index:n,value:e[n++]});}return r.push({type:"END",index:n,value:""}),r}a(D,"lexer");function F(e,t={}){let r=D(e);t.delimiter??="/#?",t.prefixes??="./";let n=`[^${x(t.delimiter)}]+?`,c=[],l=0,f=0,i=new Set,o=a(u=>{if(f<r.length&&r[f].type===u)return r[f++].value},"tryConsume"),h=a(()=>o("OTHER_MODIFIER")??o("ASTERISK"),"tryConsumeModifier"),p=a(u=>{let d=o(u);if(d!==void 0)return d;let{type:g,index:y}=r[f];throw new TypeError(`Unexpected ${g} at ${y}, expected ${u}`)},"mustConsume"),A=a(()=>{let u="",d;for(;d=o("CHAR")??o("ESCAPED_CHAR");)u+=d;return u},"consumeText"),xe=a(u=>u,"DefaultEncodePart"),N=t.encodePart||xe,H="",$=a(u=>{H+=u;},"appendToPendingFixedValue"),M=a(()=>{H.length&&(c.push(new P(3,"","",N(H),"",3)),H="");},"maybeAddPartFromPendingFixedValue"),X=a((u,d,g,y,Z)=>{let m=3;switch(Z){case "?":m=1;break;case "*":m=0;break;case "+":m=2;break}if(!d&&!g&&m===3){$(u);return}if(M(),!d&&!g){if(!u)return;c.push(new P(3,"","",N(u),"",m));return}let S;g?g==="*"?S=v:S=g:S=n;let k=2;S===n?(k=1,S=""):S===v&&(k=0,S="");let E;if(d?E=d:g&&(E=l++),i.has(E))throw new TypeError(`Duplicate name '${E}'.`);i.add(E),c.push(new P(k,E,N(u),S,N(y),m));},"addPart");for(;f<r.length;){let u=o("CHAR"),d=o("NAME"),g=o("REGEX");if(!d&&!g&&(g=o("ASTERISK")),d||g){let m=u??"";t.prefixes.indexOf(m)===-1&&($(m),m=""),M();let S=h();X(m,d,g,"",S);continue}let y=u??o("ESCAPED_CHAR");if(y){$(y);continue}if(o("OPEN")){let m=A(),S=o("NAME"),k=o("REGEX");!S&&!k&&(k=o("ASTERISK"));let E=A();p("CLOSE");let be=h();X(m,S,k,E,be);continue}M(),p("END");}return c}a(F,"parse");function x(e){return e.replace(/([.+*?^${}()[\]|/\\])/g,"\\$1")}a(x,"escapeString");function B(e){return e&&e.ignoreCase?"ui":"u"}a(B,"flags");function q(e,t,r){return W(F(e,r),t,r)}a(q,"stringToRegexp");function T(e){switch(e){case 0:return "*";case 1:return "?";case 2:return "+";case 3:return ""}}a(T,"modifierToString");function W(e,t,r={}){r.delimiter??="/#?",r.prefixes??="./",r.sensitive??=false,r.strict??=false,r.end??=true,r.start??=true,r.endsWith="";let n=r.start?"^":"";for(let s of e){if(s.type===3){s.modifier===3?n+=x(s.value):n+=`(?:${x(s.value)})${T(s.modifier)}`;continue}t&&t.push(s.name);let i=`[^${x(r.delimiter)}]+?`,o=s.value;if(s.type===1?o=i:s.type===0&&(o=v),!s.prefix.length&&!s.suffix.length){s.modifier===3||s.modifier===1?n+=`(${o})${T(s.modifier)}`:n+=`((?:${o})${T(s.modifier)})`;continue}if(s.modifier===3||s.modifier===1){n+=`(?:${x(s.prefix)}(${o})${x(s.suffix)})`,n+=T(s.modifier);continue}n+=`(?:${x(s.prefix)}`,n+=`((?:${o})(?:`,n+=x(s.suffix),n+=x(s.prefix),n+=`(?:${o}))*)${x(s.suffix)})`,s.modifier===0&&(n+="?");}let c=`[${x(r.endsWith)}]|$`,l=`[${x(r.delimiter)}]`;if(r.end)return r.strict||(n+=`${l}?`),r.endsWith.length?n+=`(?=${c})`:n+="$",new RegExp(n,B(r));r.strict||(n+=`(?:${l}(?=${c}))?`);let f=false;if(e.length){let s=e[e.length-1];s.type===3&&s.modifier===3&&(f=r.delimiter.indexOf(s)>-1);}return f||(n+=`(?=${l}|${c})`),new RegExp(n,B(r))}a(W,"partsToRegexp");var b={delimiter:"",prefixes:"",sensitive:true,strict:true},J={delimiter:".",prefixes:"",sensitive:true,strict:true},Q={delimiter:"/",prefixes:"/",sensitive:true,strict:true};function ee(e,t){return e.length?e[0]==="/"?true:!t||e.length<2?false:(e[0]=="\\"||e[0]=="{")&&e[1]=="/":false}a(ee,"isAbsolutePathname");function te(e,t){return e.startsWith(t)?e.substring(t.length,e.length):e}a(te,"maybeStripPrefix");function ke(e,t){return e.endsWith(t)?e.substr(0,e.length-t.length):e}a(ke,"maybeStripSuffix");function _(e){return !e||e.length<2?false:e[0]==="["||(e[0]==="\\"||e[0]==="{")&&e[1]==="["}a(_,"treatAsIPv6Hostname");var re=["ftp","file","http","https","ws","wss"];function U(e){if(!e)return true;for(let t of re)if(e.test(t))return true;return false}a(U,"isSpecialScheme");function ne(e,t){if(e=te(e,"#"),t||e==="")return e;let r=new URL("https://example.com");return r.hash=e,r.hash?r.hash.substring(1,r.hash.length):""}a(ne,"canonicalizeHash");function se(e,t){if(e=te(e,"?"),t||e==="")return e;let r=new URL("https://example.com");return r.search=e,r.search?r.search.substring(1,r.search.length):""}a(se,"canonicalizeSearch");function ie(e,t){return t||e===""?e:_(e)?K(e):j(e)}a(ie,"canonicalizeHostname");function ae(e,t){if(t||e==="")return e;let r=new URL("https://example.com");return r.password=e,r.password}a(ae,"canonicalizePassword");function oe(e,t){if(t||e==="")return e;let r=new URL("https://example.com");return r.username=e,r.username}a(oe,"canonicalizeUsername");function ce(e,t,r){if(r||e==="")return e;if(t&&!re.includes(t))return new URL(`${t}:${e}`).pathname;let n=e[0]=="/";return e=new URL(n?e:"/-"+e,"https://example.com").pathname,n||(e=e.substring(2,e.length)),e}a(ce,"canonicalizePathname");function le(e,t,r){return z(t)===e&&(e=""),r||e===""?e:G(e)}a(le,"canonicalizePort");function fe(e,t){return e=ke(e,":"),t||e===""?e:w(e)}a(fe,"canonicalizeProtocol");function z(e){switch(e){case "ws":case "http":return "80";case "wws":case "https":return "443";case "ftp":return "21";default:return ""}}a(z,"defaultPortForProtocol");function w(e){if(e==="")return e;if(/^[-+.A-Za-z0-9]*$/.test(e))return e.toLowerCase();throw new TypeError(`Invalid protocol '${e}'.`)}a(w,"protocolEncodeCallback");function he(e){if(e==="")return e;let t=new URL("https://example.com");return t.username=e,t.username}a(he,"usernameEncodeCallback");function ue(e){if(e==="")return e;let t=new URL("https://example.com");return t.password=e,t.password}a(ue,"passwordEncodeCallback");function j(e){if(e==="")return e;if(/[\t\n\r #%/:<>?@[\]^\\|]/g.test(e))throw new TypeError(`Invalid hostname '${e}'`);let t=new URL("https://example.com");return t.hostname=e,t.hostname}a(j,"hostnameEncodeCallback");function K(e){if(e==="")return e;if(/[^0-9a-fA-F[\]:]/g.test(e))throw new TypeError(`Invalid IPv6 hostname '${e}'`);return e.toLowerCase()}a(K,"ipv6HostnameEncodeCallback");function G(e){if(e===""||/^[0-9]*$/.test(e)&&parseInt(e)<=65535)return e;throw new TypeError(`Invalid port '${e}'.`)}a(G,"portEncodeCallback");function de(e){if(e==="")return e;let t=new URL("https://example.com");return t.pathname=e[0]!=="/"?"/-"+e:e,e[0]!=="/"?t.pathname.substring(2,t.pathname.length):t.pathname}a(de,"standardURLPathnameEncodeCallback");function pe(e){return e===""?e:new URL(`data:${e}`).pathname}a(pe,"pathURLPathnameEncodeCallback");function ge(e){if(e==="")return e;let t=new URL("https://example.com");return t.search=e,t.search.substring(1,t.search.length)}a(ge,"searchEncodeCallback");function me(e){if(e==="")return e;let t=new URL("https://example.com");return t.hash=e,t.hash.substring(1,t.hash.length)}a(me,"hashEncodeCallback");var C=class{#i;#n=[];#t={};#e=0;#s=1;#l=0;#o=0;#d=0;#p=0;#g=false;constructor(t){this.#i=t;}get result(){return this.#t}parse(){for(this.#n=D(this.#i,true);this.#e<this.#n.length;this.#e+=this.#s){if(this.#s=1,this.#n[this.#e].type==="END"){if(this.#o===0){this.#b(),this.#f()?this.#r(9,1):this.#h()?this.#r(8,1):this.#r(7,0);continue}else if(this.#o===2){this.#u(5);continue}this.#r(10,0);break}if(this.#d>0)if(this.#A())this.#d-=1;else continue;if(this.#T()){this.#d+=1;continue}switch(this.#o){case 0:this.#P()&&this.#u(1);break;case 1:if(this.#P()){this.#C();let t=7,r=1;this.#E()?(t=2,r=3):this.#g&&(t=2),this.#r(t,r);}break;case 2:this.#S()?this.#u(3):(this.#x()||this.#h()||this.#f())&&this.#u(5);break;case 3:this.#O()?this.#r(4,1):this.#S()&&this.#r(5,1);break;case 4:this.#S()&&this.#r(5,1);break;case 5:this.#y()?this.#p+=1:this.#w()&&(this.#p-=1),this.#k()&&!this.#p?this.#r(6,1):this.#x()?this.#r(7,0):this.#h()?this.#r(8,1):this.#f()&&this.#r(9,1);break;case 6:this.#x()?this.#r(7,0):this.#h()?this.#r(8,1):this.#f()&&this.#r(9,1);break;case 7:this.#h()?this.#r(8,1):this.#f()&&this.#r(9,1);break;case 8:this.#f()&&this.#r(9,1);break;}}this.#t.hostname!==void 0&&this.#t.port===void 0&&(this.#t.port="");}#r(t,r){switch(this.#o){case 0:break;case 1:this.#t.protocol=this.#c();break;case 2:break;case 3:this.#t.username=this.#c();break;case 4:this.#t.password=this.#c();break;case 5:this.#t.hostname=this.#c();break;case 6:this.#t.port=this.#c();break;case 7:this.#t.pathname=this.#c();break;case 8:this.#t.search=this.#c();break;case 9:this.#t.hash=this.#c();break;}this.#o!==0&&t!==10&&([1,2,3,4].includes(this.#o)&&[6,7,8,9].includes(t)&&(this.#t.hostname??=""),[1,2,3,4,5,6].includes(this.#o)&&[8,9].includes(t)&&(this.#t.pathname??=this.#g?"/":""),[1,2,3,4,5,6,7].includes(this.#o)&&t===9&&(this.#t.search??="")),this.#R(t,r);}#R(t,r){this.#o=t,this.#l=this.#e+r,this.#e+=r,this.#s=0;}#b(){this.#e=this.#l,this.#s=0;}#u(t){this.#b(),this.#o=t;}#m(t){return t<0&&(t=this.#n.length-t),t<this.#n.length?this.#n[t]:this.#n[this.#n.length-1]}#a(t,r){let n=this.#m(t);return n.value===r&&(n.type==="CHAR"||n.type==="ESCAPED_CHAR"||n.type==="INVALID_CHAR")}#P(){return this.#a(this.#e,":")}#E(){return this.#a(this.#e+1,"/")&&this.#a(this.#e+2,"/")}#S(){return this.#a(this.#e,"@")}#O(){return this.#a(this.#e,":")}#k(){return this.#a(this.#e,":")}#x(){return this.#a(this.#e,"/")}#h(){if(this.#a(this.#e,"?"))return true;if(this.#n[this.#e].value!=="?")return false;let t=this.#m(this.#e-1);return t.type!=="NAME"&&t.type!=="REGEX"&&t.type!=="CLOSE"&&t.type!=="ASTERISK"}#f(){return this.#a(this.#e,"#")}#T(){return this.#n[this.#e].type=="OPEN"}#A(){return this.#n[this.#e].type=="CLOSE"}#y(){return this.#a(this.#e,"[")}#w(){return this.#a(this.#e,"]")}#c(){let t=this.#n[this.#e],r=this.#m(this.#l).index;return this.#i.substring(r,t.index)}#C(){let t={};Object.assign(t,b),t.encodePart=w;let r=q(this.#c(),void 0,t);this.#g=U(r);}};a(C,"Parser");var V=["protocol","username","password","hostname","port","pathname","search","hash"],O="*";function Se(e,t){if(typeof e!="string")throw new TypeError("parameter 1 is not of type 'string'.");let r=new URL(e,t);return {protocol:r.protocol.substring(0,r.protocol.length-1),username:r.username,password:r.password,hostname:r.hostname,port:r.port,pathname:r.pathname,search:r.search!==""?r.search.substring(1,r.search.length):void 0,hash:r.hash!==""?r.hash.substring(1,r.hash.length):void 0}}a(Se,"extractValues");function R(e,t){return t?I(e):e}a(R,"processBaseURLString");function L(e,t,r){let n;if(typeof t.baseURL=="string")try{n=new URL(t.baseURL),t.protocol===void 0&&(e.protocol=R(n.protocol.substring(0,n.protocol.length-1),r)),!r&&t.protocol===void 0&&t.hostname===void 0&&t.port===void 0&&t.username===void 0&&(e.username=R(n.username,r)),!r&&t.protocol===void 0&&t.hostname===void 0&&t.port===void 0&&t.username===void 0&&t.password===void 0&&(e.password=R(n.password,r)),t.protocol===void 0&&t.hostname===void 0&&(e.hostname=R(n.hostname,r)),t.protocol===void 0&&t.hostname===void 0&&t.port===void 0&&(e.port=R(n.port,r)),t.protocol===void 0&&t.hostname===void 0&&t.port===void 0&&t.pathname===void 0&&(e.pathname=R(n.pathname,r)),t.protocol===void 0&&t.hostname===void 0&&t.port===void 0&&t.pathname===void 0&&t.search===void 0&&(e.search=R(n.search.substring(1,n.search.length),r)),t.protocol===void 0&&t.hostname===void 0&&t.port===void 0&&t.pathname===void 0&&t.search===void 0&&t.hash===void 0&&(e.hash=R(n.hash.substring(1,n.hash.length),r));}catch{throw new TypeError(`invalid baseURL '${t.baseURL}'.`)}if(typeof t.protocol=="string"&&(e.protocol=fe(t.protocol,r)),typeof t.username=="string"&&(e.username=oe(t.username,r)),typeof t.password=="string"&&(e.password=ae(t.password,r)),typeof t.hostname=="string"&&(e.hostname=ie(t.hostname,r)),typeof t.port=="string"&&(e.port=le(t.port,e.protocol,r)),typeof t.pathname=="string"){if(e.pathname=t.pathname,n&&!ee(e.pathname,r)){let c=n.pathname.lastIndexOf("/");c>=0&&(e.pathname=R(n.pathname.substring(0,c+1),r)+e.pathname);}e.pathname=ce(e.pathname,e.protocol,r);}return typeof t.search=="string"&&(e.search=se(t.search,r)),typeof t.hash=="string"&&(e.hash=ne(t.hash,r)),e}a(L,"applyInit");function I(e){return e.replace(/([+*?:{}()\\])/g,"\\$1")}a(I,"escapePatternString");function Te(e){return e.replace(/([.+*?^${}()[\]|/\\])/g,"\\$1")}a(Te,"escapeRegexpString");function Ae(e,t){t.delimiter??="/#?",t.prefixes??="./",t.sensitive??=false,t.strict??=false,t.end??=true,t.start??=true,t.endsWith="";let r=".*",n=`[^${Te(t.delimiter)}]+?`,c=/[$_\u200C\u200D\p{ID_Continue}]/u,l="";for(let f=0;f<e.length;++f){let s=e[f];if(s.type===3){if(s.modifier===3){l+=I(s.value);continue}l+=`{${I(s.value)}}${T(s.modifier)}`;continue}let i=s.hasCustomName(),o=!!s.suffix.length||!!s.prefix.length&&(s.prefix.length!==1||!t.prefixes.includes(s.prefix)),h=f>0?e[f-1]:null,p=f<e.length-1?e[f+1]:null;if(!o&&i&&s.type===1&&s.modifier===3&&p&&!p.prefix.length&&!p.suffix.length)if(p.type===3){let A=p.value.length>0?p.value[0]:"";o=c.test(A);}else o=!p.hasCustomName();if(!o&&!s.prefix.length&&h&&h.type===3){let A=h.value[h.value.length-1];o=t.prefixes.includes(A);}o&&(l+="{"),l+=I(s.prefix),i&&(l+=`:${s.name}`),s.type===2?l+=`(${s.value})`:s.type===1?i||(l+=`(${n})`):s.type===0&&(!i&&(!h||h.type===3||h.modifier!==3||o||s.prefix!=="")?l+="*":l+=`(${r})`),s.type===1&&i&&s.suffix.length&&c.test(s.suffix[0])&&(l+="\\"),l+=I(s.suffix),o&&(l+="}"),s.modifier!==3&&(l+=T(s.modifier));}return l}a(Ae,"partsToPattern");var Y=class{#i;#n={};#t={};#e={};#s={};#l=false;constructor(t={},r,n){try{let c;if(typeof r=="string"?c=r:n=r,typeof t=="string"){let i=new C(t);if(i.parse(),t=i.result,c===void 0&&typeof t.protocol!="string")throw new TypeError("A base URL must be provided for a relative constructor string.");t.baseURL=c;}else {if(!t||typeof t!="object")throw new TypeError("parameter 1 is not of type 'string' and cannot convert to dictionary.");if(c)throw new TypeError("parameter 1 is not of type 'string'.")}typeof n>"u"&&(n={ignoreCase:!1});let l={ignoreCase:n.ignoreCase===!0},f={pathname:O,protocol:O,username:O,password:O,hostname:O,port:O,search:O,hash:O};this.#i=L(f,t,!0),z(this.#i.protocol)===this.#i.port&&(this.#i.port="");let s;for(s of V){if(!(s in this.#i))continue;let i={},o=this.#i[s];switch(this.#t[s]=[],s){case "protocol":Object.assign(i,b),i.encodePart=w;break;case "username":Object.assign(i,b),i.encodePart=he;break;case "password":Object.assign(i,b),i.encodePart=ue;break;case "hostname":Object.assign(i,J),_(o)?i.encodePart=K:i.encodePart=j;break;case "port":Object.assign(i,b),i.encodePart=G;break;case "pathname":U(this.#n.protocol)?(Object.assign(i,Q,l),i.encodePart=de):(Object.assign(i,b,l),i.encodePart=pe);break;case "search":Object.assign(i,b,l),i.encodePart=ge;break;case "hash":Object.assign(i,b,l),i.encodePart=me;break}try{this.#s[s]=F(o,i),this.#n[s]=W(this.#s[s],this.#t[s],i),this.#e[s]=Ae(this.#s[s],i),this.#l=this.#l||this.#s[s].some(h=>h.type===2);}catch{throw new TypeError(`invalid ${s} pattern '${this.#i[s]}'.`)}}}catch(c){throw new TypeError(`Failed to construct 'URLPattern': ${c.message}`)}}get[Symbol.toStringTag](){return "URLPattern"}test(t={},r){let n={pathname:"",protocol:"",username:"",password:"",hostname:"",port:"",search:"",hash:""};if(typeof t!="string"&&r)throw new TypeError("parameter 1 is not of type 'string'.");if(typeof t>"u")return false;try{typeof t=="object"?n=L(n,t,!1):n=L(n,Se(t,r),!1);}catch{return false}let c;for(c of V)if(!this.#n[c].exec(n[c]))return false;return true}exec(t={},r){let n={pathname:"",protocol:"",username:"",password:"",hostname:"",port:"",search:"",hash:""};if(typeof t!="string"&&r)throw new TypeError("parameter 1 is not of type 'string'.");if(typeof t>"u")return;try{typeof t=="object"?n=L(n,t,!1):n=L(n,Se(t,r),!1);}catch{return null}let c={};r?c.inputs=[t,r]:c.inputs=[t];let l;for(l of V){let f=this.#n[l].exec(n[l]);if(!f)return null;let s={};for(let[i,o]of this.#t[l].entries())if(typeof o=="string"||typeof o=="number"){let h=f[i+1];s[o]=h;}c[l]={input:n[l]??"",groups:s};}return c}static compareComponent(t,r,n){let c=a((i,o)=>{for(let h of ["type","modifier","prefix","value","suffix"]){if(i[h]<o[h])return -1;if(i[h]===o[h])continue;return 1}return 0},"comparePart"),l=new P(3,"","","","",3),f=new P(0,"","","","",3),s=a((i,o)=>{let h=0;for(;h<Math.min(i.length,o.length);++h){let p=c(i[h],o[h]);if(p)return p}return i.length===o.length?0:c(i[h]??l,o[h]??l)},"comparePartList");return !r.#e[t]&&!n.#e[t]?0:r.#e[t]&&!n.#e[t]?s(r.#s[t],[f]):!r.#e[t]&&n.#e[t]?s([f],n.#s[t]):s(r.#s[t],n.#s[t])}get protocol(){return this.#e.protocol}get username(){return this.#e.username}get password(){return this.#e.password}get hostname(){return this.#e.hostname}get port(){return this.#e.port}get pathname(){return this.#e.pathname}get search(){return this.#e.search}get hash(){return this.#e.hash}get hasRegExpGroups(){return this.#l}};a(Y,"URLPattern");
646
+
647
+ function parseUrl(s) {
648
+ return new URL(typeof s === "string" ? s : s.href);
649
+ }
650
+ function depaginatePathname(url, pathnamePaginationSelector = /\/(page\/)?\d+\/?$/) {
651
+ const newUrl = new URL(url.toString());
652
+ newUrl.pathname = newUrl.pathname.replace(pathnamePaginationSelector, "/");
653
+ return newUrl;
654
+ }
655
+ function getPaginationLinks(doc = document, url = location.href, pathnamePaginationSelector = /\/(page\/)?\d+\/?$/) {
656
+ const baseUrl = depaginatePathname(parseUrl(url), pathnamePaginationSelector);
657
+ const pathnameStrict = doc instanceof Document;
658
+ const host = doc.baseURI || baseUrl.origin;
659
+ const urlPattern = new Y({
660
+ pathname: pathnameStrict ? `${baseUrl.pathname}*` : "*",
661
+ hostname: baseUrl.hostname
662
+ });
663
+ const pageLinks = [...doc.querySelectorAll("a[href]")].map((a) => a.href).filter((h) => URL.canParse(h));
664
+ return pageLinks.filter((h) => {
665
+ return urlPattern.test(new URL(h, host));
666
+ });
667
+ }
668
+ function upgradePathname(curr, links, pathnamePaginationSelector = /\/(page\/)?\d+\/?$/) {
669
+ if (pathnamePaginationSelector.test(curr.pathname) || links.length < 1) return curr;
670
+ const linksDepaginated = links.map(
671
+ (l) => depaginatePathname(l, pathnamePaginationSelector)
672
+ );
673
+ if (linksDepaginated.some((l) => l.pathname === curr.pathname)) return curr;
674
+ const last = linksDepaginated.at(-1);
675
+ if (last.pathname !== curr.pathname) curr.pathname = last.pathname;
676
+ return curr;
677
+ }
678
+
679
+ class PaginationStrategy {
680
+ doc = document;
681
+ url;
682
+ paginationSelector = ".pagination";
683
+ searchParamSelector = "page";
684
+ static _pathnameSelector = /\/(page\/)?\d+\/?$/;
685
+ pathnameSelector = /\/(\d+)\/?$/;
686
+ dataparamSelector = "[data-parameters *= from]";
687
+ overwritePaginationLast;
688
+ offsetMin = 1;
689
+ constructor(options) {
690
+ if (options) {
691
+ Object.entries(options).forEach(([k, v]) => {
692
+ Object.assign(this, { [k]: v });
693
+ });
694
+ }
695
+ this.url = parseUrl(options?.url || this.doc.URL);
696
+ }
697
+ getPaginationElement() {
698
+ return this.doc.querySelector(this.paginationSelector);
699
+ }
700
+ get hasPagination() {
701
+ return !!this.getPaginationElement();
702
+ }
703
+ getPaginationOffset() {
704
+ return this.offsetMin;
705
+ }
706
+ getPaginationLast() {
707
+ if (this.overwritePaginationLast) return this.overwritePaginationLast(1);
708
+ return 1;
709
+ }
710
+ getPaginationUrlGenerator() {
711
+ return (_) => this.url.href;
712
+ }
713
+ }
714
+
715
+ class PaginationStrategyDataParams extends PaginationStrategy {
716
+ getPaginationLast() {
717
+ const links = this.getPaginationElement()?.querySelectorAll(this.dataparamSelector);
718
+ const pages = Array.from(links || [], (l) => {
719
+ const p = l.getAttribute("data-parameters");
720
+ const v = p?.match(/from\w*:(\d+)/)?.[1] || this.offsetMin.toString();
721
+ return parseInt(v);
722
+ });
723
+ const lastPage = Math.max(...pages, this.offsetMin);
724
+ if (this.overwritePaginationLast) return this.overwritePaginationLast(lastPage);
725
+ return lastPage;
726
+ }
727
+ getPaginationOffset() {
728
+ const link = this.getPaginationElement()?.querySelector(
729
+ ".prev[data-parameters *= from], .prev [data-parameters *= from]"
730
+ );
731
+ if (!link) return this.offsetMin;
732
+ const p = link.getAttribute("data-parameters");
733
+ const v = p?.match(/from\w*:(\d+)/)?.[1] || this.offsetMin.toString();
734
+ return parseInt(v);
735
+ }
736
+ getPaginationUrlGenerator() {
737
+ const url = new URL(this.url.href);
738
+ const parametersElement = this.getPaginationElement()?.querySelector(
739
+ "a[data-block-id][data-parameters]"
740
+ );
741
+ const block_id = parametersElement?.getAttribute("data-block-id") || "";
742
+ const parameters = parseDataParams(
743
+ parametersElement?.getAttribute("data-parameters") || ""
744
+ );
745
+ const attrs = {
746
+ block_id,
747
+ function: "get_block",
748
+ mode: "async",
749
+ ...parameters
750
+ };
751
+ Object.keys(attrs).forEach((k) => {
752
+ url.searchParams.set(k, attrs[k]);
753
+ });
754
+ const paginationUrlGenerator = (n) => {
755
+ Object.keys(attrs).forEach((k) => {
756
+ k.includes("from") && url.searchParams.set(k, n.toString());
757
+ });
758
+ url.searchParams.set("_", Date.now().toString());
759
+ return url.href;
760
+ };
761
+ return paginationUrlGenerator;
762
+ }
763
+ static testLinks(doc = document) {
764
+ const dataParamLinks = Array.from(
765
+ doc.querySelectorAll("[data-parameters *= from]")
766
+ );
767
+ return dataParamLinks.length > 0;
768
+ }
769
+ }
770
+
771
+ class PaginationStrategyPathnameParams extends PaginationStrategy {
772
+ extractPage = (a) => {
773
+ const href = typeof a === "string" ? a : a.href;
774
+ const { pathname } = new URL(href, this.doc.baseURI || this.url.origin);
775
+ return parseInt(
776
+ pathname.match(this.pathnameSelector)?.pop() || this.offsetMin.toString()
777
+ );
778
+ };
779
+ static checkLink(link, pathnameSelector = PaginationStrategy._pathnameSelector) {
780
+ return pathnameSelector.test(link.pathname);
781
+ }
782
+ static testLinks(links, options) {
783
+ const result = links.some(
784
+ (h) => PaginationStrategyPathnameParams.checkLink(h, options.pathnameSelector)
785
+ );
786
+ if (result) {
787
+ const pathnamesMatched = links.filter(
788
+ (h) => PaginationStrategyPathnameParams.checkLink(h, options.pathnameSelector)
789
+ );
790
+ options.url = upgradePathname(
791
+ parseUrl(options.url),
792
+ pathnamesMatched
793
+ );
794
+ }
795
+ return result;
796
+ }
797
+ getPaginationLast() {
798
+ const links = getPaginationLinks(
799
+ this.getPaginationElement() || document,
800
+ this.url.href,
801
+ this.pathnameSelector
802
+ );
803
+ const pages = Array.from(links, this.extractPage);
804
+ const lastPage = Math.max(...pages, this.offsetMin);
805
+ if (this.overwritePaginationLast) return this.overwritePaginationLast(lastPage);
806
+ return lastPage;
807
+ }
808
+ getPaginationOffset() {
809
+ return this.extractPage(this.url.href);
810
+ }
811
+ getPaginationUrlGenerator(url_ = this.url) {
812
+ const url = new URL(url_.href);
813
+ const pathnameSelectorPlaceholder = this.pathnameSelector.toString().replace(/[/|\\|$|?|(|)]+/g, "/");
814
+ if (!this.pathnameSelector.test(url.pathname)) {
815
+ url.pathname = url.pathname.concat(pathnameSelectorPlaceholder.replace(/d\+/, this.offsetMin.toString())).replace(/\/{2,}/g, "/");
816
+ }
817
+ const paginationUrlGenerator = (offset) => {
818
+ url.pathname = url.pathname.replace(
819
+ this.pathnameSelector,
820
+ pathnameSelectorPlaceholder.replace(/d\+/, offset.toString())
821
+ );
822
+ return url.href;
823
+ };
824
+ return paginationUrlGenerator;
825
+ }
826
+ }
827
+
828
+ class PaginationStrategySearchParams extends PaginationStrategy {
829
+ extractPage = (a) => {
830
+ const href = typeof a === "string" ? a : a.href;
831
+ const p = new URL(href).searchParams.get(this.searchParamSelector);
832
+ return parseInt(p) || this.offsetMin;
833
+ };
834
+ getPaginationLast() {
835
+ const links = getPaginationLinks(
836
+ this.getPaginationElement() || document,
837
+ this.url.href
838
+ ).filter(
839
+ (h) => PaginationStrategySearchParams.checkLink(new URL(h), this.searchParamSelector)
840
+ );
841
+ const pages = links.map(this.extractPage);
842
+ const lastPage = Math.max(...pages, this.offsetMin);
843
+ if (this.overwritePaginationLast) return this.overwritePaginationLast(lastPage);
844
+ return lastPage;
845
+ }
846
+ getPaginationOffset() {
847
+ if (this.doc === document) {
848
+ return this.extractPage(this.url);
849
+ }
850
+ const link = this.getPaginationElement()?.querySelector(
851
+ `a.active[href *= "${this.searchParamSelector}="]`
852
+ );
853
+ return this.extractPage(link);
854
+ }
855
+ getPaginationUrlGenerator() {
856
+ const url = new URL(this.url.href);
857
+ const paginationUrlGenerator = (offset) => {
858
+ url.searchParams.set(this.searchParamSelector, offset.toString());
859
+ return url.href;
860
+ };
861
+ return paginationUrlGenerator;
862
+ }
863
+ static checkLink(link, searchParamSelector) {
864
+ const searchParamSelectors = ["page", "p"];
865
+ if (searchParamSelector) searchParamSelectors.push(searchParamSelector);
866
+ return searchParamSelectors.some((p) => link.searchParams.get(p) !== null);
867
+ }
868
+ static testLinks(links, searchParamSelector) {
869
+ return links.some(
870
+ (h) => PaginationStrategySearchParams.checkLink(h, searchParamSelector)
871
+ );
872
+ }
873
+ }
874
+
875
+ function getPaginationStrategy(options) {
876
+ const _paginationStrategy = new PaginationStrategy(options);
877
+ const pagination = _paginationStrategy.getPaginationElement();
878
+ Object.assign(options, { ..._paginationStrategy });
879
+ const { url, searchParamSelector } = options;
880
+ if (!pagination) {
881
+ return _paginationStrategy;
882
+ }
883
+ if (typeof options.getPaginationUrlGenerator === "function") {
884
+ return new PaginationStrategy(options);
885
+ }
886
+ const pageLinks = getPaginationLinks(pagination, url).map((l) => new URL(l));
887
+ const selectStrategy = () => {
888
+ if (PaginationStrategyDataParams.testLinks(pagination)) {
889
+ return PaginationStrategyDataParams;
890
+ }
891
+ if (PaginationStrategySearchParams.testLinks(pageLinks, searchParamSelector)) {
892
+ return PaginationStrategySearchParams;
893
+ }
894
+ if (PaginationStrategyPathnameParams.testLinks(pageLinks, options)) {
895
+ return PaginationStrategyPathnameParams;
896
+ }
897
+ console.error("Found No Strategy");
898
+ return PaginationStrategy;
899
+ };
900
+ const PaginationStrategyConstructor = selectStrategy();
901
+ const paginationStrategy = new PaginationStrategyConstructor(options);
902
+ return paginationStrategy;
903
+ }
904
+
905
+ class RulesGlobal {
906
+ delay;
907
+ customGenerator;
908
+ getThumbUrl(thumb) {
909
+ return (thumb.querySelector("a[href]") || thumb).href;
910
+ }
911
+ titleSelector;
912
+ uploaderSelector;
913
+ durationSelector;
914
+ customThumbDataSelectors;
915
+ getThumbDataStrategy = "default";
916
+ getThumbDataCallback;
917
+ getThumbData(thumb) {
918
+ let { titleSelector, uploaderSelector, durationSelector } = this;
919
+ const thumbData = { title: "" };
920
+ if (this.getThumbDataStrategy === "auto-text") {
921
+ const text = sanitizeStr(thumb.innerText);
922
+ thumbData.title = text;
923
+ thumbData.duration = timeToSeconds(text.match(/\d+m|\d+:\d+/)?.[0] || "");
924
+ return thumbData;
925
+ }
926
+ if (this.getThumbDataStrategy === "auto-select") {
927
+ titleSelector = "[class *= title],[title]";
928
+ durationSelector = "[class *= duration]";
929
+ uploaderSelector = "[class *= uploader], [class *= user], [class *= name]";
930
+ }
931
+ if (this.getThumbDataStrategy === "auto-select") {
932
+ const selected = querySelectorLast(thumb, titleSelector);
933
+ if (selected) {
934
+ thumbData.title = sanitizeStr(selected.innerText);
935
+ } else {
936
+ thumbData.title = sanitizeStr(thumb.innerText);
937
+ }
938
+ } else {
939
+ thumbData.title = querySelectorText(thumb, titleSelector);
940
+ }
941
+ if (uploaderSelector) {
942
+ const uploader = querySelectorText(thumb, uploaderSelector);
943
+ thumbData.title = `${thumbData.title} user:${uploader}`;
944
+ }
945
+ if (durationSelector) {
946
+ const duration = timeToSeconds(querySelectorText(thumb, durationSelector));
947
+ thumbData.duration = duration;
948
+ }
949
+ this.getThumbDataCallback?.(thumb, thumbData);
950
+ function getCustomThumbData(selector, type) {
951
+ if (type === "boolean") {
952
+ return !!thumb.querySelector(selector);
953
+ }
954
+ if (type === "string") {
955
+ return querySelectorText(thumb, selector);
956
+ }
957
+ return Number.parseInt(querySelectorText(thumb, selector));
958
+ }
959
+ if (this.customThumbDataSelectors) {
960
+ Object.entries(this.customThumbDataSelectors).forEach(([name, x]) => {
961
+ const data = getCustomThumbData(x.selector, x.type);
962
+ Object.assign(thumbData, { [name]: data });
963
+ });
964
+ }
965
+ return thumbData;
966
+ }
967
+ getThumbImgDataAttrSelector;
968
+ getThumbImgDataAttrDelete;
969
+ getThumbImgDataStrategy = "default";
970
+ getThumbImgData(thumb) {
971
+ const result = {};
972
+ if (this.getThumbImgDataStrategy === "auto") {
973
+ const img = thumb.querySelector("img");
974
+ if (!img) return {};
975
+ result.img = img;
976
+ if (typeof this.getThumbImgDataAttrSelector === "function") {
977
+ result.imgSrc = this.getThumbImgDataAttrSelector(img);
978
+ } else {
979
+ const possibleAttrs = this.getThumbImgDataAttrSelector ? [this.getThumbImgDataAttrSelector].flat() : ["data-src", "src"];
980
+ for (const attr of possibleAttrs) {
981
+ const imgSrc = img.getAttribute(attr);
982
+ if (imgSrc) {
983
+ result.imgSrc = imgSrc;
984
+ img.removeAttribute(attr);
985
+ break;
986
+ }
987
+ }
988
+ }
989
+ if (this.getThumbImgDataAttrDelete) {
990
+ if (this.getThumbImgDataAttrDelete === "auto") {
991
+ removeClassesAndDataAttributes(img, "lazy");
992
+ } else {
993
+ if (this.getThumbImgDataAttrDelete.startsWith(".")) {
994
+ img.classList.remove(this.getThumbImgDataAttrDelete.slice(1));
995
+ } else {
996
+ img.removeAttribute(this.getThumbImgDataAttrDelete);
997
+ }
998
+ }
999
+ if (img.src.includes("data:image")) {
1000
+ result.img.src = "";
1001
+ }
1002
+ if (img.complete && img.naturalWidth > 0) {
1003
+ return {};
1004
+ }
1005
+ }
1006
+ }
1007
+ return result;
1008
+ }
1009
+ containerSelector = ".container";
1010
+ containerSelectorLast;
1011
+ intersectionObservableSelector;
1012
+ get intersectionObservable() {
1013
+ return this.intersectionObservableSelector && document.querySelector(this.intersectionObservableSelector);
1014
+ }
1015
+ get observable() {
1016
+ return this.intersectionObservable || this.paginationStrategy.getPaginationElement();
1017
+ }
1018
+ get container() {
1019
+ if (typeof this.containerSelectorLast === "string") {
1020
+ return querySelectorLast(document, this.containerSelectorLast);
1021
+ }
1022
+ if (typeof this.containerSelector === "string") {
1023
+ return document.querySelector(this.containerSelector);
1024
+ }
1025
+ return this.containerSelector();
1026
+ }
1027
+ thumbsSelector = ".thumb";
1028
+ getThumbsStrategy = "default";
1029
+ getThumbsTransform;
1030
+ getThumbs(html) {
1031
+ if (!html) return [];
1032
+ let thumbs;
1033
+ if (this.getThumbsStrategy === "auto") {
1034
+ if (typeof this.containerSelector !== "string") return [];
1035
+ const container = html.querySelector(this.containerSelector);
1036
+ thumbs = [...container?.children || []];
1037
+ }
1038
+ thumbs = Array.from(html.querySelectorAll(this.thumbsSelector));
1039
+ if (typeof this.getThumbsTransform === "function") {
1040
+ thumbs.forEach(this.getThumbsTransform);
1041
+ }
1042
+ return thumbs;
1043
+ }
1044
+ paginationStrategyOptions = {};
1045
+ paginationStrategy;
1046
+ customDataSelectorFns = [
1047
+ "filterInclude",
1048
+ "filterExclude",
1049
+ "filterDuration"
1050
+ ];
1051
+ animatePreview;
1052
+ storeOptions;
1053
+ createStore() {
1054
+ const config = { ...StoreStateDefault, ...this.storeOptions };
1055
+ this.store = new jabroniOutfit.JabronioStore(config);
1056
+ return this.store;
1057
+ }
1058
+ schemeOptions = [];
1059
+ createGui() {
1060
+ const scheme = jabroniOutfit.setupScheme(
1061
+ this.schemeOptions,
1062
+ DefaultScheme
1063
+ );
1064
+ this.gui = new jabroniOutfit.JabronioGUI(scheme, this.store);
1065
+ return this.gui;
1066
+ }
1067
+ store;
1068
+ gui;
1069
+ dataManager;
1070
+ infiniteScroller;
1071
+ getPaginationData;
1072
+ resetInfiniteScroller() {
1073
+ this.infiniteScroller?.dispose();
1074
+ if (!this.paginationStrategy.hasPagination) return;
1075
+ this.infiniteScroller = InfiniteScroller.create(this);
1076
+ }
1077
+ gropeStrategy = "all-in-one";
1078
+ gropeInit() {
1079
+ if (!this.gropeStrategy) return;
1080
+ if (this.gropeStrategy === "all-in-one") {
1081
+ this.dataManager?.parseData(this.container, this.container);
1082
+ }
1083
+ if (this.gropeStrategy === "all-in-all") {
1084
+ getCommonParents(this.getThumbs(document.body)).forEach((c) => {
1085
+ this.dataManager.parseData(c, c, true);
1086
+ });
1087
+ }
1088
+ }
1089
+ get isEmbedded() {
1090
+ return window.self !== window.top;
1091
+ }
1092
+ setupStoreListeners() {
1093
+ const eventsMap = {
1094
+ "sort by duration": {
1095
+ action: (direction2) => this.dataManager.sortBy("duration", direction2)
1096
+ }
1097
+ };
1098
+ let lastEvent;
1099
+ let direction = true;
1100
+ this.store.eventSubject.subscribe((event) => {
1101
+ if (event === lastEvent) {
1102
+ direction = !direction;
1103
+ } else {
1104
+ lastEvent = event;
1105
+ direction = true;
1106
+ }
1107
+ if (event in eventsMap) {
1108
+ const ev = eventsMap[event];
1109
+ ev?.action(direction);
1110
+ }
1111
+ });
1112
+ this.store.stateSubject.subscribe((a) => {
1113
+ this.dataManager.applyFilters(a);
1114
+ });
1115
+ }
1116
+ dataManagerOptions = {};
1117
+ setupDataManager() {
1118
+ this.dataManager = new DataManager(this);
1119
+ if (this.dataManagerOptions) {
1120
+ Object.assign(this.dataManager, this.dataManagerOptions);
1121
+ }
1122
+ return this.dataManager;
1123
+ }
1124
+ mutationObservers = [];
1125
+ resetOnPaginationOrContainerDeath = true;
1126
+ resetOn() {
1127
+ if (!this.resetOnPaginationOrContainerDeath) return;
1128
+ const observables = [
1129
+ this.container,
1130
+ this.intersectionObservable || this.paginationStrategy.getPaginationElement()
1131
+ ].filter(Boolean);
1132
+ if (observables.length === 0) return;
1133
+ observables.forEach((o) => {
1134
+ const observer = waitForElementToDisappear(o, () => {
1135
+ this.reset();
1136
+ });
1137
+ this.mutationObservers.push(observer);
1138
+ });
1139
+ }
1140
+ onResetCallback;
1141
+ reset() {
1142
+ this.mutationObservers.forEach((o) => {
1143
+ o.disconnect();
1144
+ });
1145
+ this.mutationObservers = [];
1146
+ this.paginationStrategy = getPaginationStrategy(this.paginationStrategyOptions);
1147
+ this.setupDataManager();
1148
+ this.setupStoreListeners();
1149
+ this.resetInfiniteScroller();
1150
+ this.container && this.animatePreview?.(this.container);
1151
+ this.gropeInit();
1152
+ this.onResetCallback?.();
1153
+ this.resetOn();
1154
+ }
1155
+ constructor(options) {
1156
+ if (this.isEmbedded) throw Error("Embedded is not supported");
1157
+ Object.assign(this, options);
1158
+ this.paginationStrategy = getPaginationStrategy(this.paginationStrategyOptions);
1159
+ this.store = this.createStore();
1160
+ this.gui = this.createGui();
1161
+ this.dataManager = this.setupDataManager();
1162
+ this.reset();
1163
+ }
1164
+ }
1165
+
1166
+ function onPointerOverAndLeave(container, subjectSelector, onOver, onLeave) {
1167
+ let target;
1168
+ let onOverFinally;
1169
+ function handleLeaveEvent() {
1170
+ onOverFinally?.();
1171
+ target = void 0;
1172
+ }
1173
+ function handleEvent(e) {
1174
+ const currentTarget = e.target;
1175
+ if (!subjectSelector(currentTarget) || target === currentTarget) return;
1176
+ target = currentTarget;
1177
+ const result = onOver(target);
1178
+ onOverFinally = result?.onOverCallback;
1179
+ const leaveSubject = result?.leaveTarget || target;
1180
+ leaveSubject.addEventListener("pointerleave", handleLeaveEvent, {
1181
+ once: true
1182
+ });
1183
+ }
1184
+ container.addEventListener("pointerover", handleEvent);
1185
+ }
1186
+
1187
+ const show_video_prev = _unsafeWindow.show_video_prev;
1188
+ new RulesGlobal({
1189
+ paginationStrategyOptions: {
1190
+ paginationSelector: ".numlist2"
1191
+ },
1192
+ customThumbDataSelectors: {
1193
+ quality: { type: "number", selector: '[title="Quality"]' }
1194
+ },
1195
+ containerSelectorLast: "#vidresults",
1196
+ thumbsSelector: "div[id^=vf][data-id]",
1197
+ uploaderSelector: '[title="Uploader"]',
1198
+ titleSelector: "a",
1199
+ durationSelector: '[title="Duration"]',
1200
+ getThumbImgDataStrategy: "auto",
1201
+ getThumbImgDataAttrDelete: "auto",
1202
+ customDataSelectorFns: [
1203
+ "filterInclude",
1204
+ "filterExclude",
1205
+ "filterDuration",
1206
+ {
1207
+ quality360: (el, state) => !!state.quality360 && el.quality !== 360
1208
+ },
1209
+ {
1210
+ quality480: (el, state) => !!state.quality480 && el.quality !== 480
1211
+ },
1212
+ {
1213
+ quality720: (el, state) => !!state.quality720 && el.quality !== 720
1214
+ },
1215
+ {
1216
+ quality1080: (el, state) => !!state.quality1080 && el.quality !== 1080
1217
+ },
1218
+ {
1219
+ quality4k: (el, state) => !!state.quality4k && el.quality !== 4
1220
+ }
1221
+ ],
1222
+ schemeOptions: [
1223
+ "Text Filter",
1224
+ "Badge",
1225
+ "Duration Filter",
1226
+ {
1227
+ title: "Quality Filter ",
1228
+ content: [
1229
+ {
1230
+ quality360: false
1231
+ },
1232
+ {
1233
+ quality480: false
1234
+ },
1235
+ {
1236
+ quality720: false
1237
+ },
1238
+ {
1239
+ quality1080: false
1240
+ },
1241
+ {
1242
+ quality4k: false
1243
+ }
1244
+ ]
1245
+ },
1246
+ "Advanced"
1247
+ ],
1248
+ animatePreview
1249
+ });
1250
+ function animatePreview(doc) {
1251
+ onPointerOverAndLeave(
1252
+ doc,
1253
+ (e) => e instanceof HTMLImageElement,
1254
+ (e) => {
1255
+ const target = e;
1256
+ const thumb = target.closest("[data-id]");
1257
+ const id = thumb?.getAttribute("data-id");
1258
+ show_video_prev(id);
1259
+ }
1260
+ );
1261
+ }
1262
+
1263
+ })(jabronioutfit);
1264
+
1265
+ })();