chore: initial commit

This commit is contained in:
你的用户名
2025-11-01 21:58:31 +08:00
commit 0406b5664f
101 changed files with 20458 additions and 0 deletions

View File

@@ -0,0 +1,865 @@
#!/usr/bin/env python3
"""
整合版客服机器人 - AI增强版
包含:
1. AI对话引导
2. 镜像搜索功能
3. 自动翻页缓存
4. 智能去重
"""
import asyncio
import logging
import time
import os
import httpx
# import anthropic # 已替换为 claude-agent-sdk
from claude_agent_wrapper import init_claude_agent
import json
import sys
from typing import Dict, Optional
from datetime import datetime
# 添加路径
sys.path.insert(0, "/home/atai/bot_data")
# Pyrogram imports
from pyrogram import Client as PyrogramClient, filters
from pyrogram.types import Message as PyrogramMessage
from pyrogram.raw.functions.messages import GetBotCallbackAnswer
# Telegram Bot imports
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import Application, CommandHandler, MessageHandler, CallbackQueryHandler, filters as tg_filters
from telegram.ext import ContextTypes
# 导入数据库
try:
from database import CacheDatabase
except ImportError:
CacheDatabase = None
logging.warning("database.py未找到缓存功能将禁用")
# ================== 配置 ==================
API_ID = 24660516
API_HASH = "eae564578880a59c9963916ff1bbbd3a"
SESSION_NAME = "user_session"
BOT_TOKEN = "8426529617:AAHAxzohSMFBAxInzbAVJsZfkB5bHnOyFC4"
TARGET_BOT = "@openaiw_bot"
ADMIN_ID = 7363537082
# AI服务配置
MAC_API_URL = "http://192.168.9.10:8000"
# 搜索命令列表
SEARCH_COMMANDS = ['/topchat', '/search', '/text', '/human']
# 日志配置
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# 初始化Claude Agent SDK客户端
try:
claude_client = init_claude_agent()
if claude_client:
logger.info("✅ Claude Agent SDK客户端已初始化")
else:
logger.error("❌ Claude Agent SDK初始化失败")
claude_client = None
except Exception as e:
logger.error(f"❌ Claude Agent SDK初始化失败: {e}")
claude_client = None
# ================== 对话管理 ==================
class ConversationManager:
"""管理用户对话上下文"""
def __init__(self, max_history=5):
self.conversations = {}
self.max_history = max_history
def add_message(self, user_id: int, role: str, content: str):
"""添加消息到历史"""
if user_id not in self.conversations:
self.conversations[user_id] = []
self.conversations[user_id].append({
"role": role,
"content": content,
"timestamp": datetime.now().isoformat()
})
# 保持最近的N条消息
if len(self.conversations[user_id]) > self.max_history * 2:
self.conversations[user_id] = self.conversations[user_id][-self.max_history * 2:]
def get_history(self, user_id: int, limit: int = 2) -> list:
"""获取用户对话历史"""
if user_id not in self.conversations:
return []
history = self.conversations[user_id][-limit * 2:]
return [{"role": msg["role"], "content": msg["content"]} for msg in history]
def clear_history(self, user_id: int):
"""清空用户历史"""
if user_id in self.conversations:
del self.conversations[user_id]
# ================== 自动翻页管理器 ==================
class AutoPaginationManager:
"""后台自动翻页 - 用户无感知"""
def __init__(self, pyrogram_client, cache_db, target_bot_id, logger):
self.pyrogram_client = pyrogram_client
self.cache_db = cache_db
self.target_bot_id = target_bot_id
self.logger = logger
self.active_tasks = {}
async def start_pagination(self, user_id, command, keyword, first_message):
"""启动后台翻页任务"""
if user_id in self.active_tasks:
return
task = asyncio.create_task(self._paginate(user_id, command, keyword, first_message))
self.active_tasks[user_id] = task
self.logger.info(f"[翻页] 后台任务启动: {command} {keyword}")
async def _paginate(self, user_id, command, keyword, message):
"""执行翻页"""
try:
page = 1
self._save_to_cache(command, keyword, page, message)
if not self._has_next(message):
self.logger.info(f"[翻页] 只有1页")
return
current = message
page = 2
max_pages = 100 # 最多100页防止死循环
while page <= max_pages:
await asyncio.sleep(2)
next_msg = await self._click_next(current)
if not next_msg:
self.logger.info(f"[翻页] 点击失败,停止翻页")
break
self._save_to_cache(command, keyword, page, next_msg)
self.logger.info(f"[翻页] 第{page}页已保存")
if not self._has_next(next_msg):
self.logger.info(f"[翻页] ✅ 完成,共{page}")
break
current = next_msg
page += 1
except Exception as e:
self.logger.error(f"[翻页] 错误: {e}")
finally:
if user_id in self.active_tasks:
del self.active_tasks[user_id]
def _has_next(self, msg):
"""检查是否有下一页"""
if not msg.reply_markup:
return False
for row in msg.reply_markup.inline_keyboard:
for btn in row:
if btn.text:
text = btn.text.strip()
# 检查右箭头(排除左箭头)
if any(arrow in text for arrow in ["➡️", "", "", "»"]):
if not any(prev in text for prev in ["⬅️", "", "", "«"]):
return True
# 检查文字
if any(x in text for x in ["下一页", "Next"]):
return True
return False
async def _click_next(self, msg):
"""点击下一页"""
try:
from pyrogram.raw.functions.messages import GetBotCallbackAnswer
for row in msg.reply_markup.inline_keyboard:
for btn in row:
if btn.text and btn.callback_data:
text = btn.text.strip()
# 检查是否是下一页按钮
is_next = False
if any(arrow in text for arrow in ['➡️', '', '', '»']):
if not any(prev in text for prev in ['⬅️', '', '', '«']):
is_next = True
if any(x in text for x in ['下一页', 'Next']):
is_next = True
if is_next:
await self.pyrogram_client.invoke(
GetBotCallbackAnswer(
peer=await self.pyrogram_client.resolve_peer(self.target_bot_id),
msg_id=msg.id,
data=btn.callback_data
)
)
await asyncio.sleep(1.5)
return await self.pyrogram_client.get_messages(self.target_bot_id, msg.id)
except Exception as e:
self.logger.error(f"[翻页] 点击失败: {e}")
return None
def _save_to_cache(self, cmd, keyword, page, msg):
"""保存到缓存"""
if not self.cache_db:
return
try:
text = msg.text or msg.caption or ""
buttons = []
if msg.reply_markup:
for row in msg.reply_markup.inline_keyboard:
for btn in row:
buttons.append({"text": btn.text, "url": btn.url if btn.url else None})
self.cache_db.save_cache(cmd, keyword, page, text, result_html=None, buttons=buttons)
except Exception as e:
self.logger.error(f"[翻页] 保存失败: {e}")
class IntegratedBotAI:
"""整合的客服机器人 - AI增强版"""
def __init__(self):
# Bot应用
self.app = None
# Pyrogram客户端用于镜像
self.pyrogram_client: Optional[PyrogramClient] = None
self.target_bot_id: Optional[int] = None
# 消息映射
self.pyrogram_to_telegram = {}
self.telegram_to_pyrogram = {}
self.callback_data_map = {}
self.user_search_sessions = {}
# AI会话状态
self.user_ai_sessions = {}
# 缓存数据库
self.cache_db = CacheDatabase() if CacheDatabase else None
# 对话管理器
self.conversation_manager = ConversationManager()
self.pagination_manager = None
async def setup_pyrogram(self):
"""设置Pyrogram客户端"""
try:
proxy_config = None
if os.environ.get('ALL_PROXY'):
proxy_url = os.environ.get('ALL_PROXY', '').replace('socks5://', '')
if proxy_url:
host, port = proxy_url.split(':')
proxy_config = {"scheme": "socks5", "hostname": host, "port": int(port)}
self.pyrogram_client = PyrogramClient(
SESSION_NAME, api_id=API_ID, api_hash=API_HASH,
proxy=proxy_config if proxy_config else None
)
await self.pyrogram_client.start()
logger.info("✅ Pyrogram客户端已启动")
# 初始化自动翻页管理器
self.pagination_manager = AutoPaginationManager(
self.pyrogram_client, self.cache_db, self.target_bot_id, logger
)
logger.info("✅ 自动翻页管理器已初始化")
target = await self.pyrogram_client.get_users(TARGET_BOT)
self.target_bot_id = target.id
logger.info(f"✅ 已连接到搜索机器人: {target.username}")
@self.pyrogram_client.on_message(filters.user(self.target_bot_id))
async def on_bot_response(_, message: PyrogramMessage):
await self.handle_search_response(message)
@self.pyrogram_client.on_edited_message(filters.user(self.target_bot_id))
async def on_message_edited(_, message: PyrogramMessage):
await self.handle_search_response(message, is_edit=True)
return True
except Exception as e:
logger.error(f"Pyrogram设置失败: {e}")
return False
async def call_ai_service(self, user_id: int, message: str, context: dict = None) -> dict:
"""优化的Claude API调用 - 带上下文记忆和改进提示词"""
if not claude_client:
logger.error("Claude客户端未初始化")
return {
"type": "auto",
"response": "👋 我来帮你搜索!\n\n直接发关键词,或试试:\n• /search 群组名\n• /text 讨论内容\n• /topchat 热门分类",
"confidence": 0.3
}
try:
logger.info(f"[用户 {user_id}] 调用Claude API: {message}")
username = context.get('username', f'user_{user_id}') if context else f'user_{user_id}'
first_name = context.get('first_name', '') if context else ''
# 构建对话历史
messages = []
# 添加历史对话最近2轮
history = self.conversation_manager.get_history(user_id, limit=2)
messages.extend(history)
# 添加当前消息(优化的提示词)
current_prompt = f"""你是@ktfund_bot的AI助手专业的Telegram群组搜索助手。
【重要】你的回复中可以包含可执行的命令,我会为它们生成按钮。
命令格式:/search 关键词 或 /text 关键词
用户信息:@{username} ({first_name})
用户说:"{message}"
【可用工具】
• /search [关键词] - 搜索群组名称
• /text [关键词] - 搜索讨论内容
• /human [关键词] - 搜索用户
• /topchat - 热门分类
【回复要求】
1. 简短友好2-4行
2. 给1-2个具体命令建议
3. 口语化,像朋友聊天
4. 命令要在独立的一行
【示例】
用户:"找AI群"
回复:
找AI群的话试试
/search AI
/text ChatGPT
直接回复:"""
messages.append({
"role": "user",
"content": current_prompt
})
# 调用Claude Agent SDK
claude_response = await claude_client.chat_async(
messages=messages,
model="claude-sonnet-4-5-20250929",
max_tokens=512,
temperature=0.7
)
# 保存对话历史
self.conversation_manager.add_message(user_id, "user", message)
self.conversation_manager.add_message(user_id, "assistant", claude_response)
logger.info(f"[用户 {user_id}] ✅ Claude回复成功 ({len(claude_response)}字)")
# 智能提取命令建议
suggested_commands = self._extract_commands(claude_response)
return {
"type": "ai",
"response": claude_response,
"confidence": 1.0,
"suggested_commands": suggested_commands
}
except Exception as e:
logger.error(f"[用户 {user_id}] ❌ Claude API失败: {e}")
return {
"type": "auto",
"response": "👋 我来帮你搜索!\n\n直接发关键词,或试试:\n• /search 群组名\n• /text 讨论内容\n• /topchat 热门分类",
"confidence": 0.3
}
def _extract_commands(self, response_text: str) -> list:
"""从回复中提取建议的命令"""
import re
commands = []
# 匹配 /command pattern
patterns = [
r'/search\s+[\w\s]+',
r'/text\s+[\w\s]+',
r'/human\s+[\w\s]+',
r'/topchat'
]
for pattern in patterns:
matches = re.findall(pattern, response_text)
commands.extend([m.strip() for m in matches[:1]])
return commands[:2]
def _extract_command_buttons(self, text: str) -> list:
"""从AI回复中提取命令按钮"""
import re
buttons = []
# 匹配:/command keyword
pattern = r'/(search|text|human|topchat)\s*([^\n]*)'
matches = re.findall(pattern, text, re.IGNORECASE)
for cmd, keywords in matches[:3]:
cmd = cmd.lower()
keywords = keywords.strip()[:30] # 限制长度
if keywords:
display = f"/{cmd} {keywords}"
callback = f"cmd_{cmd}_{keywords.replace(' ', '_')}"[:64]
else:
display = f"/{cmd}"
callback = f"cmd_{cmd}"
buttons.append((display, callback))
return buttons
async def handle_start(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
"""处理/start命令 - AI引导模式"""
user = update.effective_user
user_id = user.id
self.user_ai_sessions[user_id] = {"started_at": datetime.now(), "conversation": []}
welcome_text = (
f"👋 您好 {user.first_name}\n\n"
"我是智能搜索助手可以帮您找到Telegram上的群组和频道。\n\n"
"🔍 我能做什么:\n"
"• 搜索群组/频道\n"
"• 搜索特定话题的讨论\n"
"• 查找用户\n"
"• 浏览热门分类\n\n"
"💬 直接告诉我您想找什么,我会帮您选择最合适的搜索方式!"
)
keyboard = [
[InlineKeyboardButton("🔍 搜索群组", callback_data="quick_search"),
InlineKeyboardButton("📚 使用指南", callback_data="quick_help")],
[InlineKeyboardButton("🔥 热门分类", callback_data="quick_topchat")]
]
await update.message.reply_text(welcome_text, reply_markup=InlineKeyboardMarkup(keyboard))
# 通知管理员
admin_notification = (
f"🆕 新用户访问 (AI模式):\n"
f"👤 {user.first_name} {user.last_name or ''}\n"
f"🆔 {user.id}\n"
f"👤 @{user.username or ''}\n"
f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
)
await context.bot.send_message(chat_id=ADMIN_ID, text=admin_notification)
async def handle_message(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
"""处理所有消息 - AI智能路由"""
if not update.message or not update.message.text:
return
user = update.effective_user
user_id = user.id
text = update.message.text
is_admin = user_id == ADMIN_ID
if is_admin and update.message.reply_to_message:
await self.handle_admin_reply(update, context)
return
if self.is_search_command(text):
await self.handle_search_command(update, context)
return
await self.handle_ai_conversation(update, context)
def is_search_command(self, text: str) -> bool:
"""检查是否是搜索命令"""
return text and text.split()[0] in SEARCH_COMMANDS
async def handle_ai_conversation(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
"""AI对话处理 - 带智能按钮"""
user = update.effective_user
user_id = user.id
message = update.message.text
# 显示"正在输入"
await update.message.chat.send_action("typing")
# 构建上下文
user_context = {
"username": user.username or f"user{user_id}",
"first_name": user.first_name or "朋友",
"last_name": user.last_name
}
# 调用AI
ai_response = await self.call_ai_service(user_id, message, user_context)
response_text = ai_response.get("response", "")
# 提取命令按钮
buttons = self._extract_command_buttons(response_text)
try:
if buttons:
# 构建按钮键盘
keyboard = []
for display, callback in buttons:
keyboard.append([InlineKeyboardButton(
f"🔍 {display}",
callback_data=callback
)])
# 添加常用按钮
keyboard.append([
InlineKeyboardButton("🔥 热门目录", callback_data="cmd_topchat"),
InlineKeyboardButton("📖 帮助", callback_data="cmd_help")
])
await update.message.reply_text(
response_text,
reply_markup=InlineKeyboardMarkup(keyboard)
)
logger.info(f"[AI对话] 已回复用户 {user_id} (带{len(buttons)}个按钮)")
else:
# 无按钮版本
await update.message.reply_text(response_text)
logger.info(f"[AI对话] 已回复用户 {user_id}")
except Exception as e:
logger.error(f"[AI对话] 发送失败: {e}, 降级为纯文本")
try:
await update.message.reply_text(response_text)
except:
await update.message.reply_text("抱歉,回复失败。请直接发送命令,如:/search AI")
async def handle_search_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
"""处理搜索命令 - 带缓存"""
user = update.effective_user
user_id = user.id
command = update.message.text
# 提取命令和关键词
parts = command.split(maxsplit=1)
cmd = parts[0]
keyword = parts[1] if len(parts) > 1 else ""
# 检查缓存
if self.cache_db and keyword:
cached = self.cache_db.get_cache(cmd, keyword, 1)
if cached:
logger.info(f"返回缓存结果: {cmd} {keyword}")
await update.message.reply_text(
f"📦 从缓存返回结果:\n\n{cached['text'][:4000]}",
parse_mode='HTML'
)
return
# 通知管理员
admin_notification = (
f"🔍 用户执行搜索:\n"
f"👤 {user.first_name} {user.last_name or ''}\n"
f"🆔 {user_id}\n"
f"📝 {command}\n"
f"{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
)
await context.bot.send_message(chat_id=ADMIN_ID, text=admin_notification)
wait_msg = await update.message.reply_text("🔍 正在搜索,请稍候...")
self.user_search_sessions[user_id] = {
'chat_id': update.effective_chat.id,
'wait_msg_id': wait_msg.message_id,
'command': cmd,
'keyword': keyword,
'timestamp': datetime.now()
}
await self.pyrogram_client.send_message(self.target_bot_id, command)
logger.info(f"搜索: {command}")
async def handle_search_response(self, message: PyrogramMessage, is_edit: bool = False):
"""处理搜索机器人的响应 - 保存到缓存"""
try:
if not self.user_search_sessions:
return
user_id = max(self.user_search_sessions.keys(), key=lambda k: self.user_search_sessions[k]['timestamp'])
session = self.user_search_sessions[user_id]
text = message.text or message.caption or "无结果"
try:
if message.text and hasattr(message.text, 'html'):
text = message.text.html
except:
pass
keyboard = self.convert_keyboard(message)
if is_edit and message.id in self.pyrogram_to_telegram:
telegram_msg_id = self.pyrogram_to_telegram[message.id]
await self.app.bot.edit_message_text(
chat_id=session['chat_id'],
message_id=telegram_msg_id,
text=text[:4000],
reply_markup=keyboard,
parse_mode='HTML'
)
else:
try:
await self.app.bot.delete_message(
chat_id=session['chat_id'],
message_id=session['wait_msg_id']
)
except:
pass
sent = await self.app.bot.send_message(
chat_id=session['chat_id'],
text=text[:4000],
reply_markup=keyboard,
parse_mode='HTML'
)
self.pyrogram_to_telegram[message.id] = sent.message_id
self.telegram_to_pyrogram[sent.message_id] = message.id
# 保存到缓存
if self.cache_db and session.get('keyword'):
buttons = self.extract_buttons(message)
self.cache_db.save_cache(
session['command'],
session['keyword'],
1, # 第一页
text,
text,
buttons
)
# 后台自动翻页(用户无感知)
if self.pagination_manager:
asyncio.create_task(
self.pagination_manager.start_pagination(
user_id, session['command'], session['keyword'], message
)
)
except Exception as e:
logger.error(f"处理搜索响应失败: {e}")
def convert_keyboard(self, message: PyrogramMessage) -> Optional[InlineKeyboardMarkup]:
"""转换键盘"""
if not message.reply_markup or not message.reply_markup.inline_keyboard:
return None
try:
buttons = []
for row in message.reply_markup.inline_keyboard:
button_row = []
for btn in row:
if btn.url:
button_row.append(InlineKeyboardButton(text=btn.text, url=btn.url))
elif btn.callback_data:
callback_id = f"cb_{time.time():.0f}_{len(self.callback_data_map)}"
self.callback_data_map[callback_id] = (message.id, btn.callback_data)
button_row.append(InlineKeyboardButton(text=btn.text, callback_data=callback_id[:64]))
if button_row:
buttons.append(button_row)
return InlineKeyboardMarkup(buttons) if buttons else None
except Exception as e:
logger.error(f"键盘转换失败: {e}")
return None
def extract_buttons(self, message: PyrogramMessage) -> list:
"""提取按钮数据"""
if not message.reply_markup or not message.reply_markup.inline_keyboard:
return []
buttons = []
for row in message.reply_markup.inline_keyboard:
for btn in row:
buttons.append({"text": btn.text, "url": btn.url if btn.url else None})
return buttons
async def handle_callback(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
"""处理按钮点击 - 执行搜索命令"""
query = update.callback_query
data = query.data
user = query.from_user
await query.answer()
if data.startswith("cmd_"):
# 解析命令
parts = data.replace("cmd_", "").split("_", 1)
cmd = parts[0]
keywords = parts[1].replace("_", " ") if len(parts) > 1 else ""
# 构造完整命令
command = f"/{cmd} {keywords}" if keywords else f"/{cmd}"
logger.info(f"[用户 {user.id}] 点击按钮: {command}")
# 显示执行提示
await query.message.reply_text(f"🔍 正在执行:{command}\n请稍候...")
# 转发到搜索bot
try:
await self.pyrogram_client.send_message(self.target_bot_id, command)
# 记录搜索会话
self.user_search_sessions[user.id] = {
'chat_id': query.message.chat_id,
'wait_msg_id': query.message.message_id + 1,
'command': f"/{cmd}",
'keyword': keywords,
'timestamp': datetime.now()
}
logger.info(f"[镜像] 已转发: {command}")
except Exception as e:
logger.error(f"[镜像] 转发失败: {e}")
await query.message.reply_text("❌ 搜索失败,请稍后重试或直接发送命令")
elif data == "cmd_help":
await query.message.reply_text(
"📖 使用指南:\n\n"
"• /search [关键词] - 按群组名称搜索\n"
"• /text [关键词] - 按消息内容搜索\n"
"• /human [关键词] - 按用户名搜索\n"
"• /topchat - 热门群组目录\n\n"
"💡 或者直接告诉我你想找什么!"
)
else:
logger.warning(f"未知callback: {data}")
async def handle_admin_reply(self, update: Update, context: ContextTypes.DEFAULT_TYPE):
"""处理管理员回复"""
reply_to = update.message.reply_to_message
if not reply_to or not reply_to.text:
return
import re
user_id = None
for line in reply_to.text.split('\n'):
if '🆔' in line or 'ID:' in line:
numbers = re.findall(r'\d+', line)
if numbers:
user_id = int(numbers[0])
break
if not user_id:
await update.message.reply_text("❌ 无法识别用户ID")
return
try:
await context.bot.send_message(chat_id=user_id, text=update.message.text)
await update.message.reply_text(f"✅ 已回复给用户 {user_id}")
except Exception as e:
await update.message.reply_text(f"❌ 回复失败: {str(e)}")
async def initialize(self):
"""初始化机器人"""
try:
logger.info("正在初始化整合机器人...")
if not await self.setup_pyrogram():
logger.error("Pyrogram初始化失败")
return False
builder = Application.builder().token(BOT_TOKEN)
if os.environ.get('HTTP_PROXY'):
proxy_url = os.environ.get('HTTP_PROXY')
logger.info(f"配置Telegram Bot代理: {proxy_url}")
request = httpx.AsyncClient(proxies={"http://": proxy_url, "https://": proxy_url}, timeout=30.0)
builder = builder.request(request)
self.app = builder.build()
self.app.add_handler(CommandHandler("start", self.handle_start))
self.app.add_handler(CallbackQueryHandler(self.handle_callback))
self.app.add_handler(MessageHandler(tg_filters.ALL, self.handle_message))
logger.info("✅ 整合机器人初始化完成")
return True
except Exception as e:
logger.error(f"初始化失败: {e}")
return False
async def run(self):
"""运行机器人"""
try:
await self.app.initialize()
await self.app.start()
await self.app.updater.start_polling(drop_pending_updates=True)
logger.info("="*50)
logger.info("✅ AI增强版Bot已启动")
logger.info(f"AI服务: {MAC_API_URL}")
logger.info(f"缓存功能: {'启用' if self.cache_db else '禁用'}")
logger.info("="*50)
await asyncio.Event().wait()
except KeyboardInterrupt:
logger.info("收到停止信号")
finally:
await self.cleanup()
async def cleanup(self):
"""清理资源"""
logger.info("正在清理...")
if self.app:
await self.app.updater.stop()
await self.app.stop()
await self.app.shutdown()
if self.pyrogram_client:
await self.pyrogram_client.stop()
logger.info("✅ 清理完成")
async def main():
"""主函数"""
bot = IntegratedBotAI()
if await bot.initialize():
await bot.run()
else:
logger.error("初始化失败,退出")
if __name__ == "__main__":
asyncio.run(main())