import os import logging import asyncio from telegram import Bot, Update from telegram.ext import Application, CommandHandler, MessageHandler, filters, ContextTypes from telegram.error import TelegramError, NetworkError, TimedOut from config import TELEGRAM_BOT_TOKEN from api_client import APIClient # 设置日志记录 logging.basicConfig( level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger(__name__) # 创建 API 客户端 api_client = APIClient() async def start_command(update: Update, context: ContextTypes.DEFAULT_TYPE): """处理 /start 命令""" try: logger.info(f"收到 /start 命令,来自用户: {update.message.from_user.username}") await update.message.reply_text( "👋 你好!我是一个智能助手。\n\n" "🤖 我可以:\n" "1. 回答你的问题\n" "2. 帮你完成任务\n" "3. 陪你聊天\n\n" "💡 直接发消息给我就可以开始对话!\n" "🔄 使用 /clear 可以清除对话历史\n" "❓ 使用 /help 查看更多帮助" ) except Exception as e: logger.error(f"处理 /start 命令时出错: {str(e)}", exc_info=True) await update.message.reply_text("抱歉,处理命令时出现错误,请稍后再试。") async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE): """处理 /help 命令""" try: logger.info(f"收到 /help 命令,来自用户: {update.message.from_user.username}") await update.message.reply_text( "🔍 帮助信息:\n\n" "命令列表:\n" "/start - 开始对话\n" "/help - 显示帮助信息\n" "/clear - 清除对话历史\n" "/check - 检查机器人权限\n\n" "使用提示:\n" "1. 直接发送消息即可与我对话\n" "2. 我会记住对话内容,保持上下文连贯\n" "3. 如果想开始新话题,可以用 /clear 清除历史\n" "4. 我会用emoji让对话更生动\n" "5. 如果遇到问题,请尝试重新发送消息" ) except Exception as e: logger.error(f"处理 /help 命令时出错: {str(e)}", exc_info=True) await update.message.reply_text("抱歉,处理命令时出现错误,请稍后再试。") async def clear_command(update: Update, context: ContextTypes.DEFAULT_TYPE): """处理 /clear 命令""" try: chat_id = update.message.chat_id logger.info(f"收到 /clear 命令,来自用户: {update.message.from_user.username}") # 清除对话历史 api_client.clear_history(chat_id) await update.message.reply_text( "🧹 已清除对话历史!\n" "现在我们可以开始新的对话了。" ) except Exception as e: logger.error(f"处理 /clear 命令时出错: {str(e)}", exc_info=True) await update.message.reply_text("抱歉,清除历史记录时出现错误,请稍后再试。") async def check_permissions_command(update: Update, context: ContextTypes.DEFAULT_TYPE): """检查机器人权限""" try: chat = update.message.chat logger.info(f"正在检查权限 - 聊天ID: {chat.id}, 类型: {chat.type}") # 获取机器人信息 bot_info = await context.bot.get_me() logger.info(f"机器人信息 - ID: {bot_info.id}, 用户名: @{bot_info.username}") # 获取机器人成员信息 try: bot_member = await chat.get_member(context.bot.id) logger.info(f"机器人成员信息 - 状态: {bot_member.status}, 权限: {vars(bot_member)}") except Exception as e: logger.error(f"获取机器人成员信息失败: {str(e)}") bot_member = None # 获取发送者信息 try: sender = await chat.get_member(update.message.from_user.id) logger.info(f"发送者信息 - 状态: {sender.status}, 权限: {vars(sender)}") except Exception as e: logger.error(f"获取发送者信息失败: {str(e)}") sender = None permissions_info = [ f"🤖 机器人信息:", f"- 用户名:@{bot_info.username}", f"- ID:{bot_info.id}", f"- 是否为机器人:{'是' if bot_info.is_bot else '否'}", f"\n📱 当前聊天信息:", f"- 类型:{chat.type}", f"- ID:{chat.id}", f"- 标题:{chat.title if chat.type != 'private' else '私聊'}", f"\n👤 发送者信息:", f"- 用户名:@{update.message.from_user.username}", f"- ID:{update.message.from_user.id}", f"- 状态:{sender.status if sender else '未知'}" ] if bot_member: permissions_info.extend([ f"\n🔑 机器人权限:", f"- 成员状态:{bot_member.status}", f"- 是否为管理员:{'是' if bot_member.status in ['administrator', 'creator'] else '否'}", f"- 是否可以发送消息:{'是' if getattr(bot_member, 'can_send_messages', None) is not False else '否'}", f"- 是否可以发送媒体消息:{'是' if getattr(bot_member, 'can_send_media_messages', None) is not False else '否'}", f"- 是否可以添加网页预览:{'是' if getattr(bot_member, 'can_add_web_page_previews', None) is not False else '否'}", f"- 是否可以发送其他消息:{'是' if getattr(bot_member, 'can_send_other_messages', None) is not False else '否'}", f"- 原始权限数据:{vars(bot_member)}" ]) else: permissions_info.append("\n❌ 无法获取机器人权限信息") await update.message.reply_text("\n".join(permissions_info)) except Exception as e: error_msg = f"检查权限时出错: {str(e)}" logger.error(error_msg, exc_info=True) await update.message.reply_text(f"抱歉,检查权限时出现错误:\n{error_msg}") async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE, retry_count=0): """处理用户消息""" try: # 获取用户信息和消息 user = update.message.from_user message_text = update.message.text chat_id = update.message.chat_id bot_username = context.bot.username # 检查是否是群组消息 is_group = update.message.chat.type in ["group", "supergroup"] logger.info(f"消息类型: {'群组消息' if is_group else '私聊消息'}") logger.info(f"机器人用户名: {bot_username}") logger.info(f"原始消息: {message_text}") # 检查是否提到了机器人(包括回复和@) mentioned = False if is_group: # 检查是否是回复机器人的消息 if update.message.reply_to_message and update.message.reply_to_message.from_user.id == context.bot.id: mentioned = True # 检查是否@机器人(支持消息中的任何位置) elif bot_username and f"@{bot_username}" in message_text: mentioned = True # 移除@username部分 message_text = message_text.replace(f"@{bot_username}", "").strip() logger.info(f"是否提到机器人: {mentioned}") # 如果没有提到机器人,则忽略消息 if not mentioned: logger.info("未提到机器人,忽略消息") return logger.info(f"处理消息 [{chat_id}] 来自 {user.username}: {message_text}") # 发送"正在输入"状态 await update.message.chat.send_action(action="typing") # 调用 AI API 获取回复 response = await api_client.get_ai_response(chat_id, message_text) # 发送回复 await update.message.reply_text(response) logger.info(f"已回复消息 [{chat_id}]: {response[:100]}...") except (NetworkError, TimedOut) as e: if retry_count < 3: logger.warning(f"发送消息失败,正在重试 ({retry_count + 1}/3): {str(e)}") await asyncio.sleep(1) return await handle_message(update, context, retry_count + 1) else: logger.error(f"发送消息失败,已达到最大重试次数: {str(e)}") await update.message.reply_text("抱歉,发送消息时出现错误,请稍后再试。") except Exception as e: logger.error(f"处理消息时出错: {str(e)}", exc_info=True) await update.message.reply_text("抱歉,处理消息时出现错误,请稍后再试。") async def error_handler(update: object, context: ContextTypes.DEFAULT_TYPE) -> None: """处理错误""" logger.error("发生异常:", exc_info=context.error) async def cleanup(): """清理资源""" await api_client.close() def run_bot(): """运行机器人""" try: # 创建应用 application = Application.builder().token(TELEGRAM_BOT_TOKEN).build() # 添加处理器 application.add_handler(CommandHandler("start", start_command)) application.add_handler(CommandHandler("help", help_command)) application.add_handler(CommandHandler("clear", clear_command)) application.add_handler(CommandHandler("check", check_permissions_command)) # 添加消息处理器,处理提及和私聊消息 application.add_handler(MessageHandler( (filters.TEXT & ~filters.COMMAND) & (filters.ChatType.GROUPS | filters.ChatType.PRIVATE) & (filters.Entity("mention") | filters.ChatType.PRIVATE), handle_message )) # 添加处理器,处理回复机器人的消息 application.add_handler(MessageHandler( (filters.TEXT & ~filters.COMMAND) & filters.REPLY, handle_message )) # 添加错误处理器 application.add_error_handler(error_handler) # 启动机器人 logger.info("正在启动机器人...") application.run_polling(drop_pending_updates=True) except Exception as e: logger.error(f"启动机器人时出错: {str(e)}", exc_info=True) raise finally: # 确保清理资源 asyncio.run(cleanup()) if __name__ == "__main__": run_bot()