14 KiB
🔧 Завдання для Cursor: Виправити telegram-gateway (DAARWIZZ і Helion не відповідають)
🎯 Мета
Зробити так, щоб обидва боти (DAARWIZZ і Helion) автоматично ініціалізувались при старті та відповідали на повідомлення через polling.
📋 Проблеми зараз
- ❌ Боти не ініціалізуються автоматично при старті
- ❌
bots.yamlне монтується в контейнер - ❌ Polling не запускається для ботів з конфігурації
- ❌ Логування недостатнє для діагностики
✅ Що потрібно зробити
1. Виправити docker-compose.yml
Файл: /Users/apple/github-projects/microdao-daarion/telegram-infrastructure/docker-compose.yml
Додати volume для bots.yaml:
telegram-gateway:
build: ./telegram-gateway
container_name: telegram-gateway
restart: unless-stopped
env_file:
- .env
environment:
- TELEGRAM_API_BASE=http://telegram-bot-api:8081
- NATS_URL=nats://nats:4222
- ROUTER_BASE_URL=http://router:9102
- DEBUG=true
depends_on:
- telegram-bot-api
- nats
ports:
- "127.0.0.1:8000:8000"
volumes:
- ./telegram-gateway/bots.yaml:/app/bots.yaml:ro # ← ДОДАТИ ЦЕЙ РЯДОК
networks:
- telegram-net
- dagi-network
Чому: Контейнер має читати bots.yaml при старті, але файл не копіюється в образ і не монтується як volume.
2. Виправити app/main.py — автоматична ініціалізація ботів
Файл: /Users/apple/github-projects/microdao-daarion/telegram-infrastructure/telegram-gateway/app/main.py
Поточний код on_startup():
@app.on_event("startup")
async def on_startup():
# Підключаємося до NATS
await nats_client.connect()
logger.info("Connected to NATS at %s", settings.NATS_URL)
# На цьому етапі список ботів пустий; їх додаватимуть через /bots/register.
# За потреби сюди можна додати завантаження конфігів з БД.
Новий код on_startup() (ЗАМІНИТИ):
@app.on_event("startup")
async def on_startup():
# 1. Підключаємося до NATS
await nats_client.connect()
logger.info("✅ Connected to NATS at %s", settings.NATS_URL)
# 2. Завантажити конфігурацію ботів з bots.yaml або env
from .config import load_bots_config
try:
bot_configs = load_bots_config()
logger.info("📋 Loaded %d bot(s) from config", len(bot_configs))
except Exception as e:
logger.warning("⚠️ Failed to load bots config: %s", e)
bot_configs = []
# 3. Зареєструвати всі боти в реєстрі
if bot_configs:
bots_registry.register_from_config(bot_configs)
logger.info("📝 Registered %d bot(s) in registry", len(bot_configs))
# 4. Запустити polling для кожного бота
for bot_config in bot_configs:
agent_id = bot_config.agent_id
bot_token = bot_config.bot_token
# Запускаємо polling в фоновій задачі
asyncio.create_task(telegram_listener.add_bot(bot_token))
logger.info("🚀 Started polling for agent=%s (token=%s...)", agent_id, bot_token[:16])
if not bot_configs:
logger.warning("⚠️ No bots configured. Use /bots/register to add bots manually.")
Чому: Зараз боти не запускаються автоматично — треба викликати /bots/register вручну. Цей код автоматично завантажує конфіг і запускає polling при старті.
3. Перевірити app/config.py — функція load_bots_config()
Файл: /Users/apple/github-projects/microdao-daarion/telegram-infrastructure/telegram-gateway/app/config.py
Переконайся, що функція існує і виглядає приблизно так:
from pathlib import Path
from typing import List
import yaml
import os
from pydantic import BaseModel
class BotConfig(BaseModel):
agent_id: str
bot_token: str
def load_bots_config() -> List[BotConfig]:
"""
Завантажити конфігурацію ботів з bots.yaml або env variables.
Пріоритет:
1. bots.yaml (якщо існує)
2. Environment variables: BOT_<AGENT_ID>_TOKEN
"""
bots = []
# Спробувати завантажити з bots.yaml
config_path = Path("/app/bots.yaml") # Шлях в контейнері
if config_path.exists():
try:
with open(config_path, "r") as f:
data = yaml.safe_load(f)
if data and "bots" in data:
for bot_data in data["bots"]:
bots.append(BotConfig(**bot_data))
except Exception as e:
# Fallback до env variables
pass
# Fallback: завантажити з env variables
if not bots:
for key, value in os.environ.items():
if key.startswith("BOT_") and key.endswith("_TOKEN"):
agent_id = key[4:-6].lower() # BOT_DAARWIZZ_TOKEN -> daarwizz
bots.append(BotConfig(agent_id=agent_id, bot_token=value))
return bots
Якщо функція відсутня або неповна — додай/виправ її.
4. Перевірити app/bots_registry.py — метод register_from_config()
Файл: /Users/apple/github-projects/microdao-daarion/telegram-infrastructure/telegram-gateway/app/bots_registry.py
Переконайся, що метод існує:
from typing import List
from .config import BotConfig
class BotsRegistry:
# ... інші методи ...
def register_from_config(self, configs: List[BotConfig]) -> None:
"""Масова реєстрація ботів з конфігурації"""
for config in configs:
self.register(config)
# або напряму:
# self._agent_to_token[config.agent_id] = config.bot_token
# self._token_to_agent[config.bot_token] = config.agent_id
Якщо метод відсутній — додай його.
5. Додати детальне логування в app/telegram_listener.py
Файл: /Users/apple/github-projects/microdao-daarion/telegram-infrastructure/telegram-gateway/app/telegram_listener.py
Оновити метод add_bot() для кращого логування:
async def add_bot(self, bot_token: str) -> None:
if bot_token in self._bots:
logger.info("🔄 Bot already registered: %s...", bot_token[:16])
return
logger.info("🤖 Creating bot: %s...", bot_token[:16])
bot = await self._create_bot(bot_token)
dp = Dispatcher()
@dp.message(F.text)
async def on_message(message: Message) -> None:
agent_id = bots_registry.get_agent_by_token(bot_token)
if not agent_id:
logger.warning("⚠️ No agent_id for bot_token=%s...", bot_token[:16])
return
logger.info("📨 Received message: agent=%s, chat=%s, user=%s, len=%d",
agent_id, message.chat.id, message.from_user.id if message.from_user else 0, len(message.text or ""))
event = TelegramUpdateEvent(
agent_id=agent_id,
bot_id=f"bot:{bot_token[:8]}",
chat_id=message.chat.id,
user_id=message.from_user.id if message.from_user else 0,
text=message.text,
raw_update=message.model_dump()
)
logger.info("📤 Publishing to NATS: subject=agent.telegram.update, agent=%s", agent_id)
await nats_client.publish_json(
subject="agent.telegram.update",
data=event.model_dump()
)
# Запускаємо polling у фоні
async def _polling():
try:
logger.info("🔁 Start polling for bot %s...", bot_token[:16])
await dp.start_polling(bot)
except asyncio.CancelledError:
logger.info("🛑 Polling cancelled for bot %s...", bot_token[:16])
except Exception as e:
logger.exception("💥 Polling error for bot %s...: %s", bot_token[:16], e)
raise
task = asyncio.create_task(_polling())
self._bots[bot_token] = bot
self._dispatchers[bot_token] = dp
self._tasks[bot_token] = task
logger.info("✅ Bot registered and polling started: %s...", bot_token[:16])
Чому: Детальніше логування допоможе побачити, що відбувається при отриманні повідомлень.
6. Створити bots.yaml локально (якщо ще не створений)
Файл: /Users/apple/github-projects/microdao-daarion/telegram-infrastructure/telegram-gateway/bots.yaml
Вміст:
bots:
- agent_id: daarwizz
bot_token: 8323412397:AAFxaru-hHRl08A3T6TC02uHLvO5wAB0m3M
- agent_id: helion
bot_token: 8112062582:AAGI7tPFo4gvZ6bfbkFu9miq5GdAH2_LvcM
🧪 Як перевірити після змін
1. Деплой на сервер (виконати з Mac)
cd /Users/apple/github-projects/microdao-daarion/telegram-infrastructure
# Синхронізація коду
rsync -avz --exclude='.git' --exclude='__pycache__' --exclude='*.pyc' --exclude='data/' ./ root@144.76.224.179:/opt/telegram-infrastructure/
# Перезапуск на сервері
ssh root@144.76.224.179 "cd /opt/telegram-infrastructure && docker compose down telegram-gateway && docker compose up -d --build telegram-gateway"
2. Перевірка логів (на сервері)
ssh root@144.76.224.179
docker logs -f telegram-gateway
Очікувані рядки в логах:
✅ Connected to NATS at nats://nats:4222
📋 Loaded 2 bot(s) from config
📝 Registered 2 bot(s) in registry
🚀 Started polling for agent=daarwizz (token=8323412397:AAFxa...)
🚀 Started polling for agent=helion (token=8112062582:AAGI7...)
🔁 Start polling for bot 8323412397:AAFxa...
🔁 Start polling for bot 8112062582:AAGI7...
3. Перевірка списку ботів
curl -s http://127.0.0.1:8000/bots/list | jq .
Очікувана відповідь:
{
"bots": ["daarwizz", "helion"],
"count": 2
}
4. Перевірка polling tasks
curl -s http://127.0.0.1:8000/debug/bots | jq .
Очікувана відповідь:
{
"registered_bots": 2,
"bot_tokens": ["8323412397:AAFxa...", "8112062582:AAGI7..."],
"registry_mappings": 2,
"active_tasks": 2
}
curl -s http://127.0.0.1:8000/debug/bots/tasks | jq .
Очікувана відповідь:
{
"8323412397:AAFxa...": {
"done": false,
"cancelled": false
},
"8112062582:AAGI7...": {
"done": false,
"cancelled": false
}
}
5. Надіслати тестове повідомлення
В Telegram:
- Надішліть "Привіт" в DAARWIZZ бот
- Надішліть "Привіт" в Helion бот
В логах має з'явитись:
📨 Received message: agent=daarwizz, chat=123456, user=789, len=6
📤 Publishing to NATS: subject=agent.telegram.update, agent=daarwizz
📨 Received message: agent=helion, chat=123456, user=789, len=6
📤 Publishing to NATS: subject=agent.telegram.update, agent=helion
⚠️ Troubleshooting
Якщо боти не ініціалізуються:
# Перевірити, чи bots.yaml є в контейнері
docker exec telegram-gateway cat /app/bots.yaml
# Має показати вміст файлу. Якщо "No such file" — volume не працює
Якщо polling не запускається:
# Перевірити логи aiogram
docker logs telegram-gateway 2>&1 | grep -i "polling\|error\|exception"
Якщо повідомлення не приходять:
# Перевірити, чи webhooks видалені
curl -s "https://api.telegram.org/bot8323412397:AAFxaru-hHRl08A3T6TC02uHLvO5wAB0m3M/getWebhookInfo" | jq .result.url
curl -s "https://api.telegram.org/bot8112062582:AAGI7tPFo4gvZ6bfbkFu9miq5GdAH2_LvcM/getWebhookInfo" | jq .result.url
# Обидва мають повертати: "" (порожній рядок = webhook видалений)
📝 Checklist для Cursor
- Додати
volumes:вdocker-compose.ymlдляtelegram-gateway - Оновити
on_startup()вapp/main.pyз автоматичною ініціалізацією - Перевірити/додати
load_bots_config()вapp/config.py - Перевірити/додати
register_from_config()вapp/bots_registry.py - Додати детальне логування в
app/telegram_listener.py - Створити
telegram-gateway/bots.yamlз реальними токенами
🎯 Очікуваний результат
Після виконання всіх кроків:
- ✅ Обидва боти (DAARWIZZ і Helion) автоматично стартують при запуску контейнера
- ✅ Polling працює для обох ботів
- ✅ Повідомлення отримуються і публікуються в NATS
- ✅ Детальні логи для діагностики
- ✅
/bots/listпоказує обидва боти
Після цього агенти мають відповідати на повідомлення! 🎉