pervert-monkey 1.0.25 → 1.0.27
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/README.md +5 -2
- package/dist/core/pervertmonkey.core.es.d.ts +2 -541
- package/dist/core/pervertmonkey.core.es.js +8005 -9281
- package/dist/core/pervertmonkey.core.es.js.map +1 -1
- package/dist/core/pervertmonkey.core.umd.js +8833 -10051
- package/dist/core/pervertmonkey.core.umd.js.map +1 -1
- package/dist/userscripts/3hentai.user.js +40 -46
- package/dist/userscripts/camgirlfinder.user.js +56 -49
- package/dist/userscripts/camwhores.user.js +286 -343
- package/dist/userscripts/e-hentai.user.js +54 -57
- package/dist/userscripts/ebalka.user.js +52 -55
- package/dist/userscripts/eporner.user.js +76 -68
- package/dist/userscripts/erome.user.js +79 -84
- package/dist/userscripts/eroprofile.user.js +28 -29
- package/dist/userscripts/javhdporn.user.js +28 -22
- package/dist/userscripts/missav.user.js +22 -23
- package/dist/userscripts/motherless.user.js +141 -152
- package/dist/userscripts/namethatporn.user.js +49 -58
- package/dist/userscripts/nhentai.user.js +104 -99
- package/dist/userscripts/obmenvsem.user.js +61 -69
- package/dist/userscripts/pornhub.user.js +50 -47
- package/dist/userscripts/simpcity.user.js +82 -24
- package/dist/userscripts/socialmediagirls.user.js +26 -22
- package/dist/userscripts/spankbang.user.js +62 -44
- package/dist/userscripts/thisvid.user.js +1269 -1366
- package/dist/userscripts/xhamster.user.js +119 -132
- package/dist/userscripts/xmegadrive.user.js +82 -0
- package/dist/userscripts/xvideos.user.js +115 -91
- package/package.json +10 -6
- package/src/core/data-handler/data-filter.ts +3 -3
- package/src/core/data-handler/data-manager.ts +11 -3
- package/src/core/parsers/pagination-parser/index.ts +0 -4
- package/src/core/parsers/pagination-parser/pagination-strategies/PaginationStrategyPathnameParams.ts +36 -1
- package/src/core/rules/index.ts +3 -3
- package/src/userscripts/index.ts +1 -1
- package/src/userscripts/meta.json +1 -1
- package/src/userscripts/scripts/3hentai.ts +1 -1
- package/src/userscripts/scripts/camgirlfinder.ts +1 -1
- package/src/userscripts/scripts/camwhores.ts +2 -2
- package/src/userscripts/scripts/e-hentai.ts +1 -1
- package/src/userscripts/scripts/ebalka.ts +2 -2
- package/src/userscripts/scripts/eporner.ts +41 -15
- package/src/userscripts/scripts/erome.ts +1 -1
- package/src/userscripts/scripts/eroprofile.ts +6 -6
- package/src/userscripts/scripts/javhdporn.ts +1 -1
- package/src/userscripts/scripts/missav.ts +1 -1
- package/src/userscripts/scripts/motherless.ts +28 -19
- package/src/userscripts/scripts/namethatporn.ts +1 -1
- package/src/userscripts/scripts/nhentai.ts +1 -1
- package/src/userscripts/scripts/obmenvsem.ts +1 -1
- package/src/userscripts/scripts/pornhub.ts +4 -2
- package/src/userscripts/scripts/simpcity.ts +72 -5
- package/src/userscripts/scripts/{socialmediagirls copy.ts → socialmediagirls.ts} +1 -1
- package/src/userscripts/scripts/spankbang.ts +20 -4
- package/src/userscripts/scripts/thisvid.ts +8 -21
- package/src/userscripts/scripts/xhamster.ts +12 -4
- package/src/userscripts/scripts/xmegadrive.ts +78 -0
- package/src/userscripts/scripts/xvideos.ts +26 -7
- package/src/utils/fetch/index.ts +2 -0
- package/src/utils/objects/memoize.ts +1 -9
- package/dist/test/test.user.js +0 -10301
- package/dist/userscripts/socialmediagirls copy.user.js +0 -41
|
@@ -15,9 +15,17 @@ export class DataManager {
|
|
|
15
15
|
);
|
|
16
16
|
public dataFilter: DataFilter;
|
|
17
17
|
|
|
18
|
+
public static create(
|
|
19
|
+
rules: Rules,
|
|
20
|
+
o: Partial<Pick<DataManager, 'removeDuplicates' | 'containerHomogenity'>> = {},
|
|
21
|
+
) {
|
|
22
|
+
return new DataManager(rules, o.removeDuplicates, o.containerHomogenity);
|
|
23
|
+
}
|
|
24
|
+
|
|
18
25
|
constructor(
|
|
19
|
-
|
|
20
|
-
|
|
26
|
+
public rules: Rules,
|
|
27
|
+
public removeDuplicates = false,
|
|
28
|
+
public containerHomogenity?: Parameters<typeof areElementsAlike>[2],
|
|
21
29
|
) {
|
|
22
30
|
this.dataFilter = new DataFilter(this.rules);
|
|
23
31
|
}
|
|
@@ -65,7 +73,7 @@ export class DataManager {
|
|
|
65
73
|
public async parseData(
|
|
66
74
|
html: HTMLElement,
|
|
67
75
|
container?: HTMLElement,
|
|
68
|
-
removeDuplicates =
|
|
76
|
+
removeDuplicates = this.removeDuplicates,
|
|
69
77
|
shouldLazify = true,
|
|
70
78
|
) {
|
|
71
79
|
const thumbs = this.rules.thumbsParser.getThumbs(html);
|
|
@@ -19,19 +19,15 @@ export function getPaginationStrategy(
|
|
|
19
19
|
const { url, searchParamSelector } = options;
|
|
20
20
|
|
|
21
21
|
if (!pagination) {
|
|
22
|
-
// console.error('Found No Pagination');
|
|
23
22
|
return _paginationStrategy;
|
|
24
23
|
}
|
|
25
24
|
|
|
26
25
|
if (typeof options.getPaginationUrlGenerator === 'function') {
|
|
27
|
-
// console.log(PaginationStrategy.name);
|
|
28
26
|
return new PaginationStrategy(options);
|
|
29
27
|
}
|
|
30
28
|
|
|
31
29
|
const pageLinks = getPaginationLinks(pagination, url).map((l) => new URL(l));
|
|
32
30
|
|
|
33
|
-
// console.log({ pageLinks: pageLinks.map((l) => l.href) });
|
|
34
|
-
|
|
35
31
|
const selectStrategy = (): typeof PaginationStrategy => {
|
|
36
32
|
if (PaginationStrategyDataParams.testLinks(pagination)) {
|
|
37
33
|
return PaginationStrategyDataParams;
|
package/src/core/parsers/pagination-parser/pagination-strategies/PaginationStrategyPathnameParams.ts
CHANGED
|
@@ -7,7 +7,8 @@ export class PaginationStrategyPathnameParams extends PaginationStrategy {
|
|
|
7
7
|
const href = typeof a === 'string' ? a : a.href;
|
|
8
8
|
const { pathname } = new URL(href, this.doc.baseURI || this.url.origin);
|
|
9
9
|
return parseInt(
|
|
10
|
-
pathname.match(this.pathnameSelector)?.pop() ||
|
|
10
|
+
pathname.match(this.pathnameSelector)?.filter(Boolean)?.pop() ||
|
|
11
|
+
this.offsetMin.toString(),
|
|
11
12
|
);
|
|
12
13
|
};
|
|
13
14
|
|
|
@@ -55,19 +56,53 @@ export class PaginationStrategyPathnameParams extends PaginationStrategy {
|
|
|
55
56
|
getPaginationUrlGenerator(url_: URL = this.url) {
|
|
56
57
|
const url = new URL(url_.href);
|
|
57
58
|
|
|
59
|
+
// console.log('this.pathnameSelector', this.pathnameSelector);
|
|
60
|
+
|
|
58
61
|
const pathnameSelectorPlaceholder = this.pathnameSelector
|
|
59
62
|
.toString()
|
|
60
63
|
.replace(/\\{1,}/g, '')
|
|
61
64
|
.replace(/[$?()]+/g, '')
|
|
62
65
|
.replace(/\/{1,}/g, '/');
|
|
63
66
|
|
|
67
|
+
// console.log({ pathnameSelectorPlaceholder, 'url.pathname': url.pathname });
|
|
68
|
+
|
|
64
69
|
if (!this.pathnameSelector.test(url.pathname)) {
|
|
65
70
|
url.pathname = url.pathname
|
|
66
71
|
.concat(pathnameSelectorPlaceholder.replace(/d\+/, this.offsetMin.toString()))
|
|
67
72
|
.replace(/\/{1,}/g, '/');
|
|
68
73
|
}
|
|
69
74
|
|
|
75
|
+
// console.log({ pathnameSelectorPlaceholder, 'url.pathname': url.pathname });
|
|
76
|
+
|
|
70
77
|
const paginationUrlGenerator = (offset: number) => {
|
|
78
|
+
// console.log({
|
|
79
|
+
// pathname: url.pathname,
|
|
80
|
+
// replace: '',
|
|
81
|
+
// pathnameSelector: this.pathnameSelector,
|
|
82
|
+
// pathnameSelectorPlaceholder: pathnameSelectorPlaceholder.replace(
|
|
83
|
+
// /d\+/,
|
|
84
|
+
// offset.toString(),
|
|
85
|
+
// ),
|
|
86
|
+
// });
|
|
87
|
+
|
|
88
|
+
// pathnameSelectorPlaceholder.replace()
|
|
89
|
+
// need to create tests
|
|
90
|
+
|
|
91
|
+
// url.pathname = url.pathname.replace(
|
|
92
|
+
// this.pathnameSelector,
|
|
93
|
+
// (a, b, c, d) => {
|
|
94
|
+
// console.log({ a, b, c, d, pathnameSelectorPlaceholder });
|
|
95
|
+
// if (a.length + 1 < pathnameSelectorPlaceholder.length) {
|
|
96
|
+
// return a.replace(/\d+/, offset.toString());
|
|
97
|
+
// }
|
|
98
|
+
// // return a;
|
|
99
|
+
// return pathnameSelectorPlaceholder.replace(/d\+/, offset.toString());
|
|
100
|
+
// },
|
|
101
|
+
// // pathnameSelectorPlaceholder.replace(/d\+/, offset.toString()),
|
|
102
|
+
// );
|
|
103
|
+
// return url.href;
|
|
104
|
+
// };
|
|
105
|
+
|
|
71
106
|
url.pathname = url.pathname.replace(
|
|
72
107
|
this.pathnameSelector,
|
|
73
108
|
pathnameSelectorPlaceholder.replace(/d\+/, offset.toString()),
|
package/src/core/rules/index.ts
CHANGED
|
@@ -62,7 +62,7 @@ export class Rules {
|
|
|
62
62
|
public paginationStrategy: PaginationStrategy;
|
|
63
63
|
|
|
64
64
|
public dataManager: DataManager;
|
|
65
|
-
public
|
|
65
|
+
public dataManagerOptions: Parameters<typeof DataManager.create>[1] = {};
|
|
66
66
|
|
|
67
67
|
public customDataFilterFns: (Record<string, DataFilterFnFrom<any>> | string)[] = [];
|
|
68
68
|
private hookDataFilterFns() {
|
|
@@ -157,7 +157,7 @@ export class Rules {
|
|
|
157
157
|
|
|
158
158
|
this.paginationStrategy = getPaginationStrategy(this.paginationStrategyOptions);
|
|
159
159
|
|
|
160
|
-
this.dataManager =
|
|
160
|
+
this.dataManager = DataManager.create(this, this.dataManagerOptions);
|
|
161
161
|
|
|
162
162
|
this.inputController.dispose();
|
|
163
163
|
this.inputController = new JabronioGuiController(this.store, this.dataManager);
|
|
@@ -188,7 +188,7 @@ export class Rules {
|
|
|
188
188
|
this.gui = this.createGui();
|
|
189
189
|
|
|
190
190
|
this.hookDataFilterFns();
|
|
191
|
-
this.dataManager =
|
|
191
|
+
this.dataManager = DataManager.create(this, this.dataManagerOptions);
|
|
192
192
|
this.inputController = new JabronioGuiController(this.store, this.dataManager);
|
|
193
193
|
|
|
194
194
|
this.reset();
|
package/src/userscripts/index.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import './scripts/
|
|
1
|
+
import './scripts/xmegadrive';
|
|
@@ -6,5 +6,5 @@
|
|
|
6
6
|
"grant": ["unsafeWindow", "GM_addStyle"],
|
|
7
7
|
"homepageURL": "https://sleazyfork.org/en/users/1253342-smartacephale",
|
|
8
8
|
"supportURL": "https://github.com/smartacephale/sleazy-fork/issues",
|
|
9
|
-
"source": "https://github.com/smartacephale"
|
|
9
|
+
"source": "https://github.com/smartacephale/sleazy-fork"
|
|
10
10
|
}
|
|
@@ -4,7 +4,7 @@ import { circularShift, OnHover, Tick } from '../../utils';
|
|
|
4
4
|
|
|
5
5
|
export const meta: MonkeyUserScript = {
|
|
6
6
|
name: '3Hentai PervertMonkey',
|
|
7
|
-
version: '1.0.
|
|
7
|
+
version: '1.0.20',
|
|
8
8
|
description: 'Infinite scroll [optional], Filter by Title, thumb preview',
|
|
9
9
|
match: 'https://*.3hentai.net/*',
|
|
10
10
|
};
|
|
@@ -2,7 +2,7 @@ import type { MonkeyUserScript } from 'vite-plugin-monkey';
|
|
|
2
2
|
|
|
3
3
|
export const meta: MonkeyUserScript = {
|
|
4
4
|
name: 'CamGirlFinder PervertMonkey',
|
|
5
|
-
version: '1.6.
|
|
5
|
+
version: '1.6.19',
|
|
6
6
|
description:
|
|
7
7
|
'Adds model links for CamWhores, webcamrecordings, recu.me, camvideos, privat-zapisi',
|
|
8
8
|
match: ['https://camgirlfinder.net/*'],
|
|
@@ -17,10 +17,10 @@ import {
|
|
|
17
17
|
|
|
18
18
|
export const meta: MonkeyUserScript = {
|
|
19
19
|
name: 'CamWhores PervertMonkey',
|
|
20
|
-
version: '3.0.
|
|
20
|
+
version: '3.0.24',
|
|
21
21
|
description:
|
|
22
22
|
'Infinite scroll [optional]. Filter by Title, Duration and Private/Public. Sort by Duration and Views. Mass friend request button. Download button',
|
|
23
|
-
match: ['https://*.camwhores.tv', 'https://*.camwhores.*/*'],
|
|
23
|
+
match: ['https://*.camwhores.tv/*', 'https://*.camwhores.*/*'],
|
|
24
24
|
exclude: 'https://*.camwhores.tv/*mode=async*',
|
|
25
25
|
};
|
|
26
26
|
|
|
@@ -4,7 +4,7 @@ import { fetchHtml } from '../../utils';
|
|
|
4
4
|
|
|
5
5
|
export const meta: MonkeyUserScript = {
|
|
6
6
|
name: 'E-Hentai PervertMonkey',
|
|
7
|
-
version: '1.0.
|
|
7
|
+
version: '1.0.20',
|
|
8
8
|
description: 'Infinite scroll [optional], Filter by Title',
|
|
9
9
|
match: ['https://*.e-hentai.org/*'],
|
|
10
10
|
};
|
|
@@ -4,7 +4,7 @@ import { downloader, exterminateVideo, OnHover, parseHtml } from '../../utils';
|
|
|
4
4
|
|
|
5
5
|
export const meta: MonkeyUserScript = {
|
|
6
6
|
name: 'Ebalka PervertMonkey',
|
|
7
|
-
version: '3.0.
|
|
7
|
+
version: '3.0.21',
|
|
8
8
|
description:
|
|
9
9
|
'Infinite scroll [optional], Filter by Title and Duration, Sort by Duration, Download button.',
|
|
10
10
|
match: [
|
|
@@ -49,7 +49,7 @@ function animatePreview(container: HTMLElement) {
|
|
|
49
49
|
const src = e.querySelector('.card__image')?.getAttribute('data-preview') as string;
|
|
50
50
|
|
|
51
51
|
const videoElem =
|
|
52
|
-
parseHtml(`<video style="position: absolute; left:
|
|
52
|
+
parseHtml(`<video style="position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%) scale(1.1); visibility: visible; margin-top: -1px;"
|
|
53
53
|
autoplay="" loop="" playsinline="true" webkit-playsinline="true" src="${src}"></video>`) as HTMLVideoElement;
|
|
54
54
|
e.appendChild(videoElem);
|
|
55
55
|
|
|
@@ -5,22 +5,24 @@ import { OnHover } from '../../utils';
|
|
|
5
5
|
|
|
6
6
|
export const meta: MonkeyUserScript = {
|
|
7
7
|
name: 'Eporner PervertMonkey',
|
|
8
|
-
version: '2.
|
|
8
|
+
version: '2.1.4',
|
|
9
9
|
description:
|
|
10
10
|
'Infinite scroll [optional], Filter by Title, Uploader, Duration and HD, Sort by Views and Duration',
|
|
11
11
|
match: ['https://*.eporner.com/*', 'https://*.eporner.*/*'],
|
|
12
|
+
supportURL: 'https://sleazyfork.org/en/scripts/552559-eporner-pervertmonkey/feedback',
|
|
12
13
|
};
|
|
13
14
|
|
|
14
|
-
const show_video_prev = (unsafeWindow as any).show_video_prev;
|
|
15
|
-
|
|
16
15
|
const rules = new Rules({
|
|
17
16
|
paginationStrategyOptions: {
|
|
18
17
|
paginationSelector: '.numlist2',
|
|
18
|
+
// pathnameSelector: /\/(\d+)\/?$/,
|
|
19
|
+
// pathnameSelector: /\/(\d+)\/([\w-]+\/)?$/
|
|
20
|
+
overwritePaginationLast: (n, _) => (n === 9 ? 9999 : n),
|
|
19
21
|
},
|
|
20
22
|
thumbs: { selector: 'div[id^=vf][data-id]' },
|
|
21
23
|
thumb: {
|
|
22
24
|
selectors: {
|
|
23
|
-
title: 'a',
|
|
25
|
+
title: 'a[href*=video-]',
|
|
24
26
|
uploader: '[title="Uploader"]',
|
|
25
27
|
duration: '[title="Duration"]',
|
|
26
28
|
views: { selector: '[title="Views"]', type: 'float' },
|
|
@@ -31,14 +33,40 @@ const rules = new Rules({
|
|
|
31
33
|
strategy: 'auto',
|
|
32
34
|
remove: 'auto',
|
|
33
35
|
},
|
|
34
|
-
containerSelectorLast: '
|
|
36
|
+
containerSelectorLast: 'div:has(div[id^=vf][data-id])',
|
|
35
37
|
customDataFilterFns: [
|
|
36
|
-
{
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
{
|
|
39
|
+
qualityFilter: {
|
|
40
|
+
handle(el, state) {
|
|
41
|
+
const hasAnyQualitySelected =
|
|
42
|
+
state.quality360 ||
|
|
43
|
+
state.quality480 ||
|
|
44
|
+
state.quality720 ||
|
|
45
|
+
state.quality1080 ||
|
|
46
|
+
state.quality2k ||
|
|
47
|
+
state.quality4k;
|
|
48
|
+
|
|
49
|
+
if (!hasAnyQualitySelected) return false;
|
|
50
|
+
|
|
51
|
+
return !(
|
|
52
|
+
(state.quality360 && el.quality === 360) ||
|
|
53
|
+
(state.quality480 && el.quality === 480) ||
|
|
54
|
+
(state.quality720 && el.quality === 720) ||
|
|
55
|
+
(state.quality1080 && el.quality === 1080) ||
|
|
56
|
+
(state.quality2k && el.quality === 2) ||
|
|
57
|
+
(state.quality4k && el.quality === 4)
|
|
58
|
+
);
|
|
59
|
+
},
|
|
60
|
+
deps: [
|
|
61
|
+
'quality360',
|
|
62
|
+
'quality480',
|
|
63
|
+
'quality720',
|
|
64
|
+
'quality1080',
|
|
65
|
+
'quality2k',
|
|
66
|
+
'quality4k',
|
|
67
|
+
],
|
|
68
|
+
},
|
|
69
|
+
},
|
|
42
70
|
],
|
|
43
71
|
schemeOptions: [
|
|
44
72
|
'Title Filter',
|
|
@@ -65,9 +93,7 @@ const rules = new Rules({
|
|
|
65
93
|
|
|
66
94
|
function animatePreview(doc: HTMLElement) {
|
|
67
95
|
OnHover.create(doc, 'div[id^=vf][data-id]', (e) => {
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
const id = thumb?.getAttribute('data-id');
|
|
71
|
-
show_video_prev(id);
|
|
96
|
+
const thumb = e.closest('[data-id]');
|
|
97
|
+
(unsafeWindow as any).EP.thumbs.preview.start(thumb);
|
|
72
98
|
});
|
|
73
99
|
}
|
|
@@ -4,7 +4,7 @@ import { Rules } from '../../core';
|
|
|
4
4
|
|
|
5
5
|
export const meta: MonkeyUserScript = {
|
|
6
6
|
name: 'Erome PervertMonkey',
|
|
7
|
-
version: '5.0.
|
|
7
|
+
version: '5.0.21',
|
|
8
8
|
description:
|
|
9
9
|
'Infinite scroll [optional], Filter by Title, Uploader and Video/Photo albums, Sort by Views. Show/Hide Photos in album. Remove disclaimer. Restore Search Bar',
|
|
10
10
|
match: ['*://*.erome.com/*'],
|
|
@@ -3,7 +3,7 @@ import { Rules } from '../../core';
|
|
|
3
3
|
|
|
4
4
|
export const meta: MonkeyUserScript = {
|
|
5
5
|
name: 'Eroprofile PervertMonkey',
|
|
6
|
-
version: '2.0.
|
|
6
|
+
version: '2.0.21',
|
|
7
7
|
description: 'Infinite scroll [optional], Filter by Title and Duration, Sort by Duration',
|
|
8
8
|
match: ['https://*.eroprofile.com/*'],
|
|
9
9
|
};
|
|
@@ -12,17 +12,17 @@ document.querySelector('.videoGrid')?.after(document.querySelector('.clB') as HT
|
|
|
12
12
|
|
|
13
13
|
const rules = new Rules({
|
|
14
14
|
paginationStrategyOptions: {
|
|
15
|
-
paginationSelector: '.
|
|
15
|
+
paginationSelector: '.page-nav',
|
|
16
16
|
searchParamSelector: 'pnum',
|
|
17
17
|
},
|
|
18
|
-
thumbs: { selector: '.video' },
|
|
18
|
+
thumbs: { selector: '.grid-tile-video' },
|
|
19
19
|
thumb: {
|
|
20
20
|
selectors: {
|
|
21
|
-
title: '
|
|
22
|
-
duration: '.
|
|
21
|
+
title: '.title',
|
|
22
|
+
duration: '.duration',
|
|
23
23
|
},
|
|
24
24
|
},
|
|
25
|
-
containerSelector: '
|
|
25
|
+
containerSelector: 'div:has(>.grid-tile-video)',
|
|
26
26
|
schemeOptions: [
|
|
27
27
|
'Title Filter',
|
|
28
28
|
'Duration Filter',
|
|
@@ -3,7 +3,7 @@ import { Rules } from '../../core';
|
|
|
3
3
|
|
|
4
4
|
export const meta: MonkeyUserScript = {
|
|
5
5
|
name: 'Javhdporn PervertMonkey',
|
|
6
|
-
version: '3.0.
|
|
6
|
+
version: '3.0.20',
|
|
7
7
|
description:
|
|
8
8
|
'Infinite scroll [optional], Filter by Title and Duration, Sort By Duration and Views',
|
|
9
9
|
match: ['https://*.javhdporn.net/*', 'https://*.javhdporn.*/*'],
|
|
@@ -3,7 +3,7 @@ import { Rules } from '../../core';
|
|
|
3
3
|
|
|
4
4
|
export const meta: MonkeyUserScript = {
|
|
5
5
|
name: 'Missav PervertMonkey',
|
|
6
|
-
version: '3.0.
|
|
6
|
+
version: '3.0.19',
|
|
7
7
|
description: 'Infinite scroll [optional], Filter by Title and Duration, Sort by Duration',
|
|
8
8
|
match: [
|
|
9
9
|
'https://*.missav123.com/*',
|
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
import type { MonkeyUserScript } from 'vite-plugin-monkey';
|
|
2
2
|
import { GM_addElement, GM_addStyle, unsafeWindow } from '$';
|
|
3
3
|
import { Rules } from '../../core';
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
fetchWith,
|
|
6
|
+
OnHover,
|
|
7
|
+
replaceElementTag,
|
|
8
|
+
Tick,
|
|
9
|
+
waitForElementToAppear,
|
|
10
|
+
} from '../../utils';
|
|
5
11
|
|
|
6
12
|
export const meta: MonkeyUserScript = {
|
|
7
13
|
name: 'Motherless PervertMonkey',
|
|
8
|
-
version: '5.0.
|
|
14
|
+
version: '5.0.25',
|
|
9
15
|
description:
|
|
10
16
|
'Infinite scroll [optional], Filter by Title, Uploader and Duration, Sort by Duration and Views',
|
|
11
|
-
match: ['https://motherless.
|
|
17
|
+
match: ['https://motherless.xxx/*'],
|
|
12
18
|
grant: ['GM_addElement', 'GM_addStyle', 'unsafeWindow'],
|
|
13
19
|
};
|
|
14
20
|
|
|
@@ -16,7 +22,7 @@ export const meta: MonkeyUserScript = {
|
|
|
16
22
|
const $ = (unsafeWindow as any).$;
|
|
17
23
|
|
|
18
24
|
const rules = new Rules({
|
|
19
|
-
|
|
25
|
+
containerSelector: '.content-inner',
|
|
20
26
|
thumbs: { selector: '.thumb-container, .mobile-thumb' },
|
|
21
27
|
thumb: {
|
|
22
28
|
selectors: {
|
|
@@ -142,25 +148,28 @@ async function desktopAddMobGalleries() {
|
|
|
142
148
|
const galleries = document.querySelector('.media-related-galleries');
|
|
143
149
|
if (!galleries) return;
|
|
144
150
|
|
|
151
|
+
await new Promise((resolve) => {
|
|
152
|
+
waitForElementToAppear(document, '.thumb-container.gallery-container', resolve);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
const mobDom = await fetchWith<HTMLElement>(window.location.href, {
|
|
156
|
+
type: 'html',
|
|
157
|
+
mobile: true,
|
|
158
|
+
});
|
|
159
|
+
const mobGalleries = mobDom.querySelectorAll<HTMLElement>('.ml-gallery-thumb');
|
|
160
|
+
|
|
145
161
|
const galleriesContainer = galleries.querySelector('.content-inner') as HTMLElement;
|
|
146
|
-
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
'.
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
galleriesContainer.append(mobileGalleryToDesktop(x));
|
|
155
|
-
}
|
|
162
|
+
|
|
163
|
+
for (const x of mobGalleries.values()) {
|
|
164
|
+
const mobGallery = mobileGalleryToDesktop(x);
|
|
165
|
+
const mobGalleryId = (mobGallery.querySelector('a') as HTMLAnchorElement).href
|
|
166
|
+
.split('/')
|
|
167
|
+
.at(-1);
|
|
168
|
+
if (galleriesContainer.querySelector(`a[href*=${mobGalleryId}]`)) continue;
|
|
169
|
+
galleriesContainer.append(mobGallery);
|
|
156
170
|
}
|
|
157
171
|
}
|
|
158
172
|
|
|
159
|
-
const overwrite1 = (x: string) => `@media only screen and (max-width: 1280px) {
|
|
160
|
-
#categories-page.inner ${x} }`;
|
|
161
|
-
|
|
162
|
-
rules.dataManager.dataFilter.createCssFilters(overwrite1);
|
|
163
|
-
|
|
164
173
|
GM_addStyle(`
|
|
165
174
|
.img-container, .desktop-thumb { min-height: 150px; max-height: 150px; }
|
|
166
175
|
|
|
@@ -4,7 +4,7 @@ import { Rules } from '../../core';
|
|
|
4
4
|
|
|
5
5
|
export const meta: MonkeyUserScript = {
|
|
6
6
|
name: 'NameThatPorn PervertMonkey',
|
|
7
|
-
version: '3.0.
|
|
7
|
+
version: '3.0.20',
|
|
8
8
|
description: 'Infinite scroll [optional], Filter by Title, Uploader and Solved/Unsolved',
|
|
9
9
|
match: ['https://namethatporn.com/*'],
|
|
10
10
|
};
|
|
@@ -4,7 +4,7 @@ import { parseHtml } from '../../utils';
|
|
|
4
4
|
|
|
5
5
|
export const meta: MonkeyUserScript = {
|
|
6
6
|
name: 'NHentai PervertMonkey',
|
|
7
|
-
version: '4.0.
|
|
7
|
+
version: '4.0.20',
|
|
8
8
|
description: 'Infinite scroll [optional], Filter by Title',
|
|
9
9
|
match: ['https://*.nhentai.net/*', 'https://*.nhentai.*/*'],
|
|
10
10
|
};
|
|
@@ -5,7 +5,7 @@ import { fetchHtml, parseUrl } from '../../utils';
|
|
|
5
5
|
|
|
6
6
|
export const meta: MonkeyUserScript = {
|
|
7
7
|
name: 'Obmenvsem PervertMonkey',
|
|
8
|
-
version: '1.0.
|
|
8
|
+
version: '1.0.22',
|
|
9
9
|
description: 'Infinite scroll [optional], Filter by Title and Duration, Sort by Duration',
|
|
10
10
|
match: [
|
|
11
11
|
'https://*.obmenvsem.com/*',
|
|
@@ -3,7 +3,7 @@ import { Rules } from '../../core';
|
|
|
3
3
|
|
|
4
4
|
export const meta: MonkeyUserScript = {
|
|
5
5
|
name: 'PornHub PervertMonkey',
|
|
6
|
-
version: '4.0.
|
|
6
|
+
version: '4.0.20',
|
|
7
7
|
description:
|
|
8
8
|
'Infinite scroll [optional]. Filter by Title, Uploader and Duration. Sort by Duration and Views',
|
|
9
9
|
match: ['https://*.pornhub.com/*'],
|
|
@@ -20,7 +20,9 @@ const rules = new Rules({
|
|
|
20
20
|
.filter((e) => e.children.length > 0 && e.checkVisibility())
|
|
21
21
|
.sort((a, b) => b.children.length - a.children.length)?.[0] as HTMLElement,
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
dataManagerOptions: {
|
|
24
|
+
containerHomogenity: { id: true, className: true },
|
|
25
|
+
},
|
|
24
26
|
thumbs: { selector: 'li[data-video-vkey]' },
|
|
25
27
|
thumb: {
|
|
26
28
|
selectors: {
|
|
@@ -3,13 +3,72 @@ import { Rules } from '../../core';
|
|
|
3
3
|
|
|
4
4
|
export const meta: MonkeyUserScript = {
|
|
5
5
|
name: 'Simpcity PervertMonkey',
|
|
6
|
-
version: '1.0.
|
|
7
|
-
description: 'Infinite scroll [optional], Filter by Title',
|
|
8
|
-
match:
|
|
6
|
+
version: '1.0.3',
|
|
7
|
+
description: 'Infinite scroll [optional], Filter by Title and Uploader, Sort by Views',
|
|
8
|
+
match: [
|
|
9
|
+
'https://simpcity.cr/threads/*',
|
|
10
|
+
'https://simpcity.cr/watched/threads*',
|
|
11
|
+
'https://simpcity.cr/forums/*',
|
|
12
|
+
'https://simpcity.cr/account/bookmarks*',
|
|
13
|
+
'https://simpcity.cr/tags/*',
|
|
14
|
+
],
|
|
9
15
|
'run-at': 'document-end',
|
|
10
16
|
};
|
|
11
17
|
|
|
12
|
-
const
|
|
18
|
+
const IS_WATCHED_THREADS = /^\/watched\/threads/.test(location.pathname);
|
|
19
|
+
const IS_FORUM_PAGE = /^\/forums\//.test(location.pathname);
|
|
20
|
+
const IS_BOOKMARKS_PAGE = /^\/account\/bookmarks/.test(location.pathname);
|
|
21
|
+
const IS_TAGS_PAGE = /^\/tags\//.test(location.pathname);
|
|
22
|
+
|
|
23
|
+
type RulesConfig = ConstructorParameters<typeof Rules>[0];
|
|
24
|
+
|
|
25
|
+
const structItemConfig: RulesConfig = {
|
|
26
|
+
containerSelectorLast: '.structItemContainer-group, .structItemContainer',
|
|
27
|
+
paginationStrategyOptions: {
|
|
28
|
+
paginationSelector: '.block-outer--after .pageNav',
|
|
29
|
+
pathnameSelector: /\/page-(\d+)\/?$/,
|
|
30
|
+
},
|
|
31
|
+
thumbs: {
|
|
32
|
+
selector: '.structItem.structItem--thread',
|
|
33
|
+
},
|
|
34
|
+
thumb: {
|
|
35
|
+
selectors: {
|
|
36
|
+
title: '.structItem-title a',
|
|
37
|
+
uploader: '.structItem-parts .username',
|
|
38
|
+
views: {
|
|
39
|
+
selector: '.structItem-cell--meta dl:nth-of-type(2) dd',
|
|
40
|
+
type: 'float',
|
|
41
|
+
},
|
|
42
|
+
replies: {
|
|
43
|
+
selector: '.structItem-cell--meta dl:nth-of-type(1) dd',
|
|
44
|
+
type: 'float',
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
gropeStrategy: 'all-in-all',
|
|
49
|
+
schemeOptions: ['Title Filter', 'Uploader Filter', 'Sort By Views', 'Badge', 'Advanced'],
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const contentRowConfig: RulesConfig = {
|
|
53
|
+
containerSelector: 'ol.block-body, ol.listPlain',
|
|
54
|
+
paginationStrategyOptions: {
|
|
55
|
+
paginationSelector: '.block-outer--after .pageNav',
|
|
56
|
+
pathnameSelector: /\/page-(\d+)\/?$/,
|
|
57
|
+
},
|
|
58
|
+
thumbs: {
|
|
59
|
+
selector: 'li.block-row',
|
|
60
|
+
},
|
|
61
|
+
thumb: {
|
|
62
|
+
selectors: {
|
|
63
|
+
title: '.contentRow-title a',
|
|
64
|
+
uploader: '.contentRow-minor .username',
|
|
65
|
+
},
|
|
66
|
+
getUrlSelector: '.contentRow-title a',
|
|
67
|
+
},
|
|
68
|
+
schemeOptions: ['Title Filter', 'Uploader Filter', 'Badge', 'Advanced'],
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const threadConfig: RulesConfig = {
|
|
13
72
|
containerSelector: '.js-replyNewMessageContainer',
|
|
14
73
|
paginationStrategyOptions: {
|
|
15
74
|
paginationSelector: '.block-container + * .pageNav',
|
|
@@ -24,4 +83,12 @@ const rules = new Rules({
|
|
|
24
83
|
},
|
|
25
84
|
gropeStrategy: 'all-in-all',
|
|
26
85
|
schemeOptions: ['Title Filter', 'Badge', 'Advanced'],
|
|
27
|
-
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const rules = new Rules(
|
|
89
|
+
IS_BOOKMARKS_PAGE || IS_TAGS_PAGE
|
|
90
|
+
? contentRowConfig
|
|
91
|
+
: IS_WATCHED_THREADS || IS_FORUM_PAGE
|
|
92
|
+
? structItemConfig
|
|
93
|
+
: threadConfig,
|
|
94
|
+
);
|
|
@@ -3,7 +3,7 @@ import { Rules } from '../../core';
|
|
|
3
3
|
|
|
4
4
|
export const meta: MonkeyUserScript = {
|
|
5
5
|
name: 'Socialmediagirls PervertMonkey',
|
|
6
|
-
version: '1.0.
|
|
6
|
+
version: '1.0.5',
|
|
7
7
|
description: 'Infinite scroll [optional], Filter by Title',
|
|
8
8
|
match: 'https://forums.socialmediagirls.com/threads/*',
|
|
9
9
|
'run-at': 'document-end',
|
|
@@ -3,7 +3,7 @@ import { Rules } from '../../core';
|
|
|
3
3
|
|
|
4
4
|
export const meta: MonkeyUserScript = {
|
|
5
5
|
name: 'SpankBang.com PervertMonkey',
|
|
6
|
-
version: '4.0
|
|
6
|
+
version: '4.1.0',
|
|
7
7
|
description:
|
|
8
8
|
'Infinite scroll [optional]. Filter by Title and Duration. Sort by Duration and Views',
|
|
9
9
|
match: ['https://*.spankbang.com/*', 'https://*.spankbang.*/*'],
|
|
@@ -27,9 +27,25 @@ const rules = new Rules({
|
|
|
27
27
|
thumbImg: { strategy: 'auto' },
|
|
28
28
|
gropeStrategy: 'all-in-all',
|
|
29
29
|
customDataFilterFns: [
|
|
30
|
-
{
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
{
|
|
31
|
+
qualityFilter: {
|
|
32
|
+
handle(el, state) {
|
|
33
|
+
const hasAnyQualitySelected =
|
|
34
|
+
state.qualityLow ||
|
|
35
|
+
state.qualityHD ||
|
|
36
|
+
state.quality4k;
|
|
37
|
+
|
|
38
|
+
if (!hasAnyQualitySelected) return false;
|
|
39
|
+
|
|
40
|
+
return !(
|
|
41
|
+
(state.qualityLow && el.quality === '') ||
|
|
42
|
+
(state.qualityHD && el.quality === 'HD') ||
|
|
43
|
+
(state.quality4k && el.quality === '4K')
|
|
44
|
+
);
|
|
45
|
+
},
|
|
46
|
+
deps: ['qualityLow', 'qualityHD', 'quality4k'],
|
|
47
|
+
},
|
|
48
|
+
},
|
|
33
49
|
],
|
|
34
50
|
schemeOptions: [
|
|
35
51
|
'Title Filter',
|