Skip to content

Instantly share code, notes, and snippets.

@SmugZombie
Last active December 3, 2025 22:11
Show Gist options
  • Select an option

  • Save SmugZombie/d8417afaa4456ea3aedb33b9ff794e9a to your computer and use it in GitHub Desktop.

Select an option

Save SmugZombie/d8417afaa4456ea3aedb33b9ff794e9a to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Datto RMM Idle Refresh Helper (Countdown + Ignore Paths)
// @namespace http://tampermonkey.net/
// @version 1.4
// @description Refresh Datto RMM after idle periods to keep SSO sessions alive, with a countdown. Ignores certain paths.
// @match https://zinfandel.rmm.datto.com/*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// ==/UserScript==
(function() {
'use strict';
// --- IGNORE PATHS HERE ---
const IGNORED_PATH_PREFIXES = [
"/web-remote", // ignores /web-remote, /web-remote/..., /web-remoteXYZ...
];
function shouldIgnorePath() {
const path = window.location.pathname;
return IGNORED_PATH_PREFIXES.some(prefix => path.startsWith(prefix));
}
// If the path should be ignored, do not initialize ANY idle/refresh behavior
if (shouldIgnorePath()) {
console.log("[Datto IdleRefresh] Ignored path:", window.location.pathname);
return;
}
// --- CONFIG ---
const INACTIVITY_MS = 3 * 1000;
const REFRESH_DELAY_MS = 1 * 60 * 1000;
// --- STATE ---
let enabled = GM_getValue("datto_idle_refresh_enabled", true);
let lastActivity = Date.now();
let idleTimer = null;
let refreshTimer = null;
let refreshCountdownInterval = null;
let refreshTargetTime = null;
let ui = null;
function log(...a) { console.log("[Datto IdleRefresh]", ...a); }
// -------------------------------------
// TIMER HELPERS
// -------------------------------------
function clearIdleTimer() {
if (idleTimer) {
clearTimeout(idleTimer);
idleTimer = null;
}
}
function clearRefreshTimer() {
if (refreshTimer) {
clearTimeout(refreshTimer);
refreshTimer = null;
}
refreshTargetTime = null;
stopCountdown();
}
function clearAllTimers() {
clearIdleTimer();
clearRefreshTimer();
}
function scheduleIdleTimer() {
clearIdleTimer();
if (!enabled) return;
idleTimer = setTimeout(handleIdle, INACTIVITY_MS);
updateUI();
}
function handleIdle() {
if (!enabled) return;
const now = Date.now();
const diff = now - lastActivity;
if (diff < INACTIVITY_MS - 500) {
scheduleIdleTimer();
return;
}
log("User idle detected. Scheduling refresh in", REFRESH_DELAY_MS / 1000, "seconds...");
scheduleRefresh();
}
function scheduleRefresh() {
clearRefreshTimer();
if (!enabled) return;
refreshTargetTime = Date.now() + REFRESH_DELAY_MS;
refreshTimer = setTimeout(doRefresh, REFRESH_DELAY_MS);
startCountdown();
updateUI();
}
function doRefresh() {
if (!enabled) return;
const now = Date.now();
const diff = now - lastActivity;
if (diff < INACTIVITY_MS - 500) {
log("Refresh canceled—user became active again.");
clearRefreshTimer();
scheduleIdleTimer();
updateUI();
return;
}
log("Refreshing page due to inactivity...");
stopCountdown();
window.location.reload();
}
// -------------------------------------
// USER ACTIVITY
// -------------------------------------
const activityEvents = [
"mousemove", "mousedown", "mouseup", "click",
"keydown", "keyup", "touchstart", "touchmove",
"scroll", "focus"
];
function onActivity() {
if (!enabled) return;
lastActivity = Date.now();
clearRefreshTimer();
scheduleIdleTimer();
updateUI();
}
// -------------------------------------
// COUNTDOWN UI
// -------------------------------------
function startCountdown() {
stopCountdown();
if (!refreshTargetTime) return;
refreshCountdownInterval = setInterval(updateUI, 1000);
}
function stopCountdown() {
if (refreshCountdownInterval) {
clearInterval(refreshCountdownInterval);
refreshCountdownInterval = null;
}
}
// -------------------------------------
// TOGGLE UI
// -------------------------------------
function createUI() {
if (ui) return;
ui = document.createElement("div");
ui.id = "datto-idle-refresh-toggle";
Object.assign(ui.style, {
position: "fixed",
bottom: "60px",
right: "10px",
zIndex: 999999,
padding: "6px 10px",
background: "#222",
color: "#fff",
fontSize: "12px",
fontFamily: "Arial, sans-serif",
borderRadius: "4px",
cursor: "pointer",
opacity: "0.75",
transition: "opacity 0.2s, background 0.2s",
userSelect: "none"
});
ui.addEventListener("mouseenter", () => {
ui.style.opacity = "1";
ui.style.background = enabled ? "#28a745" : "#666";
});
ui.addEventListener("mouseleave", () => {
ui.style.opacity = "0.75";
ui.style.background = "#222";
});
ui.addEventListener("click", () => {
enabled = !enabled;
GM_setValue("datto_idle_refresh_enabled", enabled);
clearAllTimers();
stopCountdown();
if (enabled) {
lastActivity = Date.now();
scheduleIdleTimer();
}
updateUI();
});
document.body.appendChild(ui);
updateUI();
}
function updateUI() {
if (!ui) return;
if (!enabled) {
ui.textContent = "Datto Idle Refresh: OFF (paused)";
return;
}
if (refreshTimer && refreshTargetTime) {
const msLeft = refreshTargetTime - Date.now();
const secondsLeft = Math.max(0, Math.ceil(msLeft / 1000));
ui.textContent = `Datto Idle Refresh: ON (refresh in ${secondsLeft}s)`;
return;
}
ui.textContent = "Datto Idle Refresh: ON (monitoring activity)";
}
// -------------------------------------
// MENU COMMAND
// -------------------------------------
GM_registerMenuCommand("Toggle idle refresh", () => {
enabled = !enabled;
GM_setValue("datto_idle_refresh_enabled", enabled);
clearAllTimers();
stopCountdown();
if (enabled) {
lastActivity = Date.now();
scheduleIdleTimer();
}
updateUI();
});
// -------------------------------------
// INIT
// -------------------------------------
function init() {
if (shouldIgnorePath()) {
console.log("[Datto IdleRefresh] Ignored path:", window.location.pathname);
return;
}
createUI();
activityEvents.forEach(evt =>
window.addEventListener(evt, onActivity, { passive: true })
);
document.addEventListener("visibilitychange", () => {
if (!document.hidden) onActivity();
});
if (enabled) {
scheduleIdleTimer();
}
updateUI();
log("Initialized.");
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init);
} else {
init();
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment