zhenxun_bot/zhenxun/plugins/bym_ai/bym_gift/data_source.py
2025-07-01 16:56:34 +08:00

174 lines
4.7 KiB
Python

import asyncio
from collections.abc import Callable
from datetime import datetime
import inspect
import random
from types import MappingProxyType
from nonebot.adapters import Bot, Event
from nonebot.utils import is_coroutine_callable
from nonebot_plugin_alconna import UniMessage, UniMsg
from nonebot_plugin_uninfo import Uninfo
from tortoise.expressions import F
from zhenxun.configs.config import BotConfig
from zhenxun.configs.path_config import IMAGE_PATH
from zhenxun.utils.platform import PlatformUtils
from ..exception import GiftRepeatSendException
from ..models.bym_gift_log import GiftLog
from ..models.bym_gift_store import GiftStore
from ..models.bym_user import BymUser
from .gift_register import gift_register
ICON_PATH = IMAGE_PATH / "gift_icon"
ICON_PATH.mkdir(parents=True, exist_ok=True)
gift_list = []
async def send_gift(user_id: str, session: Uninfo) -> str:
global gift_list
if (
await GiftLog.filter(
user_id=session.user.id, create_time__gte=datetime.now().date(), type=0
).count()
> 2
):
raise GiftRepeatSendException
if not gift_list:
gift_list = await GiftStore.all()
gift = random.choice(gift_list)
user = await BymUser.get_user(user_id, PlatformUtils.get_platform(session))
if gift.uuid not in user.props:
user.props[gift.uuid] = 0
user.props[gift.uuid] += 1
await asyncio.gather(
*[
user.save(update_fields=["props"]),
GiftLog.create(user_id=user_id, uuid=gift.uuid, type=0),
GiftStore.filter(uuid=gift.uuid).update(count=F("count") + 1),
]
)
return f"{BotConfig.self_nickname}赠送了{gift.name}作为礼物。"
def __build_params(
bot: Bot,
event: Event,
session: Uninfo,
message: UniMsg,
gift: GiftStore,
num: int,
):
group_id = None
if session.group:
group_id = session.group.parent.id if session.group.parent else session.group.id
return {
"_bot": bot,
"event": event,
"user_id": session.user.id,
"group_id": group_id,
"num": num,
"name": gift.name,
"message": message,
}
def __parse_args(
args: MappingProxyType,
**kwargs,
) -> dict:
"""解析参数
参数:
args: MappingProxyType
返回:
list[Any]: 参数
"""
_kwargs = kwargs.copy()
for key in kwargs:
if key not in args:
del _kwargs[key]
return _kwargs
async def __run(
func: Callable,
**kwargs,
) -> str | UniMessage | None:
"""运行道具函数
参数:
goods: Goods
param: ShopParam
返回:
str | MessageFactory | None: 使用完成后返回信息
"""
args = inspect.signature(func).parameters # type: ignore
if args and next(iter(args.keys())) != "kwargs":
return (
await func(**__parse_args(args, **kwargs))
if is_coroutine_callable(func)
else func(**__parse_args(args, **kwargs))
)
if is_coroutine_callable(func):
return await func()
else:
return func()
async def use_gift(
bot: Bot,
event: Event,
session: Uninfo,
message: UniMsg,
name: str,
num: int,
) -> str | UniMessage:
"""使用道具
参数:
bot: Bot
event: Event
session: Session
message: 消息
name: 礼物名称
num: 使用数量
text: 其他信息
返回:
str | MessageFactory: 使用完成后返回信息
"""
user = await BymUser.get_user(user_id=session.user.id)
if name.isdigit():
try:
uuid = list(user.props.keys())[int(name)]
gift_info = await GiftStore.get_or_none(uuid=uuid)
except IndexError:
return "仓库中礼物不存在..."
else:
gift_info = await GiftStore.get_or_none(goods_name=name)
if not gift_info:
return f"{name} 不存在..."
func = gift_register.get_func(gift_info.name)
if not func:
return f"{gift_info.name} 未注册使用函数, 无法使用..."
if user.props[gift_info.uuid] < num:
return f"你的 {gift_info.name} 数量不足 {num} 个..."
kwargs = __build_params(bot, event, session, message, gift_info, num)
result = await __run(func, **kwargs)
if gift_info.uuid not in user.usage_count:
user.usage_count[gift_info.uuid] = 0
user.usage_count[gift_info.uuid] += num
user.props[gift_info.uuid] -= num
if user.props[gift_info.uuid] < 0:
del user.props[gift_info.uuid]
await user.save(update_fields=["props", "usage_count"])
await GiftLog.create(user_id=session.user.id, uuid=gift_info.uuid, type=1)
if not result:
result = f"使用道具 {gift_info.name} {num} 次成功!"
return result