mirror of
https://github.com/zhenxun-org/zhenxun_bot.git
synced 2025-12-15 14:22:55 +08:00
feat✨: 俄罗斯轮盘
This commit is contained in:
parent
899acc248d
commit
15aba0bea9
186
zhenxun/plugins/russian/__init__.py
Normal file
186
zhenxun/plugins/russian/__init__.py
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
from nonebot.adapters import Bot
|
||||||
|
from nonebot.plugin import PluginMetadata
|
||||||
|
from nonebot_plugin_alconna import Arparma
|
||||||
|
from nonebot_plugin_alconna import At as alcAt
|
||||||
|
from nonebot_plugin_alconna import Match
|
||||||
|
from nonebot_plugin_saa import Image, Text
|
||||||
|
from nonebot_plugin_session import EventSession
|
||||||
|
|
||||||
|
from zhenxun.configs.utils import PluginExtraData, RegisterConfig
|
||||||
|
from zhenxun.services.log import logger
|
||||||
|
from zhenxun.utils.depends import UserName
|
||||||
|
|
||||||
|
from .command import (
|
||||||
|
_accept_matcher,
|
||||||
|
_rank_matcher,
|
||||||
|
_record_matcher,
|
||||||
|
_refuse_matcher,
|
||||||
|
_russian_matcher,
|
||||||
|
_settlement_matcher,
|
||||||
|
_shoot_matcher,
|
||||||
|
)
|
||||||
|
from .data_source import Russian, russian_manage
|
||||||
|
from .model import RussianUser
|
||||||
|
|
||||||
|
__plugin_meta__ = PluginMetadata(
|
||||||
|
name="俄罗斯轮盘",
|
||||||
|
description="虽然是运气游戏,但这可是战场啊少年",
|
||||||
|
usage="""
|
||||||
|
又到了决斗时刻
|
||||||
|
指令:
|
||||||
|
装弹 [金额] [子弹数] ?[at]: 开启游戏,装填子弹,可选自定义金额,或邀请决斗对象
|
||||||
|
接受对决: 接受当前存在的对决
|
||||||
|
拒绝对决: 拒绝邀请的对决
|
||||||
|
开枪: 开出未知的一枪
|
||||||
|
结算: 强行结束当前比赛 (仅当一方未开枪超过30秒时可使用)
|
||||||
|
我的战绩: 对,你的战绩
|
||||||
|
轮盘胜场排行/轮盘败场排行/轮盘欧洲人排行/轮盘慈善家排行/轮盘最高连胜排行/轮盘最高连败排行: 各种排行榜
|
||||||
|
示例:装弹 3 100 @sdd
|
||||||
|
* 注:同一时间群内只能有一场对决 *
|
||||||
|
""".strip(),
|
||||||
|
extra=PluginExtraData(
|
||||||
|
author="HibiKier",
|
||||||
|
version="0.1",
|
||||||
|
menu_type="群内小游戏",
|
||||||
|
configs=[
|
||||||
|
RegisterConfig(
|
||||||
|
key="MAX_RUSSIAN_BET_GOLD",
|
||||||
|
value=1000,
|
||||||
|
help="俄罗斯轮盘最大赌注金额",
|
||||||
|
default_value=1000,
|
||||||
|
type=int,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
).dict(),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@_russian_matcher.handle()
|
||||||
|
async def _(money: int, num: Match[int], at_user: Match[alcAt]):
|
||||||
|
_russian_matcher.set_path_arg("money", money)
|
||||||
|
if num.available:
|
||||||
|
_russian_matcher.set_path_arg("num", num.result)
|
||||||
|
if at_user.available:
|
||||||
|
_russian_matcher.set_path_arg("at_user", at_user.result.target)
|
||||||
|
|
||||||
|
|
||||||
|
@_russian_matcher.got_path("num", prompt="请输入装填子弹的数量!(最多6颗)")
|
||||||
|
async def _(
|
||||||
|
bot: Bot,
|
||||||
|
session: EventSession,
|
||||||
|
arparma: Arparma,
|
||||||
|
money: int,
|
||||||
|
num: int,
|
||||||
|
at_user: Match[alcAt],
|
||||||
|
uname: str = UserName(),
|
||||||
|
):
|
||||||
|
gid = session.id2
|
||||||
|
if not session.id1:
|
||||||
|
await Text("用户id为空...").finish()
|
||||||
|
if not gid:
|
||||||
|
await Text("群组id为空...").finish()
|
||||||
|
_at_user = at_user.result.target if at_user.available else None
|
||||||
|
rus = Russian(
|
||||||
|
at_user=_at_user, player1=(session.id1, uname), money=money, bullet_num=num
|
||||||
|
)
|
||||||
|
result = await russian_manage.add_russian(bot, gid, rus)
|
||||||
|
await result.send()
|
||||||
|
logger.info(
|
||||||
|
f"添加俄罗斯轮盘 装弹: {num}, 金额: {money}",
|
||||||
|
arparma.header_result,
|
||||||
|
session=session,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@_accept_matcher.handle()
|
||||||
|
async def _(session: EventSession, arparma: Arparma, uname: str = UserName()):
|
||||||
|
global a
|
||||||
|
gid = session.id2
|
||||||
|
if not session.id1:
|
||||||
|
await Text("用户id为空...").finish()
|
||||||
|
if not gid:
|
||||||
|
await Text("群组id为空...").finish()
|
||||||
|
result = russian_manage.accept(gid, session.id1, uname)
|
||||||
|
await result.send()
|
||||||
|
logger.info(f"俄罗斯轮盘接受对决", arparma.header_result, session=session)
|
||||||
|
|
||||||
|
|
||||||
|
@_refuse_matcher.handle()
|
||||||
|
async def _(session: EventSession, arparma: Arparma, uname: str = UserName()):
|
||||||
|
gid = session.id2
|
||||||
|
if not session.id1:
|
||||||
|
await Text("用户id为空...").finish()
|
||||||
|
if not gid:
|
||||||
|
await Text("群组id为空...").finish()
|
||||||
|
result = russian_manage.refuse(gid, session.id1, uname)
|
||||||
|
await result.send()
|
||||||
|
logger.info(f"俄罗斯轮盘拒绝对决", arparma.header_result, session=session)
|
||||||
|
|
||||||
|
|
||||||
|
@_settlement_matcher.handle()
|
||||||
|
async def _(session: EventSession, arparma: Arparma):
|
||||||
|
gid = session.id2
|
||||||
|
if not session.id1:
|
||||||
|
await Text("用户id为空...").finish()
|
||||||
|
if not gid:
|
||||||
|
await Text("群组id为空...").finish()
|
||||||
|
result = await russian_manage.settlement(gid, session.id1, session.platform)
|
||||||
|
await result.send()
|
||||||
|
logger.info(f"俄罗斯轮盘结算", arparma.header_result, session=session)
|
||||||
|
|
||||||
|
|
||||||
|
@_shoot_matcher.handle()
|
||||||
|
async def _(bot: Bot, session: EventSession, arparma: Arparma, uname: str = UserName()):
|
||||||
|
gid = session.id2
|
||||||
|
if not session.id1:
|
||||||
|
await Text("用户id为空...").finish()
|
||||||
|
if not gid:
|
||||||
|
await Text("群组id为空...").finish()
|
||||||
|
result, settle = await russian_manage.shoot(
|
||||||
|
bot, gid, session.id1, uname, session.platform
|
||||||
|
)
|
||||||
|
await result.send()
|
||||||
|
if settle:
|
||||||
|
await settle.send()
|
||||||
|
logger.info(f"俄罗斯轮盘开枪", arparma.header_result, session=session)
|
||||||
|
|
||||||
|
|
||||||
|
@_record_matcher.handle()
|
||||||
|
async def _(session: EventSession, arparma: Arparma):
|
||||||
|
gid = session.id2
|
||||||
|
if not session.id1:
|
||||||
|
await Text("用户id为空...").finish()
|
||||||
|
if not gid:
|
||||||
|
await Text("群组id为空...").finish()
|
||||||
|
user, _ = await RussianUser.get_or_create(user_id=session.id1, group_id=gid)
|
||||||
|
await Text(
|
||||||
|
f"俄罗斯轮盘\n"
|
||||||
|
f"总胜利场次:{user.win_count}\n"
|
||||||
|
f"当前连胜:{user.winning_streak}\n"
|
||||||
|
f"最高连胜:{user.max_winning_streak}\n"
|
||||||
|
f"总失败场次:{user.fail_count}\n"
|
||||||
|
f"当前连败:{user.losing_streak}\n"
|
||||||
|
f"最高连败:{user.max_losing_streak}\n"
|
||||||
|
f"赚取金币:{user.make_money}\n"
|
||||||
|
f"输掉金币:{user.lose_money}",
|
||||||
|
).send(reply=True)
|
||||||
|
logger.info(f"俄罗斯轮盘查看战绩", arparma.header_result, session=session)
|
||||||
|
|
||||||
|
|
||||||
|
@_rank_matcher.handle()
|
||||||
|
async def _(session: EventSession, arparma: Arparma, rank_type: str, num: int):
|
||||||
|
gid = session.id2
|
||||||
|
if not session.id1:
|
||||||
|
await Text("用户id为空...").finish()
|
||||||
|
if not gid:
|
||||||
|
await Text("群组id为空...").finish()
|
||||||
|
if 51 < num or num < 10:
|
||||||
|
num = 10
|
||||||
|
result = await russian_manage.rank(session.id1, gid, rank_type, num)
|
||||||
|
if isinstance(result, str):
|
||||||
|
await Text(result).finish(reply=True)
|
||||||
|
result.show()
|
||||||
|
await Image(result.pic2bytes()).send(reply=True)
|
||||||
|
logger.info(
|
||||||
|
f"查看轮盘排行: {rank_type} 数量: {num}", arparma.header_result, session=session
|
||||||
|
)
|
||||||
108
zhenxun/plugins/russian/command.py
Normal file
108
zhenxun/plugins/russian/command.py
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
from nonebot_plugin_alconna import Alconna, Args
|
||||||
|
from nonebot_plugin_alconna import At as alcAt
|
||||||
|
from nonebot_plugin_alconna import on_alconna
|
||||||
|
|
||||||
|
from zhenxun.utils.rules import ensure_group
|
||||||
|
|
||||||
|
_russian_matcher = on_alconna(
|
||||||
|
Alconna(
|
||||||
|
"俄罗斯轮盘",
|
||||||
|
Args["money", int]["num?", int]["at_user?", alcAt],
|
||||||
|
),
|
||||||
|
aliases={"装弹"},
|
||||||
|
rule=ensure_group,
|
||||||
|
priority=5,
|
||||||
|
block=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
_accept_matcher = on_alconna(
|
||||||
|
Alconna("接受对决"),
|
||||||
|
aliases={"接受决斗", "接受挑战"},
|
||||||
|
rule=ensure_group,
|
||||||
|
priority=5,
|
||||||
|
block=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
_refuse_matcher = on_alconna(
|
||||||
|
Alconna("拒绝对决"),
|
||||||
|
aliases={"拒绝决斗", "拒绝挑战"},
|
||||||
|
rule=ensure_group,
|
||||||
|
priority=5,
|
||||||
|
block=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
_shoot_matcher = on_alconna(
|
||||||
|
Alconna("开枪"),
|
||||||
|
aliases={"咔", "嘭", "嘣"},
|
||||||
|
rule=ensure_group,
|
||||||
|
priority=5,
|
||||||
|
block=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
_settlement_matcher = on_alconna(
|
||||||
|
Alconna("结算"),
|
||||||
|
rule=ensure_group,
|
||||||
|
priority=5,
|
||||||
|
block=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
_record_matcher = on_alconna(
|
||||||
|
Alconna("我的战绩"),
|
||||||
|
rule=ensure_group,
|
||||||
|
priority=5,
|
||||||
|
block=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
_rank_matcher = on_alconna(
|
||||||
|
Alconna(
|
||||||
|
"russian-rank",
|
||||||
|
Args["rank_type", ["win", "lose", "a", "b", "max_win", "max_lose"]][
|
||||||
|
"num?", int, 10
|
||||||
|
],
|
||||||
|
),
|
||||||
|
rule=ensure_group,
|
||||||
|
priority=5,
|
||||||
|
block=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
_rank_matcher.shortcut(
|
||||||
|
r"轮盘胜场排行(?P<num>\d*)",
|
||||||
|
command="russian-rank",
|
||||||
|
arguments=["win", "{num}"],
|
||||||
|
prefix=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
_rank_matcher.shortcut(
|
||||||
|
r"轮盘败场排行(?P<num>\d*)",
|
||||||
|
command="russian-rank",
|
||||||
|
arguments=["lose", "{num}"],
|
||||||
|
prefix=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
_rank_matcher.shortcut(
|
||||||
|
r"轮盘欧洲人排行(?P<num>\d*)",
|
||||||
|
command="russian-rank",
|
||||||
|
arguments=["a", "{num}"],
|
||||||
|
prefix=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
_rank_matcher.shortcut(
|
||||||
|
r"轮盘慈善家排行(?P<num>\d*)",
|
||||||
|
command="russian-rank",
|
||||||
|
arguments=["b", "{num}"],
|
||||||
|
prefix=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
_rank_matcher.shortcut(
|
||||||
|
r"轮盘最高连胜排行(?P<num>\d*)",
|
||||||
|
command="russian-rank",
|
||||||
|
arguments=["max_win", "{num}"],
|
||||||
|
prefix=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
_rank_matcher.shortcut(
|
||||||
|
r"轮盘最高连败排行(?P<num>\d*)",
|
||||||
|
command="russian-rank",
|
||||||
|
arguments=["max_lose", "{num}"],
|
||||||
|
prefix=True,
|
||||||
|
)
|
||||||
479
zhenxun/plugins/russian/data_source.py
Normal file
479
zhenxun/plugins/russian/data_source.py
Normal file
@ -0,0 +1,479 @@
|
|||||||
|
import random
|
||||||
|
import time
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
from apscheduler.jobstores.base import JobLookupError
|
||||||
|
from nonebot.adapters import Bot
|
||||||
|
from nonebot_plugin_apscheduler import scheduler
|
||||||
|
from nonebot_plugin_saa import Image, Mention, MessageFactory, Text
|
||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
from zhenxun.configs.config import NICKNAME, Config
|
||||||
|
from zhenxun.models.group_member_info import GroupInfoUser
|
||||||
|
from zhenxun.models.user_console import UserConsole
|
||||||
|
from zhenxun.utils.enum import GoldHandle
|
||||||
|
from zhenxun.utils.image_utils import BuildImage, BuildMat, MatType, text2image
|
||||||
|
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 __build_job(
|
||||||
|
self, bot: Bot, group_id: str, is_add: bool = False, platform: str | None = None
|
||||||
|
):
|
||||||
|
"""移除定时任务和构建新定时任务
|
||||||
|
|
||||||
|
参数:
|
||||||
|
bot: Bot
|
||||||
|
group_id: 群组id
|
||||||
|
is_add: 是否添加新定时任务.
|
||||||
|
platform: 平台
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
scheduler.remove_job(f"russian_job_{group_id}")
|
||||||
|
except JobLookupError:
|
||||||
|
pass
|
||||||
|
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)
|
||||||
|
|
||||||
|
async def add_russian(
|
||||||
|
self, bot: Bot, group_id: str, rus: Russian
|
||||||
|
) -> Text | MessageFactory:
|
||||||
|
"""添加决斗
|
||||||
|
|
||||||
|
参数:
|
||||||
|
bot: Bot
|
||||||
|
group_id: 群组id
|
||||||
|
rus: Russian
|
||||||
|
|
||||||
|
返回:
|
||||||
|
Text | MessageFactory: 返回消息
|
||||||
|
"""
|
||||||
|
russian = self._data.get(group_id)
|
||||||
|
if russian:
|
||||||
|
if russian.time + 30 < time.time():
|
||||||
|
if not russian.player2:
|
||||||
|
return Text(
|
||||||
|
f"现在是 {russian.player1[1]} 发起的对决, 请接受对决或等待决斗超时..."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return Text(
|
||||||
|
f"{russian.player1[1]} 和 {russian.player2[1]}的对决还未结束!"
|
||||||
|
)
|
||||||
|
return Text(
|
||||||
|
f"现在是 {russian.player1[1]} 发起的对决\n请等待比赛结束后再开始下一轮..."
|
||||||
|
)
|
||||||
|
max_money = base_config.get("MAX_RUSSIAN_BET_GOLD")
|
||||||
|
if rus.money > max_money:
|
||||||
|
return Text(f"太多了!单次金额不能超过{max_money}!")
|
||||||
|
user = await UserConsole.get_user(rus.player1[0])
|
||||||
|
if user.gold < rus.money:
|
||||||
|
return Text("你没有足够的钱支撑起这场挑战")
|
||||||
|
rus.bullet_arr = self.__random_bullet(rus.bullet_num)
|
||||||
|
self._data[group_id] = rus
|
||||||
|
message_list = []
|
||||||
|
if rus.at_user:
|
||||||
|
user = await GroupInfoUser.get_or_none(
|
||||||
|
user_id=rus.at_user, group_id=group_id
|
||||||
|
)
|
||||||
|
message_list = [
|
||||||
|
Text(f"{rus.player1[1]} 向"),
|
||||||
|
Mention(rus.at_user),
|
||||||
|
Text(
|
||||||
|
f"发起了决斗!请 {user.user_name if user else rus.at_user} 在30秒内回复‘接受对决’ or ‘拒绝对决’,超时此次决斗作废!"
|
||||||
|
),
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
message_list = [
|
||||||
|
Text(
|
||||||
|
"若30秒内无人接受挑战则此次对决作废【首次游玩请发送 ’俄罗斯轮盘帮助‘ 来查看命令】"
|
||||||
|
)
|
||||||
|
]
|
||||||
|
result = Text(
|
||||||
|
"咔 " * rus.bullet_num
|
||||||
|
+ f"装填完毕\n挑战金额:{rus.money}\n第一枪的概率为:{float(rus.bullet_num) / 7.0 * 100:.2f}%\n"
|
||||||
|
)
|
||||||
|
message_list.insert(0, result)
|
||||||
|
self.__build_job(bot, group_id, True)
|
||||||
|
return MessageFactory(message_list)
|
||||||
|
|
||||||
|
def accept(self, group_id: str, user_id: str, uname: str) -> Text | MessageFactory:
|
||||||
|
"""接受对决
|
||||||
|
|
||||||
|
参数:
|
||||||
|
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:
|
||||||
|
return Text("又不是找你决斗,你接受什么啊!气!")
|
||||||
|
if russian.player2:
|
||||||
|
return Text("当前决斗已被其他玩家接受!请等待下局对决!")
|
||||||
|
russian.player2 = (user_id, uname)
|
||||||
|
russian.next_user = russian.player1[0]
|
||||||
|
return MessageFactory(
|
||||||
|
[
|
||||||
|
Text("决斗已经开始!请"),
|
||||||
|
Mention(russian.player1[0]),
|
||||||
|
Text("先开枪!"),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return Text("目前没有进行的决斗,请发送 装弹 开启决斗吧!")
|
||||||
|
|
||||||
|
def refuse(self, group_id: str, user_id: str, uname: str) -> Text | MessageFactory:
|
||||||
|
"""拒绝决斗
|
||||||
|
|
||||||
|
参数:
|
||||||
|
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:
|
||||||
|
return Text("又不是找你决斗,你拒绝什么啊!气!")
|
||||||
|
del self._data[group_id]
|
||||||
|
return MessageFactory(
|
||||||
|
[Mention(russian.player1[0]), Text(f"{uname}拒绝了你的对决!")]
|
||||||
|
)
|
||||||
|
return Text("当前决斗并没有指定对手,无法拒绝哦!")
|
||||||
|
return Text("目前没有进行的决斗,请发送 装弹 开启决斗吧!")
|
||||||
|
|
||||||
|
async def shoot(
|
||||||
|
self, bot: Bot, group_id: str, user_id: str, uname: str, platform: str
|
||||||
|
) -> tuple[Text | MessageFactory, Text | MessageFactory | None]:
|
||||||
|
"""开枪
|
||||||
|
|
||||||
|
参数:
|
||||||
|
bot: Bot
|
||||||
|
group_id: 群组id
|
||||||
|
user_id: 用户id
|
||||||
|
uname: 用户名称
|
||||||
|
platform: 平台
|
||||||
|
|
||||||
|
返回:
|
||||||
|
Text | MessageFactory: 返回消息
|
||||||
|
"""
|
||||||
|
if russian := self._data.get(group_id):
|
||||||
|
if not russian.player2:
|
||||||
|
return Text("当前还没有玩家接受对决,无法开枪..."), None
|
||||||
|
if user_id not in [russian.player1[0], russian.player2[0]]:
|
||||||
|
"""非玩家1和玩家2发送开枪"""
|
||||||
|
return (
|
||||||
|
Text(
|
||||||
|
random.choice(
|
||||||
|
[
|
||||||
|
f"不要打扰 {russian.player1[1]} 和 {russian.player2[1]} 的决斗啊!",
|
||||||
|
f"给我好好做好一个观众!不然{NICKNAME}就要生气了",
|
||||||
|
f"不要捣乱啊baka{uname}!",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
if user_id != russian.next_user:
|
||||||
|
"""相同玩家连续开枪"""
|
||||||
|
return (
|
||||||
|
Text(f"你的左轮不是连发的!该 {russian.player2[1]} 开枪了!"),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
if russian.bullet_arr[russian.bullet_index] == 1:
|
||||||
|
"""去世"""
|
||||||
|
result = Text(
|
||||||
|
random.choice(
|
||||||
|
[
|
||||||
|
'"嘭!",你直接去世了',
|
||||||
|
"眼前一黑,你直接穿越到了异世界...(死亡)",
|
||||||
|
"终究还是你先走一步...",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
settle = await self.settlement(group_id, user_id, platform)
|
||||||
|
return result, settle
|
||||||
|
else:
|
||||||
|
"""存活"""
|
||||||
|
p = (russian.bullet_index + 1) / len(russian.bullet_arr) * 100
|
||||||
|
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 (
|
||||||
|
MessageFactory([Text(result), Mention(next_user), Text(" 了!")]),
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
return Text("目前没有进行的决斗,请发送 装弹 开启决斗吧!"), None
|
||||||
|
|
||||||
|
async def settlement(
|
||||||
|
self, group_id: str, user_id: str | None, platform: str | None = None
|
||||||
|
) -> Text | MessageFactory:
|
||||||
|
"""结算
|
||||||
|
|
||||||
|
参数:
|
||||||
|
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]
|
||||||
|
return Text("规定时间内还未有人接受决斗,当前决斗过期...")
|
||||||
|
return Text("决斗还未开始,,无法结算哦...")
|
||||||
|
if user_id and user_id not in [russian.player1[0], russian.player1[0]]:
|
||||||
|
return Text("吃瓜群众不要捣乱!黄牌警告!")
|
||||||
|
if not self.__check_is_timeout(group_id):
|
||||||
|
return Text(
|
||||||
|
f"{russian.player1[1]} 和 {russian.player1[1]} 比赛并未超时,请继续比赛..."
|
||||||
|
)
|
||||||
|
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
|
||||||
|
)
|
||||||
|
await UserConsole.reduce_gold(
|
||||||
|
lose_user[0], russian.money, GoldHandle.PLUGIN, "russian", platform
|
||||||
|
)
|
||||||
|
result = [Text("这场决斗是 "), Mention(win_user[0]), Text(" 胜利了!")]
|
||||||
|
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"
|
||||||
|
f"哼哼,{NICKNAME}从中收取了 {float(rand)}%({fee}金币) 作为手续费!\n"
|
||||||
|
f"子弹排列:{russian.bullet_arr}",
|
||||||
|
padding=10,
|
||||||
|
color="#f9f6f2",
|
||||||
|
)
|
||||||
|
result.append(Image(image.pic2bytes()))
|
||||||
|
del self._data[group_id]
|
||||||
|
return MessageFactory(result)
|
||||||
|
return Text("赢家和输家获取错误...")
|
||||||
|
return Text("比赛并没有开始...无法结算...")
|
||||||
|
|
||||||
|
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()
|
||||||
107
zhenxun/plugins/russian/model.py
Normal file
107
zhenxun/plugins/russian/model.py
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
from tortoise import fields
|
||||||
|
|
||||||
|
from zhenxun.services.db_context import Model
|
||||||
|
|
||||||
|
|
||||||
|
class RussianUser(Model):
|
||||||
|
|
||||||
|
id = fields.IntField(pk=True, generated=True, auto_increment=True)
|
||||||
|
"""自增id"""
|
||||||
|
user_id = fields.CharField(255)
|
||||||
|
"""用户id"""
|
||||||
|
group_id = fields.CharField(255)
|
||||||
|
"""群聊id"""
|
||||||
|
win_count = fields.IntField(default=0)
|
||||||
|
"""胜利次数"""
|
||||||
|
fail_count = fields.IntField(default=0)
|
||||||
|
"""失败次数"""
|
||||||
|
make_money = fields.IntField(default=0)
|
||||||
|
"""赢得金币"""
|
||||||
|
lose_money = fields.IntField(default=0)
|
||||||
|
"""输得金币"""
|
||||||
|
winning_streak = fields.IntField(default=0)
|
||||||
|
"""当前连胜"""
|
||||||
|
losing_streak = fields.IntField(default=0)
|
||||||
|
"""当前连败"""
|
||||||
|
max_winning_streak = fields.IntField(default=0)
|
||||||
|
"""最大连胜"""
|
||||||
|
max_losing_streak = fields.IntField(default=0)
|
||||||
|
"""最大连败"""
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
table = "russian_users"
|
||||||
|
table_description = "俄罗斯轮盘数据表"
|
||||||
|
unique_together = ("user_id", "group_id")
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def add_count(cls, user_id: str, group_id: str, itype: str):
|
||||||
|
"""添加用户输赢次数
|
||||||
|
|
||||||
|
说明:
|
||||||
|
user_id: 用户id
|
||||||
|
group_id: 群号
|
||||||
|
itype: 输或赢 'win' or 'lose'
|
||||||
|
"""
|
||||||
|
user, _ = await cls.get_or_create(user_id=user_id, group_id=group_id)
|
||||||
|
if itype == "win":
|
||||||
|
_max = (
|
||||||
|
user.max_winning_streak
|
||||||
|
if user.max_winning_streak > user.winning_streak + 1
|
||||||
|
else user.winning_streak + 1
|
||||||
|
)
|
||||||
|
user.win_count = user.win_count + 1
|
||||||
|
user.winning_streak = user.winning_streak + 1
|
||||||
|
user.losing_streak = 0
|
||||||
|
user.max_winning_streak = _max
|
||||||
|
await user.save(
|
||||||
|
update_fields=[
|
||||||
|
"win_count",
|
||||||
|
"winning_streak",
|
||||||
|
"losing_streak",
|
||||||
|
"max_winning_streak",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
elif itype == "lose":
|
||||||
|
_max = (
|
||||||
|
user.max_losing_streak
|
||||||
|
if user.max_losing_streak > user.losing_streak + 1
|
||||||
|
else user.losing_streak + 1
|
||||||
|
)
|
||||||
|
user.fail_count = user.fail_count + 1
|
||||||
|
user.losing_streak = user.losing_streak + 1
|
||||||
|
user.winning_streak = 0
|
||||||
|
user.max_losing_streak = _max
|
||||||
|
await user.save(
|
||||||
|
update_fields=[
|
||||||
|
"fail_count",
|
||||||
|
"winning_streak",
|
||||||
|
"losing_streak",
|
||||||
|
"max_losing_streak",
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return user
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def money(cls, user_id: str, group_id: str, itype: str, count: int):
|
||||||
|
"""添加用户输赢金钱
|
||||||
|
|
||||||
|
参数:
|
||||||
|
user_id: 用户id
|
||||||
|
group_id: 群号
|
||||||
|
itype: 输或赢 'win' or 'lose'
|
||||||
|
count: 金钱数量
|
||||||
|
"""
|
||||||
|
user, _ = await cls.get_or_create(user_id=str(user_id), group_id=group_id)
|
||||||
|
if itype == "win":
|
||||||
|
user.make_money = user.make_money + count
|
||||||
|
elif itype == "lose":
|
||||||
|
user.lose_money = user.lose_money + count
|
||||||
|
await user.save(update_fields=["make_money", "lose_money"])
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
async def _run_script(cls):
|
||||||
|
return [
|
||||||
|
"ALTER TABLE russian_users RENAME COLUMN user_qq TO user_id;", # 将user_qq改为user_id
|
||||||
|
"ALTER TABLE russian_users ALTER COLUMN user_id TYPE character varying(255);",
|
||||||
|
"ALTER TABLE russian_users ALTER COLUMN group_id TYPE character varying(255);",
|
||||||
|
]
|
||||||
@ -556,7 +556,7 @@ class BuildMat:
|
|||||||
random_color = random.choice(bar_color)
|
random_color = random.choice(bar_color)
|
||||||
max_num = max(self.y_index)
|
max_num = max(self.y_index)
|
||||||
for y_p, y in zip(init_graph.y_point, self.build_data.data):
|
for y_p, y in zip(init_graph.y_point, self.build_data.data):
|
||||||
bar_width = int(y / max_num * graph_height)
|
bar_width = int(y / max_num * graph_height) or 1
|
||||||
bar = BuildImage(bar_width, 18, random_color)
|
bar = BuildImage(bar_width, 18, random_color)
|
||||||
await mark_image.paste(bar, (y_width + 1, y_p - 9))
|
await mark_image.paste(bar, (y_width + 1, y_p - 9))
|
||||||
if self.build_data.display_num:
|
if self.build_data.display_num:
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user