from __future__ import annotations import aiohttp from yuxi.channels.models import DeliveryResult from yuxi.utils.logging_config import logger from .constants import DM_CHAT_PREFIX, GROUP_CHAT_PREFIX from .media_upload import ( FILE_TYPE_VOICE, build_media_payload, upload_media, validate_media_size, ) async def send_voice( voice_data: bytes, chat_id: str, token: str, http_client: aiohttp.ClientSession, api_base: str, filename: str = "voice.mp3", max_size_mb: int = 100, ) -> DeliveryResult: validate_media_size(voice_data, max_size_mb=max_size_mb, label="voice") group_openid = None if chat_id.startswith(GROUP_CHAT_PREFIX): group_openid = chat_id.replace(GROUP_CHAT_PREFIX, "") try: file_id = await upload_media( voice_data, token, http_client=http_client, filename=filename, file_type=FILE_TYPE_VOICE, group_openid=group_openid, ) except Exception as e: return DeliveryResult(success=False, error=f"Voice upload failed: {e}") payload = build_media_payload(chat_id, file_id, msg_type=7) url = _resolve_media_send_url(api_base, chat_id) headers = { "Authorization": f"QQBot {token}", "Content-Type": "application/json", } try: async with http_client.post(url, json=payload, headers=headers) as resp: if resp.status == 200: data = await resp.json() return DeliveryResult( success=True, message_id=data.get("id") or data.get("message_id"), ) return DeliveryResult(success=False, error=f"Voice send failed: HTTP {resp.status}") except Exception as e: logger.error(f"[QQBot] Voice send error: {e}") return DeliveryResult(success=False, error=str(e)) async def send_video( video_data: bytes, chat_id: str, token: str, http_client: aiohttp.ClientSession, api_base: str, filename: str = "video.mp4", max_size_mb: int = 100, ) -> DeliveryResult: from .media_upload import FILE_TYPE_VIDEO validate_media_size(video_data, max_size_mb=max_size_mb, label="video") group_openid = None if chat_id.startswith(GROUP_CHAT_PREFIX): group_openid = chat_id.replace(GROUP_CHAT_PREFIX, "") try: file_id = await upload_media( video_data, token, http_client=http_client, filename=filename, file_type=FILE_TYPE_VIDEO, group_openid=group_openid, ) except Exception as e: return DeliveryResult(success=False, error=f"Video upload failed: {e}") payload = build_media_payload(chat_id, file_id, msg_type=7) url = _resolve_media_send_url(api_base, chat_id) headers = { "Authorization": f"QQBot {token}", "Content-Type": "application/json", } try: async with http_client.post(url, json=payload, headers=headers) as resp: if resp.status == 200: data = await resp.json() return DeliveryResult( success=True, message_id=data.get("id") or data.get("message_id"), ) return DeliveryResult(success=False, error=f"Video send failed: HTTP {resp.status}") except Exception as e: logger.error(f"[QQBot] Video send error: {e}") return DeliveryResult(success=False, error=str(e)) async def send_file( file_data: bytes, chat_id: str, token: str, http_client: aiohttp.ClientSession, api_base: str, filename: str = "file.bin", max_size_mb: int = 100, ) -> DeliveryResult: from .media_upload import FILE_TYPE_FILE validate_media_size(file_data, max_size_mb=max_size_mb, label="file") group_openid = None if chat_id.startswith(GROUP_CHAT_PREFIX): group_openid = chat_id.replace(GROUP_CHAT_PREFIX, "") try: file_id = await upload_media( file_data, token, http_client=http_client, filename=filename, file_type=FILE_TYPE_FILE, group_openid=group_openid, ) except Exception as e: return DeliveryResult(success=False, error=f"File upload failed: {e}") payload = build_media_payload(chat_id, file_id, msg_type=7) url = _resolve_media_send_url(api_base, chat_id) headers = { "Authorization": f"QQBot {token}", "Content-Type": "application/json", } try: async with http_client.post(url, json=payload, headers=headers) as resp: if resp.status == 200: data = await resp.json() return DeliveryResult( success=True, message_id=data.get("id") or data.get("message_id"), ) return DeliveryResult(success=False, error=f"File send failed: HTTP {resp.status}") except Exception as e: logger.error(f"[QQBot] File send error: {e}") return DeliveryResult(success=False, error=str(e)) def _resolve_media_send_url(api_base: str, chat_id: str) -> str: if chat_id.startswith(GROUP_CHAT_PREFIX): group_openid = chat_id.replace(GROUP_CHAT_PREFIX, "") return f"{api_base}/v2/groups/{group_openid}/messages" elif chat_id.startswith(DM_CHAT_PREFIX): openid = chat_id.replace(DM_CHAT_PREFIX, "") return f"{api_base}/v2/users/{openid}/messages" elif chat_id: return f"{api_base}/v2/channels/{chat_id}/messages" return f"{api_base}/v2/users/@me/messages"