import logging import httpx logger = logging.getLogger(__name__) MEDIA_UPLOAD_URL = "https://qyapi.weixin.qq.com/cgi-bin/media/upload" MEDIA_GET_URL = "https://qyapi.weixin.qq.com/cgi-bin/media/get" MEDIA_UPLOAD_IMG_URL = "https://qyapi.weixin.qq.com/cgi-bin/media/uploadimg" class WeComMedia: def __init__(self, gateway): self._gateway = gateway self._http: httpx.AsyncClient | None = None async def upload(self, media_type: str, file_path: str) -> str | None: token = self._gateway.access_token if not token: return None url = f"{MEDIA_UPLOAD_URL}?access_token={token}&type={media_type}" if self._http is None: self._http = httpx.AsyncClient(timeout=30.0) try: with open(file_path, "rb") as f: files = {"media": f} resp = await self._http.post(url, files=files) data = resp.json() if data.get("errcode") == 0: return data.get("media_id") logger.error("WeCom media upload failed: %s", data) return None except Exception: logger.exception("WeCom media upload error") return None async def download(self, media_id: str, save_path: str) -> bool: token = self._gateway.access_token if not token: return False url = f"{MEDIA_GET_URL}?access_token={token}&media_id={media_id}" if self._http is None: self._http = httpx.AsyncClient(timeout=30.0) try: resp = await self._http.get(url) with open(save_path, "wb") as f: f.write(resp.content) return True except Exception: logger.exception("WeCom media download error") return False async def close(self): if self._http: await self._http.aclose() self._http = None