pervert-monkey 1.0.13 → 1.0.17
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 +90 -36
- package/dist/core/pervertmonkey.core.es.js +258 -129
- package/dist/core/pervertmonkey.core.es.js.map +1 -1
- package/dist/core/pervertmonkey.core.umd.js +258 -129
- package/dist/core/pervertmonkey.core.umd.js.map +1 -1
- package/dist/userscripts/3hentai.user.js +4 -5
- package/dist/userscripts/camgirlfinder.user.js +2 -2
- package/dist/userscripts/camwhores.user.js +7 -16
- package/dist/userscripts/e-hentai.user.js +8 -8
- package/dist/userscripts/ebalka.user.js +18 -10
- package/dist/userscripts/eporner.user.js +24 -41
- package/dist/userscripts/erome.user.js +13 -16
- package/dist/userscripts/eroprofile.user.js +5 -14
- package/dist/userscripts/javhdporn.user.js +6 -5
- package/dist/userscripts/missav.user.js +10 -4
- package/dist/userscripts/motherless.user.js +13 -6
- package/dist/userscripts/namethatporn.user.js +10 -16
- package/dist/userscripts/nhentai.user.js +5 -13
- package/dist/userscripts/obmenvsem.user.js +11 -4
- package/dist/userscripts/pornhub.user.js +14 -6
- package/dist/userscripts/spankbang.user.js +28 -7
- package/dist/userscripts/thisvid.user.js +15 -33
- package/dist/userscripts/xhamster.user.js +13 -18
- package/dist/userscripts/xvideos.user.js +33 -5
- package/package.json +1 -1
- package/src/core/data-handler/data-filter-fn-defaults.ts +52 -0
- package/src/core/data-handler/data-filter-fn.ts +62 -0
- package/src/core/data-handler/data-filter.ts +31 -103
- package/src/core/data-handler/data-manager.ts +91 -28
- package/src/core/jabroni-config/default-scheme.ts +54 -5
- package/src/core/jabroni-config/index.ts +1 -0
- package/src/core/jabroni-config/jabroni-gui-controller.ts +1 -1
- package/src/core/jabroni-config/scheme-selectors-mapping.ts +12 -0
- package/src/core/parsers/thumb-data-parser.ts +15 -19
- package/src/core/rules/index.ts +15 -9
- package/src/userscripts/index.ts +1 -1
- package/src/userscripts/scripts/3hentai.ts +3 -4
- package/src/userscripts/scripts/camgirlfinder.ts +1 -1
- package/src/userscripts/scripts/camwhores.ts +5 -14
- package/src/userscripts/scripts/e-hentai.ts +12 -12
- package/src/userscripts/scripts/ebalka.ts +16 -8
- package/src/userscripts/scripts/eporner.ts +23 -39
- package/src/userscripts/scripts/erome.ts +13 -17
- package/src/userscripts/scripts/eroprofile.ts +4 -12
- package/src/userscripts/scripts/javhdporn.ts +7 -8
- package/src/userscripts/scripts/missav.ts +10 -4
- package/src/userscripts/scripts/motherless.ts +13 -7
- package/src/userscripts/scripts/namethatporn.ts +10 -17
- package/src/userscripts/scripts/nhentai.ts +6 -13
- package/src/userscripts/scripts/obmenvsem.ts +14 -4
- package/src/userscripts/scripts/pornhub.ts +13 -4
- package/src/userscripts/scripts/spankbang.ts +29 -5
- package/src/userscripts/scripts/thisvid.ts +16 -31
- package/src/userscripts/scripts/xhamster.ts +13 -18
- package/src/userscripts/scripts/xvideos.ts +32 -3
- package/src/utils/dom/dom-observers.ts +3 -3
- package/src/utils/dom/index.ts +1 -1
- package/src/utils/parsers/index.ts +5 -2
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// ==UserScript==
|
|
2
2
|
// @name Obmensvem PervertMonkey
|
|
3
3
|
// @namespace pervertmonkey
|
|
4
|
-
// @version 1.0.
|
|
4
|
+
// @version 1.0.8
|
|
5
5
|
// @author violent-orangutan
|
|
6
|
-
// @description Infinite scroll [optional], Filter by Title and Duration
|
|
6
|
+
// @description Infinite scroll [optional], Filter by Title and Duration, Sort by Duration
|
|
7
7
|
// @license MIT
|
|
8
8
|
// @icon https://www.google.com/s2/favicons?sz=64&domain=obmenvsem.com
|
|
9
9
|
// @homepage https://github.com/smartacephale/sleazy-fork
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
// @supportURL https://github.com/smartacephale/sleazy-fork/issues
|
|
13
13
|
// @match https://*.obmenvsem.com/*
|
|
14
14
|
// @match https://*.obmenvsem.*/*
|
|
15
|
-
// @
|
|
15
|
+
// @match https://*.obmenvsems.*/*
|
|
16
|
+
// @require https://cdn.jsdelivr.net/npm/pervert-monkey@1.0.17/dist/core/pervertmonkey.core.umd.js
|
|
16
17
|
// @require data:application/javascript,var core = window.pervertmonkey.core || pervertmonkey.core; var utils = core;
|
|
17
18
|
// @grant GM_addElement
|
|
18
19
|
// @grant GM_addStyle
|
|
@@ -77,7 +78,13 @@
|
|
|
77
78
|
return img.src;
|
|
78
79
|
}
|
|
79
80
|
},
|
|
80
|
-
schemeOptions: [
|
|
81
|
+
schemeOptions: [
|
|
82
|
+
"Title Filter",
|
|
83
|
+
"Duration Filter",
|
|
84
|
+
"Sort By Duration",
|
|
85
|
+
"Badge",
|
|
86
|
+
"Advanced"
|
|
87
|
+
]
|
|
81
88
|
});
|
|
82
89
|
|
|
83
90
|
})(core, utils);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// ==UserScript==
|
|
2
2
|
// @name PornHub PervertMonkey
|
|
3
3
|
// @namespace pervertmonkey
|
|
4
|
-
// @version 4.0.
|
|
4
|
+
// @version 4.0.7
|
|
5
5
|
// @author violent-orangutan
|
|
6
|
-
// @description Infinite scroll [optional]. Filter by Title and Duration
|
|
6
|
+
// @description Infinite scroll [optional]. Filter by Title, Uploader and Duration. Sort by Duration and Views
|
|
7
7
|
// @license MIT
|
|
8
8
|
// @icon https://www.google.com/s2/favicons?sz=64&domain=pornhub.com
|
|
9
9
|
// @homepage https://github.com/smartacephale/sleazy-fork
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// @supportURL https://github.com/smartacephale/sleazy-fork/issues
|
|
13
13
|
// @match https://*.pornhub.com/*
|
|
14
14
|
// @exclude https://*.pornhub.com/embed/*
|
|
15
|
-
// @require https://cdn.jsdelivr.net/npm/pervert-monkey@1.0.
|
|
15
|
+
// @require https://cdn.jsdelivr.net/npm/pervert-monkey@1.0.17/dist/core/pervertmonkey.core.umd.js
|
|
16
16
|
// @require data:application/javascript,var core = window.pervertmonkey.core || pervertmonkey.core; var utils = core;
|
|
17
17
|
// @grant GM_addStyle
|
|
18
18
|
// @grant unsafeWindow
|
|
@@ -28,20 +28,28 @@
|
|
|
28
28
|
overwritePaginationLast: (n) => n === 9 ? 9999 : n
|
|
29
29
|
},
|
|
30
30
|
containerSelector: () => [...document.querySelectorAll("ul:has(> li[data-video-vkey])")].filter((e) => e.children.length > 0 && e.checkVisibility()).pop(),
|
|
31
|
-
|
|
31
|
+
containerHomogenity: { id: true, className: true },
|
|
32
32
|
thumbs: { selector: "li[data-video-vkey]" },
|
|
33
33
|
thumb: {
|
|
34
34
|
selectors: {
|
|
35
35
|
title: "span.title",
|
|
36
36
|
uploader: ".usernameWrap",
|
|
37
|
-
duration: ".duration"
|
|
37
|
+
duration: ".duration",
|
|
38
|
+
views: { selector: ".views", type: "float" }
|
|
38
39
|
}
|
|
39
40
|
},
|
|
40
41
|
thumbImg: {
|
|
41
42
|
selector: ["data-mediumthumb", "data-image"]
|
|
42
43
|
},
|
|
43
44
|
gropeStrategy: "all-in-all",
|
|
44
|
-
schemeOptions: [
|
|
45
|
+
schemeOptions: [
|
|
46
|
+
"Title Filter",
|
|
47
|
+
"Uploader Filter",
|
|
48
|
+
"Duration Filter",
|
|
49
|
+
"Sort By",
|
|
50
|
+
"Badge",
|
|
51
|
+
"Advanced"
|
|
52
|
+
]
|
|
45
53
|
});
|
|
46
54
|
function bypassAgeVerification() {
|
|
47
55
|
cookieStore.set({
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// ==UserScript==
|
|
2
2
|
// @name SpankBang.com PervertMonkey
|
|
3
3
|
// @namespace pervertmonkey
|
|
4
|
-
// @version 4.0.
|
|
4
|
+
// @version 4.0.7
|
|
5
5
|
// @author violent-orangutan
|
|
6
|
-
// @description Infinite scroll [optional]. Filter by Title and Duration
|
|
6
|
+
// @description Infinite scroll [optional]. Filter by Title and Duration. Sort by Duration and Views
|
|
7
7
|
// @license MIT
|
|
8
8
|
// @icon https://www.google.com/s2/favicons?sz=64&domain=spankbang.com
|
|
9
9
|
// @homepage https://github.com/smartacephale/sleazy-fork
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
// @supportURL https://github.com/smartacephale/sleazy-fork/issues
|
|
13
13
|
// @match https://*.spankbang.com/*
|
|
14
14
|
// @match https://*.spankbang.*/*
|
|
15
|
-
// @require https://cdn.jsdelivr.net/npm/pervert-monkey@1.0.
|
|
15
|
+
// @require https://cdn.jsdelivr.net/npm/pervert-monkey@1.0.17/dist/core/pervertmonkey.core.umd.js
|
|
16
16
|
// @require data:application/javascript,var core = window.pervertmonkey.core || pervertmonkey.core; var utils = core;
|
|
17
17
|
// @grant GM_addStyle
|
|
18
18
|
// @grant unsafeWindow
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
(function (core) {
|
|
23
23
|
'use strict';
|
|
24
24
|
|
|
25
|
-
new core.Rules({
|
|
25
|
+
const rules = new core.Rules({
|
|
26
26
|
containerSelector: ".main-container .js-media-list, .main_content_container .video-list",
|
|
27
27
|
paginationStrategyOptions: {
|
|
28
28
|
paginationSelector: ".paginate-bar, .pagination"
|
|
@@ -31,13 +31,34 @@
|
|
|
31
31
|
thumb: {
|
|
32
32
|
selectors: {
|
|
33
33
|
title: "[title]",
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
duration: '[data-testid="video-item-length"]',
|
|
35
|
+
views: { selector: '[data-testid="views"]', type: "float" },
|
|
36
|
+
quality: { selector: '[data-testid="video-item-resolution"]', type: "string" }
|
|
36
37
|
}
|
|
37
38
|
},
|
|
38
39
|
thumbImg: { strategy: "auto" },
|
|
39
40
|
gropeStrategy: "all-in-all",
|
|
40
|
-
|
|
41
|
+
customDataFilterFns: [
|
|
42
|
+
{ qualityLow: (e, state) => !!state.qualityLow && e.quality !== "" },
|
|
43
|
+
{ qualityHD: (e, state) => !!state.qualityHD && e.quality !== "HD" },
|
|
44
|
+
{ quality4k: (e, state) => !!state.quality4k && e.quality !== "4K" }
|
|
45
|
+
],
|
|
46
|
+
schemeOptions: [
|
|
47
|
+
"Title Filter",
|
|
48
|
+
"Duration Filter",
|
|
49
|
+
{
|
|
50
|
+
title: "Quality Filter",
|
|
51
|
+
content: [
|
|
52
|
+
{ qualityLow: false, label: "Low" },
|
|
53
|
+
{ qualityHD: false, label: "HD" },
|
|
54
|
+
{ quality4k: false, label: "4K" }
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
"Sort By",
|
|
58
|
+
"Badge",
|
|
59
|
+
"Advanced"
|
|
60
|
+
]
|
|
41
61
|
});
|
|
62
|
+
console.log(rules.dataManager.data.values().toArray());
|
|
42
63
|
|
|
43
64
|
})(core);
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// ==UserScript==
|
|
2
2
|
// @name ThisVid.com Improved
|
|
3
3
|
// @namespace pervertmonkey
|
|
4
|
-
// @version 8.0.
|
|
4
|
+
// @version 8.0.7
|
|
5
5
|
// @author violent-orangutan
|
|
6
|
-
// @description Infinite scroll [optional]. Preview for private videos. Filter
|
|
6
|
+
// @description Infinite scroll [optional]. Preview for private videos. Filter by Title, Duration, Quality and Public/Private. Sort by Duration and Views. Private/Public feed of friends uploads. Check access to private vids. Mass friend request button. Sorts messages. Download button 📼
|
|
7
7
|
// @license MIT
|
|
8
8
|
// @icon https://www.google.com/s2/favicons?sz=64&domain=thisvid.com
|
|
9
9
|
// @homepage https://github.com/smartacephale/sleazy-fork
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// @source github:smartacephale/sleazy-fork
|
|
12
12
|
// @supportURL https://github.com/smartacephale/sleazy-fork/issues
|
|
13
13
|
// @match https://*.thisvid.com/*
|
|
14
|
-
// @require https://cdn.jsdelivr.net/npm/pervert-monkey@1.0.
|
|
14
|
+
// @require https://cdn.jsdelivr.net/npm/pervert-monkey@1.0.17/dist/core/pervertmonkey.core.umd.js
|
|
15
15
|
// @require data:application/javascript,var core = window.pervertmonkey.core || pervertmonkey.core; var utils = core;
|
|
16
16
|
// @grant GM_addStyle
|
|
17
17
|
// @grant unsafeWindow
|
|
@@ -929,36 +929,17 @@ function takeWhile(predicate) {
|
|
|
929
929
|
return { img, imgSrc };
|
|
930
930
|
}
|
|
931
931
|
},
|
|
932
|
-
|
|
932
|
+
containerSelector: () => utils.querySelectorLast(
|
|
933
|
+
document,
|
|
934
|
+
"div:has(> .tumbpu[title]):not(.thumbs-photo), div:has(> .thumb-holder)"
|
|
935
|
+
) || document.querySelector(".thumbs-items"),
|
|
933
936
|
animatePreview,
|
|
934
|
-
customDataSelectorFns: [
|
|
935
|
-
"filterInclude",
|
|
936
|
-
"filterExclude",
|
|
937
|
-
"filterDuration",
|
|
938
|
-
{
|
|
939
|
-
filterPrivate: (el, state) => state.filterPrivate && el.private
|
|
940
|
-
},
|
|
941
|
-
{
|
|
942
|
-
filterPublic: (el, state) => state.filterPublic && !el.private
|
|
943
|
-
},
|
|
944
|
-
{
|
|
945
|
-
filterHD: (el, state) => state.filterHD && !el.hd
|
|
946
|
-
},
|
|
947
|
-
{
|
|
948
|
-
filterNonHD: (el, state) => state.filterNonHD && el.hd
|
|
949
|
-
}
|
|
950
|
-
],
|
|
951
937
|
schemeOptions: [
|
|
952
|
-
"
|
|
938
|
+
"Title Filter",
|
|
953
939
|
"Duration Filter",
|
|
954
940
|
"Privacy Filter",
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
content: [
|
|
958
|
-
{ filterHD: false, label: "hd" },
|
|
959
|
-
{ filterNonHD: false, label: "non-hd" }
|
|
960
|
-
]
|
|
961
|
-
},
|
|
941
|
+
"HD Filter",
|
|
942
|
+
"Sort By",
|
|
962
943
|
"Badge",
|
|
963
944
|
{
|
|
964
945
|
title: "Advanced",
|
|
@@ -1014,9 +995,9 @@ function takeWhile(predicate) {
|
|
|
1014
995
|
}
|
|
1015
996
|
return g();
|
|
1016
997
|
}
|
|
1017
|
-
function getMembers(
|
|
1018
|
-
const friendsList =
|
|
1019
|
-
return Array.from(friendsList.querySelectorAll(".tumbpu") || []).map((
|
|
998
|
+
function getMembers(e) {
|
|
999
|
+
const friendsList = e.querySelector("#list_members_friends_items") || e;
|
|
1000
|
+
return Array.from(friendsList.querySelectorAll(".tumbpu") || []).map((e2) => e2.href.match(/\d+/)?.[0]).filter((_) => _);
|
|
1020
1001
|
}
|
|
1021
1002
|
async function friendMemberFriends(orientationFilter) {
|
|
1022
1003
|
const memberId = window.location.pathname.match(/\d+/)?.[0];
|
|
@@ -1164,6 +1145,7 @@ function takeWhile(predicate) {
|
|
|
1164
1145
|
(target) => {
|
|
1165
1146
|
const img = target.querySelector("img");
|
|
1166
1147
|
const orig = img.getAttribute("src");
|
|
1148
|
+
if (!orig) return;
|
|
1167
1149
|
tick.start(
|
|
1168
1150
|
() => iteratePreviewFrames(img),
|
|
1169
1151
|
() => {
|
|
@@ -1322,7 +1304,7 @@ function takeWhile(predicate) {
|
|
|
1322
1304
|
paginationSelector: ".footer"
|
|
1323
1305
|
},
|
|
1324
1306
|
schemeOptions: [
|
|
1325
|
-
"
|
|
1307
|
+
"Title Filter",
|
|
1326
1308
|
"Duration Filter",
|
|
1327
1309
|
"Privacy Filter",
|
|
1328
1310
|
"Badge",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// ==UserScript==
|
|
2
2
|
// @name Xhamster Improved
|
|
3
3
|
// @namespace pervertmonkey
|
|
4
|
-
// @version 5.0.
|
|
4
|
+
// @version 5.0.8
|
|
5
5
|
// @author violent-orangutan
|
|
6
|
-
// @description Infinite scroll [optional], Filter by Title and Duration
|
|
6
|
+
// @description Infinite scroll [optional], Filter by Title, Duration and Watched/Unwatched. Sort by Duration and Views
|
|
7
7
|
// @license MIT
|
|
8
8
|
// @icon https://www.google.com/s2/favicons?sz=64&domain=xhamster.com
|
|
9
9
|
// @homepage https://github.com/smartacephale/sleazy-fork
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
// @match https://*.xhamster.com/*
|
|
14
14
|
// @match https://*.xhamster.*/*
|
|
15
15
|
// @exclude https://*.xhamster.com/embed*
|
|
16
|
-
// @require https://cdn.jsdelivr.net/npm/pervert-monkey@1.0.
|
|
16
|
+
// @require https://cdn.jsdelivr.net/npm/pervert-monkey@1.0.17/dist/core/pervertmonkey.core.umd.js
|
|
17
17
|
// @require data:application/javascript,var core = window.pervertmonkey.core || pervertmonkey.core; var utils = core;
|
|
18
18
|
// @grant GM_addElement
|
|
19
19
|
// @grant GM_addStyle
|
|
@@ -80,10 +80,8 @@
|
|
|
80
80
|
selectors: {
|
|
81
81
|
title: ".video-thumb-info__name,.video-thumb-info>a",
|
|
82
82
|
duration: ".thumb-image-container__duration",
|
|
83
|
-
watched: {
|
|
84
|
-
|
|
85
|
-
selector: '[data-role="video-watched'
|
|
86
|
-
}
|
|
83
|
+
watched: { selector: '[data-role="video-watched', type: "boolean" },
|
|
84
|
+
views: { selector: ".video-thumb-views", type: "float" }
|
|
87
85
|
}
|
|
88
86
|
},
|
|
89
87
|
thumbImg: {
|
|
@@ -91,20 +89,16 @@
|
|
|
91
89
|
remove: "[loading]"
|
|
92
90
|
},
|
|
93
91
|
gropeStrategy: "all-in-all",
|
|
94
|
-
|
|
95
|
-
"filterInclude",
|
|
96
|
-
"filterExclude",
|
|
97
|
-
"filterDuration",
|
|
92
|
+
customDataFilterFns: [
|
|
98
93
|
{
|
|
99
|
-
filterWatched: (
|
|
94
|
+
filterWatched: (e, state) => !!(state.filterWatched && e.watched)
|
|
100
95
|
},
|
|
101
96
|
{
|
|
102
|
-
filterUnwatched: (
|
|
97
|
+
filterUnwatched: (e, state) => !!(state.filterUnwatched && !e.watched)
|
|
103
98
|
}
|
|
104
99
|
],
|
|
105
100
|
schemeOptions: [
|
|
106
|
-
"
|
|
107
|
-
"Badge",
|
|
101
|
+
"Title Filter",
|
|
108
102
|
{
|
|
109
103
|
title: "Filter Watched",
|
|
110
104
|
content: [
|
|
@@ -112,7 +106,9 @@
|
|
|
112
106
|
{ filterUnwatched: false, label: "unwatched" }
|
|
113
107
|
]
|
|
114
108
|
},
|
|
109
|
+
"Sort By",
|
|
115
110
|
"Duration Filter",
|
|
111
|
+
"Badge",
|
|
116
112
|
"Advanced"
|
|
117
113
|
],
|
|
118
114
|
animatePreview
|
|
@@ -138,17 +134,16 @@
|
|
|
138
134
|
utils.OnHover.create(document.body, ".video-thumb", (e) => {
|
|
139
135
|
const container = e.querySelector(".thumb-image-container__image");
|
|
140
136
|
const videoSrc = e.querySelector("[data-previewvideo]")?.getAttribute("data-previewvideo");
|
|
141
|
-
console.log(container, videoSrc);
|
|
142
137
|
return createPreviewVideoElement(videoSrc, container);
|
|
143
138
|
});
|
|
144
139
|
}
|
|
145
140
|
function expandMoreVideoPage() {
|
|
146
141
|
utils.watchElementChildrenCount(rules.container, () => setTimeout(rules.gropeInit, 1800));
|
|
147
|
-
utils.waitForElementToAppear(document.body, 'button[data-role="show-more-next"]', (
|
|
142
|
+
utils.waitForElementToAppear(document.body, 'button[data-role="show-more-next"]', (e) => {
|
|
148
143
|
const observer = new utils.Observer((target) => {
|
|
149
144
|
target.click();
|
|
150
145
|
});
|
|
151
|
-
observer.observe(
|
|
146
|
+
observer.observe(e);
|
|
152
147
|
});
|
|
153
148
|
}
|
|
154
149
|
if (IS_VIDEO_PAGE) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// ==UserScript==
|
|
2
2
|
// @name XVideos Improved
|
|
3
3
|
// @namespace pervertmonkey
|
|
4
|
-
// @version 4.0.
|
|
4
|
+
// @version 4.0.8
|
|
5
5
|
// @author violent-orangutan
|
|
6
|
-
// @description Infinite scroll [optional], Filter by Title and Duration
|
|
6
|
+
// @description Infinite scroll [optional], Filter by Title, Uploader and Duration. Sort by Duration and Views.
|
|
7
7
|
// @license MIT
|
|
8
8
|
// @icon https://www.google.com/s2/favicons?sz=64&domain=xvideos.com
|
|
9
9
|
// @homepage https://github.com/smartacephale/sleazy-fork
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// @source github:smartacephale/sleazy-fork
|
|
12
12
|
// @supportURL https://github.com/smartacephale/sleazy-fork/issues
|
|
13
13
|
// @match https://*.xvideos.com/*
|
|
14
|
-
// @require https://cdn.jsdelivr.net/npm/pervert-monkey@1.0.
|
|
14
|
+
// @require https://cdn.jsdelivr.net/npm/pervert-monkey@1.0.17/dist/core/pervertmonkey.core.umd.js
|
|
15
15
|
// @require data:application/javascript,var core = window.pervertmonkey.core || pervertmonkey.core; var utils = core;
|
|
16
16
|
// @grant GM_addStyle
|
|
17
17
|
// @grant unsafeWindow
|
|
@@ -35,7 +35,9 @@
|
|
|
35
35
|
selectors: {
|
|
36
36
|
title: "[class*=title]",
|
|
37
37
|
uploader: "[class*=name]",
|
|
38
|
-
duration: "[class*=duration]"
|
|
38
|
+
duration: "[class*=duration]",
|
|
39
|
+
views: { selector: ".metadata a ~ span", type: "float" },
|
|
40
|
+
quality: { selector: ".video-hd-mark", type: "string" }
|
|
39
41
|
},
|
|
40
42
|
callback: (thumb) => {
|
|
41
43
|
setTimeout(() => {
|
|
@@ -44,7 +46,33 @@
|
|
|
44
46
|
}, 200);
|
|
45
47
|
}
|
|
46
48
|
},
|
|
47
|
-
|
|
49
|
+
customDataFilterFns: [
|
|
50
|
+
{ qualityLow: (e, state) => !!state.qualityLow && e.quality !== "" },
|
|
51
|
+
{ quality360: (e, state) => !!state.quality360 && e.quality !== "360p" },
|
|
52
|
+
{ quality720: (e, state) => !!state.quality720 && e.quality !== "720p" },
|
|
53
|
+
{ quality1080: (e, state) => !!state.quality1080 && e.quality !== "1080p" },
|
|
54
|
+
{ quality1440: (e, state) => !!state.quality1440 && e.quality !== "1440p" },
|
|
55
|
+
{ quality4k: (e, state) => !!state.quality4k && e.quality !== "4k" }
|
|
56
|
+
],
|
|
57
|
+
schemeOptions: [
|
|
58
|
+
"Title Filter",
|
|
59
|
+
"Uploader Filter",
|
|
60
|
+
"Duration Filter",
|
|
61
|
+
{
|
|
62
|
+
title: "Quality Filter",
|
|
63
|
+
content: [
|
|
64
|
+
{ qualityLow: false, label: "Low" },
|
|
65
|
+
{ quality360: false, label: "360p" },
|
|
66
|
+
{ quality720: false, label: "720p" },
|
|
67
|
+
{ quality1080: false, label: "1080p" },
|
|
68
|
+
{ quality1440: false, label: "1440p" },
|
|
69
|
+
{ quality4k: false, label: "4k" }
|
|
70
|
+
]
|
|
71
|
+
},
|
|
72
|
+
"Sort By",
|
|
73
|
+
"Badge",
|
|
74
|
+
"Advanced"
|
|
75
|
+
],
|
|
48
76
|
animatePreview
|
|
49
77
|
});
|
|
50
78
|
function animatePreview(container) {
|
package/package.json
CHANGED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { RegexFilter } from '../../utils';
|
|
2
|
+
import type { DataFilterFnFrom } from './data-filter-fn';
|
|
3
|
+
|
|
4
|
+
function createTextFilter(
|
|
5
|
+
filterName: string,
|
|
6
|
+
dataPropName: string,
|
|
7
|
+
positive: boolean,
|
|
8
|
+
): DataFilterFnFrom<(_: string) => boolean> {
|
|
9
|
+
const filterNameValue = `${filterName}Words`;
|
|
10
|
+
return {
|
|
11
|
+
handle(e, state, searchFilter) {
|
|
12
|
+
if (!Object.hasOwn(state, filterName) || !state[filterName]) return false;
|
|
13
|
+
return !searchFilter?.(e[dataPropName] as string);
|
|
14
|
+
},
|
|
15
|
+
$preDefine: (state) => {
|
|
16
|
+
const r = new RegexFilter(state[filterNameValue] as string);
|
|
17
|
+
if (positive) return (s: string) => r.hasEvery(s);
|
|
18
|
+
return (s: string) => r.hasNone(s);
|
|
19
|
+
},
|
|
20
|
+
deps: [filterNameValue],
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const filterDuration: DataFilterFnFrom<(_: number) => boolean> = {
|
|
25
|
+
handle(e, state, notInRange) {
|
|
26
|
+
if (!state.filterDuration) return false;
|
|
27
|
+
return !!notInRange?.(e.duration as number);
|
|
28
|
+
},
|
|
29
|
+
$preDefine: (state) => {
|
|
30
|
+
const from = state.filterDurationFrom as number;
|
|
31
|
+
const to = state.filterDurationTo as number;
|
|
32
|
+
function notInRange(d: number): boolean {
|
|
33
|
+
return d < from || d > to;
|
|
34
|
+
}
|
|
35
|
+
return notInRange;
|
|
36
|
+
},
|
|
37
|
+
deps: ['filterDurationFrom', 'filterDurationTo'],
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const defaultDataFilterFns: Record<string, DataFilterFnFrom<any>> = {
|
|
41
|
+
filterDuration,
|
|
42
|
+
|
|
43
|
+
filterExclude: createTextFilter('filterExclude', 'title', false),
|
|
44
|
+
filterInclude: createTextFilter('filterInclude', 'title', true),
|
|
45
|
+
filterUploaderExclude: createTextFilter('filterUploaderExclude', 'uploader', false),
|
|
46
|
+
filterUploaderInclude: createTextFilter('filterUploaderInclude', 'uploader', true),
|
|
47
|
+
|
|
48
|
+
filterHD: (e, state) => (state.filterHD && !e.hd) as boolean,
|
|
49
|
+
filterNonHD: (e, state) => (state.filterNonHD && e.hd) as boolean,
|
|
50
|
+
filterPrivate: (e, state) => (state.filterPrivate && e.private) as boolean,
|
|
51
|
+
filterPublic: (e, state) => (state.filterPublic && !e.private) as boolean,
|
|
52
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { StoreState } from 'jabroni-outfit';
|
|
2
|
+
import type { DataElement } from './data-manager';
|
|
3
|
+
|
|
4
|
+
export type DataFilterFnHandle<R> = (
|
|
5
|
+
el: DataElement,
|
|
6
|
+
state: StoreState,
|
|
7
|
+
$preDefineResult?: R,
|
|
8
|
+
) => boolean;
|
|
9
|
+
|
|
10
|
+
export type DataFilterFnFrom<R> = Partial<DataFilterFn<R>> | DataFilterFnHandle<R>;
|
|
11
|
+
|
|
12
|
+
export type DataFilterFnRenderedResult = {
|
|
13
|
+
name: string;
|
|
14
|
+
condition: boolean;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type DataFilterFnRendered = (v: DataElement) => DataFilterFnRenderedResult;
|
|
18
|
+
|
|
19
|
+
export class DataFilterFn<R> {
|
|
20
|
+
public static prefix = 'filter-';
|
|
21
|
+
|
|
22
|
+
public static setPrefix(name: string) {
|
|
23
|
+
return `${DataFilterFn.prefix}${name}`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
constructor(
|
|
27
|
+
public handle: DataFilterFnHandle<R>,
|
|
28
|
+
public deps: string[] = [],
|
|
29
|
+
public name: string,
|
|
30
|
+
public $preDefine?: (state: StoreState) => R,
|
|
31
|
+
) {
|
|
32
|
+
this.name = DataFilterFn.setPrefix(name);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public static from<R>(options: DataFilterFnFrom<R>, name: string) {
|
|
36
|
+
if (typeof options === 'function') {
|
|
37
|
+
const deps = [name];
|
|
38
|
+
return new DataFilterFn(options, deps, name);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return new DataFilterFn(
|
|
42
|
+
options.handle as DataFilterFnHandle<R>,
|
|
43
|
+
options.deps,
|
|
44
|
+
name,
|
|
45
|
+
options.$preDefine,
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public renderFn(state: StoreState) {
|
|
50
|
+
const name = this.name;
|
|
51
|
+
|
|
52
|
+
return (): DataFilterFnRendered => {
|
|
53
|
+
const preDefined = this.$preDefine?.(state);
|
|
54
|
+
|
|
55
|
+
return (a: DataElement) => {
|
|
56
|
+
const condition = this.handle(a, state, preDefined);
|
|
57
|
+
|
|
58
|
+
return ({ condition, name });
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
}
|