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