Files
abot/plugins/game_task/main.py

555 lines
22 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import random
from datetime import datetime
from typing import Dict, Any, List, Optional, Tuple
from loguru import logger
from async_job import async_job
from base.plugin_common.message_plugin_interface import MessagePluginInterface
from base.plugin_common.plugin_interface import PluginStatus
from utils.decorator.plugin_decorators import plugin_stats_decorator
from utils.robot_cmd.robot_command import Feature, PermissionStatus, GroupBotManager
from utils.decorator.points_decorator import points_reward_decorator
from utils.ai.game_chatgpt_qa import game_question_json, game_answer_json
from db.connection import DBConnectionManager
from db.encyclopedia import EncyclopediaDB
class GameTaskPlugin(MessagePluginInterface):
"""游戏任务插件"""
@property
def name(self) -> str:
return "百科问答"
@property
def version(self) -> str:
return "1.0.0"
@property
def description(self) -> str:
return "百科问答游戏系统,支持问答积分"
@property
def author(self) -> str:
return "Trae AI"
@property
def command_prefix(self) -> Optional[str]:
return "" # 不需要前缀,直接匹配命令
@property
def commands(self) -> List[str]:
return self._commands
def __init__(self):
super().__init__()
self.LOG = logger
async_job.at_times(["17:58"])(self.run_random_task_assignment)
def initialize(self, context: Dict[str, Any]) -> bool:
"""初始化插件"""
self.LOG.info(f"正在初始化 {self.name} 插件...")
# 保存上下文对象
self.event_system = context.get("event_system")
# 初始化配置
self._commands = self._config.get("GameTask", {}).get("command",
["/t", "/a", "/s", "/r", "/l", "/h"])
self.command_format = self._config.get("GameTask", {}).get("command-format", """
🎮 百科问答指令:
/s - 加入游戏
/t - 获取任务
/a <任务ID> <答案> - 提交答案
/r - 查看排行榜
/l - 查看活跃任务
/h - 查看未完成任务
""")
self.enable = self._config.get("GameTask", {}).get("enable", True)
# 初始化数据库连接
self.db_manager = DBConnectionManager.get_instance()
self.encyclopedia_db = EncyclopediaDB(self.db_manager)
self.LOG.info(f"[{self.name}] 插件初始化完成,指令:{self._commands}")
return True
def start(self) -> bool:
"""启动插件"""
self.LOG.info(f"[{self.name}] 插件已启动")
self.status = PluginStatus.RUNNING
return True
def stop(self) -> bool:
"""停止插件"""
self.LOG.info(f"[{self.name}] 插件已停止")
self.status = PluginStatus.STOPPED
return True
def can_process(self, message: Dict[str, Any]) -> bool:
"""检查是否可以处理该消息"""
if not self.enable:
return False
content = str(message.get("content", "")).strip()
command = content.split(" ")[0]
return command in self._commands
def calculate_game_points(self, message: Dict[str, Any], success: bool, response: str) -> int:
"""计算游戏积分"""
if not success:
return 0
try:
return int(response)
except (TypeError, ValueError):
return 0
@plugin_stats_decorator(plugin_name="百科问答")
async def process_message(self, message: Dict[str, Any]) -> Tuple[bool, Optional[str]]:
"""处理消息"""
content = str(message.get("content", "")).strip()
command = content.split(" ")[0].lower()
sender = message.get("sender")
roomid = message.get("roomid", "")
gbm: GroupBotManager = message.get("gbm")
all_contacts = message.get("all_contacts", {})
self.LOG.debug(f"插件执行: {self.name}{content}")
# 检查权限
if roomid and gbm.get_group_permission(roomid, Feature.TASK_GAME) == PermissionStatus.DISABLED:
return False, "没有权限"
try:
# 获取用户昵称
wx_nick_name = all_contacts.get(sender, sender)
if command == "/s":
await self._handle_join_game(sender, roomid, wx_nick_name)
return True, "加入游戏成功"
elif command == "/t":
await self._handle_get_task(sender, roomid)
return True, "获取任务成功"
elif command == "/a":
# 这里传递整个消息对象给处理方法
return await self._handle_submit_answer(message)
elif command == "/r":
await self._handle_show_rank(sender, roomid)
return True, "显示排行榜成功"
elif command == "/l":
await self._handle_show_active_tasks(sender, roomid)
return True, "显示活跃任务成功"
elif command == "/h":
await self._handle_list_uncompleted_tasks(sender, roomid)
return True, "列举未完成任务成功"
else:
await self.bot.send_at_message((roomid if roomid else sender), f"❌未知命令!\n{self.command_format}",
[sender])
return False, "未知命令"
except Exception as e:
self.LOG.error(f"处理消息出错: {e}")
return False, f"处理出错: {e}"
async def _handle_join_game(self, sender: str, roomid: str, wx_nick_name: str) -> None:
"""处理加入游戏请求"""
try:
# 检查并添加群聊
if not self.encyclopedia_db.check_group_exists(roomid):
self.encyclopedia_db.add_group(roomid)
await self.bot.send_text_message(
(roomid if roomid else sender),
f"🎉 群 {roomid} 已就位,准备开燥!",
sender
)
# 检查并添加玩家
player = self.encyclopedia_db.get_player(sender, roomid)
if not player:
self.encyclopedia_db.add_player(sender, roomid, wx_nick_name)
await self.bot.send_text_message(
(roomid if roomid else sender),
f"🎉 哇塞,{wx_nick_name} 你来啦!\n"
f"🌟 群 {roomid} 瞬间燃爆!\n"
f"🎈 快来接任务,秀翻全场!指令: /t",
sender
)
except Exception as e:
self.LOG.error(f"加入游戏出错: {e}")
await self.bot.send_text_message(
(roomid if roomid else sender),
f"😔 加入游戏出错,请稍后再试!",
sender
)
async def _handle_get_task(self, sender: str, roomid: str) -> None:
"""处理获取任务请求"""
try:
# 获取群内所有玩家
players = self.encyclopedia_db.get_all_players_in_group(roomid)
# 如果群里没有玩家,自动初始化并添加当前用户
if not players:
# 检查并添加群聊
if not self.encyclopedia_db.check_group_exists(roomid):
self.encyclopedia_db.add_group(roomid)
await self.bot.send_text_message(
(roomid if roomid else sender),
f"🎉 群 {roomid} 已就位,准备开燥!",
sender
)
# 获取用户昵称 (从all_contacts中获取可能不可行因为这里没有all_contacts参数)
# 使用sender作为临时昵称
wx_nick_name = sender
# 添加当前用户为玩家
self.encyclopedia_db.add_player(sender, roomid, wx_nick_name)
await self.bot.send_text_message(
(roomid if roomid else sender),
f"🎉 哇塞,{wx_nick_name} 你是第一个玩家!\n"
f"🌟 已自动为你加入游戏!\n"
f"🎈 现在就为你准备题目...",
sender
)
# 更新玩家列表
players = self.encyclopedia_db.get_all_players_in_group(roomid)
player_dict = {p['player_id']: p['player_name'] for p in players}
if sender not in player_dict:
await self.bot.send_text_message(
(roomid if roomid else sender),
f"😅 嘿,你谁啊?\n"
f"🌟 先用 /s 报名,不然没法玩哦!",
sender
)
return
# 以下是原有的出题逻辑
task = game_question_json("请出题!")
category = task["category"]
question = task["question"]
answer = task["answer"]
score = int(task["score"])
description = task.get("description", "")
# 创建活跃任务
active_task_id = self.encyclopedia_db.create_active_task(
roomid, question, answer, score, description, sender
)
if not active_task_id:
await self.bot.send_text_message(
(roomid if roomid else sender),
f"😔 任务创建失败,请稍后再试!",
sender
)
return
await self.bot.send_text_message(
(roomid if roomid else sender),
f"🎁 {player_dict[sender]},你的专属任务闪亮登场!\n"
f"🎀 任务ID: {active_task_id}\n"
f"🎈 问题:[{category}]{question}\n"
f"🌼 积分:{score}\n"
f"🌈 快上答案:/a {active_task_id} 答案",
sender
)
except Exception as e:
self.LOG.error(f"获取任务出错: {e}")
await self.bot.send_text_message(
(roomid if roomid else sender),
f"😔 获取任务出错,请稍后再试!",
sender
)
@points_reward_decorator(calculate_game_points, "game", "百科答题奖励", Feature.TASK_GAME)
async def _handle_submit_answer(self, message: Dict[str, Any]) -> Tuple[bool, Optional[str]]:
"""处理提交答案请求"""
try:
content = str(message.get("content", "")).strip()
sender = message.get("sender")
roomid = message.get("roomid", "")
parts = content.split(" ", 2)
if len(parts) < 3:
await self.bot.send_text_message(
(roomid if roomid else sender),
f"😅 喂,格式不对啊!\n"
f"🌟 正确姿势:/a [任务ID] [答案]\n"
f"🎈 比如:/a 1 钒",
sender
)
return False, "0"
task_id = parts[1]
answer = parts[2]
# 获取玩家信息
player = self.encyclopedia_db.get_player(sender, roomid)
if not player:
await self.bot.send_text_message(
(roomid if roomid else sender),
f"😅 嘿,你是路人甲吗?\n"
f"🌟 用 /s 先加入群 {roomid} 吧!",
sender
)
return False, "0"
player_name = player['player_name']
if not task_id.isdigit():
await self.bot.send_text_message(
(roomid if roomid else sender),
f"😅 喂任务ID得是数字好吗\n"
f"🌟 比如1\n"
f"🎈 别瞎搞,重新来!",
sender
)
return False, "0"
active_task_id = int(task_id)
# 获取任务信息
task_data = self.encyclopedia_db.get_task_by_id(roomid, active_task_id)
if not task_data:
await self.bot.send_text_message(
(roomid if roomid else sender),
f"😔 哎哟,任务 task_{active_task_id} 不翼而飞啦!\n"
f"🌼 可能被别人抢先一步咯!",
sender
)
return False, "0"
if task_data['status'] == 'completed':
await self.bot.send_text_message(
(roomid if roomid else sender),
f"😄 哈哈,你慢了一步!\n"
f"🌟 任务 task_{active_task_id} 已经完结\n"
f"🎈 快去抢新任务吧!",
sender
)
return False, "0"
question = task_data['question']
correct_answer_db = task_data['answer'].lower()
top_score = task_data['score']
holder_id = task_data['holder_id']
# 获取任务持有者信息
holder = self.encyclopedia_db.get_task_holder(roomid, holder_id)
holder_name = holder['player_name'] if holder else "未知玩家"
answer_json = {"question": question, "top_score": str(top_score), "answer": answer}
result = game_answer_json(answer_json)
points = int(result["score"])
description = result["description"]
is_correct = points > 0
# 记录答题历史
self.encyclopedia_db.add_task_history(
roomid, active_task_id, sender, answer, is_correct, points
)
if is_correct:
# 完成任务
self.encyclopedia_db.complete_task(active_task_id)
if sender == holder_id:
await self.bot.send_text_message(
(roomid if roomid else sender),
f"🎉 {player_name} 你是天才吗?\n"
f"🌟 任务:{question}\n"
f"🎈 答对啦,简直无敌!\n"
f"🌈 奖励:{points}\n"
f"🎀 彩蛋:{description}",
sender
)
else:
await self.bot.send_text_message(
(roomid if roomid else sender),
f"🎉 {player_name} 抢答王上线!\n"
f"🌟 任务:{question}\n"
f"🎈 原主:{holder_name} 被你截胡啦!\n"
f"🌈 狂揽 {points} 分,太骚了!\n"
f"🎀 彩蛋:{description}",
sender
)
else:
# 扣除积分
self.encyclopedia_db.update_player_points(sender, roomid, -1)
points = -1
await self.bot.send_text_message(
(roomid if roomid else sender),
f"😅 {player_name} 你这是要笑死我吗?\n"
f"🌼 任务:{question}\n"
f"🎈 你答:{answer}\n"
f"🌟 正确答案:{correct_answer_db}\n"
f"🌈 扣 1 分,别哭哦!\n"
f"🎀 提示:{description}\n"
f"🌟 任务ID: {active_task_id} 还能抢救一下!",
sender
)
return True, str(points)
except Exception as e:
self.LOG.error(f"提交答案出错: {e}")
return False, "0"
async def _handle_show_rank(self, sender: str, roomid: str) -> None:
"""处理显示排行榜请求"""
try:
# 获取排行榜
ranks = self.encyclopedia_db.get_player_ranking(roomid, 10)
if not ranks:
await self.bot.send_text_message(
(roomid if roomid else sender),
f"😔 群 {roomid} 冷冷清清\n"
f"🌟 快来一起燥起来吧!",
sender
)
return
rank_text = f"🎉 群答题 {roomid} 排行榜Top 10来啦\n"
for i, row in enumerate(ranks, 1):
rank_text += f"🐓 {i}. {row['player_name']}: {row['points']}\n"
await self.bot.send_at_message(
(roomid if roomid else sender),
rank_text,
[sender]
)
except Exception as e:
self.LOG.error(f"显示排行榜出错: {e}")
await self.bot.send_text_message(
(roomid if roomid else sender),
f"😔 获取排行榜出错,请稍后再试!",
sender
)
async def _handle_show_active_tasks(self, sender: str, roomid: str) -> None:
"""处理显示活跃任务请求"""
try:
# 获取活跃任务
tasks = self.encyclopedia_db.get_active_tasks_in_group(roomid)
if not tasks:
await self.bot.send_text_message(
(roomid if roomid else sender),
f"😄 群 {roomid} 现在一片祥和\n"
f"🌟 没任务?快用 /t 搞一个!",
sender
)
return
task_text = f"🎉 群 {roomid} 活跃任务速递:\n"
for task in tasks:
task_text += (
f"🌈 任务ID: task_{task['active_task_id']}\n"
f"🎀 问题:{task['question']}\n"
f"🌼 大佬:{task['player_name']}\n"
)
await self.bot.send_text_message(
(roomid if roomid else sender),
task_text,
sender
)
except Exception as e:
self.LOG.error(f"显示活跃任务出错: {e}")
await self.bot.send_text_message(
(roomid if roomid else sender),
f"😔 获取活跃任务出错,请稍后再试!",
sender
)
async def _handle_list_uncompleted_tasks(self, sender: str, roomid: str) -> None:
"""处理列举未完成任务请求"""
try:
# 获取未完成任务
tasks = self.encyclopedia_db.get_active_tasks_in_group(roomid)
if not tasks:
await self.bot.send_text_message(
(roomid if roomid else sender),
f"😄 群 {roomid} 全员开挂?\n"
f"🌟 没未完成任务,快用 /t 再战!",
sender
)
return
task_text = f"🎉 群 {roomid} 未完成任务大曝光:\n"
for task in tasks:
task_text += (
f"🌈 任务ID: task_{task['active_task_id']}\n"
f"🎀 问题:{task['question']}\n"
f"🌼 主人:{task['player_name']}\n"
)
await self.bot.send_text_message(
(roomid if roomid else sender),
task_text,
sender
)
except Exception as e:
self.LOG.error(f"列举未完成任务出错: {e}")
await self.bot.send_text_message(
(roomid if roomid else sender),
f"😔 获取未完成任务出错,请稍后再试!",
sender
)
async def run_random_task_assignment(self) -> None:
"""定时任务整点触发排除23:00-08:00"""
current_hour = datetime.now().hour
if current_hour >= 23 or current_hour < 9:
self.LOG.info(f"当前时间 {current_hour}:00 在23:00-08:00区间跳过任务发放")
return
try:
# 获取所有群聊
groups = self.encyclopedia_db.get_all_groups()
for group in groups:
# 检查权限
if GroupBotManager.get_group_permission(group, Feature.TASK_GAME) == PermissionStatus.DISABLED:
continue
# 获取群内所有玩家
players = self.encyclopedia_db.get_all_players_in_group(group)
if not players:
continue
# 随机选择一个玩家
holder = random.choice(players)
holder_id = holder['player_id']
holder_name = holder['player_name']
# 创建任务
task = game_question_json("请出题!")
category = task["category"]
question = task["question"]
answer = task["answer"]
score = int(task["score"])
description = task.get("description", "")
# 创建活跃任务
active_task_id = self.encyclopedia_db.create_active_task(
group, question, answer, score, description, holder_id
)
if active_task_id:
await self.bot.send_at_message(
group,
f"🎁 新任务来袭,够不够刺激?\n"
f"🎀 任务ID: {active_task_id}\n"
f"🌟 幸运鹅:{holder_name}\n"
f"🎈 问题:[{category}]{question}\n"
f"🌼 积分:{score}\n"
f"🌈 抢答格式:/a {active_task_id} 答案",
[holder_id])
except Exception as e:
self.LOG.error(f"定时任务出错: {e}")