新增企业微信、微博、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
106 lines
3.1 KiB
Python
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
|