Last active
May 8, 2023 06:34
-
-
Save fabledowl/8c8db5858e096866c42dfa114034f0f2 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
// ==UserScript== | |
// @name Telegram - Get Users | |
// @author [email protected] | |
// @desription Greasemonkey script to extract users from Telegram groups | |
// @namespace https://fabledowlblog.wordpress.com/ | |
// @include https://web.telegram.org/* | |
// @downloadUrl https://gist.github.com/fabledowl/8c8db5858e096866c42dfa114034f0f2/raw/getUsers.user.js | |
// @updateUrl https://gist.github.com/fabledowl/8c8db5858e096866c42dfa114034f0f2/raw/getUsers.user.js | |
// @version 0.4 | |
// @grant none | |
// @run-at document-start | |
// ==/UserScript== | |
(function () { | |
'use strict'; | |
var runAngular = function () { | |
try { | |
if (angular.element(document.body).injector().get('$rootScope')) { | |
initialize(); | |
return; | |
} | |
} catch (e) { | |
window.setTimeout(runAngular, 1); | |
} | |
}; | |
runAngular(); | |
function initialize() { | |
var rootScope = angular.element(document.body).injector().get('$rootScope'); | |
var mtpApiManager = angular.element(document).injector().get('MtpApiManager'); | |
var appChatsManager = angular.element(document).injector().get('AppChatsManager'); | |
var users = [ | |
]; | |
var jsonData = [ | |
]; | |
var id; | |
var channelName; | |
var userCount; | |
var offset = 0; | |
function getUsers() { | |
id = Math.abs(rootScope.selectedPeerID); | |
if (appChatsManager.isChannel(id)) { | |
getChannelFull(id).then(function(data) { | |
if (data.full_chat.pFlags.can_view_participants) { | |
getParticipants(); | |
} else { | |
reset(); | |
} | |
}); | |
} else { | |
getChatFull(id).then(function(data) { | |
parseResults(data); | |
displayData(); | |
}); | |
} | |
} | |
function reset() { | |
$('#spinner').hide(); | |
$('#getUsers').prop('disabled', false); | |
} | |
function getParticipants() { | |
if (offset > userCount) { | |
return; | |
} | |
mtpApiManager.invokeApi('channels.getParticipants', { | |
channel: appChatsManager.getChannelInput(id), | |
filter: { | |
_: 'channelParticipantsRecent' | |
}, | |
limit: 200, | |
offset: offset | |
}).then(function (data) { | |
parseResults(data); | |
offset += 200; | |
if (offset > userCount) { | |
displayData(); | |
return; | |
} | |
}).then(delayPromise(randomIntBetween(2000, 5000))).then(function () { | |
getParticipants(); | |
}).catch (function (e) { | |
reset(); | |
}); | |
} // Delay promise function | |
function getChannelFull(id) { | |
return mtpApiManager.invokeApi("channels.getFullChannel", { | |
channel: appChatsManager.getChannelInput(id) | |
}); | |
} | |
function getChatFull(id) { | |
return mtpApiManager.invokeApi("messages.getFullChat", { | |
chat_id: appChatsManager.getChatInput(id) | |
}); | |
} | |
function delayPromise(delay) { | |
return function (data) { | |
return new Promise(function (resolve, reject) { | |
setTimeout(function () { | |
resolve(data); | |
}, delay); | |
}); | |
}; | |
} | |
function randomIntBetween(min, max) { | |
return Math.floor(Math.random() * (max - min + 1) + min); | |
} | |
function addStyle(css) { | |
$('head').append($('<style>').text(css)); | |
} | |
function addUserRow(user) { | |
$('#users').append($('<tr><td><a class="view-user" href="https://web.telegram.org/#/im?p=u' + user.id + '_' + user.access_hash + '">' + user.id + '</a></td><td>' + user.full_name + '</td><td>' + user.username + '</td><td>' + user.lastOnline + '</td><td>' + user.type + '</td>')); | |
} | |
function downloadFile(users, channelName, channelID) { | |
var d = new Date(); | |
var day = d.getUTCDate(); | |
var month = d.getUTCMonth() + 1; | |
var year = d.getUTCFullYear(); | |
var filename = channelID + '_' + day + '-' + month + '-' + year; | |
var fileContent = 'Channel Name:\t' + channelName + '\r\n'; | |
fileContent += 'ID\tFirst Name\tLast Name\tUsername\tAccount Type\tLast Online\tDate Joined\tInvited By\tAccess Hash\r\n'; | |
for (var l = 0; l < users.length; l++) { | |
var user = users[l]; | |
var id = user.id; | |
var firstName = (user.first_name ? user.first_name : '').replace(/\n/g, '').replace(/\r/g, ''); | |
var lastName = (user.last_name ? user.last_name : '').replace(/\n/g, '').replace(/\r/g, ''); | |
var username = (user.username ? user.username : '').replace(/\n/g, '').replace(/\r/g, ''); | |
var dataString = id + '\t' + firstName + '\t' + lastName + '\t' + username + '\t' + user.type + '\t' + user.lastOnline + '\t' + user.dateJoined + '\t' + user.inviter_id + '\t' + user.access_hash; | |
fileContent += (l < users.length ? dataString + '\r\n' : dataString); | |
} | |
var link = document.createElement('a'); | |
link.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileContent)); | |
link.setAttribute('download', filename + '.txt'); | |
$('body').append(link); | |
link.click(); | |
link.remove(); | |
} | |
function parseResults(data) { | |
var participants; | |
if (data.participants) { | |
participants = data.participants.map(function (participant) { | |
var user = data.users[getUserById(participant.user_id, data.users)]; | |
Object.assign(user, participant); | |
return user; | |
}); | |
} else { | |
participants = data.users; | |
} | |
for (var j = 0; j < participants.length; j++) { | |
participants[j].dateJoined = 'N/A'; | |
if (participants[j].date) { | |
participants[j].dateJoined = new Date(participants[j].date * 1000).toUTCString(); | |
} | |
participants[j].full_name = ''; | |
if (participants[j].first_name) { | |
participants[j].full_name += participants[j].first_name; | |
} | |
if (participants[j].last_name) { | |
participants[j].full_name += ' ' + participants[j].last_name; | |
} | |
participants[j].username = (participants[j].username ? participants[j].username : ''); | |
if (participants[j]._.includes('Creator')) { | |
participants[j].type = 'Creator'; | |
} else if (participants[j]._.includes('Editor')) { | |
participants[j].type = 'Admin'; | |
} else { | |
participants[j].type = 'User'; | |
} | |
if (participants[j].status) { | |
if (participants[j].status._ == 'userStatusOffline') { | |
participants[j].lastOnline = new Date(participants[j].status.was_online * 1000).toUTCString(); | |
} else if (participants[j].status._ == 'userStatusOnline') { | |
participants[j].lastOnline = new Date().toUTCString(); | |
} else if (participants[j].status._ == 'userStatusRecently') { | |
participants[j].lastOnline = 'Recently'; | |
} else if (participants[j].status._ == 'userStatusLastWeek') { | |
participants[j].lastOnline = 'Last Week'; | |
} else if (participants[j].status._ == 'userStatusLastMonth') { | |
participants[j].lastOnline = 'Last Month'; | |
} | |
} else { | |
participants[j].lastOnline = 'Unknown'; | |
} | |
participants[j].inviter_id = (participants[j].inviter_id ? participants[j].inviter_id : ''); | |
addUserRow(participants[j]); | |
} | |
Array.prototype.push.apply(users, participants); | |
function getUserById(id, elements) { | |
var index = elements.filter(function (element) { | |
return element.id === id; | |
}) [0]; | |
return elements.indexOf(index); | |
} | |
} | |
function displayData() { | |
$('#usercount').text(users.length + ' members'); | |
$('#exportUsers').unbind('click').click(function () { | |
downloadFile(users, channelName, id); | |
}); | |
$('#spinner').hide(); | |
$('.custom-panel').show(); | |
} | |
function createUI() { | |
// Create UI - Modal/Button/Spinner | |
addStyle('.spinner {position: absolute; display:none; overflow: auto; top: 50%; left: 50%; width: 150px; height: 150px; margin: -75px 0 0 -75px; z-index:250; background-color: #FFFFFF; border: 1px solid #000000;}' + | |
'.spinner img {width: 60px; height: 60px; margin-top: 45px; margin-left: 45px;}' + | |
'.custom-panel {position: absolute; display: none; top: 50%; left: 50%; width: 700px; height: 400px; margin: -200px 0 0 -350px; z-index:240;}' + | |
'.custom-panel-heading {background-color:rgb(86, 130, 163); color: #FFFFFF; height:48px; padding: 15px; font-size: 13px;}' + | |
'.custom-panel-body {background-color: #FFFFFF; height:352px; border-left: 1px solid rgb(233, 235, 237); border-right: 1px solid rgb(233, 235, 237); border-bottom: 1px solid rgb(233, 235, 237); overflow: auto;}' + | |
'.close-btn {background-color:rgb(86, 130, 163); border: 1px solid rgb(233, 235, 237); float: right; margin-left: 5px;}' + | |
'.profile_photo {border-radius: 50%; height:18px; width: 18px;}' + | |
'.get-users-btn {position: absolute; bottom: 5px; left: 5px; background-color:rgb(86, 130, 163); border: 1px solid rgb(233, 235, 237); padding: 10px; color: #FFFFFF; font-weight: bold;}' | |
); | |
$('body').append('<div id="spinner" class="spinner"><img src="data:image/gif;base64,R0lGODlhLQAtAPMPANTU1O3t7fJoRfv7++9OJdvb2+Lf3/SBZPixn/7v6/m+r/b29ubm5u0wAM3Nzf///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgAPACwAAAAALQAtAAAE//DJSesIBjg3WxMHklRkaUpBsa2c5L0fcs5VoLFrB7+ETJsDFY6l270Eox8lMBwWjS+fktnEPaEehVJiqBJd2NdhOul6ARNCuDFGnZiG8tAQGFQSioOx/egGSgsrcVwrDHYzCXoefGYOCyRCG4N9AI9bBgSMLAU1c1s0jSt/Ezc4k58VoStoKFWsqBWlOKOROJawFIFNnANVDLglDFUXw8AkvU0YTafGcnOyos0kVDjQK4fSE8heLK/ZpE3f4uPk5RVN3uLWXuXb1cnk1N2qkuT0DnTF3+4sdb7iwprYqcUCmzF+Kzg9kNct2zoHox6sY4brnjeG+MTRiyih1qQMBltpDADwcRMJXRkJbTAkMmDKPituLXmpiiTHCcpMybm5xJkrcF4m8Sxxz4oEbvW2YAx3FCnET0uNPnA6dMYCglK5FZCJykaVCa6qdsUKFkcBscAuZNhQ1mbIGREAACH5BAUKAA8ALBgAAAAVABUAAARg0Lliwng46y37DFuIeR4AihlJFheqqmf4wuLsGShgOzimhIOAQdV7HBoI1IDRKR4bjQTqsQA4oVDBdPPEIreYrpcAfhC83t/WgMZqwWLvotyGJuH1Q1lRf28TdQ1lZnURACH5BAUKAA8ALCIABwALAB8AAARe8EkZppXG1fuyc8PlfYU1fhqGroAErGu1wGj5MPQXPnna5QZKzjboTV40jnLJ5BAa0GhDkpBKJQorVCA5aBuHR/WLeHi/Cca3wX1+FeYvYXKWlulS7qWeUHrvSnAWEQAh+QQFCgAPACwYABgAFQAVAAAEZ/DJSSdwOLvK39BaVwUgVoiUUToGKn1r4D7M6gzuYp/uFc+qEmAmCWpkHQPhMDE6eJXEoUFlFjO4SUIxpXqtDxVSQvCav5Ox5MxugCtttqITNyNE9YYggYoT7i5sAnNEVAIHCHxEEhEAIfkEBQoADwAsBwAiAB8ACwAABFrwSXmImTjPBa6mTXh82cA4qJcdYdscSlIGBmo7KujuxATcQNyEtStOgsGLosg8IoGBB4K5cz5RUUlCQA1ZkYWBBkGgfm+ALEnBrUqCBTVpkkAc2s6CISD+RAAAIfkEBQoADwAsAAAYABUAFQAABF+wydnIuzhjSpP+j8BJCqgdY3OYGZI2Hvsk7yqHr3Err3UTKZvMxRHeRBOhAbBg0SRKh5TBckWlWENg8CldDNgwFmACi8+gwHltUq/DrEHhLb0FAO/bJWCG6y8DfHMOEQAh+QQFCgAPACwAAAcACwAfAAAEYPBJqaaVqJ0rU/vbJXyglZGlRKDkprAk8YxwY3j1dsLSkUs0VuVRayQkNRlnyWxeHNCoAzCRSgeSghUakBi2DoMkAHZgB2VGtrx4kMHUBwAsdm/r6yhegobuJ2R/Fl0WEQAh+QQFCgAPACwAAAAAFQAVAAAEYvDJSWtCR7RWu1TaJnoUQogoRyZhOnqI63qKPHuHjVbBlOsESsBh8LkOigRl4GgWJb/GgVRoOn2EZ2dovZIogK5VS+KKHYCvpHp2LNTMNkP9MIvpD0ObTG336G0OA3htaXgRADs="></div>'); | |
$('body').append('<button class="get-users-btn" id="getUsers">Get Users</button>'); | |
$('body').append('<div class="custom-panel"><div class="custom-panel-heading">' + | |
'<span style="font-weight: bold;">Channel Participants</span> <span id="usercount" style="color: rgb(185, 207, 227);"></span><button class="close-btn" id="closeUsers">Close</button><button class="close-btn" id="exportUsers">Export</button></div>' + | |
'<div class="custom-panel-body"><table id="users" class="table table-striped"><tr><th>ID</th><th>Name</th><th>Username</th><th>Last Online</th><th>Type</th></tr></table></div></div>'); | |
$('#closeUsers').click(function () { | |
$('#users').find('tr:gt(0)').remove(); | |
$('.custom-panel').hide(); | |
$('#getUsers').prop('disabled', false); | |
}); | |
$('#getUsers').click(function () { | |
if (!rootScope.selectedPeerID || rootScope.selectedPeerID > 0) { | |
return; | |
} | |
users = [ | |
]; | |
offset = 0; | |
userCount = parseInt($('span.tg_head_peer_status span').text().split(' ') [0]); | |
channelName = $('span.tg_head_peer_title').text(); | |
if (userCount === '' || channelName === '') { | |
return; | |
} | |
$('#spinner').show(); | |
$('#getUsers').prop('disabled', true); | |
getUsers(); | |
}); | |
} | |
createUI(); | |
} | |
}) (); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment