fix(sign_in): 修复签到命令 Rule 构造 NameError(MessageEvent 注解全局可见)
- rules.py 改为模块顶层导入 nonebot(NoneBot Rule 解析依赖参数注解在全局命名空间求值) - 权限纯函数 is_allowed 拆至 permission.py(无 nonebot 依赖,保持可测性) - 测试加载模块列表同步调整(config/api/service/permission)
This commit is contained in:
24
danding_bot/plugins/danding_sign_in/permission.py
Normal file
24
danding_bot/plugins/danding_sign_in/permission.py
Normal file
@@ -0,0 +1,24 @@
|
||||
"""独立签到插件 - 权限纯函数(无 nonebot 依赖,便于单元测试)。"""
|
||||
|
||||
from typing import Optional
|
||||
|
||||
|
||||
def is_allowed(
|
||||
user_id: int,
|
||||
group_id: Optional[int],
|
||||
*,
|
||||
allowed_group_id: int,
|
||||
allowed_user_id: int,
|
||||
) -> bool:
|
||||
"""签到权限纯函数:管理员任意场景可用;其他用户仅白名单群聊可用。
|
||||
|
||||
Args:
|
||||
user_id: 消息发送者 QQ
|
||||
group_id: 群聊 ID,非群聊场景为 None
|
||||
allowed_group_id: 白名单群聊
|
||||
allowed_user_id: 管理员 QQ
|
||||
"""
|
||||
|
||||
if user_id == allowed_user_id:
|
||||
return True
|
||||
return group_id is not None and group_id == allowed_group_id
|
||||
@@ -1,49 +1,21 @@
|
||||
"""独立签到插件 - 权限校验。
|
||||
"""独立签到插件 - 权限校验(NoneBot Rule)。
|
||||
|
||||
签到命令仅在白名单群聊(或管理员)中可用;私聊非管理员不可用。
|
||||
与 onmyoji_gacha 的规则不同:抽卡规则私聊放行,签到规则更严格(群聊白名单)。
|
||||
|
||||
注意:本模块必须顶层导入 nonebot(NoneBot Rule 解析依赖参数注解,
|
||||
注解名需要在模块全局命名空间可见),纯函数逻辑见 permission.py。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
from nonebot.rule import Rule
|
||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent
|
||||
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from nonebot.rule import Rule
|
||||
|
||||
|
||||
def is_allowed(
|
||||
user_id: int,
|
||||
group_id: Optional[int],
|
||||
*,
|
||||
allowed_group_id: int,
|
||||
allowed_user_id: int,
|
||||
) -> bool:
|
||||
"""签到权限纯函数:管理员任意场景可用;其他用户仅白名单群聊可用。
|
||||
|
||||
Args:
|
||||
user_id: 消息发送者 QQ
|
||||
group_id: 群聊 ID,非群聊场景为 None
|
||||
allowed_group_id: 白名单群聊
|
||||
allowed_user_id: 管理员 QQ
|
||||
"""
|
||||
|
||||
if user_id == allowed_user_id:
|
||||
return True
|
||||
return group_id is not None and group_id == allowed_group_id
|
||||
from .config import Config
|
||||
from .permission import is_allowed
|
||||
|
||||
|
||||
def check_permission() -> Rule:
|
||||
"""生成签到命令权限 Rule(白名单群聊 + 管理员)。
|
||||
|
||||
延迟导入 nonebot(与 config.py 同模式),保证纯函数在无 nonebot 的
|
||||
测试环境中可加载。
|
||||
"""
|
||||
|
||||
from nonebot.rule import Rule
|
||||
from nonebot.adapters.onebot.v11 import GroupMessageEvent, MessageEvent
|
||||
|
||||
from .config import Config
|
||||
"""生成签到命令权限 Rule(白名单群聊 + 管理员)。"""
|
||||
|
||||
config = Config()
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""独立签到插件(danding_sign_in)测试。
|
||||
|
||||
直接加载 config/api/service/rules 子模块,避免执行 nonebot 插件入口;
|
||||
直接加载 config/api/service/permission 子模块,避免执行 nonebot 插件入口;
|
||||
aiohttp 调用用 FakeSession/FakeResponse 替身 mock(与 test_onmyoji_gacha_http_api.py 同模式)。
|
||||
"""
|
||||
|
||||
@@ -15,7 +15,11 @@ import pytest
|
||||
|
||||
|
||||
def load_modules():
|
||||
"""直接加载 danding_sign_in 子模块,避免测试环境执行 nonebot 插件入口。"""
|
||||
"""直接加载 danding_sign_in 子模块,避免测试环境执行 nonebot 插件入口。
|
||||
|
||||
rules.py 顶层导入 nonebot(Rule 解析要求注解全局可见),无 nonebot 的
|
||||
测试环境不加载它;权限纯函数在 permission.py 中测试。
|
||||
"""
|
||||
|
||||
plugin_dir = Path(__file__).resolve().parents[1] / "danding_bot" / "plugins" / "danding_sign_in"
|
||||
package_name = "_danding_sign_in_under_test"
|
||||
@@ -23,7 +27,7 @@ def load_modules():
|
||||
package.__path__ = [str(plugin_dir)]
|
||||
sys.modules[package_name] = package
|
||||
|
||||
for module_name in ("config", "api", "service", "rules"):
|
||||
for module_name in ("config", "api", "service", "permission"):
|
||||
full_name = f"{package_name}.{module_name}"
|
||||
spec = importlib.util.spec_from_file_location(full_name, plugin_dir / f"{module_name}.py")
|
||||
module = importlib.util.module_from_spec(spec)
|
||||
@@ -35,15 +39,15 @@ def load_modules():
|
||||
sys.modules[f"{package_name}.config"],
|
||||
sys.modules[f"{package_name}.api"],
|
||||
sys.modules[f"{package_name}.service"],
|
||||
sys.modules[f"{package_name}.rules"],
|
||||
sys.modules[f"{package_name}.permission"],
|
||||
)
|
||||
|
||||
|
||||
config_module, api_module, service_module, rules_module = load_modules()
|
||||
config_module, api_module, service_module, permission_module = load_modules()
|
||||
Config = config_module.Config
|
||||
SignInAPI = api_module.SignInAPI
|
||||
perform_daily_sign_in = service_module.perform_daily_sign_in
|
||||
is_allowed = rules_module.is_allowed
|
||||
is_allowed = permission_module.is_allowed
|
||||
|
||||
|
||||
class FakeResponse:
|
||||
|
||||
Reference in New Issue
Block a user