Как стать автором
Обновить

Как я создал Telegram-бота для поиска сообщений по ID и не сошел с ума

Уровень сложностиПростой

Всем привет! Хочу поделиться историей, как я с нуля собрал Telegram-бота, который умеет искать сообщения по user_id, выгружать их в Excel и при этом не разваливаться на больших объёмах. Было всего: баги, тормоза, таймауты и вишенка на торте — неожиданный переезд на Windows Server, от которого всё вдруг стало работать.

С чего всё началось

Идея была простая: хотелось бота, который умеет искать все сообщения конкретного пользователя в Telegram-группах, где сидит мой userbot. Чтобы по ID выдать Excel-файл со всеми его сообщениями — удобно, просто, красиво.

Плюс в голове крутилась мысль: а почему бы не сделать это более-менее универсальным инструментом, которым можно делиться или даже масштабировать?

Что использовали

  • Telethon — слушает чаты и собирает сообщения

  • Aiogram — обычный Telegram-бот для общения с пользователем

  • PostgreSQL — база, куда всё складывается

  • asyncpg — чтобы всё работало асинхронно

  • Pandas + OpenPyXL — формируем Excel-файл по запросу

Первые проблемы: тормоза в базе

Сначала всё было бодро. Пока в базе было 1000–5000 сообщений — запросы летали. Но когда стало 100K и больше — банальный SELECT COUNT(*) FROM events WHERE user_id = ... начал отвечать секунд по 10.

Добавили индекс:

CREATE INDEX IF NOT EXISTS idx_events_user_id ON events(user_id);

И... всё стало нормально. Мораль: индексы — это не просто «рекомендация», а «обязательная техника безопасности».

Потом начались таймауты

Когда пользователи стали запрашивать выгрузки по user_id с десятками тысяч сообщений, бот начал падать. Просто — TimeoutError. Причём всё валилось где-то внутри conn.fetch().

Решение оказалось несложным: вместо одной огромной выборки — постраничная загрузка. По 1000 сообщений за раз:

async def fetch_pg_events(pool, user_id, batch_size=1000):
    offset = 0
    all_rows = []
    while True:
        async with pool.acquire() as conn:
            rows = await conn.fetch("SELECT ... OFFSET $1 LIMIT $2", offset, batch_size)
        if not rows:
            break
        all_rows.extend(rows)
        offset += batch_size
    return all_rows

Работает стабильно, не падает, не тормозит.

Неожиданный баг: Linux не выдержал

Наш userbot слушал около 100 чатов одновременно. Всё работало на VPS с Ubuntu... пока не переставало. Через пару часов бот просто «умирал». Логов ноль. Подключений больше 500. Была догадка, что это связано с epoll, uvloop или чем-то похожим. Пробовали патчить, отключать uvloop, менять ядра — всё впустую.

В какой-то момент решил: а может попробовать на Windows? И внезапно...

Переезд на Windows Server

Да, это может звучать как «антипаттерн», но Windows Server просто взял и заработал:

  • asyncio ведёт себя стабильно

  • Telethon не падает

  • легче дебажить через RDP

В результате бот уже недели две работает без падений, обрабатывает тысячи новых и старых сообщений, формирует Excel-файлы и не требует лишнего внимания.

Что в итоге

На выходе получился Telegram-бот, который:

  • ищет сообщения по ID пользователя

  • умеет выгружать их в Excel с ссылками на оригинал

  • стабильно работает на PostgreSQL

  • не падает, не зависает и живёт на Windows Server

Telegram бот: https://t.me/message_searcher

Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.