mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2025-12-14 21:52:56 +08:00
新增插件智能模式适配 (#1850)
* 新增插件智能模式适配 * 🚨 auto fix by pre-commit hooks * 更改类名,命名更清晰 * 🎨 添加模块化参数 * 🎨 AI模块化修改 * 🩹 道具调用修复 * 🩹 修复商品使用前检测 * ✨ retry增加参数适配 * ✨ 修改道具使用函数参数传递 * ✨ 捕获道具无法使用异常 * 🐛 添加依赖require * 🐛 修复插件使用问题 --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: HibiKier <45528451+HibiKier@users.noreply.github.com>
This commit is contained in:
parent
78df9ed086
commit
a6ddb726d3
@ -18,6 +18,7 @@ from nonebot_plugin_uninfo import Uninfo
|
||||
|
||||
from zhenxun.configs.utils import BaseBlock, Command, PluginExtraData, RegisterConfig
|
||||
from zhenxun.services.log import logger
|
||||
from zhenxun.utils.decorator.shop import NotMeetUseConditionsException
|
||||
from zhenxun.utils.depends import UserName
|
||||
from zhenxun.utils.enum import BlockType, PluginType
|
||||
from zhenxun.utils.exception import GoodsNotFound
|
||||
@ -202,6 +203,12 @@ async def _(
|
||||
await MessageUtils.build_message(
|
||||
f"没有找到道具 {name.result} 或道具数量不足..."
|
||||
).send(reply_to=True)
|
||||
except NotMeetUseConditionsException as e:
|
||||
if info := e.get_info():
|
||||
await MessageUtils.build_message(info).finish() # type: ignore
|
||||
await MessageUtils.build_message(
|
||||
f"使用道具 {name.result} 的条件不满足..."
|
||||
).send(reply_to=True)
|
||||
|
||||
|
||||
@_matcher.assign("gold-list")
|
||||
|
||||
@ -194,7 +194,6 @@ class ShopManage:
|
||||
"num": num,
|
||||
"text": text,
|
||||
"goods_name": goods.name,
|
||||
"message": message,
|
||||
}
|
||||
|
||||
@classmethod
|
||||
@ -203,8 +202,9 @@ class ShopManage:
|
||||
args: MappingProxyType,
|
||||
param: ShopParam,
|
||||
session: Uninfo,
|
||||
message: UniMsg,
|
||||
**kwargs,
|
||||
) -> list[Any]:
|
||||
) -> dict:
|
||||
"""解析参数
|
||||
|
||||
参数:
|
||||
@ -212,31 +212,30 @@ class ShopManage:
|
||||
param: ShopParam
|
||||
|
||||
返回:
|
||||
list[Any]: 参数
|
||||
dict: 参数
|
||||
"""
|
||||
param_list = []
|
||||
_bot = param.bot
|
||||
param.bot = None
|
||||
param_json = {**param.to_dict(), **param.extra_data}
|
||||
param_json["bot"] = _bot
|
||||
for par in args.keys():
|
||||
if par in ["shop_param"]:
|
||||
param_list.append(param)
|
||||
elif par in ["session"]:
|
||||
param_list.append(session)
|
||||
elif par in ["message"]:
|
||||
param_list.append(kwargs.get("message"))
|
||||
elif par not in ["args", "kwargs"]:
|
||||
param_list.append(param_json.get(par))
|
||||
if kwargs.get(par) is not None:
|
||||
del kwargs[par]
|
||||
return param_list
|
||||
param_json = {
|
||||
"bot": _bot,
|
||||
"kwargs": kwargs,
|
||||
**param.to_dict(),
|
||||
**param.extra_data,
|
||||
"session": session,
|
||||
"message": message,
|
||||
}
|
||||
for key in list(param_json.keys()):
|
||||
if key not in args:
|
||||
del param_json[key]
|
||||
return param_json
|
||||
|
||||
@classmethod
|
||||
async def run_before_after(
|
||||
cls,
|
||||
goods: Goods,
|
||||
param: ShopParam,
|
||||
session: Uninfo,
|
||||
message: UniMsg,
|
||||
run_type: Literal["after", "before"],
|
||||
**kwargs,
|
||||
):
|
||||
@ -250,16 +249,19 @@ class ShopManage:
|
||||
fun_list = goods.before_handle if run_type == "before" else goods.after_handle
|
||||
if fun_list:
|
||||
for func in fun_list:
|
||||
args = inspect.signature(func).parameters
|
||||
if args and next(iter(args.keys())) != "kwargs":
|
||||
if args := inspect.signature(func).parameters:
|
||||
if asyncio.iscoroutinefunction(func):
|
||||
await func(*cls.__parse_args(args, param, **kwargs))
|
||||
await func(
|
||||
**cls.__parse_args(args, param, session, message, **kwargs)
|
||||
)
|
||||
else:
|
||||
func(*cls.__parse_args(args, param, **kwargs))
|
||||
func(
|
||||
**cls.__parse_args(args, param, session, message, **kwargs)
|
||||
)
|
||||
elif asyncio.iscoroutinefunction(func):
|
||||
await func(**kwargs)
|
||||
await func()
|
||||
else:
|
||||
func(**kwargs)
|
||||
func()
|
||||
|
||||
@classmethod
|
||||
async def __run(
|
||||
@ -267,6 +269,7 @@ class ShopManage:
|
||||
goods: Goods,
|
||||
param: ShopParam,
|
||||
session: Uninfo,
|
||||
message: UniMsg,
|
||||
**kwargs,
|
||||
) -> str | UniMessage | None:
|
||||
"""运行道具函数
|
||||
@ -280,18 +283,20 @@ class ShopManage:
|
||||
"""
|
||||
args = inspect.signature(goods.func).parameters # type: ignore
|
||||
if goods.func:
|
||||
if args and next(iter(args.keys())) != "kwargs":
|
||||
if args:
|
||||
return (
|
||||
await goods.func(*cls.__parse_args(args, param, session, **kwargs))
|
||||
await goods.func(
|
||||
**cls.__parse_args(args, param, session, message, **kwargs)
|
||||
)
|
||||
if asyncio.iscoroutinefunction(goods.func)
|
||||
else goods.func(*cls.__parse_args(args, param, session, **kwargs))
|
||||
else goods.func(
|
||||
**cls.__parse_args(args, param, session, message, **kwargs)
|
||||
)
|
||||
)
|
||||
if asyncio.iscoroutinefunction(goods.func):
|
||||
return await goods.func(
|
||||
**kwargs,
|
||||
)
|
||||
return await goods.func()
|
||||
else:
|
||||
return goods.func(**kwargs)
|
||||
return goods.func()
|
||||
|
||||
@classmethod
|
||||
async def use(
|
||||
@ -339,12 +344,12 @@ class ShopManage:
|
||||
)
|
||||
if num > param.max_num_limit:
|
||||
return f"{goods_info.goods_name} 单次使用最大数量为{param.max_num_limit}..."
|
||||
await cls.run_before_after(goods, param, "before", **kwargs)
|
||||
result = await cls.__run(goods, param, session, **kwargs)
|
||||
await cls.run_before_after(goods, param, session, message, "before", **kwargs)
|
||||
result = await cls.__run(goods, param, session, message, **kwargs)
|
||||
await UserConsole.use_props(
|
||||
session.user.id, goods_info.uuid, num, PlatformUtils.get_platform(session)
|
||||
)
|
||||
await cls.run_before_after(goods, param, "after", **kwargs)
|
||||
await cls.run_before_after(goods, param, session, message, "after", **kwargs)
|
||||
if not result and param.send_success_msg:
|
||||
result = f"使用道具 {goods.name} {num} 次成功!"
|
||||
return result
|
||||
|
||||
@ -170,6 +170,40 @@ class PluginSetting(BaseModel):
|
||||
"""调用插件好感度限制"""
|
||||
|
||||
|
||||
class AICallableProperties(BaseModel):
|
||||
type: str
|
||||
"""参数类型"""
|
||||
description: str
|
||||
"""参数描述"""
|
||||
enums: list[str] | None = None
|
||||
"""参数枚举"""
|
||||
|
||||
|
||||
class AICallableParam(BaseModel):
|
||||
type: str
|
||||
"""类型"""
|
||||
properties: dict[str, AICallableProperties]
|
||||
"""参数列表"""
|
||||
required: list[str]
|
||||
"""必要参数"""
|
||||
|
||||
|
||||
class AICallableTag(BaseModel):
|
||||
name: str
|
||||
"""工具名称"""
|
||||
parameters: AICallableParam | None = None
|
||||
"""工具参数"""
|
||||
description: str
|
||||
"""工具描述"""
|
||||
func: Callable | None = None
|
||||
"""工具函数"""
|
||||
|
||||
def to_dict(self):
|
||||
result = model_dump(self)
|
||||
del result["func"]
|
||||
return result
|
||||
|
||||
|
||||
class SchedulerModel(BaseModel):
|
||||
trigger: Literal["date", "interval", "cron"]
|
||||
"""trigger"""
|
||||
@ -249,6 +283,8 @@ class PluginExtraData(BaseModel):
|
||||
"""常用sql"""
|
||||
is_show: bool = True
|
||||
"""是否显示在菜单中"""
|
||||
smart_tools: list[AICallableTag] | None = None
|
||||
"""智能模式函数工具集"""
|
||||
|
||||
def to_dict(self, **kwargs):
|
||||
return model_dump(self, **kwargs)
|
||||
|
||||
@ -5,3 +5,4 @@ require("nonebot_plugin_alconna")
|
||||
require("nonebot_plugin_session")
|
||||
require("nonebot_plugin_htmlrender")
|
||||
require("nonebot_plugin_uninfo")
|
||||
require("nonebot_plugin_waiter")
|
||||
|
||||
@ -1,16 +1,24 @@
|
||||
from anyio import EndOfStream
|
||||
from httpx import ConnectError, HTTPStatusError, TimeoutException
|
||||
from tenacity import retry, retry_if_exception_type, stop_after_attempt, wait_fixed
|
||||
|
||||
|
||||
class Retry:
|
||||
@staticmethod
|
||||
def api():
|
||||
def api(
|
||||
retry_count: int = 3, wait: int = 1, exception: tuple[type[Exception], ...] = ()
|
||||
):
|
||||
"""接口调用重试"""
|
||||
base_exceptions = (
|
||||
TimeoutException,
|
||||
ConnectError,
|
||||
HTTPStatusError,
|
||||
EndOfStream,
|
||||
*exception,
|
||||
)
|
||||
return retry(
|
||||
reraise=True,
|
||||
stop=stop_after_attempt(3),
|
||||
wait=wait_fixed(1),
|
||||
retry=retry_if_exception_type(
|
||||
(TimeoutException, ConnectError, HTTPStatusError)
|
||||
),
|
||||
stop=stop_after_attempt(retry_count),
|
||||
wait=wait_fixed(wait),
|
||||
retry=retry_if_exception_type(base_exceptions),
|
||||
)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user