pornhub.com channel videos link grabber

This adds a button to pornhub channel pages to get links to all videos

// ==UserScript==
// @name pornhub.com channel videos link grabber
// @description This adds a button to pornhub channel pages to get links to all videos
// @version 1.0.1
// @license MIT
// @match https://*.pornhub.com/channels/*
// @match https://*.pornhubpremium.com/channels/*
// @namespace https://sleazyfork.org/users/179893
// @grant GM.xmlHttpRequest
// ==/UserScript==
(function () {
  'use strict'

  addcss(`.loader {
        position: absolute;
        left: 50%;
        top: 50%;
        z-index: 200;
        border: 16px solid #f3f3f3; /* Light grey */
        border-top: 16px solid #3498db; /* Blue */
        border-radius: 50%;
        width: 120px;
        height: 120px;
        margin: -60px 0 0 -60px;
        animation: spin 2s linear infinite;
    }
    
    @keyframes spin {
        0% { transform: rotate(0deg); }
        100% { transform: rotate(360deg); }
    }`)

  var linkList = []
  var currentUrl = window.location.href
  var paginationBaseUrl = currentUrl
  var myRegexp = /^(https:\/\/.*.pornhub.*.com\/channels\/)([^\/]*)(\/.*)?$/g
  var match = myRegexp.exec(currentUrl)
  if (match) {
    if (currentUrl.indexOf('/videos') === -1) {
      paginationBaseUrl += '/videos'
    }

    // paginationBaseUrl = match[1] + match[2] + '/videos'
    console.log('matched: ' + paginationBaseUrl)
  }

  var btnContainer = document.querySelector('.rightSide .sectionChannelsWrapper div.title')

  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)

  function startGettingAllTheLinks () {
    Promise.resolve(ShowLoader()) // FIXME This doesn't work for some reason
      .then(getLinks)
      .then(() => {
        console.log('found ' + linkList.length + ' links')
        for (var i = 0; i < linkList.length; i++) {
          console.log(linkList[i].href)
        }
      })
      .then(RemoveLoader())
      .then(showLinks)
  }

  const wait = ms => new Promise((resolve) => setTimeout(resolve, ms))

  const addQueryParam = function (url, paramName, paramValue) {
    if (url.indexOf('?') !== -1) {
      let newUrl = new URL(url)
      if (newUrl.searchParams.has(paramName)) {
        newUrl.searchParams.delete(paramName)
      }
      newUrl.searchParams.append(paramName, paramValue)
      return newUrl.toString()
    } else {
      return url + '?' + paramName + '=' + paramValue
    }
  }

  const getLinks = async function (index = 1) {
    let url = addQueryParam(paginationBaseUrl, 'page', index)
    let responseData
    try {
      responseData = await makeRequest('GET', url)
    } catch (error) {
      console.log(error)
    }
    if (responseData) {
      if (responseData.status && responseData.status >= 200 && responseData.status < 300) {
        extractLinks(responseData.response)
        console.log('parsed page ' + index)
        await getLinks(index + 1)
      } else {
        switch (responseData.status) {
          case 404:
            console.log('404 for page ' + index + '. Looks like ' + (index - 1) + ' is the last page.')
            break
          case 429:
            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 {
      console.log('now this is unexpected ...')
    }
  }

  function extractLinks (response) {
    var links = response.querySelectorAll('div.sectionChannelsWrapper ul.videos li .title a')
    for (var i = 0; i < links.length; i++) {
      linkList.push(links[i])
    }
  }

  function makeRequest (method, url) {
    console.log('new Request ' + method + ' ' + url)
    return new Promise(function (resolve, reject) {
      GM.xmlHttpRequest({
        method: method,
        url: url,
        onload: function (response) {
          var responseXML = null
          responseXML = new DOMParser()
            .parseFromString(response.responseText, 'text/html')

          resolve({
            response: responseXML,
            status: response.status,
            statusText: response.statusText
          })
        },
        onerror: function (response) {
          reject(new Error('the request ' + method + ' ' + url + ' failed'))
        }
      })

      // 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 = document.createElement('div')
    loader.id = 'myVeryOwnCustomLoaderUsingAnUniqueId'
    loader.className = 'loader'
    document.body.appendChild(loader)
  }

  function RemoveLoader () {
    var loader = document.getElementById('myVeryOwnCustomLoaderUsingAnUniqueId')
    if (loader) {
      loader.parentNode.removeChild(loader)
    }
  }

  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' // use a long id to avoid name conflicts
    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)'

    // add close btn
    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 = '80%'
    innerModalDiv.style.color = '#ababab'

    var instructions1 = document.createElement('p')
    var instructions2 = document.createElement('p')
    var instructions3 = document.createElement('p')

    instructions1.innerHTML = 'Save the links to a local textfile (e.g. &quotC:\\Temp\\dl\\linklist.txt)&quot and run youtube-dl whith the -a argument and the path to the linklist.'
    instructions2.innerHTML = 'youtube-dl -a &quotC:\\Temp\\dl\\linklist.txt&quot'
    instructions3.innerHTML = 'Or just use jDownloader with the linklist'

    innerModalDiv.appendChild(instructions1)
    innerModalDiv.appendChild(instructions2)
    innerModalDiv.appendChild(instructions3)

    var linkListDiv

    linkListDiv = document.createElement('div')

    for (var i = 0; i < linkList.length; i++) {
      var a = document.createElement('a')
      var p = document.createElement('p')
      p.innerHTML = linkList[i].href
      a.href = linkList[i].href
      a.download = linkList[i].title
      a.appendChild(p)
      linkListDiv.appendChild(a)
    }
    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)
  }
})()