基于 qqbotsdk-py 的入群验证:进群发按钮验证码、完成前禁言、 超时踢出(11253 时兜底长期禁言)、乱点他人按钮处罚、状态持久化 与重启恢复。38 个单元/集成测试。
71 lines
2.3 KiB
Python
71 lines
2.3 KiB
Python
"""验证业务配置:SDK 的 .env(AppID/AppSecret 等)之上再读验证参数。
|
||
|
||
全部项都有内置默认值,.env 里按需覆盖;取值越界或非法启动即报错。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import os
|
||
from dataclasses import dataclass
|
||
from pathlib import Path
|
||
|
||
from dotenv import load_dotenv
|
||
|
||
# 幂等:qqbotsdk 导入时也会 load_dotenv(),且不会覆盖已存在的环境变量
|
||
load_dotenv()
|
||
|
||
|
||
def _int_env(name: str, default: int, lo: int, hi: int) -> int:
|
||
raw = os.getenv(name, "").strip()
|
||
if not raw:
|
||
return default
|
||
try:
|
||
value = int(raw)
|
||
except ValueError:
|
||
raise ValueError(f"{name} 应为整数,实际: {raw!r}") from None
|
||
if not lo <= value <= hi:
|
||
raise ValueError(f"{name} 应在 {lo}~{hi} 之间,实际: {value}")
|
||
return value
|
||
|
||
|
||
def _bool_env(name: str, default: bool) -> bool:
|
||
raw = os.getenv(name, "").strip().lower()
|
||
if not raw:
|
||
return default
|
||
if raw in ("1", "true", "yes", "on"):
|
||
return True
|
||
if raw in ("0", "false", "no", "off"):
|
||
return False
|
||
raise ValueError(f"{name} 应为 true/false,实际: {raw!r}")
|
||
|
||
|
||
@dataclass(frozen=True, slots=True)
|
||
class AuthConfig:
|
||
"""验证业务参数,含义与默认值见 .env.example。"""
|
||
|
||
verify_timeout_minutes: int
|
||
pending_mute_hours: int
|
||
timeout_kick: bool
|
||
timeout_fallback_mute_hours: int
|
||
captcha_options: int
|
||
verified_trust_days: int
|
||
foreign_click_limit: int
|
||
foreign_click_mute_minutes: int
|
||
data_dir: Path
|
||
|
||
@classmethod
|
||
def load(cls) -> "AuthConfig":
|
||
return cls(
|
||
verify_timeout_minutes=_int_env("VERIFY_TIMEOUT_MINUTES", 10, 1, 1440),
|
||
pending_mute_hours=_int_env("PENDING_MUTE_HOURS", 24, 1, 24 * 30),
|
||
timeout_kick=_bool_env("TIMEOUT_KICK", True),
|
||
timeout_fallback_mute_hours=_int_env(
|
||
"TIMEOUT_FALLBACK_MUTE_HOURS", 72, 1, 24 * 30
|
||
),
|
||
captcha_options=_int_env("CAPTCHA_OPTIONS", 4, 2, 5),
|
||
verified_trust_days=_int_env("VERIFIED_TRUST_DAYS", 0, 0, 365),
|
||
foreign_click_limit=_int_env("FOREIGN_CLICK_LIMIT", 3, 1, 100),
|
||
foreign_click_mute_minutes=_int_env("FOREIGN_CLICK_MUTE_MINUTES", 5, 1, 1440),
|
||
data_dir=Path(os.getenv("DATA_DIR", "data")),
|
||
)
|