Skip to content

Instantly share code, notes, and snippets.

@malys
Last active September 19, 2026 16:20
Show Gist options
  • Select an option

  • Save malys/ad119aeeab2b627ee44f3cefc3788cbd to your computer and use it in GitHub Desktop.

Select an option

Save malys/ad119aeeab2b627ee44f3cefc3788cbd to your computer and use it in GitHub Desktop.
[Open all changedetection ] open unread links in new tab and change state to read #changedetection #userscript
// ==UserScript==
// @name ChangeDetection
// @namespace Violentmonkey Scripts
// @match https://changedetection.l.malys.ovh/*
// @grant GM_openInTab
// @version 1.4
// @author -
// @description Open unread links and mark them viewed
// @downloadURL https://gist.githubusercontent.com/malys/ad119aeeab2b627ee44f3cefc3788cbd/raw/userscript.js
// @updateURL https://gist.githubusercontent.com/malys/ad119aeeab2b627ee44f3cefc3788cbd/raw/userscript.js
// ==/UserScript==
'use strict';
function listLinks() {
const rows = [...document.querySelectorAll('tr.unviewed')];
console.log('Unread rows:', rows.length);
if (!rows.length) {
alert('No unread watches');
return;
}
for (const row of rows) {
// Open monitored URL
const link = row.querySelector('a.external[href]');
if (link) {
console.log('Opening:', link.href);
GM_openInTab(link.href, {
active: false,
insert: true
});
}
// Select actual checkbox
const checkbox = row.querySelector(
'input[name="uuids"][type="checkbox"]'
);
if (checkbox && !checkbox.checked) {
checkbox.click();
}
}
// Find button by attributes, NOT by text
const viewed = document.querySelector(
'button[name="op"][value="mark-viewed"]'
);
console.log('Mark viewed button:', viewed);
if (!viewed) {
alert('Mark viewed button not found');
return;
}
// Allow ChangeDetection's checkbox JS to update
setTimeout(() => {
const form = viewed.closest('form');
if (form && typeof form.requestSubmit === 'function') {
form.requestSubmit(viewed);
} else {
viewed.click();
}
}, 300);
}
function addButton() {
if (document.querySelector('#mybutt')) {
return;
}
const button = document.createElement('button');
button.id = 'mybutt';
button.type = 'button';
button.textContent = 'View all';
button.style.cssText = `
position: fixed;
top: 20px;
left: 10px;
height: 32px;
min-width: 90px;
background: #0073ea;
color: white;
border: 0;
border-radius: 4px;
padding: 5px 10px;
cursor: pointer;
z-index: 99999;
`;
button.addEventListener('click', listLinks);
document.body.appendChild(button);
}
addButton();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment