nonebot2 icon indicating copy to clipboard operation
nonebot2 copied to clipboard

RFC: 统一插件元数据声明

Open mnixry opened this issue 2 years ago • 24 comments

为什么

现在, NoneBot社区内有各种类型的插件, 为了对这些插件查询帮助等, 需要一个统一的规范. 目前存在大量插件自己写了帮助, 导致一个帮助可能会触发大量插件响应, 并且格式不统一

怎么做

目前, 社区对于插件规范有了多种实现, 包括以下两种

所以, 我们可以在插件根中使用字段指定一部分插件元数据

具体规范

字段规范(已部分实现)

以下字段应作为插件根中的全局变量被声明.

初版设计(未使用)
__plugin_adapters__ = [OneBotV11Adapter] #插件支持的Adapter, 如果不写就默认支持所有Adapter, 可以考虑根据这个字段进行adapter加载检测
__plugin_name__ = PluginName('unique_name',human='插件人类阅读名称') #如果没有unique name就用插件包名代替
__plugin_name__ = 'unique_name [插件人类阅读名称]' #这样也行, 就不用定义结构体了

__plugin_des__ = '插件介绍' #简短介绍插件的功能(不包括使用方法), 可以给个字数限制?

__plugin_usage__ = '插件用法' #插件使用方法, 可能需要支持很多种定义方式
__plugin_usage__:Dict[Adapter,str] #这样应该也可以被接受
__plugin_usage__:Dict[Type[Matcher],str] #这样可能也得需要支持, 就是直接根据命令生成

__plugin_settings__: Config #插件的配置, 读env出来的那些

__plugin_version__:str #插件版本, 如果没有就从包元数据读取
__plugin_author__ = 'Author <[email protected]>'  #插件作者声明, 不写就没有
@dataclass(eq=False)
class PluginMetadata:
    """插件元信息,由插件编写者提供"""

    name: str
    """插件名称"""
    description: str
    """插件功能介绍"""
    usage: str
    """插件使用方法"""
    type: Optional[str] = None
    """插件类型,用于商店分类"""
    homepage: Optional[str] = None
    """插件主页"""
    config: Optional[Type[BaseModel]] = None
    """插件配置项"""
    supported_adapters: Optional[Set[str]] = None
    """插件支持的适配器模块路径

    格式为 `<module>[:<Adapter>]`,`~` 为 `nonebot.adapters.` 的缩写。

    `None` 表示支持**所有适配器**。
    """
    extra: Dict[Any, Any] = field(default_factory=dict)
    """插件额外信息,可由插件编写者自由扩展定义"""

__plugin_meta__ = PluginMetadata(...)

API规范(未确定)

添加一个钩子, 在插件加载完成后调用, 返回包含上述字段的函数

def plugin_load_callback(plugin_name:str,plugin:Module)->Optional[PluginMetadata]:
	"""
	如果返回None就不管了, 如果返回了元数据就取, 如果异常阻止该插件加载并记录该异常
	如果有多个返回元数据的行为呢?
	"""
    	...

添加能够读取全部插件元数据的API

添加一个内建插件叫nonebot.plugin.help提供最简单的帮助支持, 即: 将nonebot-plugin-help合并进来

兼容性

理论上不会break, 如果__plugin_meta__没写就代表没有声明元数据

其他

可以考虑为适配了以上信息的插件在插件商店中优先推荐, 或者进行标识

mnixry avatar May 28 '22 05:05 mnixry

基于目前插件情况考虑,__plugin_adapters__ 还是默认为 [OneBotV11Adapter] 为好。

j1g5awi avatar May 28 '22 06:05 j1g5awi

插件的优先级能不能也做个推荐值,社区插件的优先级有点混乱

Copaan avatar May 28 '22 08:05 Copaan

是否应该把 __plugin_usage__ 细分,如添加 __plugin_cmd__, __plugin_example__

MeetWq avatar May 30 '22 12:05 MeetWq

这个理论上可以有

synodriver avatar May 30 '22 12:05 synodriver

为什么不考虑从docstring里面读呢

synodriver avatar May 30 '22 12:05 synodriver

为什么不考虑从docstring里面读呢

感觉也可以,主要还是要看 @yanyongyu 这边插件系统设计的怎么样处理起来比较方便?

mnixry avatar May 30 '22 12:05 mnixry

可以弄成Optional的,有的话最好,没有也不报错那种,还要和之前的相兼容

synodriver avatar May 30 '22 12:05 synodriver

如果是元数据的话,肯定是一个结构体更易读取,docstring你还得解析string

yanyongyu avatar May 31 '22 02:05 yanyongyu

alpha 版本赋值 __plugin_name__ 可能影响插件加载 #502 #623,现在 beta 版本没问题了吗?

Ailitonia avatar Jun 01 '22 01:06 Ailitonia

alpha 版本赋值 __plugin_name__ 可能影响插件加载 https://github.com/nonebot/nonebot2/issues/502 https://github.com/nonebot/nonebot2/issues/623,现在 beta 版本没问题了吗?

https://github.com/nonebot/nonebot2/commit/72f5aeea54971781087366207b346dbc9ba7a4e7 https://github.com/nonebot/nonebot2/commit/08f56db385dd03c3716997091831dca72251bf56 https://github.com/nonebot/nonebot2/commit/2ccbc93e48ca591b87d523ecdd642d853cc59e88 三次 commit 已经移除了 __plugin_name__ 属性,没问题了

MingxuanGame avatar Jun 01 '22 01:06 MingxuanGame

可不可以给matcher也添加元数据呢,毕竟一个插件内可能有多个功能、用法不同的matcher

CMHopeSunshine avatar Jun 20 '22 18:06 CMHopeSunshine

为加强插件发布规范,决定将插件元数据纳入插件发布审核流程。现阶段拟添加以下字段,相关细节暂未确定,大家有啥想法可以讨论一下(

class PluginMetadata:
    ...
    homepage: Optional[str] = None  # 发布插件必填
    type: Optional[str] = None  # 发布插件必填,类型由 noneflow 校验
    supported_adapters: Optional[Set[str]] = None  # 默认所有适配器

yanyongyu avatar Apr 24 '23 02:04 yanyongyu

我认为目前比较麻烦的是各插件的帮助指令都大同小异,一个指令可能就同时触发了多个插件的帮助。个人觉得插件帮助类的信息也可以加入到元数据中,框架提供一个统一的帮助指令,根据元数据自动生成各个插件的帮助文档,如果能带参数细化到查看指定插件的帮助文档最好了

zangxx66 avatar Apr 25 '23 07:04 zangxx66

@zangxx66 插件的帮助信息已经在元数据里了哦,description和usage,现在也已经有帮助相关插件了,你可以在商店里查看

yanyongyu avatar Apr 25 '23 07:04 yanyongyu

@zangxx66 插件的帮助信息已经在元数据里了哦,description和usage,现在也已经有帮助相关插件了,你可以在商店里查看

我有一个小小的疑问,这个插件目前是作为可选安装的吗,如果用户没有安装这个插件还是会造成大量插件同时响应帮助

zangxx66 avatar Apr 25 '23 07:04 zangxx66

nb官方不会去限制插件是否自己有帮助命令,这个你也没法做到统一

yanyongyu avatar Apr 25 '23 09:04 yanyongyu

插件都要发布到pypi吧,发布的时候要写package的元数据的,用那些何如?

synodriver avatar Apr 25 '23 09:04 synodriver

不用管数据是在哪的,现在问题是插件不遵守你也没有办法

yanyongyu avatar Apr 25 '23 09:04 yanyongyu

我们是不是可以考虑把定义插件需要的配置model也作为标准要求的元数据之一?

这样做nb-cli ui的话可以有更好的插件配置选项

mnixry avatar Apr 26 '23 08:04 mnixry

我们是不是可以考虑把定义插件需要的配置model也作为标准要求的元数据之一?

现在不是已经有config了吗

yanyongyu avatar Apr 26 '23 08:04 yanyongyu

现在不是已经有config了吗

嗯,我的意思是把这个config model字段作为plugin publish bot会采用的一个字段,给这个字段生成json schema并存储在文档索引,这样就可以在使用ui的时候知道有哪些字段需要配置(甚至不需要安装就可以)

然后剩下几个publish bot要求的字段也加进插件索引吧?这样会不会更好点

mnixry avatar Apr 26 '23 08:04 mnixry

config没必要在商店里进行索引吧,代价太大了,这个更适合在webui里进行,剩下发布插件要求的字段会进行索引

yanyongyu avatar Apr 26 '23 08:04 yanyongyu

由于存在可选适配器支持的可能,插件支持的适配器列表改为supported_adapters: Optional[List[str]] = None

yanyongyu avatar May 06 '23 03:05 yanyongyu

为了保证tag的规范性和帮助插件开发者选择合适的tag,依然采用文档发布前端填写相关tag并提交,另外插件类型由于分类可能会变动,不适合与nonebot库一同编写,我更倾向于依然从前端选择提交或者noneflow进行string校验

yanyongyu avatar May 10 '23 16:05 yanyongyu