Omoggle Simple Spoof (Score + Camera)

Visual score spoof (10.0) + camera image replacement – works even after updates

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

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

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

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

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

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         Omoggle Simple Spoof (Score + Camera)
// @namespace    http://tampermonkey.net/
// @version      3.0
// @description  Visual score spoof (10.0) + camera image replacement – works even after updates
// @match        *://*.omoggle.com/*
// @grant        none
// @run-at       document-start
// ==/UserScript==

(function() {
  'use strict';

  // ======================= SCORE SPOOF (visual + finalize) =======================
  // Force your displayed score to always be 10.0
  function fixScoreText() {
    const scoreSelector = 'span.font-mono.font-black.text-white.drop-shadow-md, .score-value, [class*="score"]';
    const observer = new MutationObserver(() => {
      document.querySelectorAll(scoreSelector).forEach(el => {
        const txt = el.innerText.trim();
        if (/^\d+(\.\d)?$/.test(txt) && parseFloat(txt) !== 10.0) {
          el.innerText = '10.0';
        }
      });
    });
    observer.observe(document.body, { childList: true, subtree: true, characterData: true });
  }

  // Intercept finalize fetch to set opponent score low (9.8)
  const origFetch = window.fetch;
  window.fetch = function(url, options) {
    if (typeof url === 'string' && (url.includes('/api/match/finalize') || url.includes('/api/ranked/finalize'))) {
      if (options && options.body) {
        try {
          const body = JSON.parse(options.body);
          // Set your score to 10.0, opponent to 9.8
          if (body.selfScore !== undefined) body.selfScore = 10.0;
          if (body.opponentScore !== undefined) body.opponentScore = 9.8;
          if (body.myScore !== undefined) body.myScore = 10.0;
          if (body.theirScore !== undefined) body.theirScore = 9.8;
          options.body = JSON.stringify(body);
        } catch(e) {}
      }
    }
    return origFetch.call(this, url, options);
  };

  // Run score spoof when DOM ready
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', fixScoreText);
  } else {
    fixScoreText();
  }

  // ======================= CAMERA SPOOF (static image from file) =======================
  let cameraActive = false;
  let cameraStream = null;
  let imageElement = null;
  const STORAGE_KEY = 'omoggle_cam_image';

  // Create a canvas that draws the selected image
  let canvas = null;
  let ctx = null;
  let animationId = null;

  function initCanvas() {
    if (canvas) return;
    canvas = document.createElement('canvas');
    canvas.width = 640;
    canvas.height = 480;
    ctx = canvas.getContext('2d');
    ctx.fillStyle = '#000';
    ctx.fillRect(0, 0, 640, 480);
  }

  function drawImage(img) {
    if (!ctx) return;
    ctx.clearRect(0, 0, 640, 480);
    const scale = Math.max(640 / img.width, 480 / img.height);
    const dx = (640 - img.width * scale) / 2;
    const dy = (480 - img.height * scale) / 2;
    ctx.drawImage(img, dx, dy, img.width * scale, img.height * scale);
  }

  function loadImageFromDataURL(dataURL) {
    const img = new Image();
    img.onload = () => {
      imageElement = img;
      drawImage(img);
      if (cameraActive && canvas) {
        // Update the stream if active
        if (cameraStream) {
          const newStream = canvas.captureStream(30);
          const newTrack = newStream.getVideoTracks()[0];
          const oldTracks = cameraStream.getVideoTracks();
          oldTracks.forEach(t => t.stop());
          cameraStream = newStream;
          // Replace in all video elements using this stream
          document.querySelectorAll('video').forEach(vid => {
            if (vid.srcObject === cameraStream) vid.srcObject = newStream;
          });
        }
      }
    };
    img.src = dataURL;
  }

  function loadSavedImage() {
    const saved = localStorage.getItem(STORAGE_KEY);
    if (saved) loadImageFromDataURL(saved);
  }

  function saveImageFromFile(file) {
    const reader = new FileReader();
    reader.onload = e => {
      localStorage.setItem(STORAGE_KEY, e.target.result);
      loadImageFromDataURL(e.target.result);
    };
    reader.readAsDataURL(file);
  }

  // Override getUserMedia to return our canvas stream when camera spoof is active
  const originalGetUserMedia = navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);
  navigator.mediaDevices.getUserMedia = async function(constraints) {
    if (cameraActive && constraints && constraints.video) {
      if (!canvas) initCanvas();
      if (imageElement) drawImage(imageElement);
      if (!cameraStream) cameraStream = canvas.captureStream(30);
      // If audio requested, combine real audio with fake video
      if (constraints.audio) {
        try {
          const audioStream = await originalGetUserMedia({ audio: constraints.audio });
          const tracks = [...cameraStream.getVideoTracks(), ...audioStream.getAudioTracks()];
          return new MediaStream(tracks);
        } catch(e) {
          return cameraStream;
        }
      }
      return cameraStream;
    }
    return originalGetUserMedia(constraints);
  };

  // Also patch RTCPeerConnection to ensure track replacement
  const origAddTrack = RTCPeerConnection.prototype.addTrack;
  RTCPeerConnection.prototype.addTrack = function(track, ...streams) {
    if (cameraActive && track.kind === 'video' && cameraStream) {
      const fakeTrack = cameraStream.getVideoTracks()[0];
      if (fakeTrack) return origAddTrack.call(this, fakeTrack, ...streams);
    }
    return origAddTrack.call(this, track, ...streams);
  };

  // ======================= UI (mobile friendly) =======================
  function buildUI() {
    if (document.getElementById('simple-spoof-ui')) return;

    const toggleBtn = document.createElement('button');
    toggleBtn.id = 'simple-spoof-toggle';
    toggleBtn.innerText = '📷';
    toggleBtn.style.cssText = `
      position: fixed;
      bottom: 20px;
      right: 20px;
      width: 50px;
      height: 50px;
      border-radius: 25px;
      background: #00ff88;
      border: none;
      font-size: 24px;
      z-index: 999999;
      cursor: pointer;
      box-shadow: 0 2px 10px black;
    `;
    document.body.appendChild(toggleBtn);

    const panel = document.createElement('div');
    panel.id = 'simple-spoof-ui';
    panel.style.cssText = `
      position: fixed;
      bottom: 80px;
      right: 20px;
      width: 240px;
      background: #111;
      border: 2px solid #00ff88;
      border-radius: 12px;
      padding: 12px;
      color: white;
      font-family: monospace;
      z-index: 999998;
      display: none;
      flex-direction: column;
      gap: 10px;
    `;
    panel.innerHTML = `
      <div style="display:flex; justify-content:space-between; align-items:center;">
        <span style="color:#00ff88;">📷 Camera Spoof</span>
        <label style="display:flex; align-items:center; gap:6px;">
          <span>OFF</span>
          <input type="checkbox" id="camToggleCheckbox">
        </label>
      </div>
      <button id="choosePhotoBtn" style="background:#333; border:1px solid #00ff88; border-radius:8px; padding:6px; color:white;">Select Photo</button>
      <input type="file" id="photoInput" accept="image/*" style="display:none;">
      <div id="camStatus" style="font-size:11px; color:#aaa;">No photo loaded</div>
      <div style="font-size:10px; border-top:1px solid #333; margin-top:5px; padding-top:5px;">
        Score: <span style="color:#00ff88;">10.0 (you)</span> | Opp: 9.8
      </div>
    `;
    document.body.appendChild(panel);

    const checkbox = document.getElementById('camToggleCheckbox');
    const statusDiv = document.getElementById('camStatus');
    const chooseBtn = document.getElementById('choosePhotoBtn');
    const fileInput = document.getElementById('photoInput');

    checkbox.addEventListener('change', () => {
      cameraActive = checkbox.checked;
      const label = checkbox.parentElement.querySelector('span:first-child');
      if (cameraActive) {
        label.innerText = 'ON';
        if (!imageElement) loadSavedImage();
        statusDiv.innerText = 'Active – using ' + (imageElement ? 'photo' : 'default black');
      } else {
        label.innerText = 'OFF';
        statusDiv.innerText = 'Camera spoof off';
      }
    });

    chooseBtn.addEventListener('click', () => fileInput.click());
    fileInput.addEventListener('change', e => {
      if (e.target.files[0]) {
        saveImageFromFile(e.target.files[0]);
        statusDiv.innerText = 'Photo saved! Enable spoof.';
      }
    });

    toggleBtn.addEventListener('click', () => {
      const isVisible = panel.style.display === 'flex';
      panel.style.display = isVisible ? 'none' : 'flex';
    });

    // Load saved photo on startup
    loadSavedImage();
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', buildUI);
  } else {
    buildUI();
  }
})();