Created
March 10, 2024 14:38
-
-
Save Kenya-West/0e489eb750bbdd240d372032c8b7d595 to your computer and use it in GitHub Desktop.
Collect channel usernames in Telegram Web (A)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Because there is no API method nor programmatic access to Telegram channel usernames, | |
// this script was created. It is a workaround to collect usernames from the chat folder. | |
// It collects names and usernames and saves them to an array. | |
// 1. Open https://web.telegram.org/a/; | |
// 2. Open the chat filder. Main one is not supported! And there should be no "Archived chats" chat; | |
// 3. Open the browser console; | |
// 4. Paste the script and run it; | |
// 5. Wait for the script to finish. It should take a few minutes. | |
// Current bugs: | |
// - The script does not always collect usernames when chat is a forum. | |
let namesList = []; | |
let namesListDelta = 1; | |
let scrollingCounter = 0; | |
const scrollingCounterLimit = 5; | |
async function scrollAndCollectNames() { | |
while(namesListDelta > 0 || scrollingCounter < scrollingCounterLimit) { | |
console.log('Starting a new iteration...'); | |
let delta = namesList.length; | |
let elems = Array.from(document.querySelectorAll("#LeftColumn.Transition .chat-list.Transition_slide-active .ListItem")); | |
// elems = elems.slice(0,3); // for testing purposes | |
console.log(`Found ${elems.length} elements...`); | |
await sleep(200); | |
for await (const elem of elems) { | |
console.log(`Processing elem with name: ${elem.querySelector(".info .info-row .title")?.innerText}...`); | |
const name = elem.querySelector(".info .info-row .title")?.innerText; | |
// setting username here is valid, yet it is costly in terms of performance and time | |
// so better to do it after filtering names so the loop will not start over again | |
// also worth noting that the username is not always available | |
// despite teh fact name is not unique, it is still a good enough identifier | |
// const username = await getUsername(elem); | |
if (!namesList.find(item => item.name === name)) { | |
namesList.push({ | |
name, | |
username: await getUsername(elem) | |
}); | |
} | |
} | |
namesListDelta = namesList.length - delta; | |
scrollingCounter++; | |
console.log(`Scrolling iteration ${scrollingCounter} completed. Names list delta: ${namesListDelta}`); | |
// two scroll methods: prefer 1st one | |
elems[elems.length-1]?.scrollIntoView(); | |
// const chatList = document.querySelector(".chat-list.custom-scroll.Transition_slide.Transition_slide-active"); | |
// chatList.scrollTo(0,9999); | |
await new Promise(resolve => setTimeout(resolve, 500)); | |
} | |
} | |
async function getUsername(elem) { | |
async function simulateMouseClick(element){ | |
console.log('Simulating mouse click...'); | |
const mouseClickEvents = ['mousedown', 'click', 'mouseup']; | |
mouseClickEvents.forEach(mouseEventType => | |
element.dispatchEvent( | |
new MouseEvent(mouseEventType, { | |
view: window, | |
bubbles: true, | |
cancelable: true, | |
buttons: 1 | |
}) | |
) | |
); | |
} | |
async function getUserNameText() { | |
console.log('Getting username...'); | |
const rightPane = document.querySelector("#RightColumn"); | |
const username = rightPane?.querySelector(".ChatExtra .ListItem:nth-child(2) .multiline-item .title")?.innerText || '<no username>'; | |
return username; | |
} | |
console.log('Getting username for an element...', elem); | |
await simulateMouseClick(elem.querySelector(".ListItem-button")); | |
await sleep(2000); // wait for the click event to be processed | |
await simulateMouseClick(document.querySelector("#MiddleColumn .MiddleHeader .Transition .chat-info-wrapper")); | |
await sleep(2000); // wait for the click event to be processed | |
return await getUserNameText(); | |
} | |
await scrollAndCollectNames().then(() => { | |
console.log('Finished collecting names.'); | |
console.dir(namesList); | |
}).catch((e) => { | |
console.log('Finished collecting names.'); | |
console.dir(namesList); | |
}); | |
/** | |
* | |
* @param {number} ms | |
* @returns Promise | |
*/ | |
function sleep(ms) { | |
return new Promise((r) => setTimeout(r, ms)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment