# !/usr/bin/env python3
# -*- coding: utf-8 -*-
from io import BufferedReader
from json import loads
from json.decoder import JSONDecodeError
from os.path import exists
from time import time
from typing import BinaryIO, Dict, List, Optional, Tuple, Union

from . import _api_model
from ._utils import (
    empty_temp,
    http_temp,
    objectize,
    regular_temp,
    sdk_error_temp,
    security_header,
    security_wrapper,
)
from .http import FormData_
from .utils import convert_color


class AsyncAPI:
    def __init__(self, bot_url, session, logger, check_warning):
        self.bot_url = bot_url
        self._mini_id = None
        self._mini_secret = None
        self._session = session
        self.logger = logger
        self.check_warning = check_warning
        self.security_code = ""
        self.code_expire = 0

    def security_setup(self, mini_id: str, mini_secret: str):
        self._mini_id = mini_id
        self._mini_secret = mini_secret

    @security_wrapper
    async def __security_check_code(self):
        if self._mini_secret is None:
            self.logger.error("无法调用内容安全检测接口（备注：没有填入小程序密钥）")
            return None
        return_ = await self._session.get(
            f"https://api.q.qq.com/api/getToken?grant_type=client_credential&"
            f"appid={self._mini_id}&secret={self._mini_secret}"
        )
        resp = await return_.json()
        code = resp.get("access_token")
        if not code:
            self.logger.error(
                f"无法调用内容安全检测接口（code: {return_.status}, content: {await return_.text()}）"
            )
            return None
        self.security_code = code
        self.code_expire = time() + 7000
        return self.security_code

    @security_wrapper
    async def security_check(self, content: str) -> bool:
        """
        腾讯小程序侧内容安全检测接口，使用此接口必须填入bot_secret密钥

        :param content: 需要检测的内容
        :return: True或False（bool），代表是否通过安全检测
        """
        if not self.security_code or time() >= self.code_expire:
            await self.__security_check_code()
        return_ = await self._session.post(
            f"https://api.q.qq.com/api/json/security/MsgSecCheck?access_token={self.security_code}",
            json={"content": content},
            headers=security_header,
        )
        check = await return_.json()
        self.logger.debug(f"[安全接口] {check}")
        if check.get("errCode") in (-1800110107, -1800110108, -1800110109):
            await self.__security_check_code()
            return_ = await self._session.post(
                f"https://api.q.qq.com/api/json/security/MsgSecCheck?access_token={self.security_code}",
                json={"content": content},
                headers=security_header,
            )
            check = await return_.json()
            self.logger.debug(f"[安全接口] {check}")
        if check["errCode"] == 0:
            return True
        return False

    async def get_bot_info(self) -> _api_model.get_bot_info():
        """
        获取机器人详情

        :return:返回的.data中为解析后的json数据
        """
        return_ = await self._session.get(f"{self.bot_url}/users/@me")
        return await regular_temp(return_)

    async def get_bot_guilds(self) -> _api_model.get_bot_guilds():
        """
        获取机器人所在的所有频道列表

        :return: 返回的.data中为包含所有数据的一个list，列表每个项均为object数据
        """
        trace_ids = []
        codes = []
        results = []
        data = []
        return_dict = None
        try:
            while True:
                if return_dict is None:
                    return_ = await self._session.get(
                        f"{self.bot_url}/users/@me/guilds"
                    )
                elif len(return_dict) == 100:
                    return_ = await self._session.get(
                        f'{self.bot_url}/users/@me/guilds?after={return_dict[-1]["id"]}'
                    )
                else:
                    break
                trace_ids.append(return_.headers["X-Tps-Trace-Id"])
                codes.append(return_.status)
                return_dict = await return_.json()
                if isinstance(return_dict, dict) and "code" in return_dict.keys():
                    results.append(False)
                    data.append(return_dict)
                    break
                else:
                    results.append(True)
                    for items in return_dict:
                        data.append(items)
        except (JSONDecodeError, AttributeError, KeyError):
            return objectize(
                {"data": [], "trace_id": trace_ids, "http_code": codes, "result": False}
            )
        return objectize(
            {"data": data, "trace_id": trace_ids, "http_code": codes, "result": results}
        )

    async def get_guild_info(self, guild_id: str) -> _api_model.get_guild_info():
        """
        获取频道详情信息

        :param guild_id: 频道id
        :return: 返回的.data中为解析后的json数据
        """
        return_ = await self._session.get(f"{self.bot_url}/guilds/{guild_id}")
        return await regular_temp(return_)

    async def get_guild_channels(
        self, guild_id: str
    ) -> _api_model.get_guild_channels():
        """
        获取频道的所有子频道列表数据

        :param guild_id: 频道id
        :return: 返回的.data中为解析后的json数据
        """
        return_ = await self._session.get(f"{self.bot_url}/guilds/{guild_id}/channels")
        return await regular_temp(return_)

    async def get_channels_info(
        self, channel_id: str
    ) -> _api_model.get_channels_info():
        """
        获取子频道数据

        :param channel_id: 子频道id
        :return: 返回的.data中为解析后的json数据
        """
        return_ = await self._session.get(f"{self.bot_url}/channels/{channel_id}")
        return await regular_temp(return_)

    async def create_channels(
        self,
        guild_id: str,
        name: str,
        type_: int,
        position: int,
        parent_id: str,
        sub_type: int,
        private_type: int,
        private_user_ids: List[str],
        speak_permission: int,
        application_id: Optional[str] = None,
    ) -> _api_model.create_channels():
        """
        用于在 guild_id 指定的频道下创建一个子频道，一般仅私域机器人可用

        :param guild_id: 频道id
        :param name: 需要创建的子频道名
        :param type_: 需要创建的子频道类型
        :param position: 需要创建的子频道位置
        :param parent_id: 需要创建的子频道所属分组ID
        :param sub_type: 需要创建的子频道子类型
        :param private_type: 需要创建的子频道私密类型
        :param private_user_ids: 需要创建的子频道私密类型成员ID列表
        :param speak_permission: 需要创建的子频道发言权限
        :param application_id: 需要创建的应用类型子频道应用 AppID，仅应用子频道需要该字段
        :return: 返回的.data中为解析后的json数据
        """
        self.check_warning("创建子频道")
        json_ = {
            "name": name,
            "type": type_,
            "position": position,
            "parent_id": parent_id,
            "sub_type": sub_type,
            "private_type": private_type,
            "private_user_ids": private_user_ids,
            "speak_permission": speak_permission,
            "application_id": application_id,
        }
        return_ = await self._session.post(
            f"{self.bot_url}/guilds/{guild_id}/channels", json=json_
        )
        return await regular_temp(return_)

    async def patch_channels(
        self,
        channel_id: str,
        name: Optional[str] = None,
        position: Optional[int] = None,
        parent_id: Optional[str] = None,
        private_type: Optional[int] = None,
        speak_permission: Optional[int] = None,
    ) -> _api_model.patch_channels():
        """
        用于修改 channel_id 指定的子频道的信息，需要修改哪个字段，就传递哪个字段即可

        :param channel_id: 目标子频道ID
        :param name: 子频道名
        :param position: 子频道排序
        :param parent_id: 子频道所属分组id
        :param private_type: 子频道私密类型
        :param speak_permission: 子频道发言权限
        :return: 返回的.data中为解析后的json数据
        """
        self.check_warning("修改子频道")
        json_ = {
            "name": name,
            "position": position,
            "parent_id": parent_id,
            "private_type": private_type,
            "speak_permission": speak_permission,
        }
        return_ = await self._session.patch(
            f"{self.bot_url}/channels/{channel_id}", json=json_
        )
        return await regular_temp(return_)

    async def delete_channels(self, channel_id) -> _api_model.delete_channels():
        """
        用于删除 channel_id 指定的子频道

        :param channel_id: 子频道id
        :return: 返回的.result显示是否成功
        """
        self.check_warning("删除子频道")
        return_ = await self._session.delete(f"{self.bot_url}/channels/{channel_id}")
        return await http_temp(return_, 200)

    async def get_guild_members(self, guild_id: str) -> _api_model.get_guild_members():
        """
        用于获取 guild_id 指定的频道中所有成员的详情列表

        :param guild_id: 频道id
        :return: 返回的.data中为包含所有数据的一个list，列表每个项均为object数据
        """
        trace_ids = []
        codes = []
        results = []
        data = []
        return_dict = None
        try:
            while True:
                if return_dict is None:
                    return_ = await self._session.get(
                        f"{self.bot_url}/guilds/{guild_id}/members?limit=400"
                    )
                elif not return_dict:
                    break
                else:
                    return_ = await self._session.get(
                        f"{self.bot_url}/guilds/{guild_id}/members?limit=400&after="
                        + return_dict[-1]["user"]["id"]
                    )
                trace_ids.append(return_.headers["X-Tps-Trace-Id"])
                codes.append(return_.status)
                return_dict = await return_.json()
                if isinstance(return_dict, dict) and "code" in return_dict.keys():
                    results.append(False)
                    data.append(return_dict)
                    break
                else:
                    results.append(True)
                    for items in return_dict:
                        if items not in data:
                            data.append(items)
        except (JSONDecodeError, AttributeError, KeyError):
            return objectize(
                {
                    "data": [],
                    "trace_id": trace_ids,
                    "http_code": codes,
                    "result": [False],
                }
            )
        if data:
            return objectize(
                {
                    "data": data,
                    "trace_id": trace_ids,
                    "http_code": codes,
                    "result": results,
                }
            )
        else:
            return objectize(
                {
                    "data": [],
                    "trace_id": trace_ids,
                    "http_code": codes,
                    "result": [False],
                }
            )

    async def get_role_members(
        self, guild_id: str, role_id: str
    ) -> _api_model.get_role_members():
        """
        用于获取 guild_id 频道中指定 role_id 身份组下所有成员的详情列表

        :param guild_id: 频道id
        :param role_id: 身份组id
        :return: 返回的.data中为包含所有数据的一个list，列表每个项均为object数据
        """
        trace_ids = []
        codes = []
        results = []
        data = []
        return_dict = None
        start_index = 0
        try:
            while True:
                if return_dict is not None and not return_dict.get("data"):
                    break
                return_ = await self._session.get(
                    f"{self.bot_url}/guilds/{guild_id}/roles/{role_id}/members?"
                    f"limit=400&start_index={start_index}"
                )
                trace_ids.append(return_.headers["X-Tps-Trace-Id"])
                codes.append(return_.status)
                return_dict = await return_.json()
                if isinstance(return_dict, dict) and "code" in return_dict.keys():
                    results.append(False)
                    data.append(return_dict)
                    break
                else:
                    results.append(True)
                    for items in return_dict.get("data", {}):
                        if items not in data:
                            data.append(items)
                    start_index = return_dict.get("next")
                    if not start_index:
                        break
        except (JSONDecodeError, AttributeError, KeyError):
            return objectize(
                {
                    "data": [],
                    "trace_id": trace_ids,
                    "http_code": codes,
                    "result": [False],
                }
            )
        if data:
            return objectize(
                {
                    "data": data,
                    "trace_id": trace_ids,
                    "http_code": codes,
                    "result": results,
                }
            )
        else:
            return objectize(
                {
                    "data": [],
                    "trace_id": trace_ids,
                    "http_code": codes,
                    "result": [False],
                }
            )

    async def get_member_info(
        self, guild_id: str, user_id: str
    ) -> _api_model.get_member_info():
        """
        用于获取 guild_id 指定的频道中 user_id 对应成员的详细信息

        :param guild_id: 频道id
        :param user_id: 成员id
        :return: 返回的.data中为解析后的json数据
        """
        return_ = await self._session.get(
            f"{self.bot_url}/guilds/{guild_id}/members/{user_id}"
        )
        return await regular_temp(return_)

    async def delete_member(
        self,
        guild_id: str,
        user_id: str,
        add_blacklist: bool = False,
        delete_history_msg_days: int = 0,
    ) -> _api_model.delete_member():
        """
        用于删除 guild_id 指定的频道下的成员 user_id

        :param guild_id: 频道ID
        :param user_id: 目标用户ID
        :param add_blacklist: 是否同时添加黑名单
        :param delete_history_msg_days: 用于撤回该成员的消息，可以指定撤回消息的时间范围
        :return: 返回的.result显示是否成功
        """
        self.check_warning("删除频道成员")
        if delete_history_msg_days not in (3, 7, 15, 30, 0, -1):
            return sdk_error_temp("注意delete_history_msg_days的数值只能是3，7，15，30，0，-1")
        json_ = {
            "add_blacklist": add_blacklist,
            "delete_history_msg_days": delete_history_msg_days,
        }
        return_ = await self._session.delete(
            f"{self.bot_url}/guilds/{guild_id}/members/{user_id}", json=json_
        )
        return await http_temp(return_, 204)

    async def get_guild_roles(self, guild_id: str) -> _api_model.get_guild_roles():
        """
        用于获取 guild_id指定的频道下的身份组列表

        :param guild_id: 频道id
        :return: 返回的.data中为解析后的json数据
        """
        return_ = await self._session.get(f"{self.bot_url}/guilds/{guild_id}/roles")
        return await regular_temp(return_)

    async def create_role(
        self,
        guild_id: str,
        name: Optional[str] = None,
        hoist: Optional[bool] = None,
        color: Optional[Union[str, Tuple[int, int, int]]] = None,
    ) -> _api_model.create_role():
        """
        用于在 guild_id 指定的频道下创建一个身份组

        :param guild_id: 频道id
        :param name: 身份组名（选填)
        :param hoist: 是否在成员列表中单独展示（选填）
        :param color: 身份组颜色，支持输入RGB的三位tuple或HEX的sting颜色（选填)
        :return: 返回的.data中为解析后的json数据
        """
        if hoist is not None:
            if hoist:
                hoist_ = 1
            else:
                hoist_ = 0
        else:
            hoist_ = None
        if color is not None:
            color_ = convert_color(color)
        else:
            color_ = None
        json_ = {"name": name, "color": color_, "hoist": hoist_}
        return_ = await self._session.post(
            f"{self.bot_url}/guilds/{guild_id}/roles", json=json_
        )
        return await regular_temp(return_)

    async def patch_role(
        self,
        guild_id: str,
        role_id: str,
        name: Optional[str] = None,
        hoist: Optional[bool] = None,
        color: Optional[Union[str, Tuple[int, int, int]]] = None,
    ) -> _api_model.patch_role():
        """
        用于修改频道 guild_id 下 role_id 指定的身份组

        :param guild_id: 频道id
        :param role_id: 需要修改的身份组ID
        :param name: 身份组名（选填)
        :param hoist: 是否在成员列表中单独展示（选填）
        :param color: 身份组颜色，支持输入RGB的三位tuple或HEX的sting颜色（选填)
        :return: 返回的.data中为解析后的json数据
        """
        if hoist is not None:
            if hoist:
                hoist_ = 1
            else:
                hoist_ = 0
        else:
            hoist_ = None
        if color is not None:
            color_ = convert_color(color)
        else:
            color_ = None
        json_ = {"name": name, "color": color_, "hoist": hoist_}
        return_ = await self._session.patch(
            f"{self.bot_url}/guilds/{guild_id}/roles/{role_id}", json=json_
        )
        return await regular_temp(return_)

    async def delete_role(
        self, guild_id: str, role_id: str
    ) -> _api_model.delete_role():
        """
        用于删除频道 guild_id下 role_id 对应的身份组

        :param guild_id: 频道ID
        :param role_id: 需要删除的身份组ID
        :return: 返回的.result显示是否成功
        """
        return_ = await self._session.delete(
            f"{self.bot_url}/guilds/{guild_id}/roles/{role_id}"
        )
        return await http_temp(return_, 204)

    async def create_role_member(
        self,
        user_id: str,
        guild_id: str,
        role_id: str,
        channel_id: Optional[str] = None,
    ) -> _api_model.role_members():
        """
        为频道指定成员添加指定身份组

        :param user_id: 目标用户的id
        :param guild_id: 目标频道guild id
        :param role_id: 身份组编号，可从例如get_roles函数获取
        :param channel_id: 如果要增加的身份组ID是5-子频道管理员，需要输入此项来指定具体是哪个子频道
        :return: 返回的.result显示是否成功
        """
        if role_id == "5":
            if channel_id is not None:
                return_ = await self._session.put(
                    f"{self.bot_url}/guilds/{guild_id}/members/{user_id}/roles/"
                    f"{role_id}",
                    json={"channel": {"id": channel_id}},
                )
            else:
                return sdk_error_temp(
                    "注意如果要增加的身份组ID是5-子频道管理员，需要输入channel_id项来指定具体是哪个子频道"
                )
        else:
            return_ = await self._session.put(
                f"{self.bot_url}/guilds/{guild_id}/members/{user_id}/roles/{role_id}"
            )
        return await http_temp(return_, 204)

    async def delete_role_member(
        self,
        user_id: str,
        guild_id: str,
        role_id: str,
        channel_id: Optional[str] = None,
    ) -> _api_model.role_members():
        """
        删除频道指定成员的指定身份组

        :param user_id: 目标用户的id
        :param guild_id: 目标频道guild id
        :param role_id: 身份组编号，可从例如get_roles函数获取
        :param channel_id: 如果要增加的身份组ID是5-子频道管理员，需要输入此项来指定具体是哪个子频道
        :return: 返回的.result显示是否成功
        """
        if role_id == "5":
            if channel_id is not None:
                return_ = await self._session.delete(
                    f"{self.bot_url}/guilds/{guild_id}/members/{user_id}/roles/"
                    f"{role_id}",
                    json={"channel": {"id": channel_id}},
                )
            else:
                return sdk_error_temp(
                    "注意如果要增加的身份组ID是5-子频道管理员，需要输入channel_id项来指定具体是哪个子频道"
                )
        else:
            return_ = await self._session.delete(
                f"{self.bot_url}/guilds/{guild_id}/members/{user_id}/roles/{role_id}"
            )
        return await http_temp(return_, 204)

    async def get_channel_member_permission(
        self, channel_id: str, user_id: str
    ) -> _api_model.get_channel_member_permission():
        """
        用于获取 子频道 channel_id 下用户 user_id 的权限

        :param channel_id: 子频道id
        :param user_id: 用户id
        :return: 返回的.data中为解析后的json数据
        """
        return_ = await self._session.get(
            f"{self.bot_url}/channels/{channel_id}/members/{user_id}/permissions"
        )
        return await regular_temp(return_)

    async def put_channel_member_permission(
        self,
        channel_id: str,
        user_id: str,
        add: Optional[str] = None,
        remove: Optional[str] = None,
    ) -> _api_model.put_channel_mr_permission():
        """
        用于修改子频道 channel_id 下用户 user_id 的权限

        :param channel_id: 子频道id
        :param user_id: 用户id
        :param add: 需要添加的权限，string格式，可选：1，2，4，8
        :param remove:需要删除的权限，string格式，可选：1，2，4，8
        :return: 返回的.result显示是否成功
        """
        if not all([items in ("1", "2", "4", "8", None) for items in (add, remove)]):
            return sdk_error_temp("注意add或remove的值只能为为1、2、4或8的文本格式内容")
        json_ = {"add": add, "remove": remove}
        return_ = await self._session.put(
            f"{self.bot_url}/channels/{channel_id}/members/{user_id}/permissions",
            json=json_,
        )
        return await http_temp(return_, 204)

    async def get_channel_role_permission(
        self, channel_id: str, role_id: str
    ) -> _api_model.get_channel_role_permission():
        """
        用于获取 子频道 channel_id 下身份组 role_id 的权限

        :param channel_id: 子频道id
        :param role_id: 身份组id
        :return: 返回的.data中为解析后的json数据
        """
        return_ = await self._session.get(
            f"{self.bot_url}/channels/{channel_id}/roles/{role_id}/permissions"
        )
        return await regular_temp(return_)

    async def put_channel_role_permission(
        self,
        channel_id: str,
        role_id: str,
        add: Optional[str] = None,
        remove: Optional[str] = None,
    ) -> _api_model.put_channel_mr_permission():
        """
        用于修改子频道 channel_id 下身份组 role_id 的权限

        :param channel_id: 子频道id
        :param role_id: 身份组id
        :param add: 需要添加的权限，string格式，可选：1，2，4，8
        :param remove:需要删除的权限，string格式，可选：1，2，4，8
        :return: 返回的.result显示是否成功
        """
        if not all([items in ("1", "2", "4", "8", None) for items in (add, remove)]):
            return sdk_error_temp("注意add或remove的值只能为为1、2、4或8的文本格式内容")
        json_ = {"add": add, "remove": remove}
        return_ = await self._session.put(
            f"{self.bot_url}/channels/{channel_id}/roles/{role_id}/permissions",
            json=json_,
        )
        return await http_temp(return_, 204)

    async def get_message_info(
        self, channel_id: str, message_id: str
    ) -> _api_model.get_message_info():
        """
        用于获取子频道 channel_id 下的消息 message_id 的详情

        :param channel_id: 频道ID
        :param message_id: 目标消息ID
        :return: 返回的.data中为解析后的json数据
        """
        return_ = await self._session.get(
            f"{self.bot_url}/channels/{channel_id}/messages/{message_id}"
        )
        return await regular_temp(return_)

    async def send_msg(
        self,
        channel_id: str,
        content: Optional[str] = None,
        image: Optional[str] = None,
        file_image: Optional[Union[bytes, BinaryIO, str]] = None,
        message_id: Optional[str] = None,
        event_id: Optional[str] = None,
        message_reference_id: Optional[str] = None,
        ignore_message_reference_error: Optional[bool] = None,
    ) -> _api_model.send_msg():
        """
        发送普通消息的API

        :param channel_id: 子频道id
        :param content: 消息文本（选填，此项与image至少需要有一个字段，否则无法下发消息）
        :param image: 图片url，不可发送本地图片（选填，此项与msg至少需要有一个字段，否则无法下发消息）
        :param file_image: 本地图片，可选三种方式传参，具体可参阅github中的example_10或帮助文档
        :param message_id: 消息id（选填）
        :param event_id: 事件id（选填）
        :param message_reference_id: 引用消息的id（选填）
        :param ignore_message_reference_error: 是否忽略获取引用消息详情错误，默认否（选填）
        :return: 返回的.data中为解析后的json数据
        """
        if message_reference_id is not None:
            if ignore_message_reference_error is None:
                ignore_message_reference_error = False
            json_ = {
                "content": content,
                "msg_id": message_id,
                "event_id": event_id,
                "image": image,
                "message_reference": {
                    "message_id": message_reference_id,
                    "ignore_get_message_error": ignore_message_reference_error,
                },
            }
        else:
            json_ = {
                "content": content,
                "msg_id": message_id,
                "event_id": event_id,
                "image": image,
            }
        if file_image is not None:
            if isinstance(file_image, BufferedReader):
                file_image = file_image.read()
            elif isinstance(file_image, str):
                if exists(file_image):
                    with open(file_image, "rb") as img:
                        file_image = img.read()
                else:
                    return sdk_error_temp("目标图片路径不存在，无法发送")
            json_["file_image"] = file_image
            data_ = FormData_()
            for keys, values in json_.items():
                if values is not None:
                    data_.add_field(keys, values)
            return_ = await self._session.post(
                f"{self.bot_url}/channels/{channel_id}/messages", data=data_
            )
        else:
            return_ = await self._session.post(
                f"{self.bot_url}/channels/{channel_id}/messages", json=json_
            )
        return await regular_temp(return_)

    async def send_embed(
        self,
        channel_id: str,
        title: Optional[str] = None,
        content: Optional[List[str]] = None,
        image: Optional[str] = None,
        prompt: Optional[str] = None,
        message_id: Optional[str] = None,
        event_id: Optional[str] = None,
    ) -> _api_model.send_msg():
        """
        发送embed模板消息的API

        :param channel_id: 子频道id
        :param title: 标题文本（选填）
        :param content: 内容文本列表，每一项之间将存在分行（选填）
        :param image: 略缩图url，不可发送本地图片（选填）
        :param prompt: 消息弹窗通知的文本内容（选填）
        :param message_id: 消息id（选填）
        :param event_id: 事件id（选填）
        :return: 返回的.data中为解析后的json数据
        """
        json_ = {
            "embed": {
                "title": title,
                "prompt": prompt,
                "thumbnail": {"url": image},
                "fields": [],
            },
            "msg_id": message_id,
            "event_id": event_id,
        }
        if content is not None:
            for items in content:
                json_["embed"]["fields"].append({"name": items})
        return_ = await self._session.post(
            f"{self.bot_url}/channels/{channel_id}/messages", json=json_
        )
        return await regular_temp(return_)

    async def send_ark_23(
        self,
        channel_id: str,
        content: List[str],
        link: List[str],
        desc: Optional[str] = None,
        prompt: Optional[str] = None,
        message_id: Optional[str] = None,
        event_id: Optional[str] = None,
    ) -> _api_model.send_msg():
        """
        发送ark（id=23）模板消息的API，请注意机器人是否有权限使用此API

        :param channel_id: 子频道id
        :param content: 内容文本列表，每一项之间将存在分行
        :param link: 链接url列表，长度应与内容列一致。将根据位置顺序填充文本超链接，如文本不希望填充链接可使用空文本或None填充位置
        :param desc: 描述文本内容（选填）
        :param prompt: 消息弹窗通知的文本内容（选填）
        :param message_id: 消息id（选填）
        :param event_id: 事件id（选填）
        :return: 返回的.data中为解析后的json数据
        """
        if len(content) != len(link):
            return sdk_error_temp("注意内容列表长度应与链接列表长度一致")
        json_ = {
            "ark": {
                "template_id": 23,
                "kv": [
                    {"key": "#DESC#", "value": desc},
                    {"key": "#PROMPT#", "value": prompt},
                    {"key": "#LIST#", "obj": []},
                ],
            },
            "msg_id": message_id,
            "event_id": event_id,
        }
        for i, items in enumerate(content):
            json_["ark"]["kv"][2]["obj"].append(
                {
                    "obj_kv": [
                        {"key": "desc", "value": items},
                        {"key": "link", "value": link[i]},
                    ]
                }
            )
        return_ = await self._session.post(
            f"{self.bot_url}/channels/{channel_id}/messages", json=json_
        )
        return await regular_temp(return_)

    async def send_ark_24(
        self,
        channel_id: str,
        title: Optional[str] = None,
        content: Optional[str] = None,
        subtitile: Optional[str] = None,
        link: Optional[str] = None,
        image: Optional[str] = None,
        desc: Optional[str] = None,
        prompt: Optional[str] = None,
        message_id: Optional[str] = None,
        event_id: Optional[str] = None,
    ) -> _api_model.send_msg():
        """
        发送ark（id=24）模板消息的API，请注意机器人是否有权限使用此API

        :param channel_id: 子频道id
        :param title: 标题文本（选填）
        :param content: 详情描述文本（选填）
        :param subtitile: 子标题文本（选填）
        :param link: 跳转的链接url（选填）
        :param image: 略缩图url，不可发送本地图片（选填）
        :param desc: 描述文本内容（选填）
        :param prompt: 消息弹窗通知的文本内容（选填）
        :param message_id: 消息id（选填）
        :param event_id: 事件id（选填）
        :return: 返回的.data中为解析后的json数据
        """
        json_ = {
            "ark": {
                "template_id": 24,
                "kv": [
                    {"key": "#DESC#", "value": desc},
                    {"key": "#PROMPT#", "value": prompt},
                    {"key": "#TITLE#", "value": title},
                    {"key": "#METADESC#", "value": content},
                    {"key": "#IMG#", "value": image},
                    {"key": "#LINK#", "value": link},
                    {"key": "#SUBTITLE#", "value": subtitile},
                ],
            },
            "msg_id": message_id,
            "event_id": event_id,
        }
        return_ = await self._session.post(
            f"{self.bot_url}/channels/{channel_id}/messages", json=json_
        )
        return await regular_temp(return_)

    async def send_ark_37(
        self,
        channel_id: str,
        title: Optional[str] = None,
        content: Optional[str] = None,
        link: Optional[str] = None,
        image: Optional[str] = None,
        prompt: Optional[str] = None,
        message_id: Optional[str] = None,
        event_id: Optional[str] = None,
    ) -> _api_model.send_msg():
        """
        发送ark（id=37）模板消息的API，请注意机器人是否有权限使用此API

        :param channel_id: 子频道id
        :param title: 标题文本（选填）
        :param content: 内容文本（选填）
        :param link: 跳转的链接url（选填）
        :param image: 略缩图url，不可发送本地图片（选填）
        :param prompt: 消息弹窗通知的文本内容（选填）
        :param message_id: 消息id（选填）
        :param event_id: 事件id（选填）
        :return: 返回的.data中为解析后的json数据
        """
        json_ = {
            "ark": {
                "template_id": 37,
                "kv": [
                    {"key": "#PROMPT#", "value": prompt},
                    {"key": "#METATITLE#", "value": title},
                    {"key": "#METASUBTITLE#", "value": content},
                    {"key": "#METACOVER#", "value": image},
                    {"key": "#METAURL#", "value": link},
                ],
            },
            "msg_id": message_id,
            "event_id": event_id,
        }
        return_ = await self._session.post(
            f"{self.bot_url}/channels/{channel_id}/messages", json=json_
        )
        return await regular_temp(return_)

    async def send_markdown(
        self,
        channel_id: str,
        template_id: Optional[str] = None,
        key_values: Optional[
            Union[
                List[Dict[str, Union[str, List[str]]]], Dict[str, Union[str, List[str]]]
            ]
        ] = None,
        content: Optional[str] = None,
        keyboard_id: Optional[str] = None,
        keyboard_content: Optional[dict] = None,
        message_id: Optional[str] = None,
        event_id: Optional[str] = None,
    ) -> _api_model.send_msg():
        """
        发送markdown消息的API，请注意机器人是否有权限使用此API

        :param channel_id: 子频道id
        :param template_id: markdown 模板 id（选填，与content不可同时存在）
        :param key_values: markdown 模版 key values列表，格式为：{key1: value1, key2: value2}（选填，与content不可同时存在）
        :param content: 原生 markdown 内容（选填，与template_id, key, values不可同时存在）
        :param keyboard_id: keyboard 模板 id（选填，与keyboard_content不可同时存在）
        :param keyboard_content: 原生 keyboard 内容（选填，与keyboard_id不可同时存在）
        :param message_id: 消息id（选填）
        :param event_id: 事件id（选填）
        :return: 返回的.data中为解析后的json数据
        """
        if keyboard_content:
            if keyboard_id:
                self.logger.warning(
                    "注意keyboard_id与keyboard_content不可同时存在，注意系统已根据优先级仅保留keyboard_content"
                )
            keyboard = {"content": keyboard_content}
        elif keyboard_id:
            keyboard = {"id": keyboard_id}
        else:
            keyboard = None
        if content:
            if template_id:
                self.logger.warning("注意content与template_id不可同时存在，注意系统已根据优先级仅保留content")
            json_ = {
                "markdown": {"content": content},
                "msg_id": message_id,
                "event_id": event_id,
                "keyboard": keyboard,
            }
        else:
            if not template_id or not key_values:
                return sdk_error_temp("注意content与template_id必须存在任意一个，否则消息无法下发！")
            if isinstance(key_values, dict):
                params = []
                for k, v in key_values.items():
                    if isinstance(v, list) or isinstance(v, tuple):
                        v = list(v)
                    else:
                        v = [str(v)]
                    params.append({"key": k, "values": v})
            else:
                try:
                    params = list(key_values)
                    for items in params:
                        for k, v in items.items():
                            if isinstance(v, list) or isinstance(v, tuple):
                                items[k] = [str(v[0])]
                            else:
                                items[k] = [str(v)]
                except Exception:
                    return sdk_error_temp(
                        "发送markdown消息的key_values仅可以是dict或list[dict]类型！"
                    )
            json_ = {
                "markdown": {"custom_template_id": template_id, "params": params},
                "msg_id": message_id,
                "event_id": event_id,
                "keyboard": keyboard,
            }
        return_ = await self._session.post(
            f"{self.bot_url}/channels/{channel_id}/messages", json=json_
        )
        return await regular_temp(return_)

    async def delete_msg(
        self, channel_id: str, message_id: str, hidetip: bool = False
    ) -> _api_model.delete_msg():
        """
        撤回消息的API，注意一般情况下仅私域可以使用

        :param channel_id: 子频道id
        :param message_id: 需撤回消息的消息id
        :param hidetip: 是否隐藏提示小灰条，True为隐藏，False为显示（选填）
        :return: 返回的.result显示是否成功
        """
        self.check_warning("撤回消息")
        return_ = await self._session.delete(
            f"{self.bot_url}/channels/{channel_id}/messages/{message_id}"
            f"?hidetip={str(hidetip).lower()}"
        )
        return await http_temp(return_, 200)

    async def get_guild_setting(self, guild_id: str) -> _api_model.get_guild_setting():
        """
        用于获取机器人在频道 guild_id 内的消息频率设置

        :param guild_id: 频道id
        :return: 返回的.data中为解析后的json数据
        """
        return_ = await self._session.get(
            f"{self.bot_url}/guilds/{guild_id}/message/setting"
        )
        return await regular_temp(return_)

    async def create_dm_guild(
        self, target_id: str, guild_id: str
    ) -> _api_model.create_dm_guild():
        """
        当机器人主动跟用户私信时，创建并获取一个虚拟频道id的API

        :param target_id: 目标用户id
        :param guild_id: 机器人跟目标用户所在的频道id
        :return: 返回的.data中为解析后的json数据，注意发送私信仅需要使用guild_id这一项虚拟频道id的数据
        """
        json_ = {"recipient_id": target_id, "source_guild_id": guild_id}
        return_ = await self._session.post(f"{self.bot_url}/users/@me/dms", json=json_)
        return await regular_temp(return_)

    async def send_dm(
        self,
        guild_id: str,
        content: Optional[str] = None,
        image: Optional[str] = None,
        file_image: Optional[Union[bytes, BinaryIO, str]] = None,
        message_id: Optional[str] = None,
        event_id: Optional[str] = None,
        message_reference_id: Optional[str] = None,
        ignore_message_reference_error: Optional[bool] = None,
    ) -> _api_model.send_msg():
        """
        私信用户的API

        :param guild_id: 虚拟频道id（非子频道id），从用户主动私信机器人的事件、或机器人主动创建私信的API中获取
        :param content: 消息内容文本
        :param image: 图片url，不可发送本地图片（选填，此项与msg至少需要有一个字段，否则无法下发消息）
        :param file_image: 本地图片，可选三种方式传参，具体可参阅github中的example_10或帮助文档
        :param message_id: 消息id（选填）
        :param event_id: 事件id（选填）
        :param message_reference_id: 引用消息的id（选填）
        :param ignore_message_reference_error: 是否忽略获取引用消息详情错误，默认否（选填）
        :return: 返回的.data中为解析后的json数据
        """
        if message_reference_id is not None:
            if ignore_message_reference_error is None:
                ignore_message_reference_error = False
            json_ = {
                "content": content,
                "msg_id": message_id,
                "event_id": event_id,
                "image": image,
                "message_reference": {
                    "message_id": message_reference_id,
                    "ignore_get_message_error": ignore_message_reference_error,
                },
            }
        else:
            json_ = {
                "content": content,
                "msg_id": message_id,
                "event_id": event_id,
                "image": image,
            }
        if file_image is not None:
            if isinstance(file_image, BufferedReader):
                file_image = file_image.read()
            elif isinstance(file_image, str):
                if exists(file_image):
                    with open(file_image, "rb") as img:
                        file_image = img.read()
                else:
                    return sdk_error_temp("目标图片路径不存在，无法发送")
            json_["file_image"] = file_image
            data_ = FormData_()
            for keys, values in json_.items():
                if values is not None:
                    data_.add_field(keys, values)
            return_ = await self._session.post(
                f"{self.bot_url}/dms/{guild_id}/messages", data=data_
            )
        else:
            return_ = await self._session.post(
                f"{self.bot_url}/dms/{guild_id}/messages", json=json_
            )
        return await regular_temp(return_)

    async def delete_dm_msg(
        self, guild_id: str, message_id: str, hidetip: bool = False
    ) -> _api_model.delete_msg():
        """
        用于撤回私信频道 guild_id 中 message_id 指定的私信消息。只能用于撤回机器人自己发送的私信

        :param guild_id: 虚拟频道id（非子频道id），从用户主动私信机器人的事件、或机器人主动创建私信的API中获取
        :param message_id: 需撤回消息的消息id
        :param hidetip: 是否隐藏提示小灰条，True为隐藏，False为显示（选填）
        :return: 返回的.result显示是否成功
        """
        self.check_warning("撤回私信消息")
        return_ = await self._session.delete(
            f"{self.bot_url}/dms/{guild_id}/messages/{message_id}?"
            f"hidetip={str(hidetip).lower()}"
        )
        return await http_temp(return_, 200)

    async def mute_all_member(
        self,
        guild_id: str,
        mute_end_timestamp: Optional[str],
        mute_seconds: Optional[str],
    ) -> _api_model.mute_member():
        """
        用于将频道的全体成员（非管理员）禁言

        :param guild_id: 频道id
        :param mute_end_timestamp: 禁言到期时间戳，绝对时间戳，单位：秒（与 mute_seconds 字段同时赋值的话，以该字段为准）
        :param mute_seconds: 禁言多少秒（两个字段二选一，默认以 mute_end_timestamp 为准）
        :return: 返回的.result显示是否成功
        """
        json_ = {"mute_end_timestamp": mute_end_timestamp, "mute_seconds": mute_seconds}
        return_ = await self._session.patch(
            f"{self.bot_url}/guilds/{guild_id}/mute", json=json_
        )
        return await http_temp(return_, 204)

    async def mute_member(
        self,
        guild_id: str,
        user_id: str,
        mute_end_timestamp: Optional[str],
        mute_seconds: Optional[str],
    ) -> _api_model.mute_member():
        """
        用于禁言频道 guild_id 下的成员 user_id

        :param guild_id: 频道id
        :param user_id: 目标成员的用户ID
        :param mute_end_timestamp: 禁言到期时间戳，绝对时间戳，单位：秒（与 mute_seconds 字段同时赋值的话，以该字段为准）
        :param mute_seconds: 禁言多少秒（两个字段二选一，默认以 mute_end_timestamp 为准）
        :return: 返回的.result显示是否成功
        """
        json_ = {"mute_end_timestamp": mute_end_timestamp, "mute_seconds": mute_seconds}
        return_ = await self._session.patch(
            f"{self.bot_url}/guilds/{guild_id}/members/{user_id}/mute", json=json_
        )
        return await http_temp(return_, 204)

    async def mute_members(
        self,
        guild_id: str,
        user_id: List[str],
        mute_end_timestamp: Optional[str],
        mute_seconds: Optional[str],
    ) -> _api_model.mute_members():
        """
        用于将频道的指定批量成员（非管理员）禁言

        :param guild_id: 频道id
        :param user_id: 目标成员的用户ID列表
        :param mute_end_timestamp: 禁言到期时间戳，绝对时间戳，单位：秒（与 mute_seconds 字段同时赋值的话，以该字段为准）
        :param mute_seconds: 禁言多少秒（两个字段二选一，默认以 mute_end_timestamp 为准）
        :return: 返回的.data中为解析后的json数据
        """
        json_ = {
            "mute_end_timestamp": mute_end_timestamp,
            "mute_seconds": mute_seconds,
            "user_ids": user_id,
        }
        return_ = await self._session.patch(
            f"{self.bot_url}/guilds/{guild_id}/mute", json=json_
        )
        trace_id = (
            return_.headers.get("X-Tps-Trace-Id", None)
            if hasattr(return_, "headers")
            else None
        )
        status_code = getattr(return_, "status", None)
        try:
            return_dict = await return_.json()
            if status_code == 200:
                result = False
            else:
                result = True
            return objectize(
                {
                    "data": return_dict,
                    "trace_id": trace_id,
                    "http_code": status_code,
                    "result": result,
                }
            )
        except JSONDecodeError:
            return objectize(
                {
                    "data": None,
                    "trace_id": trace_id,
                    "http_code": status_code,
                    "result": False,
                }
            )

    async def create_announce(
        self,
        guild_id,
        channel_id: Optional[str] = None,
        message_id: Optional[str] = None,
        announces_type: Optional[int] = None,
        recommend_channels_id: Optional[List[str]] = None,
        recommend_channels_introduce: Optional[List[str]] = None,
    ) -> _api_model.create_announce():
        """
        用于创建频道全局公告，公告类型分为 消息类型的频道公告 和 推荐子频道类型的频道公告

        :param guild_id: 频道id
        :param channel_id: 子频道id，message_id 有值则为必填
        :param message_id: 消息id，此项有值则优选将某条消息设置为成员公告
        :param announces_type: 公告类别 0：成员公告，1：欢迎公告，默认为成员公告
        :param recommend_channels_id: 推荐子频道id列表，会一次全部替换推荐子频道列表
        :param recommend_channels_introduce: 推荐子频道推荐语列表，列表长度应与recommend_channels_id一致
        :return: 返回的.data中为解析后的json数据
        """
        json_ = {
            "channel_id": channel_id,
            "message_id": message_id,
            "announces_type": announces_type,
            "recommend_channels": [],
        }
        if recommend_channels_id is not None and recommend_channels_id:
            if len(recommend_channels_id) == len(recommend_channels_introduce):
                for i, items in enumerate(recommend_channels_id):
                    json_["recommend_channels"].append(
                        {
                            "channel_id": items,
                            "introduce": recommend_channels_introduce[i],
                        }
                    )
            else:
                return sdk_error_temp("注意推荐子频道ID列表长度，应与推荐子频道推荐语列表长度一致")
        return_ = await self._session.post(
            f"{self.bot_url}/guilds/{guild_id}/announces", json=json_
        )
        return await regular_temp(return_)

    async def delete_announce(
        self, guild_id: str, message_id: str = "all"
    ) -> _api_model.delete_announce():
        """
        用于删除频道 guild_id 下指定 message_id 的全局公告

        :param guild_id: 频道id
        :param message_id: message_id有值时会校验message_id合法性；若不校验，请将message_id设置为all（默认为all）
        :return: 返回的.result显示是否成功
        """
        return_ = await self._session.delete(
            f"{self.bot_url}/guilds/{guild_id}/announces/{message_id}"
        )
        return await http_temp(return_, 204)

    async def create_pinmsg(
        self, channel_id: str, message_id: str
    ) -> _api_model.pinmsg():
        """
        用于添加子频道 channel_id 内的精华消息

        :param channel_id: 子频道id
        :param message_id: 目标消息id
        :return: 返回的.data中为解析后的json数据
        """
        return_ = await self._session.put(
            f"{self.bot_url}/channels/{channel_id}/pins/{message_id}"
        )
        return await regular_temp(return_)

    async def delete_pinmsg(
        self, channel_id: str, message_id: str
    ) -> _api_model.delete_pinmsg():
        """
        用于删除子频道 channel_id 下指定 message_id 的精华消息

        :param channel_id: 子频道id
        :param message_id: 目标消息id
        :return: 返回的.result显示是否成功
        """
        return_ = await self._session.delete(
            f"{self.bot_url}/channels/{channel_id}/pins/{message_id}"
        )
        return await http_temp(return_, 204)

    async def get_pinmsg(self, channel_id: str) -> _api_model.pinmsg():
        """
        用于获取子频道 channel_id 内的精华消息

        :param channel_id: 子频道id
        :return: 返回的.data中为解析后的json数据
        """
        return_ = await self._session.get(f"{self.bot_url}/channels/{channel_id}/pins")
        return await regular_temp(return_)

    async def get_schedules(
        self, channel_id: str, since: Optional[int] = None
    ) -> _api_model.get_schedules():
        """
        用于获取channel_id指定的子频道中当天的日程列表

        :param channel_id: 日程子频道id
        :param since: 起始时间戳(ms)
        :return: 返回的.data中为解析后的json数据
        """
        json_ = {"since": since}
        return_ = await self._session.get(
            f"{self.bot_url}/channels/{channel_id}/schedules", json=json_
        )
        return await regular_temp(return_)

    async def get_schedule_info(
        self, channel_id: str, schedule_id: str
    ) -> _api_model.schedule_info():
        """
        获取日程子频道 channel_id 下 schedule_id 指定的的日程的详情

        :param channel_id: 日程子频道id
        :param schedule_id: 日程id
        :return: 返回的.data中为解析后的json数据
        """
        return_ = await self._session.get(
            f"{self.bot_url}/channels/{channel_id}/schedules/{schedule_id}"
        )
        return await regular_temp(return_)

    async def create_schedule(
        self,
        channel_id: str,
        schedule_name: str,
        start_timestamp: str,
        end_timestamp: str,
        jump_channel_id: str,
        remind_type: str,
    ) -> _api_model.schedule_info():
        """
        用于在 channel_id 指定的日程子频道下创建一个日程

        :param channel_id: 日程子频道id
        :param schedule_name: 日程名称
        :param start_timestamp: 日程开始时间戳(ms)
        :param end_timestamp: 日程结束时间戳(ms)
        :param jump_channel_id: 日程开始时跳转到的子频道id
        :param remind_type: 日程提醒类型
        :return: 返回的.data中为解析后的json数据
        """
        json_ = {
            "schedule": {
                "name": schedule_name,
                "start_timestamp": start_timestamp,
                "end_timestamp": end_timestamp,
                "jump_channel_id": jump_channel_id,
                "remind_type": remind_type,
            }
        }
        return_ = await self._session.post(
            f"{self.bot_url}/channels/{channel_id}/schedules", json=json_
        )
        return await regular_temp(return_)

    async def patch_schedule(
        self,
        channel_id: str,
        schedule_id: str,
        schedule_name: str,
        start_timestamp: str,
        end_timestamp: str,
        jump_channel_id: str,
        remind_type: str,
    ) -> _api_model.schedule_info():
        """
        用于修改日程子频道 channel_id 下 schedule_id 指定的日程的详情

        :param channel_id: 日程子频道id
        :param schedule_id: 日程id
        :param schedule_name: 日程名称
        :param start_timestamp: 日程开始时间戳(ms)
        :param end_timestamp: 日程结束时间戳(ms)
        :param jump_channel_id: 日程开始时跳转到的子频道id
        :param remind_type: 日程提醒类型
        :return: 返回的.data中为解析后的json数据
        """
        json_ = {
            "schedule": {
                "name": schedule_name,
                "start_timestamp": start_timestamp,
                "end_timestamp": end_timestamp,
                "jump_channel_id": jump_channel_id,
                "remind_type": remind_type,
            }
        }
        return_ = await self._session.patch(
            f"{self.bot_url}/channels/{channel_id}/schedules/{schedule_id}", json=json_
        )
        return await regular_temp(return_)

    async def delete_schedule(
        self, channel_id: str, schedule_id: str
    ) -> _api_model.delete_schedule():
        """
        用于删除日程子频道 channel_id 下 schedule_id 指定的日程

        :param channel_id: 日程子频道id
        :param schedule_id: 日程id
        :return: 返回的.result显示是否成功
        """
        return_ = await self._session.delete(
            f"{self.bot_url}/channels/{channel_id}/schedules/{schedule_id}"
        )
        return await http_temp(return_, 204)

    async def create_reaction(
        self, channel_id: str, message_id: str, type_: str, id_: str
    ) -> _api_model.reactions():
        """
        对message_id指定的消息进行表情表态

        :param channel_id: 子频道id
        :param message_id: 目标消息id
        :param type_: 表情类型
        :param id_: 表情id
        :return: 返回的.result显示是否成功
        """
        return_ = await self._session.put(
            f"{self.bot_url}/channels/{channel_id}/messages/{message_id}/reactions/"
            f"{type_}/{id_}"
        )
        return await http_temp(return_, 204)

    async def delete_reaction(
        self, channel_id: str, message_id: str, type_: str, id_: str
    ) -> _api_model.reactions():
        """
        删除自己对message_id指定消息的表情表态

        :param channel_id: 子频道id
        :param message_id: 目标消息id
        :param type_: 表情类型
        :param id_: 表情id
        :return: 返回的.result显示是否成功
        """
        return_ = await self._session.delete(
            f"{self.bot_url}/channels/{channel_id}/messages/{message_id}/reactions/"
            f"{type_}/{id_}"
        )
        return await http_temp(return_, 204)

    async def get_reaction_users(
        self, channel_id: str, message_id: str, type_: str, id_: str
    ) -> _api_model.get_reaction_users():
        """
        拉取对消息 message_id 指定表情表态的用户列表

        :param channel_id: 子频道id
        :param message_id: 目标消息id
        :param type_: 表情类型
        :param id_: 表情id
        :return: 返回的.data中为解析后的json数据列表
        """
        return_ = await self._session.get(
            f"{self.bot_url}/channels/{channel_id}/messages/{message_id}/reactions/"
            f"{type_}/{id_}?cookie=&limit=50"
        )
        trace_ids = [
            return_.headers.get("X-Tps-Trace-Id", None)
            if hasattr(return_, "headers")
            else None
        ]
        codes = [getattr(return_, "status", None)]
        all_users = []
        try:
            return_dict = await return_.json()
            if isinstance(return_dict, dict) and "code" in return_dict.keys():
                all_users.append(return_dict)
                results = [False]
            else:
                for items in return_dict["users"]:
                    all_users.append(items)
                results = [True]
                while True:
                    if return_dict["is_end"]:
                        break
                    return_ = await self._session.get(
                        f"{self.bot_url}/channels/{channel_id}/messages/{message_id}/"
                        f'reactions/{type_}/{id_}?cookies={return_dict["cookie"]}'
                    )
                    trace_ids.append(return_.headers["X-Tps-Trace-Id"])
                    codes.append(return_.status)
                    return_dict = await return_.json()
                    if isinstance(return_dict, dict) and "code" in return_dict.keys():
                        results.append(False)
                        all_users.append(return_dict)
                        break
                    else:
                        results.append(True)
                        for items in return_dict["users"]:
                            all_users.append(items)
            return objectize(
                {
                    "data": all_users,
                    "trace_id": trace_ids,
                    "http_code": codes,
                    "result": results,
                }
            )
        except (JSONDecodeError, AttributeError, KeyError):
            return objectize(
                {
                    "data": [],
                    "trace_id": trace_ids,
                    "http_code": codes,
                    "result": [False],
                }
            )

    async def control_audio(
        self,
        channel_id: str,
        status: int,
        audio_url: Optional[str] = None,
        text: Optional[str] = None,
    ) -> _api_model.audio():
        """
        用于控制子频道 channel_id 下的音频

        :param channel_id: 子频道id
        :param status: 播放状态
        :param audio_url: 音频数据的url，可选，status为0时传
        :param text: 状态文本（比如：简单爱-周杰伦），可选，status为0时传，其他操作不传
        :return: 返回的.result显示是否成功
        """
        json_ = {"audio_url": audio_url, "text": text, "status": status}
        return_ = await self._session.post(
            f"{self.bot_url}/channels/{channel_id}/audio", json=json_
        )
        return await empty_temp(return_)

    async def bot_on_mic(self, channel_id: str) -> _api_model.audio():
        """
        机器人在 channel_id 对应的语音子频道上麦

        :param channel_id: 子频道id
        :return: 返回的.result显示是否成功
        """
        return_ = await self._session.put(f"{self.bot_url}/channels/{channel_id}/mic")
        return await empty_temp(return_)

    async def bot_off_mic(self, channel_id: str) -> _api_model.audio():
        """
        机器人在 channel_id 对应的语音子频道下麦

        :param channel_id: 子频道id
        :return: 返回的.result显示是否成功
        """
        return_ = await self._session.delete(
            f"{self.bot_url}/channels/{channel_id}/mic"
        )
        return await empty_temp(return_)

    async def get_threads(self, channel_id: str) -> _api_model.get_threads():
        """
        获取子频道下的帖子列表

        :param channel_id: 目标论坛子频道id
        :return: 返回的.data中为解析后的json数据列表
        """
        self.check_warning("获取帖子列表")
        return_ = await self._session.get(
            f"{self.bot_url}/channels/{channel_id}/threads"
        )
        trace_ids = [
            return_.headers.get("X-Tps-Trace-Id", None)
            if hasattr(return_, "headers")
            else None
        ]
        codes = [getattr(return_, "status", None)]
        all_threads = []
        try:
            return_dict = await return_.json()
            if isinstance(return_dict, dict) and "code" in return_dict.keys():
                all_threads.append(return_dict)
                results = [False]
            else:
                for items in return_dict["threads"]:
                    if (
                        "thread_info" in items.keys()
                        and "content" in items["thread_info"].keys()
                    ):
                        items["thread_info"]["content"] = loads(
                            items["thread_info"]["content"]
                        )
                    all_threads.append(items)
                results = [True]
                while True:
                    if return_dict["is_finish"]:
                        break
                    return_ = await self._session.get(
                        f"{self.bot_url}/channels/{channel_id}/threads"
                    )
                    trace_ids.append(return_.headers["X-Tps-Trace-Id"])
                    codes.append(return_.status)
                    return_dict = await return_.json()
                    if isinstance(return_dict, dict) and "code" in return_dict.keys():
                        results.append(False)
                        all_threads.append(return_dict)
                        break
                    else:
                        results.append(True)
                        for items in return_dict["threads"]:
                            if (
                                "thread_info" in items.keys()
                                and "content" in items["thread_info"].keys()
                            ):
                                items["thread_info"]["content"] = loads(
                                    items["thread_info"]["content"]
                                )
                            all_threads.append(items)
            return objectize(
                {
                    "data": all_threads,
                    "trace_id": trace_ids,
                    "http_code": codes,
                    "result": results,
                }
            )
        except (JSONDecodeError, AttributeError, KeyError):
            return objectize(
                {
                    "data": [],
                    "trace_id": trace_ids,
                    "http_code": codes,
                    "result": [False],
                }
            )

    async def get_thread_info(
        self, channel_id: str, thread_id: str
    ) -> _api_model.get_thread_info():
        """
        获取子频道下的帖子详情

        :param channel_id: 目标论坛子频道id
        :param thread_id: 帖子id
        :return: 返回的.data中为解析后的json数据
        """
        self.check_warning("获取帖子详情")
        return_ = await self._session.get(
            f"{self.bot_url}/channels/{channel_id}/threads/{thread_id}"
        )
        return await regular_temp(return_)

    async def create_thread(
        self, channel_id: str, title: str, content: str, format_: int
    ) -> _api_model.create_thread():
        """
        创建帖子，创建成功后，返回创建成功的任务ID

        :param channel_id: 目标论坛子频道id
        :param title: 帖子标题
        :param content: 帖子内容（具体格式根据format_判断）
        :param format_: 帖子文本格式（1：普通文本、2：HTML、3：Markdown、4：Json）
        :return: 返回的.data中为解析后的json数据
        """
        self.check_warning("发表帖子")
        json_ = {"title": title, "content": content, "format": format_}
        return_ = await self._session.put(
            f"{self.bot_url}/channels/{channel_id}/threads", json=json_
        )
        return await regular_temp(return_)

    async def delete_thread(
        self, channel_id: str, thread_id: str
    ) -> _api_model.delete_thread():
        """
        删除指定子频道下的某个帖子

        :param channel_id: 目标论坛子频道id
        :param thread_id: 帖子id
        :return: 返回的.result显示是否成功
        """
        self.check_warning("删除帖子")
        return_ = await self._session.delete(
            f"{self.bot_url}/channels/{channel_id}/threads/{thread_id}"
        )
        return await http_temp(return_, 204)

    async def get_guild_permissions(
        self, guild_id: str
    ) -> _api_model.get_guild_permissions():
        """
        获取机器人在频道 guild_id 内可以使用的权限列表

        :param guild_id: 频道id
        :return: 返回的.data中为解析后的json数据
        """
        return_ = await self._session.get(
            f"{self.bot_url}/guilds/{guild_id}/api_permission"
        )
        trace_id = (
            return_.headers.get("X-Tps-Trace-Id", None)
            if hasattr(return_, "headers")
            else None
        )
        status_code = getattr(return_, "status", None)
        try:
            return_dict = await return_.json()
            if isinstance(return_dict, dict) and "code" in return_dict.keys():
                result = False
            else:
                result = True
                for i in range(len(return_dict["apis"])):
                    api = _api_model.api_converter_re(
                        return_dict["apis"][i]["method"], return_dict["apis"][i]["path"]
                    )
                    return_dict["apis"][i]["api"] = api
            return objectize(
                {
                    "data": return_dict,
                    "trace_id": trace_id,
                    "http_code": status_code,
                    "result": result,
                }
            )
        except JSONDecodeError:
            return objectize(
                {
                    "data": None,
                    "trace_id": trace_id,
                    "http_code": status_code,
                    "result": False,
                }
            )

    async def create_permission_demand(
        self, guild_id: str, channel_id: str, api: str, desc: Optional[str]
    ) -> _api_model.create_permission_demand():
        """
        发送频道API接口权限授权链接到频道

        :param guild_id: 频道id
        :param channel_id: 子频道id
        :param api: 需求权限的API在sdk的名字
        :param desc: 机器人申请对应的API接口权限后可以使用功能的描述
        :return: 返回成功或不成功
        """
        path, method = _api_model.api_converter(api)
        if not path:
            return sdk_error_temp("目标API不存在，请检查API名称是否正确")
        json_ = {
            "channel_id": channel_id,
            "api_identify": {"path": path, "method": method.upper()},
            "desc": desc,
        }
        return_ = await self._session.post(
            f"{self.bot_url}/guilds/{guild_id}/api_permission/demand", json=json_
        )
        return await empty_temp(return_)
