ForcePilot/backend/package/yuxi/channels/adapters/irc/accounts.py
Kris 2dd1a075f2 feat(irc): 实现完整的IRC适配器基础功能模块
新增IRC协议相关的全套工具模块,包括:
- 核心协议解析与CTCP处理
- 消息发送缓存与文本 sanitize
- 账号配置管理与运行时状态
- 命令处理与权限控制
- 服务发现与诊断工具
- 多账号网关与配置加载
2026-05-12 00:45:10 +08:00

132 lines
3.6 KiB
Python

from __future__ import annotations
import os
from copy import deepcopy
from typing import Any
def resolve_merged_account_config(
base_config: dict[str, Any],
account_config: dict[str, Any],
) -> dict[str, Any]:
merged = deepcopy(base_config)
_deep_merge(merged, account_config)
return merged
def _deep_merge(base: dict, override: dict) -> None:
for key, value in override.items():
if key in base and isinstance(base[key], dict) and isinstance(value, dict):
_deep_merge(base[key], value)
else:
base[key] = value
def list_irc_account_ids(config: dict[str, Any]) -> list[str]:
accounts = config.get("accounts", {})
if not isinstance(accounts, dict):
return []
return list(accounts.keys())
def list_enabled_irc_accounts(config: dict[str, Any]) -> list[dict[str, Any]]:
accounts = config.get("accounts", {})
if not isinstance(accounts, dict):
return []
result: list[dict[str, Any]] = []
base_config = _extract_base_config(config)
for account_id, account_config in accounts.items():
if not isinstance(account_config, dict):
continue
if account_config.get("enabled") is False:
continue
merged = resolve_merged_account_config(base_config, account_config)
merged["_account_id"] = account_id
result.append(merged)
return result
def _extract_base_config(config: dict[str, Any]) -> dict[str, Any]:
top_level_keys = {
"server",
"port",
"use_tls",
"nick",
"username",
"realname",
"password",
"sasl_username",
"sasl_password",
"use_sasl",
"nickserv_service",
"nickserv_password",
"nickserv_password_file",
"nickserv_register",
"nickserv_register_email",
"nickserv_enabled",
"auto_join_channels",
"nick_recovery",
"dm_policy",
"group_policy",
"allowFrom",
"groupAllowFrom",
"groups",
"dangerouslyAllowNameMatching",
"groupAllowFromFallbackToAllowFrom",
"connect_timeout",
"probe_timeout",
"chunker_mode",
"commands",
"reply_enabled",
"markdown",
"server_password",
"server_password_file",
}
return {k: v for k, v in config.items() if k in top_level_keys and v}
def get_account_config(
config: dict[str, Any],
account_id: str,
) -> dict[str, Any] | None:
accounts = config.get("accounts", {})
if not isinstance(accounts, dict):
return None
account_config = accounts.get(account_id)
if not isinstance(account_config, dict):
return None
if account_config.get("enabled") is False:
return None
base_config = _extract_base_config(config)
merged = resolve_merged_account_config(base_config, account_config)
merged["_account_id"] = account_id
return merged
def is_configured(config: dict[str, Any]) -> bool:
host = config.get("server", "") or os.environ.get("IRC_HOST", "")
nick = config.get("nick", "") or os.environ.get("IRC_NICK", "")
return bool(host and nick)
def has_configured_state() -> bool:
return bool(os.environ.get("IRC_HOST", "") and os.environ.get("IRC_NICK", ""))
def resolve_default_irc_account_id(
config: dict[str, Any],
default: str = "default",
) -> str:
accounts = config.get("accounts", {})
if isinstance(accounts, dict) and default in accounts:
return default
account_ids = list_irc_account_ids(config)
if account_ids:
return account_ids[0]
return default