Visual score spoof (10.0) + camera image replacement – works even after updates
// ==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();
}
})();