zhenxun_bot/zhenxun/plugins/russian/data_source.py

536 lines
20 KiB
Python
Raw Normal View History

2024-06-10 21:10:04 +08:00
import random
import time
from datetime import datetime, timedelta
from apscheduler.jobstores.base import JobLookupError
from nonebot.adapters import Bot
2024-08-11 15:57:33 +08:00
from nonebot_plugin_alconna import At, UniMessage
2024-06-10 21:10:04 +08:00
from nonebot_plugin_apscheduler import scheduler
from pydantic import BaseModel
2024-08-24 17:06:23 +08:00
from zhenxun.configs.config import BotConfig, Config
2024-06-10 21:10:04 +08:00
from zhenxun.models.group_member_info import GroupInfoUser
from zhenxun.models.user_console import UserConsole
from zhenxun.utils.enum import GoldHandle
2024-08-05 01:10:50 +08:00
from zhenxun.utils.exception import InsufficientGold
2024-06-10 21:10:04 +08:00
from zhenxun.utils.image_utils import BuildImage, BuildMat, MatType, text2image
2024-08-11 15:57:33 +08:00
from zhenxun.utils.message import MessageUtils
2024-06-10 21:10:04 +08:00
from zhenxun.utils.platform import PlatformUtils
from .model import RussianUser
base_config = Config.get("russian")
class Russian(BaseModel):
at_user: str | None
"""指定决斗对象"""
player1: tuple[str, str]
"""玩家1id, 昵称"""
player2: tuple[str, str] | None = None
"""玩家2id, 昵称"""
money: int
"""金额"""
bullet_num: int
"""子弹数"""
bullet_arr: list[int] = []
"""子弹排列"""
bullet_index: int = 0
"""当前子弹下标"""
next_user: str = ""
"""下一个开枪用户"""
time: float = time.time()
"""创建时间"""
win_user: str | None = None
"""胜利者"""
class RussianManage:
def __init__(self) -> None:
self._data: dict[str, Russian] = {}
def __check_is_timeout(self, group_id: str) -> bool:
"""检查决斗是否超时
参数:
group_id: 群组id
返回:
bool: 是否超时
"""
if russian := self._data.get(group_id):
if russian.time + 30 < time.time():
return True
return False
def __random_bullet(self, num: int) -> list[int]:
"""随机排列子弹
参数:
num: 子弹数量
返回:
list[int]: 子弹排列数组
"""
bullet_list = [0, 0, 0, 0, 0, 0, 0]
for i in random.sample([0, 1, 2, 3, 4, 5, 6], num):
bullet_list[i] = 1
return bullet_list
def __remove_job(self, group_id: str):
"""移除定时任务
参数:
group_id: 群组id
"""
try:
scheduler.remove_job(f"russian_job_{group_id}")
except JobLookupError:
pass
2024-06-10 21:10:04 +08:00
def __build_job(
self, bot: Bot, group_id: str, is_add: bool = False, platform: str | None = None
):
"""移除定时任务和构建新定时任务
参数:
bot: Bot
group_id: 群组id
is_add: 是否添加新定时任务.
platform: 平台
"""
self.__remove_job(group_id)
2024-06-10 21:10:04 +08:00
if is_add:
date = datetime.now() + timedelta(seconds=31)
scheduler.add_job(
self.__auto_end_game,
"date",
run_date=date.replace(microsecond=0),
id=f"russian_job_{group_id}",
args=[bot, group_id, platform],
)
async def __auto_end_game(self, bot: Bot, group_id: str, platform: str):
"""自动结束对决
参数:
bot: Bot
group_id: 群组id
platform: 平台
"""
result = await self.settlement(group_id, None, platform)
if result:
await PlatformUtils.send_message(bot, None, group_id, result)
2024-08-11 15:57:33 +08:00
async def add_russian(self, bot: Bot, group_id: str, rus: Russian) -> UniMessage:
2024-06-10 21:10:04 +08:00
"""添加决斗
参数:
bot: Bot
group_id: 群组id
rus: Russian
返回:
2024-08-11 15:57:33 +08:00
UniMessage: 返回消息
2024-06-10 21:10:04 +08:00
"""
russian = self._data.get(group_id)
if russian:
if russian.time + 30 < time.time():
if not russian.player2:
2024-08-11 15:57:33 +08:00
return MessageUtils.build_message(
2024-06-10 21:10:04 +08:00
f"现在是 {russian.player1[1]} 发起的对决, 请接受对决或等待决斗超时..."
)
else:
2024-08-11 15:57:33 +08:00
return MessageUtils.build_message(
2024-06-10 21:10:04 +08:00
f"{russian.player1[1]}{russian.player2[1]}的对决还未结束!"
)
2024-08-11 15:57:33 +08:00
return MessageUtils.build_message(
2024-06-10 21:10:04 +08:00
f"现在是 {russian.player1[1]} 发起的对决\n请等待比赛结束后再开始下一轮..."
)
max_money = base_config.get("MAX_RUSSIAN_BET_GOLD")
if rus.money > max_money:
2024-08-11 15:57:33 +08:00
return MessageUtils.build_message(f"太多了!单次金额不能超过{max_money}")
2024-06-10 21:10:04 +08:00
user = await UserConsole.get_user(rus.player1[0])
if user.gold < rus.money:
2024-08-11 15:57:33 +08:00
return MessageUtils.build_message("你没有足够的钱支撑起这场挑战")
2024-06-10 21:10:04 +08:00
rus.bullet_arr = self.__random_bullet(rus.bullet_num)
self._data[group_id] = rus
2024-08-11 15:57:33 +08:00
message_list: list[str | At] = []
2024-06-10 21:10:04 +08:00
if rus.at_user:
user = await GroupInfoUser.get_or_none(
user_id=rus.at_user, group_id=group_id
)
message_list = [
2024-08-11 15:57:33 +08:00
f"{rus.player1[1]}",
At(flag="user", target=rus.at_user),
f"发起了决斗!请 {user.user_name if user else rus.at_user} 在30秒内回复接受对决 or ‘拒绝对决’,超时此次决斗作废!",
2024-06-10 21:10:04 +08:00
]
else:
message_list = [
2024-08-11 15:57:33 +08:00
"若30秒内无人接受挑战则此次对决作废【首次游玩请at我发送 ’帮助俄罗斯轮盘‘ 来查看命令】"
2024-06-10 21:10:04 +08:00
]
2024-08-11 15:57:33 +08:00
result = (
2024-06-10 21:10:04 +08:00
"" * rus.bullet_num
+ f"装填完毕\n挑战金额:{rus.money}\n第一枪的概率为:{float(rus.bullet_num) / 7.0 * 100:.2f}%\n"
)
2024-08-11 15:57:33 +08:00
2024-06-10 21:10:04 +08:00
message_list.insert(0, result)
self.__build_job(bot, group_id, True)
2024-08-11 15:57:33 +08:00
return MessageUtils.build_message(message_list) # type: ignore
2024-06-10 21:10:04 +08:00
2024-08-05 01:10:50 +08:00
async def accept(
2024-08-07 23:31:25 +08:00
self, bot: Bot, group_id: str, user_id: str, uname: str
2024-08-11 15:57:33 +08:00
) -> UniMessage:
2024-06-10 21:10:04 +08:00
"""接受对决
参数:
2024-08-07 23:31:25 +08:00
bot: Bot
2024-06-10 21:10:04 +08:00
group_id: 群组id
user_id: 用户id
uname: 用户名称
返回:
Text | MessageFactory: 返回消息
"""
if russian := self._data.get(group_id):
if russian.at_user and russian.at_user != user_id:
2024-08-11 15:57:33 +08:00
return MessageUtils.build_message("又不是找你决斗,你接受什么啊!气!")
2024-06-10 21:10:04 +08:00
if russian.player2:
2024-08-11 15:57:33 +08:00
return MessageUtils.build_message(
"当前决斗已被其他玩家接受!请等待下局对决!"
)
if russian.player1[0] == user_id:
2024-08-11 15:57:33 +08:00
return MessageUtils.build_message("你发起的对决,你接受什么啊!气!")
2024-08-05 01:10:50 +08:00
user = await UserConsole.get_user(user_id)
if user.gold < russian.money:
2024-08-11 15:57:33 +08:00
return MessageUtils.build_message("你没有足够的钱来接受这场挑战...")
2024-06-10 21:10:04 +08:00
russian.player2 = (user_id, uname)
russian.next_user = russian.player1[0]
2024-08-07 23:31:25 +08:00
self.__build_job(bot, group_id, True)
2024-08-11 15:57:33 +08:00
return MessageUtils.build_message(
2024-06-10 21:10:04 +08:00
[
2024-08-11 15:57:33 +08:00
"决斗已经开始!请",
At(flag="user", target=russian.player1[0]),
"先开枪!",
2024-06-10 21:10:04 +08:00
]
)
2024-08-11 15:57:33 +08:00
return MessageUtils.build_message(
"目前没有进行的决斗,请发送 装弹 开启决斗吧!"
)
2024-06-10 21:10:04 +08:00
2024-08-11 15:57:33 +08:00
def refuse(self, group_id: str, user_id: str, uname: str) -> UniMessage:
2024-06-10 21:10:04 +08:00
"""拒绝决斗
参数:
group_id: 群组id
user_id: 用户id
uname: 用户名称
返回:
Text | MessageFactory: 返回消息
"""
if russian := self._data.get(group_id):
if russian.at_user:
if russian.at_user != user_id:
2024-08-11 15:57:33 +08:00
return MessageUtils.build_message(
"又不是找你决斗,你拒绝什么啊!气!"
)
2024-06-10 21:10:04 +08:00
del self._data[group_id]
self.__remove_job(group_id)
2024-08-11 15:57:33 +08:00
return MessageUtils.build_message(
[
At(flag="user", target=russian.player1[0]),
f"{uname}拒绝了你的对决!",
]
2024-06-10 21:10:04 +08:00
)
2024-08-11 15:57:33 +08:00
return MessageUtils.build_message("当前决斗并没有指定对手,无法拒绝哦!")
return MessageUtils.build_message(
"目前没有进行的决斗,请发送 装弹 开启决斗吧!"
)
2024-06-10 21:10:04 +08:00
async def shoot(
self, bot: Bot, group_id: str, user_id: str, uname: str, platform: str
2024-08-11 15:57:33 +08:00
) -> tuple[UniMessage, UniMessage | None]:
2024-06-10 21:10:04 +08:00
"""开枪
参数:
bot: Bot
group_id: 群组id
user_id: 用户id
uname: 用户名称
platform: 平台
返回:
Text | MessageFactory: 返回消息
"""
if russian := self._data.get(group_id):
if not russian.player2:
2024-08-11 15:57:33 +08:00
return (
MessageUtils.build_message("当前还没有玩家接受对决,无法开枪..."),
None,
)
2024-06-10 21:10:04 +08:00
if user_id not in [russian.player1[0], russian.player2[0]]:
"""非玩家1和玩家2发送开枪"""
return (
2024-08-11 15:57:33 +08:00
MessageUtils.build_message(
2024-06-10 21:10:04 +08:00
random.choice(
[
f"不要打扰 {russian.player1[1]}{russian.player2[1]} 的决斗啊!",
2024-08-24 19:32:52 +08:00
f"给我好好做好一个观众!不然{BotConfig.self_nickname}就要生气了",
2024-06-10 21:10:04 +08:00
f"不要捣乱啊baka{uname}",
]
)
),
None,
)
if user_id != russian.next_user:
"""相同玩家连续开枪"""
return (
2024-08-11 15:57:33 +08:00
MessageUtils.build_message(
f"你的左轮不是连发的!该 {russian.player2[1]} 开枪了!"
),
2024-06-10 21:10:04 +08:00
None,
)
if russian.bullet_arr[russian.bullet_index] == 1:
"""去世"""
2024-08-11 15:57:33 +08:00
result = MessageUtils.build_message(
2024-06-10 21:10:04 +08:00
random.choice(
[
'"嘭!",你直接去世了',
"眼前一黑,你直接穿越到了异世界...(死亡)",
"终究还是你先走一步...",
]
)
)
settle = await self.settlement(group_id, user_id, platform)
return result, settle
else:
"""存活"""
2024-08-05 20:25:02 +08:00
p = (
(russian.bullet_index + russian.bullet_num + 1)
/ len(russian.bullet_arr)
* 100
)
2024-06-10 21:10:04 +08:00
result = (
random.choice(
[
"呼呼,没有爆裂的声响,你活了下来",
"虽然黑洞洞的枪口很恐怖,但好在没有子弹射出来,你活下来了",
'"",你没死,看来运气不错',
]
)
+ f"\n下一枪中弹的概率: {p:.2f}%, 轮到 "
)
next_user = (
russian.player2[0]
if russian.next_user == russian.player1[0]
else russian.player1[0]
)
russian.next_user = next_user
russian.bullet_index += 1
self.__build_job(bot, group_id, True)
return (
2024-08-11 15:57:33 +08:00
MessageUtils.build_message(
[result, At(flag="user", target=next_user), " 了!"]
),
2024-06-10 21:10:04 +08:00
None,
)
2024-08-11 15:57:33 +08:00
return (
MessageUtils.build_message("目前没有进行的决斗,请发送 装弹 开启决斗吧!"),
None,
)
2024-06-10 21:10:04 +08:00
async def settlement(
self, group_id: str, user_id: str | None, platform: str | None = None
2024-08-11 15:57:33 +08:00
) -> UniMessage:
2024-06-10 21:10:04 +08:00
"""结算
参数:
group_id: 群组id
user_id: 用户id
platform: 平台
返回:
Text | MessageFactory: 返回消息
"""
if russian := self._data.get(group_id):
if not russian.player2:
if self.__check_is_timeout(group_id):
del self._data[group_id]
2024-08-11 15:57:33 +08:00
return MessageUtils.build_message(
"规定时间内还未有人接受决斗,当前决斗过期..."
)
return MessageUtils.build_message("决斗还未开始,,无法结算哦...")
if user_id and user_id not in [russian.player1[0], russian.player2[0]]:
2024-08-11 15:57:33 +08:00
return MessageUtils.build_message(f"吃瓜群众不要捣乱!黄牌警告!")
2024-06-10 21:10:04 +08:00
if not self.__check_is_timeout(group_id):
2024-08-11 15:57:33 +08:00
return MessageUtils.build_message(
f"{russian.player1[1]}{russian.player2[1]} 比赛并未超时,请继续比赛..."
2024-06-10 21:10:04 +08:00
)
win_user = None
lose_user = None
if win_user:
russian.next_user = (
russian.player1[0]
if win_user == russian.player2[0]
else russian.player2[0]
)
if russian.next_user != russian.player1[0]:
win_user = russian.player1
lose_user = russian.player2
else:
win_user = russian.player2
lose_user = russian.player1
if win_user and lose_user:
rand = 0
if russian.money > 10:
rand = random.randint(0, 5)
fee = int(russian.money * float(rand) / 100)
fee = 1 if fee < 1 and rand != 0 else fee
else:
fee = 0
winner = await RussianUser.add_count(win_user[0], group_id, "win")
loser = await RussianUser.add_count(lose_user[0], group_id, "lose")
await RussianUser.money(
win_user[0], group_id, "win", russian.money - fee
)
await RussianUser.money(lose_user[0], group_id, "lose", russian.money)
await UserConsole.add_gold(
win_user[0], russian.money - fee, "russian", platform
)
2024-08-05 01:10:50 +08:00
try:
await UserConsole.reduce_gold(
lose_user[0],
russian.money,
GoldHandle.PLUGIN,
"russian",
platform,
)
except InsufficientGold:
if u := await UserConsole.get_user(lose_user[0]):
u.gold = 0
await u.save(update_fields=["gold"])
2024-08-11 15:57:33 +08:00
result = [
"这场决斗是 ",
At(flag="user", target=win_user[0]),
" 胜利了!",
]
2024-06-10 21:10:04 +08:00
image = await text2image(
f"结算:\n"
f"\t胜者:{win_user[1]}\n"
f"\t赢取金币:{russian.money - fee}\n"
f"\t累计胜场:{winner.win_count}\n"
f"\t累计赚取金币:{winner.make_money}\n"
f"-------------------\n"
f"\t败者:{lose_user[1]}\n"
f"\t输掉金币:{russian.money}\n"
f"\t累计败场:{loser.fail_count}\n"
f"\t累计输掉金币:{loser.lose_money}\n"
f"-------------------\n"
2024-08-24 19:32:52 +08:00
f"哼哼,{BotConfig.self_nickname}从中收取了 {float(rand)}%({fee}金币) 作为手续费!\n"
2024-06-10 21:10:04 +08:00
f"子弹排列:{russian.bullet_arr}",
padding=10,
color="#f9f6f2",
)
self.__remove_job(group_id)
2024-08-11 15:57:33 +08:00
result.append(image)
2024-06-10 21:10:04 +08:00
del self._data[group_id]
2024-08-11 15:57:33 +08:00
return MessageUtils.build_message(result)
return MessageUtils.build_message("赢家和输家获取错误...")
return MessageUtils.build_message("比赛并没有开始...无法结算...")
2024-06-10 21:10:04 +08:00
async def __get_x_index(self, users: list[RussianUser], group_id: str):
uid_list = [u.user_id for u in users]
group_user_list = await GroupInfoUser.filter(
user_id__in=uid_list, group_id=group_id
).all()
group_user = {gu.user_id: gu.user_name for gu in group_user_list}
data = []
for uid in uid_list:
if uid in group_user:
data.append(group_user[uid])
else:
data.append(uid)
return data
async def rank(
self, user_id: str, group_id: str, rank_type: str, num: int
) -> BuildImage | str:
x_index = []
data = []
title = ""
x_name = ""
if rank_type == "win":
users = (
await RussianUser.filter(group_id=group_id, win_count__not=0)
.order_by("win_count")
.limit(num)
)
x_index = await self.__get_x_index(users, group_id)
data = [u.win_count for u in users]
title = "胜场排行"
x_name = "场次"
if rank_type == "lose":
users = (
await RussianUser.filter(group_id=group_id, fail_count__not=0)
.order_by("fail_count")
.limit(num)
)
x_index = await self.__get_x_index(users, group_id)
data = [u.fail_count for u in users]
title = "败场排行"
x_name = "场次"
if rank_type == "a":
users = (
await RussianUser.filter(group_id=group_id, make_money__not=0)
.order_by("make_money")
.limit(num)
)
x_index = await self.__get_x_index(users, group_id)
data = [u.make_money for u in users]
title = "欧洲人排行"
x_name = "金币"
if rank_type == "b":
users = (
await RussianUser.filter(group_id=group_id, lose_money__not=0)
.order_by("lose_money")
.limit(num)
)
x_index = await self.__get_x_index(users, group_id)
data = [u.lose_money for u in users]
title = "慈善家排行"
x_name = "金币"
if rank_type == "max_win":
users = (
await RussianUser.filter(group_id=group_id, max_winning_streak__not=0)
.order_by("max_winning_streak")
.limit(num)
)
x_index = await self.__get_x_index(users, group_id)
data = [u.max_winning_streak for u in users]
title = "最高连胜排行"
x_name = "场次"
if rank_type == "max_lose":
users = (
await RussianUser.filter(group_id=group_id, max_losing_streak__not=0)
.order_by("max_losing_streak")
.limit(num)
)
x_index = await self.__get_x_index(users, group_id)
data = [u.max_losing_streak for u in users]
title = "最高连败排行"
x_name = "场次"
if not data:
return "当前数据为空..."
mat = BuildMat(MatType.BARH)
mat.x_index = x_index
mat.data = data # type: ignore
mat.title = title
mat.x_name = x_name
return await mat.build()
russian_manage = RussianManage()