ForcePilot/backend/package/yuxi/channel/extensions/weibo/menu.py

106 lines
3.1 KiB
Python
Raw Normal View History

import logging
import httpx
logger = logging.getLogger(__name__)
MENU_CREATE_URL = "https://m.api.weibo.com/2/messages/menu/create.json"
MENU_SHOW_URL = "https://m.api.weibo.com/2/messages/menu/show.json"
MENU_DELETE_URL = "https://m.api.weibo.com/2/messages/menu/delete.json"
class WeiboMenu:
def __init__(self, gateway=None):
self._gateway = gateway
self._http: httpx.AsyncClient | None = None
async def create(self, menus: list[dict]) -> bool:
"""
创建自定义菜单
menus 格式示例:
[
{
"name": "产品中心",
"sub_button": [
{"type": "click", "name": "产品A", "key": "product_a"},
{"type": "view", "name": "官网", "url": "https://example.com"},
]
},
{"type": "click", "name": "联系客服", "key": "contact"},
]
限制
- 一级菜单 1~3
- 二级菜单 1~5
- type 支持 click / view
"""
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 menu create")
return False
body = {"menus": menus}
try:
resp = await self._http.post(
MENU_CREATE_URL,
params={"access_token": token},
json=body,
)
data = resp.json()
if data.get("error_code"):
logger.error("Menu create failed: %s", data)
return False
logger.info("Menu created successfully")
return True
except Exception:
logger.exception("Menu create error")
return False
async def show(self) -> dict | None:
"""查询当前菜单配置"""
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:
return None
try:
resp = await self._http.get(
MENU_SHOW_URL,
params={"access_token": token},
)
return resp.json()
except Exception:
logger.exception("Menu show error")
return None
async def delete(self) -> bool:
"""删除当前菜单"""
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:
return False
try:
resp = await self._http.post(
MENU_DELETE_URL,
params={"access_token": token},
)
data = resp.json()
return "error_code" not in data
except Exception:
logger.exception("Menu delete error")
return False
async def close(self):
if self._http:
await self._http.aclose()
self._http = None