forked from sass/tipibot
Discomboluating
This commit is contained in:
249
economy_prestige_commands.py
Normal file
249
economy_prestige_commands.py
Normal file
@@ -0,0 +1,249 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from collections.abc import Awaitable, Callable
|
||||
|
||||
import discord
|
||||
from discord import app_commands
|
||||
|
||||
import economy
|
||||
import strings as S
|
||||
|
||||
|
||||
def register_prestige_commands(
|
||||
tree: app_commands.CommandTree,
|
||||
check_cmd_rate: Callable[[discord.Interaction], Awaitable[bool]],
|
||||
ensure_level_role: Callable[[discord.Member, int], Awaitable[None]],
|
||||
) -> None:
|
||||
class PrestigeView(discord.ui.View):
|
||||
def __init__(self, user_id: int, tab: str = "status"):
|
||||
super().__init__(timeout=60)
|
||||
self.user_id = user_id
|
||||
self.tab = tab
|
||||
|
||||
async def _rebuild(self, data: dict):
|
||||
self.clear_items()
|
||||
pp = data.get("prestige_points", 0)
|
||||
upgrades: dict = data.get("prestige_upgrades") or {}
|
||||
exp = data.get("exp", 0)
|
||||
level = economy.get_level(exp)
|
||||
|
||||
for tab_id, label in (("status", S.PRESTIGE_UI["btn_tab_status"]), ("shop", S.PRESTIGE_UI["btn_tab_shop"])):
|
||||
btn = discord.ui.Button(
|
||||
label=label,
|
||||
style=discord.ButtonStyle.primary if tab_id == self.tab else discord.ButtonStyle.secondary,
|
||||
disabled=(tab_id == self.tab),
|
||||
row=0,
|
||||
)
|
||||
btn.callback = self._switch_tab(tab_id)
|
||||
self.add_item(btn)
|
||||
|
||||
if self.tab == "status" and level >= economy.PRESTIGE_MIN_LEVEL:
|
||||
confirm_btn = discord.ui.Button(
|
||||
label=S.PRESTIGE_UI["btn_confirm"],
|
||||
style=discord.ButtonStyle.danger,
|
||||
row=1,
|
||||
)
|
||||
confirm_btn.callback = self._do_prestige()
|
||||
cancel_btn = discord.ui.Button(
|
||||
label=S.PRESTIGE_UI["btn_cancel"],
|
||||
style=discord.ButtonStyle.secondary,
|
||||
row=1,
|
||||
)
|
||||
cancel_btn.callback = self._do_cancel()
|
||||
self.add_item(confirm_btn)
|
||||
self.add_item(cancel_btn)
|
||||
elif self.tab == "shop":
|
||||
for uid, item in economy.PRESTIGE_SHOP.items():
|
||||
cur_level = upgrades.get(uid, 0)
|
||||
if cur_level >= item["max_level"]:
|
||||
continue
|
||||
cost = item["pp_cost"]
|
||||
btn = discord.ui.Button(
|
||||
label=S.PRESTIGE_UI["btn_buy_upgrade"].format(emoji=item["emoji"], name=S.PRESTIGE_SHOP_NAMES[uid], cost=cost),
|
||||
style=discord.ButtonStyle.success if pp >= cost else discord.ButtonStyle.secondary,
|
||||
disabled=(pp < cost),
|
||||
row=1,
|
||||
)
|
||||
btn.callback = self._buy_upgrade(uid)
|
||||
self.add_item(btn)
|
||||
|
||||
def _build_status_embed(self, data: dict) -> discord.Embed:
|
||||
exp = data.get("exp", 0)
|
||||
level = economy.get_level(exp)
|
||||
pp = data.get("prestige_points", 0)
|
||||
p_level = data.get("prestige_level", 0)
|
||||
if level >= economy.PRESTIGE_MIN_LEVEL:
|
||||
pp_preview = max(1, exp // 1000)
|
||||
embed = discord.Embed(
|
||||
title=S.TITLE["prestige_confirm"],
|
||||
description=S.PRESTIGE_UI["confirm_desc"].format(level=level, exp=exp, pp=pp_preview),
|
||||
color=0xF4C430,
|
||||
)
|
||||
else:
|
||||
embed = discord.Embed(
|
||||
title=S.TITLE["prestige_too_low"],
|
||||
description=S.PRESTIGE_UI["too_low_desc"].format(level=level, required=economy.PRESTIGE_MIN_LEVEL),
|
||||
color=0xED4245,
|
||||
)
|
||||
if p_level > 0:
|
||||
embed.set_footer(text=S.PRESTIGE_UI["status_footer"].format(level=p_level, pp=pp))
|
||||
return embed
|
||||
|
||||
def _build_shop_embed(self, data: dict) -> discord.Embed:
|
||||
pp = data.get("prestige_points", 0)
|
||||
upgrades: dict = data.get("prestige_upgrades") or {}
|
||||
embed = discord.Embed(
|
||||
title=S.TITLE["prestige_shop"],
|
||||
description=S.PRESTIGE_UI["shop_desc"].format(pp=pp),
|
||||
color=0xF4C430,
|
||||
)
|
||||
for uid, item in economy.PRESTIGE_SHOP.items():
|
||||
cur_level = upgrades.get(uid, 0)
|
||||
name = f"{item['emoji']} {S.PRESTIGE_SHOP_NAMES[uid]}"
|
||||
cost_str = S.PRESTIGE_UI["shop_maxed"] if cur_level >= item["max_level"] else S.PRESTIGE_UI["shop_cost_fmt"].format(cost=item["pp_cost"])
|
||||
level_str = S.PRESTIGE_UI["shop_level_fmt"].format(cur=cur_level, max=item["max_level"])
|
||||
embed.add_field(name=f"{name} · {level_str} · {cost_str}", value=S.PRESTIGE_SHOP_DESCRIPTIONS[uid], inline=False)
|
||||
return embed
|
||||
|
||||
def _switch_tab(self, tab_id: str):
|
||||
async def _cb(interaction: discord.Interaction):
|
||||
if interaction.user.id != self.user_id:
|
||||
await interaction.response.send_message(S.ERR["not_your_menu"], ephemeral=True)
|
||||
return
|
||||
self.tab = tab_id
|
||||
await interaction.response.defer()
|
||||
data = await economy.get_user(self.user_id)
|
||||
await self._rebuild(data)
|
||||
embed = self._build_status_embed(data) if tab_id == "status" else self._build_shop_embed(data)
|
||||
await interaction.edit_original_response(embed=embed, view=self)
|
||||
|
||||
return _cb
|
||||
|
||||
def _do_prestige(self):
|
||||
async def _cb(interaction: discord.Interaction):
|
||||
if interaction.user.id != self.user_id:
|
||||
await interaction.response.send_message(S.ERR["not_your_game"], ephemeral=True)
|
||||
return
|
||||
await interaction.response.defer()
|
||||
res = await economy.do_prestige(self.user_id)
|
||||
self.clear_items()
|
||||
if not res["ok"]:
|
||||
embed = discord.Embed(
|
||||
title=S.TITLE["prestige_too_low"],
|
||||
description=S.PRESTIGE_UI["too_low_desc"].format(level=res.get("level", 0), required=res.get("required", 30)),
|
||||
color=0xED4245,
|
||||
)
|
||||
else:
|
||||
embed = discord.Embed(
|
||||
title=S.TITLE["prestige_success"].format(level=res["prestige_level"]),
|
||||
description=S.PRESTIGE_UI["success_desc"].format(pp=res["pp_earned"], level=res["prestige_level"], total_pp=res["prestige_points"]),
|
||||
color=0xF4C430,
|
||||
)
|
||||
await interaction.edit_original_response(embed=embed, view=self)
|
||||
if res.get("ok") and interaction.guild:
|
||||
member = interaction.guild.get_member(self.user_id)
|
||||
if member:
|
||||
asyncio.create_task(ensure_level_role(member, 1))
|
||||
|
||||
return _cb
|
||||
|
||||
def _do_cancel(self):
|
||||
async def _cb(interaction: discord.Interaction):
|
||||
if interaction.user.id != self.user_id:
|
||||
await interaction.response.send_message(S.ERR["not_your_game"], ephemeral=True)
|
||||
return
|
||||
self.clear_items()
|
||||
await interaction.response.edit_message(view=self)
|
||||
|
||||
return _cb
|
||||
|
||||
def _buy_upgrade(self, upgrade_id: str):
|
||||
async def _cb(interaction: discord.Interaction):
|
||||
if interaction.user.id != self.user_id:
|
||||
await interaction.response.send_message(S.ERR["not_your_menu"], ephemeral=True)
|
||||
return
|
||||
await interaction.response.defer()
|
||||
res = await economy.do_prestige_buy(self.user_id, upgrade_id)
|
||||
if not res["ok"]:
|
||||
if res["reason"] == "insufficient_pp":
|
||||
err = S.PRESTIGE_UI["buy_no_pp"].format(have=res["have"], need=res["need"])
|
||||
elif res["reason"] == "maxed":
|
||||
err = S.PRESTIGE_UI["buy_maxed"]
|
||||
else:
|
||||
err = S.ERR["generic_error"].format(error=res["reason"])
|
||||
await interaction.followup.send(err, ephemeral=True)
|
||||
return
|
||||
data = await economy.get_user(self.user_id)
|
||||
await self._rebuild(data)
|
||||
embed = self._build_shop_embed(data)
|
||||
item = economy.PRESTIGE_SHOP[res["upgrade_id"]]
|
||||
name = f"{item['emoji']} {S.PRESTIGE_SHOP_NAMES[res['upgrade_id']]}"
|
||||
embed.description = S.PRESTIGE_UI["buy_success_desc"].format(
|
||||
name=name,
|
||||
new_level=res["new_level"],
|
||||
max_level=item["max_level"],
|
||||
pp=res["pp_remaining"],
|
||||
) + "\n\n" + (embed.description or "")
|
||||
await interaction.edit_original_response(embed=embed, view=self)
|
||||
|
||||
return _cb
|
||||
|
||||
async def on_timeout(self):
|
||||
self.clear_items()
|
||||
|
||||
@tree.command(name="prestige", description=S.CMD["prestige"])
|
||||
@app_commands.guild_only()
|
||||
async def cmd_prestige(interaction: discord.Interaction):
|
||||
if await check_cmd_rate(interaction):
|
||||
return
|
||||
data = await economy.get_user(interaction.user.id)
|
||||
if data.get("eco_banned"):
|
||||
await interaction.response.send_message(S.MSG_BANNED, ephemeral=True)
|
||||
return
|
||||
view = PrestigeView(interaction.user.id)
|
||||
await view._rebuild(data)
|
||||
embed = view._build_status_embed(data)
|
||||
await interaction.response.send_message(embed=embed, view=view, ephemeral=True)
|
||||
|
||||
@tree.command(name="prestigeshop", description=S.CMD["prestigeshop"])
|
||||
async def cmd_prestigeshop(interaction: discord.Interaction):
|
||||
data = await economy.get_user(interaction.user.id)
|
||||
view = PrestigeView(interaction.user.id, tab="shop")
|
||||
await view._rebuild(data)
|
||||
embed = view._build_shop_embed(data)
|
||||
await interaction.response.send_message(embed=embed, view=view, ephemeral=True)
|
||||
|
||||
@tree.command(name="prestigebuy", description=S.CMD["prestigebuy"])
|
||||
@app_commands.describe(upgrade=S.OPT["prestigebuy_upgrade"])
|
||||
async def cmd_prestigebuy(interaction: discord.Interaction, upgrade: str):
|
||||
if await check_cmd_rate(interaction):
|
||||
return
|
||||
res = await economy.do_prestige_buy(interaction.user.id, upgrade.strip().lower())
|
||||
if not res["ok"]:
|
||||
if res["reason"] == "banned":
|
||||
await interaction.response.send_message(S.MSG_BANNED, ephemeral=True)
|
||||
elif res["reason"] == "not_found":
|
||||
await interaction.response.send_message(S.PRESTIGE_UI["buy_not_found"], ephemeral=True)
|
||||
elif res["reason"] == "maxed":
|
||||
await interaction.response.send_message(S.PRESTIGE_UI["buy_maxed"], ephemeral=True)
|
||||
elif res["reason"] == "insufficient_pp":
|
||||
await interaction.response.send_message(
|
||||
S.PRESTIGE_UI["buy_no_pp"].format(have=res["have"], need=res["need"]),
|
||||
ephemeral=True,
|
||||
)
|
||||
return
|
||||
|
||||
item = economy.PRESTIGE_SHOP[res["upgrade_id"]]
|
||||
name = f"{item['emoji']} {S.PRESTIGE_SHOP_NAMES[res['upgrade_id']]}"
|
||||
embed = discord.Embed(
|
||||
title=S.TITLE["prestige_buy_ok"],
|
||||
description=S.PRESTIGE_UI["buy_success_desc"].format(
|
||||
name=name,
|
||||
new_level=res["new_level"],
|
||||
max_level=res["max_level"],
|
||||
pp=res["pp_remaining"],
|
||||
),
|
||||
color=0x57F287,
|
||||
)
|
||||
await interaction.response.send_message(embed=embed, ephemeral=True)
|
||||
Reference in New Issue
Block a user