From 3b49e340e4fb92050509af8f8aaab4ee696760da Mon Sep 17 00:00:00 2001 From: liuwei Date: Thu, 10 Apr 2025 10:00:54 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=89=93=E5=8A=AB=E4=BF=9D?= =?UTF-8?q?=E9=87=8A=E5=8A=9F=E8=83=BD=20-=20=E6=89=93=E5=8A=AB=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=E5=90=8E=E8=87=AA=E5=8A=A8=E5=85=B3=E6=8A=BC24?= =?UTF-8?q?=E5=B0=8F=E6=97=B6=20-=20=E5=85=B6=E4=BB=96=E4=BA=BA=E5=8F=AF?= =?UTF-8?q?=E4=BB=A5=E4=BD=BF=E7=94=A8"=E4=BF=9D=E9=87=8A=20@=E7=94=A8?= =?UTF-8?q?=E6=88=B7"=E5=91=BD=E4=BB=A4=E8=8A=B1=E8=B4=B930=E7=A7=AF?= =?UTF-8?q?=E5=88=86=E4=BF=9D=E9=87=8A=20-=20=E5=9C=A8=E6=8A=BC=E6=9C=9F?= =?UTF-8?q?=E9=97=B4=E6=97=A0=E6=B3=95=E8=BF=9B=E8=A1=8C=E6=89=93=E5=8A=AB?= =?UTF-8?q?=20-=20=E4=BF=9D=E9=87=8A=E5=90=8E=E7=AB=8B=E5=8D=B3=E9=87=8A?= =?UTF-8?q?=E6=94=BE=20-=20=E6=89=80=E6=9C=89=E8=AE=B0=E5=BD=95=E9=83=BD?= =?UTF-8?q?=E4=BC=9A=E4=BF=9D=E5=AD=98=E5=9C=A8=E6=95=B0=E6=8D=AE=E5=BA=93?= =?UTF-8?q?=E4=B8=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- db/points_db.py | 90 ++++++++++++++++++++++++++++++++- plugins/point_trade/config.toml | 5 +- plugins/point_trade/main.py | 85 ++++++++++++++++++++++++++++--- 3 files changed, 170 insertions(+), 10 deletions(-) diff --git a/db/points_db.py b/db/points_db.py index 44de5fe..3ae6709 100644 --- a/db/points_db.py +++ b/db/points_db.py @@ -76,6 +76,23 @@ class PointsDBOperator(BaseDBOperator): ) ENGINE=InnoDB CHARACTER SET utf8mb4; """) + # 创建关禁闭记录表 + self.execute_update(""" + CREATE TABLE IF NOT EXISTS t_prison_records ( + id INTEGER PRIMARY KEY AUTO_INCREMENT, + user_id VARCHAR(100) NOT NULL, + group_id VARCHAR(100) NOT NULL, + start_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + end_time TIMESTAMP NOT NULL, + reason VARCHAR(255), + status TINYINT DEFAULT 1 COMMENT '1:在押 0:已释放', + bailout_user_id VARCHAR(100), + bailout_time TIMESTAMP, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + UNIQUE KEY `idx_user_group` (user_id, group_id, status) + ) ENGINE=InnoDB CHARACTER SET utf8mb4; + """) + self.logger.info("积分系统数据库表检查/创建完成") except Exception as e: self.logger.error(f"创建积分系统数据库表失败: {e}") @@ -227,7 +244,7 @@ class PointsDBOperator(BaseDBOperator): self.execute_update(""" UPDATE t_sign_record SET points = points + %s - WHERE wx_id = %s AND group_id = %s + WHERE wx_id = %s AND group__id = %s """, (points, user_id, group_id)) elif source == PointSource.GAME: self.execute_update(""" @@ -575,4 +592,73 @@ class PointsDBOperator(BaseDBOperator): return stats except Exception as e: self.logger.error(f"获取群组积分统计信息失败: {e}") - return stats \ No newline at end of file + return stats + + def imprison_user(self, user_id: str, group_id: str, hours: int = 24, reason: str = None) -> bool: + """关押用户 + Args: + user_id: 用户ID + group_id: 群组ID + hours: 关押时长(小时) + reason: 关押原因 + """ + try: + end_time = datetime.now() + timedelta(hours=hours) + self.execute_update(""" + INSERT INTO t_prison_records (user_id, group_id, end_time, reason) + VALUES (%s, %s, %s, %s) + ON DUPLICATE KEY UPDATE + start_time=CURRENT_TIMESTAMP, end_time=%s, reason=%s, status=1 + """, (user_id, group_id, end_time, reason, end_time, reason)) + return True + except Exception as e: + self.logger.error(f"关押用户失败: {e}") + return False + + def check_prison_status(self, user_id: str, group_id: str) -> Optional[Dict]: + """检查用户是否在押 + Returns: + None: 不在押 + Dict: 在押信息 + """ + try: + records = self.execute_query(""" + SELECT * FROM t_prison_records + WHERE user_id = %s AND group_id = %s AND status = 1 + AND end_time > CURRENT_TIMESTAMP + LIMIT 1 + """, (user_id, group_id)) + return records[0] if records else None + except Exception as e: + self.logger.error(f"检查用户在押状态失败: {e}") + return None + + def bailout_user(self, prisoner_id: str, bailout_user_id: str, group_id: str) -> Tuple[bool, str]: + """保释用户 + Returns: + (bool, str): (是否成功, 错误信息) + """ + try: + # 检查是否在押 + prison_record = self.check_prison_status(prisoner_id, group_id) + if not prison_record: + return False, "该用户未被关押" + + # 扣除保释金 + success, result = self.transfer_points( + bailout_user_id, "SYSTEM", group_id, 30, "保释金" + ) + if not success: + return False, result.get("error", "保释失败") + + # 释放用户 + self.execute_update(""" + UPDATE t_prison_records + SET status = 0, bailout_user_id = %s, bailout_time = CURRENT_TIMESTAMP + WHERE user_id = %s AND group_id = %s AND status = 1 + """, (bailout_user_id, prisoner_id, group_id)) + + return True, "保释成功" + except Exception as e: + self.logger.error(f"保释用户失败: {e}") + return False, f"保释失败: {str(e)}" \ No newline at end of file diff --git a/plugins/point_trade/config.toml b/plugins/point_trade/config.toml index 4272e9f..9c6b651 100644 --- a/plugins/point_trade/config.toml +++ b/plugins/point_trade/config.toml @@ -1,12 +1,13 @@ [PointTrade] enable = true -command = ["积分交易", "积分转账", "转账积分", "积分赠送", "赠送积分", "积分转移", "转移积分", "送积分", "积分送人", "送人积分", "积分赠予", "赠予", "我的积分", "积分排行", "打劫"] +command = ["积分交易", "积分转账", "转账积分", "积分赠送", "赠送积分", "积分转移", "转移积分", "送积分", "积分送人", "送人积分", "积分赠予", "赠予", "我的积分", "积分排行", "打劫","保释"] command-format = """ -🔄转账积分: +🔄积分交易指令: 积分转账 积分数 @用户 我的积分 - 查询个人积分详情 积分排行 - 查看群内积分排行榜 打劫 @用户 - 尝试打劫用户积分(有风险) +保释 @用户 - 花费30积分保释他人 """ # 打劫功能配置 diff --git a/plugins/point_trade/main.py b/plugins/point_trade/main.py index 28704f1..0e20140 100644 --- a/plugins/point_trade/main.py +++ b/plugins/point_trade/main.py @@ -71,13 +71,15 @@ class PointTradePlugin(MessagePluginInterface): # 从配置中获取参数 point_trade_config = self._config.get("PointTrade", {}) self._commands = point_trade_config.get("command", - ["积分交易", "积分转账", "转账积分", "我的积分", "积分排行", "打劫"]) + ["积分交易", "积分转账", "转账积分", + "我的积分", "积分排行", "打劫", "保释"]) self.command_format = point_trade_config.get("command-format", """ 积分交易指令: 积分转账 积分数 @用户 - 转账给指定用户 我的积分 - 查询个人积分详情 积分排行 - 查看群内积分排行榜 打劫 @用户 - 尝试打劫用户积分(有风险) +保释 @用户 - 花费30积分保释他人 """) self.enable = point_trade_config.get("enable", True) @@ -141,6 +143,8 @@ class PointTradePlugin(MessagePluginInterface): return self._handle_points_ranking(message) elif command[0] == "打劫": return self._handle_rob_points(message) + elif command[0] == "保释": + return self._handle_bailout(message) elif command[0] in self._commands: return self._handle_transfer_points(message) else: @@ -551,10 +555,17 @@ class PointTradePlugin(MessagePluginInterface): wcf.send_text(f"❌打劫过程中出现问题:{result.get('error', '未知错误')}", roomid, sender) return True, "打劫失败" else: - # 打劫失败,扣除打劫者一定比例的积分作为惩罚 - penalty_amount = int(robber_total * self.rob_penalty_percent) + # 检查是否在押 + prison_status = self.points_db.check_prison_status(sender, roomid) + if prison_status: + remaining_time = prison_status['end_time'] - datetime.now() + hours = int(remaining_time.total_seconds() / 3600) + minutes = int((remaining_time.total_seconds() % 3600) / 60) + wcf.send_text(f"❌你正在服刑!\n剩余时间: {hours}小时{minutes}分钟\n可请求他人花费30积分保释。", roomid, sender) + return True, "在押状态" - # 确保至少扣除1点积分 + # 打劫失败处理 + penalty_amount = int(robber_total * self.rob_penalty_percent) penalty_amount = max(1, penalty_amount) # 记录积分变动 @@ -564,14 +575,22 @@ class PointTradePlugin(MessagePluginInterface): ) if success: + # 关押处理 + self.points_db.imprison_user( + robber_wxid, roomid, 24, + f"打劫{target_name}失败被捕" + ) + # 获取转账后的积分信息 from_user = result.get("from_user", {}) to_user = result.get("to_user", {}) + # 构建打劫失败消息 output = ( f"🚨 打劫失败!\n" - f"👤{robber_name} 试图打劫 👤{target_name} 但被当场抓获,并赔款!\n" - f"👮‍♂️ 被罚款 {penalty_amount} 积分!\n" + f"👤{robber_name} 试图打劫 👤{target_name} 但被当场抓获!\n" + f"👮‍♂️ 被罚款 {penalty_amount} 积分并关押24小时!\n" + f"💰 可请求他人花费30积分进行保释\n" f"👤{robber_name} 当前积分: {from_user.get('total_points', 0)}" ) @@ -585,3 +604,57 @@ class PointTradePlugin(MessagePluginInterface): self.LOG.error(f"处理打劫请求出错: {e}") wcf.send_text(f"❌打劫过程中出现意外:{str(e)}", roomid, sender) return True, f"处理出错: {str(e)}" + + def _handle_bailout(self, message: Dict[str, Any]) -> Tuple[bool, Optional[str]]: + """处理保释命令""" + sender = message.get("sender") + roomid = message.get("roomid", "") + wcf: Wcf = message.get("wcf") + xml = message.get("xml", "") + + # 检查是否在群聊中 + if not roomid: + wcf.send_text("❌保释功能仅在群聊中可用!", sender, "") + return True, "非群聊环境" + + # 检查@用户是否有效 + at_users = self.at_list(xml) + if len(at_users) != 1: + wcf.send_text(f"保释失败❌\n请指定一个保释目标!\n保释 @用户", + roomid, sender) + return True, "目标无效" + + prisoner_wxid = next(iter(at_users)) + bailout_wxid = sender + + # 不能保释自己 + if prisoner_wxid == bailout_wxid: + wcf.send_text("❌你不能保释自己!", roomid, sender) + return True, "不能保释自己" + + try: + # 获取用户昵称 + prisoner_info = self._get_user_record(prisoner_wxid, roomid) + bailout_info = self._get_user_record(bailout_wxid, roomid) + + prisoner_name = prisoner_info.get('wx_nick_name', prisoner_wxid) if prisoner_info else prisoner_wxid + bailout_name = bailout_info.get('wx_nick_name', bailout_wxid) if bailout_info else bailout_wxid + + # 执行保释 + success, message = self.points_db.bailout_user(prisoner_wxid, bailout_wxid, roomid) + + if success: + output = ( + f"✅ 保释成功!\n" + f"👤{bailout_name} 花费30积分保释了 👤{prisoner_name}" + ) + wcf.send_text(output, roomid, sender) + return True, "保释成功" + else: + wcf.send_text(f"❌保释失败: {message}", roomid, sender) + return True, "保释失败" + + except Exception as e: + self.LOG.error(f"处理保释请求出错: {e}") + wcf.send_text(f"❌保释过程中出现意外:{str(e)}", roomid, sender) + return True, f"处理出错: {str(e)}"