Skip to content

Instantly share code, notes, and snippets.

@caioluders
Created March 10, 2026 20:29
Show Gist options
  • Select an option

  • Save caioluders/8160a01107a2f730d696da0081a8808b to your computer and use it in GitHub Desktop.

Select an option

Save caioluders/8160a01107a2f730d696da0081a8808b to your computer and use it in GitHub Desktop.
telegram web k
(async () => {
const DELAY_PROFILE = 800;
const DELAY_BACK = 600;
const DELAY_SEND = 1000;
const MESSAGE_TEMPLATE = (username) => `Hey ${username}, check this out!`; // ← customize your message here
const sleep = ms => new Promise(r => setTimeout(r, ms));
const rightSidebar = document.querySelector('.sidebar-right');
const container = rightSidebar?.querySelector('.search-super-content-members');
if (!container) {
console.log('❌ Open group info β†’ Members in the right sidebar first.');
return;
}
// Deduplicate members
const seen = new Set();
const memberRows = [];
container.querySelectorAll('[data-peer-id]').forEach(el => {
const id = Number(el.dataset.peerId);
if (id > 0 && !seen.has(id)) {
seen.add(id);
memberRows.push(el);
}
});
console.log(`πŸ‘₯ Found ${memberRows.length} unique members.`);
// Step 1: Resolve from IndexedDB
const resolved = new Map();
const dbNames = ['tweb-account-1','tweb-account-2','tweb-account-3','tweb-account-4'];
for (const dbName of dbNames) {
try {
const db = await new Promise((res, rej) => {
const req = indexedDB.open(dbName);
req.onsuccess = () => res(req.result);
req.onerror = () => rej(req.error);
});
if (![...db.objectStoreNames].includes('users')) { db.close(); continue; }
const tx = db.transaction('users', 'readonly');
const store = tx.objectStore('users');
const users = await new Promise(r => { const req = store.getAll(); req.onsuccess = () => r(req.result); });
db.close();
for (const u of users) {
const id = u.id || u.userId;
if (!seen.has(id)) continue;
const uname = u.username || u.usernames?.[0]?.username;
if (uname) resolved.set(id, uname);
}
if (resolved.size > 0) { console.log(`πŸ“¦ Cache: ${resolved.size} usernames`); break; }
} catch {}
}
// Step 2: Click through uncached
const uncachedRows = memberRows.filter(r => !resolved.has(Number(r.dataset.peerId)));
const noUsername = [];
if (uncachedRows.length > 0) {
console.log(`πŸ” ${uncachedRows.length} uncached. Clicking through...`);
for (let i = 0; i < uncachedRows.length; i++) {
const row = uncachedRows[i];
const peerId = Number(row.dataset.peerId);
row.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));
row.dispatchEvent(new MouseEvent('mouseup', { bubbles: true }));
row.dispatchEvent(new MouseEvent('click', { bubbles: true }));
await sleep(DELAY_PROFILE);
let username = null;
for (const r of rightSidebar.querySelectorAll('.row')) {
const sub = r.querySelector('.row-subtitle');
const title = r.querySelector('.row-title');
if (sub && /^Username$/i.test(sub.textContent.trim()) && title) {
username = title.textContent.trim();
break;
}
}
const displayName = rightSidebar.querySelector('.profile-name')?.textContent?.trim() || `id:${peerId}`;
if (username) {
resolved.set(peerId, username);
console.log(` βœ… ${i + 1}/${uncachedRows.length} β€” ${displayName} β†’ @${username}`);
} else {
noUsername.push(displayName);
console.log(` ❌ ${i + 1}/${uncachedRows.length} β€” ${displayName} β†’ no username`);
}
const backBtn = rightSidebar.querySelector('.sidebar-back-button');
if (backBtn) {
backBtn.dispatchEvent(new MouseEvent('mousedown', { bubbles: true }));
backBtn.dispatchEvent(new MouseEvent('mouseup', { bubbles: true }));
backBtn.dispatchEvent(new MouseEvent('click', { bubbles: true }));
await sleep(DELAY_BACK);
}
}
}
const usernames = [...new Set(resolved.values())].map(u => '@' + u);
console.log(`\nβœ… Collected ${usernames.length} usernames.`);
if (noUsername.length) console.log(`❌ ${noUsername.length} without username: ${noUsername.join(', ')}`);
// Step 3: Send messages
if (usernames.length === 0) { console.log('No usernames to message.'); return; }
console.log(`\nπŸ“¨ Sending ${usernames.length} messages (${DELAY_SEND}ms apart)...`);
console.log(` Message template: "${MESSAGE_TEMPLATE('@example')}"`);
console.log(' ⚠️ Type STOP in console to abort: window.__STOP_SENDING = true');
window.__STOP_SENDING = false;
const input = document.querySelector('.input-message-input[contenteditable="true"]');
const sendBtn = document.querySelector('.btn-send, .send-btn, .btn-icon.send');
if (!input) { console.log('❌ Chat input not found. Make sure the group chat is open.'); return; }
let sent = 0;
for (const username of usernames) {
if (window.__STOP_SENDING) { console.log('πŸ›‘ Stopped by user.'); break; }
const msg = MESSAGE_TEMPLATE(username);
// Set message in input
input.focus();
input.innerHTML = '';
document.execCommand('insertText', false, msg);
input.dispatchEvent(new Event('input', { bubbles: true }));
await sleep(300);
// Press Enter to send
input.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', code: 'Enter', keyCode: 13, bubbles: true }));
await sleep(DELAY_SEND);
sent++;
console.log(` πŸ“¨ ${sent}/${usernames.length} β€” sent to ${username}`);
}
console.log(`\nβœ… Done! Sent ${sent}/${usernames.length} messages.`);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment