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)
}
})()