|
1 | 1 | // ==UserScript== |
2 | 2 | // @name Improve Adult Experience |
3 | 3 | // @description Skip intros, set best quality and duration filters by default, make unrelated video previews transparent |
4 | | -// @version 0.5 |
| 4 | +// @version 0.6 |
5 | 5 | // @downloadURL https://userscripts.codonaft.com/improve-adult-experience.js |
6 | 6 | // @exclude-match https://spankbang.com/*/video/* |
7 | 7 | // @match https://spankbang.com/* |
|
28 | 28 |
|
29 | 29 | const random = (min, max) => Math.floor(Math.random() * (max - min + 1) + min); |
30 | 30 |
|
31 | | - const timeToSeconds = time => (time || '').split(':').map(Number).reduceRight((total, value, index, parts) => total + value * 60 ** (parts.length - 1 - index), 0); |
| 31 | + const timeToSeconds = time => (time || '').trim().split(':').map(Number).reduceRight((total, value, index, parts) => total + value * 60 ** (parts.length - 1 - index), 0); |
32 | 32 |
|
33 | 33 | const simulateClick = (document, node) => { |
34 | 34 | console.log('simulateClick'); |
|
43 | 43 | const pornhub = _ => { |
44 | 44 | // TODO: never redirect, just update the URLs |
45 | 45 |
|
46 | | - const processEmbedded = document => { |
47 | | - const style = document.createElement('style'); |
48 | | - style.innerHTML = ` |
| 46 | + const processEmbedded = (document, similarVideos) => { |
| 47 | + const css = ` |
49 | 48 | div.mgp_topBar { display: none !important; } |
50 | 49 | div.mgp_thumbnailsGrid { display: none !important; } |
51 | 50 | img.mgp_pornhub { display: none !important; } |
52 | 51 | `; |
| 52 | + const styleApplied = [...document.body.querySelectorAll('style')] |
| 53 | + .filter(i => i.innerHTML === css) |
| 54 | + .length > 0; |
| 55 | + if (styleApplied) { |
| 56 | + console.log('embedded video is already initialized'); |
| 57 | + return; |
| 58 | + } |
| 59 | + console.log('applying style'); |
| 60 | + const style = document.createElement('style'); |
| 61 | + style.innerHTML = css; |
53 | 62 | document.body.appendChild(style); |
54 | 63 |
|
| 64 | + const requiresRefresh = document.body.querySelector('div.mgp_errorIcon') && |
| 65 | + document.body.querySelector('p')?.textContent.includes('Please refresh the page'); |
| 66 | + if (requiresRefresh) { |
| 67 | + console.log('refreshing after error'); |
| 68 | + window.location.href = window.location.href; |
| 69 | + } |
| 70 | + |
55 | 71 | const video = document.body.querySelector('video'); |
56 | | - if (!video) return; |
| 72 | + if (!video) { |
| 73 | + console.log('embedding this video is probably not allowed'); |
| 74 | + window.stop(); |
| 75 | + // window.parent.location = window.parent.location; // TODO: do this no more than once during 5 mins for a given video? |
| 76 | + if (similarVideos.length > 0) { |
| 77 | + console.log('redirecting to random non-boring similar video'); |
| 78 | + // TODO: use non-watched videos as priority? |
| 79 | + window.location.href = similarVideos[random(0, similarVideos.length)]; // FIXME: back history |
| 80 | + } else { |
| 81 | + console.log('giving up'); |
| 82 | + } |
| 83 | + return; |
| 84 | + } |
57 | 85 |
|
58 | | - video.addEventListener('loadstart', _ => simulateClick(document, document.querySelector('div.mgp_playIcon'))); |
59 | | - video.addEventListener('loadedmetadata', _ => video.currentTime = random(video.duration / 4, video.duration / 3)); |
60 | | - document.querySelector('div.mgp_gridMenu')?.addEventListener('click', _ => setTimeout(_ => { |
| 86 | + video.addEventListener('loadstart', _ => simulateClick(document, document.body.querySelector('div.mgp_playIcon'))); |
| 87 | + video.addEventListener('loadedmetadata', _ => { |
| 88 | + // TODO: save video size? video.videoHeight |
| 89 | + video.currentTime = random(video.duration / 4, video.duration / 3); |
| 90 | + }); |
| 91 | + document.body.querySelector('div.mgp_gridMenu')?.addEventListener('click', _ => setTimeout(_ => { |
61 | 92 | if (video.paused) { |
62 | 93 | console.log('paused on grid menu'); |
63 | | - const button = document.querySelector('div.mgp_playIcon'); |
| 94 | + const button = document.body.querySelector('div.mgp_playIcon'); |
64 | 95 | simulateClick(document, button); |
65 | 96 | setTimeout(_ => { |
66 | 97 | if (video.paused) { |
|
81 | 112 | `; |
82 | 113 | document.body.appendChild(style); |
83 | 114 |
|
84 | | - [...document.body.querySelectorAll('var.duration')].forEach(i => { |
85 | | - const duration = timeToSeconds(i.innerText); |
86 | | - const t = random(duration / 4, duration / 3); |
87 | | - const link = i.closest('a'); |
88 | | - if (link) { |
89 | | - link.href += `&t=${t}`; |
90 | | - } |
91 | | - |
92 | | - const div = i.closest('a').closest('div.phimage')?.parentNode; |
93 | | - if (duration < 20 * 60) { // TODO: check quality and non-free-premiumness |
94 | | - div?.classList.add('boringcontent'); |
95 | | - } |
96 | | - }); |
| 115 | + const similarVideos = [...document.body.querySelectorAll('var.duration')] |
| 116 | + .flatMap(i => { |
| 117 | + const duration = timeToSeconds(i.textContent); |
| 118 | + const t = random(duration / 4, duration / 3); |
| 119 | + const link = i.closest('a'); |
| 120 | + if (link) { |
| 121 | + link.href += `&t=${t}`; |
| 122 | + const div = link.closest('div.phimage')?.parentNode; // TODO: find previews from current playlist as well |
| 123 | + if (duration < 20 * 60) { // TODO: check quality, non-free-premiumness, my like or dislike; temporary (with exp backoff?) ban videos that fail to load? |
| 124 | + div?.classList.add('boringcontent'); |
| 125 | + } else { |
| 126 | + return [link.href]; |
| 127 | + } |
| 128 | + } |
| 129 | + return []; |
| 130 | + }); |
97 | 131 |
|
98 | 132 | if (p.startsWith('/embed/')) { |
99 | 133 | // this branch gets selected for both iframed and redirected embedded player |
100 | | - console.log('processing embed'); |
101 | | - processEmbedded(document); // document is a part of iframe here |
| 134 | + setTimeout(_ => { |
| 135 | + console.log('processing embedded'); |
| 136 | + processEmbedded(document, similarVideos); // document is a part of iframe here |
| 137 | + }, 500); |
102 | 138 | } else if (p === '/view_video.php') { |
103 | | - const durationFromNormalPlayer = timeToSeconds(document.body.querySelector('span.mgp_total')?.innerText); |
| 139 | + const durationFromNormalPlayer = timeToSeconds(document.body.querySelector('span.mgp_total')?.textContent); |
104 | 140 | if (durationFromNormalPlayer) { |
105 | 141 | if (!params.has('t') || Number(params.get('t')) >= durationFromNormalPlayer) { |
106 | 142 | window.stop(); |
|
113 | 149 | const container = document.body.querySelector('div.playerFlvContainer'); |
114 | 150 | if (container) { |
115 | 151 | const iframe = document.createElement('iframe'); |
116 | | - /*iframe.onload = _ => { |
117 | | - console.log('iframe onload'); |
118 | | - processEmbedded(iframe.contentWindow.document); |
119 | | - };*/ |
| 152 | + iframe.onload = _ => { |
| 153 | + console.log('processing embedded video from onload'); |
| 154 | + processEmbedded(iframe.contentWindow.document, similarVideos); |
| 155 | + }; |
120 | 156 | iframe.referrerpolicy = 'no-referrer'; |
121 | 157 | iframe.width = '100%'; |
122 | 158 | iframe.height = '100%'; |
|
126 | 162 | iframe.src = embedUrl; |
127 | 163 | container.appendChild(iframe); |
128 | 164 | } else { |
129 | | - console.log('redirecting to embedded player'); |
| 165 | + console.log('player not found, redirecting to embedded player'); |
130 | 166 | window.stop(); |
131 | 167 | window.location.href = embedUrl; |
132 | 168 | } |
|
0 commit comments