// ==UserScript==
// @name Global Anti-Inactivity
// @namespace Violentmonkey Scripts
// @license MIT
// @match *://*/*
// @grant none
// @version 1.2 // Incremented version number
// @author SU2H1
// @description Attempts to prevent inactivity detection and overrides visibility API on all websites. Use responsibly and with caution.
// ==/UserScript==
(function() {
'use strict';
// -- Configuration --
const simulateActivityInterval = 60 * 1000; // Simulate activity every 60 seconds
// -- End Configuration --
// No need for the targetWebsites array or the shouldRun check because @match handles injection
console.log("Global Anti-inactivity script running on this website.");
// -- Prevent Blur Events --
// Note: This might interfere with legitimate website functions that rely on blur.
try { // Added try-catch for robustness on potentially sensitive browser/extension pages
window.onblur = null;
window.addEventListener('blur', (event) => {
event.stopImmediatePropagation(); // Using stopImmediatePropagation can be more forceful
}, true); // Use capture phase
document.addEventListener('blur', (event) => {
event.stopImmediatePropagation();
}, true); // Use capture phase
} catch (e) {
console.warn("Anti-inactivity: Could not modify blur handlers.", e);
}
// -- Override Page Visibility API --
// Note: This is invasive and might break sites relying heavily on the visibility API.
try {
let originalVisibilityStateDescriptor = Object.getOwnPropertyDescriptor(Document.prototype, 'visibilityState'); // Check prototype
if (!originalVisibilityStateDescriptor && document) { // Fallback to instance if not on prototype
originalVisibilityStateDescriptor = Object.getOwnPropertyDescriptor(document, 'visibilityState');
}
if (originalVisibilityStateDescriptor && originalVisibilityStateDescriptor.configurable) {
Object.defineProperty(document, 'visibilityState', {
get: function() { return 'visible'; },
configurable: true,
enumerable: true // Match original enumerability if possible
});
} else if (!originalVisibilityStateDescriptor) {
// Define it if it doesn't exist at all (less likely, but for completeness)
Object.defineProperty(document, 'visibilityState', {
get: function() { return 'visible'; },
configurable: true,
enumerable: true
});
} else {
console.warn("Anti-inactivity: visibilityState is not configurable.");
}
// Override addEventListener specifically on document and window for visibilitychange
const originalAddEventListener = EventTarget.prototype.addEventListener;
document.addEventListener = function(type, listener, options) {
if (type === 'visibilitychange') {
console.log("Anti-inactivity: Blocked 'visibilitychange' listener registration on document.");
return; // Ignore
}
return originalAddEventListener.call(this, type, listener, options);
};
window.addEventListener = function(type, listener, options) {
if (type === 'visibilitychange') {
console.log("Anti-inactivity: Blocked 'visibilitychange' listener registration on window.");
return; // Ignore
}
return originalAddEventListener.call(this, type, listener, options);
};
// Attempt to remove any existing listeners (might not always work reliably)
// This is complex and often impractical, blocking new ones is the main effect here.
} catch (e) {
console.warn("Anti-inactivity: Could not fully override Visibility API.", e);
}
// -- Simulate Activity --
let lastActivityTime = Date.now();
function simulateMouseMove() {
try {
const event = new MouseEvent('mousemove', {
clientX: Math.random() * window.innerWidth,
clientY: Math.random() * window.innerHeight,
bubbles: true,
cancelable: false, // Typically false for mousemove
view: window // Ensure view is set
});
document.dispatchEvent(event);
lastActivityTime = Date.now();
} catch(e) {
console.warn("Anti-inactivity: Error simulating mouse move.", e);
}
}
function simulateKeyPress() {
try {
// Keypress is deprecated, keydown/keyup are preferred, but keypress might still work for older scripts
// Focusing an element first might be necessary on some pages for key events to be processed
const event = new KeyboardEvent('keypress', {
key: String.fromCharCode(Math.floor(Math.random() * 26) + 97), // Random lowercase letter
code: 'Key' + String.fromCharCode(Math.floor(Math.random() * 26) + 65), // Corresponding KeyCode (approx)
keyCode: Math.floor(Math.random() * 26) + 97, // keyCode is deprecated but sometimes checked
which: Math.floor(Math.random() * 26) + 97, // which is also deprecated
bubbles: true,
cancelable: true // Key events are often cancelable
});
// Dispatch on document or a potentially focused element if identifiable
document.dispatchEvent(event);
lastActivityTime = Date.now();
} catch(e) {
console.warn("Anti-inactivity: Error simulating key press.", e);
}
}
const activityIntervalId = setInterval(() => {
// Only simulate activity if no real activity has been detected recently
const timeSinceLastActivity = Date.now() - lastActivityTime;
if (timeSinceLastActivity > simulateActivityInterval * 0.8) { // Start simulating a bit before the interval
if (Math.random() > 0.5) {
simulateMouseMove();
} else {
simulateKeyPress();
}
console.log("Simulating user activity.");
}
}, simulateActivityInterval);
// Keep track of actual user activity
['mousemove', 'mousedown', 'mouseup', 'keydown', 'keyup', 'wheel', 'scroll', 'touchstart', 'touchend'].forEach(eventType => {
document.addEventListener(eventType, () => {
lastActivityTime = Date.now();
}, { passive: true, capture: true }); // Capture phase and passive for broader coverage & performance
});
console.log("Global Anti-inactivity measures applied.");
// Optional: Add a way to clean up if the script were ever stopped manually (rare for UserScripts)
// window.addEventListener('unload', () => {
// clearInterval(activityIntervalId);
// Restore original methods if possible (complex and often omitted)
// });
})();