feat(skins): Implement user skin ui.
This commit is contained in:
2
src/gui
2
src/gui
Submodule src/gui updated: f2760218ef...c1bcb05c25
@@ -21,6 +21,7 @@ from .data import CustomSkinData
|
|||||||
from .skinlib import appskin_as_choice, FrozenCustomSkin, CustomSkin
|
from .skinlib import appskin_as_choice, FrozenCustomSkin, CustomSkin
|
||||||
from .settings import GlobalSkinSettings
|
from .settings import GlobalSkinSettings
|
||||||
from .settingui import GlobalSkinSettingUI
|
from .settingui import GlobalSkinSettingUI
|
||||||
|
from .userskinui import UserSkinUI
|
||||||
|
|
||||||
_p = babel._p
|
_p = babel._p
|
||||||
|
|
||||||
@@ -35,7 +36,6 @@ class CustomSkinCog(LionCog):
|
|||||||
# After initialisation, contains all the base skins available for this app
|
# After initialisation, contains all the base skins available for this app
|
||||||
self.appskin_names: bidict[int, str] = bidict()
|
self.appskin_names: bidict[int, str] = bidict()
|
||||||
|
|
||||||
# TODO: Move this to a bijection
|
|
||||||
# Bijective cache of skin property ids <-> (card_id, property_name) tuples
|
# Bijective cache of skin property ids <-> (card_id, property_name) tuples
|
||||||
self.skin_properties: bidict[int, tuple[str, str]] = bidict()
|
self.skin_properties: bidict[int, tuple[str, str]] = bidict()
|
||||||
|
|
||||||
@@ -245,8 +245,9 @@ class CustomSkinCog(LionCog):
|
|||||||
async def cmd_my_skin(self, ctx: LionContext):
|
async def cmd_my_skin(self, ctx: LionContext):
|
||||||
if not ctx.interaction:
|
if not ctx.interaction:
|
||||||
return
|
return
|
||||||
# TODO
|
ui = UserSkinUI(self.bot, ctx.author.id, ctx.author.id)
|
||||||
...
|
await ui.run(ctx.interaction, ephemeral=True)
|
||||||
|
await ui.wait()
|
||||||
|
|
||||||
# ----- Adminspace commands -----
|
# ----- Adminspace commands -----
|
||||||
@LionCog.placeholder_group
|
@LionCog.placeholder_group
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ class CustomSkin:
|
|||||||
for record in records:
|
for record in records:
|
||||||
card_id = record['card_id']
|
card_id = record['card_id']
|
||||||
prop_name = record['property_name']
|
prop_name = record['property_name']
|
||||||
prop_value = record['property_value']
|
prop_value = record['value']
|
||||||
properties[card_id][prop_name] = prop_value
|
properties[card_id][prop_name] = prop_value
|
||||||
if row.base_skin_id is not None:
|
if row.base_skin_id is not None:
|
||||||
base_skin_name = cog.appskin_names[row.base_skin_id]
|
base_skin_name = cog.appskin_names[row.base_skin_id]
|
||||||
|
|||||||
@@ -0,0 +1,552 @@
|
|||||||
|
from typing import Optional
|
||||||
|
import asyncio
|
||||||
|
import datetime as dt
|
||||||
|
|
||||||
|
import discord
|
||||||
|
from discord.ui.button import button, Button, ButtonStyle
|
||||||
|
from discord.ui.select import select, Select, SelectOption
|
||||||
|
from gui.base.AppSkin import AppSkin
|
||||||
|
from gui.base.Card import Card
|
||||||
|
|
||||||
|
from meta import LionBot, conf
|
||||||
|
from meta.errors import ResponseTimedOut, UserInputError
|
||||||
|
from meta.logger import log_wrap
|
||||||
|
from modules.premium.data import GemTransactionType
|
||||||
|
from modules.premium.errors import BalanceTooLow
|
||||||
|
from modules.skins.skinlib import CustomSkin, appskin_as_option
|
||||||
|
from utils.ui import MessageUI, input, Confirm
|
||||||
|
from utils.lib import MessageArgs, utc_now
|
||||||
|
from gui import cards
|
||||||
|
|
||||||
|
from . import babel, logger
|
||||||
|
from .data import CustomSkinData as Data
|
||||||
|
|
||||||
|
_p = babel._p
|
||||||
|
|
||||||
|
|
||||||
|
class UserSkinUI(MessageUI):
|
||||||
|
card_classes = [
|
||||||
|
cards.ProfileCard,
|
||||||
|
cards.StatsCard,
|
||||||
|
cards.WeeklyGoalCard,
|
||||||
|
cards.WeeklyStatsCard,
|
||||||
|
cards.MonthlyGoalCard,
|
||||||
|
cards.MonthlyStatsCard,
|
||||||
|
]
|
||||||
|
|
||||||
|
def __init__(self, bot: LionBot, userid: int, callerid: int, **kwargs):
|
||||||
|
super().__init__(callerid=callerid, **kwargs)
|
||||||
|
|
||||||
|
self.bot = bot
|
||||||
|
self.cog = bot.get_cog('CustomSkinCog')
|
||||||
|
self.gems = bot.get_cog('PremiumCog')
|
||||||
|
|
||||||
|
self.userid = userid
|
||||||
|
|
||||||
|
# UI State
|
||||||
|
# Map of app_skin_id -> itemid
|
||||||
|
self.inventory: dict[str, int] = {}
|
||||||
|
|
||||||
|
# Active app skin, if any
|
||||||
|
self.active: Optional[str] = None
|
||||||
|
|
||||||
|
# Skins available for purchase
|
||||||
|
self.available = self._get_available()
|
||||||
|
|
||||||
|
# Index of card currently showing
|
||||||
|
self._card: int = 0
|
||||||
|
|
||||||
|
# Name of skin currently displayed, 'default' for default
|
||||||
|
self._skin: Optional[str] = None
|
||||||
|
|
||||||
|
self.balance: int = 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_card(self) -> Card:
|
||||||
|
return self.card_classes[self._card]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def current_skin(self) -> AppSkin:
|
||||||
|
if self._skin is None:
|
||||||
|
raise ValueError("Cannot get current skin before load.")
|
||||||
|
return self.available[self._skin]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_default(self) -> bool:
|
||||||
|
return (self._skin == 'default')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_owned(self) -> bool:
|
||||||
|
return self.is_default or (self._skin in self.inventory)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_equipped(self) -> bool:
|
||||||
|
return (self.active == self._skin) or (self.is_default and not self.active)
|
||||||
|
|
||||||
|
def _get_available(self) -> dict[str, AppSkin]:
|
||||||
|
skins = {
|
||||||
|
skin.skin_id: skin for skin in AppSkin.get_all()
|
||||||
|
if skin.public or (
|
||||||
|
skin.user_whitelist is not None and
|
||||||
|
self.userid in skin.user_whitelist
|
||||||
|
)
|
||||||
|
}
|
||||||
|
skins['default'] = self._make_default()
|
||||||
|
return skins
|
||||||
|
|
||||||
|
def _make_default(self) -> AppSkin:
|
||||||
|
"""
|
||||||
|
Create a placeholder 'default' skin.
|
||||||
|
"""
|
||||||
|
t = self.bot.translator.t
|
||||||
|
|
||||||
|
skin = AppSkin(None)
|
||||||
|
skin.skin_id = 'default'
|
||||||
|
skin.display_name = t(_p(
|
||||||
|
'ui:userskins|default_skin:display_name',
|
||||||
|
"Default"
|
||||||
|
))
|
||||||
|
skin.description = t(_p(
|
||||||
|
'ui:userskins|default_skin:description',
|
||||||
|
"My default interface theme"
|
||||||
|
))
|
||||||
|
skin.price = 0
|
||||||
|
return skin
|
||||||
|
|
||||||
|
# ----- UI API -----
|
||||||
|
|
||||||
|
@log_wrap(action='equip skin')
|
||||||
|
async def _equip_owned_skin(self, itemid: Optional[int]):
|
||||||
|
"""
|
||||||
|
Equip the provided item.
|
||||||
|
|
||||||
|
if `itemid` is None, 'equips' the default skin.
|
||||||
|
"""
|
||||||
|
# Global dispatch
|
||||||
|
await self.cog.data.UserSkin.table.update_where(
|
||||||
|
userid=self.userid
|
||||||
|
).set(active=False)
|
||||||
|
if itemid is not None:
|
||||||
|
await self.cog.data.UserSkin.table.update_where(
|
||||||
|
userid=self.userid, itemid=itemid
|
||||||
|
).set(active=True)
|
||||||
|
|
||||||
|
await self.bot.global_dispatch('userset_skin', self.userid)
|
||||||
|
|
||||||
|
@log_wrap(action='purchase skin')
|
||||||
|
async def _purchase_skin(self, app_skin_name: str):
|
||||||
|
async with self.bot.db.connection() as conn:
|
||||||
|
self.bot.db.conn = conn
|
||||||
|
async with conn.transaction():
|
||||||
|
skin = self.current_skin
|
||||||
|
skinid = self.cog.appskin_names.inverse[skin.skin_id]
|
||||||
|
|
||||||
|
# Perform transaction
|
||||||
|
transaction = await self.gems.gem_transaction(
|
||||||
|
GemTransactionType.PURCHASE,
|
||||||
|
actorid=self.userid,
|
||||||
|
from_account=self.userid,
|
||||||
|
to_account=None,
|
||||||
|
amount=skin.price,
|
||||||
|
description=(
|
||||||
|
f"User purchased custom app skin {skin.skin_id} via UserSkinUI."
|
||||||
|
),
|
||||||
|
note=None,
|
||||||
|
reference=f"iid: {self._original.id if self._original else 'None'}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Create custom skin
|
||||||
|
custom_skin = await self.cog.data.CustomisedSkin.create(
|
||||||
|
base_skin_id=skinid,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Update inventory actives
|
||||||
|
await self.cog.data.UserSkin.table.update_where(
|
||||||
|
userid=self.userid
|
||||||
|
).set(active=False)
|
||||||
|
|
||||||
|
# Insert into inventory
|
||||||
|
await self.cog.data.UserSkin.create(
|
||||||
|
userid=self.userid,
|
||||||
|
custom_skin_id=custom_skin.custom_skin_id,
|
||||||
|
transactionid=transaction.transactionid,
|
||||||
|
active=True
|
||||||
|
)
|
||||||
|
|
||||||
|
# Global dispatch update
|
||||||
|
await self.bot.global_dispatch('userset_skin', self.userid)
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"<uid: {self.userid}> purchased skin {skin.skin_id}."
|
||||||
|
)
|
||||||
|
|
||||||
|
# ----- UI Components -----
|
||||||
|
|
||||||
|
# Gift Button
|
||||||
|
@button(
|
||||||
|
label="GIFT_BUTTON_PLACEHOLDER",
|
||||||
|
style=ButtonStyle.green,
|
||||||
|
)
|
||||||
|
async def gift_button(self, press: discord.Interaction, pressed: Button):
|
||||||
|
# TODO: Replace with an actual gifting interface
|
||||||
|
|
||||||
|
t = self.bot.translator.t
|
||||||
|
skin = self.current_skin
|
||||||
|
gift_hint = t(_p(
|
||||||
|
'ui:userskins|button:gift|response',
|
||||||
|
"To gift **{skin}** to a friend,"
|
||||||
|
" send them {gem}**{price}** with {gift_cmd}."
|
||||||
|
)).format(
|
||||||
|
skin=skin.display_name,
|
||||||
|
gem=self.bot.config.emojis.gem,
|
||||||
|
price=skin.price,
|
||||||
|
gift_cmd=self.bot.core.mention_cmd('gift'),
|
||||||
|
)
|
||||||
|
await press.response.send_message(gift_hint, ephemeral=True)
|
||||||
|
|
||||||
|
async def gift_button_refresh(self):
|
||||||
|
button = self.gift_button
|
||||||
|
t = self.bot.translator.t
|
||||||
|
button.label = t(_p(
|
||||||
|
'ui:userskins|button:gift|label',
|
||||||
|
"Gift to a friend"
|
||||||
|
))
|
||||||
|
price = self.current_skin.price
|
||||||
|
button.disabled = (
|
||||||
|
not price or (price > self.balance)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Purchase Button
|
||||||
|
@button(
|
||||||
|
label="PURCHASE_BUTTON_PLACEHOLDER",
|
||||||
|
style=ButtonStyle.green
|
||||||
|
)
|
||||||
|
async def purchase_button(self, press: discord.Interaction, pressed: Button):
|
||||||
|
t = self.bot.translator.t
|
||||||
|
|
||||||
|
skin = self.current_skin
|
||||||
|
|
||||||
|
# Verify we can purchase this skin
|
||||||
|
await self.reload()
|
||||||
|
|
||||||
|
if self.is_owned:
|
||||||
|
raise UserInputError(
|
||||||
|
t(_p(
|
||||||
|
'ui:userskins|button:purchase|error:already_owned',
|
||||||
|
"You already own this skin!"
|
||||||
|
))
|
||||||
|
)
|
||||||
|
elif skin.price > self.balance:
|
||||||
|
raise UserInputError(
|
||||||
|
t(_p(
|
||||||
|
'ui:userskins|button:purchase|error:insufficient_gems',
|
||||||
|
"You don't have enough LionGems to purchase this skin!"
|
||||||
|
))
|
||||||
|
)
|
||||||
|
|
||||||
|
# Confirm purchase
|
||||||
|
confirm_msg = t(_p(
|
||||||
|
'ui:userskins|button:purchase|confirm|desc',
|
||||||
|
"Are you sure you want to purchase this skin?\n"
|
||||||
|
"The price of the skin is {gem}**{price}**."
|
||||||
|
)).format(price=skin.price, gem=self.bot.config.emojis.gem)
|
||||||
|
confirm = Confirm(confirm_msg, press.user.id)
|
||||||
|
|
||||||
|
confirm.embed.set_footer(
|
||||||
|
text=t(_p(
|
||||||
|
'ui:userskins|button:purchase|confirm|footer',
|
||||||
|
"Your current balance is {balance} LionGems"
|
||||||
|
)).format(balance=self.balance)
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = await confirm.ask(press, ephemeral=True)
|
||||||
|
except ResponseTimedOut:
|
||||||
|
result = False
|
||||||
|
|
||||||
|
if result:
|
||||||
|
try:
|
||||||
|
await self._purchase_skin(skin.skin_id)
|
||||||
|
except BalanceTooLow:
|
||||||
|
raise UserInputError(
|
||||||
|
t(_p(
|
||||||
|
'ui:userskins|button:purchase|error:insufficient_gems_post_confirm',
|
||||||
|
"Insufficient LionGems to purchase this skin!"
|
||||||
|
))
|
||||||
|
)
|
||||||
|
|
||||||
|
# Ack purchase and refresh
|
||||||
|
embed = discord.Embed(
|
||||||
|
colour=discord.Colour.brand_green(),
|
||||||
|
title=t(_p(
|
||||||
|
'ui:userskins|button:purchase|embed:success|title',
|
||||||
|
"Skin Purchase"
|
||||||
|
)),
|
||||||
|
description=t(_p(
|
||||||
|
'ui:userskins|button:purchase|embed:success|desc',
|
||||||
|
"You have purchased and equipped the skin **{name}**!\n"
|
||||||
|
"Thank you for your support, and enjoy your new purchase!"
|
||||||
|
)).format(name=skin.display_name)
|
||||||
|
)
|
||||||
|
await press.followup.send(embed=embed, ephemeral=True)
|
||||||
|
await self.refresh()
|
||||||
|
|
||||||
|
async def purchase_button_refresh(self):
|
||||||
|
button = self.purchase_button
|
||||||
|
t = self.bot.translator.t
|
||||||
|
button.label = t(_p(
|
||||||
|
'ui:userskins|button:purchase|label',
|
||||||
|
"Purchase Skin"
|
||||||
|
))
|
||||||
|
button.disabled = (
|
||||||
|
self.is_owned
|
||||||
|
or self.current_skin.price > self.balance
|
||||||
|
)
|
||||||
|
|
||||||
|
# Equip Button
|
||||||
|
@button(
|
||||||
|
label="EQUIP_BUTTON_PLACEHOLDER",
|
||||||
|
style=ButtonStyle.green
|
||||||
|
)
|
||||||
|
async def equip_button(self, press: discord.Interaction, pressed: Button):
|
||||||
|
await press.response.defer(thinking=True, ephemeral=True)
|
||||||
|
t = self.bot.translator.t
|
||||||
|
|
||||||
|
to_equip = None if self.is_default else self.inventory[self._skin]
|
||||||
|
await self._equip_owned_skin(to_equip)
|
||||||
|
|
||||||
|
embed = discord.Embed(
|
||||||
|
colour=discord.Colour.brand_green(),
|
||||||
|
title=t(_p(
|
||||||
|
'ui:userskins|button:equip|embed:success|title',
|
||||||
|
"Skin Equipped"
|
||||||
|
)),
|
||||||
|
description=t(_p(
|
||||||
|
'ui:userskins|button:equip|embed:success|desc',
|
||||||
|
"You have equpped your **{name}** skin!"
|
||||||
|
)).format(name=self.current_skin.display_name)
|
||||||
|
)
|
||||||
|
await press.edit_original_response(embed=embed)
|
||||||
|
await self.refresh()
|
||||||
|
|
||||||
|
async def equip_button_refresh(self):
|
||||||
|
button = self.equip_button
|
||||||
|
t = self.bot.translator.t
|
||||||
|
button.label = t(_p(
|
||||||
|
'ui:userskins|button:equip|label',
|
||||||
|
"Equip Skin"
|
||||||
|
))
|
||||||
|
button.disabled = (
|
||||||
|
self.is_equipped or not self.is_owned
|
||||||
|
)
|
||||||
|
|
||||||
|
# Price button
|
||||||
|
@button(
|
||||||
|
label="PRICE_BUTTON_PLACEHOLDER",
|
||||||
|
style=ButtonStyle.green,
|
||||||
|
emoji=conf.emojis.gem,
|
||||||
|
)
|
||||||
|
async def price_button(self, press: discord.Interaction, pressed: Button):
|
||||||
|
await press.response.defer(thinking=False)
|
||||||
|
|
||||||
|
async def price_button_refresh(self):
|
||||||
|
button = self.price_button
|
||||||
|
t = self.bot.translator.t
|
||||||
|
|
||||||
|
price = self.current_skin.price
|
||||||
|
button.label = t(_p(
|
||||||
|
'ui:userskins|button:price|label',
|
||||||
|
"{price} Gems"
|
||||||
|
)).format(price=price)
|
||||||
|
if price < self.balance:
|
||||||
|
button.style = ButtonStyle.green
|
||||||
|
else:
|
||||||
|
button.style = ButtonStyle.danger
|
||||||
|
|
||||||
|
# Card Menu
|
||||||
|
@select(
|
||||||
|
cls=Select,
|
||||||
|
placeholder="CARD_MENU_PLACEHOLDER",
|
||||||
|
min_values=1, max_values=1
|
||||||
|
)
|
||||||
|
async def card_menu(self, selection: discord.Interaction, selected: Select):
|
||||||
|
await selection.response.defer(thinking=True, ephemeral=True)
|
||||||
|
self._card = int(selected.values[0])
|
||||||
|
await self.refresh(thinking=selection)
|
||||||
|
|
||||||
|
async def card_menu_refresh(self):
|
||||||
|
menu = self.card_menu
|
||||||
|
t = self.bot.translator.t
|
||||||
|
menu.placeholder = t(_p(
|
||||||
|
'ui:userskins|menu:card|placeholder',
|
||||||
|
"Select a card to preview"
|
||||||
|
))
|
||||||
|
options = []
|
||||||
|
for i, card in enumerate(self.card_classes):
|
||||||
|
option = SelectOption(
|
||||||
|
label=t(card.display_name),
|
||||||
|
value=str(i),
|
||||||
|
default=(i == self._card)
|
||||||
|
)
|
||||||
|
options.append(option)
|
||||||
|
menu.options = options
|
||||||
|
|
||||||
|
@button(emoji=conf.emojis.cancel, style=ButtonStyle.red)
|
||||||
|
async def quit_button(self, press: discord.Interaction, pressed: Button):
|
||||||
|
"""
|
||||||
|
Quit the UI.
|
||||||
|
"""
|
||||||
|
await press.response.defer()
|
||||||
|
await self.quit()
|
||||||
|
|
||||||
|
# Skin Menu
|
||||||
|
@select(
|
||||||
|
cls=Select,
|
||||||
|
placeholder="SKIN_MENU_PLACEHOLDER",
|
||||||
|
min_values=1, max_values=1
|
||||||
|
)
|
||||||
|
async def skin_menu(self, selection: discord.Interaction, selected: Select):
|
||||||
|
await selection.response.defer(thinking=True, ephemeral=True)
|
||||||
|
self._skin = selected.values[0]
|
||||||
|
await self.refresh(thinking=selection)
|
||||||
|
|
||||||
|
async def skin_menu_refresh(self):
|
||||||
|
menu = self.skin_menu
|
||||||
|
t = self.bot.translator.t
|
||||||
|
menu.placeholder = t(_p(
|
||||||
|
'ui:userskins|menu:skin|placeholder',
|
||||||
|
"Select a skin."
|
||||||
|
))
|
||||||
|
options = []
|
||||||
|
for skin in self.available.values():
|
||||||
|
option = appskin_as_option(skin)
|
||||||
|
if skin.skin_id == self._skin:
|
||||||
|
option.default = True
|
||||||
|
options.append(option)
|
||||||
|
menu.options = options
|
||||||
|
|
||||||
|
# ----- UI Flow -----
|
||||||
|
async def _render_card(self) -> discord.File:
|
||||||
|
if not self._skin:
|
||||||
|
raise ValueError("Rendering UserSkinUI before load.")
|
||||||
|
|
||||||
|
use_skin = None
|
||||||
|
if self._skin == 'default':
|
||||||
|
use_skin = await self.cog.get_default_skin()
|
||||||
|
else:
|
||||||
|
use_skin = self._skin
|
||||||
|
skin = {'base_skin_id': use_skin} if use_skin else {}
|
||||||
|
|
||||||
|
return await self.current_card.generate_sample(skin=skin)
|
||||||
|
|
||||||
|
async def make_message(self) -> MessageArgs:
|
||||||
|
if not self._skin:
|
||||||
|
raise ValueError("Rendering UserSkinUI before load.")
|
||||||
|
|
||||||
|
t = self.bot.translator.t
|
||||||
|
|
||||||
|
skin = self.current_skin
|
||||||
|
|
||||||
|
# Compute tagline
|
||||||
|
if not self.is_owned:
|
||||||
|
if skin.price <= self.balance:
|
||||||
|
tagline = t(_p(
|
||||||
|
'ui:userskins|tagline:purchase',
|
||||||
|
"Purchase this skin for {gem}{price}"
|
||||||
|
))
|
||||||
|
else:
|
||||||
|
tagline = t(_p(
|
||||||
|
'ui:userskins|tagline:insufficient',
|
||||||
|
"You don't have enough LionGems to buy this skin!"
|
||||||
|
))
|
||||||
|
elif not self.is_equipped:
|
||||||
|
tagline = t(_p(
|
||||||
|
'ui:userskins|tagline:equip',
|
||||||
|
"You already own this skin! Clock Equip to use it!"
|
||||||
|
))
|
||||||
|
else:
|
||||||
|
tagline = t(_p(
|
||||||
|
'ui:userskins|tagline:current',
|
||||||
|
"This is your current skin!"
|
||||||
|
))
|
||||||
|
|
||||||
|
tagline = tagline.format(
|
||||||
|
gem=self.bot.config.emojis.gem,
|
||||||
|
price=skin.price,
|
||||||
|
)
|
||||||
|
|
||||||
|
embed = discord.Embed(
|
||||||
|
colour=discord.Colour.orange(),
|
||||||
|
title=skin.display_name,
|
||||||
|
description=f"{skin.description}\n\n***{tagline}***"
|
||||||
|
)
|
||||||
|
embed.set_footer(
|
||||||
|
icon_url="https://cdn.discordapp.com/attachments/925799205954543636/938703943683416074/4CF1C849-D532-4DEC-B4C9-0AB11F443BAB.png",
|
||||||
|
text=t(_p(
|
||||||
|
'ui:userskins|footer',
|
||||||
|
"Current Balance: {balance} LionGems"
|
||||||
|
)).format(balance=self.balance)
|
||||||
|
)
|
||||||
|
embed.set_image(url='attachment://sample.png')
|
||||||
|
|
||||||
|
file = await self._render_card()
|
||||||
|
|
||||||
|
return MessageArgs(embed=embed, files=[file])
|
||||||
|
|
||||||
|
async def refresh_layout(self):
|
||||||
|
"""
|
||||||
|
(gift_button, price_button, action_button)
|
||||||
|
(skin_menu,),
|
||||||
|
(card_menu,),
|
||||||
|
"""
|
||||||
|
to_refresh = (
|
||||||
|
self.gift_button_refresh(),
|
||||||
|
self.price_button_refresh(),
|
||||||
|
self.purchase_button_refresh(),
|
||||||
|
self.equip_button_refresh(),
|
||||||
|
self.card_menu_refresh(),
|
||||||
|
self.skin_menu_refresh(),
|
||||||
|
)
|
||||||
|
await asyncio.gather(*to_refresh)
|
||||||
|
|
||||||
|
# Determine action button
|
||||||
|
skin = self.current_skin
|
||||||
|
if not self.is_owned:
|
||||||
|
if skin.price <= self.balance:
|
||||||
|
action = self.purchase_button
|
||||||
|
else:
|
||||||
|
action = self.gems.buy_gems_button()
|
||||||
|
else:
|
||||||
|
action = self.equip_button
|
||||||
|
|
||||||
|
self.set_layout(
|
||||||
|
(self.gift_button, self.price_button, action, self.quit_button,),
|
||||||
|
(self.skin_menu,),
|
||||||
|
(self.card_menu,),
|
||||||
|
)
|
||||||
|
|
||||||
|
async def reload(self):
|
||||||
|
"""
|
||||||
|
Load the user's skin inventory.
|
||||||
|
"""
|
||||||
|
records = await self.cog.data.UserSkin.table.select_where(
|
||||||
|
userid=self.userid
|
||||||
|
).join(
|
||||||
|
'customised_skins', using=('custom_skin_id',)
|
||||||
|
).select(
|
||||||
|
'itemid', 'custom_skin_id', 'base_skin_id', 'active'
|
||||||
|
).with_no_adapter()
|
||||||
|
active = None
|
||||||
|
inventory = {}
|
||||||
|
for record in records:
|
||||||
|
base_skin_name = self.cog.appskin_names[record['base_skin_id']]
|
||||||
|
inventory[base_skin_name] = record['itemid']
|
||||||
|
if record['active']:
|
||||||
|
active = base_skin_name
|
||||||
|
|
||||||
|
self.inventory = inventory
|
||||||
|
self.active = active
|
||||||
|
if self._skin is None:
|
||||||
|
self._skin = active or 'default'
|
||||||
|
|
||||||
|
self.balance = await self.gems.get_gem_balance(self.userid)
|
||||||
|
|||||||
Reference in New Issue
Block a user