0% found this document useful (0 votes)
40 views39 pages

User Script 3

Uploaded by

faustinodima
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
40 views39 pages

User Script 3

Uploaded by

faustinodima
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

// ==UserScript==

// @name Enhanced Fake Camera for VFS Global (Anti-Detection)

// @namespace http://tampermonkey.net/

// @version 3.0

// @description Replaces real camera with photo or video with enhanced anti-detection measures

// @author Original: Brazuca! (Modified for anti-detection)

// @match https://idnvui.vfsglobal.com/*

// @match https://visa.vfsglobal.com/*

// @grant none

// ==/UserScript==

(function() {

'use strict';

// ==================== STATE VARIABLES ====================

let cameraActive = false;

let mediaURL = null;

let videoStream = null;

let canvas = null;

let animationFrameId = null;

let videoElement = null;

let isPaused = false;

// ==================== ADVANCED MOCK VARIABLES ====================

// Store original methods to restore later


const originalGetUserMedia = navigator.mediaDevices.getUserMedia;

const originalEnumerateDevices = navigator.mediaDevices.enumerateDevices;

const originalMediaStreamTrack = window.MediaStreamTrack;

// Mock camera device info

const mockCameraDeviceId = 'mock-camera-' + Math.random().toString(36).substring(2, 15);

const mockCameraGroupId = 'mock-group-' + Math.random().toString(36).substring(2, 15);

const mockCameraLabel = ['HD Webcam', 'USB Camera', 'Integrated Camera']


[Math.floor(Math.random() * 3)];

// Zoom control variables

let zoomLevel = 1.0;

const zoomIncrement = 0.1;

const maxZoom = 3.0;

const minZoom = 0.5;

// Position control variables

let offsetX = 0;

let offsetY = 0;

// Reference to UI elements

let zoomContainer = null;

let pauseContainer = null;

let pauseButton = null;

let zoomInButton = null;

let zoomOutButton = null;


let zoomCounter = null;

let directionContainer = null;

// ==================== HELPER FUNCTIONS ====================

function createElement(tagName, styles) {

const element = document.createElement(tagName);

Object.assign(element.style, styles);

return element;

// Generate a random but realistic camera device ID

function generateMockDeviceId() {

return 'mock-camera-' + Math.random().toString(36).substring(2, 15);

// Function to create realistic camera constraints

function createRealisticConstraints(constraints) {

// Preserve the original constraints where possible

let result = { ...constraints };

// Add realistic video constraints if not already specified

if (!result.video || typeof result.video === 'boolean') {

result.video = {

width: { ideal: 1280, min: 640, max: 1920 },

height: { ideal: 720, min: 480, max: 1080 },


frameRate: { ideal: 30, min: 15 },

facingMode: "user"

};

} else if (typeof result.video === 'object') {

// Enhance existing video constraints

result.video = {

...result.video,

deviceId: { exact: mockCameraDeviceId },

frameRate: result.video.frameRate || { ideal: 30, min: 15 }

};

return result;

// ==================== MOCK IMPLEMENTATION ====================

async function activateFakeCamera(url, isPhoto = false) {

// Clear previous state

if (cameraActive) {

deactivateFakeCamera();

try {

// Reset zoom and position

zoomLevel = 1.0;
offsetX = 0;

offsetY = 0;

isPaused = false;

mediaURL = url;

canvas = document.createElement('canvas');

canvas.width = 1280; // Higher resolution for better quality

canvas.height = 720; // 16:9 aspect ratio

let ctx = canvas.getContext('2d', { alpha: false, desynchronized: true });

ctx.imageSmoothingEnabled = true;

ctx.imageSmoothingQuality = 'high';

if (isPhoto) {

// Handle photo with quality preservation

let image = new Image();

image.crossOrigin = "anonymous";

image.src = url;

await new Promise((resolve, reject) => {

image.onload = resolve;

image.onerror = reject;

setTimeout(() => reject(new Error("Timeout loading image")), 8000);

});
// Calculate ratio to preserve aspect

const ratio = Math.min(

canvas.width / image.width,

canvas.height / image.height

);

const newWidth = image.width * ratio;

const newHeight = image.height * ratio;

// Center image on canvas

const x = (canvas.width - newWidth) / 2;

const y = (canvas.height - newHeight) / 2;

// Clear canvas with black background

ctx.fillStyle = '#000';

ctx.fillRect(0, 0, canvas.width, canvas.height);

// Draw image with high quality

ctx.drawImage(image, x, y, newWidth, newHeight);

// For photos, create a stream with minimal frames (static image)

videoStream = canvas.captureStream(5);

// Update UI controls

updateZoomControls(true);
updatePauseButton(true);

} else {

// Handle video with proper playback

videoElement = document.createElement('video');

videoElement.src = url;

videoElement.loop = true;

videoElement.muted = true;

videoElement.autoplay = true;

videoElement.playsInline = true;

videoElement.crossOrigin = "anonymous";

// Apply additional attributes to make video seem more realistic

videoElement.volume = 0;

videoElement.onloadedmetadata = () => {

// Adjust canvas dimensions to match video if needed

if (videoElement.videoWidth && videoElement.videoHeight) {

// Keep aspect ratio but maintain quality

const aspectRatio = videoElement.videoWidth / videoElement.videoHeight;

if (aspectRatio > 1) {

// Landscape video

canvas.width = Math.min(1280, videoElement.videoWidth);

canvas.height = canvas.width / aspectRatio;

} else {

// Portrait or square video


canvas.height = Math.min(720, videoElement.videoHeight);

canvas.width = canvas.height * aspectRatio;

};

try {

await videoElement.play();

} catch (e) {

console.warn("Warning starting video playback:", e);

// Continue despite error - may be autoplay policy

// Function to draw video frames with zoom and positioning

function drawFrame() {

if (!canvas || !ctx || !videoElement) return;

if (videoElement.videoWidth && videoElement.videoHeight) {

// Calculate base dimensions preserving aspect ratio

const ratio = Math.min(

canvas.width / videoElement.videoWidth,

canvas.height / videoElement.videoHeight

);

const baseWidth = videoElement.videoWidth * ratio;


const baseHeight = videoElement.videoHeight * ratio;

// Apply zoom

const scaledWidth = baseWidth * zoomLevel;

const scaledHeight = baseHeight * zoomLevel;

// Calculate centered position with zoom and offset

const baseX = (canvas.width - baseWidth) / 2;

const baseY = (canvas.height - baseHeight) / 2;

// Offset adjusted for zoom

const x = baseX - ((scaledWidth - baseWidth) / 2) + offsetX;

const y = baseY - ((scaledHeight - baseHeight) / 2) + offsetY;

// Clear with black background

ctx.fillStyle = '#000';

ctx.fillRect(0, 0, canvas.width, canvas.height);

// Draw the video frame with applied transformations

ctx.drawImage(videoElement, x, y, scaledWidth, scaledHeight);

// Update zoom counter if present

if (zoomCounter) {

zoomCounter.textContent = `Zoom: ${zoomLevel.toFixed(1)}x`;

}
} else {

// Fallback if video dimensions aren't available

ctx.drawImage(videoElement, 0, 0, canvas.width, canvas.height);

// Continue animation loop

animationFrameId = requestAnimationFrame(drawFrame);

// Start drawing frames

drawFrame();

// Create stream with higher framerate for smoother video

videoStream = canvas.captureStream(30);

// Enable UI controls

updateZoomControls(false);

updatePauseButton(false);

// Add realistic tracks metadata to the stream

enhanceStreamWithRealisticTracks(videoStream);

// Override getUserMedia with our enhanced mock implementation

overrideMediaAPIs();
cameraActive = true;

updateButtons();

console.log(isPhoto ? "Fake photo activated!" : "Fake camera activated!");

} catch (error) {

console.error("Error activating fake media:", error);

alert("Error loading media. Check the selected file or try a smaller file.");

// Clean up in case of error

deactivateFakeCamera();

function enhanceStreamWithRealisticTracks(stream) {

if (!stream || !stream.getVideoTracks || stream.getVideoTracks().length === 0) return;

// Get the actual video track

const videoTrack = stream.getVideoTracks()[0];

// Add realistic properties to the track

if (videoTrack) {

// Store original methods to be used in our mocked ones

const originalGetSettings = videoTrack.getSettings;

const originalGetCapabilities = videoTrack.getCapabilities;


const originalGetConstraints = videoTrack.getConstraints;

const originalApplyConstraints = videoTrack.applyConstraints;

// Override getSettings to return realistic camera settings

videoTrack.getSettings = function() {

// Start with original settings if available

let settings = {};

try {

settings = originalGetSettings.call(this);

} catch (e) {

// Ignore errors from original method

// Add realistic camera settings

return {

...settings,

deviceId: mockCameraDeviceId,

groupId: mockCameraGroupId,

aspectRatio: canvas.width / canvas.height,

frameRate: 30,

height: canvas.height,

width: canvas.width,

resizeMode: "none",

facingMode: "user"

};
};

// Override getCapabilities with realistic camera capabilities

videoTrack.getCapabilities = function() {

let capabilities = {};

try {

capabilities = originalGetCapabilities.call(this);

} catch (e) {

// Ignore errors

return {

...capabilities,

deviceId: mockCameraDeviceId,

aspectRatio: {min: 0.5, max: 2.0},

frameRate: {min: 10, max: 60},

height: {min: 240, max: 1080, step: 1},

width: {min: 320, max: 1920, step: 1},

facingMode: ["user", "environment"]

};

};

// Override getConstraints to return fake constraints

videoTrack.getConstraints = function() {

let constraints = {};


try {

constraints = originalGetConstraints.call(this);

} catch (e) {

// Ignore errors

return {

...constraints,

deviceId: {exact: mockCameraDeviceId},

aspectRatio: {ideal: canvas.width / canvas.height},

frameRate: {ideal: 30},

height: {ideal: canvas.height},

width: {ideal: canvas.width},

facingMode: "user"

};

};

// Override applyConstraints to make it appear to work

videoTrack.applyConstraints = async function(constraints) {

try {

// Try original method first

return await originalApplyConstraints.call(this, constraints);

} catch (e) {

// Just return success - we're faking it anyway

return Promise.resolve();
}

};

// Override label and id with realistic values

Object.defineProperties(videoTrack, {

'label': {

get: function() { return mockCameraLabel; },

configurable: true

},

'id': {

get: function() { return mockCameraDeviceId + '-track'; },

configurable: true

},

'kind': {

get: function() { return 'video'; },

configurable: true

},

'enabled': {

get: function() { return true; },

set: function(value) { /* Do nothing */ },

configurable: true

},

'muted': {

get: function() { return false; },

configurable: true
},

'readyState': {

get: function() { return 'live'; },

configurable: true

});

function overrideMediaAPIs() {

// Override getUserMedia to return our fake stream

navigator.mediaDevices.getUserMedia = async function(constraints) {

// If camera is not active or constraints explicitly request something other than video,

// fallback to original implementation

if (!cameraActive || (constraints && constraints.audio && !constraints.video)) {

return originalGetUserMedia.call(this, constraints);

// Apply realistic constraints to make the mocked stream look more legitimate

const enhancedConstraints = createRealisticConstraints(constraints);

console.log("Enhanced constraints:", enhancedConstraints);

// Return our fake video stream

return new Promise((resolve) => {

resolve(videoStream);
});

};

// Override enumerateDevices to include our fake camera

navigator.mediaDevices.enumerateDevices = async function() {

try {

// Get the real devices first

const realDevices = await originalEnumerateDevices.call(this);

// If camera is not active, just return real devices

if (!cameraActive) {

return realDevices;

// Filter out any existing video devices that might conflict with ours

const nonVideoDevices = realDevices.filter(device => device.kind !== 'videoinput');

// Create our fake device

const fakeCamera = {

deviceId: mockCameraDeviceId,

groupId: mockCameraGroupId,

kind: 'videoinput',

label: mockCameraLabel,

toJSON: function() {

return {
deviceId: this.deviceId,

groupId: this.groupId,

kind: this.kind,

label: this.label

};

};

// Add our fake camera to the list

return [...nonVideoDevices, fakeCamera];

} catch (e) {

console.error("Error in enumerateDevices:", e);

// Fallback to original implementation in case of error

return originalEnumerateDevices.call(this);

};

function deactivateFakeCamera() {

// Stop animation frame if active

if (animationFrameId) {

cancelAnimationFrame(animationFrameId);

animationFrameId = null;

}
// Restore original media APIs

navigator.mediaDevices.getUserMedia = originalGetUserMedia;

navigator.mediaDevices.enumerateDevices = originalEnumerateDevices;

// Clean up resources

if (mediaURL && mediaURL.startsWith('blob:')) {

try {

URL.revokeObjectURL(mediaURL);

} catch(e) {

console.warn("Error revoking URL:", e);

// Reset state variables

mediaURL = null;

videoStream = null;

canvas = null;

videoElement = null;

isPaused = false;

cameraActive = false;

// Update UI

updateButtons();

updateZoomControls(true);

updatePauseButton(true);
console.log("Fake camera deactivated!");

// ==================== UI CONTROL FUNCTIONS ====================

function updateButtons() {

if (!videoButton || !photoButton) return;

if (cameraActive) {

videoButton.textContent = '🔴 Disable Media';

videoButton.style.backgroundColor = 'red';

photoButton.textContent = '🚫 Import Media';

photoButton.style.backgroundColor = 'gray';

photoButton.disabled = true;

} else {

videoButton.textContent = '🎥 Activate Video';

videoButton.style.backgroundColor = 'green';

photoButton.textContent = ' Import Photo';

photoButton.style.backgroundColor = 'blue';

photoButton.disabled = false;

}
function togglePause() {

if (!videoElement) return;

if (isPaused) {

videoElement.play();

pauseButton.textContent = ' Pause';

pauseButton.title = "Pause video";

} else {

videoElement.pause();

pauseButton.textContent = '▶️Play';

pauseButton.title = "Play video";

isPaused = !isPaused;

function updatePauseButton(hide) {

if (!pauseContainer) return;

pauseContainer.style.display = hide ? 'none' : 'flex';

// Reset pause button state

if (!hide && pauseButton) {

isPaused = false;

pauseButton.textContent = ' Pause';


pauseButton.title = "Pause video";

function updateZoomControls(hide) {

if (!zoomContainer) return;

zoomContainer.style.display = hide ? 'none' : 'flex';

if (directionContainer) {

directionContainer.style.display = hide ? 'none' : 'flex';

function adjustZoom(increment) {

// Adjust zoom level with limits

const newZoom = Math.min(maxZoom, Math.max(minZoom, zoomLevel + increment));

// Only update if there's a real change

if (newZoom !== zoomLevel) {

zoomLevel = newZoom;

// Reset offset when returning to normal zoom

if (Math.abs(zoomLevel - 1.0) < 0.05) {

offsetX = 0;

offsetY = 0;

}
}

// ==================== UI CREATION FUNCTIONS ====================

function createDirectionControls() {

const container = createElement('div', {

display: 'flex',

flexDirection: 'column',

alignItems: 'center',

gap: '5px',

marginTop: '10px'

});

// Up button

const upButton = createElement('button', {

padding: '5px 10px',

backgroundColor: '#444',

color: 'white',

border: 'none',

borderRadius: '5px',

cursor: 'pointer',

margin: '0',

fontWeight: 'bold',

width: '30px',

textAlign: 'center'
});

upButton.textContent = '↑';

upButton.title = "Move up";

upButton.addEventListener('click', () => { offsetY += 10; });

// Horizontal buttons container

const horizontalContainer = createElement('div', {

display: 'flex',

gap: '15px',

alignItems: 'center'

});

// Left button

const leftButton = createElement('button', {

padding: '5px 10px',

backgroundColor: '#444',

color: 'white',

border: 'none',

borderRadius: '5px',

cursor: 'pointer',

margin: '0',

fontWeight: 'bold',

width: '30px',

textAlign: 'center'

});
leftButton.textContent = '←';

leftButton.title = "Move left";

leftButton.addEventListener('click', () => { offsetX += 10; });

// Center button

const centerButton = createElement('button', {

padding: '5px 10px',

backgroundColor: '#555',

color: 'white',

border: 'none',

borderRadius: '5px',

cursor: 'pointer',

margin: '0',

fontWeight: 'bold',

width: '30px',

textAlign: 'center'

});

centerButton.textContent = '⊙';

centerButton.title = "Reset position";

centerButton.addEventListener('click', () => {

offsetX = 0;

offsetY = 0;

});

// Right button
const rightButton = createElement('button', {

padding: '5px 10px',

backgroundColor: '#444',

color: 'white',

border: 'none',

borderRadius: '5px',

cursor: 'pointer',

margin: '0',

fontWeight: 'bold',

width: '30px',

textAlign: 'center'

});

rightButton.textContent = '→';

rightButton.title = "Move right";

rightButton.addEventListener('click', () => { offsetX -= 10; });

// Down button

const downButton = createElement('button', {

padding: '5px 10px',

backgroundColor: '#444',

color: 'white',

border: 'none',

borderRadius: '5px',

cursor: 'pointer',

margin: '0',
fontWeight: 'bold',

width: '30px',

textAlign: 'center'

});

downButton.textContent = '↓';

downButton.title = "Move down";

downButton.addEventListener('click', () => { offsetY -= 10; });

// Assemble horizontal container

horizontalContainer.appendChild(leftButton);

horizontalContainer.appendChild(centerButton);

horizontalContainer.appendChild(rightButton);

// Assemble direction container

container.appendChild(upButton);

container.appendChild(horizontalContainer);

container.appendChild(downButton);

container.style.display = 'none'; // Hidden initially

return container;

function createControlPanel() {

// Create main container

const controlPanel = createElement('div', {


position: 'fixed',

bottom: '10px',

right: '10px',

backgroundColor: 'rgba(0, 0, 0, 0.7)',

padding: '10px',

borderRadius: '5px',

zIndex: '9999',

color: 'white',

fontFamily: 'Arial, sans-serif',

fontSize: '14px',

boxShadow: '0 0 10px rgba(0, 0, 0, 0.5)',

display: 'flex',

flexDirection: 'column',

gap: '10px'

});

// Title

const title = createElement('div', {

fontWeight: 'bold',

textAlign: 'center',

borderBottom: '1px solid #555',

paddingBottom: '5px',

marginBottom: '5px'

});

title.textContent = 'Camera Controls';


// Container for video and photo buttons

const mediaButtonsContainer = createElement('div', {

display: 'flex',

gap: '5px',

justifyContent: 'center'

});

// Video button

const videoButton = createElement('button', {

padding: '8px 12px',

backgroundColor: 'green',

color: 'white',

border: 'none',

borderRadius: '5px',

cursor: 'pointer',

flex: '1'

});

videoButton.textContent = '🎥 Activate Video';

videoButton.title = "Select and activate a video file";

videoButton.addEventListener('click', handleVideoButtonClick);

// Photo button

const photoButton = createElement('button', {

padding: '8px 12px',


backgroundColor: 'blue',

color: 'white',

border: 'none',

borderRadius: '5px',

cursor: 'pointer',

flex: '1'

});

photoButton.textContent = ' Import Photo';

photoButton.title = "Select and use a photo";

photoButton.addEventListener('click', handlePhotoButtonClick);

// Add file input (hidden)

const fileInput = createElement('input', {

display: 'none',

type: 'file'

});

fileInput.type = 'file';

fileInput.accept = 'image/*,video/*';

// Zoom controls container

zoomContainer = createElement('div', {

display: 'none', // Hidden initially

flexDirection: 'row',

gap: '5px',

alignItems: 'center',
justifyContent: 'center'

});

// Zoom out button

zoomOutButton = createElement('button', {

padding: '5px 10px',

backgroundColor: '#444',

color: 'white',

border: 'none',

borderRadius: '5px',

cursor: 'pointer',

fontWeight: 'bold'

});

zoomOutButton.textContent = '➖';

zoomOutButton.title = "Zoom out";

zoomOutButton.addEventListener('click', () => adjustZoom(-zoomIncrement));

// Zoom counter

zoomCounter = createElement('span', {

minWidth: '80px',

textAlign: 'center'

});

zoomCounter.textContent = 'Zoom: 1.0x';

// Zoom in button
zoomInButton = createElement('button', {

padding: '5px 10px',

backgroundColor: '#444',

color: 'white',

border: 'none',

borderRadius: '5px',

cursor: 'pointer',

fontWeight: 'bold'

});

zoomInButton.textContent = '➕';

zoomInButton.title = "Zoom in";

zoomInButton.addEventListener('click', () => adjustZoom(zoomIncrement));

// Pause controls container

pauseContainer = createElement('div', {

display: 'none', // Hidden initially

justifyContent: 'center'

});

// Pause/play button

pauseButton = createElement('button', {

padding: '5px 10px',

backgroundColor: '#444',

color: 'white',

border: 'none',
borderRadius: '5px',

cursor: 'pointer',

width: '100%'

});

pauseButton.textContent = ' Pause';

pauseButton.title = "Pause video";

pauseButton.addEventListener('click', togglePause);

// Create direction controls

directionContainer = createDirectionControls();

// Close button (X in top right corner)

const closeButton = createElement('button', {

position: 'absolute',

top: '5px',

right: '5px',

background: 'none',

border: 'none',

color: 'white',

cursor: 'pointer',

fontSize: '16px',

padding: '0',

margin: '0',

lineHeight: '1'

});
closeButton.textContent = '×';

closeButton.title = "Hide controls";

closeButton.addEventListener('click', () => {

controlPanel.style.display = 'none';

});

// Minimize button (to show when control panel is hidden)

const minimizeButton = createElement('button', {

position: 'fixed',

bottom: '10px',

right: '10px',

backgroundColor: 'rgba(0, 0, 0, 0.7)',

color: 'white',

border: 'none',

borderRadius: '5px',

padding: '5px 10px',

cursor: 'pointer',

zIndex: '9998',

display: 'none'

});

minimizeButton.textContent = '📷';

minimizeButton.title = "Show camera controls";

minimizeButton.addEventListener('click', () => {

controlPanel.style.display = 'flex';

minimizeButton.style.display = 'none';
});

// When control panel is closed, show minimize button

closeButton.addEventListener('click', () => {

minimizeButton.style.display = 'block';

});

// Add event listener for file selection

fileInput.addEventListener('change', handleFileSelect);

// Assemble zoom container

zoomContainer.appendChild(zoomOutButton);

zoomContainer.appendChild(zoomCounter);

zoomContainer.appendChild(zoomInButton);

// Assemble pause container

pauseContainer.appendChild(pauseButton);

// Assemble media buttons

mediaButtonsContainer.appendChild(videoButton);

mediaButtonsContainer.appendChild(photoButton);

// Assemble control panel

controlPanel.appendChild(closeButton);

controlPanel.appendChild(title);
controlPanel.appendChild(mediaButtonsContainer);

controlPanel.appendChild(zoomContainer);

controlPanel.appendChild(pauseContainer);

controlPanel.appendChild(directionContainer);

controlPanel.appendChild(fileInput);

// Add both elements to the document

document.body.appendChild(controlPanel);

document.body.appendChild(minimizeButton);

// Store references to elements

window.videoButton = videoButton;

window.photoButton = photoButton;

window.fileInput = fileInput;

// ==================== EVENT HANDLERS ====================

function handleVideoButtonClick() {

if (cameraActive) {

deactivateFakeCamera();

} else {

fileInput.setAttribute('accept', 'video/*');

fileInput.click();

}
function handlePhotoButtonClick() {

fileInput.setAttribute('accept', 'image/*');

fileInput.click();

function handleFileSelect(event) {

const file = event.target.files[0];

if (!file) return;

// Clear the input value so the same file can be selected again

event.target.value = '';

const isPhoto = file.type.startsWith('image/');

const url = URL.createObjectURL(file);

activateFakeCamera(url, isPhoto);

// ==================== KEYBOARD SHORTCUTS ====================

function setupKeyboardShortcuts() {

document.addEventListener('keydown', (event) => {

// Only if camera is active

if (!cameraActive) return;
switch(event.key) {

case '+':

case '=': // For keyboards where + requires Shift

adjustZoom(zoomIncrement);

break;

case '-':

adjustZoom(-zoomIncrement);

break;

case ' ': // Space bar

if (videoElement) togglePause();

break;

case 'ArrowUp':

offsetY += 10;

break;

case 'ArrowDown':

offsetY -= 10;

break;

case 'ArrowLeft':

offsetX += 10;

break;

case 'ArrowRight':

offsetX -= 10;

break;

case '0': // Reset zoom and position

zoomLevel = 1.0;
offsetX = 0;

offsetY = 0;

break;

});

// ==================== INITIALIZATION ====================

function init() {

// Create control panel when page is loaded

createControlPanel();

// Setup keyboard shortcuts

setupKeyboardShortcuts();

console.log("Enhanced Fake Camera for VFS Global initialized!");

// Initialize when DOM is loaded

if (document.readyState === 'loading') {

document.addEventListener('DOMContentLoaded', init);

} else {

init();

})();

You might also like