Files
croccybot/src/modules/premium/ui/transactions.py

199 lines
6.3 KiB
Python

from typing import Optional
import asyncio
import datetime as dt
import discord
from discord.ui.button import button, Button, ButtonStyle
from meta import LionBot, conf
from data import ORDER
from utils.ui import MessageUI, input
from utils.lib import MessageArgs, tabulate
from .. import babel, logger
from ..data import PremiumData
_p = babel._p
class TransactionList(MessageUI):
block_len = 5
def __init__(self, bot: LionBot, userid: int, **kwargs):
super().__init__(**kwargs)
self.bot = bot
self.userid = userid
self._pagen = 0
self.blocks: list[list[PremiumData.GemTransaction]] = [[]]
@property
def page_count(self):
return len(self.blocks)
@property
def pagen(self):
self._pagen = self._pagen % self.page_count
return self._pagen
@pagen.setter
def pagen(self, value):
self._pagen = value % self.page_count
@property
def current_page(self):
return self.blocks[self.pagen]
# ----- UI Components -----
# Backwards
@button(emoji=conf.emojis.backward, style=ButtonStyle.grey)
async def prev_button(self, press: discord.Interaction, pressed: Button):
await press.response.defer(thinking=True, ephemeral=True)
self.pagen -= 1
await self.refresh(thinking=press)
# Jump to page
@button(label="JUMP_PLACEHOLDER", style=ButtonStyle.blurple)
async def jump_button(self, press: discord.Interaction, pressed: Button):
"""
Jump-to-page button.
Loads a page-switch dialogue.
"""
t = self.bot.translator.t
try:
interaction, value = await input(
press,
title=t(_p(
'ui:transactions|button:jump|input:title',
"Jump to page"
)),
question=t(_p(
'ui:transactions|button:jump|input:question',
"Page number to jump to"
))
)
value = value.strip()
except asyncio.TimeoutError:
return
if not value.lstrip('- ').isdigit():
error_embed = discord.Embed(
title=t(_p(
'ui:transactions|button:jump|error:invalid_page',
"Invalid page number, please try again!"
)),
colour=discord.Colour.brand_red()
)
await interaction.response.send_message(embed=error_embed, ephemeral=True)
else:
await interaction.response.defer(thinking=True)
pagen = int(value.lstrip('- '))
if value.startswith('-'):
pagen = -1 * pagen
elif pagen > 0:
pagen = pagen - 1
self.pagen = pagen
await self.refresh(thinking=interaction)
async def jump_button_refresh(self):
component = self.jump_button
component.label = f"{self.pagen + 1}/{self.page_count}"
component.disabled = (self.page_count <= 1)
# Forward
@button(emoji=conf.emojis.forward, style=ButtonStyle.grey)
async def next_button(self, press: discord.Interaction, pressed: Button):
await press.response.defer(thinking=True)
self.pagen += 1
await self.refresh(thinking=press)
# Quit
@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()
# ----- UI Flow -----
async def make_message(self) -> MessageArgs:
t = self.bot.translator.t
title = t(_p(
'ui:transactions|embed|title',
"Gem Transactions for user `{userid}`"
)).format(userid=self.userid)
rows = self.current_page
if rows:
embed = discord.Embed(
colour=discord.Colour.orange(),
title=title,
description=t(_p(
'ui:transactions|embed|desc:balance',
"User {target} has a LionGem balance of {gem}**{balance}**"
)).format(
gem=self.bot.config.emojis.gem,
target=f"<@{self.userid}>",
balance=await (self.bot.get_cog('PremiumCog')).get_gem_balance(self.userid),
)
)
for row in rows:
name = f"Transaction #{row.transactionid}"
table_rows = (
('timestamp', discord.utils.format_dt(row._timestamp)),
('type', row.transaction_type.name),
('amount', str(row.amount)),
('actor', f"<@{row.actorid}>"),
('from', f"`{row.from_account}`" if row.from_account else 'None'),
('to', f"`{row.to_account}`" if row.to_account else 'None'),
('reference', str(row.reference)),
)
table = '\n'.join(tabulate(*table_rows))
embed.add_field(
name=name,
value=f"{row.description}\n{table}",
inline=False
)
else:
embed = discord.Embed(
colour=discord.Colour.brand_red(),
description = t(_p(
'ui:transactions|embed|desc:no_transactions',
"This user has no related gem transactions!"
))
)
return MessageArgs(embed=embed)
async def refresh_layout(self):
to_refresh = (
self.jump_button_refresh(),
)
await asyncio.gather(*to_refresh)
if self.page_count > 1:
self.set_layout(
(self.prev_button, self.jump_button, self.quit_button, self.next_button),
)
else:
self.set_layout(
(self.quit_button,)
)
async def reload(self):
model = PremiumData.GemTransaction
rows = await model.fetch_where(
(model.from_account == self.userid) | (model.to_account == self.userid)
).order_by('_timestamp', ORDER.DESC)
blocks = [
rows[i:i+self.block_len]
for i in range(0, len(rows), self.block_len)
]
self.blocks = blocks or [[]]