import json import logging import httpx logger = logging.getLogger(__name__) POST_URL = "https://m.api.weibo.com/2/messages/post.json" REMIND_URL = "https://m.api.weibo.com/2/messages/send.json" class WeiboSubscription: """订阅用户推送 + 消息提醒""" def __init__(self, gateway=None): self._gateway = gateway self._http: httpx.AsyncClient | None = None async def post_to_subscriber( self, receiver_id: int, msg_type: str, content: dict, ) -> dict | None: """ 向已订阅用户发送私信消息(messages/post)。 仅对已订阅用户(发送过 DY)有效。 msg_type: text / articles / position / image / voice """ if self._http is None: self._http = httpx.AsyncClient(timeout=15.0) token = self._gateway.access_token if self._gateway else None if not token: logger.error("No access_token for subscription post") return None payload = { "access_token": token, "receiver_id": receiver_id, "type": msg_type, "data": json.dumps(content), } try: resp = await self._http.post(POST_URL, data=payload) data = resp.json() if data.get("error_code"): logger.error("Subscription post failed: %s", data) return data except Exception: logger.exception("Subscription post error") return None async def send_reminder( self, receiver_id: int, text: str, ) -> dict | None: """ 发送消息提醒(messages/send)。 根据粉丝设置的提醒条件发送私信提醒。 """ if self._http is None: self._http = httpx.AsyncClient(timeout=15.0) token = self._gateway.access_token if self._gateway else None if not token: logger.error("No access_token for reminder") return None payload = { "access_token": token, "receiver_id": receiver_id, "type": "text", "data": json.dumps({"text": text}), } try: resp = await self._http.post(REMIND_URL, data=payload) data = resp.json() if data.get("error_code"): logger.error("Reminder send failed: %s", data) return data except Exception: logger.exception("Reminder send error") return None async def close(self): if self._http: await self._http.aclose() self._http = None