Telegram выкатил Serverless для ботов: без серверов, хостинга и девопса.
В начале 2022 года весь мир за одну неделю научился делиться квадратиками: 🟩🟨⬛. Wordle оказался идеально заточен под эпоху переписок — результат умещается в пару строк, спойлерить нечего, а сравнить себя с остальными хочется каждый день. Тогда и возник вопрос: если игра всё равно живёт в чатах, почему она должна жить где-то ещё?
@wordslebot — это Wordle, который поселился прямо в Telegram. Никаких установок и регистраций: открыл бота, нажал «🎮 Играть» — и ты уже в приложении, отрисованном как родное для Telegram. Есть соло-режим, партии с друзьями, дуэли и «слово дня», на которое хочется успеть до полуночи. А под капотом — целая инженерная история о том, как уместить игру с серверной частью на платформу, где нет ни серверов, ни npm, ни крона.
Под капотом у бота — платформа Telegram Serverless, и её идея в документации сформулирована честно: backend для бота и Mini App исполняется прямо на инфраструктуре Telegram. Каждый вызов функции живёт считанные мгновения в лёгком изоляте V8 — по соседству с Bot API и встроенной базой, поэтому арендовать VPS, патчить его и «держать живым» не нужно вовсе. Набор батареек прилагается каждому модулю: Bot API, SQLite-база и исходящий HTTP доступны из коробки, без установки и прописки ключей. Даже статика Mini App живёт там же: одна команда деплоя — и фронтенд раздаётся с собственного адреса вида app8885905073.tgcloud.ai, с HTTPS не настроенным, а просто существующим.
Что внутри: слово дня, пати и дуэли
Ядро бота — «Слово дня»: одно слово на всех игроков раз в сутки, шесть попыток, эмодзи-сетка в финале. Слово меняется в полночь по Москве, и у серии побед есть честное свойство — сгорать, если пропустил день. У каждого паззла есть номер, по которому результаты удобно сравнивать с друзьями, а счётчик до нового слова слегка подстёгивает возвращаться.
Вторая большая часть — совместная игра. Пати-комната собирает компанию по ссылке или коду; внутри живой чат, а режим «Загадывание слова» превращает друзей в ведущих: каждый круг кто-то один придумывает слово для остальных — при желании с подсказкой. Для дуэлей один на один генерируются одноразовые
ссылки, чтобы приглашения не превращались в спам. Сюда же — заявки в друзья, чат друзей, профили со статистикой и лидерборд; всё на двух языках, русском и английском.
Под капотом: бот без единого сервера
Слово «сервер» в этом тексте не случайно не встречается: бот целиком исполняется в облаке Telegram, а весь проект — набор маленьких функций трёх сортов. Handlers реагируют на события Telegram: входящие сообщения, нажатия инлайн-кнопок, инлайн-запросы. Endpoints — это HTTP API, через который приложение читает состояние партии, отправляет догадки и забирает статистику. Наконец, lib хранит игровую логику: проверку слов, серии, реферальный механизм и напоминания.
Аскетичный рантайм здесь к лучшему: без npm и фреймворков фронтенд написан на чистом JavaScript (около 100 КБ вместе со стилями) и стилизован под нативный Telegram, чтобы игра не выпадала из привычного окружения. Состояние на экране обновляется опросом раз в две секунды — из-за этого бот почти ничего не шлёт в личку: всё, что происходит в партии, и так видно в приложении. А в модели безопасности платформа подстраховывает сама: у эндпоинтов нет публичного API и логина в принципе — вызвать их можно только из Mini App этого бота, и личность звонящего подтверждает платформа, сверяя подпись initData ещё до запуска кода. Звонок мимо отбивается 401, так что «кто нажал кнопку» — не вопрос доверия, а гарантия.
Отдельная опора — 250 автотестов поверх стаб-версии SDK: игровая логика, комнаты, друзья, дуэли и виральный механизм покрыты так, что после каждой правки регрессия ловится до деплоя. Сам деплой — одной командой, с номерованными ревизиями: на момент написания в проде ревизия 35.
Слово дня без оракула
У «слова дня» есть техническая изюминка: отдельного хранилища «сегодняшнего слова» не существует. Слово детерминировано номером дня по Москве — по сути, словарь[номер дня % длина словаря]. У всех игроков оно совпадает само собой, и спор «а какое оно сегодня» не возникает в принципе. Заодно номер дня служит номером паззла — в том самом формате «Слово дня №20742».
И полночь здесь астрономически честная: игровой день считается формулой floor((unix + 3 часа) / 86400), так что «серия сгорит в полночь» — не фигура речи, а точное арифметическое утверждение. Такой подход убирает целый класс багов: нечему рассинхронизироваться, нечему протечь.
Крон, которого не было
Игрокам хочется напоминать: «Твоя серия сгорит в полночь!». Но у serverless-платформы нет планировщика задач, а синтетические вызовы вебхука она отбивает 401-й — дёрнуть бота извне по расписанию нельзя. Проверено живьём.
Решение — «ленивый триггер». Любой игрок, закончивший партию после 19:00 по Москве, запускает разовый вечерний батч напоминаний: бот находит всех, у кого серия ещё жива и сегодняшнее слово не сыграно, и бережно будит. Чужие победы работают планировщиком — чем активнее игроки, тем точнее «расписание». Для владельца остаётся ручной /tick, а чтобы рассылка не превращалась в шторм, батч ограничен сотней сообщений, между отправками пауза 50 мс, ответ retry_after от Telegram уважается, а одному человеку напоминают не чаще раза в день. Отписка — командой /remind off или тумблером в настройках приложения.
Виральная петля
Словесные игры созданы для сарафанного радио, и бот этим пользуется. После любой партии — победы или проигрыша — доступна кнопка «📤 Поделиться»: бот собирает пасту из эмодзи-сетки без букв загаданного слова, счёта и персональной реферальной ссылки. Отправка уходит через штатный t.me/share, а в любом чате работает инлайн-режим: напечатай @wordslebot в поле ввода — и выбери свежую сетку. Паста выглядит так:
Кто пришёл по ссылке вида t.me/wordslebot?start=ref_… — атрибутируется при первом же /start; пригласить самого себя нельзя, а существующая привязка не перезаписывается. Метки каналов (?start=vc, ?start=habr) позволяют отличить трафик из публикаций, а команда /refs показывает разбивку по источникам, топ приглашающих и K-фактор — сколько новых игроков приносит каждый существующий. Цикл замыкается: паста → ссылка → новый игрок → его паста.
Попробовать
Всё описанное собирается в один сценарий: открой @wordslebot, нажми «🎮 Играть» и попробуй угадать слово дня — сегодня оно одно и то же у всех, кто читает эти строки. Успеть нужно до полуночи: иначе серия сгорит, и это, как мы выяснили, чистая арифметика. А если зайдёт — кнопка «Поделиться» будет уже под рукой.