新增腾讯 IM(Tencent IM)渠道扩展,支持在 Yuxi 平台中集成腾讯即时通讯 IM 渠道。 包含以下功能模块: - config: 渠道配置管理 - gateway: SSE/WebSocket 网关接入 - webhook: Webhook 事件处理 - outbound: 外发消息管理 - pairing: 用户配对与绑定 - security: 安全校验 - signature: 请求签名验证 - usersig: UserSig 生成 - dedupe: 消息去重 - status: 会话状态管理 - group: 群组管理 - types: 类型定义
215 lines
7.4 KiB
Python
215 lines
7.4 KiB
Python
import logging
|
|
|
|
from yuxi.channel.extensions.tencent_im.gateway import TencentIMError, TencentIMGateway
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
GROUP_TYPES = {
|
|
"public": "Public",
|
|
"private": "Private",
|
|
"chatroom": "ChatRoom",
|
|
"avchatroom": "AVChatRoom",
|
|
"topic": "Topic",
|
|
}
|
|
|
|
|
|
class TencentIMGroupManager:
|
|
def __init__(self, gateway: TencentIMGateway | None = None):
|
|
self._gateway = gateway
|
|
|
|
async def create_group(
|
|
self,
|
|
name: str,
|
|
group_type: str = "public",
|
|
owner_account: str = "",
|
|
member_list: list[str] | None = None,
|
|
) -> str:
|
|
if not self._gateway:
|
|
raise TencentIMError(-1, "gateway not started")
|
|
im_type = GROUP_TYPES.get(group_type, "Public")
|
|
body = {
|
|
"Owner_Account": owner_account or self._gateway._account.admin_userid,
|
|
"Type": im_type,
|
|
"Name": name,
|
|
}
|
|
if member_list:
|
|
body["MemberList"] = [{"Member_Account": uid} for uid in member_list]
|
|
result = await self._gateway.call_api("group_open_http_svc/create_group", body)
|
|
return result.get("GroupId", "")
|
|
|
|
async def destroy_group(self, group_id: str) -> bool:
|
|
if not self._gateway:
|
|
return False
|
|
await self._gateway.call_api(
|
|
"group_open_http_svc/destroy_group",
|
|
{
|
|
"GroupId": group_id,
|
|
},
|
|
)
|
|
return True
|
|
|
|
async def add_group_member(self, group_id: str, member_ids: list[str]) -> bool:
|
|
if not self._gateway:
|
|
return False
|
|
await self._gateway.call_api(
|
|
"group_open_http_svc/add_group_member",
|
|
{
|
|
"GroupId": group_id,
|
|
"MemberList": [{"Member_Account": uid} for uid in member_ids],
|
|
},
|
|
)
|
|
return True
|
|
|
|
async def delete_group_member(self, group_id: str, member_ids: list[str], reason: str = "") -> bool:
|
|
if not self._gateway:
|
|
return False
|
|
await self._gateway.call_api(
|
|
"group_open_http_svc/delete_group_member",
|
|
{
|
|
"GroupId": group_id,
|
|
"MemberToDel_Account": member_ids,
|
|
"Reason": reason,
|
|
},
|
|
)
|
|
return True
|
|
|
|
async def get_group_info(self, group_ids: list[str]) -> list[dict]:
|
|
if not self._gateway:
|
|
return []
|
|
result = await self._gateway.call_api(
|
|
"group_open_http_svc/get_group_info",
|
|
{"GroupIdList": [{"GroupId": gid} for gid in group_ids]},
|
|
)
|
|
return result.get("GroupInfo", [])
|
|
|
|
async def get_group_member_info(self, group_id: str, limit: int = 100, offset: int = 0) -> list[dict]:
|
|
if not self._gateway:
|
|
return []
|
|
result = await self._gateway.call_api(
|
|
"group_open_http_svc/get_group_member_info",
|
|
{"GroupId": group_id, "Limit": limit, "Offset": offset},
|
|
)
|
|
return result.get("MemberList", [])
|
|
|
|
async def forbid_send_msg(self, group_id: str, member_ids: list[str], shut_up_time: int = 60) -> bool:
|
|
if not self._gateway:
|
|
return False
|
|
await self._gateway.call_api(
|
|
"group_open_http_svc/forbid_send_msg",
|
|
{
|
|
"GroupId": group_id,
|
|
"Members_Account": member_ids,
|
|
"ShutUpTime": shut_up_time,
|
|
},
|
|
)
|
|
return True
|
|
|
|
async def get_group_muted_account(self, group_id: str) -> list[dict]:
|
|
if not self._gateway:
|
|
return []
|
|
result = await self._gateway.call_api(
|
|
"group_open_http_svc/get_group_muted_account",
|
|
{"GroupId": group_id},
|
|
)
|
|
return result.get("MutedAccountList", [])
|
|
|
|
async def modify_group_base_info(self, group_id: str, **kwargs) -> bool:
|
|
if not self._gateway:
|
|
return False
|
|
body = {"GroupId": group_id}
|
|
if "name" in kwargs:
|
|
body["Name"] = kwargs["name"]
|
|
if "introduction" in kwargs:
|
|
body["Introduction"] = kwargs["introduction"]
|
|
if "notification" in kwargs:
|
|
body["Notification"] = kwargs["notification"]
|
|
if "face_url" in kwargs:
|
|
body["FaceUrl"] = kwargs["face_url"]
|
|
if "max_member_num" in kwargs:
|
|
body["MaxMemberNum"] = kwargs["max_member_num"]
|
|
await self._gateway.call_api("group_open_http_svc/modify_group_base_info", body)
|
|
return True
|
|
|
|
async def get_appid_group_list(self, limit: int = 100, offset: int = 0, group_type: str = "") -> list[dict]:
|
|
if not self._gateway:
|
|
return []
|
|
body = {"Limit": limit, "Offset": offset}
|
|
if group_type:
|
|
body["GroupType"] = group_type
|
|
result = await self._gateway.call_api("group_open_http_svc/get_appid_group_list", body)
|
|
return result.get("GroupIdList", [])
|
|
|
|
async def get_joined_group_list(self, user_id: str, limit: int = 100, offset: int = 0) -> list[dict]:
|
|
if not self._gateway:
|
|
return []
|
|
result = await self._gateway.call_api(
|
|
"group_open_http_svc/get_joined_group_list",
|
|
{
|
|
"Member_Account": user_id,
|
|
"Limit": limit,
|
|
"Offset": offset,
|
|
},
|
|
)
|
|
return result.get("GroupIdList", [])
|
|
|
|
async def get_role_in_group(self, group_id: str, user_id: str) -> str:
|
|
if not self._gateway:
|
|
return ""
|
|
result = await self._gateway.call_api(
|
|
"group_open_http_svc/get_role_in_group",
|
|
{
|
|
"GroupId": group_id,
|
|
"User_Account": [user_id],
|
|
},
|
|
)
|
|
roles = result.get("UserIdList", [])
|
|
if roles:
|
|
return roles[0].get("Role", "")
|
|
return ""
|
|
|
|
async def modify_group_member_info(self, group_id: str, user_id: str, **kwargs) -> bool:
|
|
if not self._gateway:
|
|
return False
|
|
body = {"GroupId": group_id, "Member_Account": user_id}
|
|
if "name_card" in kwargs:
|
|
body["NameCard"] = kwargs["name_card"]
|
|
if "shut_up_time" in kwargs:
|
|
body["ShutUpUntil"] = kwargs["shut_up_time"]
|
|
await self._gateway.call_api("group_open_http_svc/modify_group_member_info", body)
|
|
return True
|
|
|
|
async def change_group_owner(self, group_id: str, new_owner_id: str) -> bool:
|
|
if not self._gateway:
|
|
return False
|
|
await self._gateway.call_api(
|
|
"group_open_http_svc/change_group_owner",
|
|
{"GroupId": group_id, "NewOwner_Account": new_owner_id},
|
|
)
|
|
return True
|
|
|
|
async def set_unread_msg_num(self, group_id: str, user_id: str, unread_num: int) -> bool:
|
|
if not self._gateway:
|
|
return False
|
|
await self._gateway.call_api(
|
|
"group_open_http_svc/set_unread_msg_num",
|
|
{
|
|
"GroupId": group_id,
|
|
"Member_Account": user_id,
|
|
"UnreadMsgNum": unread_num,
|
|
},
|
|
)
|
|
return True
|
|
|
|
async def group_msg_get_simple(self, group_id: str, req_msg_seq: int = 0, req_msg_number: int = 20) -> list[dict]:
|
|
if not self._gateway:
|
|
return []
|
|
result = await self._gateway.call_api(
|
|
"group_open_http_svc/group_msg_get_simple",
|
|
{
|
|
"GroupId": group_id,
|
|
"ReqMsgSeq": req_msg_seq,
|
|
"ReqMsgNumber": req_msg_number,
|
|
},
|
|
)
|
|
return result.get("RspMsgList", [])
|