diff --git a/zhenxun/builtin_plugins/shop/__init__.py b/zhenxun/builtin_plugins/shop/__init__.py index 89282d63..120d2198 100644 --- a/zhenxun/builtin_plugins/shop/__init__.py +++ b/zhenxun/builtin_plugins/shop/__init__.py @@ -5,7 +5,9 @@ from nonebot_plugin_alconna import ( AlconnaQuery, Args, Arparma, + At, Match, + MultiVar, Option, Query, Subcommand, @@ -33,6 +35,7 @@ __plugin_meta__ = PluginMetadata( usage=""" 商品操作 指令: + 商店 我的金币 我的道具 使用道具 [名称/Id] @@ -46,6 +49,7 @@ __plugin_meta__ = PluginMetadata( plugin_type=PluginType.NORMAL, menu_type="商店", commands=[ + Command(command="商店"), Command(command="我的金币"), Command(command="我的道具"), Command(command="购买道具"), @@ -74,13 +78,21 @@ _matcher = on_alconna( Subcommand("my-cost", help_text="我的金币"), Subcommand("my-props", help_text="我的道具"), Subcommand("buy", Args["name?", str]["num?", int], help_text="购买道具"), - Subcommand("use", Args["name?", str]["num?", int], help_text="使用道具"), Subcommand("gold-list", Args["num?", int], help_text="金币排行"), ), priority=5, block=True, ) +_use_matcher = on_alconna( + Alconna( + "使用道具", + Args["name?", str]["num?", int]["at_users?", MultiVar(At)], + ), + priority=5, + block=True, +) + _matcher.shortcut( "我的金币", command="商店", @@ -102,13 +114,6 @@ _matcher.shortcut( prefix=True, ) -_matcher.shortcut( - "使用道具(?P.*?)", - command="商店", - arguments=["use", "{name}"], - prefix=True, -) - _matcher.shortcut( "金币排行", command="商店", @@ -172,7 +177,7 @@ async def _( await MessageUtils.build_message(result).send(reply_to=True) -@_matcher.assign("use") +@_use_matcher.handle() async def _( bot: Bot, event: Event, @@ -181,6 +186,7 @@ async def _( arparma: Arparma, name: Match[str], num: Query[int] = AlconnaQuery("num", 1), + at_users: Query[list[At]] = AlconnaQuery("at_users", []), ): if not name.available: await MessageUtils.build_message( @@ -188,7 +194,7 @@ async def _( ).finish(reply_to=True) try: result = await ShopManage.use( - bot, event, session, message, name.result, num.result, "" + bot, event, session, message, name.result, num.result, "", at_users.result ) logger.info( f"使用道具 {name.result}, 数量: {num.result}", diff --git a/zhenxun/builtin_plugins/shop/_data_source.py b/zhenxun/builtin_plugins/shop/_data_source.py index 2160238d..d4af9d08 100644 --- a/zhenxun/builtin_plugins/shop/_data_source.py +++ b/zhenxun/builtin_plugins/shop/_data_source.py @@ -8,7 +8,7 @@ from typing import Any, ClassVar, Literal from nonebot.adapters import Bot, Event from nonebot.compat import model_dump -from nonebot_plugin_alconna import UniMessage, UniMsg +from nonebot_plugin_alconna import At, UniMessage, UniMsg from nonebot_plugin_uninfo import Uninfo from pydantic import BaseModel, Field, create_model from tortoise.expressions import Q @@ -48,6 +48,10 @@ class Goods(BaseModel): """model""" session: Uninfo | None = None """Uninfo""" + at_user: str | None = None + """At对象""" + at_users: list[str] = [] + """At对象列表""" class ShopParam(BaseModel): @@ -73,6 +77,10 @@ class ShopParam(BaseModel): """Uninfo""" message: UniMsg """UniMessage""" + at_user: str | None = None + """At对象""" + at_users: list[str] = [] + """At对象列表""" extra_data: ClassVar[dict[str, Any]] = {} """额外数据""" @@ -156,6 +164,7 @@ class ShopManage: goods: Goods, num: int, text: str, + at_users: list[str] = [], ) -> tuple[ShopParam, dict[str, Any]]: """构造参数 @@ -165,6 +174,7 @@ class ShopManage: goods_name: 商品名称 num: 数量 text: 其他信息 + at_users: at用户 """ group_id = None if session.group: @@ -172,6 +182,7 @@ class ShopManage: session.group.parent.id if session.group.parent else session.group.id ) _kwargs = goods.params + at_user = at_users[0] if at_users else None model = goods.model( **{ "goods_name": goods.name, @@ -183,6 +194,8 @@ class ShopManage: "text": text, "session": session, "message": message, + "at_user": at_user, + "at_users": at_users, } ) return model, { @@ -194,6 +207,8 @@ class ShopManage: "num": num, "text": text, "goods_name": goods.name, + "at_user": at_user, + "at_users": at_users, } @classmethod @@ -223,6 +238,7 @@ class ShopManage: **param.extra_data, "session": session, "message": message, + "shop_param": ShopParam, } for key in list(param_json.keys()): if key not in args: @@ -308,6 +324,7 @@ class ShopManage: goods_name: str, num: int, text: str, + at_users: list[At] = [], ) -> str | UniMessage | None: """使用道具 @@ -319,6 +336,7 @@ class ShopManage: goods_name: 商品名称 num: 使用数量 text: 其他信息 + at_users: at用户 返回: str | MessageFactory | None: 使用完成后返回信息 @@ -339,8 +357,9 @@ class ShopManage: goods = cls.uuid2goods.get(goods_info.uuid) if not goods or not goods.func: return f"{goods_info.goods_name} 未注册使用函数, 无法使用..." + at_user_ids = [at.target for at in at_users] param, kwargs = cls.__build_params( - bot, event, session, message, goods, num, text + bot, event, session, message, goods, num, text, at_user_ids ) if num > param.max_num_limit: return f"{goods_info.goods_name} 单次使用最大数量为{param.max_num_limit}..." @@ -479,10 +498,13 @@ class ShopManage: if not user.props: return None - user.props = {uuid: count for uuid, count in user.props.items() if count > 0} - goods_list = await GoodsInfo.filter(uuid__in=user.props.keys()).all() goods_by_uuid = {item.uuid: item for item in goods_list} + user.props = { + uuid: count + for uuid, count in user.props.items() + if count > 0 and goods_by_uuid.get(uuid) + } table_rows = [] for i, prop_uuid in enumerate(user.props):