动态命令执行,解析和存储。
DynCommands允许您动态导入并运行Python功能。对于不重新启动的情况下,可将命令添加到IRC聊天机器人或CLI应用程序中。
解析字符串时,它将命令名称与参数分开,并使用这些参数执行存储的函数。每次调用解析器时,您都可以传递自己的自定义kwargs,命令将可以访问。
在允许运行之前,所有命令模块均通过限制性PPYTHON进行编译。您可以通过设置CommandParser._unrestricted to True关闭限制执行,尽管在运行不信任的代码时会高度灰心。
from pathlib import Path
from dyncommands import CommandParser , CommandContext , CommandSource
output : str = ''
def callback ( text , * args ):
global output
output = text
path = Path ( 'path/to/directory' ) # Must be a directory with a `commands.json` file in it
parser = CommandParser ( path ) # Create the parser, which initializes using data located in the path directory
source = CommandSource ( callback ) # Create a source, which is used to talk back to the caller
input_ = 'command-that-returns-wow arg1 arg2' # this command would call zzz__command-that-returns-wow.py with arg1 and arg2
parser . parse ( CommandContext ( input_ , source )) # Parse the new context and run the command and callback (If no errors occur)
assert output == 'wow'命令的元数据存储在commands.json目录CommandParser.commands_path命令中。这是将解析器的所有数据加载和存储的地方。
所有commands.json文件通过JSON Schemas通过JSonschema Python软件包验证
| 钥匙 | 类型 | 描述 | 默认 | 必需的 |
|---|---|---|---|---|
commandPrefix | 细绳 | 字符串必须从此前缀开始,否则将被忽略。空字符串接受全部。 | N/A。 | 是的 |
commands | 数组[命令] | 包含存储命令模块的元数据。 | N/A。 | 是的 |
| 钥匙 | 类型 | 描述 | 默认 | 必需的 |
|---|---|---|---|---|
name | 细绳 | 独特地将命令标识为命令范围。 | N/A。 | 是的 |
usage | 细绳 | 用法信息(如何使用ARGS)。 | “” | 不 |
description | 细绳 | 命令描述。 | “” | 不 |
permission | 整数 | CommandSource需要运行命令的权限级别。 | 0 | 不 |
function | 布尔,无效 | 是否有一个相关的Python模块要加载。 | 无效的 | 不 |
children | 数组[命令] | 子命令;这些由父母的功能处理。 (无关的模块本身)。 | [] | 不 |
overridable | 布尔 | CommandParser是否可以覆盖该对象内部的任何数据(必须手动启用)。 | 真的 | 不 |
disabled | 布尔 | 如果true仍然加载命令,但是在尝试执行时会提出残疾人。 | 错误的 | 不 |
注意:命令模块没有加载,除非将它们列在commands.json中function
commands.json内容: {
"commandPrefix" : " ! " ,
"commands" : [
{
"name" : " test " ,
"usage" : " test [*args:any] " ,
"description" : " Test command. " ,
"permission" : 500 ,
"function" : true
},
{
"name" : " test2 " ,
"function" : false
}
]
}动态加载的命令用“ zzz__”前缀表示,用文件名表示。在命令模块中,有一个函数定义为command 。此函数将映射到Command的函数属性并存储在内存中以进行执行。该功能可以访问被解析的任何ARG以及Kwargs:
“ self ”( Command ),该(命令)容纳正在执行的命令的元数据。
“解析器”( CommandParser ),该命令列表和命令数据列表。
“上下文”( CommandContext ),它提供CommandSource和发送的原始文本。
CommandParser.parse(context: CommandContext, **kwargs) 。由于命令无法导入自己的模块,因此有些包含在Globals( math , random和string )中。全局范围中包含的其他属性是: getitem ( operator.getItem )和ImproperUsageError ( dyncommands.exceptions.improperusageerror )。
def command ( * args , ** kwargs ):
self , context = kwargs . pop ( 'self' ), kwargs . pop ( 'context' )
source = context . source
if len ( args ) == 2 :
amount , sides = abs ( int ( getitem ( args , 0 ))), abs ( int ( getitem ( args , 1 )))
if amount > 0 and sides > 0 :
dice_rolls = [ f" { ( str ( i + 1 ) + ':' ) if amount > 1 else '' } { str ( random . randint ( 1 , sides )) } / { sides } " for i in range ( amount )]
source . send_feedback ( f"/me U0001f3b2 { source . display_name } rolled { 'a die' if amount == 1 else str ( amount ) + ' dice' } with { sides } side { '' if sides == 1 else 's' } : { ', ' . join ( dice_rolls ) } U0001f3b2 " )
else :
raise ImproperUsageError ( self , context )
else :
raise ImproperUsageError ( self , context )您可以随时调用CommandParser.reload()从磁盘存储中重新加载所有命令模块和元数据。
../
│
├───[commands_path]/
│ ├─── commands.json
│ ├─── zzz__[command1].py
│ ├─── zzz__[command2].py
│ └─── zzz__[command3].py
│
要添加命令,您可以手动将数据输入commands.json CommandParser.add_command(text: str, link: bool = False, **kwargs)使用此方法的最简单方法是将命令模块读取为文本并将其传递给第一个参数。您还可以在线存储命令模块以允许远程安装,因为将链接参数设置为true将以链接读取文本,并将从该链接获取原始文本数据。例如:要点和粘贴。
注意:添加命令时,必须填充“名称”的元数据。这可以以评论的形式完成。
删除已经添加的命令相对容易。只需调用CommandParser.remove_command(name: str)带有要删除的命令的名称,它将从磁盘中删除元数据和命令模块。
如果您不想在删除时删除命令,则更好的选择是用CommandParser.set_disabled(name: str, value: bool)禁用它。
# Name: points
# Usage: points [get (username:string) | set (username:string amount:integer)]
# Description: Get your current points
# Permission: 0
# Children: [{'name': 'get', 'usage': 'get (username:string)', 'permission':0}, {'name': 'set', 'usage': 'set (username:string amount:integer)', 'permission':500}]
def command ( * args , ** kwargs ):
... parser = CommandParser ( './' )
with open ( 'some_metadata.json' ) as _file :
get_ = { 'name' : 'get' , 'usage' : 'get (username:string)' , 'permission' : 0 }
set_ = { 'name' : 'set' , 'usage' : 'set (username:string amount:integer)' , 'permission' : 500 }
children = [ get_ , set_ ]
parser . add_command ( _file . read (), name = 'my-command' , description = 'Command with child commands.' , children = children ) parser = CommandParser ( './' )
with open ( 'some_metadata.json' ) as _file :
metadata = json . load ( _file )
parser . add_command ( 'https://gist.github.com/random/892hdh2fh389x0wcmksio7m' , link = True , ** metadata ) DynCommand CommandParser本地支持权限级别的处理,因此您不必在每个命令函数中实现类似的系统。
每个命令都有元数据值permission (特殊值-1除外)是CommandSource所需的最低权限级别。 -1表示“无限”的要求,在该许可系统处于活动状态时,没有CommandSource可以执行它。
要禁用权限系统,请将CommandParser的s _ignore_permission属性设置为true。注意:由于此属性以“ _”开头,因此尝试从命令的功能内部更改它将导致汇编失败和例外。