新增企业微信、微博、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
141 lines
5.0 KiB
Python
141 lines
5.0 KiB
Python
import logging
|
|
|
|
import httpx
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
LIST_URL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/list"
|
|
GET_URL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get"
|
|
BATCH_GET_URL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/batch/get_by_user"
|
|
GET_TAGS_URL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/get_corp_tag_list"
|
|
GROUPCHAT_LIST_URL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/groupchat/list"
|
|
GROUPCHAT_GET_URL = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/groupchat/get"
|
|
|
|
|
|
class WeComExternalContact:
|
|
def __init__(self, gateway):
|
|
self._gateway = gateway
|
|
self._http: httpx.AsyncClient | None = None
|
|
|
|
@property
|
|
def _token(self) -> str | None:
|
|
return self._gateway.access_token if self._gateway else None
|
|
|
|
async def list_customers(self, user_id: str) -> list[str]:
|
|
token = self._token
|
|
if not token:
|
|
return []
|
|
url = f"{LIST_URL}?access_token={token}&userid={user_id}"
|
|
try:
|
|
resp = await self._get_http().get(url)
|
|
data = resp.json()
|
|
if data.get("errcode") == 0:
|
|
return data.get("external_userid", [])
|
|
logger.warning("WeCom list_customers failed: %s", data)
|
|
return []
|
|
except Exception:
|
|
logger.exception("WeCom list_customers error")
|
|
return []
|
|
|
|
async def get_customer(self, external_userid: str) -> dict | None:
|
|
token = self._token
|
|
if not token:
|
|
return None
|
|
url = f"{GET_URL}?access_token={token}&external_userid={external_userid}"
|
|
try:
|
|
resp = await self._get_http().get(url)
|
|
data = resp.json()
|
|
if data.get("errcode") == 0:
|
|
return data.get("external_contact")
|
|
logger.warning("WeCom get_customer failed: %s", data)
|
|
return None
|
|
except Exception:
|
|
logger.exception("WeCom get_customer error")
|
|
return None
|
|
|
|
async def batch_get_customers(self, user_id: str, cursor: str = "") -> dict:
|
|
token = self._token
|
|
if not token:
|
|
return {}
|
|
url = f"{BATCH_GET_URL}?access_token={token}"
|
|
try:
|
|
resp = await self._get_http().post(url, json={"userid": user_id, "cursor": cursor})
|
|
data = resp.json()
|
|
if data.get("errcode") == 0:
|
|
return data
|
|
logger.warning("WeCom batch_get_customers failed: %s", data)
|
|
return {}
|
|
except Exception:
|
|
logger.exception("WeCom batch_get_customers error")
|
|
return {}
|
|
|
|
async def get_corp_tags(self, tag_ids: list[str] | None = None) -> list[dict]:
|
|
token = self._token
|
|
if not token:
|
|
return []
|
|
url = f"{GET_TAGS_URL}?access_token={token}"
|
|
body: dict = {}
|
|
if tag_ids:
|
|
body["tag_id"] = tag_ids
|
|
try:
|
|
resp = await self._get_http().post(url, json=body)
|
|
data = resp.json()
|
|
if data.get("errcode") == 0:
|
|
return data.get("tag_group", [])
|
|
logger.warning("WeCom get_corp_tags failed: %s", data)
|
|
return []
|
|
except Exception:
|
|
logger.exception("WeCom get_corp_tags error")
|
|
return []
|
|
|
|
async def list_groupchats(
|
|
self,
|
|
status_filter: int = 0,
|
|
owner_filter: dict | None = None,
|
|
cursor: str = "",
|
|
limit: int = 100,
|
|
) -> dict:
|
|
token = self._token
|
|
if not token:
|
|
return {}
|
|
url = f"{GROUPCHAT_LIST_URL}?access_token={token}"
|
|
body: dict = {"status_filter": status_filter, "cursor": cursor, "limit": limit}
|
|
if owner_filter:
|
|
body["owner_filter"] = owner_filter
|
|
try:
|
|
resp = await self._get_http().post(url, json=body)
|
|
data = resp.json()
|
|
if data.get("errcode") == 0:
|
|
return data
|
|
logger.warning("WeCom list_groupchats failed: %s", data)
|
|
return {}
|
|
except Exception:
|
|
logger.exception("WeCom list_groupchats error")
|
|
return {}
|
|
|
|
async def get_groupchat(self, chat_id: str) -> dict | None:
|
|
token = self._token
|
|
if not token:
|
|
return None
|
|
url = f"{GROUPCHAT_GET_URL}?access_token={token}"
|
|
try:
|
|
resp = await self._get_http().post(url, json={"chat_id": chat_id})
|
|
data = resp.json()
|
|
if data.get("errcode") == 0:
|
|
return data.get("group_chat")
|
|
logger.warning("WeCom get_groupchat failed: %s", data)
|
|
return None
|
|
except Exception:
|
|
logger.exception("WeCom get_groupchat error")
|
|
return None
|
|
|
|
def _get_http(self) -> httpx.AsyncClient:
|
|
if self._http is None:
|
|
self._http = httpx.AsyncClient(timeout=15.0)
|
|
return self._http
|
|
|
|
async def close(self):
|
|
if self._http:
|
|
await self._http.aclose()
|
|
self._http = None
|