Render alerts list functionality as embeds and make more pretty

This commit is contained in:
Emily Doherty 2024-12-03 04:13:12 -08:00
parent 96249bd608
commit ac5d794df1
3 changed files with 64 additions and 20 deletions

View File

@ -49,4 +49,10 @@ class History:
self._history.append(datum) self._history.append(datum)
return await self._process_update_triggers() return await self._process_update_triggers()
async def find_update_trigger_from_alert(self, alert: Alert) -> UpdateTrigger:
for trigger in self._update_triggers:
if trigger.alert == alert:
return trigger
raise ValueError

View File

@ -75,7 +75,7 @@ class Alert:
raise NotImplementedError raise NotImplementedError
else: else:
alert_type_str = ' '.join(self.alert_type.name.split("_")) alert_type_str = ' '.join(self.alert_type.name.split("_"))
return f"\n|\tRegion: {self.region.value.upper()}\tFlavor: {self.flavor.name.lower()}\tAlert: {alert_type_str.title()}\t|" return f"{alert_type_str.title()}"
async def _lazy_load(self, table: Table, consistent: bool = False) -> None: async def _lazy_load(self, table: Table, consistent: bool = False) -> None:
if consistent or not self._loaded: if consistent or not self._loaded:

View File

@ -4,7 +4,7 @@ from typing import Type, Dict, List
import aiohttp import aiohttp
from interactions import Extension, SlashContext, component_callback, \ from interactions import Extension, SlashContext, component_callback, \
ComponentContext, StringSelectMenu, Message, Embed ComponentContext, StringSelectMenu, Message, Embed, EmbedField
from interactions import Task, IntervalTrigger from interactions import Task, IntervalTrigger
from interactions import slash_command, listen from interactions import slash_command, listen
from interactions.api.events import Component from interactions.api.events import Component
@ -12,7 +12,7 @@ from interactions.api.events import Startup
from token_bot.controller.alerts import AlertsController from token_bot.controller.alerts import AlertsController
from token_bot.controller.users import UsersController from token_bot.controller.users import UsersController
from token_bot.history_manager.history_manager import HistoryManager from token_bot.history_manager.history_manager import HistoryManager, History
from token_bot.persistant_database.alert_category import AlertCategory from token_bot.persistant_database.alert_category import AlertCategory
from token_bot.persistant_database.alert_schema import Alert from token_bot.persistant_database.alert_schema import Alert
from token_bot.persistant_database.alert_type import AlertType from token_bot.persistant_database.alert_type import AlertType
@ -25,6 +25,18 @@ from token_bot.ui.select_menus.alert_menu import HIGH_ALERT_MENU, LOW_ALERT_MENU
from token_bot.ui.select_menus.flavor_menu import FLAVOR_MENU from token_bot.ui.select_menus.flavor_menu import FLAVOR_MENU
from token_bot.ui.select_menus.region_menu import REGION_MENU from token_bot.ui.select_menus.region_menu import REGION_MENU
#### Static Helper Functions
async def gather_alerts_by_flavor(alerts: List[Alert]) -> Dict[Flavor, List[Alert]]:
alerts_by_flavor = {}
for alert in alerts:
if alert.flavor not in alerts_by_flavor:
alerts_by_flavor[alert.flavor] = [alert]
else:
alerts_by_flavor[alert.flavor].append(alert)
return alerts_by_flavor
class Tracker(Extension): class Tracker(Extension):
def __init__(self, bot): def __init__(self, bot):
@ -54,20 +66,19 @@ class Tracker(Extension):
users_alerts[user].append(alert) users_alerts[user].append(alert)
for user in users_alerts: for user in users_alerts:
discord_user = await self.bot.fetch_user(user.user_id) discord_user = await self.bot.fetch_user(user.user_id)
alert_message = str() embeds = [Embed(
for alert in users_alerts[user]:
if alert.alert_type != AlertType.SPECIFIC_PRICE:
alert_message += f"{alert.to_human_string()}"
embed = Embed(
title="TokenBot Tracker Alert Triggered", title="TokenBot Tracker Alert Triggered",
color=0xb10000, color=0xb10000,
description=f"Hello, you requested to be sent an alert when the price of the World of Warcraft " description=f"Hello, you requested to be sent an alert when the price of the World of Warcraft "
f"token reaches a certain value.\n\n" f"token reaches a certain value.\n\n"
f"As a reminder, you can remove an alert via /remove-alert\n" f"As a reminder, you can remove an alert via ```/remove-alert```\n"
f"or you can remove all registrations via /remove-registration\n\n" f"or you can remove all registrations via ```/remove-registration```\n\n"
f"The following alerts have been triggered: {alert_message}", )]
) alerts_by_flavor = await gather_alerts_by_flavor(users_alerts[user])
await discord_user.send(embed=embed) for flavor in alerts_by_flavor:
embeds.append(await self.render_alert_flavor(alerts_by_flavor[flavor]))
await discord_user.send(embeds=embeds)
################################### ###################################
@ -95,8 +106,7 @@ class Tracker(Extension):
"Please note: \n" "Please note: \n"
"* You can only be registered with one region at a time \n" "* You can only be registered with one region at a time \n"
"* Changing your region will remove all previous alerts you have signed up for \n" "* Changing your region will remove all previous alerts you have signed up for \n"
"* You can remove all alerts and registration using /remove-registration") "* You can remove all alerts and registration using ```/remove-registration```")
await self._users.add(ctx.user.id)
await ctx.send(text, components=REGION_MENU, ephemeral=True) await ctx.send(text, components=REGION_MENU, ephemeral=True)
@slash_command() @slash_command()
@ -149,10 +159,16 @@ class Tracker(Extension):
@slash_command() @slash_command()
async def list_alerts(self, ctx: SlashContext): async def list_alerts(self, ctx: SlashContext):
alerts = await self._users.list_alerts(ctx.user.id) alerts = await self._users.list_alerts(ctx.user.id)
alerts_str = str() alerts_str = f"You have {len(alerts)} out of 25 maximum alerts registered"
for alert in alerts: embeds = [Embed(
alerts_str += f"{alert.to_human_string()}\n" title="List of TokenBot Tracker Alerts",
await ctx.send(str(alerts), ephemeral=True) color=0x0000b1,
description=alerts_str
)]
alerts_by_flavor = await gather_alerts_by_flavor(alerts)
for flavor in alerts_by_flavor:
embeds.append(await self.render_alert_flavor(alerts_by_flavor[flavor]))
await ctx.send(embeds=embeds, ephemeral=True)
################################### ###################################
# Callbacks Commands # # Callbacks Commands #
@ -264,3 +280,25 @@ class Tracker(Extension):
components=low_menu, components=low_menu,
ephemeral=True) ephemeral=True)
return await self._alert_select_menu_handler(ctx, low_menu, low_message) return await self._alert_select_menu_handler(ctx, low_menu, low_message)
async def render_alert_flavor(self, alerts: List[Alert]) -> Embed:
region = alerts[0].region
flavor = alerts[0].flavor
fields: List[EmbedField] = []
for alert in alerts:
history = await self._history_manager.get_history(alert.flavor, alert.region)
trigger = await history.find_update_trigger_from_alert(alert)
if trigger.last_trigger is not None:
alert_str = (f"Last Alerting Price Value: {format(trigger.last_trigger[1], ",")}\n"
f"Last Alerting Time: {trigger.last_trigger[0].strftime('%Y-%m-%d %H:%M:%S UTC')}\n")
else:
alert_str = "You should only be seeing this if the bot has not finished importing history at startup."
fields.append(
EmbedField(
name=f"{alert.to_human_string()} Alert", value=alert_str, inline=False))
embed = Embed(
title=f"Alerts for {region.name} {flavor.name.lower().title()}",
color=0xb10000,
fields=fields
)
return embed