ForcePilot/backend/package/yuxi/channels/adapters/matrix/profile_sync.py
Kris 2063145ce1 feat(matrix): 新增完整的Matrix适配器工具集
新增了20+个Matrix相关工具模块,包含线程处理、自动加入、消息去重、配置管理、安全策略、媒体处理、命令解析等功能,完善Matrix适配器基础能力
2026-05-12 00:45:54 +08:00

92 lines
2.3 KiB
Python

from __future__ import annotations
import hashlib
import re
from typing import Any
from urllib.parse import urlparse
_MXC_URL_PATTERN = re.compile(r"^mxc://([^/]+)/(.+)$")
_HTTP_URL_PATTERN = re.compile(r"^https?://")
def resolve_avatar_url(raw_url: str, homeserver: str | None = None) -> str | None:
if not raw_url:
return None
if _MXC_URL_PATTERN.match(raw_url):
return raw_url
if _HTTP_URL_PATTERN.match(raw_url):
if homeserver:
return _http_to_mxc(raw_url, homeserver)
return raw_url
return None
def _http_to_mxc(http_url: str, homeserver: str) -> str:
media_id = hashlib.sha256(http_url.encode()).hexdigest()[:24]
if homeserver.startswith("http"):
hs_domain = urlparse(homeserver).hostname or "matrix.org"
else:
hs_domain = homeserver
return f"mxc://{hs_domain}/{media_id}"
def resolve_display_name(
profile_data: dict[str, Any],
fallback_user_id: str = "",
) -> str:
displayname = profile_data.get("displayname", "")
if displayname:
return displayname.strip()
user_id = profile_data.get("user_id", fallback_user_id)
if user_id and user_id.startswith("@"):
localpart = user_id[1:].split(":")[0]
return localpart
return user_id or "unknown"
def compare_profiles(
current: dict[str, Any],
incoming: dict[str, Any],
) -> dict[str, tuple[Any, Any]]:
changes: dict[str, tuple[Any, Any]] = {}
for key in ("displayname", "avatar_url"):
old_val = current.get(key)
new_val = incoming.get(key)
if old_val != new_val:
changes[key] = (old_val, new_val)
return changes
def build_profile_update(
display_name: str = "",
avatar_url: str = "",
) -> dict[str, Any]:
result: dict[str, Any] = {}
if display_name:
result["displayname"] = display_name
if avatar_url:
result["avatar_url"] = avatar_url
return result
def mxc_to_http(mxc_url: str, homeserver: str) -> str:
match = _MXC_URL_PATTERN.match(mxc_url)
if not match:
return mxc_url
base = homeserver.rstrip("/")
if not base.startswith("http"):
base = f"https://{base}"
server_name = match.group(1)
media_id = match.group(2)
return f"{base}/_matrix/media/r0/download/{server_name}/{media_id}"