Skip to content

Instantly share code, notes, and snippets.

@caiohamamura
Last active August 5, 2021 21:18
Show Gist options
  • Select an option

  • Save caiohamamura/098779d9e0a8335757c7f94844366e92 to your computer and use it in GitHub Desktop.

Select an option

Save caiohamamura/098779d9e0a8335757c7f94844366e92 to your computer and use it in GitHub Desktop.
Tampermonkey - Google meet: csv list of attendance
// ==UserScript==
// @name Google meet: csv list of attendance
// @namespace http://tampermonkey.net/
// @version 0.1
// @description try to take over the world!
// @author You
// @match https://meet.google.com/*
// @grant none
// ==/UserScript==
(function() {
class ColecaoPessoas {
constructor() {
this.pessoas = [];
}
add(pessoa) {
this.pessoas.push(pessoa);
}
getOuAdd(nome) {
let pessoa;
if (this.contains(nome))
pessoa = this.pessoas.filter(pessoa => pessoa.nome == nome)[0];
else {
pessoa = new Pessoa();
pessoa.nome = nome;
this.pessoas.push(pessoa);
}
return pessoa;
}
contains(nome) {
return this.pessoas.filter(e => e.nome == nome).length > 0;
}
getAsCSV() {
var head = '"Name";"Conected";"Disconnected";"First login";"Last logoff";"NoDisconnections"\n';
let pessoas2 = this.pessoas.sort((a,b) => a.nome.trim().toLowerCase() > b.nome.trim().toLowerCase() ? 1 : -1);
pessoas2 = pessoas2.filter(p =>
p.nome.indexOf("Caio Hamamura")===-1 &&
p.nome.indexOf("Você")===-1 &&
p.nome.indexOf("Abaixar")===-1 &&
p.nome.indexOf("Desativar")===-1 &&
p.nome.indexOf("keep_off")===-1 &&
p.nome.indexOf("Todos com o som")===-1 &&
p.nome.indexOf("Sua apresentação")===-1 &&
p.nome.indexOf("Mãos")===-1
);
this.pessoas = [];
return head + pessoas2.map(pessoa => '"' + pessoa.nome.replace("\n", " ") + '";"' + pessoa.getTempo() + '";"' + pessoa.getTempoDesconectado() + '";"' + pessoa.primeiraEntrada.toLocaleTimeString() + '";"' + pessoa.ultimaSaida.toLocaleTimeString() + '";' + pessoa.quedas()).join("\n");
}
}
class Registro {
constructor() {
this.entrada = false;
this.saida = false;
}
}
const Ajudante = {
getTimeString(delta) {
delta /= 1000.0;
// calculate (and subtract) whole hours
var hours = Math.floor(delta / 3600) % 24;
delta -= hours * 3600;
// calculate (and subtract) whole minutes
var minutes = Math.floor(delta / 60) % 60;
delta -= minutes * 60;
// what's left is seconds
var seconds = delta % 60;
return `${hours.toString().padStart(2, 0)}:${minutes.toString().padStart(2, 0)}:${seconds.toFixed(0).padStart(2, 0)}`;
}
}
class Pessoa {
constructor(nome) {
this.nome = nome;
this.primeiraEntrada = false;
this.ultimaSaida = false;
this.registros = [];
this.ultimoRegistro = new Registro();
}
saiu() {
return this.ultimoRegistro.saida != false;
}
entrou() {
return this.ultimoRegistro.entrada != false;
}
entrar() {
if (this.entrou() && !this.saiu())
this.sair();
this.ultimoRegistro.entrada = new Date();
if (this.primeiraEntrada == false)
this.primeiraEntrada = this.ultimoRegistro.entrada;
}
sair() {
if (this.entrou()) {
this.ultimoRegistro.saida = new Date();
this.ultimaSaida = this.ultimoRegistro.saida;
this.addUltimoRegistro();
}
}
addUltimoRegistro() {
this.registros.push(this.ultimoRegistro);
this.ultimoRegistro = new Registro();
}
quedas() {
return this.registros.length + this.entrou() - 1;
}
getTempoDesconectado() {
var deltaTotal = 0;
this.registros.map(registro => registro.saida - registro.entrada).forEach(delta => deltaTotal += delta);
if (this.entrou() && !this.saiu()) {
deltaTotal += new Date() - this.ultimoRegistro.entrada;
this.ultimaSaida = new Date();
}
return Ajudante.getTimeString((this.ultimaSaida - this.primeiraEntrada) - deltaTotal);
}
getTempo() {
let deltaTotal = 0;
this.registros.map(registro => registro.saida - registro.entrada).forEach(delta => deltaTotal += delta);
if (this.entrou() && !this.saiu())
deltaTotal += new Date() - this.ultimoRegistro.entrada;
return Ajudante.getTimeString(deltaTotal);
}
}
var totalPeople = {};
var lastTimeout = 0;
var initialTab = 0;
var isExpanded = false;
var people = false;
var pessoas = new ColecaoPessoas();
window.pessoas = pessoas;
function personOut(nome) {
let pessoa = pessoas.getOuAdd(nome);
pessoa.sair();
}
function personIn(nome) {
let pessoa = pessoas.getOuAdd(nome);
pessoa.entrar();
}
//observer.disconnect()
function startMonitor() {
var targetNode3 = document.querySelector("[data-participant-id]").parentElement;
var config3 = { attributes: false, childList: true, subtree: true, characterData: true };
// List of all connected users
Array.from(document.querySelectorAll("[data-participant-id]")).map(item=>item.innerText).forEach(nome => personIn(nome));
var callback3 = function(mutationsList, observer) {
// console.log(mutationsList);
let todos = Array.from(document.querySelectorAll("[data-participant-id]")).map(item=>item.innerText);
let nomesAdd = mutationsList.filter(el => el.type == "characterData").map(el => el.target.wholeText);
let estavamDentro = pessoas.pessoas.filter(pessoa=>pessoa.entrou() && !pessoa.saiu()).map(pessoa => pessoa.nome);
let nomesRemove = estavamDentro.filter(el => todos.indexOf(el) == -1);
//var nomesRemove = Array.from(new Set(mutationsList.filter(el => el.removedNodes.length).map(el => el.removedNodes[0].innerText)));
// if (nomesRemove.length > 0) console.log(mutationsList);
nomesAdd.forEach(nome => personIn(nome));
nomesRemove.forEach(nome => personOut(nome));
};
var observer3 = new MutationObserver(callback3);
// Start observing the target node for configured mutations
observer3.observe(targetNode3, config3);
}
function stopMonitor() {
if (pessoas.pessoas.length == 0) return;
var res = pessoas.getAsCSV();
var a = document.createElement("a");
a.href = "data:text/csv;charset=utf-8,%EF%BB%BF" + res;
a.download = "people_" + (new Date()).toLocaleString().replaceAll("/", "-").replace(/ (\d+):(\d+):(\d+)/g, "_$1h$2m$3s") + ".csv";
a.click();
return true;
}
var myDiv = document.createElement("div");
function pauseMonitor() {
myDiv.innerText = "PLAY";
clearTimeout(lastTimeout);
}
myDiv.style.position = "absolute";
myDiv.innerText = "PLAY";
myDiv.style.top = "5px";
myDiv.style.left = "5px";
myDiv.style.zIndex = 9999999;
myDiv.style.border = "2pt black solid";
myDiv.style.backgroundColor = "black";
myDiv.style.color = "white";
myDiv.style.fontWeight = 900;
myDiv.style.opacity = 0.5;
myDiv.style.cursor = "pointer";
myDiv.onclick = function() {
if (myDiv.innerText == "PLAY") {
window.onbeforeunload = function(evt) {
stopMonitor();
}
document.querySelector("[aria-label='Sair da chamada']").onmousedown = function(e) {
stopMonitor();
return true;
}
myDiv.innerText = "PAUSE";
startMonitor();
} else {
pauseMonitor();
}
}
document.querySelector("body").append(myDiv);
document.addEventListener("DOMContentLoaded", function(event) {
console.log("Start observing");
startMonitor();
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment