Skip to content

Instantly share code, notes, and snippets.

@mingtsay
Forked from 71/boorkmarklet.md
Last active June 7, 2022 06:40
Show Gist options
  • Save mingtsay/08af750488044480205d1b06ba21f862 to your computer and use it in GitHub Desktop.
Save mingtsay/08af750488044480205d1b06ba21f862 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 comma(,) .

javascript:((n=2e3)=>{try{function h(a,b=0){if(b>7||"object"!=typeof a||null===a||a===window)return;let c=Object.getOwnPropertyDescriptors(a);for(let d in c){if(d.startsWith('["spaces/'))return Object.values(a);let e=h(c[d].value,b+1);if(void 0!==e)return e}}let i=Object.entries(window).find(a=>a[0].startsWith("closure_lm_"))[1],e=h(i),a=[];function j(b){for(let c in b){let a=b[c];if("object"==typeof a&&null!==a&&"string"==typeof a[1])return a[1]}}for(let c=0;c<e.length;c++){let f=j(e[c]);-1===a.indexOf(f)&&a.push(f)}if(0===a.length)throw new Error("Could not find any name.");a.sort((a,b)=>a.localeCompare(b));let g=a.slice(1).reduce((a,b)=>(a[0].length+b.length+1>=n?a.unshift(b):a[0]+=", "+b,a),[a[0]]).reverse();for(let b=0,{length:d}=g;b<d;b++){let k=1===d?"":" ("+(b+1)+"/"+d+")",l="Please find the list of participants below"+k+".";if(null===prompt(l,g[b]))break}}catch(m){alert("Unexpected error when running the script: "+m)}})()
((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] += ", " + 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