新增IRC协议相关的全套工具模块,包括: - 核心协议解析与CTCP处理 - 消息发送缓存与文本 sanitize - 账号配置管理与运行时状态 - 命令处理与权限控制 - 服务发现与诊断工具 - 多账号网关与配置加载
88 lines
2.7 KiB
Python
88 lines
2.7 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass, field
|
|
from typing import Any
|
|
|
|
from .security import (
|
|
IRCSecurityConfig,
|
|
_find_mutable_allowlist_entries,
|
|
)
|
|
|
|
|
|
@dataclass
|
|
class DoctorDiagnosis:
|
|
status: str = "ok"
|
|
warnings: list[str] = field(default_factory=list)
|
|
errors: list[str] = field(default_factory=list)
|
|
checks: list[dict[str, Any]] = field(default_factory=list)
|
|
|
|
|
|
def diagnose(
|
|
config: dict[str, Any],
|
|
security_config: IRCSecurityConfig | None = None,
|
|
use_tls: bool = True,
|
|
nickserv_enabled: bool = False,
|
|
nickserv_register: bool = False,
|
|
) -> DoctorDiagnosis:
|
|
result = DoctorDiagnosis()
|
|
|
|
_check_tls(result, use_tls)
|
|
_check_nickserv(result, nickserv_enabled, nickserv_register)
|
|
if security_config:
|
|
_check_policies(result, security_config)
|
|
_check_mutable_allowlist(result, security_config)
|
|
|
|
return result
|
|
|
|
|
|
def _check_tls(result: DoctorDiagnosis, use_tls: bool) -> None:
|
|
check = {"name": "tls", "status": "ok"}
|
|
if not use_tls:
|
|
check["status"] = "warning"
|
|
check["message"] = "TLS is disabled — connection is not encrypted"
|
|
result.warnings.append(check["message"])
|
|
result.checks.append(check)
|
|
|
|
|
|
def _check_nickserv(
|
|
result: DoctorDiagnosis,
|
|
nickserv_enabled: bool,
|
|
nickserv_register: bool,
|
|
) -> None:
|
|
check = {"name": "nickserv", "status": "ok"}
|
|
if not nickserv_enabled:
|
|
check["status"] = "warning"
|
|
check["message"] = "NickServ is not enabled — nick may not be reserved"
|
|
result.warnings.append(check["message"])
|
|
elif nickserv_register:
|
|
check["status"] = "warning"
|
|
check["message"] = (
|
|
"nickserv.register is enabled — after first successful registration "
|
|
"consider removing this config to avoid repeated REGISTER commands"
|
|
)
|
|
result.warnings.append(check["message"])
|
|
result.checks.append(check)
|
|
|
|
|
|
def _check_policies(
|
|
result: DoctorDiagnosis,
|
|
security_config: IRCSecurityConfig,
|
|
) -> None:
|
|
check = {"name": "group_policy", "status": "ok"}
|
|
if security_config.group_policy == "open":
|
|
check["status"] = "warning"
|
|
check["message"] = "Group policy is 'open' — anyone can trigger bot in channels"
|
|
result.warnings.append(check["message"])
|
|
result.checks.append(check)
|
|
|
|
|
|
def _check_mutable_allowlist(
|
|
result: DoctorDiagnosis,
|
|
security_config: IRCSecurityConfig,
|
|
) -> None:
|
|
mutable_entries = _find_mutable_allowlist_entries(security_config)
|
|
for entry in mutable_entries:
|
|
msg = f"Mutable allowlist entry detected: '{entry}' — consider using nick!user@host format"
|
|
result.warnings.append(msg)
|
|
result.checks.append({"name": "mutable_allowlist", "status": "warning", "message": msg})
|