Skip to content

Instantly share code, notes, and snippets.

@dobesv
Forked from 71/boorkmarklet.md
Last active November 8, 2021 19:44
Show Gist options
  • Save dobesv/4b44c9ca6f04910a3d1da41267a16f87 to your computer and use it in GitHub Desktop.
Save dobesv/4b44c9ca6f04910a3d1da41267a16f87 to your computer and use it in GitHub Desktop.
Lists all participants in a Google Meet meeting.

The following bookmarket shows a popup with the name of the participants separated by newlines.

javascript:-function(maxStrLength = 2000) { try { function findParticipants(current, depth = 0) { if (depth > 7) return; if (typeof current !== "object" || current === null || current === window) return; const descriptors = Object.getOwnPropertyDescriptors(current); for (const prop in descriptors) { if (prop.startsWith('["spaces/')) return Object.values(current); const item = findParticipants(descriptors[prop].value, depth + 1); if (item !== undefined) return item; } } const rootState = Object.entries(window).find(x => x[0].startsWith("closure_lm_"))[1], participants = findParticipants(rootState), names = []; function findName(obj) { for (const prop in obj) { const value = obj[prop]; if (typeof value === "object" && value !== null && typeof value[1] === "string") return value[1]; } } for (let i = 0; i < participants.length; i++) { const name = findName(participants[i]); if (names.indexOf(name) === -1) names.push(name); } if (names.length === 0) throw new Error("Could not find any name."); names.sort((a, b) => a.localeCompare(b)); const groups = names.slice(1).reduce((groups, name) => { if (groups[0].length + name.length + 1 >= maxStrLength) { groups.unshift(name); } else { groups[0] += "\n" + name; } return groups; }, [names[0]]).reverse(); for (let i = 0, {length} = groups; i < length; i++) { const suffix = length === 1 ? "" : " (" + (i + 1) + "/" + length + ")", message = "Please find the list of participants below" + suffix + "."; if (prompt(message, groups[i]) === null) break; } } catch (e) { alert("Unexpected error when running the script: " + e); }}()

This code can be generated by evaluating:

`javascript:${await fetch("https://gist.githubusercontent.com/dobesv/4b44c9ca6f04910a3d1da41267a16f87/raw/4169035c0777f74b633795622c93006e3352236e/google-meet-participants.js").then(x => x.text())}`.replace(/\n|\/\*[\s\S]+?\*\//g, '').replace(/ +/g, ' ')
-function(maxStrLength = 2000) {
try {
/* 1. Find the objects corresponding to the participants by recursively
walking the state of the webapp. */
function findParticipants(current, depth = 0) {
if (depth > 7)
return; /* We can find it at a lower depth. */
if (typeof current !== "object" || current === null || current === window)
return; /* We're only interested in objects. */
/* Iterate over descriptors to make sure we don't access computed properties. */
const descriptors = Object.getOwnPropertyDescriptors(current);
for (const prop in descriptors) {
if (prop.startsWith('["spaces/'))
/* We're looking for the object whose keys start with '["spaces/'. */
return Object.values(current);
const item = findParticipants(descriptors[prop].value, depth + 1);
if (item !== undefined)
return item;
}
}
const rootState = Object.entries(window).find(x => x[0].startsWith("closure_lm_"))[1],
participants = findParticipants(rootState),
names = [];
/* 2. For each object, determine the participant's name. */
function findName(obj) {
/* The property names are non-deterministic and may change at any time, but the
participant's name is always at 'participant.Aa[1]', where 'Aa' can be an
arbitrary string.
Walk the object and hope that the first match corresponds to the string. */
for (const prop in obj) {
const value = obj[prop];
if (typeof value === "object" && value !== null && typeof value[1] === "string")
return value[1];
}
}
for (let i = 0; i < participants.length; i++) {
const name = findName(participants[i]);
if (names.indexOf(name) === -1)
/* 3. Remove duplicates. */
names.push(name);
}
if (names.length === 0)
throw new Error("Could not find any name.");
/* 4. Sort the names lexicographically. */
names.forEach((elt, i) => { var j = Math.round(Math.random() * (names.length - 1)); [names[i], names[j]] = [names[j], names[i]]; });
/* Truncate to 15 names */
names.length = 15;
var ta = document.querySelector(%27textarea[name="chatTextInput"]%27);
var txt = names.map((e, n) => `${n + 1}. ${e}`).join('');
console.log(txt);
ta.value = txt;
ta.dispatchEvent(new KeyboardEvent('keydown'));
alert('Send attendee list to the chat input');
} catch (e) {
alert("Unexpected error when running the script: " + e);
}
}()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment