Skip to content

Instantly share code, notes, and snippets.

@pshanoop
Forked from 71/boorkmarklet.md
Created October 2, 2022 16:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pshanoop/7dd1a8cb29b56f5d06bb26a45372dc43 to your computer and use it in GitHub Desktop.
Save pshanoop/7dd1a8cb29b56f5d06bb26a45372dc43 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/71/7296ec9d44af7d0f1fb36b053bbe2219/raw/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.sort((a, b) => a.localeCompare(b));
/* 5. Chrome limits to 2K characters the number of characters in the string given
to "prompt", so we split the output in several groups if needed. */
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();
/* 6. Finally, output all groups using "prompt". */
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; /* User pressed "Cancel", so we stop the loop. */
}
} 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