新增小红书、XMPP、元宝、Zalo 四个渠道扩展。 小红书渠道扩展主要模块:config, gateway, webhook, outbound, streaming, pairing, security, dedupe, media, status, window XMPP 渠道扩展主要模块:plugin, config, gateway, outbound, streaming, pairing, security, dedupe, accounts, commands, muc, rate_limiter, stanza_utils, status, monitor 元宝渠道扩展主要模块:plugin, client, config_schema, gateway, outbound(chunk/queue/transport), inbound(dispatcher), streaming, pairing, security, accounts, actions, commands, codec(biz/conn), session, shared, utils Zalo 渠道扩展主要模块:api, config, gateway, webhook, outbound, pairing, security, session, polling, monitor, status
50 lines
1.4 KiB
Python
50 lines
1.4 KiB
Python
import logging
|
|
|
|
logger = logging.getLogger("yuxi.channel.xmpp.security")
|
|
|
|
|
|
def check_xmpp_allowlist(peer_id: str, allowlist: list[str]) -> bool:
|
|
if not allowlist:
|
|
return False
|
|
if "*" in allowlist:
|
|
return True
|
|
bare = _extract_bare_jid(peer_id).lower()
|
|
for entry in allowlist:
|
|
if entry == "*":
|
|
return True
|
|
if _extract_bare_jid(entry).lower() == bare:
|
|
return True
|
|
return False
|
|
|
|
|
|
def is_xmpp_mentioned(nick: str, body: str) -> bool:
|
|
if not nick or not body:
|
|
return False
|
|
import re
|
|
|
|
pattern = re.compile(rf"\b{re.escape(nick)}\b[:,\s]?", re.IGNORECASE)
|
|
return bool(pattern.search(body))
|
|
|
|
|
|
def resolve_xmpp_dm_policy(account) -> str:
|
|
return getattr(account, "dm_policy", "open")
|
|
|
|
|
|
def resolve_xmpp_group_policy(account) -> str:
|
|
return getattr(account, "group_policy", "open")
|
|
|
|
|
|
def collect_xmpp_security_warnings(account) -> list[str]:
|
|
warnings = []
|
|
if getattr(account, "dm_policy", "open") == "open":
|
|
warnings.append("XMPP DM policy is 'open' — anyone can DM the bot")
|
|
if getattr(account, "group_policy", "open") == "open":
|
|
warnings.append("XMPP group policy is 'open' — any room can trigger bot replies")
|
|
if not getattr(account, "password", ""):
|
|
warnings.append("XMPP password is not configured")
|
|
return warnings
|
|
|
|
|
|
def _extract_bare_jid(jid: str) -> str:
|
|
return jid.split("/")[0]
|