mirror of
https://github.com/Zippland/Bubbles.git
synced 2026-01-19 17:51:14 +08:00
411 lines
13 KiB
Python
411 lines
13 KiB
Python
"""
|
||
AI路由功能注册
|
||
将需要通过AI路由的功能在这里注册
|
||
"""
|
||
import re
|
||
import json
|
||
import os
|
||
from typing import Optional, Match
|
||
from datetime import datetime
|
||
|
||
from .ai_router import ai_router
|
||
from .context import MessageContext
|
||
|
||
# ======== 天气功能 ========
|
||
@ai_router.register(
|
||
name="weather_query",
|
||
description="查询城市未来五天的简要天气预报",
|
||
parameters={
|
||
"type": "object",
|
||
"properties": {
|
||
"city": {
|
||
"type": "string",
|
||
"description": "要查询天气的城市名称,如:北京、上海、深圳"
|
||
}
|
||
},
|
||
"required": ["city"]
|
||
}
|
||
)
|
||
def ai_handle_weather(ctx: MessageContext, city: str, **kwargs) -> bool:
|
||
"""AI路由的天气查询处理"""
|
||
city_name = city.strip()
|
||
if not city_name:
|
||
ctx.send_text("🤔 请告诉我你想查询哪个城市的天气")
|
||
return True
|
||
|
||
# 加载城市代码
|
||
city_codes = {}
|
||
city_code_path = os.path.join(os.path.dirname(__file__), '..', 'function', 'main_city.json')
|
||
try:
|
||
with open(city_code_path, 'r', encoding='utf-8') as f:
|
||
city_codes = json.load(f)
|
||
except Exception as e:
|
||
if ctx.logger:
|
||
ctx.logger.error(f"加载城市代码文件失败: {e}")
|
||
ctx.send_text("⚠️ 抱歉,天气功能暂时不可用")
|
||
return True
|
||
|
||
# 查找城市代码
|
||
city_code = city_codes.get(city_name)
|
||
if not city_code:
|
||
# 尝试模糊匹配
|
||
for name, code in city_codes.items():
|
||
if city_name in name:
|
||
city_code = code
|
||
city_name = name
|
||
break
|
||
|
||
if not city_code:
|
||
ctx.send_text(f"😕 找不到城市 '{city_name}' 的天气信息")
|
||
return True
|
||
|
||
# 获取天气信息
|
||
try:
|
||
from function.func_weather import Weather
|
||
weather_info = Weather(city_code).get_weather(include_forecast=True)
|
||
ctx.send_text(weather_info)
|
||
return True
|
||
except Exception as e:
|
||
if ctx.logger:
|
||
ctx.logger.error(f"获取天气信息失败: {e}")
|
||
ctx.send_text(f"😥 获取 {city_name} 天气时遇到问题")
|
||
return True
|
||
|
||
# ======== 新闻功能 ========
|
||
@ai_router.register(
|
||
name="news_query",
|
||
description="获取今日重要新闻和要闻",
|
||
parameters={
|
||
"type": "object",
|
||
"properties": {},
|
||
"required": []
|
||
}
|
||
)
|
||
def ai_handle_news(ctx: MessageContext, **kwargs) -> bool:
|
||
"""AI路由的新闻查询处理"""
|
||
try:
|
||
from function.func_news import News
|
||
news_instance = News()
|
||
is_today, news_content = news_instance.get_important_news()
|
||
|
||
if is_today:
|
||
ctx.send_text(f"📰 今日要闻来啦:\n{news_content}")
|
||
else:
|
||
if news_content:
|
||
ctx.send_text(f"ℹ️ 今日新闻暂未发布,为您找到最近的一条新闻:\n{news_content}")
|
||
else:
|
||
ctx.send_text("❌ 获取新闻失败,请稍后重试")
|
||
|
||
return True
|
||
except Exception as e:
|
||
if ctx.logger:
|
||
ctx.logger.error(f"获取新闻失败: {e}")
|
||
ctx.send_text("❌ 获取新闻时发生错误")
|
||
return True
|
||
|
||
# ======== 提醒功能 ========
|
||
@ai_router.register(
|
||
name="reminder_set",
|
||
description="为用户设置一个新的提醒",
|
||
parameters={
|
||
"type": "object",
|
||
"properties": {
|
||
"content": {
|
||
"type": "string",
|
||
"description": "提醒的具体内容和时间,如:明天下午3点开会、每天早上8点吃早餐"
|
||
}
|
||
},
|
||
"required": ["content"]
|
||
}
|
||
)
|
||
def ai_handle_reminder_set(ctx: MessageContext, content: str, **kwargs) -> bool:
|
||
"""AI路由的提醒设置处理"""
|
||
if not content.strip():
|
||
at_list = ctx.msg.sender if ctx.is_group else ""
|
||
ctx.send_text("请告诉我需要提醒什么内容和时间呀~", at_list)
|
||
return True
|
||
|
||
# 调用原有的提醒处理逻辑
|
||
from .handlers import handle_reminder
|
||
|
||
# 临时修改消息内容以适配原有处理器
|
||
original_content = ctx.msg.content
|
||
ctx.msg.content = f"提醒我{content}"
|
||
|
||
# handle_reminder不使用match参数,直接传None
|
||
result = handle_reminder(ctx, None)
|
||
|
||
# 恢复原始内容
|
||
ctx.msg.content = original_content
|
||
|
||
return result
|
||
|
||
@ai_router.register(
|
||
name="reminder_list",
|
||
description="查看用户已经设置的所有提醒列表",
|
||
parameters={
|
||
"type": "object",
|
||
"properties": {},
|
||
"required": []
|
||
}
|
||
)
|
||
def ai_handle_reminder_list(ctx: MessageContext, **kwargs) -> bool:
|
||
"""AI路由的提醒列表查看处理"""
|
||
from .handlers import handle_list_reminders
|
||
return handle_list_reminders(ctx, None)
|
||
|
||
@ai_router.register(
|
||
name="reminder_delete",
|
||
description="删除指定的提醒",
|
||
parameters={
|
||
"type": "object",
|
||
"properties": {
|
||
"description": {
|
||
"type": "string",
|
||
"description": "要删除的提醒的描述或关键词,如:开会、早餐、明天的提醒"
|
||
}
|
||
},
|
||
"required": ["description"]
|
||
}
|
||
)
|
||
def ai_handle_reminder_delete(ctx: MessageContext, description: str, **kwargs) -> bool:
|
||
"""AI路由的提醒删除处理"""
|
||
# 调用原有的删除提醒逻辑
|
||
from .handlers import handle_delete_reminder
|
||
|
||
# 临时修改消息内容
|
||
original_content = ctx.msg.content
|
||
ctx.msg.content = f"删除提醒 {description}"
|
||
|
||
# handle_delete_reminder不使用match参数,直接传None
|
||
result = handle_delete_reminder(ctx, None)
|
||
|
||
# 恢复原始内容
|
||
ctx.msg.content = original_content
|
||
|
||
return result
|
||
|
||
# ======== 帮助功能 ========
|
||
@ai_router.register(
|
||
name="help",
|
||
description="显示机器人的帮助信息和可用指令列表",
|
||
parameters={
|
||
"type": "object",
|
||
"properties": {},
|
||
"required": []
|
||
}
|
||
)
|
||
def ai_handle_help(ctx: MessageContext, **kwargs) -> bool:
|
||
"""AI路由的帮助处理"""
|
||
help_text = [
|
||
"🤖 泡泡智能助手 🤖",
|
||
"",
|
||
"🌟 我现在支持自然语言交互!你可以用平常说话的方式和我对话:",
|
||
"",
|
||
"【天气查询】",
|
||
"💬 \"北京今天天气怎么样\"",
|
||
"💬 \"上海明天会下雨吗\"",
|
||
"💬 \"查一下深圳的天气预报\"",
|
||
"",
|
||
"【新闻资讯】",
|
||
"💬 \"看看今天的新闻\"",
|
||
"💬 \"有什么重要新闻吗\"",
|
||
"",
|
||
"【智能提醒】",
|
||
"💬 \"提醒我明天下午3点开会\"",
|
||
"💬 \"每天早上8点提醒我吃早餐\"",
|
||
"💬 \"查看我的提醒\"",
|
||
"💬 \"删掉开会的提醒\"",
|
||
"",
|
||
"【智能搜索】",
|
||
"💬 \"搜索Python最新特性\"",
|
||
"💬 \"查一下机器学习教程\"",
|
||
"",
|
||
"【群聊管理】",
|
||
"💬 \"总结一下最近的聊天\" (仅群聊)",
|
||
"💬 \"清除聊天历史\" (仅群聊)",
|
||
"💬 \"查看我的装备\" (仅群聊)",
|
||
"",
|
||
"【娱乐功能】",
|
||
"💬 \"骂一下@张三\" (仅群聊)",
|
||
"",
|
||
"✨ 直接用自然语言告诉我你想做什么,我会智能理解你的意图!",
|
||
"🔧 在群聊中需要@我才能使用功能哦~"
|
||
]
|
||
help_message = "\n".join(help_text)
|
||
|
||
# 发送消息
|
||
ctx.send_text(help_message)
|
||
return True
|
||
|
||
# ======== 消息管理功能 ========
|
||
@ai_router.register(
|
||
name="summary",
|
||
description="总结群聊中最近的聊天消息内容",
|
||
parameters={
|
||
"type": "object",
|
||
"properties": {},
|
||
"required": []
|
||
}
|
||
)
|
||
def ai_handle_summary(ctx: MessageContext, **kwargs) -> bool:
|
||
"""AI路由的消息总结处理"""
|
||
if not ctx.is_group:
|
||
ctx.send_text("⚠️ 消息总结功能仅支持群聊")
|
||
return True
|
||
|
||
from .handlers import handle_summary
|
||
return handle_summary(ctx, None)
|
||
|
||
@ai_router.register(
|
||
name="clear_messages",
|
||
description="清除当前群聊的历史消息记录",
|
||
parameters={
|
||
"type": "object",
|
||
"properties": {},
|
||
"required": []
|
||
}
|
||
)
|
||
def ai_handle_clear_messages(ctx: MessageContext, **kwargs) -> bool:
|
||
"""AI路由的消息历史清除处理"""
|
||
if not ctx.is_group:
|
||
ctx.send_text("⚠️ 消息历史管理功能仅支持群聊")
|
||
return True
|
||
|
||
from .handlers import handle_clear_messages
|
||
return handle_clear_messages(ctx, None)
|
||
|
||
# ======== 决斗功能 ========
|
||
@ai_router.register(
|
||
name="check_equipment",
|
||
description="查看玩家在决斗游戏中的魔法装备和道具",
|
||
parameters={
|
||
"type": "object",
|
||
"properties": {},
|
||
"required": []
|
||
}
|
||
)
|
||
def ai_handle_check_equipment(ctx: MessageContext, **kwargs) -> bool:
|
||
"""AI路由的装备查看处理"""
|
||
if not ctx.is_group:
|
||
ctx.send_text("❌ 装备查看功能只支持群聊")
|
||
return True
|
||
|
||
from .handlers import handle_check_equipment
|
||
return handle_check_equipment(ctx, None)
|
||
|
||
# ======== 娱乐功能 ========
|
||
@ai_router.register(
|
||
name="insult_user",
|
||
description="骂指定的用户(娱乐功能,无恶意)",
|
||
parameters={
|
||
"type": "object",
|
||
"properties": {
|
||
"target_user": {
|
||
"type": "string",
|
||
"description": "要骂的目标用户的名称或昵称"
|
||
}
|
||
},
|
||
"required": ["target_user"]
|
||
}
|
||
)
|
||
def ai_handle_insult(ctx: MessageContext, target_user: str, **kwargs) -> bool:
|
||
"""AI路由的骂人处理"""
|
||
if not ctx.is_group:
|
||
ctx.send_text("❌ 骂人功能只支持群聊")
|
||
return True
|
||
|
||
# 解析参数,提取用户名
|
||
user_name = target_user.strip()
|
||
if not user_name:
|
||
ctx.send_text("🤔 请告诉我要骂谁")
|
||
return True
|
||
|
||
# 移除@符号
|
||
user_name = user_name.replace("@", "").strip()
|
||
|
||
# 创建一个假的match对象,因为原始处理器需要
|
||
fake_match = type('MockMatch', (), {
|
||
'group': lambda self, n: user_name if n == 1 else None
|
||
})()
|
||
|
||
from .handlers import handle_insult
|
||
# 临时修改消息内容以适配原有处理器
|
||
original_content = ctx.msg.content
|
||
ctx.msg.content = f"骂一下@{user_name}"
|
||
|
||
result = handle_insult(ctx, fake_match)
|
||
|
||
# 恢复原始内容
|
||
ctx.msg.content = original_content
|
||
|
||
return result
|
||
|
||
# ======== Perplexity搜索功能 ========
|
||
@ai_router.register(
|
||
name="perplexity_search",
|
||
description="使用Perplexity搜索查询资料并深度研究某个专业问题",
|
||
parameters={
|
||
"type": "object",
|
||
"properties": {
|
||
"query": {
|
||
"type": "string",
|
||
"description": "要搜索的关键词或问题,如:Python最新特性、机器学习教程"
|
||
}
|
||
},
|
||
"required": ["query"]
|
||
}
|
||
)
|
||
def ai_handle_perplexity(ctx: MessageContext, query: str, **kwargs) -> bool:
|
||
"""AI路由的Perplexity搜索处理"""
|
||
if not query.strip():
|
||
at_list = ctx.msg.sender if ctx.is_group else ""
|
||
ctx.send_text("请告诉我你想搜索什么内容", at_list)
|
||
return True
|
||
|
||
# 获取Perplexity实例
|
||
perplexity_instance = getattr(ctx.robot, 'perplexity', None)
|
||
if not perplexity_instance:
|
||
ctx.send_text("❌ Perplexity搜索功能当前不可用")
|
||
return True
|
||
|
||
# 调用Perplexity处理
|
||
content_for_perplexity = f"ask {query}"
|
||
chat_id = ctx.get_receiver()
|
||
sender_wxid = ctx.msg.sender
|
||
room_id = ctx.msg.roomid if ctx.is_group else None
|
||
is_group = ctx.is_group
|
||
|
||
was_handled, fallback_prompt = perplexity_instance.process_message(
|
||
content=content_for_perplexity,
|
||
chat_id=chat_id,
|
||
sender=sender_wxid,
|
||
roomid=room_id,
|
||
from_group=is_group,
|
||
send_text_func=ctx.send_text
|
||
)
|
||
|
||
# 如果Perplexity无法处理,使用默认AI
|
||
if not was_handled and fallback_prompt:
|
||
chat_model = getattr(ctx, 'chat', None) or (getattr(ctx.robot, 'chat', None) if ctx.robot else None)
|
||
if chat_model:
|
||
try:
|
||
import time
|
||
current_time = time.strftime("%H:%M", time.localtime())
|
||
q_with_info = f"[{current_time}] {ctx.sender_name}: {query}"
|
||
|
||
rsp = chat_model.get_answer(
|
||
question=q_with_info,
|
||
wxid=ctx.get_receiver(),
|
||
system_prompt_override=fallback_prompt
|
||
)
|
||
|
||
if rsp:
|
||
at_list = ctx.msg.sender if ctx.is_group else ""
|
||
ctx.send_text(rsp, at_list)
|
||
return True
|
||
except Exception as e:
|
||
if ctx.logger:
|
||
ctx.logger.error(f"默认AI处理失败: {e}")
|
||
|
||
return was_handled |