Skip to content

Instantly share code, notes, and snippets.

@waterrmalann
Last active June 17, 2024 14:14
Show Gist options
  • Save waterrmalann/87cbc9c32135a4e4cd65f4dc9c7e4906 to your computer and use it in GitHub Desktop.
Save waterrmalann/87cbc9c32135a4e4cd65f4dc9c7e4906 to your computer and use it in GitHub Desktop.
A script to extract all numbers from a Whatsapp community which you're an admin of.
// A script to extract numbers of all members of a Whatsapp Community
// The client should be a "Community Admin" before running this script.
const CONTAINER_IDENTIFIER = '.xyw6214.x78zum5.x1r8uery';
const NUMBER_IDENTIFIER = '.x15g3fpr span.x1iyjqo2';
const SIDE_NUMBER_IDENTIFIER = 'span._ao3e';
const COMMUNITY_NAME = 'span.x1lliihq.xh8yej3';
const DEF_DELAY = 200;
function grabNormalNumbers() {
const normalNumbers = [];
const elements = document.querySelectorAll(NUMBER_IDENTIFIER);
for (element of elements) {
if (element.innerHTML.includes('+')) {
element.style.border = "2px solid red"
normalNumbers.push(element.innerHTML)
}
}
return normalNumbers;
}
function grabOnlyNumbers() {
const onlyNumbers = [];
const allElements = document.querySelectorAll(SIDE_NUMBER_IDENTIFIER);
for (let element of allElements) {
if (element.className === "_ao3e" && element.innerHTML.includes('+')) {
element.style.border = "2px solid red"
onlyNumbers.push(element.innerHTML);
}
}
return onlyNumbers;
}
function slugify(str) {
const processed = str.replace(/[\W_]+/g, " ");
return processed.trim().replaceAll(' ', '-');
}
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms || DEF_DELAY));
}
async function automate() {
const numbers = new Set();
let counter = 0;
let oldSize = numbers.size;
function grabNumbers() {
const currentNumbers = grabNormalNumbers().concat(grabOnlyNumbers())
for (let number of currentNumbers) {
numbers.add(number);
}
const diff = numbers.size - oldSize;
if (diff) {
console.log(`%c${diff} numbers extracted...`, 'color:gray;font-style:italic');
}
}
const containers = document.querySelectorAll(CONTAINER_IDENTIFIER);
const container = containers[0];
if (!container || containers.length !== 2) {
return alert("You do not have the members tab open.");
}
container.style.border = "4px solid green";
let title = document.querySelector(COMMUNITY_NAME).innerText;
if (!title) {
title = prompt("Could not retrieve community name. Please enter manually:")
}
const name = slugify(title);
console.log("%cWhatsapp Community Extractor", "color:#25d366;font-size:2rem;font-weight:bold")
console.log("%cextracting...", "color:yellow;font-size:2rem")
console.log(`%c${title}`, 'color: orange;font-size:1.5rem');
const containerHeight = container.scrollHeight;
let scroller = 0;
container.scrollTo(0, 0);
while (scroller < containerHeight) {
grabNumbers();
scroller += 200;
await sleep(200);
container.scrollTo(0, scroller);
}
console.log("%csuccess...", "color:yellow;font-size:2rem")
const proceed = confirm(`${numbers.size} numbers extracted. Download?`);
const asArray = Array.from(numbers);
if (proceed) {
const blob = new Blob([asArray.join('\n')], {
type: "text/csv"
});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = name ? `${name}.csv` : "extraction.csv";
a.click();
}
return asArray;
}
const TITLE_BAR = '._amie';
const COMMUNITY_TAB = 'button[title="Community"]'
const MEMBERS_BTN = 'div[role="button"]._alzb'
function onElementAvailable(selector, callback) {
const observer = new MutationObserver(mutations => {
const element = document.querySelector(selector)
if (element) {
observer.disconnect();
callback(element);
}
});
observer.observe(document.body, {
childList: true,
subtree: true
});
}
function viewMembersTab() {
return new Promise((resolve, reject) => {
const canSeeMembers = document.querySelector(MEMBERS_BTN);
if (canSeeMembers && !canSeeMembers.innerText.includes('Report')) {
canSeeMembers.click();
resolve();
} else if (canSeeMembers) {
document.querySelector(COMMUNITY_TAB).click();
onElementAvailable(MEMBERS_BTN, (membersBtn) => {
membersBtn.click();
resolve();
})
} else {
document.querySelector(TITLE_BAR).click();
onElementAvailable(COMMUNITY_TAB, (communityBtn) => {
communityBtn.click();
onElementAvailable(MEMBERS_BTN, (membersBtn) => {
membersBtn.click();
resolve();
})
});
}
})
};
// viewMembersTab().then(automate)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment