omoggle live psl + video loop + drag

real-time psl slider, video cam loop, draggable menu, api hook

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

You will need to install an extension such as Tampermonkey to install this script.

Tendrás que 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.

Tendrás que instalar una extensión como Tampermonkey antes de poder 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)

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Tendrás que instalar una extensión como Stylus antes de poder instalar este script.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

Para poder instalar esto tendrás que instalar primero una extensión de estilos de usuario.

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

// ==UserScript==
// @name         omoggle live psl + video loop + drag
// @namespace    lol
// @version      9.0
// @description  real-time psl slider, video cam loop, draggable menu, api hook
// @match        https://omoggle.com/*
// @match        https://www.omoggle.com/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
    'use strict';

    let current_psl = 9.9;
    let videoStream = null;

    // -------- API INTERCEPTORS (fetch + xhr) ----------
    const oldFetch = window.fetch;
    window.fetch = function(...args) {
        let url = args[0];
        let opts = args[1] || {};
        if (typeof url === 'string' && (url.includes('/api/match/finalize') || url.includes('/api/ranked/finalize'))) {
            if (opts.body) {
                try {
                    let body = JSON.parse(opts.body);
                    if (body.psl !== undefined) body.psl = current_psl;
                    if (body.score !== undefined) body.score = current_psl;
                    if (body.rating !== undefined) body.rating = current_psl;
                    if (body.yourScore !== undefined) body.yourScore = current_psl;
                    opts.body = JSON.stringify(body);
                } catch(e) {}
            }
        }
        return oldFetch.apply(this, [url, opts]);
    };

    const XHR = XMLHttpRequest.prototype;
    const oldOpen = XHR.open;
    const oldSend = XHR.send;
    XHR.open = function(method, url, ...rest) {
        this._mog_url = url;
        return oldOpen.apply(this, [method, url, ...rest]);
    };
    XHR.send = function(body) {
        if (this._mog_url && (this._mog_url.includes('/api/match/finalize') || this._mog_url.includes('/api/ranked/finalize'))) {
            if (body && typeof body === 'string') {
                try {
                    let parsed = JSON.parse(body);
                    if (parsed.psl !== undefined) parsed.psl = current_psl;
                    if (parsed.score !== undefined) parsed.score = current_psl;
                    if (parsed.rating !== undefined) parsed.rating = current_psl;
                    body = JSON.stringify(parsed);
                } catch(e) {}
            }
        }
        return oldSend.call(this, body);
    };

    // -------- WAIT FOR PAGE THEN ADD MENU ----------
    window.addEventListener('DOMContentLoaded', () => {
        // create menu div
        let menu = document.createElement('div');
        menu.id = 'mogmenu';
        menu.style.cssText = 'position:fixed; bottom:20px; right:20px; background:#111; border:1px solid #f0f; color:#eee; font-family:monospace; font-size:13px; padding:10px; z-index:99999; width:240px; cursor:default;';
        menu.innerHTML = `
            <div id="mogHeader" style="font-weight:bold; margin-bottom:10px; text-align:center; cursor:move;">OMOGGLE TOOL (drag me)</div>
            <div>PSL: <span id="pslValue">9.9</span></div>
            <input type="range" id="pslSlider" min="0.1" max="9.9" step="0.01" value="9.9" style="width:100%; margin:5px 0;">
            <div style="margin-top:10px;">📹 fake cam (video loop)</div>
            <input type="file" id="camFile" accept="video/*" style="width:100%; margin:5px 0;">
            <div id="camStatus" style="color:#aaa; font-size:11px;">no video</div>
            <div id="apiLog" style="border-top:1px solid #333; margin-top:8px; padding-top:5px; font-size:10px;">api: idle</div>
        `;
        document.body.appendChild(menu);

        // draggable functionality
        let header = document.getElementById('mogHeader');
        let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
        header.onmousedown = dragMouseDown;
        function dragMouseDown(e) {
            e = e || window.event;
            e.preventDefault();
            pos3 = e.clientX;
            pos4 = e.clientY;
            document.onmouseup = closeDrag;
            document.onmousemove = elementDrag;
        }
        function elementDrag(e) {
            e = e || window.event;
            e.preventDefault();
            pos1 = pos3 - e.clientX;
            pos2 = pos4 - e.clientY;
            pos3 = e.clientX;
            pos4 = e.clientY;
            let top = menu.offsetTop - pos2;
            let left = menu.offsetLeft - pos1;
            if (top > 0) menu.style.top = top + 'px';
            if (left > 0) menu.style.left = left + 'px';
            menu.style.bottom = 'auto';
            menu.style.right = 'auto';
        }
        function closeDrag() {
            document.onmouseup = null;
            document.onmousemove = null;
        }

        // psl slider -> update display and global value
        let slider = document.getElementById('pslSlider');
        let pslSpan = document.getElementById('pslValue');
        slider.addEventListener('input', (e) => {
            let val = parseFloat(e.target.value).toFixed(2);
            pslSpan.innerText = val;
            current_psl = parseFloat(val);
            // instantly spoof any visible score on page
            spoofAllScores(current_psl);
            document.getElementById('apiLog').innerHTML = `api: set to ${current_psl}`;
        });

        // function to find all score elements and change them live
        function spoofAllScores(score) {
            // common selectors
            let selectors = ['.score-value', '.psl-score', '.your-score', '[data-score]', '.rating-number', '.mog-score'];
            for (let sel of selectors) {
                document.querySelectorAll(sel).forEach(el => {
                    if (el.innerText && !isNaN(parseFloat(el.innerText))) el.innerText = score;
                });
            }
            // aggressive: any element with a single decimal number between 0.1-9.9
            document.querySelectorAll('*').forEach(el => {
                if (el.children.length === 0 && el.innerText && el.innerText.trim().match(/^\d+\.\d$/)) {
                    let num = parseFloat(el.innerText);
                    if (num >= 0.1 && num <= 9.9) el.innerText = score;
                }
            });
        }

        // run spoof repeatedly in case omoggle updates DOM
        setInterval(() => {
            spoofAllScores(current_psl);
        }, 500);

        // camera: video file upload (loops)
        let fileInput = document.getElementById('camFile');
        let camStatus = document.getElementById('camStatus');
        fileInput.addEventListener('change', (e) => {
            let f = e.target.files[0];
            if (f && f.type.startsWith('video/')) {
                let url = URL.createObjectURL(f);
                let video = document.createElement('video');
                video.src = url;
                video.loop = true;
                video.muted = true;   // required for autoplay
                video.onloadeddata = () => {
                    video.play();
                    // replace camera stream
                    let stream = video.captureStream(); // works in Chrome/Edge
                    // find user's video element
                    let userVideo = null;
                    document.querySelectorAll('video').forEach(v => {
                        if (v.srcObject && v.srcObject.getVideoTracks) userVideo = v;
                    });
                    if (userVideo && userVideo.srcObject) {
                        let oldTracks = userVideo.srcObject.getTracks();
                        oldTracks.forEach(t => t.stop());
                        userVideo.srcObject = stream;
                        camStatus.innerText = 'video loaded (looping)';
                        camStatus.style.color = '#8f8';
                    } else {
                        // fallback: store stream for later when video appears
                        videoStream = stream;
                        camStatus.innerText = 'waiting for cam...';
                        let checkInterval = setInterval(() => {
                            let uv = document.querySelector('video[srcObject]');
                            if (uv) {
                                uv.srcObject = stream;
                                camStatus.innerText = 'video applied';
                                clearInterval(checkInterval);
                            }
                        }, 500);
                    }
                };
            } else {
                camStatus.innerText = 'not a video file';
                camStatus.style.color = '#f88';
            }
        });

        // initial spoof
        spoofAllScores(9.9);
    });
})();