feat(dreams): Add basic document viewer.
This commit is contained in:
@@ -3,6 +3,7 @@ this_package = 'modules'
|
|||||||
active = [
|
active = [
|
||||||
'.profiles',
|
'.profiles',
|
||||||
'.sysadmin',
|
'.sysadmin',
|
||||||
|
'.dreamspace',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from meta.logger import log_wrap
|
|||||||
from utils.lib import utc_now
|
from utils.lib import utc_now
|
||||||
|
|
||||||
from . import logger
|
from . import logger
|
||||||
|
from .ui.docviewer import DocumentViewer
|
||||||
|
|
||||||
|
|
||||||
class DreamCog(LionCog):
|
class DreamCog(LionCog):
|
||||||
@@ -46,8 +47,24 @@ class DreamCog(LionCog):
|
|||||||
# (Admin): View events/documents matching certain criteria
|
# (Admin): View events/documents matching certain criteria
|
||||||
|
|
||||||
# (User): View own event cards with info?
|
# (User): View own event cards with info?
|
||||||
|
# Let's make a demo viewer which lists their event cards and let's them open one via select?
|
||||||
|
# /documents -> Show a paged list of documents, select option displays the document in a viewer
|
||||||
|
@cmds.hybrid_command(
|
||||||
|
name='documents',
|
||||||
|
description="View your printer log!"
|
||||||
|
)
|
||||||
|
async def documents_cmd(self, ctx: LionContext):
|
||||||
|
profile = await self.bot.get_cog('ProfileCog').fetch_profile_discord(ctx.author)
|
||||||
|
events = await self.data.Events.fetch_where(user_id=profile.profileid)
|
||||||
|
docids = [event.document_id for event in events if event.document_id is not None]
|
||||||
|
if not docids:
|
||||||
|
await ctx.error_reply("You don't have any documents yet!")
|
||||||
|
return
|
||||||
|
|
||||||
# (User): View Specimen
|
view = DocumentViewer(self.bot, ctx.interaction.user.id, filter=(self.data.Document.document_id == docids))
|
||||||
|
await view.run(ctx.interaction)
|
||||||
|
|
||||||
|
# (User): View Specimen information
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
171
src/modules/dreamspace/ui/docviewer.py
Normal file
171
src/modules/dreamspace/ui/docviewer.py
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
import binascii
|
||||||
|
from itertools import chain
|
||||||
|
from typing import Optional
|
||||||
|
from dataclasses import dataclass
|
||||||
|
import asyncio
|
||||||
|
import datetime as dt
|
||||||
|
|
||||||
|
import discord
|
||||||
|
from discord.ui.select import select, Select, UserSelect
|
||||||
|
from discord.ui.button import button, Button
|
||||||
|
from discord.ui.text_input import TextInput
|
||||||
|
from discord.enums import ButtonStyle, TextStyle
|
||||||
|
from discord.components import SelectOption
|
||||||
|
|
||||||
|
from datamodels import DataModel
|
||||||
|
from meta import LionBot, conf
|
||||||
|
from meta.errors import ResponseTimedOut, SafeCancellation, UserInputError
|
||||||
|
from data import ORDER, Condition
|
||||||
|
|
||||||
|
from utils.ui import MessageUI, input
|
||||||
|
from utils.lib import MessageArgs, tabulate, utc_now
|
||||||
|
|
||||||
|
from .. import logger
|
||||||
|
|
||||||
|
class DocumentViewer(MessageUI):
|
||||||
|
"""
|
||||||
|
Simple pager which displays a filtered list of Documents.
|
||||||
|
"""
|
||||||
|
block_len = 5
|
||||||
|
|
||||||
|
def __init__(self, bot: LionBot, callerid: int, filter: Condition, **kwargs):
|
||||||
|
super().__init__(callerid=callerid, **kwargs)
|
||||||
|
|
||||||
|
self.bot = bot
|
||||||
|
self.data: DataModel = bot.core.datamodel
|
||||||
|
self.filter = filter
|
||||||
|
|
||||||
|
# Paging state
|
||||||
|
self._pagen = 0
|
||||||
|
self.blocks = [[]]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def page_count(self):
|
||||||
|
return len(self.blocks)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pagen(self):
|
||||||
|
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 -----
|
||||||
|
|
||||||
|
# Page 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)
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
interaction, value = await input(
|
||||||
|
press,
|
||||||
|
title="Jump to page",
|
||||||
|
question="Page number to jump to"
|
||||||
|
)
|
||||||
|
value = value.strip()
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
return
|
||||||
|
|
||||||
|
if not value.lstrip('- ').isdigit():
|
||||||
|
error = discord.Embed(title="Invalid page number, please try again!",
|
||||||
|
colour=discord.Colour.brand_red())
|
||||||
|
await interaction.response.send_message(embed=error, 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)
|
||||||
|
|
||||||
|
# Page forwards
|
||||||
|
@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()
|
||||||
|
# if self.child_viewer:
|
||||||
|
# await self.child_viewer.quit()
|
||||||
|
await self.quit()
|
||||||
|
|
||||||
|
# ----- UI Flow -----
|
||||||
|
|
||||||
|
async def make_message(self) -> MessageArgs:
|
||||||
|
files = []
|
||||||
|
embeds = []
|
||||||
|
for doc in self.current_page:
|
||||||
|
try:
|
||||||
|
imagedata = doc.to_bytes()
|
||||||
|
imagedata.seek(0)
|
||||||
|
except binascii.Error:
|
||||||
|
continue
|
||||||
|
fn = f"doc-{doc.document_id}.png"
|
||||||
|
file = discord.File(imagedata, fn)
|
||||||
|
embed = discord.Embed()
|
||||||
|
embed.set_image(url=f"attachment://{fn}")
|
||||||
|
files.append(file)
|
||||||
|
embeds.append(embed)
|
||||||
|
|
||||||
|
if not embeds:
|
||||||
|
embed = discord.Embed(description="You don't have any documents yet!")
|
||||||
|
embeds.append(embed)
|
||||||
|
|
||||||
|
print(f"FILES: {files}")
|
||||||
|
|
||||||
|
return MessageArgs(files=files, embeds=embeds)
|
||||||
|
|
||||||
|
async def refresh_layout(self):
|
||||||
|
to_refresh = (
|
||||||
|
self.jump_button_refresh(),
|
||||||
|
)
|
||||||
|
await asyncio.gather(*to_refresh)
|
||||||
|
if self.page_count > 1:
|
||||||
|
page_line = (
|
||||||
|
self.prev_button,
|
||||||
|
self.jump_button,
|
||||||
|
self.quit_button,
|
||||||
|
self.next_button,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
page_line = (self.quit_button,)
|
||||||
|
|
||||||
|
self.set_layout(page_line)
|
||||||
|
|
||||||
|
async def reload(self):
|
||||||
|
docs = await self.data.Document.fetch_where(self.filter).order_by('created_at', ORDER.DESC)
|
||||||
|
blocks = [
|
||||||
|
docs[i:i+self.block_len]
|
||||||
|
for i in range(0, len(docs), self.block_len)
|
||||||
|
]
|
||||||
|
self.blocks = blocks or [[]]
|
||||||
|
|
||||||
@@ -0,0 +1,406 @@
|
|||||||
|
from itertools import chain
|
||||||
|
from typing import Optional
|
||||||
|
from dataclasses import dataclass
|
||||||
|
import asyncio
|
||||||
|
import datetime as dt
|
||||||
|
|
||||||
|
import discord
|
||||||
|
from discord.ui.select import select, Select, UserSelect
|
||||||
|
from discord.ui.button import button, Button
|
||||||
|
from discord.ui.text_input import TextInput
|
||||||
|
from discord.enums import ButtonStyle, TextStyle
|
||||||
|
from discord.components import SelectOption
|
||||||
|
|
||||||
|
from datamodels import DataModel
|
||||||
|
from meta import LionBot, conf
|
||||||
|
from meta.errors import ResponseTimedOut, SafeCancellation, UserInputError
|
||||||
|
from data import ORDER, Condition
|
||||||
|
|
||||||
|
from utils.ui import MessageUI, input
|
||||||
|
from utils.lib import MessageArgs, tabulate, utc_now
|
||||||
|
|
||||||
|
from .. import logger
|
||||||
|
|
||||||
|
|
||||||
|
class EventsUI(MessageUI):
|
||||||
|
block_len = 10
|
||||||
|
|
||||||
|
def __init__(self, bot: LionBot, callerid: int, filter: Condition, **kwargs):
|
||||||
|
super().__init__(callerid=callerid, **kwargs)
|
||||||
|
|
||||||
|
self.bot = bot
|
||||||
|
self.data: DataModel = bot.core.datamodel
|
||||||
|
self.filter = Condition
|
||||||
|
|
||||||
|
# Paging state
|
||||||
|
self._pagen = 0
|
||||||
|
self.blocks = [[]]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def page_count(self):
|
||||||
|
return len(self.blocks)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def pagen(self):
|
||||||
|
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 -----
|
||||||
|
|
||||||
|
# Page 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)
|
||||||
|
self.pagen -= 1
|
||||||
|
await self.refresh(thinking=press)
|
||||||
|
|
||||||
|
# Jump to page
|
||||||
|
|
||||||
|
# Page forwards
|
||||||
|
@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()
|
||||||
|
# if self.child_viewer:
|
||||||
|
# await self.child_viewer.quit()
|
||||||
|
await self.quit()
|
||||||
|
|
||||||
|
# ----- UI Flow -----
|
||||||
|
|
||||||
|
async def make_message(self) -> MessageArgs:
|
||||||
|
...
|
||||||
|
|
||||||
|
async def refresh_layout(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
async def reload(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TicketListUI(MessageUI):
|
||||||
|
# Select Ticket
|
||||||
|
@select(
|
||||||
|
cls=Select,
|
||||||
|
placeholder="TICKETS_MENU_PLACEHOLDER",
|
||||||
|
min_values=1, max_values=1
|
||||||
|
)
|
||||||
|
async def tickets_menu(self, selection: discord.Interaction, selected: Select):
|
||||||
|
await selection.response.defer(thinking=True, ephemeral=True)
|
||||||
|
if selected.values:
|
||||||
|
ticketid = int(selected.values[0])
|
||||||
|
ticket = await Ticket.fetch_ticket(self.bot, ticketid)
|
||||||
|
ticketui = TicketUI(self.bot, ticket, self._callerid)
|
||||||
|
if self.child_ticket:
|
||||||
|
await self.child_ticket.quit()
|
||||||
|
self.child_ticket = ticketui
|
||||||
|
await ticketui.run(selection)
|
||||||
|
|
||||||
|
async def tickets_menu_refresh(self):
|
||||||
|
menu = self.tickets_menu
|
||||||
|
t = self.bot.translator.t
|
||||||
|
menu.placeholder = t(_p(
|
||||||
|
'ui:tickets|menu:tickets|placeholder',
|
||||||
|
"Select Ticket"
|
||||||
|
))
|
||||||
|
options = []
|
||||||
|
for ticket in self.current_page:
|
||||||
|
option = SelectOption(
|
||||||
|
label=f"Ticket #{ticket.data.guild_ticketid}",
|
||||||
|
value=str(ticket.data.ticketid)
|
||||||
|
)
|
||||||
|
options.append(option)
|
||||||
|
menu.options = options
|
||||||
|
|
||||||
|
# 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:tickets|button:jump|input:title',
|
||||||
|
"Jump to page"
|
||||||
|
)),
|
||||||
|
question=t(_p(
|
||||||
|
'ui:tickets|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:tickets|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()
|
||||||
|
if self.child_ticket:
|
||||||
|
await self.child_ticket.quit()
|
||||||
|
await self.quit()
|
||||||
|
|
||||||
|
# ----- UI Flow -----
|
||||||
|
def _format_ticket(self, ticket) -> str:
|
||||||
|
"""
|
||||||
|
Format a ticket into a single embed line.
|
||||||
|
"""
|
||||||
|
components = (
|
||||||
|
"[#{ticketid}]({link})",
|
||||||
|
"{created}",
|
||||||
|
"`{type}[{state}]`",
|
||||||
|
"<@{targetid}>",
|
||||||
|
"{content}",
|
||||||
|
)
|
||||||
|
|
||||||
|
formatstr = ' | '.join(components)
|
||||||
|
|
||||||
|
data = ticket.data
|
||||||
|
if not data.content:
|
||||||
|
content = 'No Content'
|
||||||
|
elif len(data.content) > 100:
|
||||||
|
content = data.content[:97] + '...'
|
||||||
|
else:
|
||||||
|
content = data.content
|
||||||
|
|
||||||
|
ticketstr = formatstr.format(
|
||||||
|
ticketid=data.guild_ticketid,
|
||||||
|
link=ticket.jump_url or 'https://lionbot.org',
|
||||||
|
created=discord.utils.format_dt(data.created_at, 'd'),
|
||||||
|
type=data.ticket_type.name,
|
||||||
|
state=data.ticket_state.name,
|
||||||
|
targetid=data.targetid,
|
||||||
|
content=content,
|
||||||
|
)
|
||||||
|
if data.ticket_state is TicketState.PARDONED:
|
||||||
|
ticketstr = f"~~{ticketstr}~~"
|
||||||
|
return ticketstr
|
||||||
|
|
||||||
|
async def make_message(self) -> MessageArgs:
|
||||||
|
t = self.bot.translator.t
|
||||||
|
embed = discord.Embed(
|
||||||
|
title=t(_p(
|
||||||
|
'ui:tickets|embed|title',
|
||||||
|
"Moderation Tickets in {guild}"
|
||||||
|
)).format(guild=self.guild.name),
|
||||||
|
timestamp=utc_now()
|
||||||
|
)
|
||||||
|
tickets = self.current_page
|
||||||
|
if tickets:
|
||||||
|
desc = '\n'.join(self._format_ticket(ticket) for ticket in tickets)
|
||||||
|
else:
|
||||||
|
desc = t(_p(
|
||||||
|
'ui:tickets|embed|desc:no_tickets',
|
||||||
|
"No tickets matching the given criteria!"
|
||||||
|
))
|
||||||
|
embed.description = desc
|
||||||
|
|
||||||
|
filterstr = self.filters.formatted()
|
||||||
|
if filterstr:
|
||||||
|
embed.add_field(
|
||||||
|
name=t(_p(
|
||||||
|
'ui:tickets|embed|field:filters|name',
|
||||||
|
"Filters"
|
||||||
|
)),
|
||||||
|
value=filterstr,
|
||||||
|
inline=False
|
||||||
|
)
|
||||||
|
|
||||||
|
return MessageArgs(embed=embed)
|
||||||
|
|
||||||
|
async def refresh_layout(self):
|
||||||
|
to_refresh = (
|
||||||
|
self.edit_filter_button_refresh(),
|
||||||
|
self.select_ticket_button_refresh(),
|
||||||
|
self.pardon_button_refresh(),
|
||||||
|
self.tickets_menu_refresh(),
|
||||||
|
self.filter_type_menu_refresh(),
|
||||||
|
self.filter_state_menu_refresh(),
|
||||||
|
self.filter_target_menu_refresh(),
|
||||||
|
self.jump_button_refresh(),
|
||||||
|
)
|
||||||
|
await asyncio.gather(*to_refresh)
|
||||||
|
|
||||||
|
action_line = (
|
||||||
|
self.edit_filter_button,
|
||||||
|
self.select_ticket_button,
|
||||||
|
self.pardon_button,
|
||||||
|
)
|
||||||
|
|
||||||
|
if self.page_count > 1:
|
||||||
|
page_line = (
|
||||||
|
self.prev_button,
|
||||||
|
self.jump_button,
|
||||||
|
self.quit_button,
|
||||||
|
self.next_button,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
page_line = ()
|
||||||
|
action_line = (*action_line, self.quit_button)
|
||||||
|
|
||||||
|
if self.show_filters:
|
||||||
|
menus = (
|
||||||
|
(self.filter_type_menu,),
|
||||||
|
(self.filter_state_menu,),
|
||||||
|
(self.filter_target_menu,),
|
||||||
|
)
|
||||||
|
elif self.show_tickets and self.current_page:
|
||||||
|
menus = ((self.tickets_menu,),)
|
||||||
|
else:
|
||||||
|
menus = ()
|
||||||
|
|
||||||
|
self.set_layout(
|
||||||
|
action_line,
|
||||||
|
*menus,
|
||||||
|
page_line,
|
||||||
|
)
|
||||||
|
|
||||||
|
async def reload(self):
|
||||||
|
tickets = await Ticket.fetch_tickets(
|
||||||
|
self.bot,
|
||||||
|
*self.filters.conditions(),
|
||||||
|
guildid=self.guild.id,
|
||||||
|
)
|
||||||
|
blocks = [
|
||||||
|
tickets[i:i+self.block_len]
|
||||||
|
for i in range(0, len(tickets), self.block_len)
|
||||||
|
]
|
||||||
|
self.blocks = blocks or [[]]
|
||||||
|
|
||||||
|
|
||||||
|
class TicketUI(MessageUI):
|
||||||
|
def __init__(self, bot: LionBot, ticket: Ticket, callerid: int, **kwargs):
|
||||||
|
super().__init__(callerid=callerid, **kwargs)
|
||||||
|
|
||||||
|
self.bot = bot
|
||||||
|
self.ticket = ticket
|
||||||
|
|
||||||
|
# ----- API -----
|
||||||
|
|
||||||
|
# ----- UI Components -----
|
||||||
|
# Pardon Ticket
|
||||||
|
@button(
|
||||||
|
label="PARDON_BUTTON_PLACEHOLDER",
|
||||||
|
style=ButtonStyle.red
|
||||||
|
)
|
||||||
|
async def pardon_button(self, press: discord.Interaction, pressed: Button):
|
||||||
|
t = self.bot.translator.t
|
||||||
|
|
||||||
|
modal_title = t(_p(
|
||||||
|
'ui:ticket|button:pardon|modal:reason|title',
|
||||||
|
"Pardon Moderation Ticket"
|
||||||
|
))
|
||||||
|
input_field = TextInput(
|
||||||
|
label=t(_p(
|
||||||
|
'ui:ticket|button:pardon|modal:reason|field|label',
|
||||||
|
"Why are you pardoning this ticket?"
|
||||||
|
)),
|
||||||
|
style=TextStyle.long,
|
||||||
|
min_length=0,
|
||||||
|
max_length=1024,
|
||||||
|
)
|
||||||
|
try:
|
||||||
|
interaction, reason = await input(
|
||||||
|
press, modal_title, field=input_field, timeout=300,
|
||||||
|
)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
raise ResponseTimedOut
|
||||||
|
|
||||||
|
await interaction.response.defer(thinking=True, ephemeral=True)
|
||||||
|
|
||||||
|
await self.ticket.pardon(modid=press.user.id, reason=reason)
|
||||||
|
await self.refresh(thinking=interaction)
|
||||||
|
|
||||||
|
|
||||||
|
async def pardon_button_refresh(self):
|
||||||
|
button = self.pardon_button
|
||||||
|
t = self.bot.translator.t
|
||||||
|
button.label = t(_p(
|
||||||
|
'ui:ticket|button:pardon|label',
|
||||||
|
"Pardon"
|
||||||
|
))
|
||||||
|
button.disabled = (self.ticket.data.ticket_state is TicketState.PARDONED)
|
||||||
|
|
||||||
|
# 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:
|
||||||
|
return await self.ticket.make_message()
|
||||||
|
|
||||||
|
async def refresh_layout(self):
|
||||||
|
await self.pardon_button_refresh()
|
||||||
|
self.set_layout(
|
||||||
|
(self.pardon_button, self.quit_button,)
|
||||||
|
)
|
||||||
|
|
||||||
|
async def reload(self):
|
||||||
|
await self.ticket.data.refresh()
|
||||||
|
|||||||
0
src/modules/dreamspace/ui/specimen.py
Normal file
0
src/modules/dreamspace/ui/specimen.py
Normal file
@@ -44,6 +44,7 @@ class TwitchLinkStatic(LeoUI):
|
|||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
super().__init__(**kwargs)
|
super().__init__(**kwargs)
|
||||||
self._embed: Optional[discord.Embed] = None
|
self._embed: Optional[discord.Embed] = None
|
||||||
|
print("INITIALISATION")
|
||||||
|
|
||||||
async def interaction_check(self, interaction: discord.Interaction):
|
async def interaction_check(self, interaction: discord.Interaction):
|
||||||
return True
|
return True
|
||||||
@@ -76,6 +77,7 @@ class TwitchLinkStatic(LeoUI):
|
|||||||
async def button_linker(self, interaction: discord.Interaction, btn: Button):
|
async def button_linker(self, interaction: discord.Interaction, btn: Button):
|
||||||
# Here we just reply to the interaction with the AuthFlow UI
|
# Here we just reply to the interaction with the AuthFlow UI
|
||||||
# TODO
|
# TODO
|
||||||
|
print("RESPONDING")
|
||||||
flowui = TwitchLinkFlow(interaction.client, interaction.user, callerid=interaction.user.id)
|
flowui = TwitchLinkFlow(interaction.client, interaction.user, callerid=interaction.user.id)
|
||||||
await flowui.run(interaction)
|
await flowui.run(interaction)
|
||||||
await flowui.wait()
|
await flowui.wait()
|
||||||
|
|||||||
Reference in New Issue
Block a user