Skip to content

Instantly share code, notes, and snippets.

@mattogodoy
Created April 16, 2024 15:38
Show Gist options
  • Select an option

  • Save mattogodoy/1618f07e0966d846bfa64bf847535293 to your computer and use it in GitHub Desktop.

Select an option

Save mattogodoy/1618f07e0966d846bfa64bf847535293 to your computer and use it in GitHub Desktop.
A Greasemonkey/Violentmonkey script to bulk-delete events in Frigate
// ==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);
}
}
@NOYB4Europe
Copy link

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