ForcePilot/backend/package/yuxi/channels/adapters/telegram/voice.py
Kris 71fec609bb feat(telegram-adapter): 实现完整的Telegram适配器基础代码
新增了Telegram适配器的全套基础模块,包括:
1.  核心适配器入口与会话工具
2.  账号管理、认证与配置系统
3.  连接相关的轮询、Webhook、更新偏移管理
4.  话题路由、管理与缓存系统
5.  消息反抖动、超时配置与工具类
6.  响应式UI与命令交互系统
7.  反应表情与通知系统
8.  审批与安全审计模块
9.  健康检查与状态监控
10. 贴纸缓存与视觉工具
11. 流式响应与协作功能
12. 群组迁移与目标归一化处理
2026-05-12 00:49:52 +08:00

129 lines
3.1 KiB
Python

from __future__ import annotations
import io
from typing import Any
from telegram import Bot
from telegram.error import TelegramError
from yuxi.utils.logging_config import logger
_VOICE_COMPATIBLE_FORMATS = frozenset({"ogg", "opus", "flac", "wav", "m4a", "mp3", "aac"})
def is_voice_compatible_audio(filename: str) -> bool:
ext = filename.rsplit(".", 1)[-1].lower() if "." in filename else ""
return ext in _VOICE_COMPATIBLE_FORMATS
async def send_voice_from_bytes(
bot: Bot,
chat_id: str,
audio_bytes: bytes,
filename: str = "voice.ogg",
duration: int | None = None,
caption: str | None = None,
**kwargs,
) -> Any:
try:
buf = io.BytesIO(audio_bytes)
buf.name = filename
return await bot.send_voice(
chat_id=chat_id,
voice=buf,
duration=duration,
caption=caption,
**kwargs,
)
except TelegramError as e:
logger.error(f"[Telegram] Failed to send voice: {e}")
raise
async def send_audio_from_bytes(
bot: Bot,
chat_id: str,
audio_bytes: bytes,
filename: str = "audio.mp3",
title: str | None = None,
performer: str | None = None,
duration: int | None = None,
caption: str | None = None,
**kwargs,
) -> Any:
try:
buf = io.BytesIO(audio_bytes)
buf.name = filename
return await bot.send_audio(
chat_id=chat_id,
audio=buf,
title=title,
performer=performer,
duration=duration,
caption=caption,
**kwargs,
)
except TelegramError as e:
logger.error(f"[Telegram] Failed to send audio: {e}")
raise
async def send_voice_or_audio(
bot: Bot,
chat_id: str,
audio_bytes: bytes,
filename: str = "audio.ogg",
as_voice: bool = False,
duration: int | None = None,
caption: str | None = None,
title: str | None = None,
performer: str | None = None,
**kwargs,
) -> Any:
if as_voice or is_voice_compatible_audio(filename):
return await send_voice_from_bytes(
bot,
chat_id,
audio_bytes,
filename=filename or "voice.ogg",
duration=duration,
caption=caption,
**kwargs,
)
return await send_audio_from_bytes(
bot,
chat_id,
audio_bytes,
filename=filename or "audio.mp3",
title=title,
performer=performer,
duration=duration,
caption=caption,
**kwargs,
)
async def send_video_note_from_bytes(
bot: Bot,
chat_id: str,
video_bytes: bytes,
filename: str = "video_note.mp4",
duration: int | None = None,
length: int | None = None,
**kwargs,
) -> Any:
try:
buf = io.BytesIO(video_bytes)
buf.name = filename
return await bot.send_video_note(
chat_id=chat_id,
video_note=buf,
duration=duration,
length=length,
**kwargs,
)
except TelegramError as e:
logger.error(f"[Telegram] Failed to send video note: {e}")
raise