Здравствуйте! Если вы когда-либо пытались извлечь данные пользователей из крупных телеграм-групп и каналов, вы наверняка знаете о технических сложностях, которые могут возникнуть. В рамках нашего проекта — платформы для спикеров и коучей — мы столкнулись с необходимостью эффективно продвигать наши курсы, используя рекламу в других группах и каналах. Однако далеко не каждый готов предоставить доступ к своему каналу или группе, особенно если предлагаемые темы курсов перекликаются с их собственными.

Для решения этой задачи наша маркетинговая команда разработала трехуровневую партнёрскую программу. Суть программы заключается в том, что владельцы групп, согласные на сотрудничество, получают уникальный идентификатор в нашей системе. Под этим ID регистрируются все новые пользователи, которые, в случае покупки курсов, генерируют вознаграждение для владельца группы.

Эта инициатива казалась нам многообещающей, однако в процессе реализации мы столкнулись с серьёзным ограничением. При попытке загрузить список пользователей из группы на 13,000 человек, система смогла обработать только 10,000. Это ограничение API Telegram значительно усложнило выполнение задуманного плана, требуя от нас дополнительных технических решений.

Решение

В API Telegram channels->getParticipants нашелся параметр поиска 'filter' => ['_' => 'channelParticipantsSearch', 'q' => "Перебираем все символы которые могут быть в логине"]

Пример решения на PHP используем библиотеку MadelineProto

<? 
//.....................................
//подключаем библиотеки, считываем данные из базы

$telegram_group_id = $group['telegram_group_id'];
$groupInfo = $MadelineProto->getFullInfo($telegram_group_id);
$participantCount = $groupInfo['full']['participants_count'] ?? 0;
echo "В группе $participantCount пользователей!<br>";
$allParticipants = [];
$limit = 200;

if ($participantCount > 10000) {
$nextchar = $group['nextchar'];
if ($nextchar === '00') {
    echo "Все символы были обработаны.<br>";
    echo '</body>';
    echo '</html>';
    exit;
}

if ($nextchar === '' || is_null($nextchar)) {
    $nextchar = 'a';
}

$alphabet = array_merge(range('a', 'z'), range('0', '9')); //можно добавить еще символов
$currentCharIndex = array_search($nextchar, $alphabet);
if ($currentCharIndex === false) {
    die("Неверное значение nextchar.");
}

$currentChar = $alphabet[$currentCharIndex];

    $offset = 0;
    do {
        $response = $MadelineProto->channels->getParticipants([
            'channel' => $telegram_group_id,
            'filter' => ['_' => 'channelParticipantsSearch', 'q' => $currentChar],
            'offset' => $offset,
            'limit' => $limit
        ]);
        foreach ($response['participants'] as $participant) {
            if (!isset($participant['user_id'])) {
                continue; // Пропускаем текущую итерацию, если ключа нет
            }
            $allParticipants[$participant['user_id']] = $participant;
        }
        $offset += $limit;
    } while (count($response['participants']) == $limit);

$nextCharIndex = $currentCharIndex + 1;
if ($nextCharIndex >= count($alphabet)) {
    $updateNextChar = '00'; //прошли все символы
} else {
    $updateNextChar = $alphabet[$nextCharIndex];
}

// Обновление следующего символа в базе данных
$updateQuery = "UPDATE telegram_group SET nextchar = :nextchar WHERE id = :id_telegram_group";
$updateStmt = $currentDb->prepare($updateQuery);
$updateStmt->bindParam(':nextchar', $updateNextChar);
$updateStmt->bindParam(':id_telegram_group', $id_telegram_group);
$updateStmt->execute();

$linkToAdd = strtolower("https://Формируем ссылку для запуска cron на этот скрипт");
  //типа INSERT INTO crons (links, active, minuts) VALUES (:link, 1, 5)
  //убираем задачу если прошли все варианты 
  //if ($updateNextChar === '00') {
    // Если обработка символов завершена, устанавливаем статус активна в 0 для этой ссылки
//     $query = "
//         UPDATE crons SET active = 0 WHERE links = :link
//     ";
//     $statement = $db->prepare($query);
//     $statement->bindParam(':link', $linkToAdd);
//     $statement->execute();
// }
?>

для того чтобы не создавать большие нагрузки на проект скрипт запускается раз в 5 минут, код успешно прошел испытание и используется в проекте

Заключение

Надеюсь, что представленное решение проблемы с ограничением API Telegram на обработку данных более чем 10,000 пользователей окажется полезным для Вас. Эта задача, хотя и может показаться сложной на первый взгляд, решается довольно просто.

Комментарии (10)


  1. Z55
    05.05.2024 03:40
    +5

    А потом вы рассылаете спам этим 13000 пользователям, верно?


    1. infosave Автор
      05.05.2024 03:40

      Не спамить сейчас не модно, попробую объяснить идею проще, например у Вас есть Телеграм канал/группа на 50000 человек, я Вам предлагаю провести на Вашем канале стрим с продвиженим моих курсов актерского мастерства, Вы регистрируетесь на моем сайте для получения партнерского вознаграждения и даете мне права для того чтобы я смог спарсить все логины под Ваш ID, потом я провожу тестовые занятия на Вашем канале и предлагаю купить мои курсы. Допустим регистрируеся на мой сайт пользователь @xxxxxxx и он пришел получается с Вашего канала, тогда при покупке курса за 80000 рублей, Вам начисляют 6000 рублей по партнерской программе, а если пользователь @xxxxxxx пригласил друзей то Вы еще получите вознаграждение и от его друзей и друзей друзей (в нашем проекте партнерка 3 уровня)


      1. Yodatg
        05.05.2024 03:40

        А если пользователь состоит в нескольких каналах и группах? И/Или у него нет юзернейма?


        1. infosave Автор
          05.05.2024 03:40

          Если пользователь находится в других группах то фиксируется только тот под чей ID он импортировался первым, если нет юзернейма то естественно не импортируется и не пойдет по партнерской программе.


      1. DDanser
        05.05.2024 03:40

        Мало того, что вы вышли со статьей на Хабр с минимальной полезностью, так еще и позволяете себе игнорировать критические знаки препинания в комментариях.


  1. h4r7w3l1
    05.05.2024 03:40
    +2

    Проблема, которая решается в голове за 2 секунды действительно стоило написания и публикации статьи?

    Вы конечно меня простите, но если это для вас открытие, добавьте хоть идейности и значимости в статью:

    • Какие лимиты на данный запрос после чего вам откажут мило в выдаче поисковых результатов?

    • Когда телеграм посчитает это злоупотреблением и что будет с акаунтом и после какого предупреждения читатели решившие повторить опыт будут "добрым" словом отзываться об этой статье?

    • Какой алгоритм на ваш взгляд используется в поиске юзернеймов?

    • А что если аккаунт без юзернейма впринципе?

    Это весьма примитивные так-же вопросы, есть и более интересные и сложные - однако не всем такой опыт вообще нужен. Но минимально добавить полезности же не сложно, а то такое ощущение что открыли для себя один из методов работы поиска подстроки в форме поиска... Не сочтите за любые формы осуждения - но согласитесь добавив деталей, минимально о кейсе, эта статья будет куда полезнее читателям


  1. infosave Автор
    05.05.2024 03:40

    На самом деле тема не такая очевидная как Вам кажется, думаю многим пригодиться, не все такие задачи решают за 2 секунды (мне потребовалось 3 дня чтобы найти способ), все пока работает без блокировок от Телеграмм, пока не является нарушением. У нас сейчас 28 пользователей платформы типа https://nk.coursefactory.pro/ пока проект развивается, в каждом кабинете уже добавлено прилично групп и каналов.


  1. AntonZiminRZN
    05.05.2024 03:40

    Делается гугл форма с регистрацией и уникальной ссылкой, отдается владельцу канала и шарится к ней доступ на просмотр. В ней видно кто зарегистрировался на вебинар, по результатам вебинара видно сколько народу реально было и сколько заплатить. Смысл городить огород с параметром, при том, что скорее всего в апи есть такой момент как пагинация, не очень понятно.


  1. LeMaX
    05.05.2024 03:40

    К сожалению, этому "лайфхаку" уже больше 5 лет... Мы еще в 3 года назад, находили беглым гуглением на гитхабе этот способ для какой-то библиотеки, и вопросы были датированы вроде бы 2018 годом.

    Но вариант не 100%, некоторые логины он банально не выгрузит, не говоря о том, что пользовательские логины могут быть скрыты политикой конфиденциальности пользователя, а фио пустое. Да и в целом не ясно зачем весь список пользователей выгружать если есть реакции через бота и диплинки на бота, чтобы не ходить на сайты и прочее. Там и собирать можно информацию которую бот будет получать.


  1. AperDan_Cup
    05.05.2024 03:40

    Я все понимаю, но использовать группы для продвижения своих шедеврокурсов?