zhenxun_bot/plugins/gold_redbag/__init__.py
2023-08-28 13:30:17 +08:00

374 lines
14 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
from nonebot.adapters.onebot.v11 import (
ActionFailed,
Bot,
GroupMessageEvent,
Message,
PokeNotifyEvent,
)
from nonebot.adapters.onebot.v11.permission import GROUP
from nonebot.matcher import Matcher
from nonebot.message import IgnoredException, run_preprocessor
from nonebot.params import CommandArg
from nonebot.permission import SUPERUSER
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.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,
end_festive_red_bag,
random_red_bag_background,
)
__zx_plugin_name__ = "金币红包"
__plugin_usage__ = """
usage
在群内发送指定金额的红包,拼手气项目
指令:
塞红包 [金币数] ?[红包数=5] ?[at指定人]: 塞入红包
开/抢/*戳一戳*: 打开红包
退回: 退回未开完的红包,必须在一分钟后使用
示例:塞红包 1000
示例:塞红包 1000 10
""".strip()
__plugin_superuser_usage__ = """
usage
节日全群红包指令
指令:
节日红包 [金额] [数量] ?[祝福语] ?[指定群]
""".strip()
__plugin_des__ = "运气项目又来了"
__plugin_cmd__ = [
"塞红包 [金币数] ?[红包数=5] ?[at指定人]",
"开/抢",
"退回",
"节日红包 [金额] [数量] ?[祝福语] ?[指定群] [_superuser]",
]
__plugin_version__ = 0.1
__plugin_author__ = "HibiKier"
__plugin_settings__ = {
"level": 5,
"default_status": True,
"limit_superuser": False,
"cmd": ["金币红包", "塞红包"],
}
__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_red_bag = on_command(
"塞红包", aliases={"金币红包"}, priority=5, block=True, permission=GROUP
)
open_ = on_command(
"", aliases={""}, priority=5, block=True, permission=GROUP, rule=rule
)
poke_ = on_notice(priority=6, block=False)
return_ = on_command("退回", aliases={"退还"}, priority=5, block=True, permission=GROUP)
festive_redbag = on_command(
"节日红包", priority=5, block=True, permission=SUPERUSER, rule=to_me()
)
GROUP_DATA: Dict[int, GroupRedBag] = {}
PATTERN = r"""!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~,。;‘、"""
# 阻断其他poke
# @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 _(
bot: Bot,
event: GroupMessageEvent,
arg: Message = CommandArg(),
at_list: List[int] = AtList(),
default_interval: int = GetConfig(config="DEFAULT_INTERVAL"),
):
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, tip = await check_gold(str(event.user_id), str(event.group_id), amount)
if not flag:
await gold_red_bag.finish(tip, at_sender=True)
num = 5
else:
num = msg[1]
if not is_number(num) or int(num) < 1:
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_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_red_bag.send("你发的红包数量也太多了,已经为你修改成与本群人数相同的红包数量...")
num = group_member_num
nickname = event.sender.card or event.sender.nickname
await group_red_bag.add_red_bag(
f"{nickname}的红包",
int(amount),
1 if at_list else num,
nickname or "",
str(event.user_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))
)
logger.info(f"塞入 {num} 个红包,共 {amount} 金币", "金币红包", event.user_id, event.group_id)
@open_.handle()
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
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):
# 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,
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()
async def _(bot: Bot, arg: Message = CommandArg()):
global redbag_data
msg = arg.extract_plain_text().strip()
if msg:
msg = msg.split()
amount = 0
num = 0
greetings = "恭喜发财 大吉大利"
gl = []
if (lens := len(msg)) < 2:
await festive_redbag.finish("参数不足,格式:节日红包 [金额] [数量] [祝福语](可省) [指定群](可省)")
if lens > 1:
if not is_number(msg[0]):
await festive_redbag.finish("金额必须要是数字!", at_sender=True)
amount = int(msg[0])
if not is_number(msg[1]):
await festive_redbag.finish("数量必须要是数字!", at_sender=True)
num = int(msg[1])
if lens > 2:
greetings = msg[2]
if lens > 3:
for i in range(3, lens):
if not is_number(msg[i]):
await festive_redbag.finish("指定的群号必须要是数字啊!", at_sender=True)
gl.append(int(msg[i]))
if not gl:
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_KEY}_{g}")
await end_festive_red_bag(bot, group_red_bag)
except JobLookupError:
pass
await group_red_bag.add_red_bag(
f"{NICKNAME}的红包", int(amount), num, NICKNAME, FESTIVE_KEY, True
)
scheduler.add_job(
end_festive_red_bag,
"date",
# 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(await random_red_bag_background(bot.self_id, greetings)),
)
logger.debug("节日红包图片信息发送成功...", "节日红包", group_id=g)
except ActionFailed:
logger.warning(f"节日红包图片信息发送失败...", "节日红包", group_id=g)
def check_on_gold_red(event) -> bool:
if group_red_bag := GROUP_DATA.get(event.group_id):
return group_red_bag.check_open(event.user_id)
return False