"""Telegram bot for receiving knowledge inbox items.""" import logging import os import re from telegram import Update from telegram.ext import Application, CommandHandler, ContextTypes, MessageHandler, filters from core.queue_db import get_status_counts, insert_item logging.basicConfig( level=logging.INFO, format="%(asctime)s [%(levelname)s] %(name)s: %(message)s", ) logger = logging.getLogger(__name__) def detect_type(text: str) -> str: """Detect the input type of a user message. Args: text: Raw message text from user. Returns: One of 'youtube', 'url', 'text'. """ text = text.strip() if re.search(r"youtube\.com/watch|youtu\.be/", text): return "youtube" if text.startswith(("http://", "https://")): return "url" return "text" async def cmd_start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: """Handle /start command.""" await update.message.reply_text( "πŸ“š *Knowledge Inbox Bot*\n\n" "λ‹€μŒμ„ μ „μ†‘ν•˜λ©΄ μžλ™μœΌλ‘œ μ²˜λ¦¬ν•˜μ—¬ Obsidian에 μ €μž₯ν•©λ‹ˆλ‹€:\n\n" "β€’ *YouTube URL* β€” 트랜슀크립트 μΆ”μΆœ ν›„ μš”μ•½\n" "β€’ *μ›Ή URL* β€” νŽ˜μ΄μ§€ λ‚΄μš© μΆ”μΆœ ν›„ μš”μ•½\n" "β€’ *자유 ν…μŠ€νŠΈ* β€” κ·ΈλŒ€λ‘œ μ €μž₯ ν›„ νƒœκ·Έ μΆ”μΆœ\n\n" "/status β€” 처리 ν˜„ν™© 쑰회", parse_mode="Markdown", ) async def cmd_status(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: """Handle /status command.""" try: counts = get_status_counts() msg = ( "πŸ“Š *처리 ν˜„ν™©*\n\n" f"⏳ λŒ€κΈ°μ€‘: {counts.get('pending', 0)}\n" f"πŸ”„ μ²˜λ¦¬μ€‘: {counts.get('processing', 0)}\n" f"βœ… μ™„λ£Œ: {counts.get('done', 0)}\n" f"❌ 였λ₯˜: {counts.get('error', 0)}" ) except Exception as exc: logger.error("Status query failed: %s", exc) msg = "❌ μƒνƒœ μ‘°νšŒμ— μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€." await update.message.reply_text(msg, parse_mode="Markdown") async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: """Handle all non-command messages.""" text = update.message.text or "" chat_id = str(update.effective_chat.id) if not text.strip(): return input_type = detect_type(text) type_labels = {"youtube": "YouTube", "url": "μ›ΉνŽ˜μ΄μ§€", "text": "ν…μŠ€νŠΈ"} try: row_id = insert_item(input_type, text.strip(), chat_id) label = type_labels[input_type] await update.message.reply_text( f"πŸ“₯ *{label}*이 큐에 μΆ”κ°€λμŠ΅λ‹ˆλ‹€.\n" f"ID: `{row_id[:8]}`\n\n" "처리 μ™„λ£Œ ν›„ Obsidian에 μ €μž₯λ©λ‹ˆλ‹€.", parse_mode="Markdown", ) except Exception as exc: logger.error("insert_item failed: %s", exc) await update.message.reply_text("❌ μ €μž₯에 μ‹€νŒ¨ν–ˆμŠ΅λ‹ˆλ‹€. μž μ‹œ ν›„ λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”.") def build_app() -> Application: """Build and configure the Telegram Application. Returns: Configured Application instance ready to run. """ token = os.environ["TELEGRAM_BOT_TOKEN"] app = Application.builder().token(token).build() app.add_handler(CommandHandler("start", cmd_start)) app.add_handler(CommandHandler("status", cmd_status)) app.add_handler(MessageHandler(filters.TEXT & ~filters.COMMAND, handle_message)) return app if __name__ == "__main__": from dotenv import load_dotenv load_dotenv() build_app().run_polling()