ForcePilot/backend/package/yuxi/channels/adapters/nostr/setup_plugin.py
Kris 7002557cf4 refactor(nostr): 整理代码结构并新增多项功能优化
1.  整理多个文件的导入顺序,移除冗余空行和重复导入
2.  为Nostr订阅添加until参数防止重复拉取
3.  实现长消息分块发送并添加间隔等待
4.  新增Relay健康分数同步任务
5.  新增TLS强制检查配置项并支持从环境变量加载
6.  重构状态恢复逻辑适配异步存储
7.  修复反应发送的参数错误
8.  新增线程模拟自动补全消息上下文
9.  添加解密指标统计和更完善的错误日志
2026-05-13 16:13:03 +08:00

99 lines
3.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)