mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2025-12-14 21:52:56 +08:00
refactor🎨: 重构红包功能
This commit is contained in:
parent
0a4df8296e
commit
81ddbc30f4
@ -331,9 +331,14 @@ PS: **ARM平台** 请使用全量版 同时 **如果你的机器 RAM < 1G 可能
|
||||
|
||||
## 更新
|
||||
|
||||
### 2022/8/20
|
||||
### 2023/8/28
|
||||
|
||||
* 重构`红包`功能,允许一个群聊中有多个用户发起的红包,发送`开`等命令会开启群中所有条件允许的红包,新增`红包结算排行`,在红包退回或抢完时统计,在`塞红包`时at可以发送专属红包
|
||||
|
||||
### 2023/8/20
|
||||
|
||||
* 修复词条回答包含at时使用模糊|正则等问时无法正确匹配问题
|
||||
* 修复开箱时最后开箱日期数据未更新
|
||||
|
||||
### 2023/8/7
|
||||
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import random
|
||||
import re
|
||||
import time
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
from apscheduler.jobstores.base import JobLookupError
|
||||
from nonebot import on_command, on_notice
|
||||
@ -21,15 +23,16 @@ from nonebot.rule import to_me
|
||||
from configs.config import NICKNAME
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from services.log import logger
|
||||
from utils.message_builder import image
|
||||
from utils.depends import AtList, GetConfig
|
||||
from utils.message_builder import at, image
|
||||
from utils.utils import is_number, scheduler
|
||||
|
||||
from .config import FESTIVE_KEY, GroupRedBag, RedBag
|
||||
from .data_source import (
|
||||
build_open_result_image,
|
||||
check_gold,
|
||||
generate_open_redbag_pic,
|
||||
generate_send_redbag_pic,
|
||||
open_redbag,
|
||||
return_gold,
|
||||
end_festive_red_bag,
|
||||
random_red_bag_background,
|
||||
)
|
||||
|
||||
__zx_plugin_name__ = "金币红包"
|
||||
@ -37,7 +40,7 @@ __plugin_usage__ = """
|
||||
usage:
|
||||
在群内发送指定金额的红包,拼手气项目
|
||||
指令:
|
||||
塞红包 [金币数] ?[红包数=5]: 塞入红包
|
||||
塞红包 [金币数] ?[红包数=5] ?[at指定人]: 塞入红包
|
||||
开/抢/*戳一戳*: 打开红包
|
||||
退回: 退回未开完的红包,必须在一分钟后使用
|
||||
示例:塞红包 1000
|
||||
@ -51,7 +54,7 @@ usage:
|
||||
""".strip()
|
||||
__plugin_des__ = "运气项目又来了"
|
||||
__plugin_cmd__ = [
|
||||
"塞红包 [金币数] ?[红包数=5]",
|
||||
"塞红包 [金币数] ?[红包数=5] ?[at指定人]",
|
||||
"开/抢",
|
||||
"退回",
|
||||
"节日红包 [金额] [数量] ?[祝福语] ?[指定群] [_superuser]",
|
||||
@ -64,14 +67,35 @@ __plugin_settings__ = {
|
||||
"limit_superuser": False,
|
||||
"cmd": ["金币红包", "塞红包"],
|
||||
}
|
||||
__plugin_resources__ = {"prts": IMAGE_PATH}
|
||||
__plugin_cd_limit__ = {"rst": "急什么急什么,待会再发!"}
|
||||
__plugin_configs__ = {
|
||||
"DEFAULT_TIMEOUT": {
|
||||
"value": 600,
|
||||
"help": "普通红包默认超时时间",
|
||||
"default_value": 600,
|
||||
"type": int,
|
||||
},
|
||||
"DEFAULT_INTERVAL": {
|
||||
"value": 60,
|
||||
"help": "用户发送普通红包最小间隔时间",
|
||||
"default_value": 60,
|
||||
"type": int,
|
||||
},
|
||||
"RANK_NUM": {
|
||||
"value": 10,
|
||||
"help": "结算排行显示前N位",
|
||||
"default_value": 10,
|
||||
"type": int,
|
||||
},
|
||||
}
|
||||
# __plugin_resources__ = {"prts": IMAGE_PATH}
|
||||
|
||||
|
||||
async def rule(event: GroupMessageEvent) -> bool:
|
||||
return check_on_gold_red(event)
|
||||
|
||||
|
||||
gold_redbag = on_command(
|
||||
gold_red_bag = on_command(
|
||||
"塞红包", aliases={"金币红包"}, priority=5, block=True, permission=GROUP
|
||||
)
|
||||
|
||||
@ -87,167 +111,197 @@ festive_redbag = on_command(
|
||||
"节日红包", priority=5, block=True, permission=SUPERUSER, rule=to_me()
|
||||
)
|
||||
|
||||
redbag_data = {}
|
||||
GROUP_DATA: Dict[int, GroupRedBag] = {}
|
||||
|
||||
festive_redbag_data = {}
|
||||
PATTERN = r"""!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~,。;‘、"""
|
||||
|
||||
|
||||
# 阻断其他poke
|
||||
@run_preprocessor
|
||||
# @run_preprocessor
|
||||
# async def _(
|
||||
# matcher: Matcher,
|
||||
# event: PokeNotifyEvent,
|
||||
# ):
|
||||
# try:
|
||||
# if matcher.type == "notice" and event.self_id == event.target_id:
|
||||
# flag = check_on_gold_red(event)
|
||||
# if flag:
|
||||
# if matcher.plugin_name == "poke":
|
||||
# raise IgnoredException("目前正在抢红包...")
|
||||
# else:
|
||||
# if matcher.plugin_name == "gold_red_bag":
|
||||
# raise IgnoredException("目前没有红包...")
|
||||
# except AttributeError:
|
||||
# pass
|
||||
|
||||
|
||||
@gold_red_bag.handle()
|
||||
async def _(
|
||||
matcher: Matcher,
|
||||
event: PokeNotifyEvent,
|
||||
bot: Bot,
|
||||
event: GroupMessageEvent,
|
||||
arg: Message = CommandArg(),
|
||||
at_list: List[int] = AtList(),
|
||||
default_interval: int = GetConfig(config="DEFAULT_INTERVAL"),
|
||||
):
|
||||
try:
|
||||
if matcher.type == "notice" and event.self_id == event.target_id:
|
||||
flag = check_on_gold_red(event)
|
||||
if flag:
|
||||
if matcher.plugin_name == "poke":
|
||||
raise IgnoredException("目前正在抢红包...")
|
||||
else:
|
||||
if matcher.plugin_name == "gold_redbag":
|
||||
raise IgnoredException("目前没有红包...")
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
|
||||
@gold_redbag.handle()
|
||||
async def _(bot: Bot, event: GroupMessageEvent, arg: Message = CommandArg()):
|
||||
global redbag_data, festive_redbag_data
|
||||
try:
|
||||
if time.time() - redbag_data[event.group_id]["time"] > 60:
|
||||
amount = (
|
||||
redbag_data[event.group_id]["amount"]
|
||||
- redbag_data[event.group_id]["open_amount"]
|
||||
)
|
||||
await return_gold(
|
||||
redbag_data[event.group_id]["user_id"], str(event.group_id), amount
|
||||
)
|
||||
await gold_redbag.send(
|
||||
f'{redbag_data[event.group_id]["nickname"]}的红包过时未开完,退还{amount}金币...'
|
||||
)
|
||||
redbag_data[event.group_id] = {}
|
||||
else:
|
||||
await gold_redbag.finish(
|
||||
f'目前 {redbag_data[event.group_id]["nickname"]} 的红包还没有开完噢,'
|
||||
f'还剩下 {len(redbag_data[event.group_id]["redbag"])} 个红包!'
|
||||
f'(或等待{str(60 - time.time() + redbag_data[event.group_id]["time"])[:2]}秒红包过时)'
|
||||
)
|
||||
except KeyError:
|
||||
pass
|
||||
msg = arg.extract_plain_text().strip()
|
||||
msg = msg.split()
|
||||
group_red_bag: Optional[GroupRedBag] = GROUP_DATA.get(event.group_id)
|
||||
if not group_red_bag:
|
||||
group_red_bag = GroupRedBag(event.group_id)
|
||||
GROUP_DATA[event.group_id] = group_red_bag
|
||||
# 剩余过期时间
|
||||
time_remaining = group_red_bag.check_timeout(event.user_id)
|
||||
if time_remaining != -1:
|
||||
# 判断用户红包是否存在且是否过时覆盖
|
||||
if user_red_bag := group_red_bag.get_user_red_bag(event.user_id):
|
||||
now = time.time()
|
||||
if now < user_red_bag.start_time + default_interval:
|
||||
await gold_red_bag.finish(
|
||||
f"你的红包还没消化完捏...还剩下 {user_red_bag.num - len(user_red_bag.open_user)} 个! 请等待红包领取完毕..."
|
||||
f"(或等待{time_remaining}秒红包cd)"
|
||||
)
|
||||
msg = arg.extract_plain_text().strip().split()
|
||||
if not msg:
|
||||
await gold_red_bag.finish("不塞钱发什么红包!")
|
||||
amount = msg[0]
|
||||
if len(msg) == 1:
|
||||
flag, amount = await check_gold(str(event.user_id), str(event.group_id), msg[0])
|
||||
flag, tip = await check_gold(str(event.user_id), str(event.group_id), amount)
|
||||
if not flag:
|
||||
await gold_redbag.finish(str(amount))
|
||||
await gold_red_bag.finish(tip, at_sender=True)
|
||||
num = 5
|
||||
else:
|
||||
amount = msg[0]
|
||||
num = msg[1]
|
||||
if not is_number(num) or int(num) < 1:
|
||||
await gold_redbag.finish("红包个数给我输正确啊!", at_sender=True)
|
||||
flag, amount = await check_gold(str(event.user_id), str(event.group_id), amount)
|
||||
await gold_red_bag.finish("红包个数给我输正确啊!", at_sender=True)
|
||||
flag, tip = await check_gold(str(event.user_id), str(event.group_id), amount)
|
||||
if not flag:
|
||||
await gold_redbag.finish(str(amount), at_sender=True)
|
||||
await gold_red_bag.finish(tip, at_sender=True)
|
||||
group_member_num = (await bot.get_group_info(group_id=event.group_id))[
|
||||
"member_count"
|
||||
]
|
||||
num = int(num)
|
||||
if num > group_member_num:
|
||||
await gold_redbag.send("你发的红包数量也太多了,已经为你修改成与本群人数相同的红包数量...")
|
||||
await gold_red_bag.send("你发的红包数量也太多了,已经为你修改成与本群人数相同的红包数量...")
|
||||
num = group_member_num
|
||||
nickname = event.sender.card or event.sender.nickname
|
||||
flag, result = init_redbag(
|
||||
await group_red_bag.add_red_bag(
|
||||
f"{nickname}的红包",
|
||||
int(amount),
|
||||
1 if at_list else num,
|
||||
nickname or "",
|
||||
str(event.user_id),
|
||||
str(event.group_id),
|
||||
nickname or str(event.user_id),
|
||||
amount,
|
||||
num,
|
||||
int(bot.self_id),
|
||||
assigner=str(at_list[0]) if at_list else None,
|
||||
)
|
||||
await gold_red_bag.send(
|
||||
f"{nickname}发起了金币红包\n金额: {amount}\n数量: {num}\n"
|
||||
+ image(await random_red_bag_background(event.user_id))
|
||||
)
|
||||
if not flag:
|
||||
await gold_redbag.finish(result, at_sender=True)
|
||||
else:
|
||||
await gold_redbag.send(
|
||||
f"{nickname}发起了金币红包\n金额:{amount}\n数量:{num}\n"
|
||||
+ image(
|
||||
b64=await generate_send_redbag_pic(
|
||||
redbag_data[str(event.group_id)]["user_id"]
|
||||
)
|
||||
)
|
||||
)
|
||||
logger.info(f"塞入 {num} 个红包,共 {amount} 金币", "金币红包", event.user_id, event.group_id)
|
||||
|
||||
|
||||
@open_.handle()
|
||||
async def _(event: GroupMessageEvent, arg: Message = CommandArg()):
|
||||
global redbag_data, festive_redbag_data
|
||||
msg = arg.extract_plain_text().strip()
|
||||
msg = (
|
||||
msg.replace("!", "")
|
||||
.replace("!", "")
|
||||
.replace(",", "")
|
||||
.replace(",", "")
|
||||
.replace(".", "")
|
||||
.replace("。", "")
|
||||
)
|
||||
if msg:
|
||||
async def _(
|
||||
event: GroupMessageEvent,
|
||||
arg: Message = CommandArg(),
|
||||
rank_num: int = GetConfig(config="RANK_NUM"),
|
||||
):
|
||||
if msg := arg.extract_plain_text().strip():
|
||||
msg = re.sub(PATTERN, "", msg)
|
||||
if "红包" not in msg:
|
||||
return
|
||||
try:
|
||||
await open_.send(
|
||||
image(b64=await get_redbag_img(str(event.user_id), str(event.group_id))),
|
||||
at_sender=True,
|
||||
)
|
||||
except KeyError:
|
||||
await open_.finish("真贪心,明明已经开过这个红包了的说...", at_sender=True)
|
||||
group_red_bag: Optional[GroupRedBag] = GROUP_DATA.get(event.group_id)
|
||||
if group_red_bag:
|
||||
open_data, settlement_list = await group_red_bag.open(event.user_id)
|
||||
send_msg = ""
|
||||
for _, item in open_data.items():
|
||||
amount, red_bag = item
|
||||
result_image = await build_open_result_image(red_bag, event.user_id, amount)
|
||||
send_msg += (
|
||||
f"开启了 {red_bag.promoter} 的红包, 获取 {amount} 个金币\n"
|
||||
+ image(result_image)
|
||||
+ "\n"
|
||||
)
|
||||
logger.info(
|
||||
f"抢到了 {red_bag.promoter}({red_bag.promoter_id}) 的红包,获取了{amount}个金币",
|
||||
"开红包",
|
||||
event.user_id,
|
||||
event.group_id,
|
||||
)
|
||||
send_msg = send_msg[:-1] if send_msg else "没有红包给你开!"
|
||||
await open_.send(send_msg, at_sender=True)
|
||||
if settlement_list:
|
||||
for red_bag in settlement_list:
|
||||
await open_.send(
|
||||
f"{red_bag.name}已结算\n"
|
||||
+ image(await red_bag.build_amount_rank(rank_num))
|
||||
)
|
||||
|
||||
|
||||
@poke_.handle()
|
||||
async def _poke_(event: PokeNotifyEvent):
|
||||
global redbag_data, festive_redbag_data
|
||||
if event.self_id == event.target_id:
|
||||
flag = check_on_gold_red(event)
|
||||
if not flag:
|
||||
return
|
||||
await poke_.send(
|
||||
image(b64=await get_redbag_img(str(event.user_id), str(event.group_id))),
|
||||
at_sender=True,
|
||||
)
|
||||
# @poke_.handle()
|
||||
# async def _poke_(event: PokeNotifyEvent):
|
||||
# group_id = getattr(event, "group_id", None)
|
||||
# if event.self_id == event.target_id and group_id:
|
||||
# is_open = check_on_gold_red(event)
|
||||
# if not is_open:
|
||||
# return
|
||||
# group_red_bag: Optional[GroupRedBag] = GROUP_DATA.get(group_id)
|
||||
# if group_red_bag:
|
||||
# open_data, settlement_list = await group_red_bag.open(event.user_id)
|
||||
# send_msg = ""
|
||||
# for _, item in open_data.items():
|
||||
# amount, red_bag = item
|
||||
# result_image = await build_open_result_image(
|
||||
# red_bag, event.user_id, amount
|
||||
# )
|
||||
# send_msg += (
|
||||
# f"开启了 {red_bag.promoter} 的红包, 获取 {amount} 个金币\n"
|
||||
# + image(result_image)
|
||||
# + "\n"
|
||||
# )
|
||||
# logger.info(
|
||||
# f"抢到了 {red_bag.promoter}({red_bag.promoter_id}) 的红包,获取了{amount}个金币",
|
||||
# "开红包",
|
||||
# event.user_id,
|
||||
# event.group_id,
|
||||
# )
|
||||
# if send_msg:
|
||||
# await open_.send(send_msg, at_sender=True)
|
||||
# if settlement_list:
|
||||
# for red_bag in settlement_list:
|
||||
# await open_.send(
|
||||
# f"{red_bag.name}已结算\n"
|
||||
# + image(await red_bag.build_amount_rank())
|
||||
# )
|
||||
|
||||
|
||||
@return_.handle()
|
||||
async def _(event: GroupMessageEvent):
|
||||
global redbag_data
|
||||
try:
|
||||
if redbag_data[event.group_id]["user_id"] != event.user_id:
|
||||
await return_.finish("不是你的红包你退回什么!", at_sender=True)
|
||||
if time.time() - redbag_data[event.group_id]["time"] <= 60:
|
||||
await return_.finish(
|
||||
f'你的红包还没有过时,在 {str(60 - time.time() + redbag_data[event.group_id]["time"])[:2]} '
|
||||
f"秒后可以退回..",
|
||||
at_sender=True,
|
||||
)
|
||||
await return_gold(
|
||||
str(event.user_id),
|
||||
str(event.group_id),
|
||||
redbag_data[event.group_id]["amount"]
|
||||
- redbag_data[event.group_id]["open_amount"],
|
||||
)
|
||||
await return_.send(
|
||||
f"已成功退还了 "
|
||||
f"{redbag_data[event.group_id]['amount'] - redbag_data[event.group_id]['open_amount']} "
|
||||
f"金币",
|
||||
at_sender=True,
|
||||
)
|
||||
logger.info(
|
||||
f"USER {event.user_id} GROUP {event.group_id} 退回了"
|
||||
f"红包 {redbag_data[event.group_id]['amount'] - redbag_data[event.group_id]['open_amount']} 金币"
|
||||
)
|
||||
redbag_data[event.group_id] = {}
|
||||
except KeyError:
|
||||
await return_.finish("目前没有红包可以退回...", at_sender=True)
|
||||
async def _(
|
||||
event: GroupMessageEvent,
|
||||
default_interval: int = GetConfig(config="DEFAULT_INTERVAL"),
|
||||
rank_num: int = GetConfig(config="RANK_NUM"),
|
||||
):
|
||||
group_red_bag: GroupRedBag = GROUP_DATA[event.group_id]
|
||||
if group_red_bag:
|
||||
if user_red_bag := group_red_bag.get_user_red_bag(event.user_id):
|
||||
now = time.time()
|
||||
if now - user_red_bag.start_time < default_interval:
|
||||
await return_.finish(
|
||||
f"你的红包还没有过时, 在 {int(default_interval - now + user_red_bag.start_time)} "
|
||||
f"秒后可以退回...",
|
||||
at_sender=True,
|
||||
)
|
||||
user_red_bag = group_red_bag.get_user_red_bag(event.user_id)
|
||||
if user_red_bag and (
|
||||
return_amount := await group_red_bag.settlement(event.user_id)
|
||||
):
|
||||
logger.info(
|
||||
f"退回了红包 {return_amount} 金币", "红包退回", event.user_id, event.group_id
|
||||
)
|
||||
await return_.send(
|
||||
f"已成功退还了 "
|
||||
f"{return_amount} 金币\n"
|
||||
+ image(await user_red_bag.build_amount_rank(rank_num)),
|
||||
at_sender=True,
|
||||
)
|
||||
await return_.send("目前没有红包可以退回...", at_sender=True)
|
||||
|
||||
|
||||
@festive_redbag.handle()
|
||||
@ -280,138 +334,40 @@ async def _(bot: Bot, arg: Message = CommandArg()):
|
||||
gl = await bot.get_group_list()
|
||||
gl = [g["group_id"] for g in gl]
|
||||
for g in gl:
|
||||
group_red_bag: Optional[GroupRedBag] = GROUP_DATA.get(g)
|
||||
if not group_red_bag:
|
||||
group_red_bag = GroupRedBag(g)
|
||||
GROUP_DATA[g] = group_red_bag
|
||||
try:
|
||||
scheduler.remove_job(f"festive_redbag_{g}")
|
||||
await end_festive_redbag(bot, g)
|
||||
scheduler.remove_job(f"{FESTIVE_KEY}_{g}")
|
||||
await end_festive_red_bag(bot, group_red_bag)
|
||||
except JobLookupError:
|
||||
pass
|
||||
init_redbag(bot.self_id, g, f"{NICKNAME}", amount, num, int(bot.self_id), 1)
|
||||
await group_red_bag.add_red_bag(
|
||||
f"{NICKNAME}的红包", int(amount), num, NICKNAME, FESTIVE_KEY, True
|
||||
)
|
||||
scheduler.add_job(
|
||||
end_festive_redbag,
|
||||
end_festive_red_bag,
|
||||
"date",
|
||||
run_date=(datetime.now() + timedelta(hours=24)).replace(microsecond=0),
|
||||
id=f"festive_redbag_{g}",
|
||||
args=[bot, g],
|
||||
# run_date=(datetime.now() + timedelta(hours=24)).replace(microsecond=0),
|
||||
run_date=(datetime.now() + timedelta(seconds=30)).replace(
|
||||
microsecond=0
|
||||
),
|
||||
id=f"{FESTIVE_KEY}_{g}",
|
||||
args=[bot, group_red_bag],
|
||||
)
|
||||
try:
|
||||
await bot.send_group_msg(
|
||||
group_id=g,
|
||||
message=f"{NICKNAME}发起了金币红包\n金额:{amount}\n数量:{num}\n"
|
||||
+ image(
|
||||
b64=await generate_send_redbag_pic(int(bot.self_id), greetings)
|
||||
),
|
||||
+ image(await random_red_bag_background(bot.self_id, greetings)),
|
||||
)
|
||||
logger.debug("节日红包图片信息发送成功...", "节日红包", group_id=g)
|
||||
except ActionFailed:
|
||||
logger.warning(f"节日红包 GROUP {g} 发送失败..")
|
||||
pass
|
||||
|
||||
|
||||
# 红包数据初始化
|
||||
def init_redbag(
|
||||
user_id: str,
|
||||
group_id: str,
|
||||
nickname: str,
|
||||
amount: int,
|
||||
num: int,
|
||||
bot_self_id: int,
|
||||
mode: int = 0,
|
||||
):
|
||||
global redbag_data, festive_redbag_data
|
||||
data = redbag_data if mode == 0 else festive_redbag_data
|
||||
if not data.get(group_id):
|
||||
data[group_id] = {}
|
||||
try:
|
||||
if data[group_id]["user_id"] and user_id != bot_self_id:
|
||||
return False, f'{data[group_id]["nickname"]}的红包还没抢完呢...'
|
||||
except KeyError:
|
||||
pass
|
||||
data[group_id]["user_id"] = user_id
|
||||
data[group_id]["nickname"] = nickname
|
||||
data[group_id]["amount"] = amount
|
||||
data[group_id]["num"] = num
|
||||
data[group_id]["open_amount"] = 0
|
||||
data[group_id]["time"] = time.time()
|
||||
data[group_id]["redbag"] = random_redbag(amount, num)
|
||||
data[group_id]["open_user"] = []
|
||||
if mode == 0:
|
||||
redbag_data = data
|
||||
else:
|
||||
festive_redbag_data = data
|
||||
return True, ""
|
||||
|
||||
|
||||
# 随机红包排列
|
||||
def random_redbag(amount: int, num: int) -> list:
|
||||
redbag_lst = []
|
||||
for _ in range(num - 1):
|
||||
tmp = int(amount / random.choice(range(3, num + 3)))
|
||||
redbag_lst.append(tmp)
|
||||
amount -= tmp
|
||||
redbag_lst.append(amount)
|
||||
return redbag_lst
|
||||
|
||||
|
||||
# 返回开红包图片
|
||||
async def get_redbag_img(user_id: str, group_id: str):
|
||||
global redbag_data, festive_redbag_data
|
||||
data = redbag_data
|
||||
mode = 0
|
||||
if festive_redbag_data.get(group_id):
|
||||
try:
|
||||
if user_id not in festive_redbag_data[group_id]["open_user"]:
|
||||
data = festive_redbag_data
|
||||
mode = 1
|
||||
except KeyError:
|
||||
pass
|
||||
amount, data = await open_redbag(user_id, group_id, data)
|
||||
text = (
|
||||
f"已领取"
|
||||
f'{data[group_id]["num"] - len(data[group_id]["redbag"])}'
|
||||
f'/{data[group_id]["num"]}个,'
|
||||
f'共{data[group_id]["open_amount"]}/{data[group_id]["amount"]}金币'
|
||||
)
|
||||
logger.info(
|
||||
f"USER {user_id} GROUP {group_id} 抢到了 {data[group_id]['user_id']} 的红包,获取了{amount}金币"
|
||||
)
|
||||
b64 = await generate_open_redbag_pic(
|
||||
data[group_id]["user_id"], data[group_id]["nickname"], amount, text
|
||||
)
|
||||
if data[group_id]["open_amount"] == data[group_id]["amount"]:
|
||||
data[group_id] = {}
|
||||
if mode == 0:
|
||||
redbag_data = data
|
||||
else:
|
||||
festive_redbag_data = data
|
||||
return b64
|
||||
|
||||
|
||||
async def end_festive_redbag(bot: Bot, group_id: int):
|
||||
global festive_redbag_data
|
||||
message = (
|
||||
f"{NICKNAME}的节日红包过时了,一共开启了 "
|
||||
f"{festive_redbag_data[group_id]['num'] - len(festive_redbag_data[group_id]['redbag'])}"
|
||||
f" 个红包,共 {festive_redbag_data[group_id]['open_amount']} 金币"
|
||||
)
|
||||
await bot.send_group_msg(group_id=group_id, message=message)
|
||||
festive_redbag_data[group_id] = {}
|
||||
logger.warning(f"节日红包图片信息发送失败...", "节日红包", group_id=g)
|
||||
|
||||
|
||||
def check_on_gold_red(event) -> bool:
|
||||
flag1 = True
|
||||
flag2 = True
|
||||
try:
|
||||
if festive_redbag_data[str(event.group_id)]["user_id"]:
|
||||
if event.user_id in festive_redbag_data[str(event.group_id)]["open_user"]:
|
||||
flag1 = False
|
||||
except KeyError:
|
||||
flag1 = False
|
||||
try:
|
||||
if redbag_data[str(event.group_id)]["user_id"]:
|
||||
if event.user_id in redbag_data[str(event.group_id)]["open_user"]:
|
||||
flag2 = False
|
||||
except KeyError:
|
||||
flag2 = False
|
||||
if flag1 or flag2:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
if group_red_bag := GROUP_DATA.get(event.group_id):
|
||||
return group_red_bag.check_open(event.user_id)
|
||||
return False
|
||||
|
||||
311
plugins/gold_redbag/config.py
Normal file
311
plugins/gold_redbag/config.py
Normal file
@ -0,0 +1,311 @@
|
||||
import random
|
||||
import time
|
||||
from datetime import datetime
|
||||
from io import BytesIO
|
||||
from typing import Dict, List, Optional, Tuple, Union, overload
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
from models.bag_user import BagUser
|
||||
from models.group_member_info import GroupInfoUser
|
||||
from plugins.gold_redbag.model import RedbagUser
|
||||
from utils.image_utils import BuildImage
|
||||
from utils.utils import get_user_avatar
|
||||
|
||||
FESTIVE_KEY = "FESTIVE"
|
||||
"""节日红包KEY"""
|
||||
|
||||
|
||||
class RedBag(BaseModel):
|
||||
|
||||
"""
|
||||
红包
|
||||
"""
|
||||
|
||||
group_id: str
|
||||
"""所属群聊"""
|
||||
name: str
|
||||
"""红包名称"""
|
||||
amount: int
|
||||
"""总金币"""
|
||||
num: int
|
||||
"""红包数量"""
|
||||
promoter: str
|
||||
"""发起人昵称"""
|
||||
promoter_id: str
|
||||
"""发起人id"""
|
||||
is_festival: bool
|
||||
"""是否为节日红包"""
|
||||
timeout: int
|
||||
"""过期时间"""
|
||||
assigner: Optional[str] = None
|
||||
"""指定人id"""
|
||||
start_time: float
|
||||
"""红包发起时间"""
|
||||
open_user: Dict[str, int] = {}
|
||||
"""开启用户"""
|
||||
red_bag_list: List[int]
|
||||
|
||||
async def build_amount_rank(self, num: int = 10) -> BuildImage:
|
||||
"""生成结算红包图片
|
||||
|
||||
参数:
|
||||
num: 查看的排名数量.
|
||||
|
||||
返回:
|
||||
BuildImage: 结算红包图片
|
||||
"""
|
||||
user_image_list = []
|
||||
if self.open_user:
|
||||
sort_data = sorted(
|
||||
self.open_user.items(), key=lambda item: item[1], reverse=True
|
||||
)
|
||||
num = num if num < len(self.open_user) else len(self.open_user)
|
||||
user_id_list = [sort_data[i][0] for i in range(num)]
|
||||
group_user_list = await GroupInfoUser.filter(
|
||||
group_id=self.group_id, user_id__in=user_id_list
|
||||
).all()
|
||||
for i in range(num):
|
||||
user_background = BuildImage(600, 100, font_size=30)
|
||||
user_id, amount = sort_data[i]
|
||||
user_ava_bytes = await get_user_avatar(user_id)
|
||||
user_ava = None
|
||||
if user_ava_bytes:
|
||||
user_ava = BuildImage(80, 80, background=BytesIO(user_ava_bytes))
|
||||
else:
|
||||
user_ava = BuildImage(80, 80)
|
||||
await user_ava.acircle_corner(10)
|
||||
await user_background.apaste(user_ava, (130, 10), True)
|
||||
no_image = BuildImage(100, 100, font_size=65, font="CJGaoDeGuo.otf")
|
||||
await no_image.atext((0, 0), f"{i+1}", center_type="center")
|
||||
await no_image.aline((99, 10, 99, 90), "#b9b9b9")
|
||||
await user_background.apaste(no_image)
|
||||
name = [
|
||||
user.user_name
|
||||
for user in group_user_list
|
||||
if user_id == user.user_id
|
||||
]
|
||||
await user_background.atext((225, 15), name[0] if name else "")
|
||||
amount_image = BuildImage(
|
||||
0, 0, plain_text=f"{amount} 元", font_size=30, font_color="#cdac72"
|
||||
)
|
||||
await user_background.apaste(
|
||||
amount_image, (user_background.w - amount_image.w - 20, 50), True
|
||||
)
|
||||
await user_background.aline((225, 99, 590, 99), "#b9b9b9")
|
||||
user_image_list.append(user_background)
|
||||
background = BuildImage(600, 150 + len(user_image_list) * 100)
|
||||
top = BuildImage(600, 100, color="#f55545", font_size=30)
|
||||
promoter_ava_bytes = await get_user_avatar(self.promoter_id)
|
||||
promoter_ava = None
|
||||
if promoter_ava_bytes:
|
||||
promoter_ava = BuildImage(60, 60, background=BytesIO(promoter_ava_bytes))
|
||||
else:
|
||||
promoter_ava = BuildImage(60, 60)
|
||||
await promoter_ava.acircle()
|
||||
await top.apaste(promoter_ava, (10, 0), True, "by_height")
|
||||
await top.atext((80, 33), self.name, (255, 255, 255))
|
||||
right_text = BuildImage(150, 100, color="#f55545", font_size=30)
|
||||
await right_text.atext((10, 33), "结算排行", (255, 255, 255))
|
||||
await right_text.aline((4, 10, 4, 90), (255, 255, 255), 2)
|
||||
await top.apaste(right_text, (460, 0))
|
||||
await background.apaste(top)
|
||||
cur_h = 110
|
||||
for user_image in user_image_list:
|
||||
await background.apaste(user_image, (0, cur_h))
|
||||
cur_h += user_image.h
|
||||
return background
|
||||
|
||||
|
||||
class GroupRedBag:
|
||||
|
||||
"""
|
||||
群组红包管理
|
||||
"""
|
||||
|
||||
def __init__(self, group_id: Union[int, str]):
|
||||
self.group_id = str(group_id)
|
||||
self._data: Dict[str, RedBag] = {}
|
||||
"""红包列表"""
|
||||
|
||||
def get_user_red_bag(self, user_id: Union[str, int]) -> Optional[RedBag]:
|
||||
"""获取用户塞红包数据
|
||||
|
||||
参数:
|
||||
user_id: 用户id
|
||||
|
||||
返回:
|
||||
Optional[RedBag]: RedBag
|
||||
"""
|
||||
return self._data.get(str(user_id))
|
||||
|
||||
def check_open(self, user_id: Union[str, int]) -> bool:
|
||||
"""检查是否有可开启的红包
|
||||
|
||||
参数:
|
||||
user_id: 用户id
|
||||
|
||||
返回:
|
||||
bool: 是否有可开启的红包
|
||||
"""
|
||||
user_id = str(user_id)
|
||||
for _, red_bag in self._data.items():
|
||||
if red_bag.assigner:
|
||||
if red_bag.assigner == user_id:
|
||||
return True
|
||||
else:
|
||||
if user_id not in red_bag.open_user:
|
||||
return True
|
||||
return False
|
||||
|
||||
def check_timeout(self, user_id: Union[int, str]) -> int:
|
||||
"""判断用户红包是否过期
|
||||
|
||||
参数:
|
||||
user_id: 用户id
|
||||
|
||||
返回:
|
||||
int: 距离过期时间
|
||||
"""
|
||||
user_id = str(user_id)
|
||||
if user_id in self._data:
|
||||
reg_bag = self._data[user_id]
|
||||
now = time.time()
|
||||
if now < reg_bag.timeout + reg_bag.start_time:
|
||||
return int(reg_bag.timeout + reg_bag.start_time - now)
|
||||
return -1
|
||||
|
||||
async def open(
|
||||
self, user_id: Union[int, str]
|
||||
) -> Tuple[Dict[str, Tuple[int, RedBag]], List[RedBag]]:
|
||||
"""开启红包
|
||||
|
||||
参数:
|
||||
user_id: 用户id
|
||||
|
||||
返回:
|
||||
Dict[str, Tuple[int, RedBag]]: 键为发起者id, 值为开启金额以及对应RedBag
|
||||
List[RedBag]: 开完的红包
|
||||
"""
|
||||
user_id = str(user_id)
|
||||
open_data = {}
|
||||
settlement_list: List[RedBag] = []
|
||||
for _, red_bag in self._data.items():
|
||||
if red_bag.num > len(red_bag.open_user):
|
||||
is_open = False
|
||||
if red_bag.assigner:
|
||||
is_open = red_bag.assigner == user_id
|
||||
else:
|
||||
is_open = user_id not in red_bag.open_user
|
||||
if is_open:
|
||||
random_amount = red_bag.red_bag_list.pop()
|
||||
await RedbagUser.add_redbag_data(
|
||||
user_id, self.group_id, "get", random_amount
|
||||
)
|
||||
await BagUser.add_gold(user_id, self.group_id, random_amount)
|
||||
red_bag.open_user[user_id] = random_amount
|
||||
open_data[red_bag.promoter_id] = (random_amount, red_bag)
|
||||
if red_bag.num == len(red_bag.open_user):
|
||||
# 红包开完,结算
|
||||
settlement_list.append(red_bag)
|
||||
if settlement_list:
|
||||
for uid in [red_bag.promoter_id for red_bag in settlement_list]:
|
||||
if uid in self._data:
|
||||
del self._data[uid]
|
||||
return open_data, settlement_list
|
||||
|
||||
def festive_red_bag_expire(self) -> Optional[RedBag]:
|
||||
"""节日红包过期
|
||||
|
||||
返回:
|
||||
Optional[RedBag]: 过期的节日红包
|
||||
"""
|
||||
if FESTIVE_KEY in self._data:
|
||||
red_bag = self._data[FESTIVE_KEY]
|
||||
del self._data[FESTIVE_KEY]
|
||||
return red_bag
|
||||
return None
|
||||
|
||||
async def settlement(
|
||||
self, user_id: Optional[Union[int, str]] = None
|
||||
) -> Optional[int]:
|
||||
"""红包退回
|
||||
|
||||
参数:
|
||||
user_id: 用户id, 指定id时结算指定用户红包.
|
||||
|
||||
返回:
|
||||
int: 退回金币
|
||||
"""
|
||||
user_id = str(user_id)
|
||||
if user_id:
|
||||
if red_bag := self._data.get(user_id):
|
||||
del self._data[user_id]
|
||||
if red_bag.red_bag_list:
|
||||
# 退还剩余金币
|
||||
if amount := sum(red_bag.red_bag_list):
|
||||
await BagUser.add_gold(user_id, self.group_id, amount)
|
||||
return amount
|
||||
return None
|
||||
|
||||
async def add_red_bag(
|
||||
self,
|
||||
name: str,
|
||||
amount: int,
|
||||
num: int,
|
||||
promoter: str,
|
||||
promoter_id: str,
|
||||
is_festival: bool = False,
|
||||
timeout: int = 60,
|
||||
assigner: Optional[str] = None,
|
||||
):
|
||||
"""添加红包
|
||||
|
||||
参数:
|
||||
name: 红包名称
|
||||
amount: 金币数量
|
||||
num: 红包数量
|
||||
promoter: 发起人昵称
|
||||
promoter_id: 发起人id
|
||||
is_festival: 是否为节日红包.
|
||||
timeout: 超时时间.
|
||||
assigner: 指定人.
|
||||
"""
|
||||
user_gold = await BagUser.get_gold(promoter_id, self.group_id)
|
||||
if not is_festival and (amount < 1 or user_gold < amount):
|
||||
raise ValueError("红包金币不足或用户金币不足")
|
||||
red_bag_list = self._random_red_bag(amount, num)
|
||||
if not is_festival:
|
||||
await BagUser.spend_gold(promoter_id, self.group_id, amount)
|
||||
await RedbagUser.add_redbag_data(promoter_id, self.group_id, "send", amount)
|
||||
self._data[promoter_id] = RedBag(
|
||||
group_id=self.group_id,
|
||||
name=name,
|
||||
amount=amount,
|
||||
num=num,
|
||||
promoter=promoter,
|
||||
promoter_id=promoter_id,
|
||||
is_festival=is_festival,
|
||||
timeout=timeout,
|
||||
start_time=time.time(),
|
||||
assigner=assigner,
|
||||
red_bag_list=red_bag_list,
|
||||
)
|
||||
|
||||
def _random_red_bag(self, amount: int, num: int) -> List[int]:
|
||||
"""初始化红包金币
|
||||
|
||||
参数:
|
||||
amount: 金币数量
|
||||
num: 红包数量
|
||||
|
||||
返回:
|
||||
List[int]: 红包列表
|
||||
"""
|
||||
red_bag_list = []
|
||||
for _ in range(num - 1):
|
||||
tmp = int(amount / random.choice(range(3, num + 3)))
|
||||
red_bag_list.append(tmp)
|
||||
amount -= tmp
|
||||
red_bag_list.append(amount)
|
||||
return red_bag_list
|
||||
@ -1,19 +1,51 @@
|
||||
import asyncio
|
||||
import os
|
||||
import random
|
||||
from io import BytesIO
|
||||
from typing import Union
|
||||
from typing import Tuple, Union
|
||||
|
||||
from nonebot.adapters.onebot.v11 import Bot
|
||||
|
||||
from configs.config import NICKNAME, Config
|
||||
from configs.path_config import IMAGE_PATH
|
||||
from models.bag_user import BagUser
|
||||
from utils.image_utils import BuildImage
|
||||
from utils.message_builder import image
|
||||
from utils.utils import get_user_avatar, is_number
|
||||
|
||||
from .model import RedbagUser
|
||||
from .config import FESTIVE_KEY, GroupRedBag, RedBag
|
||||
|
||||
|
||||
# 检查金币数量合法性,并添加记录数据
|
||||
async def check_gold(user_id: str, group_id: str, amount: Union[str, int]):
|
||||
async def end_festive_red_bag(bot: Bot, group_red_bag: GroupRedBag):
|
||||
"""结算节日红包
|
||||
|
||||
参数:
|
||||
bot: Bot
|
||||
group_red_bag: GroupRedBag
|
||||
"""
|
||||
if festive_red_bag := group_red_bag.festive_red_bag_expire():
|
||||
rank_num = Config.get_config("gold_redbag", "RANK_NUM") or 10
|
||||
rank_image = await festive_red_bag.build_amount_rank(rank_num)
|
||||
message = (
|
||||
f"{NICKNAME}的节日红包过时了,一共开启了 "
|
||||
f"{len(festive_red_bag.open_user)}"
|
||||
f" 个红包,共 {sum(festive_red_bag.open_user.values())} 金币\n" + image(rank_image)
|
||||
)
|
||||
await bot.send_group_msg(group_id=int(group_red_bag.group_id), message=message)
|
||||
|
||||
|
||||
async def check_gold(
|
||||
user_id: str, group_id: str, amount: Union[str, int]
|
||||
) -> Tuple[bool, str]:
|
||||
"""检查金币数量是否合法
|
||||
|
||||
参数:
|
||||
user_id: 用户id
|
||||
group_id: 群聊id
|
||||
amount: 金币数量
|
||||
|
||||
返回:
|
||||
Tuple[bool, str]: 是否合法以及提示语
|
||||
"""
|
||||
if is_number(amount):
|
||||
amount = int(amount)
|
||||
user_gold = await BagUser.get_gold(user_id, group_id)
|
||||
@ -21,88 +53,102 @@ async def check_gold(user_id: str, group_id: str, amount: Union[str, int]):
|
||||
return False, "小气鬼,要别人倒贴金币给你嘛!"
|
||||
if user_gold < amount:
|
||||
return False, "没有金币的话请不要发红包..."
|
||||
await BagUser.spend_gold(user_id, group_id, amount)
|
||||
await RedbagUser.add_redbag_data(user_id, group_id, "send", amount)
|
||||
return True, amount
|
||||
return True, ""
|
||||
else:
|
||||
return False, "给我好好的输入红包里金币的数量啊喂!"
|
||||
|
||||
|
||||
# 金币退回
|
||||
async def return_gold(user_id: str, group_id: str, amount: int):
|
||||
await BagUser.add_gold(user_id, group_id, amount)
|
||||
async def random_red_bag_background(
|
||||
user_id: Union[str, int], msg="恭喜发财 大吉大利"
|
||||
) -> BuildImage:
|
||||
"""构造发送红包图片
|
||||
|
||||
参数:
|
||||
user_id: 用户id
|
||||
msg: 红包消息.
|
||||
|
||||
# 开红包
|
||||
async def open_redbag(user_id: str, group_id: str, redbag_data: dict):
|
||||
amount = random.choice(redbag_data[group_id]["redbag"])
|
||||
redbag_data[group_id]["redbag"].remove(amount)
|
||||
redbag_data[group_id]["open_user"].append(user_id)
|
||||
redbag_data[group_id]["open_amount"] += amount
|
||||
await RedbagUser.add_redbag_data(user_id, group_id, "get", amount)
|
||||
await BagUser.add_gold(user_id, group_id, amount)
|
||||
return amount, redbag_data
|
||||
异常:
|
||||
ValueError: 图片背景列表为空
|
||||
|
||||
|
||||
# 随机红包图片
|
||||
async def generate_send_redbag_pic(user_id: int, msg: str = "恭喜发财 大吉大利"):
|
||||
random_redbag = random.choice(os.listdir(f"{IMAGE_PATH}/prts/redbag_2"))
|
||||
返回:
|
||||
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=f"{IMAGE_PATH}/prts/redbag_2/{random_redbag}"
|
||||
0, 0, font_size=38, background=IMAGE_PATH / "prts" / "redbag_2" / random_redbag
|
||||
)
|
||||
ava = BuildImage(65, 65, background=BytesIO(await get_user_avatar(user_id)))
|
||||
await asyncio.get_event_loop().run_in_executor(None, ava.circle)
|
||||
redbag.text(
|
||||
ava_byte = await get_user_avatar(user_id)
|
||||
ava = None
|
||||
if ava_byte:
|
||||
ava = BuildImage(65, 65, background=BytesIO(ava_byte))
|
||||
else:
|
||||
ava = BuildImage(65, 65, color=(0, 0, 0), is_alpha=True)
|
||||
await ava.acircle()
|
||||
await redbag.atext(
|
||||
(int((redbag.size[0] - redbag.getsize(msg)[0]) / 2), 210), msg, (240, 218, 164)
|
||||
)
|
||||
redbag.paste(ava, (int((redbag.size[0] - ava.size[0]) / 2), 130), True)
|
||||
return redbag.pic2bs4()
|
||||
await redbag.apaste(ava, (int((redbag.size[0] - ava.size[0]) / 2), 130), True)
|
||||
return redbag
|
||||
|
||||
|
||||
# 开红包图片
|
||||
async def generate_open_redbag_pic(
|
||||
user_id: str, send_user_nickname: str, amount: int, text: str
|
||||
):
|
||||
return await asyncio.create_task(
|
||||
_generate_open_redbag_pic(user_id, send_user_nickname, amount, text)
|
||||
)
|
||||
async def build_open_result_image(
|
||||
red_bag: RedBag, user_id: Union[int, str], amount: int
|
||||
) -> BuildImage:
|
||||
"""构造红包开启图片
|
||||
|
||||
参数:
|
||||
red_bag: RedBag
|
||||
user_id: 开启红包用户id
|
||||
amount: 开启红包获取的金额
|
||||
|
||||
# 开红包图片
|
||||
async def _generate_open_redbag_pic(
|
||||
user_id: str, send_user_nickname: str, amount: int, text: str
|
||||
):
|
||||
send_user_nickname += "的红包"
|
||||
amount_str = str(amount)
|
||||
random_redbag = random.choice(os.listdir(f"{IMAGE_PATH}/prts/redbag_1"))
|
||||
异常:
|
||||
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=f"{IMAGE_PATH}/prts/redbag_1/{random_redbag}",
|
||||
background=IMAGE_PATH / "prts" / "redbag_1" / random_redbag,
|
||||
)
|
||||
size = BuildImage(0, 0, font_size=50).getsize(send_user_nickname)
|
||||
# QQ头像
|
||||
size = BuildImage(0, 0, font_size=50).getsize(red_bag.name)
|
||||
ava_bk = BuildImage(100 + size[0], 66, is_alpha=True, font_size=50)
|
||||
ava = BuildImage(
|
||||
66, 66, is_alpha=True, background=BytesIO(await get_user_avatar(user_id))
|
||||
)
|
||||
ava_bk.paste(ava)
|
||||
ava_bk.text((100, 7), send_user_nickname)
|
||||
# ava_bk.show()
|
||||
|
||||
ava_byte = await get_user_avatar(user_id)
|
||||
ava = None
|
||||
if ava_byte:
|
||||
ava = BuildImage(66, 66, is_alpha=True, background=BytesIO(ava_byte))
|
||||
else:
|
||||
ava = BuildImage(66, 66, color=(0, 0, 0), is_alpha=True)
|
||||
await ava_bk.apaste(ava)
|
||||
ava_bk.text((100, 7), red_bag.name)
|
||||
ava_bk_w, ava_bk_h = ava_bk.size
|
||||
head.paste(ava_bk, (int((1000 - ava_bk_w) / 2), 300), alpha=True)
|
||||
# 金额
|
||||
size = BuildImage(0, 0, font_size=150).getsize(amount_str)
|
||||
price = BuildImage(size[0], size[1], is_alpha=True, font_size=150)
|
||||
price.text((0, 0), amount_str, fill=(209, 171, 108))
|
||||
await head.apaste(ava_bk, (int((1000 - ava_bk_w) / 2), 300), alpha=True)
|
||||
size = BuildImage(0, 0, font_size=150).getsize(amount)
|
||||
amount_image = BuildImage(size[0], size[1], is_alpha=True, font_size=150)
|
||||
await amount_image.atext((0, 0), str(amount), fill=(209, 171, 108))
|
||||
# 金币中文
|
||||
head.paste(price, (int((1000 - size[0]) / 2) - 50, 460), alpha=True)
|
||||
head.text(
|
||||
await head.apaste(amount_image, (int((1000 - size[0]) / 2) - 50, 460), alpha=True)
|
||||
await head.atext(
|
||||
(int((1000 - size[0]) / 2 + size[0]) - 50, 500 + size[1] - 70),
|
||||
"金币",
|
||||
fill=(209, 171, 108),
|
||||
)
|
||||
# 剩余数量和金额
|
||||
head.text((350, 900), text, (198, 198, 198))
|
||||
return head.pic2bs4()
|
||||
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.atext((350, 900), text, (198, 198, 198))
|
||||
return head
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
from datetime import datetime
|
||||
|
||||
from tortoise import fields
|
||||
|
||||
from services.db_context import Model
|
||||
@ -39,7 +41,7 @@ class OpenCasesUser(Model):
|
||||
"""赚取金币"""
|
||||
today_open_total: int = fields.IntField(default=0)
|
||||
"""今日开箱数量"""
|
||||
open_cases_time_last = fields.DatetimeField()
|
||||
open_cases_time_last: datetime = fields.DatetimeField()
|
||||
"""最后开箱日期"""
|
||||
knifes_name: str = fields.TextField(default="")
|
||||
"""已获取金色"""
|
||||
|
||||
@ -122,7 +122,10 @@ async def open_case(user_id: str, group_id: int, case_name: str) -> Union[str, M
|
||||
case_price = case_skin.sell_min_price
|
||||
user.today_open_total += 1
|
||||
user.total_count += 1
|
||||
await user.save(update_fields=["today_open_total", "total_count"])
|
||||
user.open_cases_time_last = datetime.now()
|
||||
await user.save(
|
||||
update_fields=["today_open_total", "total_count", "open_cases_time_last"]
|
||||
)
|
||||
add_count(user, skin, case_price)
|
||||
ridicule_result = random.choice(RESULT_MESSAGE[skin.color])
|
||||
price_result = skin.sell_min_price
|
||||
@ -203,7 +206,10 @@ async def open_multiple_case(
|
||||
now = datetime.now()
|
||||
user.today_open_total += num
|
||||
user.total_count += num
|
||||
await user.save(update_fields=["today_open_total", "total_count"])
|
||||
user.open_cases_time_last = datetime.now()
|
||||
await user.save(
|
||||
update_fields=["today_open_total", "total_count", "open_cases_time_last"]
|
||||
)
|
||||
case_price = 0
|
||||
if case_skin := await BuffSkin.get_or_none(case_name=case_name, color="CASE"):
|
||||
case_price = case_skin.sell_min_price
|
||||
@ -275,8 +281,12 @@ def _handle_is_MAX_COUNT() -> str:
|
||||
return f"今天已达开箱上限了喔,明天再来吧\n(提升好感度可以增加每日开箱数 #疯狂暗示)"
|
||||
|
||||
|
||||
async def total_open_statistics(user_id: str, group: str) -> str:
|
||||
user, _ = await OpenCasesUser.get_or_create(user_id=user_id, group_id=group)
|
||||
async def total_open_statistics(
|
||||
user_id: Union[str, int], group_id: Union[str, int]
|
||||
) -> str:
|
||||
user, _ = await OpenCasesUser.get_or_create(
|
||||
user_id=str(user_id), group_id=str(group_id)
|
||||
)
|
||||
return (
|
||||
f"开箱总数:{user.total_count}\n"
|
||||
f"今日开箱:{user.today_open_total}\n"
|
||||
@ -296,8 +306,8 @@ async def total_open_statistics(user_id: str, group: str) -> str:
|
||||
)
|
||||
|
||||
|
||||
async def group_statistics(group: str):
|
||||
user_list = await OpenCasesUser.filter(group_id=group).all()
|
||||
async def group_statistics(group_id: Union[int, str]):
|
||||
user_list = await OpenCasesUser.filter(group_id=str(group_id)).all()
|
||||
# lan zi fen hong jin pricei
|
||||
uplist = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.0, 0, 0]
|
||||
for user in user_list:
|
||||
@ -332,7 +342,9 @@ async def group_statistics(group: str):
|
||||
)
|
||||
|
||||
|
||||
async def get_my_knifes(user_id: str, group_id: str) -> Union[str, MessageSegment]:
|
||||
async def get_my_knifes(
|
||||
user_id: Union[str, int], group_id: Union[str, int]
|
||||
) -> Union[str, MessageSegment]:
|
||||
"""获取我的金色
|
||||
|
||||
Args:
|
||||
@ -342,7 +354,7 @@ async def get_my_knifes(user_id: str, group_id: str) -> Union[str, MessageSegmen
|
||||
Returns:
|
||||
Union[str, MessageSegment]: 回复消息或图片
|
||||
"""
|
||||
data_list = await get_old_knife(user_id, group_id)
|
||||
data_list = await get_old_knife(str(user_id), str(group_id))
|
||||
data_list += await OpenCasesLog.filter(
|
||||
user_id=user_id, group_id=group_id, color="KNIFE"
|
||||
).all()
|
||||
|
||||
@ -48,7 +48,11 @@ async def init():
|
||||
if not i_bind:
|
||||
i_bind = f"{sql_name}://{user}:{password}@{address}:{port}/{database}"
|
||||
try:
|
||||
await Tortoise.init(db_url=i_bind, modules={"models": MODELS})
|
||||
await Tortoise.init(
|
||||
db_url=i_bind,
|
||||
modules={"models": MODELS},
|
||||
# timezone="Asia/Shanghai"
|
||||
)
|
||||
await Tortoise.generate_schemas()
|
||||
logger.info(f"Database loaded successfully!")
|
||||
except Exception as e:
|
||||
|
||||
@ -411,7 +411,7 @@ def is_chinese(word: str) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
async def get_user_avatar(qq: int) -> Optional[bytes]:
|
||||
async def get_user_avatar(qq: Union[int, str]) -> Optional[bytes]:
|
||||
"""
|
||||
说明:
|
||||
快捷获取用户头像
|
||||
@ -423,8 +423,8 @@ async def get_user_avatar(qq: int) -> Optional[bytes]:
|
||||
for _ in range(3):
|
||||
try:
|
||||
return (await client.get(url)).content
|
||||
except TimeoutError:
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.error("获取用户头像错误", "Util", target=qq)
|
||||
return None
|
||||
|
||||
|
||||
@ -440,8 +440,8 @@ async def get_group_avatar(group_id: int) -> Optional[bytes]:
|
||||
for _ in range(3):
|
||||
try:
|
||||
return (await client.get(url)).content
|
||||
except TimeoutError:
|
||||
pass
|
||||
except Exception as e:
|
||||
logger.error("获取群头像错误", "Util", target=group_id)
|
||||
return None
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user