Skip to content

Commit c06f37f

Browse files
authored
Merge pull request #6 from Raven95676/dev
实验性支持存档
2 parents ec26662 + 0ef38d1 commit c06f37f

File tree

11 files changed

+366
-75
lines changed

11 files changed

+366
-75
lines changed

README.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ AstrBot 的 lorebook 插件,支持自定义触发器、变量、逻辑、占
1616

1717
建议在使用前先阅读[YAML 入门教程](https://www.runoob.com/w3cnote/yaml-intro.html)
1818

19-
## 近期更改(0.1.1 - 0.1.4)
2019

20+
## 近期更改(0.1.1 - 0.1.5)
21+
22+
- 实现存档与加载(实验性)
2123
- 实现作用域继承与变量值占位符解析
2224
- 添加非逻辑
2325
- 按会话、人格隔离lorebook
2426
- 添加重置lorebook功能
25-
- 优化解析器触发逻辑和占位符错误处理
26-
- 修复事件属性类型问题
2727

2828
## 使用方法
2929

@@ -171,6 +171,13 @@ position: 插入位置,同触发器 position。
171171
{buildin::sender_name} - 返回发送者名称
172172
```
173173
174+
**存档相关:**
175+
176+
```
177+
{buildin::load(scope)} - 加载存档,scope为world或user
178+
{buildin::save(scope)} - 保存存档,scope为world或user
179+
```
180+
174181
**时间相关:**
175182
176183
```

core/handlers/logic_handler.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def __init__(self, parser):
2020
"""
2121
self.parser = parser
2222

23-
def handle_logic_oper(self, function: str, args: list[str]) -> str:
23+
async def handle_logic_oper(self, function: str, args: list[str]) -> str:
2424
"""处理逻辑操作
2525
2626
Args:
@@ -34,14 +34,14 @@ def handle_logic_oper(self, function: str, args: list[str]) -> str:
3434
return "参数错误"
3535

3636
# 处理所有参数中的占位符
37-
processed_args = [self.parser.parse_placeholder(arg) for arg in args]
37+
processed_args = [await self.parser.parse_placeholder(arg) for arg in args]
3838

3939
match function:
4040
case "if": # 条件判断
4141
if len(processed_args) < 2:
4242
return "条件参数不足"
4343

44-
condition_result = self._eval_cond(processed_args[0])
44+
condition_result = await self._eval_cond(processed_args[0])
4545
# 如果条件为真,返回第二个参数,否则返回第三个参数(如果存在)
4646
result = (
4747
processed_args[1]
@@ -54,28 +54,28 @@ def handle_logic_oper(self, function: str, args: list[str]) -> str:
5454
# 所有条件都为真时返回"true",否则返回"false"
5555
return (
5656
"true"
57-
if all(self._eval_cond(cond) for cond in processed_args)
57+
if all(await self._eval_cond(cond) for cond in processed_args)
5858
else "false"
5959
)
6060

6161
case "or": # 逻辑或
6262
# 任一条件为真时返回"true",否则返回"false"
6363
return (
6464
"true"
65-
if any(self._eval_cond(cond) for cond in processed_args)
65+
if any(await self._eval_cond(cond) for cond in processed_args)
6666
else "false"
6767
)
6868

6969
case "not": # 逻辑非
7070
# 任一条件为真时返回"false",否则返回"true"
7171
if len(processed_args) != 1:
7272
return "逻辑非操作需要一个参数"
73-
return "true" if not self._eval_cond(processed_args[0]) else "false"
73+
return "true" if not await self._eval_cond(processed_args[0]) else "false"
7474

7575
case _:
7676
return "未知逻辑操作"
7777

78-
def _eval_cond(self, condition: str) -> bool:
78+
async def _eval_cond(self, condition: str) -> bool:
7979
"""处理条件表达式
8080
8181
Args:
@@ -99,17 +99,17 @@ def _eval_cond(self, condition: str) -> bool:
9999

100100
# 处理非逻辑(!)
101101
if condition.startswith("!"):
102-
return not self._eval_cond(condition[1:].strip())
102+
return not await self._eval_cond(condition[1:].strip())
103103

104104
# 处理逻辑与(&&)
105105
if "&&" in condition:
106106
parts = condition.split("&&")
107-
return all(self._eval_cond(part.strip()) for part in parts if part.strip())
107+
return all(await self._eval_cond(part.strip()) for part in parts if part.strip())
108108

109109
# 处理逻辑或(||)
110110
if "||" in condition:
111111
parts = condition.split("||")
112-
return any(self._eval_cond(part.strip()) for part in parts if part.strip())
112+
return any(await self._eval_cond(part.strip()) for part in parts if part.strip())
113113

114114
# 处理比较运算符
115115
for op, func in OPERATORS:

core/handlers/random_handler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def __init__(self, parser):
2020
"""
2121
self.parser = parser
2222

23-
def handle_random_oper(self, args: list[str]) -> str:
23+
async def handle_random_oper(self, args: list[str]) -> str:
2424
"""处理随机数相关操作
2525
2626
Args:

core/handlers/save_handler.py

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
import json
2+
import os
3+
import re
4+
import aiofiles
5+
import aiofiles.os as aio_os
6+
from astrbot.api import logger
7+
8+
9+
class SaveHandler:
10+
"""保存处理器类,用于处理保存和加载操作"""
11+
12+
def __init__(self, parser):
13+
"""初始化保存处理器
14+
15+
Args:
16+
parser: 解析器实例,用于访问和修改变量数据
17+
"""
18+
self.parser = parser
19+
self.data_path = os.path.join(os.getcwd(), "data", "lorebook_lite_saves")
20+
os.makedirs(
21+
self.data_path, exist_ok=True
22+
) # 同步创建目录,因为这只在初始化时执行一次
23+
24+
def _get_session_ps(self):
25+
"""获取当前会话的安全文件名
26+
27+
Returns:
28+
str: 处理后的会话ID,可用作文件名
29+
"""
30+
return re.sub(r'[\\/:*?"<>|!]', "_", self.parser.session)
31+
32+
async def handle_save_oper(self, args: list[str]) -> str:
33+
"""处理保存操作
34+
35+
Args:
36+
args: 操作参数列表
37+
38+
Returns:
39+
str: 操作结果消息
40+
"""
41+
if not args:
42+
return "无参数"
43+
44+
try:
45+
match args:
46+
case ["world"]:
47+
await self._save_world_state()
48+
return "世界状态已保存"
49+
case ["user"]:
50+
await self._save_user_state()
51+
return "用户状态已保存"
52+
case _:
53+
return "未知参数"
54+
except Exception as e:
55+
logger.error(f"保存状态时出错: {e}")
56+
return f"保存失败: {str(e)}"
57+
58+
async def handle_load_oper(self, args: list[str]) -> str:
59+
"""处理加载操作
60+
61+
Args:
62+
args: 操作参数列表
63+
64+
Returns:
65+
str: 操作结果消息
66+
"""
67+
if not args:
68+
return "无参数"
69+
70+
try:
71+
match args:
72+
case ["world"]:
73+
result = await self._load_world_state()
74+
return result if result else "世界状态已加载"
75+
case ["user"]:
76+
result = await self._load_user_state()
77+
return result if result else "用户状态已加载"
78+
case _:
79+
return "未知参数"
80+
except Exception as e:
81+
logger.error(f"加载状态时出错: {e}")
82+
return f"加载失败: {str(e)}"
83+
84+
async def _save_world_state(self) -> None:
85+
"""保存世界状态到文件"""
86+
try:
87+
world_state = self.parser._vars.get("world", {})
88+
if not world_state:
89+
logger.debug("世界状态为空,不保存")
90+
return
91+
92+
session_ps = self._get_session_ps()
93+
filename = f"{session_ps}_world_state.json"
94+
filepath = os.path.join(self.data_path, filename)
95+
96+
logger.debug(f"保存世界状态到: {filepath}")
97+
json_data = json.dumps(world_state, ensure_ascii=False, indent=2)
98+
99+
async with aiofiles.open(filepath, "w", encoding="utf-8") as f:
100+
await f.write(json_data)
101+
await f.flush()
102+
103+
except Exception as e:
104+
logger.error(f"保存世界状态时出错: {e}")
105+
raise
106+
107+
async def _save_user_state(self) -> None:
108+
"""保存用户状态到文件"""
109+
try:
110+
user_states = {}
111+
for key, value in self.parser._vars.items():
112+
if key != "world" and ":" in key:
113+
user_states[key] = value
114+
115+
if not user_states:
116+
logger.debug("用户状态为空,不保存")
117+
return
118+
119+
session_ps = self._get_session_ps()
120+
filename = f"{session_ps}_user_state.json"
121+
filepath = os.path.join(self.data_path, filename)
122+
123+
logger.debug(f"保存用户状态到: {filepath}")
124+
json_data = json.dumps(user_states, ensure_ascii=False, indent=2)
125+
126+
async with aiofiles.open(filepath, "w", encoding="utf-8") as f:
127+
await f.write(json_data)
128+
await f.flush()
129+
130+
except Exception as e:
131+
logger.error(f"保存用户状态时出错: {e}")
132+
raise
133+
134+
async def _load_world_state(self) -> str:
135+
"""加载世界状态"""
136+
try:
137+
session_ps = self._get_session_ps()
138+
filename = f"{session_ps}_world_state.json"
139+
filepath = os.path.join(self.data_path, filename)
140+
141+
if not await aio_os.path.exists(filepath):
142+
return f"找不到世界状态文件: {filename}"
143+
144+
logger.debug(f"从 {filepath} 加载世界状态")
145+
async with aiofiles.open(filepath, "r", encoding="utf-8") as f:
146+
content = await f.read()
147+
world_state = json.loads(content)
148+
149+
self.parser._vars["world"] = world_state
150+
return None
151+
152+
except Exception as e:
153+
logger.error(f"加载世界状态时出错: {e}")
154+
raise
155+
156+
async def _load_user_state(self) -> str:
157+
"""加载用户状态"""
158+
try:
159+
session_ps = self._get_session_ps()
160+
filename = f"{session_ps}_user_state.json"
161+
filepath = os.path.join(self.data_path, filename)
162+
163+
if not await aio_os.path.exists(filepath):
164+
return f"找不到用户状态文件: {filename}"
165+
166+
logger.debug(f"从 {filepath} 加载用户状态")
167+
async with aiofiles.open(filepath, "r", encoding="utf-8") as f:
168+
content = await f.read()
169+
user_states = json.loads(content)
170+
171+
for key, value in user_states.items():
172+
self.parser._vars[key] = value
173+
return None
174+
175+
except Exception as e:
176+
logger.error(f"加载用户状态时出错: {e}")
177+
raise

core/handlers/time_handler.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def __init__(self, parser):
2626
"""
2727
self.parser = parser
2828

29-
def handle_time_oper(self, args: list[str]) -> str:
29+
async def handle_time_oper(self, args: list[str]) -> str:
3030
"""处理时间相关操作
3131
3232
Args:

0 commit comments

Comments
 (0)