ForcePilot/backend/package/yuxi/channels/adapters/qqbot/voice_send.py

178 lines
5.5 KiB
Python
Raw Normal View History

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"