pervert-monkey 1.0.9 → 1.0.10
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.
- package/dist/core/pervertmonkey.core.es.d.ts +121 -59
- package/dist/core/pervertmonkey.core.es.js +1001 -315
- package/dist/core/pervertmonkey.core.es.js.map +1 -1
- package/dist/core/pervertmonkey.core.umd.js +1001 -315
- package/dist/core/pervertmonkey.core.umd.js.map +1 -1
- package/dist/userscripts/3hentai.user.js +14 -8
- package/dist/userscripts/camgirlfinder.user.js +1 -1
- package/dist/userscripts/camwhores.user.js +15 -9
- package/dist/userscripts/e-hentai.user.js +12 -6
- package/dist/userscripts/ebalka.user.js +11 -5
- package/dist/userscripts/eporner.user.js +15 -10
- package/dist/userscripts/erome.user.js +11 -10
- package/dist/userscripts/eroprofile.user.js +9 -5
- package/dist/userscripts/javhdporn.user.js +9 -5
- package/dist/userscripts/missav.user.js +10 -6
- package/dist/userscripts/motherless.user.js +11 -7
- package/dist/userscripts/namethatporn.user.js +17 -13
- package/dist/userscripts/nhentai.user.js +12 -6
- package/dist/userscripts/obmenvsem.user.js +14 -18
- package/dist/userscripts/pornhub.user.js +14 -10
- package/dist/userscripts/spankbang.user.js +10 -6
- package/dist/userscripts/thisvid.user.js +27 -21
- package/dist/userscripts/xhamster.user.js +26 -26
- package/dist/userscripts/xvideos.user.js +19 -17
- package/package.json +5 -3
- package/src/core/{data-control → data-handler}/data-filter.ts +3 -8
- package/src/core/{data-control → data-handler}/data-manager.ts +8 -7
- package/src/core/data-handler/index.ts +2 -0
- package/src/core/index.ts +4 -4
- package/src/core/infinite-scroll/index.ts +20 -29
- package/src/core/parsers/index.ts +4 -0
- package/src/core/{pagination-parsing → parsers/pagination-parser}/index.ts +3 -0
- package/src/core/{pagination-parsing → parsers/pagination-parser}/pagination-strategies/PaginationStrategy.ts +1 -1
- package/src/core/{pagination-parsing → parsers/pagination-parser}/pagination-strategies/PaginationStrategyDataParams.ts +1 -1
- package/src/core/{pagination-parsing → parsers/pagination-parser}/pagination-strategies/PaginationStrategyPathnameParams.ts +2 -1
- package/src/core/{pagination-parsing → parsers/pagination-parser}/pagination-utils/index.ts +1 -4
- package/src/core/parsers/thumb-data-parser.ts +96 -0
- package/src/core/parsers/thumb-img-parser.ts +62 -0
- package/src/core/parsers/thumbs-parser.ts +29 -0
- package/src/core/rules/index.ts +39 -207
- package/src/userscripts/index.ts +1 -1
- package/src/userscripts/scripts/3hentai.ts +14 -6
- package/src/userscripts/scripts/camwhores.ts +19 -13
- package/src/userscripts/scripts/e-hentai.ts +13 -7
- package/src/userscripts/scripts/ebalka.ts +11 -5
- package/src/userscripts/scripts/eporner.ts +16 -10
- package/src/userscripts/scripts/erome.ts +11 -10
- package/src/userscripts/scripts/eroprofile.ts +10 -6
- package/src/userscripts/scripts/javhdporn.ts +9 -5
- package/src/userscripts/scripts/missav.ts +10 -6
- package/src/userscripts/scripts/motherless.ts +11 -7
- package/src/userscripts/scripts/namethatporn.ts +18 -14
- package/src/userscripts/scripts/nhentai.ts +13 -8
- package/src/userscripts/scripts/obmenvsem.ts +14 -13
- package/src/userscripts/scripts/pornhub.ts +14 -10
- package/src/userscripts/scripts/spankbang.ts +10 -6
- package/src/userscripts/scripts/thisvid.ts +32 -27
- package/src/userscripts/scripts/xhamster.ts +37 -38
- package/src/userscripts/scripts/xvideos.ts +18 -16
- package/src/utils/index.ts +7 -19
- package/src/utils/parsers/index.ts +4 -0
- package/src/utils/strings/index.ts +2 -0
- package/src/core/data-control/index.ts +0 -2
- /package/src/core/{pagination-parsing → parsers/pagination-parser}/pagination-strategies/PaginationStrategySearchParams.ts +0 -0
- /package/src/core/{pagination-parsing → parsers/pagination-parser}/pagination-strategies/index.ts +0 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { removeClassesAndDataAttributes } from "../../utils";
|
|
2
|
+
|
|
3
|
+
export class ThumbImgParser {
|
|
4
|
+
public selector?: string | string[] | ((img: HTMLImageElement) => string);
|
|
5
|
+
public shouldDelete?: 'auto' | string;
|
|
6
|
+
public strategy: 'default' | 'auto' = 'default';
|
|
7
|
+
|
|
8
|
+
public static create(options: Partial<Pick<ThumbImgParser, 'selector' | 'shouldDelete' | 'strategy' | 'getImgData'>> = {}) {
|
|
9
|
+
return Object.assign(new ThumbImgParser(), options);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
public getImgData(thumb: HTMLElement) {
|
|
13
|
+
const result: { img?: HTMLImageElement; imgSrc?: string } = {};
|
|
14
|
+
|
|
15
|
+
if (this.strategy === 'auto') {
|
|
16
|
+
const img = thumb.querySelector<HTMLImageElement>('img');
|
|
17
|
+
if (!img) return {};
|
|
18
|
+
|
|
19
|
+
result.img = img;
|
|
20
|
+
|
|
21
|
+
if (typeof this.selector === 'function') {
|
|
22
|
+
result.imgSrc = this.selector(img);
|
|
23
|
+
} else {
|
|
24
|
+
const possibleAttrs = this.selector
|
|
25
|
+
? [this.selector].flat()
|
|
26
|
+
: ['data-src', 'src'];
|
|
27
|
+
|
|
28
|
+
for (const attr of possibleAttrs) {
|
|
29
|
+
const imgSrc = img.getAttribute(attr);
|
|
30
|
+
if (imgSrc) {
|
|
31
|
+
result.imgSrc = imgSrc;
|
|
32
|
+
img.removeAttribute(attr);
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (this.shouldDelete) {
|
|
39
|
+
if (this.shouldDelete === 'auto') {
|
|
40
|
+
removeClassesAndDataAttributes(img, 'lazy');
|
|
41
|
+
} else {
|
|
42
|
+
if (this.shouldDelete.startsWith('.')) {
|
|
43
|
+
img.classList.remove(this.shouldDelete.slice(1));
|
|
44
|
+
} else {
|
|
45
|
+
img.removeAttribute(this.shouldDelete);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (img.src.includes('data:image')) {
|
|
50
|
+
result.img.src = '';
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (img.complete && img.naturalWidth > 0) {
|
|
54
|
+
return {};
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export class ThumbsParser {
|
|
2
|
+
public selector = '.thumb';
|
|
3
|
+
public strategy: 'default' | 'auto' = 'default';
|
|
4
|
+
public transform?: (thumb: HTMLElement) => void;
|
|
5
|
+
|
|
6
|
+
public static create(options: Partial<Pick<ThumbsParser, 'selector' | 'strategy' | 'transform'>> = {}, containerSelector: string) {
|
|
7
|
+
return Object.assign(new ThumbsParser(containerSelector), options);
|
|
8
|
+
}
|
|
9
|
+
constructor(public containerSelector: string) { }
|
|
10
|
+
|
|
11
|
+
public getThumbs(html: HTMLElement): HTMLElement[] {
|
|
12
|
+
if (!html) return [];
|
|
13
|
+
let thumbs: HTMLElement[];
|
|
14
|
+
|
|
15
|
+
if (this.strategy === 'auto') {
|
|
16
|
+
if (typeof this.selector !== 'string') return [];
|
|
17
|
+
const container = html.querySelector(this.containerSelector);
|
|
18
|
+
thumbs = [...(container?.children || [])] as HTMLElement[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
thumbs = Array.from(html.querySelectorAll<HTMLElement>(this.selector));
|
|
22
|
+
|
|
23
|
+
if (typeof this.transform === 'function') {
|
|
24
|
+
thumbs.forEach(this.transform);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return thumbs;
|
|
28
|
+
}
|
|
29
|
+
}
|
package/src/core/rules/index.ts
CHANGED
|
@@ -2,174 +2,46 @@ import { JabronioGUI, JabronioStore, type JabroniTypes, setupScheme } from 'jabr
|
|
|
2
2
|
import {
|
|
3
3
|
getCommonParents,
|
|
4
4
|
querySelectorLast,
|
|
5
|
-
querySelectorText,
|
|
6
|
-
removeClassesAndDataAttributes,
|
|
7
|
-
sanitizeStr,
|
|
8
|
-
timeToSeconds,
|
|
9
5
|
waitForElementToDisappear,
|
|
10
6
|
} from '../../utils';
|
|
11
|
-
import { DataManager } from '../data-
|
|
12
|
-
import type
|
|
13
|
-
import { InfiniteScroller, type OffsetGenerator } from '../infinite-scroll/';
|
|
7
|
+
import { DataManager, type DataSelectorFn } from '../data-handler';
|
|
8
|
+
import { InfiniteScroller, type OffsetGenerator } from '../infinite-scroll';
|
|
14
9
|
import { DefaultScheme, type SchemeOptions, StoreStateDefault } from '../jabroni-config';
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
selector: string;
|
|
25
|
-
type: 'boolean' | 'string' | 'number';
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
type CustomThumbDataSelector = {
|
|
29
|
-
[x: string]: _CustomThumbDataSelector;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
export class RulesGlobal {
|
|
33
|
-
public delay?: number;
|
|
34
|
-
|
|
35
|
-
public customGenerator?: OffsetGenerator;
|
|
36
|
-
|
|
10
|
+
import {
|
|
11
|
+
getPaginationStrategy,
|
|
12
|
+
type PaginationStrategy,
|
|
13
|
+
ThumbDataParser,
|
|
14
|
+
ThumbImgParser,
|
|
15
|
+
ThumbsParser
|
|
16
|
+
} from '../parsers';
|
|
17
|
+
|
|
18
|
+
export class Rules {
|
|
37
19
|
public getThumbUrl(thumb: HTMLElement | HTMLAnchorElement) {
|
|
38
20
|
return ((thumb.querySelector('a[href]') || thumb) as HTMLAnchorElement).href;
|
|
39
21
|
}
|
|
40
22
|
|
|
41
|
-
public
|
|
42
|
-
public
|
|
43
|
-
public durationSelector: undefined | string;
|
|
44
|
-
|
|
45
|
-
public customThumbDataSelectors: undefined | CustomThumbDataSelector;
|
|
46
|
-
public getThumbDataStrategy: 'default' | 'auto-select' | 'auto-text' = 'default';
|
|
47
|
-
|
|
48
|
-
public getThumbDataCallback?: (thumb: HTMLElement, thumbData: ThumbData) => void;
|
|
49
|
-
|
|
50
|
-
public getThumbData(thumb: HTMLElement): ThumbData {
|
|
51
|
-
let { titleSelector, uploaderSelector, durationSelector } = this;
|
|
52
|
-
const thumbData: ThumbData = { title: '' };
|
|
23
|
+
public thumb: Parameters<typeof ThumbDataParser.create>[0] = {};
|
|
24
|
+
public thumbDataParser: ThumbDataParser;
|
|
53
25
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
thumbData.title = text;
|
|
57
|
-
thumbData.duration = timeToSeconds(text.match(/\d+m|\d+:\d+/)?.[0] || '');
|
|
58
|
-
return thumbData;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (this.getThumbDataStrategy === 'auto-select') {
|
|
62
|
-
titleSelector = '[class *= title],[title]';
|
|
63
|
-
durationSelector = '[class *= duration]';
|
|
64
|
-
uploaderSelector = '[class *= uploader], [class *= user], [class *= name]';
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (this.getThumbDataStrategy === 'auto-select') {
|
|
68
|
-
const selected = querySelectorLast(thumb, titleSelector as string);
|
|
69
|
-
if (selected) {
|
|
70
|
-
thumbData.title = sanitizeStr(selected.innerText as string);
|
|
71
|
-
} else {
|
|
72
|
-
thumbData.title = sanitizeStr(thumb.innerText);
|
|
73
|
-
}
|
|
74
|
-
} else {
|
|
75
|
-
thumbData.title = querySelectorText(thumb, titleSelector);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (uploaderSelector) {
|
|
79
|
-
const uploader = querySelectorText(thumb, uploaderSelector);
|
|
80
|
-
thumbData.title = `${thumbData.title} user:${uploader}`;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (durationSelector) {
|
|
84
|
-
const duration = timeToSeconds(querySelectorText(thumb, durationSelector));
|
|
85
|
-
thumbData.duration = duration;
|
|
86
|
-
}
|
|
26
|
+
public thumbImg: Parameters<typeof ThumbImgParser.create>[0] = {};
|
|
27
|
+
public thumbImgParser: ThumbImgParser;
|
|
87
28
|
|
|
88
|
-
|
|
29
|
+
public thumbs: Parameters<typeof ThumbsParser.create>[0] = {};
|
|
30
|
+
public thumbsParser: ThumbsParser;
|
|
89
31
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
type: _CustomThumbDataSelector['type'],
|
|
93
|
-
): string | number | boolean {
|
|
94
|
-
if (type === 'boolean') {
|
|
95
|
-
return !!thumb.querySelector(selector);
|
|
96
|
-
}
|
|
97
|
-
if (type === 'string') {
|
|
98
|
-
return querySelectorText(thumb, selector);
|
|
99
|
-
}
|
|
100
|
-
return Number.parseInt(querySelectorText(thumb, selector));
|
|
101
|
-
}
|
|
32
|
+
public containerSelector: string | (() => HTMLElement) = '.container';
|
|
33
|
+
public containerSelectorLast?: string;
|
|
102
34
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
Object.assign(thumbData, { [name]: data });
|
|
107
|
-
});
|
|
35
|
+
get container() {
|
|
36
|
+
if (typeof this.containerSelectorLast === 'string') {
|
|
37
|
+
return querySelectorLast(document, this.containerSelectorLast) as HTMLElement;
|
|
108
38
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
public getThumbImgDataAttrSelector?:
|
|
114
|
-
| string
|
|
115
|
-
| string[]
|
|
116
|
-
| ((img: HTMLImageElement) => string);
|
|
117
|
-
public getThumbImgDataAttrDelete?: 'auto' | string;
|
|
118
|
-
public getThumbImgDataStrategy: 'default' | 'auto' = 'default';
|
|
119
|
-
|
|
120
|
-
public getThumbImgData(thumb: HTMLElement) {
|
|
121
|
-
const result: { img?: HTMLImageElement; imgSrc?: string } = {};
|
|
122
|
-
|
|
123
|
-
if (this.getThumbImgDataStrategy === 'auto') {
|
|
124
|
-
const img = thumb.querySelector<HTMLImageElement>('img');
|
|
125
|
-
if (!img) return {};
|
|
126
|
-
|
|
127
|
-
result.img = img;
|
|
128
|
-
|
|
129
|
-
if (typeof this.getThumbImgDataAttrSelector === 'function') {
|
|
130
|
-
result.imgSrc = this.getThumbImgDataAttrSelector(img);
|
|
131
|
-
} else {
|
|
132
|
-
const possibleAttrs = this.getThumbImgDataAttrSelector
|
|
133
|
-
? [this.getThumbImgDataAttrSelector].flat()
|
|
134
|
-
: ['data-src', 'src'];
|
|
135
|
-
|
|
136
|
-
for (const attr of possibleAttrs) {
|
|
137
|
-
const imgSrc = img.getAttribute(attr);
|
|
138
|
-
if (imgSrc) {
|
|
139
|
-
result.imgSrc = imgSrc;
|
|
140
|
-
img.removeAttribute(attr);
|
|
141
|
-
break;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
if (this.getThumbImgDataAttrDelete) {
|
|
147
|
-
if (this.getThumbImgDataAttrDelete === 'auto') {
|
|
148
|
-
removeClassesAndDataAttributes(img, 'lazy');
|
|
149
|
-
} else {
|
|
150
|
-
if (this.getThumbImgDataAttrDelete.startsWith('.')) {
|
|
151
|
-
img.classList.remove(this.getThumbImgDataAttrDelete.slice(1));
|
|
152
|
-
} else {
|
|
153
|
-
img.removeAttribute(this.getThumbImgDataAttrDelete);
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
if (img.src.includes('data:image')) {
|
|
158
|
-
result.img.src = '';
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
if (img.complete && img.naturalWidth > 0) {
|
|
162
|
-
return {};
|
|
163
|
-
}
|
|
164
|
-
}
|
|
39
|
+
if (typeof this.containerSelector === 'string') {
|
|
40
|
+
return document.querySelector<HTMLElement>(this.containerSelector) as HTMLElement;
|
|
165
41
|
}
|
|
166
|
-
|
|
167
|
-
return result;
|
|
42
|
+
return this.containerSelector();
|
|
168
43
|
}
|
|
169
44
|
|
|
170
|
-
public containerSelector: string | (() => HTMLElement) = '.container';
|
|
171
|
-
public containerSelectorLast?: string;
|
|
172
|
-
|
|
173
45
|
public intersectionObservableSelector?: string;
|
|
174
46
|
|
|
175
47
|
public get intersectionObservable() {
|
|
@@ -184,42 +56,11 @@ export class RulesGlobal {
|
|
|
184
56
|
this.paginationStrategy.getPaginationElement()) as HTMLElement;
|
|
185
57
|
}
|
|
186
58
|
|
|
187
|
-
get container() {
|
|
188
|
-
if (typeof this.containerSelectorLast === 'string') {
|
|
189
|
-
return querySelectorLast(document, this.containerSelectorLast) as HTMLElement;
|
|
190
|
-
}
|
|
191
|
-
if (typeof this.containerSelector === 'string') {
|
|
192
|
-
return document.querySelector<HTMLElement>(this.containerSelector) as HTMLElement;
|
|
193
|
-
}
|
|
194
|
-
return this.containerSelector();
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
public thumbsSelector = '.thumb';
|
|
198
|
-
public getThumbsStrategy: 'default' | 'auto' = 'default';
|
|
199
|
-
public getThumbsTransform?: (thumb: HTMLElement) => void;
|
|
200
|
-
|
|
201
|
-
public getThumbs(html: HTMLElement): HTMLElement[] {
|
|
202
|
-
if (!html) return [];
|
|
203
|
-
let thumbs: HTMLElement[];
|
|
204
|
-
|
|
205
|
-
if (this.getThumbsStrategy === 'auto') {
|
|
206
|
-
if (typeof this.containerSelector !== 'string') return [];
|
|
207
|
-
const container = html.querySelector(this.containerSelector);
|
|
208
|
-
thumbs = [...(container?.children || [])] as HTMLElement[];
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
thumbs = Array.from(html.querySelectorAll<HTMLElement>(this.thumbsSelector));
|
|
212
|
-
|
|
213
|
-
if (typeof this.getThumbsTransform === 'function') {
|
|
214
|
-
thumbs.forEach(this.getThumbsTransform);
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
return thumbs;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
59
|
public paginationStrategyOptions: Partial<PaginationStrategy> = {};
|
|
221
60
|
public paginationStrategy: PaginationStrategy;
|
|
222
61
|
|
|
62
|
+
public dataManager: DataManager;
|
|
63
|
+
public dataHomogenity: ConstructorParameters<typeof DataManager>[1];
|
|
223
64
|
public customDataSelectorFns: (Record<string, DataSelectorFn<any>> | string)[] = [
|
|
224
65
|
'filterInclude',
|
|
225
66
|
'filterExclude',
|
|
@@ -229,6 +70,9 @@ export class RulesGlobal {
|
|
|
229
70
|
public animatePreview?: (doc: HTMLElement) => void;
|
|
230
71
|
|
|
231
72
|
public storeOptions?: JabroniTypes.StoreStateOptions;
|
|
73
|
+
public schemeOptions: SchemeOptions = [];
|
|
74
|
+
public store: JabronioStore;
|
|
75
|
+
public gui: JabronioGUI;
|
|
232
76
|
|
|
233
77
|
private createStore() {
|
|
234
78
|
const config = { ...StoreStateDefault, ...this.storeOptions };
|
|
@@ -236,8 +80,6 @@ export class RulesGlobal {
|
|
|
236
80
|
return this.store;
|
|
237
81
|
}
|
|
238
82
|
|
|
239
|
-
public schemeOptions: SchemeOptions = [];
|
|
240
|
-
|
|
241
83
|
private createGui() {
|
|
242
84
|
const scheme = setupScheme(
|
|
243
85
|
this.schemeOptions as Parameters<typeof setupScheme>[0],
|
|
@@ -247,10 +89,7 @@ export class RulesGlobal {
|
|
|
247
89
|
return this.gui;
|
|
248
90
|
}
|
|
249
91
|
|
|
250
|
-
public
|
|
251
|
-
public gui: JabronioGUI;
|
|
252
|
-
public dataManager: DataManager;
|
|
253
|
-
|
|
92
|
+
public customGenerator?: OffsetGenerator;
|
|
254
93
|
public infiniteScroller?: InfiniteScroller;
|
|
255
94
|
public getPaginationData?: InfiniteScroller['getPaginationData'];
|
|
256
95
|
|
|
@@ -268,7 +107,7 @@ export class RulesGlobal {
|
|
|
268
107
|
this.dataManager?.parseData(this.container, this.container);
|
|
269
108
|
}
|
|
270
109
|
if (this.gropeStrategy === 'all-in-all') {
|
|
271
|
-
getCommonParents(this.getThumbs(document.body)).forEach((c) => {
|
|
110
|
+
getCommonParents(this.thumbsParser.getThumbs(document.body)).forEach((c) => {
|
|
272
111
|
this.dataManager.parseData(c, c, true);
|
|
273
112
|
});
|
|
274
113
|
}
|
|
@@ -307,17 +146,6 @@ export class RulesGlobal {
|
|
|
307
146
|
});
|
|
308
147
|
}
|
|
309
148
|
|
|
310
|
-
public dataManagerOptions: Partial<DataManager> = {};
|
|
311
|
-
|
|
312
|
-
private setupDataManager() {
|
|
313
|
-
this.dataManager = new DataManager(this);
|
|
314
|
-
if (this.dataManagerOptions) {
|
|
315
|
-
Object.assign(this.dataManager, this.dataManagerOptions);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
return this.dataManager;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
149
|
private mutationObservers: MutationObserver[] = [];
|
|
322
150
|
|
|
323
151
|
public resetOnPaginationOrContainerDeath = true;
|
|
@@ -352,7 +180,7 @@ export class RulesGlobal {
|
|
|
352
180
|
|
|
353
181
|
this.paginationStrategy = getPaginationStrategy(this.paginationStrategyOptions);
|
|
354
182
|
|
|
355
|
-
this.
|
|
183
|
+
this.dataManager = new DataManager(this, this.dataHomogenity);
|
|
356
184
|
this.setupStoreListeners();
|
|
357
185
|
|
|
358
186
|
this.resetInfiniteScroller();
|
|
@@ -366,17 +194,21 @@ export class RulesGlobal {
|
|
|
366
194
|
this.resetOn();
|
|
367
195
|
}
|
|
368
196
|
|
|
369
|
-
constructor(options: Partial<
|
|
197
|
+
constructor(options: Partial<Rules>) {
|
|
370
198
|
if (this.isEmbedded) throw Error('Embedded is not supported');
|
|
371
199
|
|
|
372
200
|
Object.assign(this, options);
|
|
373
201
|
|
|
202
|
+
this.thumbDataParser = ThumbDataParser.create(this.thumb);
|
|
203
|
+
this.thumbImgParser = ThumbImgParser.create(this.thumbImg);
|
|
204
|
+
this.thumbsParser = ThumbsParser.create(this.thumbs, this.containerSelector as string);
|
|
205
|
+
|
|
374
206
|
this.paginationStrategy = getPaginationStrategy(this.paginationStrategyOptions);
|
|
375
207
|
|
|
376
208
|
this.store = this.createStore();
|
|
377
209
|
this.gui = this.createGui();
|
|
378
210
|
|
|
379
|
-
this.dataManager = this.
|
|
211
|
+
this.dataManager = new DataManager(this, this.dataHomogenity);
|
|
380
212
|
|
|
381
213
|
this.reset();
|
|
382
214
|
// console.log('data', this.dataManager.data.values().toArray());
|
package/src/userscripts/index.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import './scripts/
|
|
1
|
+
import './scripts/pornhub';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { MonkeyUserScript } from 'vite-plugin-monkey';
|
|
2
|
-
import {
|
|
2
|
+
import { Rules } from '../../core';
|
|
3
3
|
import { circularShift, OnHover, Tick } from '../../utils';
|
|
4
4
|
|
|
5
5
|
export const meta: MonkeyUserScript = {
|
|
@@ -9,11 +9,19 @@ export const meta: MonkeyUserScript = {
|
|
|
9
9
|
match: 'https://*.3hentai.net/*',
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
const rules = new
|
|
12
|
+
const rules = new Rules({
|
|
13
13
|
containerSelectorLast: '.listing-container',
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
thumbs: {
|
|
15
|
+
selector: '.doujin-col'
|
|
16
|
+
},
|
|
17
|
+
thumb: {
|
|
18
|
+
selectors: {
|
|
19
|
+
title: '.title',
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
thumbImg: {
|
|
23
|
+
strategy: 'auto',
|
|
24
|
+
},
|
|
17
25
|
gropeStrategy: 'all-in-all',
|
|
18
26
|
customDataSelectorFns: ['filterInclude', 'filterExclude'],
|
|
19
27
|
schemeOptions: ['Text Filter', 'Badge', 'Advanced'],
|
|
@@ -36,7 +44,7 @@ function animatePreview() {
|
|
|
36
44
|
const t = e as HTMLImageElement;
|
|
37
45
|
const origin = t.src;
|
|
38
46
|
t.src = t.src.replace(/\w+\.\w+$/, '1t.jpg');
|
|
39
|
-
t.onerror = (_) =>
|
|
47
|
+
t.onerror = (_) => tick.stop();
|
|
40
48
|
tick.start(
|
|
41
49
|
() => {
|
|
42
50
|
t.src = rotate(t.src);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { LSKDB } from 'lskdb';
|
|
2
2
|
import type { MonkeyUserScript } from 'vite-plugin-monkey';
|
|
3
3
|
import { GM_addStyle, unsafeWindow } from '$';
|
|
4
|
-
import { getPaginationStrategy, InfiniteScroller,
|
|
4
|
+
import { getPaginationStrategy, InfiniteScroller, Rules } from '../../core';
|
|
5
5
|
import {
|
|
6
6
|
circularShift,
|
|
7
7
|
downloader,
|
|
8
8
|
fetchHtml,
|
|
9
|
-
objectToFormData,
|
|
10
9
|
OnHover,
|
|
10
|
+
objectToFormData,
|
|
11
11
|
parseHtml,
|
|
12
12
|
querySelectorLastNumber,
|
|
13
13
|
querySelectorText,
|
|
@@ -39,22 +39,28 @@ const IS_COMMUNITY_LIST = /\/members\/$/.test(location.pathname);
|
|
|
39
39
|
const IS_VIDEO_PAGE = /^(\/videos)?\/\d+\//.test(location.pathname);
|
|
40
40
|
const IS_LOGGED_IN = document.cookie.includes('kt_member');
|
|
41
41
|
|
|
42
|
-
const rules = new
|
|
42
|
+
const rules = new Rules({
|
|
43
43
|
containerSelector:
|
|
44
44
|
'[id*="playlist"]:has(> .item .title),[id*="videos"]:has(> .item .title),form:has(>.item .title)',
|
|
45
45
|
paginationStrategyOptions: {
|
|
46
46
|
paginationSelector: '.pagination:not([id *= member])',
|
|
47
47
|
overwritePaginationLast: IS_MEMBER_PAGE ? () => 1 : (x) => (x === 9 ? 9999 : x),
|
|
48
48
|
},
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
'.list-videos .item, .playlist .item, .list-playlists > div > .item, .item:has(.title)',
|
|
53
|
-
gropeStrategy: 'all-in-all',
|
|
54
|
-
getThumbDataStrategy: 'auto-select',
|
|
55
|
-
customThumbDataSelectors: {
|
|
56
|
-
private: { type: 'boolean', selector: '[class*=private]' },
|
|
49
|
+
thumbs: {
|
|
50
|
+
selector:
|
|
51
|
+
'.list-videos .item, .playlist .item, .list-playlists > div > .item, .item:has(.title)'
|
|
57
52
|
},
|
|
53
|
+
thumb: {
|
|
54
|
+
strategy: 'auto-select',
|
|
55
|
+
selectors: {
|
|
56
|
+
private: { type: 'boolean', selector: '[class*=private]' },
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
thumbImg: {
|
|
60
|
+
selector: 'data-original',
|
|
61
|
+
strategy: 'auto',
|
|
62
|
+
},
|
|
63
|
+
gropeStrategy: 'all-in-all',
|
|
58
64
|
customDataSelectorFns: [
|
|
59
65
|
'filterInclude',
|
|
60
66
|
'filterExclude',
|
|
@@ -175,7 +181,7 @@ async function getMemberFriends(id: number | string) {
|
|
|
175
181
|
const paginationStrategy = getPaginationStrategy({
|
|
176
182
|
doc,
|
|
177
183
|
url,
|
|
178
|
-
overwritePaginationLast: (x) => (x === 9 ? 999 : x),
|
|
184
|
+
overwritePaginationLast: (x: number) => (x === 9 ? 999 : x),
|
|
179
185
|
});
|
|
180
186
|
|
|
181
187
|
const gen = InfiniteScroller.generatorForPaginationStrategy(paginationStrategy);
|
|
@@ -301,7 +307,7 @@ async function acceptFriendRequest(id: number | string) {
|
|
|
301
307
|
async function clearMessages() {
|
|
302
308
|
const pages = InfiniteScroller.generatorForPaginationStrategy(
|
|
303
309
|
getPaginationStrategy({
|
|
304
|
-
overwritePaginationLast: (x) => (x === 9 ? 999 : x),
|
|
310
|
+
overwritePaginationLast: (x: number) => (x === 9 ? 999 : x),
|
|
305
311
|
}),
|
|
306
312
|
);
|
|
307
313
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { MonkeyUserScript } from 'vite-plugin-monkey';
|
|
2
|
-
import {
|
|
2
|
+
import { Rules } from '../../core';
|
|
3
3
|
import { fetchHtml } from '../../utils';
|
|
4
4
|
|
|
5
5
|
export const meta: MonkeyUserScript = {
|
|
@@ -9,18 +9,24 @@ export const meta: MonkeyUserScript = {
|
|
|
9
9
|
match: ['https://*.e-hentai.org/*'],
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
-
const rules = new
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
const rules = new Rules({
|
|
13
|
+
thumbs: { selector: '.gl1t' },
|
|
14
|
+
thumb: {
|
|
15
|
+
selectors: {
|
|
16
|
+
title: '.glname'
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
thumbImg: {
|
|
20
|
+
selector: 'data-lazy-load',
|
|
21
|
+
strategy: 'auto',
|
|
22
|
+
},
|
|
15
23
|
containerSelectorLast: '.itg.gld',
|
|
16
|
-
getThumbImgDataAttrSelector: 'data-lazy-load',
|
|
17
|
-
getThumbImgDataStrategy: 'auto',
|
|
18
24
|
paginationStrategyOptions: createPaginationStrategyOptions(),
|
|
19
25
|
customDataSelectorFns: ['filterInclude', 'filterExclude'],
|
|
20
26
|
schemeOptions: ['Text Filter', 'Badge', 'Advanced'],
|
|
21
27
|
});
|
|
22
28
|
|
|
23
|
-
function createPaginationStrategyOptions():
|
|
29
|
+
function createPaginationStrategyOptions(): Rules['paginationStrategyOptions'] {
|
|
24
30
|
let nextLink: string;
|
|
25
31
|
|
|
26
32
|
function getPaginationUrlGenerator() {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { MonkeyUserScript } from 'vite-plugin-monkey';
|
|
2
|
-
import {
|
|
2
|
+
import { Rules } from '../../core';
|
|
3
3
|
import { exterminateVideo, OnHover, parseHtml } from '../../utils';
|
|
4
4
|
|
|
5
5
|
export const meta: MonkeyUserScript = {
|
|
@@ -15,14 +15,20 @@ export const meta: MonkeyUserScript = {
|
|
|
15
15
|
],
|
|
16
16
|
};
|
|
17
17
|
|
|
18
|
-
const rules = new
|
|
18
|
+
const rules = new Rules({
|
|
19
19
|
containerSelectorLast: '.content__video',
|
|
20
20
|
paginationStrategyOptions: {
|
|
21
21
|
paginationSelector: '.pagination:not([id *= member])',
|
|
22
22
|
},
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
thumbs: {
|
|
24
|
+
selector: '.card_video'
|
|
25
|
+
},
|
|
26
|
+
thumb: {
|
|
27
|
+
selectors: {
|
|
28
|
+
title: '.card__title',
|
|
29
|
+
duration: '.card__spot > span:last-child',
|
|
30
|
+
}
|
|
31
|
+
},
|
|
26
32
|
animatePreview,
|
|
27
33
|
schemeOptions: ['Text Filter', 'Badge', 'Duration Filter', 'Advanced'],
|
|
28
34
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { MonkeyUserScript } from 'vite-plugin-monkey';
|
|
2
2
|
import { unsafeWindow } from '$';
|
|
3
|
-
import {
|
|
3
|
+
import { Rules } from '../../core';
|
|
4
4
|
import { OnHover } from '../../utils';
|
|
5
5
|
|
|
6
6
|
export const meta: MonkeyUserScript = {
|
|
@@ -12,20 +12,26 @@ export const meta: MonkeyUserScript = {
|
|
|
12
12
|
|
|
13
13
|
const show_video_prev = (unsafeWindow as any).show_video_prev;
|
|
14
14
|
|
|
15
|
-
const rules = new
|
|
15
|
+
const rules = new Rules({
|
|
16
16
|
paginationStrategyOptions: {
|
|
17
17
|
paginationSelector: '.numlist2',
|
|
18
18
|
},
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
thumb: {
|
|
20
|
+
selectors: {
|
|
21
|
+
quality: { type: 'number', selector: '[title="Quality"]' },
|
|
22
|
+
title: 'a',
|
|
23
|
+
uploader: '[title="Uploader"]',
|
|
24
|
+
duration: '[title="Duration"]',
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
thumbImg: {
|
|
28
|
+
strategy: 'auto'
|
|
29
|
+
// getImgDataAttrDelete: 'auto',
|
|
30
|
+
},
|
|
31
|
+
thumbs: {
|
|
32
|
+
selector: 'div[id^=vf][data-id]',
|
|
21
33
|
},
|
|
22
34
|
containerSelectorLast: '#vidresults',
|
|
23
|
-
thumbsSelector: 'div[id^=vf][data-id]',
|
|
24
|
-
uploaderSelector: '[title="Uploader"]',
|
|
25
|
-
titleSelector: 'a',
|
|
26
|
-
durationSelector: '[title="Duration"]',
|
|
27
|
-
getThumbImgDataStrategy: 'auto',
|
|
28
|
-
getThumbImgDataAttrDelete: 'auto',
|
|
29
35
|
customDataSelectorFns: [
|
|
30
36
|
'filterInclude',
|
|
31
37
|
'filterExclude',
|