101 lines
2.9 KiB
Python
101 lines
2.9 KiB
Python
from __future__ import annotations
|
|
|
|
import logging
|
|
from typing import Any
|
|
|
|
import httpx
|
|
|
|
from yuxi.channels.models import DeliveryResult
|
|
|
|
from .token import DingDingTokenManager
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
async def upload_media(
|
|
token_manager: DingDingTokenManager,
|
|
media_type: str,
|
|
media_data: bytes,
|
|
filename: str = "file",
|
|
*,
|
|
http_client: httpx.AsyncClient | None = None,
|
|
) -> dict[str, Any]:
|
|
token = await token_manager.get_token()
|
|
url = "https://api.dingtalk.com/v1.0/media/upload"
|
|
|
|
headers = {"x-acs-dingtalk-access-token": token}
|
|
files = {"media": (filename, media_data)}
|
|
params = {"type": media_type}
|
|
|
|
if http_client is not None:
|
|
resp = await http_client.post(url, headers=headers, files=files, params=params)
|
|
else:
|
|
async with httpx.AsyncClient(timeout=httpx.Timeout(30)) as client:
|
|
resp = await client.post(url, headers=headers, files=files, params=params)
|
|
|
|
if resp.status_code != 200:
|
|
logger.error(f"upload_media HTTP {resp.status_code}: {resp.text[:300]}")
|
|
raise RuntimeError(f"Media upload failed: HTTP {resp.status_code}")
|
|
return resp.json()
|
|
|
|
|
|
async def download_media(
|
|
token_manager: DingDingTokenManager,
|
|
download_code: str,
|
|
*,
|
|
http_client: httpx.AsyncClient | None = None,
|
|
) -> bytes:
|
|
token = await token_manager.get_token()
|
|
url = "https://api.dingtalk.com/v1.0/media/download"
|
|
|
|
headers = {"x-acs-dingtalk-access-token": token}
|
|
params = {"downloadCode": download_code}
|
|
|
|
if http_client is not None:
|
|
resp = await http_client.get(url, headers=headers, params=params)
|
|
else:
|
|
async with httpx.AsyncClient(timeout=httpx.Timeout(30)) as client:
|
|
resp = await client.get(url, headers=headers, params=params)
|
|
|
|
if resp.status_code != 200:
|
|
logger.error(f"download_media HTTP {resp.status_code}: {resp.text[:300]}")
|
|
raise RuntimeError(f"Media download failed: HTTP {resp.status_code}")
|
|
|
|
return resp.content
|
|
|
|
|
|
async def send_media(
|
|
token_manager: DingDingTokenManager,
|
|
open_conversation_id: str,
|
|
robot_code: str,
|
|
media_id: str,
|
|
media_type: str,
|
|
*,
|
|
chat_type: str = "direct",
|
|
http_client: httpx.AsyncClient | None = None,
|
|
) -> DeliveryResult:
|
|
try:
|
|
msg_key_map = {
|
|
"image": "sampleImageMsg",
|
|
"voice": "sampleAudio",
|
|
"file": "sampleFile",
|
|
"video": "sampleVideo",
|
|
}
|
|
msg_key = msg_key_map.get(media_type, "sampleFile")
|
|
msg_param = {"mediaId": media_id}
|
|
|
|
from .send import _send_msg
|
|
|
|
return await _send_msg(
|
|
token_manager,
|
|
open_conversation_id,
|
|
robot_code,
|
|
msg_key,
|
|
msg_param,
|
|
chat_type=chat_type,
|
|
http_client=http_client,
|
|
)
|
|
except Exception as e:
|
|
logger.error(f"send_media failed: {e}")
|
|
return DeliveryResult(success=False, error=str(e))
|