Асинхронный замена дейлика. Разработчики пишут боту в конце дня, LLM извлекает прогресс/планы/блокеры, утром в 08:00 тимлид получает дайджест 3-2-1, каждый разработчик — свой план на день.
┌─────────────────────────────────────────────────────┐
│ Telegram Bot (polling) REST API (Fiber :80) │
│ /start, /help, текст → POST /api/v1/updates │
│ POST /api/v1/members │
│ POST /api/v1/teams │
│ GET /api/v1/digest │
└──────────────┬──────────────────────────────────────┘
│ daily_updates (status: queued)
▼
┌─────────────────────────────────────────────────────┐
│ Async Dispatcher (горутина) │
│ FOR UPDATE SKIP LOCKED → ExtractWorker │
│ OpenRouter LLM → structured_updates │
└──────────────────────────────────────────────────────┘
│ cron 08:00
▼
┌─────────────────────────────────────────────────────┐
│ DigestWorker → LLM → digest → Telegram рассылка │
└──────────────────────────────────────────────────────┘
handler → service → repository
handler/— HTTP и Telegram, только парсинг/ответservice/— бизнес-логикаrepository/— SQL через GORMdomain/— чистые Go-структуры без теговmodel/— GORM DAO с тегами, маппинг через genericmapper.goprovider/— DI-контейнер наreflect
- Открой Telegram, найди @BotFather
- Напиши
/newbot - Придумай имя бота (например:
SilentDaily Bot) - Придумай username (должен заканчиваться на
bot, например:silentdaily_bot) - BotFather пришлёт токен вида:
7123456789:AAHxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - Вставь его в
.env:
TELEGRAM_TOKEN=7123456789:AAHxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx- Зайди на openrouter.ai
- Зарегистрируйся → Keys → Create Key
- Бесплатные модели:
google/gemma-3-12b-it:free,meta-llama/llama-3.1-8b-instruct:free
# 2. Запусти
docker-compose up --build
# 3. Проверь
curl http://localhost:8080/ping
# → pongsh src/scripts/migrations.sh --upHealthcheck.
curl http://localhost:8080/ping
# → pongСоздать команду. Делается один раз тимлидом.
curl -X POST http://localhost:8080/api/v1/teams \
-H "Content-Type: application/json" \
-d '{"name": "Backend Team"}'Ответ:
{"id": 1, "name": "Backend Team"}Зарегистрировать участника команды. telegram_user_id — это числовой ID пользователя в Telegram (не username).
curl -X POST http://localhost:8080/api/v1/members \
-H "Content-Type: application/json" \
-d '{
"telegram_user_id": 123456789,
"name": "Тим Малов",
"team_id": 1,
"is_lead": true
}'Ответ:
{"status": "registered"}Как узнать свой telegram_user_id: напиши боту @userinfobot в Telegram — он пришлёт твой числовой ID.
Отправить апдейт напрямую через API (альтернатива боту).
curl -X POST http://localhost:8080/api/v1/updates \
-H "Content-Type: application/json" \
-d '{
"telegram_user_id": 123456789,
"raw_text": "Сегодня закончил авторизацию и написал тесты. Завтра займусь деплоем на staging. Блокеров нет."
}'Ответ:
{"status": "queued"}Получить дайджест команды за дату.
# Дайджест за вчера (по умолчанию)
curl "http://localhost:8080/api/v1/digest?team_id=1"
# Дайджест за конкретную дату
curl "http://localhost:8080/api/v1/digest?team_id=1&date=2026-05-31"Ответ:
{
"team_id": 1,
"date": "2026-05-31T00:00:00Z",
"lead_digest": " ТОП-3 ПРОГРЕССА:\n1. ..."
}| Команда | Описание |
|---|---|
/start |
Приветствие и инструкция |
/help |
Как пользоваться |
| любой текст | Принимается как дневной апдейт |
- Тимлид регистрирует всех через
POST /api/v1/members - В конце дня каждый пишет боту в свободной форме:
«Сегодня закончил авторизацию, написал тесты для login endpoint. Завтра займусь деплоем. Блокеров нет.»
- Бот отвечает: «✅ Апдейт принят!»
- В 08:00 следующего дня:
- Тимлид получает дайджест 3-2-1
- Каждый разработчик получает свой план на день
ExtractWorker — получает сырой текст, отправляет в OpenRouter с промптом:
Извлеки из текста:
PROGRESS: что сделано (через ;)
PLANS: что планируется (через ;)
BLOCKERS: что мешает (через ; или "нет")
DigestWorker — собирает все structured_updates команды за вчера, отправляет в LLM:
Сформируй дайджест 3-2-1:
🟢 ТОП-3 ПРОГРЕССА
📋 2 ГЛАВНЫХ ПЛАНА
🔴 1 КЛЮЧЕВОЙ БЛОКЕР
Горутина, которая каждые 2 секунды:
- Берёт одну запись
daily_updates WHERE status = 'queued'сFOR UPDATE SKIP LOCKED - Ставит статус
in_progress, инкрементитattempts - Запускает
ExtractWorkerв отдельной горутине - Слушает канал результатов → ставит
doneилиfailed
FOR UPDATE SKIP LOCKED — гарантирует что два воркера не возьмут одну задачу, даже если запущено несколько инстансов.
Ограничивает количество одновременных воркеров (по умолчанию 5).
Если воркер упал — attempts++, статус обратно в queued. После 3 попыток — failed.