ForcePilot/backend/package/yuxi/channel/sdk/targets/envelope.py
Kris b438af3ba8 feat(channel-sdk): 新增完整的渠道SDK工具链
本提交新增了全渠道SDK核心模块:
1.  异步锁、目标解析、动作调度等基础工具
2.  消息动作注册与统一调度系统
3.  测试套件与契约测试框架
4.  完整的目标解析流水线与工具函数
5.  资源依赖注入与生命周期管理
2026-05-21 10:29:12 +08:00

63 lines
2.0 KiB
Python

from yuxi.channel.message.models import UnifiedMessage
from yuxi.channel.sdk.targets.extractors import TargetFieldExtractor, TelegramTargetExtractor
from yuxi.channel.sdk.targets.pipeline import TargetResolverPipeline
class TargetToEnvelopeAdapter:
def __init__(
self,
pipeline: TargetResolverPipeline,
self_user_ids: dict[str, set[str]],
*,
extractor: TargetFieldExtractor | None = None,
):
self._pipeline = pipeline
self._self_user_ids = self_user_ids
self._extractor = extractor or TelegramTargetExtractor()
async def build(
self,
raw_message: dict,
*,
channel: str,
account_id: str,
) -> UnifiedMessage | None:
sender = self._extractor.extract_sender(raw_message)
if self._is_echo(sender.id, channel, account_id):
return None
return self._assemble_message(raw_message, sender, channel, account_id)
def _is_echo(self, sender_id: str, channel: str, account_id: str) -> bool:
key = f"{channel}:{account_id}"
self_ids = self._self_user_ids.get(key)
if not self_ids:
return False
return sender_id in self_ids
def _assemble_message(
self,
raw_message: dict,
sender,
channel: str,
account_id: str,
) -> UnifiedMessage:
content = self._extractor.extract_content(raw_message)
media_urls = self._extractor.extract_media_urls(raw_message)
msg_type = self._extractor.detect_message_type(raw_message)
group = self._extractor.extract_group(raw_message)
msg_id = self._extractor.extract_message_id(raw_message)
return UnifiedMessage(
msg_id=msg_id,
message_type=msg_type,
content=content,
sender=sender,
channel_type=channel,
account_id=account_id,
group=group,
media_urls=media_urls,
raw_payload=raw_message,
)