2chScripts / Random screenshot button

// ==UserScript==
// @name         Random screenshot button
// @namespace    https//openuserjs.org/users/2chScripts
// @version      0.2
// @description  Add "Random" button to site prnt.sc
// @author       anonymous
// @include      https://prnt.sc/
// @grant        none
// @copyright 2019, 2chScripts (https://openuserjs.org/users/2chScripts)
// @license MIT
// ==/UserScript==

(function() {
    let lastPage = 0;
    let randButton;
    let linkInput;
    let imagesWrapper;
    let prevButton;
    let nextButton;
    let perPage = 6;
    const initial = `
    <style>
            .controls-wrapper {
                margin-top: 20px;
            }
            button {
               margin: .2rem;
               padding: .2rem .5rem;
            }
            .link_row, .nav_row {
                display: flex;
                flex-direction: row;
                justify-content: center;
            }
            .image-item {
                cursor: pointer;
                background-color: #aeaeae;
                margin: 6px;
            }
            .image {
                width: 310px;
                height: 250px;
                background-size: cover;
                background-position: center;
                background-repeat: no-repeat;
            }
            .main-wrapper {
                display: flex;
                flex-wrap: wrap;
                justify-content: center;
            }
        </style>
        <div class="controls-wrapper">
            <div class="link_row"><input placeholder="Link" name="link"/><button id="random">get latest image's link</button></div>
            <div class="nav_row"><button id="prev">prev</button><button id="next">next</button></div>
        </div>
        <div id="images-wrapper" class="main-wrapper">
        </div>
    `

    const getImageLinkByNum = num => {

        return fetch(numToLink(num))
            .then(res => res.text())
            .then(body => {
                return body.match(/meta property="og:image" content="(.*?)"/)[1]
            })
            .catch(err => {console.log(err); return "404"})
    }

    const generateImages = (range) => {
        Promise.all(range.map(num => getImageLinkByNum(num)))
            .then(links => {
                let code = links.map(link => (
                    `
                       <div class="image-item">
                          <a href="${link}">
                            <div class="image" style="background-image:url(${link});"></div>
                          </a>
                       </div>
                    `
                ))
                imagesWrapper.innerHTML = code.join('')
            })
    }

    const parseJson = response => response.json();
    const getLastLink = () => {
        const image = base64ToFile("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=", "image.jpg", "image/jpeg");
        let data = new FormData();
        data.append("image", image, "image.jpg");
        fetch("/upload.php", {method: "POST", body: data})
           .then(parseJson)
           .then(res => {
                lastPage = linkToNum(res.data)
                linkInput.value = res.data
            })
    }

    const getPrevImages = () => {
        let range = [];
        for (let i=lastPage; i > lastPage-perPage;i--) {
            range.push(i)
        }
        lastPage -= perPage;
        generateImages(range);
    }

    const getNextImages = () => {
        let range = [];
        for (let i=lastPage; i < lastPage+perPage; i++) {
            range.push(i);
        }
        lastPage +=perPage;
        generateImages(range);
    }

    function base64ToFile(base64Data, tempfilename, contentType) {
        contentType = contentType || '';
        let sliceSize = 1024;
        let byteCharacters = atob(base64Data);
        let bytesLength = byteCharacters.length;
        let slicesCount = Math.ceil(bytesLength / sliceSize);
        let byteArrays = new Array(slicesCount);

        for (let sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
            let begin = sliceIndex * sliceSize;
            let end = Math.min(begin + sliceSize, bytesLength);

            let bytes = new Array(end - begin);
            for (let offset = begin, i = 0 ; offset < end; ++i, ++offset) {
                bytes[i] = byteCharacters[offset].charCodeAt(0);
            }
            byteArrays[sliceIndex] = new Uint8Array(bytes);
        }
        let file = new File(byteArrays, tempfilename, { type: contentType });
        return file;
    }

    const numToLink = num => {
        return `https://prnt.sc/${num.toString(36)}`
    }

    const linkToNum = link => {
        if (/https?:\/\/(prntscr.com|prnt.sc)\/([0-9a-z]+)/.test(link)) {
            link = link.match(/http?:\/\/(prntscr.com|prnt.sc)\/([0-9a-z]+)/)[2]
        }
        return parseInt(link, 36)
    }

    const init = () => {
        let place = document.getElementsByClassName("image-constrain")[0];
        if (!place) {
            place = document.getElementsByClassName("page-constrain")[1];
        }
        place.innerHTML = initial;
        randButton = document.getElementById("random");
        linkInput = document.querySelector("input[name=link]");
        imagesWrapper = document.getElementById("images-wrapper");
        prevButton = document.getElementById("prev");
        nextButton = document.getElementById("next");

        prevButton.onclick = getPrevImages;
        randButton.onclick = getLastLink;
        nextButton.onclick = getNextImages;
    }
    window.onload = init;
})();