Compare commits
16 Commits
task/user-
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| a70a53383d | |||
| 79924a713d | |||
| ed6406cfc9 | |||
| 3d89dbf8f4 | |||
| 97692b120a | |||
| c7a4d3d047 | |||
| 58e6ee851c | |||
| aef45eb9a4 | |||
| 8eeec67730 | |||
| 6c2227debe | |||
|
|
7c4d0a0ef2 | ||
| 4027771a65 | |||
|
|
9ed8fffcf7 | ||
| bcf93e910a | |||
| 8487e6e931 | |||
| aaff6cee86 |
@@ -454,7 +454,25 @@ app.include_router(private.router, prefix="/api", tags=["private"])
|
||||
- 阻碍因素:
|
||||
无
|
||||
|
||||
- 状态:未确认
|
||||
- 状态:成功
|
||||
|
||||
[2025-11-03_后续]
|
||||
- 已修改:
|
||||
1. utils/parser.py - 添加.talk和.私聊指令映射
|
||||
2. routers/callback.py - 添加handle_talk_command函数实现私聊指令
|
||||
|
||||
- 更改:
|
||||
1. 添加.talk <username> <content>指令,允许用户通过用户名发送私聊消息
|
||||
2. 实现用户名和URL验证,确保目标用户已注册名称和个人URL
|
||||
3. 私聊消息发送成功时不向主URL发送提示消息,保持私密性
|
||||
|
||||
- 原因:
|
||||
实现用户可用的私聊功能,作为私聊功能的开始
|
||||
|
||||
- 阻碍因素:
|
||||
无
|
||||
|
||||
- 状态:成功(测试通过)
|
||||
|
||||
# 最终审查
|
||||
|
||||
|
||||
395
.tasks/2025-11-03_2_werewolf-game.md
Normal file
395
.tasks/2025-11-03_2_werewolf-game.md
Normal file
@@ -0,0 +1,395 @@
|
||||
# 背景
|
||||
文件名:2025-11-03_2_werewolf-game.md
|
||||
创建于:2025-11-03_12:20:10
|
||||
创建者:admin
|
||||
主分支:main
|
||||
任务分支:task/werewolf_2025-11-03_1
|
||||
Yolo模式:Off
|
||||
|
||||
# 任务描述
|
||||
在WPS Bot Game项目中添加狼人杀游戏系统,支持6-12人游戏,包含身份分配、私聊功能、技能使用等核心功能。
|
||||
|
||||
## 核心需求
|
||||
1. 支持6-12人狼人杀游戏(配置:2-4狼 1预言家 1女巫 2-6平民)
|
||||
2. 主持人开房:`.狼人杀 open`
|
||||
3. 玩家加入:`.狼人杀 join`(必须注册用户名和个人URL)
|
||||
4. 开始游戏:`.狼人杀 start`,自动分配身份并通过私聊发送
|
||||
5. 私聊功能:`.狼人杀 <玩家代号> <消息>`
|
||||
6. 狼人群聊:`.狼人杀 狼人 <消息>`
|
||||
7. 技能系统:杀、验、救、毒
|
||||
8. 游戏状态查询:`.狼人杀 status`
|
||||
9. 结束游戏:`.狼人杀 end`
|
||||
|
||||
## 游戏规则
|
||||
**人数配置**:
|
||||
- 6人:2狼 1预言家 1女巫 2平民
|
||||
- 8人:2狼 1预言家 1女巫 4平民
|
||||
- 10人:3狼 1预言家 1女巫 5平民
|
||||
- 12人:4狼 1预言家 1女巫 6平民
|
||||
|
||||
**胜利条件**:
|
||||
- 狼人阵营:杀死所有神职和平民
|
||||
- 好人阵营:消灭所有狼人
|
||||
|
||||
**技能**:
|
||||
- 狼人:每晚投票刀人
|
||||
- 预言家:每晚查验一个玩家身份
|
||||
- 女巫:拥有一瓶解药(仅可使用一次)和一瓶毒药(仅可使用一次)
|
||||
- 平民:无特殊技能
|
||||
|
||||
# 项目概览
|
||||
|
||||
## 项目结构
|
||||
```
|
||||
WPSBotGame/
|
||||
├── app.py # FastAPI主应用
|
||||
├── config.py # 配置管理
|
||||
├── core/
|
||||
│ ├── database.py # SQLite数据库操作
|
||||
│ ├── middleware.py # 中间件
|
||||
│ └── models.py # 数据模型
|
||||
├── routers/
|
||||
│ ├── callback.py # Callback路由处理
|
||||
│ ├── health.py # 健康检查
|
||||
│ └── private.py # 私聊相关API
|
||||
├── games/ # 游戏模块
|
||||
│ ├── werewolf.py # 狼人杀游戏(新增)
|
||||
│ └── ... # 其他游戏
|
||||
└── utils/
|
||||
├── parser.py # 指令解析
|
||||
└── message.py # 消息发送
|
||||
```
|
||||
|
||||
# 分析
|
||||
|
||||
## 当前状态
|
||||
1. 已有私聊功能支持,用户可注册个人webhook URL
|
||||
2. 已有游戏架构:BaseGame基类、数据库状态管理
|
||||
3. 已有成语接龙等多人类游戏参考
|
||||
4. 数据库支持game_states表存储游戏状态
|
||||
|
||||
## 关键技术点
|
||||
1. **数据库层**:
|
||||
- 使用game_states表存储游戏状态(user_id=0表示群级别状态)
|
||||
- 通过state_data JSON字段存储玩家列表、身份、阶段等信息
|
||||
|
||||
2. **私聊系统**:
|
||||
- 利用现有的send_private_message函数
|
||||
- 身份信息、技能结果等通过私聊发送
|
||||
- 支持发送者标识显示
|
||||
|
||||
3. **游戏状态管理**:
|
||||
- 游戏状态存储在state_data中
|
||||
- 包含:玩家列表、身份映射、狼人列表、技能使用记录等
|
||||
|
||||
4. **技能系统**:
|
||||
- 狼人刀人:投票机制
|
||||
- 预言家验人:私聊返回结果
|
||||
- 女巫用药:限制使用次数
|
||||
|
||||
5. **指令路由**:
|
||||
- 在parser.py注册.werewolf和.狼人杀指令
|
||||
- 在callback.py中导入并注册游戏处理器
|
||||
|
||||
# 提议的解决方案
|
||||
|
||||
## 方案概述
|
||||
1. **创建狼人杀游戏类**:`games/werewolf.py`,继承BaseGame
|
||||
2. **状态数据结构**:使用JSON存储在state_data中
|
||||
3. **身份分配**:随机分配角色,狼人互相认识
|
||||
4. **私聊通知**:游戏开始时通过私聊发送身份信息
|
||||
5. **技能系统**:支持杀、验、救、毒四种技能
|
||||
6. **指令注册**:添加解析和路由支持
|
||||
|
||||
## 设计决策
|
||||
- 使用user_id=0存储群级别游戏状态(参考成语接龙)
|
||||
- 通过私聊发送敏感信息(身份、技能结果)
|
||||
- 简化实现:主持人手动推进阶段(暂不实现自动流转)
|
||||
- 使用数字代号(1-N)标识玩家
|
||||
- 支持狼人群聊功能
|
||||
|
||||
# 当前执行步骤:"实施完成"
|
||||
|
||||
# 详细实施计划
|
||||
|
||||
## 文件1: games/werewolf.py(新建文件)
|
||||
|
||||
### 主要方法
|
||||
1. **handle()** - 主处理逻辑,指令路由
|
||||
2. **get_help()** - 帮助信息
|
||||
3. **_open_game()** - 主持人开房
|
||||
4. **_join_game()** - 玩家加入
|
||||
5. **_start_game()** - 开始游戏,分配身份
|
||||
6. **_send_identities()** - 私聊发送身份信息
|
||||
7. **_private_chat()** - 玩家私聊
|
||||
8. **_wolf_group_chat()** - 狼人群聊
|
||||
9. **_handle_skill()** - 技能处理
|
||||
10. **_wolf_kill()** - 狼人刀人
|
||||
11. **_seer_check()** - 预言家验人
|
||||
12. **_witch_save()** - 女巫救人
|
||||
13. **_witch_poison()** - 女巫毒人
|
||||
14. **_show_status()** - 显示游戏状态
|
||||
15. **_end_game()** - 结束游戏
|
||||
|
||||
### 数据结构设计
|
||||
```python
|
||||
state_data = {
|
||||
'creator_id': int, # 主持人ID
|
||||
'status': str, # 'open', 'playing', 'finished'
|
||||
'players': [
|
||||
{
|
||||
'user_id': int,
|
||||
'name': str, # 注册的用户名
|
||||
'id': int, # 游戏内代号 1-N
|
||||
'role': str, # 'wolf', 'seer', 'witch', 'civilian'
|
||||
'alive': bool,
|
||||
'id_label': str # "1号玩家"
|
||||
}
|
||||
],
|
||||
'phase': str, # 当前阶段
|
||||
'round': int, # 当前回合数
|
||||
'wolves': [int], # 狼人ID列表
|
||||
'kill_target': int, # 狼人票决目标
|
||||
'seer_result': {}, # 预言家验人结果
|
||||
'witch_save': bool, # 女巫是否救人
|
||||
'witch_poison': int, # 女巫毒杀目标
|
||||
'discussed': False, # 讨论阶段是否完成
|
||||
'wolf_know_each_other': False
|
||||
}
|
||||
```
|
||||
|
||||
## 文件2: utils/parser.py
|
||||
|
||||
### 修改点:添加指令映射
|
||||
在COMMAND_MAP中添加:
|
||||
```python
|
||||
'.werewolf': 'werewolf',
|
||||
'.狼人杀': 'werewolf',
|
||||
```
|
||||
|
||||
## 文件3: routers/callback.py
|
||||
|
||||
### 修改点:添加路由处理
|
||||
在handle_command函数中添加:
|
||||
```python
|
||||
# 狼人杀系统
|
||||
if game_type == 'werewolf':
|
||||
from games.werewolf import WerewolfGame
|
||||
game = WerewolfGame()
|
||||
return await game.handle(command, chat_id, user_id)
|
||||
```
|
||||
|
||||
## 文件4: games/base.py
|
||||
|
||||
### 修改点:添加帮助信息
|
||||
在get_help_message()函数中添加狼人杀帮助说明
|
||||
|
||||
# 任务进度
|
||||
|
||||
[2025-11-03_12:20:10]
|
||||
- 已修改:
|
||||
1. games/werewolf.py - 新建狼人杀游戏类,实现所有核心功能
|
||||
2. utils/parser.py - 添加.werewolf和.狼人杀指令映射
|
||||
3. routers/callback.py - 添加狼人杀路由处理
|
||||
4. games/base.py - 添加狼人杀帮助信息
|
||||
|
||||
- 更改:
|
||||
1. 创建完整的狼人杀游戏系统
|
||||
2. 支持开房、加入、开始、私聊、技能使用等所有核心功能
|
||||
3. 实现6-12人游戏配置和角色分配
|
||||
4. 集成私聊系统发送身份信息
|
||||
5. 支持狼人群聊功能
|
||||
6. 添加帮助信息和指令注册
|
||||
|
||||
- 原因:
|
||||
实现完整的狼人杀游戏系统,支持多人游戏、身份隐藏、技能使用等核心功能
|
||||
|
||||
- 阻碍因素:
|
||||
无
|
||||
|
||||
- 状态:成功
|
||||
|
||||
[2025-11-04_17:41:14]
|
||||
- 已修改:
|
||||
1. games/werewolf.py - 改进阶段提示和自动流转功能
|
||||
|
||||
- 更改:
|
||||
1. 添加阶段名称映射系统(phase_configs),定义各阶段的中文名称、行动角色和指令说明
|
||||
2. 实现阶段管理方法:_get_phase_description()、_get_next_phase()、_advance_phase()
|
||||
3. 改进游戏开始提示,明确显示"第一夜 - 狼人行动阶段"和操作指令
|
||||
4. 实现自动阶段流转:狼人刀人后自动进入预言家阶段,预言家验人后自动进入女巫阶段
|
||||
5. 新增女巫跳过功能:支持`.werewolf 跳过`指令,女巫可以选择不行动
|
||||
6. 改进状态显示:_show_status()现在显示中文阶段名称、当前行动角色和操作指令
|
||||
7. 更新身份说明和帮助信息,添加女巫跳过选项说明
|
||||
8. 各技能方法添加阶段验证,确保在正确的阶段使用技能
|
||||
|
||||
- 原因:
|
||||
解决用户反馈的游戏阶段不明显的问题,让玩家清楚知道当前是什么阶段、谁应该行动、下一步是什么阶段
|
||||
|
||||
- 阻碍因素:
|
||||
无
|
||||
|
||||
- 状态:成功
|
||||
|
||||
[2025-11-07_10:59:09]
|
||||
- 已修改:
|
||||
1. games/werewolf.py - 支持在私聊中使用狼人杀技能(方案2实施)
|
||||
|
||||
- 更改:
|
||||
1. 新增 _find_player_game(user_id) 方法,根据玩家ID查找其参与的游戏
|
||||
2. 修改 _handle_skill() 方法,支持从私聊中使用技能指令
|
||||
3. 修改 _wolf_group_chat() 方法,支持从私聊中发送狼人群聊
|
||||
4. 修改 _private_chat() 方法,支持从私聊中发送玩家私聊
|
||||
5. 修改 _witch_pass() 方法,支持从私聊中跳过女巫行动
|
||||
6. 添加日志输出,显示在私聊中使用功能的情况
|
||||
7. 实现逻辑:先尝试用当前chat_id查找游戏(群聊场景),找不到则通过user_id查找玩家游戏(私聊场景)
|
||||
|
||||
- 原因:
|
||||
解决私聊中无法使用技能的问题。游戏在群里创建,但玩家需要在私聊中使用技能以保密。
|
||||
之前的设计只能在游戏所在群使用技能,现在支持在私聊中使用,查找玩家参与的游戏并操作。
|
||||
|
||||
- 阻碍因素:
|
||||
无
|
||||
|
||||
- 状态:成功
|
||||
|
||||
[2025-11-07_11:06:58]
|
||||
- 已修改:
|
||||
1. games/werewolf.py - 改为全局唯一游戏模式(不再按chat_id区分)
|
||||
|
||||
- 更改:
|
||||
1. 修改 _get_game_state() 方法,查询全局唯一游戏而非根据chat_id查询
|
||||
2. 新增 _get_game_chat_id() 方法,获取全局游戏所在的chat_id
|
||||
3. 简化 _find_player_game() 方法,使用全局游戏查询
|
||||
4. 修改 _open_game() 方法,检查全局是否已有游戏(而非仅检查当前群)
|
||||
5. 简化所有需要查找玩家游戏的方法(_handle_skill、_wolf_group_chat、_private_chat、_witch_pass)
|
||||
6. 保持数据库兼容性:chat_id列仍然存在并记录游戏创建的群,但查询时忽略
|
||||
7. 实现逻辑:所有查询都获取全局最新的一个狼人杀游戏,不再区分群组
|
||||
|
||||
- 原因:
|
||||
Bot全局只需要一个狼人杀游戏,不同群的玩家可以参与同一个游戏。
|
||||
简化逻辑,消除按chat_id区分的复杂性,同时保持数据库结构兼容。
|
||||
|
||||
- 阻碍因素:
|
||||
无
|
||||
|
||||
- 状态:成功
|
||||
|
||||
[2025-11-07_11:13:56]
|
||||
- 已修改:
|
||||
1. games/werewolf.py - 改进狼人投票机制
|
||||
|
||||
- 更改:
|
||||
1. 在游戏状态数据中添加 wolf_votes 字段,记录每个狼人的投票
|
||||
2. 修改 _wolf_kill() 方法,实现完整的投票流程:
|
||||
- 记录每个狼人的投票(支持改票)
|
||||
- 检查是否所有存活狼人都已投票
|
||||
- 未全部投票时提示等待其他狼人
|
||||
- 全部投票后统计票数
|
||||
- 票数唯一时确定目标并推进阶段
|
||||
- 平票时清除投票记录并要求重新投票
|
||||
3. 优化投票提示信息,显示投票进度和结果
|
||||
|
||||
- 原因:
|
||||
解决之前"只要一个狼人投票就立即刀人"的问题。
|
||||
现在要求所有狼人都投票,统计票数最多的目标,平票则重新投票,符合狼人杀游戏规则。
|
||||
|
||||
- 阻碍因素:
|
||||
无
|
||||
|
||||
- 状态:成功
|
||||
|
||||
[2025-11-07_11:22:53]
|
||||
- 已修改:
|
||||
1. games/werewolf.py - 狼人投票结果保密处理
|
||||
|
||||
- 更改:
|
||||
1. 修改狼人投票反馈机制,不在群里播报投票目标
|
||||
2. 单个狼人投票时,通过私聊确认投票,群消息只显示"投票已记录"
|
||||
3. 投票平票时,通过私聊通知狼人具体平票目标,群消息只显示"平票"
|
||||
4. 投票完成时,通过私聊通知所有狼人击杀目标,群消息只显示"投票完成"
|
||||
5. 所有敏感信息(投票目标、平票详情、击杀决定)均通过私聊发送给狼人
|
||||
|
||||
- 原因:
|
||||
符合狼人杀游戏规则,狼人刀人的决定应该保密,不能在群里公开播报。
|
||||
只有狼人自己知道投票情况和击杀目标,其他玩家在天亮时才知道结果。
|
||||
|
||||
- 阻碍因素:
|
||||
无
|
||||
|
||||
- 状态:成功
|
||||
|
||||
[2025-11-07_11:40:44]
|
||||
- 已修改:
|
||||
1. games/werewolf.py - 新增空刀机制
|
||||
|
||||
- 更改:
|
||||
1. 允许狼人投票给0号(表示空刀,不杀人)
|
||||
2. 修改 _wolf_kill() 方法,对target_id=0不验证目标存在性
|
||||
3. 修改投票确认消息,区分空刀和正常投票
|
||||
4. 修改票数统计逻辑,投票0不计入击杀目标统计
|
||||
5. 新增全部空刀处理:如果所有狼人都空刀,kill_target设为0(平安夜)
|
||||
6. 修改 _advance_phase() 为async,进入女巫阶段时私聊通知女巫刀人情况
|
||||
7. 女巫有解药时可知道今晚是否有人被刀(0号为平安夜)
|
||||
|
||||
- 原因:
|
||||
符合狼人杀游戏规则,狼人可以选择空刀(不杀人)。
|
||||
女巫在有解药时需要知道今晚是否有人被刀以决定是否使用解药。
|
||||
|
||||
- 阻碍因素:
|
||||
无
|
||||
|
||||
- 状态:成功
|
||||
|
||||
[2025-11-10_10:20:38]
|
||||
- 已修改:
|
||||
1. games/werewolf.py - 调整status指令的房间名单展示
|
||||
|
||||
- 更改:
|
||||
1. 房间开放阶段现在显示已加入玩家的房内ID与用户名
|
||||
2. 游戏进行阶段的玩家状态显示同时包含房内ID和用户名
|
||||
|
||||
- 原因:
|
||||
提升`.werewolf status`指令提供的信息量,方便玩家识别房间成员
|
||||
|
||||
- 阻碍因素:
|
||||
无
|
||||
|
||||
- 状态:未确认
|
||||
|
||||
[2025-11-10_10:27:07]
|
||||
- 已修改:
|
||||
1. games/werewolf.py - 统一狼人投票记录的键类型
|
||||
|
||||
- 更改:
|
||||
1. `_wolf_kill()` 读取和保存 `wolf_votes` 时转换为字符串键
|
||||
2. 统计投票进度时将键重新转换为整数,确保与 `alive_wolves` 对齐
|
||||
|
||||
- 原因:
|
||||
修复狼人全部投票后仍提示有人未投票的问题
|
||||
|
||||
- 阻碍因素:
|
||||
无
|
||||
|
||||
- 状态:未确认
|
||||
|
||||
[2025-11-10_10:36:39]
|
||||
- 已修改:
|
||||
1. games/werewolf.py - 修复狼人投票流程与阶段推进
|
||||
|
||||
- 更改:
|
||||
1. `_wolf_kill()` 读取 `wolf_votes` 时统一转换为整数键,存储与统计均使用整数
|
||||
2. `_wolf_kill()`、`_seer_check()`、`_witch_save()`、`_witch_poison()`、`_witch_pass()` 中的 `_advance_phase` 调用改为 `await`
|
||||
|
||||
- 原因:
|
||||
修复狼人投票完成后仍判定未投票、平安夜提示错误及阶段推进信息显示 `<coroutine>` 的问题
|
||||
|
||||
- 阻碍因素:
|
||||
无
|
||||
|
||||
- 状态:未确认
|
||||
|
||||
# 最终审查
|
||||
|
||||
待审查阶段完成...
|
||||
|
||||
@@ -23,12 +23,12 @@ class AlchemyGame(BaseGame):
|
||||
self.prize_pool: List[Tuple[int, str, float, str]] = [
|
||||
# (权重, 类型, 倍率, 描述)
|
||||
(500, "penalty", 0, "炼金失败"),
|
||||
(100, "penalty", -1, "炼金爆炸"),
|
||||
(100, "points", 0.1, "少量积分"),
|
||||
(160, "penalty", -1, "炼金爆炸"),
|
||||
(110, "points", 0.1, "少量积分"),
|
||||
(390, "points", 0.5, "少量积分"),
|
||||
(500, "points", 1, "等值积分"),
|
||||
(390, "points", 2, "丰厚积分"),
|
||||
(200, "points", 5, "丰厚积分"),
|
||||
(136, "points", 5, "丰厚积分"),
|
||||
(9, "points", 10, "🌟 巨额积分"),
|
||||
(1, "points", 100, "💎 传说积分"),
|
||||
]
|
||||
|
||||
@@ -138,6 +138,18 @@ def get_help_message() -> str:
|
||||
- `.赌场 21点 settle` - 庄家结算
|
||||
- `.赌场 21点 cancel` - 庄家放弃游戏(返还下注)
|
||||
|
||||
### 🐺 狼人杀
|
||||
- `.狼人杀 open` - 主持人创建房间
|
||||
- `.狼人杀 join` - 加入游戏
|
||||
- `.狼人杀 start` - 主持人开始游戏
|
||||
- `.狼人杀 <id> <消息>` - 私聊指定玩家
|
||||
- `.狼人杀 狼人 <消息>` - 狼人群聊
|
||||
- `.狼人杀 杀 <id>` - 狼人投票杀人
|
||||
- `.狼人杀 验 <id>` - 预言家验人
|
||||
- `.狼人杀 救 <id>` - 女巫救人
|
||||
- `.狼人杀 毒 <id>` - 女巫毒人
|
||||
- `.狼人杀 status` - 查看状态
|
||||
|
||||
### 其他
|
||||
- `.help` - 显示帮助
|
||||
- `.stats` - 查看个人统计
|
||||
|
||||
@@ -91,9 +91,6 @@ class GiftGame(BaseGame):
|
||||
if points <= 0:
|
||||
return "❌ 赠送积分数量必须大于0!"
|
||||
|
||||
if points > 1000:
|
||||
return "❌ 单次赠送积分不能超过1000!"
|
||||
|
||||
if sender_id == receiver_id:
|
||||
return "❌ 不能赠送积分给自己!"
|
||||
|
||||
|
||||
1261
games/werewolf.py
Normal file
1261
games/werewolf.py
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
"""Callback路由处理"""
|
||||
import logging
|
||||
import re
|
||||
from fastapi import APIRouter, Request
|
||||
from fastapi.responses import JSONResponse
|
||||
|
||||
@@ -48,6 +49,15 @@ async def callback_receive(request: Request):
|
||||
game_type, command = parse_result
|
||||
logger.info(f"识别指令: game_type={game_type}, command={command}")
|
||||
|
||||
# 检查是否包含 @s 参数(私聊标志)
|
||||
use_private_url = False
|
||||
# 使用正则表达式匹配独立的 @s 参数(前后有空格或字符串边界)
|
||||
if re.search(r'\s+@s\s+|\s+@s$|^@s\s+|^@s$', command):
|
||||
use_private_url = True
|
||||
# 从命令中移除 @s 参数,保持其他参数不变
|
||||
command = re.sub(r'\s+@s(\s+|$)|^@s\s+', ' ', command).strip()
|
||||
logger.info(f"检测到 @s 参数,将优先使用个人URL发送反馈,清理后的命令: {command}")
|
||||
|
||||
# 检查限流
|
||||
rate_limiter = get_rate_limiter()
|
||||
if not rate_limiter.is_allowed():
|
||||
@@ -75,21 +85,75 @@ async def callback_receive(request: Request):
|
||||
|
||||
# 发送回复
|
||||
if response_text:
|
||||
sender = get_message_sender()
|
||||
|
||||
# AI 对话:统一按 Markdown 发送(按任务决策)
|
||||
if game_type == 'ai_chat':
|
||||
try:
|
||||
await sender.send_markdown(response_text)
|
||||
except Exception as send_md_err:
|
||||
logger.error(f"发送Markdown消息失败,改用文本发送: {send_md_err}")
|
||||
await sender.send_text(response_text)
|
||||
else:
|
||||
# 其他模块保持原有启发式:以 # 开头视为 Markdown,否则文本
|
||||
if response_text.startswith('#'):
|
||||
await sender.send_markdown(response_text)
|
||||
# 如果使用了 @s 参数,优先发送到个人URL
|
||||
if use_private_url:
|
||||
db = get_db()
|
||||
user_webhook_url = db.get_user_webhook_url(callback_data.creator)
|
||||
|
||||
if user_webhook_url:
|
||||
# 有个人URL,发送到个人URL
|
||||
from utils.message import send_private_message
|
||||
# 判断消息类型
|
||||
if game_type == 'ai_chat':
|
||||
msg_type = 'markdown'
|
||||
elif response_text.startswith('#'):
|
||||
msg_type = 'markdown'
|
||||
else:
|
||||
msg_type = 'text'
|
||||
|
||||
success = await send_private_message(
|
||||
user_id=callback_data.creator,
|
||||
content=response_text,
|
||||
msg_type=msg_type
|
||||
)
|
||||
if not success:
|
||||
# 如果私聊发送失败,回退到主URL
|
||||
logger.warning(f"个人URL发送失败,回退到主URL: user_id={callback_data.creator}")
|
||||
sender = get_message_sender()
|
||||
if game_type == 'ai_chat':
|
||||
try:
|
||||
await sender.send_markdown(response_text)
|
||||
except Exception as send_md_err:
|
||||
logger.error(f"发送Markdown消息失败,改用文本发送: {send_md_err}")
|
||||
await sender.send_text(response_text)
|
||||
else:
|
||||
if response_text.startswith('#'):
|
||||
await sender.send_markdown(response_text)
|
||||
else:
|
||||
await sender.send_text(response_text)
|
||||
# 成功发送到个人URL,不向主URL发送
|
||||
else:
|
||||
await sender.send_text(response_text)
|
||||
# 没有个人URL,回退到主URL
|
||||
logger.info(f"用户 {callback_data.creator} 没有注册个人URL,使用主URL发送")
|
||||
sender = get_message_sender()
|
||||
if game_type == 'ai_chat':
|
||||
try:
|
||||
await sender.send_markdown(response_text)
|
||||
except Exception as send_md_err:
|
||||
logger.error(f"发送Markdown消息失败,改用文本发送: {send_md_err}")
|
||||
await sender.send_text(response_text)
|
||||
else:
|
||||
if response_text.startswith('#'):
|
||||
await sender.send_markdown(response_text)
|
||||
else:
|
||||
await sender.send_text(response_text)
|
||||
else:
|
||||
# 没有 @s 参数,正常发送到主URL
|
||||
sender = get_message_sender()
|
||||
|
||||
# AI 对话:统一按 Markdown 发送(按任务决策)
|
||||
if game_type == 'ai_chat':
|
||||
try:
|
||||
await sender.send_markdown(response_text)
|
||||
except Exception as send_md_err:
|
||||
logger.error(f"发送Markdown消息失败,改用文本发送: {send_md_err}")
|
||||
await sender.send_text(response_text)
|
||||
else:
|
||||
# 其他模块保持原有启发式:以 # 开头视为 Markdown,否则文本
|
||||
if response_text.startswith('#'):
|
||||
await sender.send_markdown(response_text)
|
||||
else:
|
||||
await sender.send_text(response_text)
|
||||
|
||||
return JSONResponse({"result": "ok"})
|
||||
|
||||
@@ -218,6 +282,12 @@ async def handle_command(game_type: str, command: str,
|
||||
game = CasinoGame()
|
||||
return await game.handle(command, chat_id, user_id)
|
||||
|
||||
# 狼人杀系统
|
||||
if game_type == 'werewolf':
|
||||
from games.werewolf import WerewolfGame
|
||||
game = WerewolfGame()
|
||||
return await game.handle(command, chat_id, user_id)
|
||||
|
||||
# 未知游戏类型
|
||||
logger.warning(f"未知游戏类型: {game_type}")
|
||||
return "❌ 未知的游戏类型"
|
||||
|
||||
2
start_background.sh
Normal file → Executable file
2
start_background.sh
Normal file → Executable file
@@ -20,7 +20,7 @@ fi
|
||||
echo "正在启动LiuBaiBlog网站服务器..."
|
||||
|
||||
# 使用nohup在后台运行
|
||||
nohup python3 app.py > "$LOG_FILE" 2>&1 &
|
||||
nohup venv/bin/python3 -m jurigged -v app.py > "$LOG_FILE" 2>&1 &
|
||||
PID=$!
|
||||
|
||||
# 保存PID
|
||||
|
||||
0
stop_background.sh
Normal file → Executable file
0
stop_background.sh
Normal file → Executable file
@@ -88,6 +88,10 @@ class CommandParser:
|
||||
# 赌场系统
|
||||
'.赌场': 'casino',
|
||||
'.casino': 'casino',
|
||||
|
||||
# 狼人杀系统
|
||||
'.werewolf': 'werewolf',
|
||||
'.狼人杀': 'werewolf',
|
||||
}
|
||||
|
||||
# 机器人名称模式(用于从@消息中提取)
|
||||
@@ -113,9 +117,9 @@ class CommandParser:
|
||||
|
||||
# 拦截全角空格与全角标点(不允许)
|
||||
# 范围包含:全角空格\u3000、全角标点\uFF01-\uFF60、兼容区\uFFE0-\uFFEE
|
||||
if re.search(r"[\u3000\uFF01-\uFF60\uFFE0-\uFFEE]", content):
|
||||
logger.debug(f"包含全角字符,忽略: {content}")
|
||||
return None
|
||||
# if re.search(r"[\u3000\uFF01-\uFF60\uFFE0-\uFFEE]", content):
|
||||
# logger.debug(f"包含全角字符,忽略: {content}")
|
||||
# return None
|
||||
|
||||
# 大小写不敏感匹配(仅用于匹配,不改变返回的原始内容)
|
||||
content_lower = content.lower()
|
||||
|
||||
Reference in New Issue
Block a user