Created
April 16, 2024 15:38
-
-
Save mattogodoy/1618f07e0966d846bfa64bf847535293 to your computer and use it in GitHub Desktop.
A Greasemonkey/Violentmonkey script to bulk-delete events in Frigate
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name Frigate - Bulk delete events | |
| // @namespace Violentmonkey Scripts | |
| // @match http://192.168.1.120:8100/events* | |
| // @grant none | |
| // @version 1.0 | |
| // @author Matto Godoy | |
| // @description Deletes multiple events one by one in Frigate NVR | |
| // ==/UserScript== | |
| const sleep = time => new Promise(res => setTimeout(res, time, "done sleeping")); | |
| window.onload = function(){ | |
| // Wait for the page to load (it takes a good while) | |
| console.log("Waiting..."); | |
| sleep(3000).then(msg => { | |
| console.log("Let's go!"); | |
| addLinks(); | |
| }); | |
| }; | |
| // 1. Find the "PAST EVENTS" title so we can add the link under it | |
| function findTitleLocation(){ | |
| var titleElement; | |
| for (const h1 of document.querySelectorAll("h1")) { | |
| if (h1.textContent.includes("Past Events")) { | |
| titleElement = h1; | |
| break; | |
| } | |
| } | |
| return titleElement; | |
| } | |
| // 2. Add the Delete link | |
| function addLinks(){ | |
| var titleEl = findTitleLocation(); | |
| // Add "Add checks" link | |
| var html = '<a href="javascript:void(0);" style="color: green;">Add checks</a>'; | |
| var el = document.createElement('div'); | |
| el.innerHTML = html; | |
| el.addEventListener('click', addCheckboxes); | |
| titleEl.append(el); | |
| // Add "Select all" link | |
| var html = '<a href="javascript:void(0);" style="color: yellow;">Select all</a>'; | |
| var el = document.createElement('div'); | |
| el.innerHTML = html; | |
| el.addEventListener('click', checkAllBoxes); | |
| titleEl.append(el); | |
| // Add "Delete" link | |
| var html = '<a href="javascript:void(0);" style="color: red;">Delete all selected clips</a>'; | |
| var el = document.createElement('div'); | |
| el.innerHTML = html; | |
| el.addEventListener('click', cleanClips); | |
| titleEl.append(el); | |
| } | |
| // 3. Add checkboxes to all events in the list | |
| function addCheckboxes(){ | |
| const events = document.getElementsByClassName('flex bg-slate-100 dark:bg-slate-800 rounded cursor-pointer min-w-[330px]'); | |
| for(i=0; i<events.length; i++){ | |
| var eventEl = events[i].childNodes[1].childNodes[2]; | |
| if(eventEl.childElementCount > 2) | |
| continue; // Already has a checkbox | |
| var html = '<input type="checkbox" id="deleteEvent_' + i + '" class="delete-event" onclick="event.stopPropagation();" />'; | |
| var checkboxEl = document.createElement('div'); | |
| checkboxEl.innerHTML = html; | |
| eventEl.prepend(checkboxEl); | |
| } | |
| } | |
| // Marks all boxes as checked | |
| function checkAllBoxes(){ | |
| var checkboxes = document.getElementsByClassName('delete-event'); | |
| for (var i=0; i<checkboxes.length; i++) { | |
| checkboxes[i].checked = true; | |
| } | |
| } | |
| // 4. Get all checked boxes so we can delete those events | |
| function getCheckedBoxes() { | |
| var checkboxes = document.getElementsByClassName('delete-event'); | |
| var checkboxesChecked = []; | |
| for (var i=0; i<checkboxes.length; i++) { | |
| if (checkboxes[i].checked) { | |
| checkboxesChecked.push(checkboxes[i]); | |
| } | |
| } | |
| return checkboxesChecked.length > 0 ? checkboxesChecked : null; | |
| } | |
| // 5. Delete the clips that have their checkboxes checked | |
| function cleanClips() { | |
| const delayTime = 2000; // milliseconds | |
| var checkboxes = getCheckedBoxes(); | |
| if(checkboxes == null) | |
| return false; | |
| for (var i=0; i<checkboxes.length; i++) { | |
| (function(i) { | |
| setTimeout(function() { | |
| console.log("Deleting", i + 1, "of", checkboxes.length, "clips..."); | |
| var deleteButton = checkboxes[i].parentElement.parentElement.childNodes[1]; | |
| deleteButton.dispatchEvent(new Event('click')); | |
| }, delayTime * i); | |
| })(i); | |
| } | |
| } |
Author
Great idea. Thank you for your work.
I tried to use it with Greasemonkey and tampermonkey in Firefox but it did not work and I don't know how to fix it.
Tampermonkey had some syntax complains which I fixed :
I will reduce the retain to 1 day every now an than.
// ==UserScript==
// @name Frigate - Bulk delete events
// @namespace Violentmonkey Scripts
// @match http://homeassistant.local:8123/events*, http://192.168.1.77:8123/events*
// @grant none
// @version 1.02
// @author Matto Godoy
// @description Deletes multiple events one by one in Frigate NVR
// ==/UserScript==
const sleep = time => new Promise(res => setTimeout(res, time, "done sleeping"));
window.onload = function(){
// Wait for the page to load (it takes a good while)
console.log("Waiting...");
sleep(3000).then(msg => {
console.log("Let's go!");
addLinks();
});
};
// 1. Find the "PAST EVENTS" title so we can add the link under it
function findTitleLocation(){
var titleElement;
for (const h1 of document.querySelectorAll("h1")) {
if (h1.textContent.includes("Past Events")) {
titleElement = h1;
break;
}
}
return titleElement;
}
// 2. Add the Delete link
function addLinks(){
var titleEl = findTitleLocation();
// Add "Add checks" link
var html = '<a href="javascript:void(0);" style="color: green;">Add checks</a>';
var el = document.createElement('div');
el.innerHTML = html;
el.addEventListener('click', addCheckboxes);
titleEl.append(el);
// Add "Select all" link
var html1 = '<a href="javascript:void(0);" style="color: yellow;">Select all</a>';
var el1 = document.createElement('div');
el1.innerHTML = html1;
el1.addEventListener('click', checkAllBoxes);
titleEl.append(el1);
// Add "Delete" link
var html2 = '<a href="javascript:void(0);" style="color: red;">Delete all selected clips</a>';
var el2 = document.createElement('div');
el2.innerHTML = html2;
el2.addEventListener('click', cleanClips);
titleEl.append(el2);
}
// 3. Add checkboxes to all events in the list
function addCheckboxes(){
const events = document.getElementsByClassName('flex bg-slate-100 dark:bg-slate-800 rounded cursor-pointer min-w-[330px]');
var i;
for(i=0; i<events.length; i++){
var eventEl = events[i].childNodes[1].childNodes[2];
if(eventEl.childElementCount > 2){
continue; }// Already has a checkbox
var html = '<input type="checkbox" id="deleteEvent_' + i + '" class="delete-event" onclick="event.stopPropagation();" />';
var checkboxEl = document.createElement('div');
checkboxEl.innerHTML = html;
eventEl.prepend(checkboxEl);
}
}
// Marks all boxes as checked
function checkAllBoxes(){
var checkboxes = document.getElementsByClassName('delete-event');
for (var i=0; i<checkboxes.length; i++) {
checkboxes[i].checked = true;
}
}
// 4. Get all checked boxes so we can delete those events
function getCheckedBoxes() {
var checkboxes = document.getElementsByClassName('delete-event');
var checkboxesChecked = [];
for (var i=0; i<checkboxes.length; i++) {
if (checkboxes[i].checked) {
checkboxesChecked.push(checkboxes[i]);
}
}
return checkboxesChecked.length > 0 ? checkboxesChecked : null;
}
// 5. Delete the clips that have their checkboxes checked
function cleanClips() {
const delayTime = 2000; // milliseconds
var checkboxes = getCheckedBoxes();
if(checkboxes == null)
{return false;}
for (var i=0; i<checkboxes.length; i++) {
(function(i) {
setTimeout(function() {
console.log("Deleting", i + 1, "of", checkboxes.length, "clips...");
var deleteButton = checkboxes[i].parentElement.parentElement.childNodes[1];
deleteButton.dispatchEvent(new Event('click'));
}, delayTime * i);
})(i);
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Here's a demo of how it works:
frigate-bulk-delete.mov