GBT HTML5 native player, full preload, download (GBTPP)

Replaces fluid player with browsers HTML5 native player, initialises native preload and proceeds full preload in background.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         GBT HTML5 native player, full preload, download (GBTPP)
// @version      4.8
// @namespace    _pc
// @description  Replaces fluid player with browsers HTML5 native player, initialises native preload and proceeds full preload in background.
// @author       verydelight
// @license      MIT
// @icon         https://www.gayporntube.com/favicon.ico
// @connect      gayporntube.com
// @compatible   Firefox Tampermonkey
// @grant        GM.xmlHttpRequest
// @grant        GM_download
// @grant        GM_xmlHttpRequest
// @grant        GM.download
// @match        *://*.gayporntube.com/video/*
// @webRequest   {"selector":"*fluidplayer*","action":"cancel"}
// ==/UserScript==
(async function() {
    const max_retries = 3;
    const timeOut = 2000;
    console.log("GBTPP: Script started.");

    const videoplayer = document.getElementById('play-video');
    if (!videoplayer) {
        console.error("GBTPP: No #play-video element found");
        return;
    }
    console.log("GBTPP: Found #play-video element.");

    const videoplayerSource = videoplayer.querySelector('source');
    if (!videoplayerSource) {
        console.error("GBTPP: No <source> inside #play-video");
        return;
    }
    console.log("GBTPP: Found video source element.");

    const pattern = /\/\?br=\d*$/;
    const src = videoplayerSource.src.replace(pattern, '');
    if (src !== videoplayerSource.src) {
        videoplayerSource.src = src;
        console.log("GBTPP: Cleaned video source URL.");
    }

    videoplayer.removeAttribute("height");
    videoplayer.removeAttribute("width");
    videoplayer.setAttribute("preload", "auto");
    videoplayer.focus();
    console.log("GBTPP: Configured native video player.");

    let retries = 0;
    await downloadVideo(videoplayerSource.src);

    async function downloadVideo(url) {
        try {
            // UI feedback area
            const statusBox = document.createElement("div");
            statusBox.classList.add("blue");
            statusBox.style.fontWeight = "bold";
            statusBox.textContent = "Starting preload…";
            videoplayer.parentNode.insertBefore(statusBox, videoplayer.nextSibling);
            console.log("GBTPP: UI status box created.");

            console.log("GBTPP: Initiating full preload.");
            const response = await new Promise((resolve, reject) => {
                GM.xmlHttpRequest({
                    method: 'GET',
                    responseType: 'blob',
                    url: url,
                    headers: {
                        "Content-Type": "video/mp4",
                        "Accept": "video/mp4"
                    },
                    onprogress: (event) => {
                        if (event.lengthComputable) {
                            const loadedMB = (event.loaded / 1048576).toFixed(2);
                            const totalMB = (event.total / 1048576).toFixed(2);
                            const percent = (event.loaded / event.total * 100).toFixed(1);
                            statusBox.textContent = `Preloaded ${loadedMB} / ${totalMB} MB (${percent}%)`;
                            console.log(`GBTPP: Download progress: ${loadedMB}/${totalMB} MB (${percent}%)`);
                        } else {
                            statusBox.textContent = `Preloaded ${(event.loaded / 1048576).toFixed(2)} MB…`;
                            console.log(`GBTPP: Download progress: ${(event.loaded / 1048576).toFixed(2)} MB loaded.`);
                        }
                    },
                    onload: resolve,
                    onerror: reject,
                    ontimeout: reject
                });
            });
            console.log("GBTPP: Full preload completed.");

            console.log("GBTPP: Creating blob from response.");
            const blob = new Blob([response.response], { type: 'video/mp4' });
            const objectUrl = URL.createObjectURL(blob);
            console.log("GBTPP: Blob created and Object URL obtained.");

            // keep playback position/state
            console.log("GBTPP: Updating video player source with new blob URL.");
            const { currentTime, paused, ended } = videoplayer;
            videoplayerSource.src = objectUrl;
            videoplayer.load();
            videoplayer.currentTime = currentTime;
            if (!paused && !ended && currentTime > 0) {
                videoplayer.play();
            }
            console.log("GBTPP: Video player source updated and playback state restored.");

            // notify user final
            statusBox.textContent = "Video fully preloaded (Click Download button to save video)";
            console.log("GBTPP: Final user notification displayed.");

            const container = document.querySelector("#tab_video_info");
            if (container) {
                const dlBttn = container.querySelector(".bttn");
                if (dlBttn) {
                    console.log("GBTPP: Updating Download button.");
                    try {
                        const href = dlBttn.getAttribute('href');
                        const urlObj = new URL(href, location.href);
                        const filename = urlObj.searchParams.get('download_filename') || "video.mp4";
                        dlBttn.href = objectUrl;
                        dlBttn.download = filename;
                        console.log(`GBTPP: Download button updated with filename: ${filename}`);
                    } catch (e) {
                        console.warn("GBTPP: Could not parse filename, but download button should still work.", e);
                    }
                }
            }
        } catch (err) {
            console.error("GBTPP: An error occurred during preload.", err);
            if (retries++ < max_retries) {
                console.warn(`GBTPP: Retry ${retries}/${max_retries} after error`, err);
                setTimeout(() => downloadVideo(url), timeOut);
            } else {
                console.error(`GBTPP: Failed after ${max_retries} retries. Giving up.`, err);
                alert("GBTPP: Video preload failed after multiple attempts.");
            }
        }
    }
})();