记录两次Astrbot插件开发(贴表情插件,mc信息查询插件)

573 阅读3分钟

初次接触Astrbot的插件开发,得益于官方提供的详细的api文档,我这样的新手也能快速上手.本文记录开发过程中的感想.

Astrbot介绍:

image.png

官网:AstrBot

贴表情插件:

使用NapCat接口文档中的api接口

核心代码

 async def send_emoji(self, event, message_id, emoji_id):
        # 调用 napcat 的 api 发送贴表情请求
        if event.get_platform_name() == "aiocqhttp":
            # qq
            assert isinstance(event, AiocqhttpMessageEvent)
            client = event.bot  # 得到 client
            payloads = {
                "message_id": message_id,
                "emoji_id": emoji_id,
                "set": True
            }
            ret = await client.api.call_action('set_msg_emoji_like', **payloads)  # 调用 协议端  API
            logger.info(f"表情ID:{emoji_id}")
            logger.info(f"贴表情返回结果: {ret}")
            post_result = ret['result']
            if post_result == 0:
                logger.info("请求贴表情成功")
            elif post_result == 65002:
                logger.error("已经回应过该表情")
            elif post_result == 65001:
                logger.error("表情已达上限,无法添加新的表情")
            else:
                logger.error("未知错误")

使用aiohttp进行异步请求,提高并发性,值得注意的是应该对api调用速度进行限制,防止触发风控.

消息链

消息链是astrbot中的重要概念,astrbot会将接收到的消息解析为消息链,同时发送消息时也需要先构造消息链.

引用方式: import astrbot.api.message_components as Comp

常用消息类型:

ComponentTypes = {
    "plain": Plain, # 文本消息
    "text": Plain, # 文本消息,同上
    "face": Face, # QQ 表情
    "record": Record, # 语音
    "video": Video, # 视频
    "at": At, # At 消息发送者
    "music": Music, # 音乐
    "image": Image, # 图片
    "reply": Reply, # 回复消息
    "forward": Forward, # 转发消息
    "node": Node, # 转发消息中的节点
    "nodes": Nodes, # Node 的列表,用于支持一个转发消息中的多个节点
    "poke": Poke, # 戳一戳
}

获取发送者id

sender_id=event.get_sender_id()

获取被引用回复的消息id

#获取转发消息id
    async def get_reply_id(self,event):
        message_chain = event.message_obj.message
        # 获取转发消息的消息 ID
        replyID = None
        for message in message_chain:
            if message.type == "Reply":
                replyID = message.id
                break
        return replyID

获取原消息发送者id

#获取接收者id(返回为str类型)
    async def get_receiver_id(self,event):
        message_chain = event.message_obj.message
        #获取接收者id
        receiverID=None
        for message in message_chain:
            if message.type=="Reply":
                receiverID=message.sender_id
                break
        return str(receiverID)

mc信息查询插件

核心实现

  1. 使用mcstatus获取服务器状态
  2. 使用pillow绘制图片
  3. 读写json配置实现多服查询

mcstatus

# 调用mcstatus获取服务器信息
server = await JavaServer.async_lookup(host)
# 使用异步方法查询服务器状态
status = await server.async_status()
players_list = []
latency = int(status.latency)
plays_max = status.players.max
plays_online = status.players.online
server_version = status.version.name

pillow绘制

主要涉及图片与base64的相互转换,需要掌握base64库的用法,要注意类型!!!

pillow绘制后返回base64 byte类型:

# 转换为base64
buffer = io.BytesIO()
img.save(buffer, format="PNG")
img_base64 = base64.b64encode(buffer.getvalue()).decode("utf-8")
# 返回base64 bytes
return img_base64

mcstatus解析的图片数据为base64 string类型

icon_data = status.icon.split(",")[1]

关于路径问题

涉及到文件路径时并非想象中的那么简单,需要考虑不同系统的兼容性问题以及文件路径是否存在等.

得益于python提供的强大的pathlib库,我们可以很方便的实现动态获取文件路径(相对路径)

Path(__file__).resolve() 将返回py脚本当前执行位置的绝对路径,可以使用.parent获取其上级目录,使用/'str'插入下级目录.

# 确保目录存在
Path(json_path).parent.mkdir(parents=True, exist_ok=True)

可以检查文件路径是否存在,并在其不存在时自动创建

关于py面向对象开发

在 Python 里,self代表类的实例对象。定义一个类时,类中的方法(函数)通常会把self作为首个参数,这是为了让方法能够访问和操作实例的属性与其他方法。