新增 iMessage 通道适配器完整实现,包含: 1. 核心适配器与工具工厂导出 2. 运行时存储、反射防护、会话路由等基础组件 3. 消息信封、线程管理、回复上下文格式化 4. Tapback 表情反应处理、自定义异常体系 5. 审批按钮、联系人解析、速率限制功能 6. 文本净化、目标解析、缓存管理模块 7. 配置 schema、多账户支持、安装向导等配置模块 8. 审计日志、媒体AI处理等扩展功能
117 lines
3.6 KiB
Python
117 lines
3.6 KiB
Python
from __future__ import annotations
|
|
|
|
from enum import StrEnum
|
|
|
|
from pydantic import BaseModel, Field, field_validator
|
|
|
|
|
|
class DmPolicyEnum(StrEnum):
|
|
PAIRING = "pairing"
|
|
ALLOWLIST = "allowlist"
|
|
OPEN = "open"
|
|
DISABLED = "disabled"
|
|
|
|
|
|
class GroupPolicyEnum(StrEnum):
|
|
OPEN = "open"
|
|
ALLOWLIST = "allowlist"
|
|
DISABLED = "disabled"
|
|
|
|
|
|
class IMessageConnectionConfig(BaseModel):
|
|
server_url: str = "http://localhost:1234"
|
|
password: str = ""
|
|
probe_timeout_ms: int = Field(default=10000, ge=1000, le=60000)
|
|
max_retries: int = Field(default=3, ge=1, le=10)
|
|
http_timeout_s: float = Field(default=30.0, ge=1.0, le=300.0)
|
|
|
|
|
|
class IMessageSecurityConfigSchema(BaseModel):
|
|
dm_policy: DmPolicyEnum = DmPolicyEnum.PAIRING
|
|
group_policy: GroupPolicyEnum = GroupPolicyEnum.ALLOWLIST
|
|
allow_from: list[str] = Field(default_factory=list)
|
|
group_allow_from: list[str] = Field(default_factory=list)
|
|
require_mention: bool = False
|
|
|
|
@field_validator("dm_policy", mode="before")
|
|
@classmethod
|
|
def coerce_dm_policy(cls, v):
|
|
if isinstance(v, str):
|
|
try:
|
|
return DmPolicyEnum(v)
|
|
except ValueError:
|
|
return DmPolicyEnum.PAIRING
|
|
return v
|
|
|
|
@field_validator("group_policy", mode="before")
|
|
@classmethod
|
|
def coerce_group_policy(cls, v):
|
|
if isinstance(v, str):
|
|
try:
|
|
return GroupPolicyEnum(v)
|
|
except ValueError:
|
|
return GroupPolicyEnum.ALLOWLIST
|
|
return v
|
|
|
|
|
|
class GroupOverrideConfig(BaseModel):
|
|
enabled: bool | None = None
|
|
require_mention: bool | None = None
|
|
tools: list[str] | None = None
|
|
|
|
|
|
class IMessageAccountConfig(BaseModel):
|
|
account_id: str = "default"
|
|
name: str = ""
|
|
connection: IMessageConnectionConfig = Field(default_factory=IMessageConnectionConfig)
|
|
security: IMessageSecurityConfigSchema = Field(default_factory=IMessageSecurityConfigSchema)
|
|
enabled: bool = True
|
|
default_to: str = ""
|
|
|
|
|
|
class IMessageFullConfig(BaseModel):
|
|
name: str = "iMessage"
|
|
connection: IMessageConnectionConfig = Field(default_factory=IMessageConnectionConfig)
|
|
security: IMessageSecurityConfigSchema = Field(default_factory=IMessageSecurityConfigSchema)
|
|
|
|
config_writes: bool = True
|
|
block_streaming: bool = False
|
|
text_chunk_limit: int = Field(default=4096, ge=100, le=16000)
|
|
media_max_mb: int = Field(default=100, ge=1, le=1000)
|
|
history_limit: int = Field(default=20, ge=1, le=200)
|
|
|
|
default_account: str = ""
|
|
default_to: str = ""
|
|
accounts: dict[str, IMessageAccountConfig] = Field(default_factory=dict)
|
|
|
|
include_attachments: bool = False
|
|
attachment_roots: list[str] = Field(default_factory=list)
|
|
remote_attachment_roots: list[str] = Field(default_factory=list)
|
|
|
|
groups: dict[str, GroupOverrideConfig] = Field(default_factory=dict)
|
|
|
|
ws_reconnect_initial_delay: float = Field(default=5.0, ge=0.5, le=120.0)
|
|
ws_reconnect_max_delay: float = Field(default=60.0, ge=1.0, le=600.0)
|
|
|
|
loop_rate_limit: int = Field(default=5, ge=0, le=50)
|
|
loop_rate_window_s: float = Field(default=60.0, ge=1.0, le=600.0)
|
|
loop_cooldown_s: float = Field(default=120.0, ge=1.0, le=3600.0)
|
|
|
|
@field_validator("accounts", mode="before")
|
|
@classmethod
|
|
def coerce_accounts(cls, v):
|
|
if v is None:
|
|
return {}
|
|
if isinstance(v, list):
|
|
return {a.account_id: a for a in v}
|
|
return v
|
|
|
|
|
|
def validate_config(config: dict) -> IMessageFullConfig:
|
|
"""校验并标准化 iMessage 配置。
|
|
|
|
Raises:
|
|
ValidationError: 配置不符合 Schema 时抛出。
|
|
"""
|
|
return IMessageFullConfig(**config)
|