1. 整理多个文件的导入顺序,移除冗余空行和重复导入 2. 为Nostr订阅添加until参数防止重复拉取 3. 实现长消息分块发送并添加间隔等待 4. 新增Relay健康分数同步任务 5. 新增TLS强制检查配置项并支持从环境变量加载 6. 重构状态恢复逻辑适配异步存储 7. 修复反应发送的参数错误 8. 新增线程模拟自动补全消息上下文 9. 添加解密指标统计和更完善的错误日志
99 lines
3.7 KiB
Python
99 lines
3.7 KiB
Python
from __future__ import annotations
|
||
|
||
from typing import Any
|
||
|
||
from yuxi.channels.adapters.nostr.config import NostrConfig
|
||
from yuxi.channels.adapters.nostr.crypto import NostrCrypto, NostrCryptoError
|
||
from yuxi.channels.adapters.nostr.setup import NostrSetupAdapter
|
||
|
||
|
||
class NostrSetupPlugin:
|
||
channel_id: str = "nostr"
|
||
channel_label: str = "Nostr (Decentralized)"
|
||
channel_description: str = "Nostr 去中心化社交网络 DM 协议配置向导"
|
||
|
||
def __init__(self, config: dict[str, Any] | None = None):
|
||
self._config = config or {}
|
||
self._setup_adapter = NostrSetupAdapter()
|
||
|
||
@property
|
||
def config(self) -> dict[str, Any]:
|
||
return self._config
|
||
|
||
def get_setup_wizard(self) -> dict[str, Any]:
|
||
return {
|
||
"channel_id": self.channel_id,
|
||
"label": self.channel_label,
|
||
"description": self.channel_description,
|
||
"steps": self._setup_adapter.get_setup_steps(),
|
||
"help": "详细文档请参考: /docs/channels/nostr",
|
||
}
|
||
|
||
async def validate_credentials(self, private_key: str) -> dict[str, Any]:
|
||
result = await self._setup_adapter.verify_key(private_key)
|
||
if result.get("success"):
|
||
return {"valid": True, "npub": result.get("npub"), "hex": result.get("hex")}
|
||
return {"valid": False, "error": result.get("error", "unknown")}
|
||
|
||
async def probe_connectivity(self, relays: list[str], timeout_ms: int = 8000) -> dict[str, Any]:
|
||
result = await self._setup_adapter.probe_relays(relays)
|
||
return {
|
||
"connected": result.get("success", False),
|
||
"reachable": result.get("reachable", 0),
|
||
"total": result.get("total", 0),
|
||
"details": result.get("details", []),
|
||
}
|
||
|
||
def get_recommendations(self) -> dict[str, Any]:
|
||
return {
|
||
"relays": [
|
||
"wss://relay.damus.io",
|
||
"wss://relay.primal.net",
|
||
"wss://relay.nostr.info",
|
||
"wss://nos.lol",
|
||
],
|
||
"dm_policy": "pairing",
|
||
"nip17_enabled": True,
|
||
"streaming_mode": "block",
|
||
}
|
||
|
||
async def validate_full_config(self, full_config: dict[str, Any]) -> dict[str, Any]:
|
||
errors: list[str] = []
|
||
warnings: list[str] = []
|
||
|
||
try:
|
||
NostrConfig.from_dict(full_config)
|
||
except Exception as e:
|
||
errors.append(f"配置验证失败: {e}")
|
||
return {"valid": False, "errors": errors, "warnings": warnings}
|
||
|
||
private_key = full_config.get("private_key") or full_config.get("accounts", {}).get("default", {}).get(
|
||
"private_key", ""
|
||
)
|
||
if private_key:
|
||
try:
|
||
NostrCrypto(private_key)
|
||
except NostrCryptoError as e:
|
||
errors.append(f"私钥无效: {e}")
|
||
else:
|
||
warnings.append("未配置私钥,将自动生成临时密钥")
|
||
|
||
relays = full_config.get("relays") or full_config.get("accounts", {}).get("default", {}).get("relays")
|
||
if not relays:
|
||
warnings.append("未配置 Relay,将使用默认 Relay 列表")
|
||
else:
|
||
invalid_relays = [r for r in relays if not r.startswith(("ws://", "wss://"))]
|
||
if invalid_relays:
|
||
warnings.append(f"以下 Relay URL 格式可能无效: {invalid_relays}")
|
||
|
||
return {"valid": len(errors) == 0, "errors": errors, "warnings": warnings}
|
||
|
||
|
||
def get_setup_plugin(config: dict[str, Any] | None = None) -> NostrSetupPlugin:
|
||
return NostrSetupPlugin(config)
|
||
|
||
|
||
async def verify_channel_setup(config: dict[str, Any]) -> dict[str, Any]:
|
||
plugin = NostrSetupPlugin(config)
|
||
return await plugin.validate_full_config(config)
|