pervert-monkey 1.0.7 → 1.0.8
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/userscripts/3hentai.user.js +34 -0
- package/dist/userscripts/camgirlfinder.user.js +66 -0
- package/dist/userscripts/camwhores.user.js +375 -0
- package/dist/userscripts/e-hentai.user.js +70 -0
- package/dist/userscripts/ebalka.user.js +63 -0
- package/dist/userscripts/eporner.user.js +103 -0
- package/dist/userscripts/erome.user.js +105 -0
- package/dist/userscripts/eroprofile.user.js +52 -0
- package/dist/userscripts/javhdporn.user.js +36 -0
- package/dist/userscripts/missav.user.js +40 -0
- package/dist/userscripts/motherless.user.js +178 -0
- package/dist/userscripts/namethatporn.user.js +77 -0
- package/dist/userscripts/nhentai.user.js +120 -0
- package/dist/userscripts/pornhub.user.js +57 -0
- package/dist/userscripts/spankbang.user.js +71 -0
- package/dist/userscripts/thisvid.user.js +1411 -0
- package/dist/userscripts/xhamster.user.js +161 -0
- package/dist/userscripts/xvideos.user.js +87 -0
- package/package.json +1 -1
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// ==UserScript==
|
|
2
|
+
// @name Xhamster Improved
|
|
3
|
+
// @namespace pervertmonkey
|
|
4
|
+
// @version 5.0.1
|
|
5
|
+
// @author violent-orangutan
|
|
6
|
+
// @description Infinite scroll [optional], Filter by Title and Duration
|
|
7
|
+
// @license MIT
|
|
8
|
+
// @icon https://www.google.com/s2/favicons?sz=64&domain=xhamster.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://*.xhamster.com/*
|
|
14
|
+
// @match https://*.xhamster.*/*
|
|
15
|
+
// @exclude https://*.xhamster.com/embed*
|
|
16
|
+
// @require https://cdn.jsdelivr.net/npm/pervert-monkey@1.0.8/dist/core/pervertmonkey.core.umd.js
|
|
17
|
+
// @require data:application/javascript,var core = window.pervertmonkey.core || pervertmonkey.core; var utils = core;
|
|
18
|
+
// @grant GM_addStyle
|
|
19
|
+
// @grant unsafeWindow
|
|
20
|
+
// @run-at document-idle
|
|
21
|
+
// ==/UserScript==
|
|
22
|
+
|
|
23
|
+
(function (core, utils) {
|
|
24
|
+
'use strict';
|
|
25
|
+
|
|
26
|
+
var _unsafeWindow = (() => typeof unsafeWindow != "undefined" ? unsafeWindow : undefined)();
|
|
27
|
+
|
|
28
|
+
const IS_VIDEO_PAGE = /^\/videos|moments\//.test(location.pathname);
|
|
29
|
+
const IS_PLAYLIST = /^\/my\/favorites\/videos\/\w+/.test(location.pathname);
|
|
30
|
+
function createThumb(data) {
|
|
31
|
+
const attrsToReplace = {
|
|
32
|
+
href: data.pageURL,
|
|
33
|
+
"data-previewvideo": data.trailerURL,
|
|
34
|
+
"data-previewvideo-fallback": data.trailerFallbackUrl,
|
|
35
|
+
"data-sprite": data.spriteURL,
|
|
36
|
+
title: data.title,
|
|
37
|
+
"data-video-id": data.id,
|
|
38
|
+
srcset: data.thumbURL,
|
|
39
|
+
src: data.imageURL
|
|
40
|
+
};
|
|
41
|
+
const text = {
|
|
42
|
+
".video-thumb-views": data.views,
|
|
43
|
+
"[title]": data.title,
|
|
44
|
+
'[data-role="video-duration"] div': data.duration
|
|
45
|
+
};
|
|
46
|
+
return utils.instantiateTemplate(".video-thumb", attrsToReplace, text);
|
|
47
|
+
}
|
|
48
|
+
const getPaginationData = !IS_PLAYLIST ? void 0 : async (url) => {
|
|
49
|
+
const data = await utils.fetchJson(url);
|
|
50
|
+
const thumbsHtml = data.list.map((e) => createThumb(e)).join("\n");
|
|
51
|
+
return utils.parseHtml(`<div>${thumbsHtml}</div>`);
|
|
52
|
+
};
|
|
53
|
+
function createPlaylistPaginationStrategy() {
|
|
54
|
+
const collectionId = location.pathname.split("/my/favorites/videos/")[1].split("-")[0];
|
|
55
|
+
const data = _unsafeWindow.initials;
|
|
56
|
+
const paginationLast = data.favoritesVideoPaging.maxPages;
|
|
57
|
+
const paginationOffset = data.favoritesVideoPaging.active;
|
|
58
|
+
const playlistPaginationStrategy = {
|
|
59
|
+
paginationSelector: 'nav[class *= "pagination"]',
|
|
60
|
+
getPaginationLast: () => paginationLast,
|
|
61
|
+
getPaginationOffset: () => paginationOffset,
|
|
62
|
+
getPaginationUrlGenerator: () => (offset) => {
|
|
63
|
+
return `https://xhamster.com/api/front/favorite/get-playlist?id=${collectionId}&perPage=60&page=${offset}`;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
return playlistPaginationStrategy;
|
|
67
|
+
}
|
|
68
|
+
const paginationStrategyOptionsDefault = {
|
|
69
|
+
paginationSelector: ".prev-next-list, .test-pager"
|
|
70
|
+
};
|
|
71
|
+
const paginationStrategyOptions = IS_PLAYLIST ? createPlaylistPaginationStrategy() : paginationStrategyOptionsDefault;
|
|
72
|
+
const rules = new core.RulesGlobal({
|
|
73
|
+
paginationStrategyOptions,
|
|
74
|
+
getPaginationData,
|
|
75
|
+
containerSelectorLast: ".thumb-list",
|
|
76
|
+
thumbsSelector: ".video-thumb",
|
|
77
|
+
titleSelector: ".video-thumb-info__name,.video-thumb-info>a",
|
|
78
|
+
durationSelector: ".thumb-image-container__duration",
|
|
79
|
+
gropeStrategy: "all-in-all",
|
|
80
|
+
getThumbImgDataStrategy: "auto",
|
|
81
|
+
getThumbImgDataAttrDelete: "[loading]",
|
|
82
|
+
customThumbDataSelectors: {
|
|
83
|
+
watched: {
|
|
84
|
+
type: "boolean",
|
|
85
|
+
selector: '[data-role="video-watched'
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
customDataSelectorFns: [
|
|
89
|
+
"filterInclude",
|
|
90
|
+
"filterExclude",
|
|
91
|
+
"filterDuration",
|
|
92
|
+
{
|
|
93
|
+
filterWatched: (el, state) => !!(state.filterWatched && el.watched)
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
filterUnwatched: (el, state) => !!(state.filterUnwatched && !el.watched)
|
|
97
|
+
}
|
|
98
|
+
],
|
|
99
|
+
schemeOptions: [
|
|
100
|
+
"Text Filter",
|
|
101
|
+
"Badge",
|
|
102
|
+
{
|
|
103
|
+
title: "Filter Watched",
|
|
104
|
+
content: [
|
|
105
|
+
{ filterWatched: false, label: "watched" },
|
|
106
|
+
{ filterUnwatched: false, label: "unwatched" }
|
|
107
|
+
]
|
|
108
|
+
},
|
|
109
|
+
"Duration Filter",
|
|
110
|
+
"Advanced"
|
|
111
|
+
],
|
|
112
|
+
animatePreview
|
|
113
|
+
});
|
|
114
|
+
function animatePreview() {
|
|
115
|
+
function createPreviewVideoElement(src, mount) {
|
|
116
|
+
const video = document.createElement("video");
|
|
117
|
+
video.playsInline = true;
|
|
118
|
+
video.autoplay = true;
|
|
119
|
+
video.loop = true;
|
|
120
|
+
video.classList.add("thumb-image-container__video");
|
|
121
|
+
video.src = src;
|
|
122
|
+
video.addEventListener(
|
|
123
|
+
"loadeddata",
|
|
124
|
+
() => {
|
|
125
|
+
mount.before(video);
|
|
126
|
+
},
|
|
127
|
+
false
|
|
128
|
+
);
|
|
129
|
+
return () => utils.exterminateVideo(video);
|
|
130
|
+
}
|
|
131
|
+
utils.OnHover.create(
|
|
132
|
+
document.body,
|
|
133
|
+
(e) => e.classList.contains("thumb-image-container__image"),
|
|
134
|
+
(e) => {
|
|
135
|
+
const videoSrc = e.parentElement?.getAttribute("data-previewvideo");
|
|
136
|
+
const onOverCallback = createPreviewVideoElement(videoSrc, e);
|
|
137
|
+
const leaveTarget = e.parentElement?.parentElement;
|
|
138
|
+
return { leaveTarget, onOverCallback };
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
function expandMoreVideoPage() {
|
|
143
|
+
utils.watchElementChildrenCount(rules.container, () => setTimeout(parseThumbs, 1800));
|
|
144
|
+
utils.waitForElementToAppear(document.body, 'button[data-role="show-more-next"]', (el) => {
|
|
145
|
+
const observer = new utils.Observer((target) => {
|
|
146
|
+
target.click();
|
|
147
|
+
});
|
|
148
|
+
observer.observe(el);
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
function parseThumbs() {
|
|
152
|
+
const containers = utils.getCommonParents(rules.getThumbs(document.body));
|
|
153
|
+
containers.forEach((c) => {
|
|
154
|
+
rules.dataManager.parseData(c, c);
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
if (IS_VIDEO_PAGE) {
|
|
158
|
+
expandMoreVideoPage();
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
})(core, utils);
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// ==UserScript==
|
|
2
|
+
// @name XVideos Improved
|
|
3
|
+
// @namespace pervertmonkey
|
|
4
|
+
// @version 4.0.1
|
|
5
|
+
// @author violent-orangutan
|
|
6
|
+
// @description Infinite scroll [optional], Filter by Title and Duration
|
|
7
|
+
// @license MIT
|
|
8
|
+
// @icon https://www.google.com/s2/favicons?sz=64&domain=xvideos.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://*.xvideos.com/*
|
|
14
|
+
// @require https://cdn.jsdelivr.net/npm/pervert-monkey@1.0.8/dist/core/pervertmonkey.core.umd.js
|
|
15
|
+
// @require data:application/javascript,var core = window.pervertmonkey.core || pervertmonkey.core; var utils = core;
|
|
16
|
+
// @grant GM_addStyle
|
|
17
|
+
// @grant unsafeWindow
|
|
18
|
+
// @run-at document-idle
|
|
19
|
+
// ==/UserScript==
|
|
20
|
+
|
|
21
|
+
(function (core, utils) {
|
|
22
|
+
'use strict';
|
|
23
|
+
|
|
24
|
+
var _unsafeWindow = (() => typeof unsafeWindow != "undefined" ? unsafeWindow : undefined)();
|
|
25
|
+
|
|
26
|
+
const xv = _unsafeWindow.xv;
|
|
27
|
+
new core.RulesGlobal({
|
|
28
|
+
paginationStrategyOptions: {
|
|
29
|
+
paginationSelector: "#main .pagination:last-child",
|
|
30
|
+
searchParamSelector: "p"
|
|
31
|
+
},
|
|
32
|
+
containerSelector: "#content > div",
|
|
33
|
+
thumbsSelector: "div.thumb-block[id^=video_]:not(.thumb-ad)",
|
|
34
|
+
titleSelector: "[class*=title]",
|
|
35
|
+
uploaderSelector: "[class*=name]",
|
|
36
|
+
durationSelector: "[class*=duration]",
|
|
37
|
+
gropeStrategy: "all-in-one",
|
|
38
|
+
customDataSelectorFns: ["filterInclude", "filterExclude"],
|
|
39
|
+
schemeOptions: ["Text Filter", "Duration Filter", "Badge", "Advanced"],
|
|
40
|
+
animatePreview,
|
|
41
|
+
getThumbDataCallback(thumb) {
|
|
42
|
+
setTimeout(() => {
|
|
43
|
+
const id = parseInt(thumb.getAttribute("data-id"));
|
|
44
|
+
xv.thumbs.prepareVideo(id);
|
|
45
|
+
}, 200);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
function animatePreview(container) {
|
|
49
|
+
function createPreviewElement(src, mount) {
|
|
50
|
+
const elem = utils.parseHtml(`
|
|
51
|
+
<div class="videopv" style="display: none;">
|
|
52
|
+
<video autoplay="autoplay" playsinline="playsinline" muted="muted"></video>
|
|
53
|
+
</div>`);
|
|
54
|
+
mount.after(elem);
|
|
55
|
+
const video = elem.querySelector("video");
|
|
56
|
+
video.src = src;
|
|
57
|
+
video.addEventListener(
|
|
58
|
+
"loadeddata",
|
|
59
|
+
() => {
|
|
60
|
+
mount.style.opacity = "0";
|
|
61
|
+
elem.style.display = "block";
|
|
62
|
+
elem.style.background = "#000";
|
|
63
|
+
},
|
|
64
|
+
false
|
|
65
|
+
);
|
|
66
|
+
return () => {
|
|
67
|
+
utils.exterminateVideo(video);
|
|
68
|
+
elem.remove();
|
|
69
|
+
mount.style.opacity = "1";
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
function getVideoURL(src) {
|
|
73
|
+
return src.replace(/\w+\.\w+$/, () => "preview.mp4");
|
|
74
|
+
}
|
|
75
|
+
utils.OnHover.create(
|
|
76
|
+
container,
|
|
77
|
+
(target) => target.tagName === "IMG" && target.id.includes("pic_"),
|
|
78
|
+
(target) => {
|
|
79
|
+
const videoSrc = getVideoURL(target.src);
|
|
80
|
+
const onOverCallback = createPreviewElement(videoSrc, target);
|
|
81
|
+
const leaveTarget = target.closest(".thumb-inside");
|
|
82
|
+
return { leaveTarget, onOverCallback };
|
|
83
|
+
}
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
})(core, utils);
|