omoggle live psl + video loop + drag

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

Você precisará instalar uma extensão como Tampermonkey, Greasemonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Violentmonkey para instalar este script.

Você precisará instalar uma extensão como Tampermonkey ou Userscripts para instalar este script.

Você precisará instalar uma extensão como o Tampermonkey para instalar este script.

Você precisará instalar um gerenciador de scripts de usuário para instalar este script.

(Eu já tenho um gerenciador de scripts de usuário, me deixe instalá-lo!)

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar uma extensão como o Stylus para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

Você precisará instalar um gerenciador de estilos de usuário para instalar este estilo.

(Eu já possuo um gerenciador de estilos de usuário, me deixar fazer a instalação!)

// ==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);
    });
})();