ForcePilot/backend/package/yuxi/channel/extensions/weibo/menu.py
Kris 7215418610 feat(channel): 添加企业微信、微博、WhatsApp 和 Workplace 渠道扩展
新增企业微信、微博、WhatsApp、Workplace 四个渠道扩展。

企业微信渠道扩展主要模块:config, gateway, webhook, webhook_bot, outbound, streaming, pairing, security, crypto, dedupe, persistent_dedupe, card, directory, events, externalcontact, media, mentions, menu, message, oauth, status

微博渠道扩展主要模块:config, gateway, webhook, outbound, streaming, pairing, security, dedupe, passive_reply, broadcast, message, menu, media, subscription, template, status

WhatsApp 渠道扩展主要模块:config, gateway, webhook, outbound, streaming, pairing, security, dedupe, actions, monitor, status

Workplace 渠道扩展主要模块:config, gateway, webhook, outbound, streaming, pairing, security, dedupe, actions, challenge, groups, media, mentions, menu, monitor, persona, quick_reply, signature, subscriptions, template, threading, users, status
2026-05-21 12:01:56 +08:00

106 lines
3.1 KiB
Python

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