新增 Telegram 渠道扩展,支持在 Yuxi 平台中集成 Telegram 即时通讯渠道。 包含以下功能模块: - config: 渠道配置管理 - gateway: SSE/WebSocket 网关接入 - webhook: Webhook 事件处理 - polling: 长轮询模式 - outbound: 外发消息管理 - streaming: 流式消息处理 - pairing: 用户配对与绑定 - security: 安全校验 - dedupe: 消息去重 - monitor: 渠道状态监控 - status: 会话状态管理 - session: 会话管理 - actions: 动作处理 - inline_keyboard: 内联键盘 - native_commands: 原生指令 - chat: 聊天管理 - delivery: 消息送达确认 - media: 媒体资源处理 - profile: 用户资料 - reactions: 表情反应 - sticker: 贴纸处理 - types: 类型定义
86 lines
2.4 KiB
Python
86 lines
2.4 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
from enum import StrEnum
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class TelegramAction(StrEnum):
|
|
REACT = "react"
|
|
SEND = "send"
|
|
POLL = "poll"
|
|
STICKER = "sticker"
|
|
DELETE = "delete"
|
|
EDIT = "edit"
|
|
TYPING = "typing"
|
|
|
|
|
|
class ReactionLevel(StrEnum):
|
|
OFF = "off"
|
|
ACK = "ack"
|
|
MINIMAL = "minimal"
|
|
|
|
|
|
REACTION_LEVEL_EMOJI = {
|
|
"typing": "👀",
|
|
"done": "✅",
|
|
"error": "❌",
|
|
"thinking": "🤔",
|
|
}
|
|
|
|
|
|
def resolve_reaction_emoji(level: str, action: str = "typing") -> str | None:
|
|
if level == "off":
|
|
return None
|
|
if level == "ack" and action == "typing":
|
|
return REACTION_LEVEL_EMOJI["typing"]
|
|
if level == "minimal":
|
|
return REACTION_LEVEL_EMOJI.get(action)
|
|
return None
|
|
|
|
|
|
class TelegramActions:
|
|
@staticmethod
|
|
async def react(
|
|
outbound, target_id: str, message_id: str, level: str, account_id: str | None = None,
|
|
) -> None:
|
|
emoji = resolve_reaction_emoji(level, "typing")
|
|
if not emoji:
|
|
return
|
|
await outbound.send_reaction(target_id, message_id, emoji, account_id=account_id)
|
|
|
|
@staticmethod
|
|
async def clear_reaction(
|
|
outbound, target_id: str, message_id: str, account_id: str | None = None,
|
|
) -> None:
|
|
try:
|
|
await outbound.send_reaction(target_id, message_id, "", account_id=account_id)
|
|
except Exception:
|
|
logger.debug("Failed to clear reaction", exc_info=True)
|
|
|
|
@staticmethod
|
|
async def send_typing(
|
|
outbound, target_id: str, thread_id: str | None = None, account_id: str | None = None,
|
|
) -> None:
|
|
await outbound.send_typing(target_id, thread_id=thread_id, account_id=account_id)
|
|
|
|
@staticmethod
|
|
async def delete_message(
|
|
outbound, target_id: str, message_id: str, account_id: str | None = None,
|
|
) -> None:
|
|
await outbound.delete_message(target_id, message_id, account_id=account_id)
|
|
|
|
@staticmethod
|
|
def get_action_whitelist(account: dict) -> list[str]:
|
|
actions = []
|
|
if account.get("actions_send_message", True):
|
|
actions.append("send")
|
|
if account.get("actions_reactions", True):
|
|
actions.append("react")
|
|
if account.get("actions_poll", True):
|
|
actions.append("poll")
|
|
if account.get("actions_sticker", True):
|
|
actions.append("sticker")
|
|
return actions
|