ErisPulse 2.7.1.dev2__tar.gz → 2.7.1.dev4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/PKG-INFO +1 -1
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/pyproject.toml +1 -1
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Bases/adapter.py +70 -55
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Bases/config_schema.py +9 -10
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Bases/converter.py +3 -1
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Bases/errors.py +0 -5
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Bases/i18n_schema.py +2 -2
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Bases/kv_builder.py +9 -8
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Bases/module.py +5 -6
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Bases/send_builder.py +9 -4
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Bases/send_rules.py +5 -5
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Bases/storage.py +3 -1
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Event/base.py +4 -4
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Event/command.py +21 -13
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Event/session_type.py +6 -6
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Event/wrapper.py +120 -34
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/adapter.py +47 -39
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/client.py +1 -1
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/constants.py +26 -3
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/i18n/locales/en.py +117 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/i18n/locales/ja.py +117 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/i18n/locales/ru.py +117 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/i18n/locales/zh_cn.py +117 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/i18n/locales/zh_tw.py +117 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/master.py +2 -1
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/module.py +2 -2
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/router.py +168 -257
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/storage.py +33 -68
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/finders/bases/finder.py +2 -2
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/loaders/module.py +12 -5
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/runtime/exceptions.py +2 -1
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/runtime/frame_config.py +6 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/runtime/memory.py +13 -4
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/sdk.py +221 -40
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/.gitignore +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/LICENSE +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/README.pypi.md +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/__init__.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/base.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/cli.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/commands/__init__.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/commands/create.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/commands/doctor.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/commands/init.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/commands/install.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/commands/language.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/commands/list.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/commands/list_remote.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/commands/run.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/commands/self_update.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/commands/types.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/commands/uninstall.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/commands/upgrade.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/console.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/constants.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/hints.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/i18n/__init__.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/i18n/locales/__init__.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/i18n/locales/en.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/i18n/locales/ja.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/i18n/locales/ru.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/i18n/locales/zh_cn.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/i18n/locales/zh_tw.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/registry.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/utils/__init__.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/utils/display.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/utils/file_watcher.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/utils/package_manager.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/CLI/utils/scaffold_text.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Bases/__init__.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Bases/client.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Bases/manager.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Bases/router.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Bases/websocket.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Event/__init__.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Event/message.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Event/message_builder.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Event/meta.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Event/notice.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/Event/request.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/__init__.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/assets/__init__.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/assets/error.css +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/assets/error.html +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/assets/root.css +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/assets/root.html +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/config.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/i18n/__init__.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/i18n/constants.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/i18n/locales/__init__.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/lifecycle.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/Core/logger.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/__init__.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/__main__.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/finders/__init__.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/finders/adapter.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/finders/bases/__init__.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/finders/module.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/loaders/__init__.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/loaders/adapter.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/loaders/bases/__init__.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/loaders/bases/loader.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/loaders/strategy.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/loaders/strict.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/py.typed +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/runtime/__init__.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/runtime/config_schema.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/runtime/context.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/runtime/diagnostics.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/runtime/hints.py +0 -0
- {erispulse-2.7.1.dev2 → erispulse-2.7.1.dev4}/src/ErisPulse/runtime/tasks.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: ErisPulse
|
|
3
|
-
Version: 2.7.1.
|
|
3
|
+
Version: 2.7.1.dev4
|
|
4
4
|
Summary: Event-driven modular async bot framework — write once, deploy to any platform | 事件驱动的模块化异步机器人框架,一次编写,多平台部署
|
|
5
5
|
Project-URL: Homepage, https://github.com/ErisPulse/ErisPulse
|
|
6
6
|
Project-URL: Documentation, https://www.erisdev.com#docs
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "ErisPulse"
|
|
7
|
-
version = "2.7.1-dev.
|
|
7
|
+
version = "2.7.1-dev.4"
|
|
8
8
|
description = "Event-driven modular async bot framework — write once, deploy to any platform | 事件驱动的模块化异步机器人框架,一次编写,多平台部署"
|
|
9
9
|
readme = "README.pypi.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -19,6 +19,7 @@ if TYPE_CHECKING:
|
|
|
19
19
|
# typing.Self 仅在 3.11+ 提供,3.10 需 typing_extensions 兜底
|
|
20
20
|
from typing_extensions import Self
|
|
21
21
|
|
|
22
|
+
from ..config import config as config_mgr
|
|
22
23
|
from ..constants import (
|
|
23
24
|
DEFAULT_SEND_METHOD,
|
|
24
25
|
DEFAULT_SEND_TARGET_TYPE,
|
|
@@ -28,6 +29,9 @@ from ..constants import (
|
|
|
28
29
|
STATUS_FAILED,
|
|
29
30
|
STATUS_OK,
|
|
30
31
|
)
|
|
32
|
+
from ..i18n import i18n
|
|
33
|
+
from ..lifecycle import lifecycle
|
|
34
|
+
from ..logger import logger
|
|
31
35
|
|
|
32
36
|
_CHAIN_MODIFIER_NAMES = frozenset({
|
|
33
37
|
"At", "AtAll", "Reply", "To", "Using", "Account",
|
|
@@ -137,6 +141,7 @@ def _wrap_send_method(method_name: str, original_method: Callable, send_dsl: "Se
|
|
|
137
141
|
"bot_id": send_dsl._account_id or "",
|
|
138
142
|
}
|
|
139
143
|
|
|
144
|
+
# 循环依赖:Core/adapter.py 顶层导入本模块(BaseAdapter)
|
|
140
145
|
from ..adapter import _msg_logger
|
|
141
146
|
|
|
142
147
|
target_type = send_dsl._target_type or ""
|
|
@@ -158,7 +163,6 @@ def _wrap_send_method(method_name: str, original_method: Callable, send_dsl: "Se
|
|
|
158
163
|
|
|
159
164
|
# 预判是否有生命周期监听者:无监听时跳过 Task 创建与 emit 调度,
|
|
160
165
|
# 避免每条发送消息都无条件 spawn 两个后台任务
|
|
161
|
-
from ..lifecycle import lifecycle
|
|
162
166
|
|
|
163
167
|
_has_sending_hooks = lifecycle.has_handlers("message.sending")
|
|
164
168
|
_has_sent_hooks = lifecycle.has_handlers("message.sent")
|
|
@@ -309,10 +313,13 @@ class SendDSL:
|
|
|
309
313
|
return resolved
|
|
310
314
|
return attr
|
|
311
315
|
|
|
312
|
-
from ..logger import logger
|
|
313
316
|
|
|
314
317
|
logger.warning(
|
|
315
|
-
|
|
318
|
+
i18n.t(
|
|
319
|
+
"core.adapter.send_method_not_implemented",
|
|
320
|
+
platform=self._adapter.__class__.__name__,
|
|
321
|
+
name=name,
|
|
322
|
+
)
|
|
316
323
|
)
|
|
317
324
|
|
|
318
325
|
raise AttributeError(
|
|
@@ -428,11 +435,12 @@ class SendDSL:
|
|
|
428
435
|
:param kwargs: 其他参数
|
|
429
436
|
:return: asyncio.Task
|
|
430
437
|
"""
|
|
431
|
-
from ..logger import logger
|
|
432
438
|
|
|
433
439
|
logger.error(
|
|
434
|
-
|
|
435
|
-
|
|
440
|
+
i18n.t(
|
|
441
|
+
"core.adapter.raw_ob12_not_implemented",
|
|
442
|
+
platform=self._adapter.__class__.__name__,
|
|
443
|
+
)
|
|
436
444
|
)
|
|
437
445
|
|
|
438
446
|
async def _not_impl():
|
|
@@ -441,7 +449,10 @@ class SendDSL:
|
|
|
441
449
|
"retcode": RETCODE_NOT_IMPLEMENTED,
|
|
442
450
|
"data": None,
|
|
443
451
|
"message_id": "",
|
|
444
|
-
"message":
|
|
452
|
+
"message": i18n.t(
|
|
453
|
+
"core.adapter.raw_ob12_not_implemented_short",
|
|
454
|
+
platform=self._adapter.__class__.__name__,
|
|
455
|
+
),
|
|
445
456
|
}
|
|
446
457
|
|
|
447
458
|
try:
|
|
@@ -923,19 +934,26 @@ class RequestDSL:
|
|
|
923
934
|
:param action: 操作名称(accept/reject)
|
|
924
935
|
:return: 标准错误响应字典
|
|
925
936
|
"""
|
|
926
|
-
from ..logger import logger
|
|
927
937
|
|
|
928
938
|
platform_name = self._adapter.__class__.__name__
|
|
929
939
|
logger.warning(
|
|
930
|
-
|
|
931
|
-
|
|
940
|
+
i18n.t(
|
|
941
|
+
"core.adapter.request_not_implemented",
|
|
942
|
+
platform=platform_name,
|
|
943
|
+
action=action,
|
|
944
|
+
request_id=self._request_id,
|
|
945
|
+
)
|
|
932
946
|
)
|
|
933
947
|
return {
|
|
934
948
|
"status": STATUS_FAILED,
|
|
935
949
|
"retcode": RETCODE_NOT_IMPLEMENTED,
|
|
936
950
|
"data": None,
|
|
937
951
|
"message_id": "",
|
|
938
|
-
"message":
|
|
952
|
+
"message": i18n.t(
|
|
953
|
+
"core.adapter.request_op_not_implemented",
|
|
954
|
+
platform=platform_name,
|
|
955
|
+
action=action,
|
|
956
|
+
),
|
|
939
957
|
}
|
|
940
958
|
|
|
941
959
|
def _create_task(self, coro) -> Awaitable[Any]:
|
|
@@ -1321,7 +1339,6 @@ class BaseAdapter(ABC):
|
|
|
1321
1339
|
{!--< /tips >!--}
|
|
1322
1340
|
"""
|
|
1323
1341
|
|
|
1324
|
-
...
|
|
1325
1342
|
|
|
1326
1343
|
class Api(ApiDSL):
|
|
1327
1344
|
"""
|
|
@@ -1337,7 +1354,6 @@ class BaseAdapter(ABC):
|
|
|
1337
1354
|
{!--< /tips >!--}
|
|
1338
1355
|
"""
|
|
1339
1356
|
|
|
1340
|
-
...
|
|
1341
1357
|
|
|
1342
1358
|
class Send(SendDSL):
|
|
1343
1359
|
"""
|
|
@@ -1373,9 +1389,8 @@ class BaseAdapter(ABC):
|
|
|
1373
1389
|
}
|
|
1374
1390
|
|
|
1375
1391
|
async def _send_example():
|
|
1376
|
-
from ..logger import logger
|
|
1377
1392
|
|
|
1378
|
-
logger.info(
|
|
1393
|
+
logger.info(i18n.t("core.adapter.send_example", text=text))
|
|
1379
1394
|
return mock_response
|
|
1380
1395
|
|
|
1381
1396
|
return asyncio.create_task(_send_example())
|
|
@@ -1420,18 +1435,22 @@ class BaseAdapter(ABC):
|
|
|
1420
1435
|
"""
|
|
1421
1436
|
|
|
1422
1437
|
async def _send_raw():
|
|
1423
|
-
from ..logger import logger
|
|
1424
1438
|
|
|
1425
1439
|
logger.error(
|
|
1426
|
-
|
|
1427
|
-
|
|
1440
|
+
i18n.t(
|
|
1441
|
+
"core.adapter.raw_ob12_not_implemented",
|
|
1442
|
+
platform=self._adapter.__class__.__name__,
|
|
1443
|
+
)
|
|
1428
1444
|
)
|
|
1429
1445
|
return {
|
|
1430
1446
|
"status": STATUS_FAILED,
|
|
1431
1447
|
"retcode": RETCODE_NOT_IMPLEMENTED,
|
|
1432
1448
|
"data": None,
|
|
1433
1449
|
"message_id": "",
|
|
1434
|
-
"message":
|
|
1450
|
+
"message": i18n.t(
|
|
1451
|
+
"core.adapter.raw_ob12_not_implemented_short",
|
|
1452
|
+
platform=self._adapter.__class__.__name__,
|
|
1453
|
+
),
|
|
1435
1454
|
}
|
|
1436
1455
|
|
|
1437
1456
|
try:
|
|
@@ -1509,7 +1528,8 @@ class BaseAdapter(ABC):
|
|
|
1509
1528
|
:return: API调用结果
|
|
1510
1529
|
:raises NotImplementedError: 必须由子类实现
|
|
1511
1530
|
"""
|
|
1512
|
-
|
|
1531
|
+
|
|
1532
|
+
raise NotImplementedError(i18n.t("core.adapter.must_implement_call_api"))
|
|
1513
1533
|
|
|
1514
1534
|
@abstractmethod
|
|
1515
1535
|
async def start(self) -> None:
|
|
@@ -1518,7 +1538,8 @@ class BaseAdapter(ABC):
|
|
|
1518
1538
|
|
|
1519
1539
|
:raises NotImplementedError: 必须由子类实现
|
|
1520
1540
|
"""
|
|
1521
|
-
|
|
1541
|
+
|
|
1542
|
+
raise NotImplementedError(i18n.t("core.adapter.must_implement_start"))
|
|
1522
1543
|
|
|
1523
1544
|
@abstractmethod
|
|
1524
1545
|
async def shutdown(self) -> None:
|
|
@@ -1527,7 +1548,8 @@ class BaseAdapter(ABC):
|
|
|
1527
1548
|
|
|
1528
1549
|
:raises NotImplementedError: 必须由子类实现
|
|
1529
1550
|
"""
|
|
1530
|
-
|
|
1551
|
+
|
|
1552
|
+
raise NotImplementedError(i18n.t("core.adapter.must_implement_shutdown"))
|
|
1531
1553
|
|
|
1532
1554
|
@property
|
|
1533
1555
|
def cfg(self):
|
|
@@ -1546,11 +1568,9 @@ class BaseAdapter(ABC):
|
|
|
1546
1568
|
{!--< /tips >!--}
|
|
1547
1569
|
"""
|
|
1548
1570
|
if self.ConfigClass is None:
|
|
1549
|
-
raise AttributeError(
|
|
1550
|
-
"未声明 ConfigClass,请设置 MyAdapter.ConfigClass = MyConfig"
|
|
1551
|
-
)
|
|
1552
1571
|
|
|
1553
|
-
|
|
1572
|
+
raise AttributeError(i18n.t("core.adapter.config_class_not_declared"))
|
|
1573
|
+
|
|
1554
1574
|
from .config_schema import dict_to_dataclass
|
|
1555
1575
|
|
|
1556
1576
|
# 适配器的 EventMixin 在 AdapterManager.register() 注入 _platform 后注册
|
|
@@ -1570,7 +1590,6 @@ class BaseAdapter(ABC):
|
|
|
1570
1590
|
if value is not None:
|
|
1571
1591
|
from dataclasses import asdict
|
|
1572
1592
|
|
|
1573
|
-
from ..config import config as config_mgr
|
|
1574
1593
|
|
|
1575
1594
|
try:
|
|
1576
1595
|
config_mgr.setConfig(self._get_config_key(), asdict(value))
|
|
@@ -1601,11 +1620,9 @@ class BaseAdapter(ABC):
|
|
|
1601
1620
|
:raises AttributeError: 未声明 AccountConfigClass 时抛出
|
|
1602
1621
|
"""
|
|
1603
1622
|
if self.AccountConfigClass is None:
|
|
1604
|
-
raise AttributeError(
|
|
1605
|
-
"未声明 AccountConfigClass,请设置 MyAdapter.AccountConfigClass = MyBotConfig"
|
|
1606
|
-
)
|
|
1607
1623
|
|
|
1608
|
-
|
|
1624
|
+
raise AttributeError(i18n.t("core.adapter.account_config_not_declared"))
|
|
1625
|
+
|
|
1609
1626
|
from .config_schema import dict_to_dataclass, validate_config
|
|
1610
1627
|
|
|
1611
1628
|
key = f"{self._get_config_key()}.accounts"
|
|
@@ -1623,7 +1640,7 @@ class BaseAdapter(ABC):
|
|
|
1623
1640
|
errors = validate_config(instance)
|
|
1624
1641
|
if errors:
|
|
1625
1642
|
self._get_logger().error(
|
|
1626
|
-
|
|
1643
|
+
i18n.t("core.adapter.account_config_invalid", name=name, error=", ".join(errors))
|
|
1627
1644
|
)
|
|
1628
1645
|
continue
|
|
1629
1646
|
accounts[name] = instance
|
|
@@ -1637,7 +1654,6 @@ class BaseAdapter(ABC):
|
|
|
1637
1654
|
if value is not None:
|
|
1638
1655
|
from dataclasses import asdict
|
|
1639
1656
|
|
|
1640
|
-
from ..config import config as config_mgr
|
|
1641
1657
|
|
|
1642
1658
|
key = f"{self._get_config_key()}.accounts"
|
|
1643
1659
|
try:
|
|
@@ -1674,17 +1690,18 @@ class BaseAdapter(ABC):
|
|
|
1674
1690
|
return self.__class__.__name__
|
|
1675
1691
|
|
|
1676
1692
|
def _get_logger(self):
|
|
1677
|
-
"""
|
|
1693
|
+
"""
|
|
1694
|
+
{!--< internal-use >!--}
|
|
1695
|
+
获取 logger,兼容 sdk 未注入的场景
|
|
1696
|
+
|
|
1697
|
+
此处刻意使用函数内导入:模块顶层已有 ``logger``,但函数内动态导入可让测试
|
|
1698
|
+
通过 ``patch("ErisPulse.Core.logger.logger")`` 拦截日志输出。
|
|
1699
|
+
"""
|
|
1678
1700
|
if hasattr(self, "logger"):
|
|
1679
1701
|
return self.logger
|
|
1680
|
-
|
|
1681
|
-
from ..logger import logger
|
|
1682
|
-
|
|
1683
|
-
return logger
|
|
1684
|
-
except ImportError:
|
|
1685
|
-
import logging
|
|
1702
|
+
from ..logger import logger
|
|
1686
1703
|
|
|
1687
|
-
|
|
1704
|
+
return logger
|
|
1688
1705
|
|
|
1689
1706
|
def _ensure_config_exists(self):
|
|
1690
1707
|
"""
|
|
@@ -1700,7 +1717,6 @@ class BaseAdapter(ABC):
|
|
|
1700
1717
|
|
|
1701
1718
|
if self.ConfigClass is None:
|
|
1702
1719
|
return
|
|
1703
|
-
from ..config import config as config_mgr
|
|
1704
1720
|
from .config_schema import (
|
|
1705
1721
|
dataclass_to_defaults_dict,
|
|
1706
1722
|
dataclass_to_toml_with_comments,
|
|
@@ -1713,7 +1729,7 @@ class BaseAdapter(ABC):
|
|
|
1713
1729
|
data = dataclass_to_defaults_dict(self.ConfigClass)
|
|
1714
1730
|
toml_str = dataclass_to_toml_with_comments(self.ConfigClass)
|
|
1715
1731
|
config_mgr.setConfig(key, data, immediate=True)
|
|
1716
|
-
self._get_logger().info(
|
|
1732
|
+
self._get_logger().info(i18n.t("core.adapter.config_template_generated", key=key, toml=toml_str))
|
|
1717
1733
|
|
|
1718
1734
|
def _ensure_i18n_registered(self):
|
|
1719
1735
|
"""
|
|
@@ -1741,7 +1757,7 @@ class BaseAdapter(ABC):
|
|
|
1741
1757
|
except Exception:
|
|
1742
1758
|
# i18n 注册失败不应中断适配器初始化
|
|
1743
1759
|
self._get_logger().debug(
|
|
1744
|
-
|
|
1760
|
+
i18n.t("core.adapter.i18n_register_failed", adapter=self.__class__.__name__),
|
|
1745
1761
|
exc_info=True,
|
|
1746
1762
|
)
|
|
1747
1763
|
|
|
@@ -1768,7 +1784,7 @@ class BaseAdapter(ABC):
|
|
|
1768
1784
|
register_event_mixin(platform, self.EventMixin)
|
|
1769
1785
|
except Exception:
|
|
1770
1786
|
self._get_logger().debug(
|
|
1771
|
-
|
|
1787
|
+
i18n.t("core.adapter.eventmixin_register_failed", adapter=self.__class__.__name__),
|
|
1772
1788
|
exc_info=True,
|
|
1773
1789
|
)
|
|
1774
1790
|
|
|
@@ -1781,7 +1797,6 @@ class BaseAdapter(ABC):
|
|
|
1781
1797
|
"""
|
|
1782
1798
|
if self.AccountConfigClass is None:
|
|
1783
1799
|
return
|
|
1784
|
-
from ..config import config as config_mgr
|
|
1785
1800
|
from .config_schema import dataclass_to_defaults_dict
|
|
1786
1801
|
|
|
1787
1802
|
key = f"{self._get_config_key()}.accounts"
|
|
@@ -1791,7 +1806,7 @@ class BaseAdapter(ABC):
|
|
|
1791
1806
|
default_account = dataclass_to_defaults_dict(self.AccountConfigClass)
|
|
1792
1807
|
data = {"default": default_account}
|
|
1793
1808
|
config_mgr.setConfig(key, data, immediate=True)
|
|
1794
|
-
self._get_logger().info(
|
|
1809
|
+
self._get_logger().info(i18n.t("core.adapter.account_config_generated", key=key))
|
|
1795
1810
|
|
|
1796
1811
|
def _resolve_account(self, account_id: str | None = None) -> tuple:
|
|
1797
1812
|
"""
|
|
@@ -1836,7 +1851,10 @@ class BaseAdapter(ABC):
|
|
|
1836
1851
|
if cfg.enabled:
|
|
1837
1852
|
return name, cfg
|
|
1838
1853
|
|
|
1839
|
-
|
|
1854
|
+
|
|
1855
|
+
raise ValueError(
|
|
1856
|
+
i18n.t("core.adapter.account_not_found", account_id=account_id)
|
|
1857
|
+
)
|
|
1840
1858
|
|
|
1841
1859
|
async def emit_meta(self, detail_type: str, bot_id: str, **extra_info):
|
|
1842
1860
|
"""
|
|
@@ -1847,8 +1865,9 @@ class BaseAdapter(ABC):
|
|
|
1847
1865
|
:param extra_info: 扩展字段(user_name, nickname, avatar 等)
|
|
1848
1866
|
"""
|
|
1849
1867
|
if not self._platform:
|
|
1850
|
-
raise RuntimeError("
|
|
1868
|
+
raise RuntimeError(i18n.t("core.adapter.platform_not_injected"))
|
|
1851
1869
|
|
|
1870
|
+
# 循环依赖:Core/adapter.py 顶层导入本模块(BaseAdapter)
|
|
1852
1871
|
from ..adapter import adapter
|
|
1853
1872
|
|
|
1854
1873
|
await adapter.emit(
|
|
@@ -1926,13 +1945,9 @@ class BaseAdapter(ABC):
|
|
|
1926
1945
|
:param old_config: 变更前的配置实例
|
|
1927
1946
|
:param new_config: 变更后的配置实例
|
|
1928
1947
|
"""
|
|
1929
|
-
...
|
|
1930
1948
|
|
|
1931
1949
|
async def emit(self, *args, **kwargs):
|
|
1932
|
-
raise NotImplementedError(
|
|
1933
|
-
"适配器的 emit 方法已被弃用。请使用 adapter.emit() 通过 AdapterManager 提交事件。"
|
|
1934
|
-
"如果你是适配器开发者,请查看 ErisPulse 文档进行更新。"
|
|
1935
|
-
)
|
|
1950
|
+
raise NotImplementedError(i18n.t("core.adapter.emit_deprecated"))
|
|
1936
1951
|
|
|
1937
1952
|
def send(
|
|
1938
1953
|
self, target_type: str, target_id: str, message: Any, **kwargs: Any
|
|
@@ -1961,7 +1976,7 @@ class BaseAdapter(ABC):
|
|
|
1961
1976
|
method = getattr(self.Send.To(target_type, target_id), method_name, None) # pyright: ignore[reportArgumentType]
|
|
1962
1977
|
if not method:
|
|
1963
1978
|
raise AttributeError(
|
|
1964
|
-
|
|
1979
|
+
i18n.t("core.adapter.send_method_missing", name=method_name)
|
|
1965
1980
|
)
|
|
1966
1981
|
return await method(message, **kwargs)
|
|
1967
1982
|
|
|
@@ -21,6 +21,8 @@ from collections.abc import Mapping
|
|
|
21
21
|
from dataclasses import MISSING, dataclass, field, fields
|
|
22
22
|
from typing import Any, ClassVar
|
|
23
23
|
|
|
24
|
+
from ..i18n import i18n
|
|
25
|
+
|
|
24
26
|
# ---------------------------------------------------------------------------
|
|
25
27
|
# 内部辅助函数
|
|
26
28
|
# ---------------------------------------------------------------------------
|
|
@@ -303,7 +305,7 @@ class I18nConfig:
|
|
|
303
305
|
language: str = field(
|
|
304
306
|
default="auto",
|
|
305
307
|
metadata={
|
|
306
|
-
"description": "显示语言 (auto=自动检测, zh-CN, zh-TW, en, ja, ru)",
|
|
308
|
+
"description": {"i18n": "core.config.i18n_language_description", "default": "显示语言 (auto=自动检测, zh-CN, zh-TW, en, ja, ru)"},
|
|
307
309
|
"required": False,
|
|
308
310
|
"ui": {
|
|
309
311
|
"widget": "select",
|
|
@@ -373,7 +375,7 @@ def dataclass_to_toml_with_comments(
|
|
|
373
375
|
required = meta.get("required", False) if meta else False
|
|
374
376
|
|
|
375
377
|
if description:
|
|
376
|
-
suffix = "
|
|
378
|
+
suffix = i18n.t("core.config.required_suffix") if required else ""
|
|
377
379
|
lines.append(f"# {description}{suffix}")
|
|
378
380
|
|
|
379
381
|
# secret 字段不把真实值写入模板文件,避免配置文件泄露敏感信息
|
|
@@ -466,7 +468,6 @@ def _notify_instance_config_update(
|
|
|
466
468
|
instance.on_config_update(old_config, new_config)
|
|
467
469
|
except Exception as e:
|
|
468
470
|
try:
|
|
469
|
-
from ErisPulse.Core.i18n import i18n
|
|
470
471
|
from ErisPulse.Core.logger import logger
|
|
471
472
|
|
|
472
473
|
params = dict(log_params)
|
|
@@ -504,7 +505,7 @@ def validate_config(instance) -> list[str]:
|
|
|
504
505
|
# 1. required 非空(需要 metadata 声明)
|
|
505
506
|
if meta.get("required", False) and _is_empty(value):
|
|
506
507
|
desc_text = _resolve_description_text(meta) or f.name
|
|
507
|
-
errors.append(
|
|
508
|
+
errors.append(i18n.t("core.config.field_required_empty", field=f.name, desc=desc_text))
|
|
508
509
|
continue # 已为空,类型/范围检查无意义
|
|
509
510
|
|
|
510
511
|
# 跳过空值后续检查
|
|
@@ -519,7 +520,7 @@ def validate_config(instance) -> list[str]:
|
|
|
519
520
|
if expected is not None and not isinstance(value, expected):
|
|
520
521
|
# bool 是 int 的子类:声明 int 但实际为 bool 视为类型不符
|
|
521
522
|
errors.append(
|
|
522
|
-
|
|
523
|
+
i18n.t("core.config.field_type_mismatch", field=f.name, expected=type_name, actual=type(value).__name__)
|
|
523
524
|
)
|
|
524
525
|
|
|
525
526
|
# 3. 枚举选项(options 可在 ui 子表或 metadata 顶层)
|
|
@@ -529,7 +530,7 @@ def validate_config(instance) -> list[str]:
|
|
|
529
530
|
o.get("value") if isinstance(o, dict) else o for o in options
|
|
530
531
|
]
|
|
531
532
|
if value not in plain_opts:
|
|
532
|
-
errors.append(
|
|
533
|
+
errors.append(i18n.t("core.config.field_option_invalid", field=f.name, value=value))
|
|
533
534
|
|
|
534
535
|
# 4. 数值范围
|
|
535
536
|
if isinstance(value, (int, float)) and not isinstance(value, bool):
|
|
@@ -540,9 +541,9 @@ def validate_config(instance) -> list[str]:
|
|
|
540
541
|
if max_val is None:
|
|
541
542
|
max_val = meta.get("max")
|
|
542
543
|
if min_val is not None and value < min_val:
|
|
543
|
-
errors.append(
|
|
544
|
+
errors.append(i18n.t("core.config.field_below_min", field=f.name, value=value, min=min_val))
|
|
544
545
|
if max_val is not None and value > max_val:
|
|
545
|
-
errors.append(
|
|
546
|
+
errors.append(i18n.t("core.config.field_above_max", field=f.name, value=value, max=max_val))
|
|
546
547
|
|
|
547
548
|
return errors
|
|
548
549
|
|
|
@@ -636,7 +637,6 @@ def register_config_i18n(
|
|
|
636
637
|
:param domain: i18n 域标识,默认 "config"
|
|
637
638
|
:return: 注册的翻译条目数
|
|
638
639
|
"""
|
|
639
|
-
from ErisPulse.Core.i18n import i18n
|
|
640
640
|
|
|
641
641
|
count = 0
|
|
642
642
|
for f in fields(config_class):
|
|
@@ -706,7 +706,6 @@ def resolve_config_schema(config_class: type, resolve_i18n: bool = True) -> dict
|
|
|
706
706
|
if not resolve_i18n:
|
|
707
707
|
return schema
|
|
708
708
|
|
|
709
|
-
from ErisPulse.Core.i18n import i18n
|
|
710
709
|
|
|
711
710
|
for field_schema in schema["fields"].values():
|
|
712
711
|
# description
|
|
@@ -72,8 +72,10 @@ class BaseConverter:
|
|
|
72
72
|
:param raw_event: 平台原始事件数据
|
|
73
73
|
:return: OneBot12 标准格式事件字典;无法识别时返回 None
|
|
74
74
|
"""
|
|
75
|
+
from ..i18n import i18n
|
|
76
|
+
|
|
75
77
|
raise NotImplementedError(
|
|
76
|
-
|
|
78
|
+
i18n.t("core.converter.must_implement_convert", name=self.__class__.__name__)
|
|
77
79
|
)
|
|
78
80
|
|
|
79
81
|
|
|
@@ -21,7 +21,6 @@ class ErisPulseError(Exception):
|
|
|
21
21
|
所有 ErisPulse 自定义异常的基类。
|
|
22
22
|
"""
|
|
23
23
|
|
|
24
|
-
...
|
|
25
24
|
|
|
26
25
|
|
|
27
26
|
class ClientError(ErisPulseError):
|
|
@@ -39,7 +38,6 @@ class ClientError(ErisPulseError):
|
|
|
39
38
|
... print(f"请求失败: {e}")
|
|
40
39
|
"""
|
|
41
40
|
|
|
42
|
-
...
|
|
43
41
|
|
|
44
42
|
|
|
45
43
|
|
|
@@ -56,7 +54,6 @@ class ClientConnectionError(ClientError):
|
|
|
56
54
|
... print("无法连接到服务器")
|
|
57
55
|
"""
|
|
58
56
|
|
|
59
|
-
...
|
|
60
57
|
|
|
61
58
|
|
|
62
59
|
class ClientTimeoutError(ClientError):
|
|
@@ -72,7 +69,6 @@ class ClientTimeoutError(ClientError):
|
|
|
72
69
|
... print("请求超时")
|
|
73
70
|
"""
|
|
74
71
|
|
|
75
|
-
...
|
|
76
72
|
|
|
77
73
|
|
|
78
74
|
class HTTPStatusError(ClientError):
|
|
@@ -104,7 +100,6 @@ class WebSocketError(ErisPulseError):
|
|
|
104
100
|
WebSocket 连接、通信相关的异常。
|
|
105
101
|
"""
|
|
106
102
|
|
|
107
|
-
...
|
|
108
103
|
|
|
109
104
|
|
|
110
105
|
class WebSocketDisconnect(WebSocketError):
|
|
@@ -15,6 +15,7 @@ ErisPulse i18n 键声明 Schema 模块
|
|
|
15
15
|
{!--< /tips >!--}
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
+
from ..i18n import i18n
|
|
18
19
|
|
|
19
20
|
class I18nKey:
|
|
20
21
|
"""
|
|
@@ -73,7 +74,7 @@ class I18nKey:
|
|
|
73
74
|
ru: str | None = None,
|
|
74
75
|
):
|
|
75
76
|
if not default:
|
|
76
|
-
raise ValueError("
|
|
77
|
+
raise ValueError(i18n.t("core.i18n_schema.default_required"))
|
|
77
78
|
|
|
78
79
|
self._key = key
|
|
79
80
|
self.default = default
|
|
@@ -214,7 +215,6 @@ class BaseI18n:
|
|
|
214
215
|
>>> MyKeys.register(prefix="myapp.", domain="myapp")
|
|
215
216
|
2 # zh-CN + en
|
|
216
217
|
"""
|
|
217
|
-
from ..i18n import i18n
|
|
218
218
|
|
|
219
219
|
count = 0
|
|
220
220
|
for attr_name, i18n_key in cls._collect_keys().items():
|
|
@@ -24,6 +24,7 @@ ErisPulse KV 查询构建器
|
|
|
24
24
|
import json
|
|
25
25
|
from typing import Any
|
|
26
26
|
|
|
27
|
+
from ..i18n import i18n
|
|
27
28
|
from .storage import BaseQueryBuilder
|
|
28
29
|
|
|
29
30
|
_TABLE_PREFIX = "__erispulse_sql__"
|
|
@@ -197,18 +198,18 @@ class KVQueryBuilder(BaseQueryBuilder):
|
|
|
197
198
|
return self._exec_update()
|
|
198
199
|
if self._operation == "delete":
|
|
199
200
|
return self._exec_delete()
|
|
200
|
-
raise ValueError(
|
|
201
|
+
raise ValueError(i18n.t("core.kvbuilder.unknown_operation", op=self._operation))
|
|
201
202
|
|
|
202
203
|
def _exec_insert(self) -> int:
|
|
203
204
|
if not isinstance(self._data, dict):
|
|
204
|
-
raise ValueError("
|
|
205
|
+
raise ValueError(i18n.t("core.kvbuilder.insert_needs_dict"))
|
|
205
206
|
row_id = self._get_next_id()
|
|
206
207
|
self._storage.set(self._row_key(row_id), json.dumps(self._data, ensure_ascii=False))
|
|
207
208
|
return 1
|
|
208
209
|
|
|
209
210
|
def _exec_insert_multi(self) -> int:
|
|
210
211
|
if not isinstance(self._data, list):
|
|
211
|
-
raise ValueError("
|
|
212
|
+
raise ValueError(i18n.t("core.kvbuilder.insert_multi_needs_list"))
|
|
212
213
|
count = 0
|
|
213
214
|
for row in self._data:
|
|
214
215
|
row_id = self._get_next_id()
|
|
@@ -241,7 +242,7 @@ class KVQueryBuilder(BaseQueryBuilder):
|
|
|
241
242
|
|
|
242
243
|
def _exec_update(self) -> int:
|
|
243
244
|
if not isinstance(self._data, dict):
|
|
244
|
-
raise ValueError("
|
|
245
|
+
raise ValueError(i18n.t("core.kvbuilder.update_needs_dict"))
|
|
245
246
|
count = 0
|
|
246
247
|
for row_id, row in self._scan_rows():
|
|
247
248
|
if self._match_row(row):
|
|
@@ -304,13 +305,13 @@ class KVQueryBuilder(BaseQueryBuilder):
|
|
|
304
305
|
"""异步执行查询"""
|
|
305
306
|
if self._operation == "insert":
|
|
306
307
|
if not isinstance(self._data, dict):
|
|
307
|
-
raise ValueError("
|
|
308
|
+
raise ValueError(i18n.t("core.kvbuilder.insert_needs_dict"))
|
|
308
309
|
row_id = self._get_next_id()
|
|
309
310
|
await self._storage.aset(self._row_key(row_id), json.dumps(self._data, ensure_ascii=False))
|
|
310
311
|
return 1
|
|
311
312
|
if self._operation == "insert_multi":
|
|
312
313
|
if not isinstance(self._data, list):
|
|
313
|
-
raise ValueError("
|
|
314
|
+
raise ValueError(i18n.t("core.kvbuilder.insert_multi_needs_list"))
|
|
314
315
|
count = 0
|
|
315
316
|
for row in self._data:
|
|
316
317
|
row_id = self._get_next_id()
|
|
@@ -321,7 +322,7 @@ class KVQueryBuilder(BaseQueryBuilder):
|
|
|
321
322
|
return await self._aexec_select()
|
|
322
323
|
if self._operation == "update":
|
|
323
324
|
if not isinstance(self._data, dict):
|
|
324
|
-
raise ValueError("
|
|
325
|
+
raise ValueError(i18n.t("core.kvbuilder.update_needs_dict"))
|
|
325
326
|
count = 0
|
|
326
327
|
for row_id, row in await self._ascan_rows():
|
|
327
328
|
if self._match_row(row):
|
|
@@ -336,7 +337,7 @@ class KVQueryBuilder(BaseQueryBuilder):
|
|
|
336
337
|
await self._storage.adelete(self._row_key(row_id))
|
|
337
338
|
count += 1
|
|
338
339
|
return count
|
|
339
|
-
raise ValueError(
|
|
340
|
+
raise ValueError(i18n.t("core.kvbuilder.unknown_operation", op=self._operation))
|
|
340
341
|
|
|
341
342
|
async def _aexec_select(self) -> list[tuple]:
|
|
342
343
|
rows = await self._ascan_rows()
|
|
@@ -8,7 +8,10 @@ from abc import ABC, abstractmethod
|
|
|
8
8
|
from typing import Any, TypedDict
|
|
9
9
|
|
|
10
10
|
from ...loaders.strategy import ModuleLoadStrategy
|
|
11
|
+
from ..config import config as config_mgr
|
|
11
12
|
from ..constants import DEFAULT_LAZY_LOADING_ENABLED, DEFAULT_MODULE_PRIORITY
|
|
13
|
+
from ..i18n import i18n
|
|
14
|
+
from ..logger import logger
|
|
12
15
|
|
|
13
16
|
|
|
14
17
|
class ModuleEvent(TypedDict):
|
|
@@ -154,7 +157,6 @@ class BaseModule(ABC):
|
|
|
154
157
|
|
|
155
158
|
if self.ConfigClass is None:
|
|
156
159
|
return
|
|
157
|
-
from ..config import config as config_mgr
|
|
158
160
|
from .config_schema import (
|
|
159
161
|
dataclass_to_defaults_dict,
|
|
160
162
|
)
|
|
@@ -167,8 +169,7 @@ class BaseModule(ABC):
|
|
|
167
169
|
config_mgr.setConfig(key, data, immediate=True)
|
|
168
170
|
# 懒加载 logger(模块可能未注入 sdk)
|
|
169
171
|
try:
|
|
170
|
-
|
|
171
|
-
logger.info(f"已生成 {key} 默认配置模板")
|
|
172
|
+
logger.info(i18n.t("core.module.config_template_generated", key=key))
|
|
172
173
|
except ImportError:
|
|
173
174
|
pass
|
|
174
175
|
|
|
@@ -212,9 +213,8 @@ class BaseModule(ABC):
|
|
|
212
213
|
"""
|
|
213
214
|
if self.ConfigClass is None:
|
|
214
215
|
raise AttributeError(
|
|
215
|
-
"
|
|
216
|
+
i18n.t("core.module.config_class_not_declared")
|
|
216
217
|
)
|
|
217
|
-
from ..config import config as config_mgr
|
|
218
218
|
from .config_schema import dict_to_dataclass
|
|
219
219
|
|
|
220
220
|
data = config_mgr.getConfig(self._get_config_key())
|
|
@@ -230,7 +230,6 @@ class BaseModule(ABC):
|
|
|
230
230
|
if value is not None:
|
|
231
231
|
from dataclasses import asdict
|
|
232
232
|
|
|
233
|
-
from ..config import config as config_mgr
|
|
234
233
|
|
|
235
234
|
try:
|
|
236
235
|
config_mgr.setConfig(self._get_config_key(), asdict(value))
|