NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name PornHub PornStar/Models Videos Link Grabber // @description This adds an "Get all video links" button on pornstar/model pages (in the tab -> videos) which opens an popup and show all video links from this pornstar/model as list // @version 0.0.2 // @license MIT // @author SuperPanda // @match https://pornhub.com/pornstar/* // @match https://*.pornhub.com/pornstar/* // @match https://pornhub.com/pornstar/*/videos // @match https://*.pornhub.com/pornstar/*/videos // @match https://pornhub.com/model/*/videos // @match https://*.pornhub.com/model/*/videos // @match https://pornhub.com/model/* // @match https://*.pornhub.com/model/* // @match https://pornhubpremium.com/pornstar/*/videos // @match https://*.pornhubpremium.com/pornstar/*/videos // @match https://pornhubpremium.com/model/*/videos // @match https://*.pornhubpremium.com/model/*/videos // @updateURL https://openuserjs.org/meta/SuperPanda/PornHub_PornStarModels_Videos_Link_Grabber.meta.js // @downloadURL https://openuserjs.org/install/SuperPanda/PornHub_PornStarModels_Videos_Link_Grabber.user.js // @copyright 2020, SuperPanda (https://openuserjs.org/users/SuperPanda) // ==/UserScript== (function () { 'use strict' addcss(`.loader-links { position: fixed; top: 40vh; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .loader-links-wrapper { align-items: center; position: fixed; background-color: rgba(0,0,0,0.8); display: flex; height: 100%; width: 100%; justify-content: center; margin: 0; z-index: 500; overflow: hidden; } .loader-links { width: 60px; } .loader-links-wheel { animation: spin 1s infinite linear; border: 2px solid rgba(30, 30, 30, 0.5); border-left: 4px solid #fff; border-radius: 50%; height: 50px; margin-bottom: 10px; width: 50px; } .loader-links-text { color: #fff; font-family: arial, sans-serif; } .loader-links-text:after { content: 'Loading'; animation: load 2s linear infinite; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } @keyframes load { 0% { content: 'Loading'; } 33% { content: 'Loading.'; } 67% { content: 'Loading..'; } 100% { content: 'Loading...'; } }`) var activeLog = false var linkList = [] var currentUrl = window.location.href if (document.querySelector('.sectionTitle .spriteProfileIcons') !== null){ var btnContainer = document.querySelector('.sectionTitle .spriteProfileIcons') } else { var btnContainer = document.querySelector('.section_header .spriteProfileIcons .mediumPlayAllBtn') } var linkGrabberBtn = document.createElement('a') linkGrabberBtn.text = 'Get all video links' linkGrabberBtn.onclick = startGettingAllTheLinks linkGrabberBtn.classList.add('greyButton') linkGrabberBtn.classList.add('float-right') //btnContainer.appendChild(linkGrabberBtn) btnContainer.insertBefore(linkGrabberBtn, btnContainer.childNodes[0]) function validURL(str) { var pattern = new RegExp('^(https?:\\/\\/)?'+ // protocol '((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|'+ // domain name '((\\d{1,3}\\.){3}\\d{1,3}))'+ // OR ip (v4) address '(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*'+ // port and path '(\\?[;&a-z\\d%_.~+=-]*)?'+ // query string '(\\#[-a-z\\d_]*)?$','i'); // fragment locator return !!pattern.test(str); } function startGettingAllTheLinks () { Promise.resolve(ShowLoader()) // FIXME This doesn't work for some reason .then(getLinks) .then(() => { if (activeLog == true) { console.log('found ' + linkList.length + ' links') } for (var i = 0; i < linkList.length; i++) { if (activeLog == true) { console.log(linkList[i].href) } } }) .then(showLinks) } const wait = ms => new Promise((resolve) => setTimeout(resolve, ms)) const getLinks = async function (index = 1) { let url = currentUrl + '?page=' + index let responseData try { responseData = await makeRequest('GET', url, index) } catch (error) { if (activeLog == true) { console.log(error) } } if (responseData) { if (responseData.status && responseData.status >= 200 && responseData.status < 300) { extractLinks(responseData.response) if (activeLog == true) { console.log('parsed page ' + index) } await getLinks(index + 1) } else { switch (responseData.status) { case 404: if (activeLog == true) { console.log('404 for page ' + index + '. Looks like ' + (index - 1) + ' is the last page.') } break case 429: if (activeLog == true) { console.log('Too many requests. I\'ll wait a bit and try again') } await wait(1000) await getLinks(index) break default: console.error('Augh, there was an error!', responseData.status, responseData.statusText, index) break } } } else { if (activeLog == true) { console.log('now this is unexpected ...') } } } function extractLinks (response) { var links = response.querySelectorAll('div.sectionWrapper ul.videos li .linkVideoThumb') for (var i = 0; i < links.length; i++) { linkList.push(links[i]) } } function makeRequest (method, url, pageIndex) { if (activeLog == true) { console.log('new Request ' + method + ' ' + url) } return new Promise(function (resolve, reject) { var xhr = new XMLHttpRequest() xhr.open(method, url) xhr.responseType = 'document' xhr.onload = function () { resolve({ response: xhr.response, status: this.status, statusText: xhr.statusText, pageIndex: pageIndex }) } xhr.onerror = function () { reject(new Error('the request ' + method + ' ' + url + ' failed')) } xhr.send() }) } function ShowLoader () { var loader_wrapper = document.createElement('div') loader_wrapper.className = 'loader-links-wrapper' loader_wrapper.id = 'createLinksLoader' var loader = document.createElement('div') var loader_wheel = document.createElement('div') var loader_text = document.createElement('div') loader.className = 'loader-links' loader_wheel.className = 'loader-links-wheel' loader_text.className = 'loader-links-text' loader_wrapper.appendChild(loader) loader.appendChild(loader_wheel) loader.appendChild(loader_text) var addLoader = document.querySelector('.wrapper') addLoader.insertBefore(loader_wrapper, addLoader.childNodes[0]) } function RemoveLoader () { var loader = document.getElementById('createLinksLoader') if (loader) { loader.style.transition = '.5s'; loader.style.opacity = '0'; loader.style.visibility = 'hidden'; } } function addcss (css) { var head = document.getElementsByTagName('head')[0] var s = document.createElement('style') s.setAttribute('type', 'text/css') if (s.styleSheet) { // IE s.styleSheet.cssText = css } else { // the world s.appendChild(document.createTextNode(css)) } head.appendChild(s) } function showLinks () { var outerModalDiv = document.createElement('div') var innerModalDiv = document.createElement('div') outerModalDiv.id = 'pornstarVidsLinkContainingModalPanel' outerModalDiv.style.display = 'block' outerModalDiv.style.position = 'fixed' outerModalDiv.style.zIndex = '100' outerModalDiv.style.paddingTop = '100px' outerModalDiv.style.left = '0' outerModalDiv.style.top = '0' outerModalDiv.style.width = '100%' outerModalDiv.style.height = '100%' outerModalDiv.style.overflow = 'auto' outerModalDiv.style.backgroundColor = 'rgb(0,0,0)' outerModalDiv.style.backgroundColor = 'rgb(0,0,0,0.4)' var closeButtonContainer = document.createElement('div') closeButtonContainer.className = 'userButtons' var closeButton = CreateButton('X', null, RemoveOuterModalPanel) closeButton.style.cssFloat = 'right' closeButtonContainer.appendChild(closeButton) innerModalDiv.appendChild(closeButtonContainer) innerModalDiv.style.backgroundColor = '#1b1b1b' innerModalDiv.style.margin = 'auto' innerModalDiv.style.padding = '20px' innerModalDiv.style.border = '1px solid #888' innerModalDiv.style.width = '50%' innerModalDiv.style.color = '#ababab' innerModalDiv.style.textAlign = 'center' var founded = document.createElement('p') founded.innerHTML = 'I have found '+ linkList.length + ' video links.' innerModalDiv.appendChild(founded) var linkListDiv linkListDiv = document.createElement('textarea') linkListDiv.readOnly = true; linkListDiv.style.width = '600px' linkListDiv.style.height = '300px' for (var i = 0; i < linkList.length; i++) { if (validURL(linkList[i].href)) { var span = document.createElement('p') span.innerHTML = linkList[i].href + ' ' linkListDiv.innerHTML += linkList[i].href + ' '; } } RemoveLoader() innerModalDiv.appendChild(linkListDiv) outerModalDiv.appendChild(innerModalDiv) document.body.appendChild(outerModalDiv) } function CreateButton (text, id, onClickEvent) { var innerbutton = document.createElement('button') innerbutton.innerText = text innerbutton.className = 'buttonBase' innerbutton.style.backgroundColor = '#f90' innerbutton.style.color = '#000' innerbutton.style.fontWeight = '700' innerbutton.display = 'inline-block' var button = document.createElement('div') if (id) button.id = id button.style.padding = '5px 10px' button.style.lineHeight = '1.2em' button.style.borderRadius = '4px' button.onclick = onClickEvent button.appendChild(innerbutton) return button } function RemoveOuterModalPanel () { var toRemove = document.getElementById('pornstarVidsLinkContainingModalPanel') toRemove.parentNode.removeChild(toRemove) } })()