import 'dart:async'; import 'dart:io'; import '../lib/config.dart'; import '../lib/telegram.dart'; import '../lib/claude_runner.dart'; void main() async { final config = Config.fromEnv(); if (config.telegramToken.isEmpty) { stderr.writeln('ERROR: TELEGRAM_BOT_TOKEN must be set'); exit(1); } if (config.allowedChatIds.isEmpty) { stderr.writeln('ERROR: ALLOWED_CHAT_IDS must be set (comma-separated chat ids)'); exit(1); } final telegram = TelegramClient(config.telegramToken); final claude = ClaudeRunner(config); stderr.writeln('agent-news-bot starting, allowed chats: ${config.allowedChatIds}'); var offset = 0; while (true) { final updates = await telegram.getUpdates(offset: offset); for (final update in updates) { offset = (update['update_id'] as int) + 1; final message = update['message']; if (message == null) continue; final chatId = message['chat']['id'] as int; final messageId = message['message_id'] as int; final text = message['text']?.toString().trim(); if (text == null || text.isEmpty) continue; if (!config.allowedChatIds.contains(chatId)) { stderr.writeln(' → отклонено, чат $chatId не в ALLOWED_CHAT_IDS'); continue; } if (text == '/start') { await telegram.sendMessage( chatId, 'Привет! Я agent-news. Команда /news — свежая выжимка по ИИ ' '(ресёрч делает Claude Code, займёт 1-3 минуты).', ); continue; } if (text == '/news' || text.startsWith('/news ')) { final topic = text.startsWith('/news ') ? text.substring(6).trim() : null; if (claude.isBusy) { await telegram.sendMessage(chatId, 'Уже выполняю другой запрос, подожди.', replyToMessageId: messageId); continue; } await telegram.sendMessage( chatId, '🔎 Ищу свежую информацию${topic != null ? ' по теме «$topic»' : ' по ИИ'}, ' 'это займёт пару минут…', replyToMessageId: messageId, ); await telegram.sendTyping(chatId); unawaited(_runNews(claude, telegram, chatId, topic)); continue; } } } } Future _runNews( ClaudeRunner claude, TelegramClient telegram, int chatId, String? topic, ) async { final result = await claude.runNews(chatId: chatId, topic: topic); switch (result.outcome) { case ClaudeOutcome.success: stderr.writeln('news for $chatId done'); break; case ClaudeOutcome.busy: break; // уже сообщили выше case ClaudeOutcome.timeout: await telegram.sendMessage(chatId, 'Не успел уложиться по времени, попробуй позже.'); break; case ClaudeOutcome.failure: stderr.writeln('news for $chatId failed: ${result.detail}'); await telegram.sendMessage(chatId, 'Не получилось выполнить ресёрч, попробуй позже.'); break; } }