|
1 | 1 | // ==UserScript== |
2 | 2 | // @name Improve Adult Experience |
3 | | -// @description Skip intros, set best quality and duration filters by default, make unrelated video previews transparent |
4 | | -// @version 0.7 |
| 3 | +// @description Skip intros, set best quality and duration filters by default, make unwanted video previews transparent |
| 4 | +// @version 0.8 |
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/* |
|
18 | 18 | (_ => { |
19 | 19 | 'use strict'; |
20 | 20 |
|
21 | | - const MIN_DURATION_MIN = 20; |
| 21 | + // TODO: improve resistance to exceptions |
| 22 | + |
| 23 | + const MIN_DURATION_MINS = 20; |
22 | 24 | const MIN_VIDEO_HEIGHT = 1080; |
23 | 25 |
|
24 | 26 | if (performance.getEntriesByType('navigation')[0]?.responseStatus !== 200) return; |
|
37 | 39 |
|
38 | 40 | const simulateClick = (document, node) => { |
39 | 41 | console.log('simulateClick'); |
| 42 | + if (!node) return; |
40 | 43 | const rect = node.getBoundingClientRect(); |
41 | 44 | const clientX = rect.x + rect.width / 2; |
42 | 45 | const clientY = rect.y + rect.height / 2; |
|
52 | 55 | }; |
53 | 56 |
|
54 | 57 | const pornhub = _ => { |
55 | | - // TODO: never redirect, just update the URLs |
56 | | - // TODO: improve resistance to exceptions |
57 | | - |
58 | 58 | const UNWANTED = '__unwanted'; |
59 | 59 | const loadUnwanted = () => JSON.parse(localStorage.getItem(UNWANTED)) || {}; |
60 | 60 | const setUnwanted = (url, ttl) => { |
|
72 | 72 |
|
73 | 73 | const processEmbedded = (document, similarVideos) => { |
74 | 74 | const main = document.querySelector('div#main-container') || document.body; |
75 | | - const css = ` |
76 | | - div.mgp_topBar { display: none !important; } |
77 | | - div.mgp_thumbnailsGrid { display: none !important; } |
78 | | - img.mgp_pornhub { display: none !important; } |
79 | | - `; |
80 | | - const styleApplied = !![...main.querySelectorAll('style')].find(i => i.innerHTML === css); |
81 | | - if (styleApplied) { |
82 | | - console.log('embedded video is already initialized'); |
83 | | - return; |
| 75 | + |
| 76 | + try { |
| 77 | + const css = ` |
| 78 | + div.mgp_topBar { display: none !important; } |
| 79 | + div.mgp_thumbnailsGrid { display: none !important; } |
| 80 | + img.mgp_pornhub { display: none !important; } |
| 81 | + `; |
| 82 | + const styleApplied = !![...main.querySelectorAll('style')].find(i => i.innerHTML === css); |
| 83 | + if (styleApplied) { |
| 84 | + console.log('embedded video is already initialized'); |
| 85 | + return; |
| 86 | + } |
| 87 | + console.log('applying style'); |
| 88 | + const style = document.createElement('style'); |
| 89 | + style.innerHTML = css; |
| 90 | + main.appendChild(style); |
| 91 | + } catch (e) { |
| 92 | + console.error(e); |
84 | 93 | } |
85 | | - console.log('applying style'); |
86 | | - const style = document.createElement('style'); |
87 | | - style.innerHTML = css; |
88 | | - main.appendChild(style); |
89 | 94 |
|
90 | | - const requiresRefresh = main.querySelector('div.mgp_errorIcon') && main.querySelector('p')?.textContent.includes('Please refresh the page'); |
91 | | - if (requiresRefresh) { |
92 | | - console.log('refreshing after error'); |
93 | | - window.location.href = window.location.toString(); |
| 95 | + try { |
| 96 | + const requiresRefresh = main.querySelector('div.mgp_errorIcon') && main.querySelector('p')?.textContent.includes('Please refresh the page'); |
| 97 | + if (requiresRefresh) { |
| 98 | + console.log('refreshing after error'); |
| 99 | + window.location.href = window.location.toString(); |
| 100 | + } |
| 101 | + } catch (e) { |
| 102 | + console.error(e); |
94 | 103 | } |
95 | 104 |
|
96 | 105 | const video = main.querySelector('video'); |
97 | | - if (!video) { |
98 | | - console.log('embedding this video is probably not allowed'); |
99 | | - window.stop(); |
100 | | - |
101 | | - if (!isUnwanted(url)) { |
102 | | - console.log('making single refresh attempt'); |
103 | | - setUnwanted(url, currentTime() + 5 * 60); |
104 | | - window.location = url.toString(); |
105 | | - return; |
106 | | - } |
| 106 | + try { |
| 107 | + if (!video) { |
| 108 | + console.log('embedding this video is probably not allowed'); |
| 109 | + window.stop(); |
107 | 110 |
|
108 | | - if (similarVideos.length > 0) { |
109 | | - console.log('redirecting to random non-unwanted similar video'); |
110 | | - const newSimilarVideos = similarVideos.filter(i => !watchedVideos.has(i)); |
111 | | - window.location.href = newSimilarVideos.length > 0 ? pickRandom(newSimilarVideos) : pickRandom(similarVideos); |
112 | | - } else { |
113 | | - console.log('giving up'); |
| 111 | + if (!isUnwanted(url)) { |
| 112 | + console.log('making single refresh attempt'); |
| 113 | + setUnwanted(url, currentTime() + 60 * 60); |
| 114 | + window.location = url.toString(); |
| 115 | + return; |
| 116 | + } |
| 117 | + |
| 118 | + if (similarVideos.length > 0) { |
| 119 | + console.log('redirecting to a random non-unwanted similar video'); |
| 120 | + const newSimilarVideos = similarVideos.filter(i => !watchedVideos.has(i)); |
| 121 | + window.location.href = newSimilarVideos.length > 0 ? pickRandom(newSimilarVideos) : pickRandom(similarVideos); |
| 122 | + } else { |
| 123 | + console.log('giving up'); |
| 124 | + } |
| 125 | + return; |
114 | 126 | } |
115 | | - return; |
| 127 | + } catch (e) { |
| 128 | + console.error(e); |
116 | 129 | } |
117 | 130 |
|
118 | 131 | video.addEventListener('loadstart', _ => simulateClick(document, main.querySelector('div.mgp_playIcon'))); |
|
139 | 152 | video.load(); |
140 | 153 | }; |
141 | 154 |
|
142 | | - const processPreview = i => { |
143 | | - const link = i.closest('a'); |
144 | | - if (link) { |
145 | | - const duration = timeToSeconds(i.textContent); |
146 | | - const t = random(duration / 4, duration / 3); |
| 155 | + const premiumRedirect = node => node.href.startsWith('javascript:'); |
| 156 | + |
| 157 | + const processPreview = node => { |
| 158 | + try { |
| 159 | + const link = node.closest('a'); |
| 160 | + if (!link) return; |
147 | 161 |
|
148 | | - const premiumRedirect = !link.href.startsWith('https://'); |
149 | | - if (!premiumRedirect) { |
| 162 | + const duration = timeToSeconds(node.textContent); |
| 163 | + const premium = premiumRedirect(link); |
| 164 | + if (!premium) { |
| 165 | + const t = random(duration / 4, duration / 3); |
150 | 166 | link.href += `&t=${t}`; |
151 | 167 | } |
152 | 168 |
|
153 | | - const node = link.closest('div.phimage')?.parentNode || link.closest('li'); |
154 | | - if (premiumRedirect || duration < MIN_DURATION_MIN * 60 || isUnwanted(new URL(link.href))) { |
155 | | - node?.classList.add(UNWANTED); |
| 169 | + const container = link.closest('div.phimage')?.parentNode || link.closest('li'); |
| 170 | + if (premium || duration < MIN_DURATION_MINS * 60 || isUnwanted(new URL(link.href))) { |
| 171 | + container?.classList.add(UNWANTED); |
156 | 172 | } else { |
157 | 173 | if (link.querySelector('div.watchedVideoText')) { |
158 | 174 | watchedVideos.add(link.href); |
159 | 175 | } |
160 | 176 | return link.href; |
161 | 177 | } |
| 178 | + } catch (e) { |
| 179 | + console.log(e); |
162 | 180 | } |
163 | 181 | }; |
164 | 182 |
|
|
176 | 194 | const main = document.querySelector('div#main-container') || document.body; |
177 | 195 | subscribeOnChanges(main, processPlaylistItem); |
178 | 196 |
|
179 | | - const style = document.createElement('style'); |
180 | | - style.innerHTML = ` |
181 | | - div.${UNWANTED}, li.${UNWANTED} { opacity: 10%; } |
182 | | - div.${UNWANTED}:hover, li.${UNWANTED}:hover { opacity: 40%; } |
183 | | - `; |
184 | | - main.appendChild(style); |
| 197 | + try { |
| 198 | + const style = document.createElement('style'); |
| 199 | + style.innerHTML = ` |
| 200 | + div.${UNWANTED}, li.${UNWANTED} { opacity: 10%; } |
| 201 | + div.${UNWANTED}:hover, li.${UNWANTED}:hover { opacity: 40%; } |
| 202 | + `; |
| 203 | + main.appendChild(style); |
| 204 | + } catch (e) { |
| 205 | + console.error(e); |
| 206 | + } |
| 207 | + |
| 208 | + const filterParams = Object.entries({ |
| 209 | + 'min_duration': MIN_DURATION_MINS, |
| 210 | + 'hd': 1, |
| 211 | + 'o': 'tr', |
| 212 | + 't': 'm', |
| 213 | + }); |
| 214 | + |
| 215 | + const processLink = node => { |
| 216 | + if (node.nodeType !== 1) return; |
| 217 | + if (node.tagName === 'A') { |
| 218 | + try { |
| 219 | + if (premiumRedirect(node)) return; |
| 220 | + const url = new URL(node.href.startsWith('https:') ? node.href : `${window.location.origin}${node.href}`); |
| 221 | + const params = url.searchParams; |
| 222 | + const p = url.pathname; |
| 223 | + if (p === '/video' || p === '/video/search' || p.startsWith('/categories/')) { |
| 224 | + filterParams.forEach(([key, value]) => params.set(key, value)); |
| 225 | + node.href = url.toString(); |
| 226 | + } |
| 227 | + } catch (e) { |
| 228 | + console.error(node.href, e); |
| 229 | + } |
| 230 | + return; |
| 231 | + } |
| 232 | + node.childNodes.forEach(processLink); |
| 233 | + }; |
| 234 | + |
| 235 | + subscribeOnChanges(main, processLink); |
| 236 | + |
| 237 | + // TODO |
| 238 | + /*const searchForm = main.querySelector('form#search_form') || main.querySelector('form'); |
| 239 | + if (searchForm) { |
| 240 | + filterParams.forEach(([key, value]) => { |
| 241 | + const input = document.createElement('input'); |
| 242 | + input.type = 'hidden'; |
| 243 | + input.name = key; |
| 244 | + input.value = value; |
| 245 | + searchForm.appendChild(input); |
| 246 | + }); |
| 247 | + }*/ |
185 | 248 |
|
186 | 249 | const similarVideos = [...main.querySelectorAll('var.duration')] |
187 | 250 | .map(i => processPreview(i)) |
|
231 | 294 | window.location.href = embedUrl; |
232 | 295 | } |
233 | 296 | } |
234 | | - } else if (params.get('hd') !== '1' && !params.has('min_duration') && (p.startsWith('/categories/') || p === '/video' || p === '/video/search')) { |
235 | | - params.set('min_duration', MIN_DURATION_MIN); |
236 | | - params.set('hd', 1); |
237 | | - newUrl = url.toString(); |
238 | 297 | } |
239 | 298 | }; |
240 | 299 |
|
|
243 | 302 |
|
244 | 303 | if (p === '/' && params.has('k') && !params.has('quality')) { |
245 | 304 | params.set('sort', 'rating'); |
246 | | - params.set('durf', `${MIN_DURATION_MIN}min_more`); |
| 305 | + params.set('durf', `${MIN_DURATION_MINS}min_more`); |
247 | 306 | params.set('quality', `${MIN_VIDEO_HEIGHT}P`); |
248 | 307 | newUrl = url.toString(); |
249 | 308 | } else if (p.startsWith('/c/') && !p.includes(`q:${MIN_VIDEO_HEIGHT}P`)) { |
250 | 309 | const ps = p.split('/'); |
251 | 310 | if (ps.length >= 3) { |
252 | | - url.pathname = `${ps[1]}/s:rating/d:${MIN_DURATION_MIN}min_more/q:${MIN_VIDEO_HEIGHT}P/${ps[2]}`; |
| 311 | + url.pathname = `${ps[1]}/s:rating/d:${MIN_DURATION_MINS}min_more/q:${MIN_VIDEO_HEIGHT}P/${ps[2]}`; |
253 | 312 | newUrl = url.toString(); |
254 | 313 | } |
255 | 314 | } |
|
263 | 322 | url.pathname = '/trending_videos/' |
264 | 323 | } |
265 | 324 | params.set('q', 'fhd'); |
266 | | - params.set('d', MIN_DURATION_MIN); |
| 325 | + params.set('d', MIN_DURATION_MINS); |
267 | 326 | newUrl = url.toString(); |
268 | 327 | } |
269 | 328 | }; |
|
274 | 333 | [...document.body.querySelectorAll('a')] |
275 | 334 | .filter(i => !!['categories', 'channels', 'models', 'top-rated'].find(page => expectedPage(page, i.href))) |
276 | 335 | .forEach(i => { |
277 | | - const url = new URL(i.href); |
278 | | - const ps = url.pathname.split('/').filter(i => i.length > 0); |
279 | | - for (const i of ['hd', 'top-rated', 'thirty-all-min']) { |
280 | | - if (!ps.includes(i)) { |
281 | | - ps.push(i); |
| 336 | + try { |
| 337 | + const url = new URL(i.href); |
| 338 | + const ps = url.pathname.split('/').filter(i => i.length > 0); |
| 339 | + for (const i of ['hd', 'top-rated', 'thirty-all-min']) { |
| 340 | + if (!ps.includes(i)) { |
| 341 | + ps.push(i); |
| 342 | + } |
282 | 343 | } |
| 344 | + ps.push(''); |
| 345 | + ps.unshift(''); |
| 346 | + url.pathname = ps.join('/'); |
| 347 | + i.href = url.toString(); |
| 348 | + } catch (e) { |
| 349 | + console.error(i.href, e); |
283 | 350 | } |
284 | | - ps.push(''); |
285 | | - ps.unshift(''); |
286 | | - url.pathname = ps.join('/'); |
287 | | - i.href = url.toString(); |
288 | 351 | }); |
289 | 352 | }; |
290 | 353 |
|
|
0 commit comments