mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2025-12-15 06:12:53 +08:00
235 lines
8.0 KiB
Python
235 lines
8.0 KiB
Python
import asyncio
|
|
import os
|
|
import random
|
|
from io import BytesIO
|
|
from typing import Dict
|
|
|
|
from nonebot.adapters import Bot
|
|
from nonebot.exception import ActionFailed
|
|
from nonebot_plugin_alconna import UniMessage
|
|
|
|
from zhenxun.configs.config import BotConfig, Config
|
|
from zhenxun.configs.path_config import IMAGE_PATH
|
|
from zhenxun.models.user_console import UserConsole
|
|
from zhenxun.utils.image_utils import BuildImage
|
|
from zhenxun.utils.message import MessageUtils
|
|
from zhenxun.utils.platform import PlatformUtils
|
|
|
|
from .config import FestiveRedBagManage, GroupRedBag, RedBag
|
|
|
|
|
|
class RedBagManager:
|
|
|
|
_data: Dict[str, GroupRedBag] = {}
|
|
|
|
@classmethod
|
|
def get_group_data(cls, group_id: str) -> GroupRedBag:
|
|
"""获取群组红包数据
|
|
|
|
参数:
|
|
group_id: 群组id
|
|
|
|
返回:
|
|
GroupRedBag | None: GroupRedBag
|
|
"""
|
|
if group_id not in cls._data:
|
|
cls._data[group_id] = GroupRedBag(group_id)
|
|
return cls._data[group_id]
|
|
|
|
@classmethod
|
|
async def _auto_end_festive_red_bag(cls, bot: Bot, group_id: str, platform: str):
|
|
"""自动结算节日红包
|
|
|
|
参数:
|
|
bot: Bot
|
|
group_id: 群组id
|
|
platform: 平台
|
|
"""
|
|
if target := PlatformUtils.get_target(bot, group_id=group_id):
|
|
rank_num = Config.get_config("gold_redbag", "RANK_NUM") or 10
|
|
group_red_bag = cls.get_group_data(group_id)
|
|
red_bag = group_red_bag.get_festive_red_bag()
|
|
if not red_bag:
|
|
return
|
|
rank_image = await red_bag.build_amount_rank(rank_num, platform)
|
|
if red_bag.is_festival and red_bag.uuid:
|
|
FestiveRedBagManage.remove(red_bag.uuid)
|
|
await asyncio.sleep(random.randint(1, 5))
|
|
try:
|
|
await MessageUtils.build_message(
|
|
[
|
|
f"{BotConfig.self_nickname}的节日红包过时了,一共开启了 "
|
|
f"{len(red_bag.open_user)}"
|
|
f" 个红包,共 {sum(red_bag.open_user.values())} 金币\n",
|
|
rank_image,
|
|
]
|
|
).send(target=target, bot=bot)
|
|
except ActionFailed:
|
|
pass
|
|
|
|
@classmethod
|
|
async def end_red_bag(
|
|
cls,
|
|
group_id: str,
|
|
user_id: str | None = None,
|
|
is_festive: bool = False,
|
|
platform: str = "",
|
|
) -> UniMessage | None:
|
|
"""结算红包
|
|
|
|
参数:
|
|
group_id: 群组id或频道id
|
|
user_id: 用户id
|
|
is_festive: 是否节日红包
|
|
platform: 用户平台
|
|
"""
|
|
rank_num = Config.get_config("gold_redbag", "RANK_NUM") or 10
|
|
group_red_bag = cls.get_group_data(group_id)
|
|
if not group_red_bag:
|
|
return None
|
|
if is_festive:
|
|
if festive_red_bag := group_red_bag.festive_red_bag_expire():
|
|
rank_image = await festive_red_bag.build_amount_rank(rank_num, platform)
|
|
return MessageUtils.build_message(
|
|
[
|
|
f"{BotConfig.self_nickname}的节日红包过时了,一共开启了 "
|
|
f"{len(festive_red_bag.open_user)}"
|
|
f" 个红包,共 {sum(festive_red_bag.open_user.values())} 金币\n",
|
|
rank_image,
|
|
]
|
|
)
|
|
else:
|
|
if not user_id:
|
|
return None
|
|
return_gold, red_bag = await group_red_bag.settlement(user_id, platform)
|
|
if red_bag:
|
|
rank_image = await red_bag.build_amount_rank(rank_num, platform)
|
|
return MessageUtils.build_message(
|
|
[
|
|
f"已成功退还了 " f"{return_gold} 金币\n",
|
|
rank_image.pic2bytes(),
|
|
]
|
|
)
|
|
|
|
@classmethod
|
|
async def check_gold(cls, user_id: str, amount: int, platform: str) -> str | None:
|
|
"""检查金币数量是否合法
|
|
|
|
参数:
|
|
user_id: 用户id
|
|
amount: 金币数量
|
|
platform: 所属平台
|
|
|
|
返回:
|
|
tuple[bool, str]: 是否合法以及提示语
|
|
"""
|
|
user = await UserConsole.get_user(user_id, platform)
|
|
if amount < 1:
|
|
return "小气鬼,要别人倒贴金币给你嘛!"
|
|
if user.gold < amount:
|
|
return "没有金币的话请不要发红包..."
|
|
return None
|
|
|
|
@classmethod
|
|
async def random_red_bag_background(
|
|
cls, user_id: str, msg: str = "恭喜发财 大吉大利", platform: str = ""
|
|
) -> BuildImage:
|
|
"""构造发送红包图片
|
|
|
|
参数:
|
|
user_id: 用户id
|
|
msg: 红包消息.
|
|
platform: 平台.
|
|
|
|
异常:
|
|
ValueError: 图片背景列表为空
|
|
|
|
返回:
|
|
BuildImage: 构造后的图片
|
|
"""
|
|
background_list = os.listdir(f"{IMAGE_PATH}/prts/redbag_2")
|
|
if not background_list:
|
|
raise ValueError("prts/redbag_1 背景图列表为空...")
|
|
random_redbag = random.choice(background_list)
|
|
redbag = BuildImage(
|
|
0,
|
|
0,
|
|
font_size=38,
|
|
background=IMAGE_PATH / "prts" / "redbag_2" / random_redbag,
|
|
)
|
|
ava_byte = await PlatformUtils.get_user_avatar(user_id, platform)
|
|
ava = None
|
|
if ava_byte:
|
|
ava = BuildImage(65, 65, background=BytesIO(ava_byte))
|
|
else:
|
|
ava = BuildImage(65, 65, color=(0, 0, 0))
|
|
await ava.circle()
|
|
await redbag.text(
|
|
(int((redbag.size[0] - redbag.getsize(msg)[0]) / 2), 210),
|
|
msg,
|
|
(240, 218, 164),
|
|
)
|
|
await redbag.paste(ava, (int((redbag.size[0] - ava.size[0]) / 2), 130))
|
|
return redbag
|
|
|
|
@classmethod
|
|
async def build_open_result_image(
|
|
cls, red_bag: RedBag, user_id: str, amount: int, platform: str
|
|
) -> BuildImage:
|
|
"""构造红包开启图片
|
|
|
|
参数:
|
|
red_bag: RedBag
|
|
user_id: 开启红包用户id
|
|
amount: 开启红包获取的金额
|
|
platform: 平台
|
|
|
|
异常:
|
|
ValueError: 图片背景列表为空
|
|
|
|
返回:
|
|
BuildImage: 构造后的图片
|
|
"""
|
|
background_list = os.listdir(f"{IMAGE_PATH}/prts/redbag_1")
|
|
if not background_list:
|
|
raise ValueError("prts/redbag_1 背景图列表为空...")
|
|
random_redbag = random.choice(background_list)
|
|
head = BuildImage(
|
|
1000,
|
|
980,
|
|
font_size=30,
|
|
background=IMAGE_PATH / "prts" / "redbag_1" / random_redbag,
|
|
)
|
|
size = BuildImage.get_text_size(red_bag.name, font_size=50)
|
|
ava_bk = BuildImage(100 + size[0], 66, (255, 255, 255, 0), font_size=50)
|
|
|
|
ava_byte = await PlatformUtils.get_user_avatar(user_id, platform)
|
|
ava = None
|
|
if ava_byte:
|
|
ava = BuildImage(66, 66, background=BytesIO(ava_byte))
|
|
else:
|
|
ava = BuildImage(66, 66, color=(0, 0, 0))
|
|
await ava_bk.paste(ava)
|
|
await ava_bk.text((100, 7), red_bag.name)
|
|
ava_bk_w, ava_bk_h = ava_bk.size
|
|
await head.paste(ava_bk, (int((1000 - ava_bk_w) / 2), 300))
|
|
size = BuildImage.get_text_size(str(amount), font_size=150)
|
|
amount_image = BuildImage(size[0], size[1], (255, 255, 255, 0), font_size=150)
|
|
await amount_image.text((0, 0), str(amount), fill=(209, 171, 108))
|
|
# 金币中文
|
|
await head.paste(amount_image, (int((1000 - size[0]) / 2) - 50, 460))
|
|
await head.text(
|
|
(int((1000 - size[0]) / 2 + size[0]) - 50, 500 + size[1] - 70),
|
|
"金币",
|
|
fill=(209, 171, 108),
|
|
)
|
|
# 剩余数量和金额
|
|
text = (
|
|
f"已领取"
|
|
f"{red_bag.num - len(red_bag.open_user)}"
|
|
f"/{red_bag.num}个,"
|
|
f"共{sum(red_bag.open_user.values())}/{red_bag.amount}金币"
|
|
)
|
|
await head.text((350, 900), text, (198, 198, 198))
|
|
return head
|