ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

深入 NoneBot2 适配器开发:从零编写适配器对接新平台

深入 NoneBot2 适配器开发:从零编写适配器对接新平台 后端即时通讯【免费下载链接】nonebot2跨平台 Python 异步聊天机器人框架 / Asynchronous multi-platform chatbot framework written in Python项目地址https://gitcode.com/gh_mirrors/no/nonebot2点击查看免费下载NoneBot2 是跨平台的 Python 异步聊天机器人框架其跨平台能力正来源于灵活的**协议适配器Adapter**机制——每一个聊天平台QQ、Telegram、Discord 等都对应一个适配器由它负责与平台通信、转换事件、调用接口。本篇指南以 website/versioned_docs/version-2.5.0/developer/adapter-writing.md 为主线完整讲解如何从零为 NoneBot2 编写一个适配器项目结构、Adapter/Bot/Event/Message四大组件的实现、客户端与服务端两种通信方式、事件转换与 API 调用以及适配器的测试与发布流程。读完本篇你将能够独立搭建一个可用的nonebot-adapter-{name}适配器项目并理解其与 NoneBot 核心的调用关系。适配器的功能与组成在动手编写之前先明确适配器在整个 NoneBot 中扮演的角色。NoneBot 将平台差异全部封装在适配器内一个完整适配器通常由四个部分组成详见 适配器功能与组成Adapter负责与平台建立通信连接、接收事件数据、将 payload 转换为 NoneBot 事件、调用平台 API并正确创建Bot对象注册到 NoneBot 中Bot机器人开发者可直接获取并使用的核心对象存储平台机器人相关信息提供回复事件、调用 API 的上层方法Event平台事件的统一载体所有平台消息在进入处理流程前都必须转换为 NoneBot 事件Message/MessageSegment负责消息的正确序列化与解析供机器人插件处理。编写适配器时我们需要继承 NoneBot 提供的基类即 nonebot/adapters/init.py 导出的Adapter、Bot、Event、Message、MessageSegment并根据实际平台的协议特性填充每个部分的具体实现。项目组织结构NoneBot 适配器项目通常以nonebot-adapter-{adapter-name}命名并以命名空间包的形式编写——即实际代码放在nonebot/adapters/{adapter-name}目录下。这样安装适配器后import nonebot.adapters.{adapter-name}即可直接可用同时共享nonebot.adapters命名空间 nonebot-adapter-{adapter-name} ├── nonebot │ ├── adapters │ │ ├── {adapter-name} │ │ │ ├── __init__.py │ │ │ ├── adapter.py │ │ │ ├── bot.py │ │ │ ├── config.py │ │ │ ├── event.py │ │ │ └── message.py ├── pyproject.toml └── README.md:::tip 上述项目结构仅作推荐不做强制要求保证实际可用性即可。各文件职责清晰adapter.py通信与事件转换、bot.pyBot 对象、config.py配置模型、event.py事件模型、message.py消息模型是官方推荐的拆分方式。 :::使用 NB-CLI 创建项目NoneBot 官方脚手架 NB-CLI 提供了适配器项目的快速创建命令nb adapter create按照指引输入适配器名称以及存储位置即可自动生成带有基本结构的适配器项目省去手动搭建目录与pyproject.toml的重复劳动。适配器的组成部分在阅读以下代码时请注意代码中提到的Adapter、Bot、Event、Message均指适配器内我们自己编写的类如adapter.py中的class Adapter(BaseAdapter)而非 NoneBot 基类本身基类统一以Base*或直接导入别名的方式区分。日志工具Log适配器处理过程中通常需要打印日志但直接使用 NoneBot 默认logger难以区分适配器输出与框架其它日志。NoneBot 在 nonebot/utils.py 中提供了logger_wrapper可以包装出一个带适配器名称前缀的log函数from nonebot.utils import logger_wrapper log logger_wrapper(your_adapter_name)从源码可以看到logger_wrapper返回的log(level, message, exceptionNone)内部等价于logger.opt(colorsTrue, exceptionexception).log( level, fm{escape_tag(logger_name)}/m | {message} )也就是说它会用m品红色标记适配器名称前缀并支持 loguru 的彩色标签如y、r、bg ...与异常堆栈打印。用法如下from .log import log log(DEBUG, A DEBUG log.) log(INFO, A INFO log.) try: ... except Exception as e: log(ERROR, something error., e)三个参数依次为日志等级DEBUG/INFO/WARNING/ERROR等、日志内容、可选的异常对象传入后会自动附带异常堆栈。配置模型Config适配器通常需要一些配置项例如平台连接密钥、Bot 账号等。适配器配置方法与插件配置类似参考 插件配置定义一个继承pydantic.BaseModel的配置类即可from pydantic import BaseModel class Config(BaseModel): xxx_id: str xxx_token: str这些配置项如何读取将在下方Adapter一节介绍。值得说明的是get_plugin_config的实现位于 nonebot/plugin/init.py它会从全局配置中提取对应字段并支持从.env环境文件读取因此用户只需在 NoneBot 的.env中写入XXX_ID...、XXX_TOKEN...即可被自动注入。Adapter通信与事件中枢Adapter是适配器的核心。在编写平台相关内容之前需要继承基类并实现基本信息from typing import Any from typing_extensions import override from nonebot.drivers import Driver from nonebot import get_plugin_config from nonebot.adapters import Adapter as BaseAdapter from .config import Config class Adapter(BaseAdapter): override def __init__(self, driver: Driver, **kwargs: Any): super().__init__(driver, **kwargs) # 读取适配器所需的配置项 self.adapter_config: Config get_plugin_config(Config) classmethod override def get_name(cls) - str: 适配器名称 return your_adapter_name这里有两个关键点get_name()返回适配器名称如onebot它会被Bot.type、日志前缀等多处使用Bot 基类 的type属性即直接返回self.adapter.get_name()get_plugin_config(Config)在__init__中调用一次性完成配置读取。从 Adapter 基类 的源码可以看到基类还提供了若干现成能力我们在下面会逐一用到self.driverNoneBot 的 Driver 实例负责网络通信bot_connect(bot)/bot_disconnect(bot)向 NoneBot 登记/注销 Bot 连接setup_http_server(setup)/setup_websocket_server(setup)注册服务端路由request(setup)/websocket(setup)发起客户端 HTTP / WebSocket 请求以asynccontextmanager形式提供抽象方法_call_api(bot, api, **data)实际调用平台 API 的逻辑。与平台交互客户端通信方式NoneBot 提供多种 Driver 帮助适配器进行网络通信主要分为客户端主动连接平台和服务端接收平台推送两类。我们需要根据平台文档和特性选择合适的通信方式。如果平台提供 WebSocket 服务端机器人作为客户端主动连接使用客户端通信方式import asyncio from typing_extensions import override from nonebot import get_plugin_config from nonebot.exception import WebSocketClosed from nonebot.drivers import Request, WebSocketClientMixin class Adapter(BaseAdapter): override def __init__(self, driver: Driver, **kwargs: Any): super().__init__(driver, **kwargs) self.adapter_config: Config get_plugin_config(Config) self.task: Optional[asyncio.Task] None # 存储 ws 任务 self.setup() def setup(self) - None: if not isinstance(self.driver, WebSocketClientMixin): # 判断用户配置的 Driver 类型是否符合适配器要求不符合时应抛出异常 raise RuntimeError( fCurrent driver {self.config.driver} doesnt support websocket client connections! f{self.get_name()} Adapter need a WebSocket Client Driver to work. ) # 在 NoneBot 启动和关闭时进行相关操作 self.driver.on_startup(self.startup) self.driver.on_shutdown(self.shutdown) async def startup(self) - None: 定义启动时的操作例如和平台建立连接 self.task asyncio.create_task(self._forward_ws()) # 建立 ws 连接 async def _forward_ws(self): request Request( methodGET, urlyour_platform_websocket_url, headers{token: ...}, # 鉴权请求头 ) while True: try: async with self.websocket(request) as ws: try: # 处理 websocket ... except WebSocketClosed as e: log( ERROR, rbg #f8bbd0WebSocket Closed/bg #f8bbd0/r, e, ) except Exception as e: log( ERROR, rbg #f8bbd0Error while process data from websocket platform_websocket_url. Trying to reconnect.../bg #f8bbd0/r, e, ) finally: # 这里要断开 Bot 连接 ... except Exception as e: # 尝试重连 log( ERROR, rbg #f8bbd0Error while setup websocket to platform_websocket_url. Trying to reconnect.../bg #f8bbd0/r, e, ) await asyncio.sleep(3) # 重连间隔 async def shutdown(self) - None: 定义关闭时的操作例如停止任务、断开连接 # 断开 ws 连接 if self.task is not None and not self.task.done(): self.task.cancel()这段代码呈现了客户端适配器的完整生命周期setup()校验当前 Driver 是否支持 WebSocket 客户端isinstance(self.driver, WebSocketClientMixin)不支持则抛出RuntimeError提示用户更换 Driver随后通过driver.on_startup/driver.on_shutdown注册生命周期回调startup()NoneBot 启动时创建asyncio.Task执行_forward_ws建立连接_forward_ws()构造Request发起连接进入while True重连循环连接内处理收到的数据遇到WebSocketClosed定义于 nonebot/exception.py或其它异常时打印带彩色标签的日志finally中执行 Bot 断开逻辑外层except负责连接建立失败的延时重连asyncio.sleep(3)shutdown()NoneBot 关闭时取消任务断开连接。与平台交互服务端通信方式如果平台采用HTTP Webhook 推送或反向 WebSocket平台主动连接机器人则适配器作为服务端需要依赖实现 ASGI 的 Driver如 FastAPI、Quart参考 nonebot/internal/driver/abstract.py 中的ASGIMixinfrom nonebot import get_plugin_config from nonebot.drivers import ( Request, ASGIMixin, WebSocket, HTTPServerSetup, WebSocketServerSetup, ) class Adapter(BaseAdapter): override def __init__(self, driver: Driver, **kwargs: Any): super().__init__(driver, **kwargs) self.adapter_config: Config get_plugin_config(Config) self.setup() def setup(self) - None: if not isinstance(self.driver, ASGIMixin): raise RuntimeError( fCurrent driver {self.config.driver} doesnt support asgi server! f{self.get_name()} Adapter need a asgi server driver to work. ) # 建立服务端路由 # HTTP Webhook 路由 http_setup HTTPServerSetup( URL(your_webhook_url), # 路由地址 POST, # 接收的方法 WEBHOOK name, # 路由名称 self._handle_http, # 处理函数 ) self.setup_http_server(http_setup) # 反向 Websocket 路由 ws_setup WebSocketServerSetup( URL(your_websocket_url), # 路由地址 WebSocket name, # 路由名称 self._handle_ws, # 处理函数 ) self.setup_websocket_server(ws_setup) async def _handle_http(self, request: Request) - Response: HTTP 路由处理函数只有一个类型为 Request 的参数且返回值类型为 Response ... return Response( status_code200, # 状态码 headers{something: something}, # 响应头 contentxxx, # 响应内容 ) async def _handle_ws(self, websocket: WebSocket) - Any: WebSocket 路由处理函数只有一个类型为 WebSocket 的参数 ...HTTPServerSetup与WebSocketServerSetup均定义于 nonebot/internal/driver/model.py分别描述一个 HTTP / WebSocket 路由的地址、方法、名称与处理函数setup_http_server/setup_websocket_server是 Adapter 基类 提供的便捷方法内部会再次校验 Driver 是否为ASGIMixin随后把路由注册到 ASGI 应用中。关于通信方式的选择主流适配器的做法可以作为参考OneBot 系列同时支持WebSocket 客户端、WebSocket 服务端、HTTP WEBHOOK、HTTP POSTQQ 适配器使用WebSocket 服务端与HTTP WEBHOOKTelegram 适配器使用HTTP WEBHOOK。可以结合平台文档决定实现一种或多种方式。建立 Bot 连接与平台建立连接后需要将Bot实例化并调用适配器的bot_connect方法告知 NoneBot 建立了 Bot 连接与平台断开连接或重连时则调用bot_disconnect告知 NoneBot 断开连接from .bot import Bot class Adapter(BaseAdapter): def _handle_connect(self): bot_id ... # 通过配置或者平台 API 等方式获取到 Bot 的 ID bot Bot(self, self_idbot_id) # 实例化 Bot self.bot_connect(bot) # 建立 Bot 连接 def _handle_disconnect(self): self.bot_disconnect(bot) # 断开 Bot 连接bot_connect/bot_disconnect由 Adapter 基类 实现前者会把 Bot 存入self.bots[bot.self_id]并通知 Driver 登记连接后者会从字典中移除 Bot若不存在则抛出RuntimeError并通知 Driver 注销连接。这也是后续框架中get_bot、get_bots等查询接口的数据来源。转换 Event 事件接收到平台事件数据后需要将其转换为适配器的Event再交给 Bot 的handle_event方法处理。转换时可以利用nonebot.compat.type_validate_python直接按 pydantic 模型校验compat.py 中提供同时兼容 pydantic v1/v2import asyncio from typing import Any, Dict from nonebot.compat import type_validate_python from .bot import Bot from .event import Event from .log import log class Adapter(BaseAdapter): classmethod def payload_to_event(cls, payload: Dict[str, Any]) - Event: 根据平台事件的特性转换平台 payload 为具体 Event Event 模型继承自 pydantic.BaseModel具体请参考 pydantic 文档 # 做一层异常处理以应对平台事件数据的变更 try: return type_validate_python(your_event_class, payload) except Exception as e: # 无法正常解析为具体 Event 时给出日志提示 log( WARNING, fParse event error: {str(payload)}, ) # 也可以尝试转为基础 Event 进行处理 return type_validate_python(Event, payload) async def _forward(self, bot: Bot): payload: Dict[str, Any] # 接收到的事件数据 event self.payload_to_event(payload) # 让 bot 对事件进行处理 asyncio.create_task(bot.handle_event(event))type_validate_python(your_event_class, payload)会根据事件的message_type等字段选择具体的事件子类进行校验一旦平台数据结构变更导致解析失败则降级为解析基础Event并输出WARNING日志保证事件不至于完全丢失。注意asyncio.create_task(bot.handle_event(event))表明事件处理是异步调度、不阻塞连接接收循环的。调用平台 API适配器需要实现Adapter的_call_api方法这是 Adapter 基类 声明的抽象方法使插件开发者能够通过bot.call_api(...)调用平台 API。通信方式不同实现也不同from typing import Any from typing_extensions import override from nonebot.drivers import Request, WebSocket from .bot import Bot class Adapter(BaseAdapter): override async def _call_api(self, bot: Bot, api: str, **data: Any) - Any: log(DEBUG, fCalling API y{api}/y) # 给予日志提示 platform_data your_handle_data_method(data) # 自行将数据转为平台所需要的格式 # 采用 HTTP 请求的方式需要构造一个 Request 对象 request Request( methodGET, # 请求方法 urlapi, # 接口地址 headers..., # 请求头通常需要包含鉴权信息 paramsplatform_data, # 自行处理数据的传输形式 # jsonplatform_data, # dataplatform_data, ) # 发送请求返回结果 return await self.driver.request(request) # 采用 WebSocket 通信的方式可以直接调用 send 方法发送数据 # 通过某种方式获取到 bot 对应的 websocket 对象 ws: WebSocket your_get_websocket_method(bot.self_id) await ws.send_text(platform_data) # 发送 str 类型的数据 await ws.send_bytes(platform_data) # 发送 bytes 类型的数据 await ws.send(platform_data) # 是以上两种方式的合体 # 接收并返回结果同样的也有 str 和 bytes 的区别 return await ws.receive_text() return await ws.receive_bytes() return await ws.receive()实现要点HTTP 方式构造Request对象定义于 nonebot/internal/driver/model.py按需使用params查询参数、jsonJSON 请求体、data表单/原始数据三种传输形式之一然后通过self.driver.request(request)发送并返回ResponseWebSocket 方式根据bot.self_id找到对应的WebSocket对象调用send_textstr/send_bytesbytes/send合体发送数据用receive_text/receive_bytes/receive接收返回。从 Bot 基类 可以看到bot.call_api(api, **data)最终会调用self.adapter._call_api(self, api, **data)并且支持两种调用姿势await bot.call_api(send_msg, messagehello)或直接await bot.send_msg(messagehello)通过__getattr__动态生成。此外还提供了on_calling_api/on_called_api钩子可用于统一拦截、Mock API 调用如测试场景。Bot机器人对象Bot是插件开发者直接获取并使用的核心对象。需要继承基类Bot并实现相关方法from typing import TYPE_CHECKING, Any, Union from typing_extensions import override from nonebot.message import handle_event from nonebot.adapters import Bot as BaseBot from .event import Event from .message import Message, MessageSegment if TYPE_CHECKING: from .adapter import Adapter class Bot(BaseBot): your_adapter_name 协议 Bot 适配。 override def __init__(self, adapter: Adapter, self_id: str, **kwargs: Any): super().__init__(adapter, self_id) self.adapter: Adapter adapter # 一些有关 Bot 的信息也可以在此定义和存储 async def handle_event(self, event: Event): # 根据需要对事件进行某些预处理例如 # 检查事件是否和机器人有关操作去除事件消息首尾的 bot # 检查事件是否有回复消息调用平台 API 获取原始消息的消息内容 ... # 调用 handle_event 让 NoneBot 对事件进行处理 await handle_event(self, event) override async def send( self, event: Event, message: Union[str, Message, MessageSegment], **kwargs: Any, ) - Any: # 根据平台实现 Bot 回复事件的方法 # 将消息处理为平台所需的格式后调用发送消息接口进行发送例如 data message_to_platform_data(message) await self.send_message( datadata, ... )几个关键设计handle_event注意这里的handle_event是从nonebot.message导入的框架函数事件分发总入口与 Adapter 中的转换方法不同。Bot 重写它是为了在进入框架处理前做平台相关的预处理如剔除消息首尾的bot、解析回复消息原文然后再调用框架的handle_event(self, event)进入正常的匹配与分发流程send这是 Bot 基类 声明的抽象方法接收event与message可以是str、Message或MessageSegment需要将消息转为平台格式后调用发送接口内部通常复用_call_api或直接调用平台 APIself_id在__init__中通过super().__init__(adapter, self_id)设置用于标识机器人账号。Event事件模型Event是 NoneBot 的事件主体对象继承 pydanticBaseModel与Event基类见 nonebot/internal/adapter/event.py。基础Event需要实现六个抽象方法from typing_extensions import override from nonebot.compat import model_dump from nonebot.adapters import Event as BaseEvent class Event(BaseEvent): override def get_event_name(self) - str: # 返回事件的名称用于日志打印 return event name override def get_event_description(self) - str: # 返回事件的描述用于日志打印请注意转义 loguru tag return escape_tag(repr(model_dump(self))) override def get_message(self): # 获取事件消息的方法根据事件具体实现如果事件非消息类型事件则抛出异常 raise ValueError(Event has no message!) override def get_user_id(self) - str: # 获取用户 ID 的方法根据事件具体实现如果事件没有用户 ID则抛出异常 raise ValueError(Event has no context!) override def get_session_id(self) - str: # 获取事件会话 ID 的方法根据事件具体实现如果事件没有相关 ID则抛出异常 raise ValueError(Event has no context!) override def is_tome(self) - bool: # 判断事件是否和机器人有关 return False各方法语义与基类 event.py 的抽象定义一一对应get_type()事件类型通常是 NoneBot 内置的四类之一见下文get_event_name()/get_event_description()事件名称与描述用于日志打印get_event_description中建议用escape_tag转义避免平台原始内容中的字符被 loguru 当作颜色标签解析get_user_id()/get_session_id()用户 ID 与会话 ID会话 ID 通常由用户 ID、群组 ID 组合而成get_message()事件消息内容is_tome()事件是否与机器人有关例如是否 了机器人。基类还提供了默认实现get_plaintext()通过get_message().extract_plain_text()获取纯文本与get_log_string()通常无需重写。然后根据平台消息的类型编写各种具体事件并根据事件类型实现get_type方法事件类型见 事件类型。消息类型事件还应重写get_message、get_user_id等方法例如from .message import Message class HeartbeatEvent(Event): 心跳时间通常为元事件 override def get_type(self) - str: return meta_event class MessageEvent(Event): 消息事件 message_id: str user_id: str override def get_type(self) - str: return message override def get_message(self) - Message: # 返回事件消息对应的 NoneBot Message 对象 return self.message override def get_user_id(self) - str: return self.user_id class JoinRoomEvent(Event): 加入房间事件通常为通知事件 user_id: str room_id: str override def get_type(self) - str: return notice class ApplyAddFriendEvent(Event): 申请添加好友事件通常为请求事件 user_id: str override def get_type(self) - str: return requestNoneBot 内置的四种事件类型为meta_event元事件如心跳、message消息事件、notice通知事件如入群、request请求事件如好友申请。字段直接使用 pydantic 声明如message_id: str平台 payload 会按此模型自动校验填充。Message消息序列化Message负责正确序列化消息供插件处理。需要同时继承MessageSegment和Message两个类并实现相关方法from typing import Type, Iterable from typing_extensions import override from nonebot.utils import escape_tag from nonebot.adapters import Message as BaseMessage from nonebot.adapters import MessageSegment as BaseMessageSegment class MessageSegment(BaseMessageSegment[Message]): classmethod override def get_message_class(cls) - Type[Message]: # 返回适配器的 Message 类型本身 return Message override def __str__(self) - str: # 返回该消息段的纯文本表现形式通常在日志中展示 return text of MessageSegment override def is_text(self) - bool: # 判断该消息段是否为纯文本 return self.type text class Message(BaseMessage[MessageSegment]): classmethod override def get_segment_class(cls) - Type[MessageSegment]: # 返回适配器的 MessageSegment 类型本身 return MessageSegment staticmethod override def _construct(msg: str) - Iterable[MessageSegment]: # 实现从字符串中构造消息数组如无字符串嵌入格式可直接返回文本类型 MessageSegment ...从 Message 基类 的源码可以理解这些方法的用途MessageSegment基类是 dataclass含type: str与data: dict[str, Any]两个字段get_message_class()用于建立消息段到消息数组的关联__add__、join等操作依赖它__str__()返回消息段的纯文本表现形式命令匹配等场景会用到is_text()判断消息段是否为纯文本Message基类继承自listget_segment_class()反向关联消息段类型_construct(msg)实现从字符串解析出消息段数组若平台没有字符串嵌入格式如 CQ 码直接返回一个文本类型MessageSegment即可Message还自带template()方法消息模板用法类似str.format与extract_plain_text()等实用方法基类均已实现。然后根据平台具体的消息类型实现各种MessageSegment消息段图片、语音、At 等并通过类方法工厂方法暴露给插件使用。OneBot V11、QQ、Telegram 等适配器在message.py中都实现了丰富的消息段类型可作为参考。适配器测试适配器测试没有统一范式开发者可根据需要选择测试方案。这里给出两个常见问题的解决方法测试中无法导入 editable 模式安装的适配器代码。在 pytest 的conftest.py内添加如下代码将适配器的nonebot/adapters路径追加到命名空间包搜索路径from pathlib import Path import nonebot.adapters nonebot.adapters.__path__.append( # type: ignore str((Path(__file__).parent.parent / nonebot / adapters).resolve()) )这是因为适配器采用命名空间包结构pytest 默认的导入机制可能无法解析 editable 安装下的nonebot.adapters.{name}手动追加__path__即可解决Path(__file__).parent.parent指向项目根目录即nonebot/的上级。计算适配器测试覆盖率。在pyproject.toml中添加 pytest 配置[tool.pytest.ini_options] addopts --cov nonebot/adapters/{adapter-name} --cov-report term-missing将{adapter-name}替换为实际适配器名运行 pytest 即可输出终端缺失行覆盖报告。后续工作发布与文档完成适配器代码后若希望将适配器发布到 NoneBot 商店将适配器包发布到PyPIpython -m build构建、twine upload上传或在pyproject.toml中配置发布工具按官方流程操作前往商店适配器页签点击发布适配器按钮填写适配器相关信息名称、简介、仓库地址等并提交等待审核上架。另外建议为适配器编写文档或提供一些插件开发示例帮助其他开发者快速上手使用你的适配器——良好的文档与示例是适配器被广泛采用的重要一环。总结适配器编写要点一览编写 NoneBot2 适配器的核心脉络可以概括为组成部分继承基类核心职责必实现内容Adapternonebot.adapters.Adapter通信连接、事件转换、API 调用、Bot 注册get_name、_call_api以及按需setup/startup/shutdown、payload_to_eventBotnonebot.adapters.Bot存储机器人信息、回复事件、调用 API 的上层入口send抽象方法按需重写handle_eventEventnonebot.adapters.Event平台事件的统一载体get_type、get_event_name、get_event_description、get_user_id、get_session_id、get_message、is_tomeMessage/MessageSegmentnonebot.adapters.Message/MessageSegment消息的解析与序列化get_message_class、get_segment_class、_construct、is_text、__str__建议在编写过程中对照 适配器功能与组成、Driver 详解 与 事件类型 三篇文档并结合本仓库中 Adapter 基类、Bot 基类、Event 基类、Message 基类 的源码理解每个待实现方法的实际调用场景即可写出健壮、符合 NoneBot 规范的平台适配器。赞分享后端即时通讯【免费下载链接】nonebot2跨平台 Python 异步聊天机器人框架 / Asynchronous multi-platform chatbot framework written in Python项目地址https://gitcode.com/gh_mirrors/no/nonebot2点击查看免费下载相关推荐NoneBot2 适配器开发实战从零编写 Adapter 对接任意聊天平台NoneBot2 适配器开发实战从零编写 Adapter 对接任意聊天平台 本篇技术指南以 NoneBot2 框架的适配器开发文档为核心完整讲解如何编写一个后端即时通讯NoneBot2 适配器开发完全指南从零编写跨平台协议适配器NoneBot2 适配器开发完全指南从零编写跨平台协议适配器 NoneBot2 是一个跨平台 Python 异步聊天机器人框架其跨平台能力正是由适配器后端即时通讯HsMod插件炉石传说玩家的终极游戏体验增强指南HsMod插件炉石传说玩家的终极游戏体验增强指南 炉石传说作为全球最受欢迎的卡牌游戏之一其丰富的玩法和策略性吸引了数百万玩家。然而冗长的动画、繁琐的操作和游戏开发上一篇HashLips Art Engine日志级别配置调试与生产环境区分下一篇gh_mirrors/de/deprecated-version的微前端状态管理方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表