From 34badf17eb5353e0103f046b4ffe19d8fcf60817 Mon Sep 17 00:00:00 2001 From: Emily Doherty Date: Sun, 8 Dec 2024 17:07:26 -0800 Subject: [PATCH] Once and for all reformat. Will be using black code formatter --- requirements.txt | 1 + token_bot/controller/alerts.py | 6 +- token_bot/controller/users.py | 6 +- token_bot/core.py | 4 +- token_bot/history_manager/history.py | 18 +- token_bot/history_manager/history_manager.py | 33 +- token_bot/history_manager/update_trigger.py | 33 +- token_bot/persistant_database/__init__.py | 1 - .../persistant_database/alert_category.py | 6 +- token_bot/persistant_database/alert_schema.py | 41 ++- token_bot/persistant_database/alert_type.py | 3 +- token_bot/persistant_database/database.py | 5 +- token_bot/persistant_database/user_schema.py | 45 +-- token_bot/token_bot.py | 10 +- token_bot/token_database/database.py | 8 +- token_bot/token_database/flavor.py | 1 - token_bot/token_database/region.py | 9 +- token_bot/tracker.py | 303 ++++++++++-------- token_bot/ui/action_row/tracker.py | 5 +- token_bot/ui/buttons/tracker/add.py | 44 +-- .../ui/buttons/tracker/alert_category.py | 12 +- token_bot/ui/buttons/tracker/registration.py | 14 +- token_bot/ui/select_menus/alert_menu.py | 24 +- token_bot/ui/select_menus/flavor_menu.py | 10 +- token_bot/ui/select_menus/region_menu.py | 12 +- 25 files changed, 359 insertions(+), 295 deletions(-) diff --git a/requirements.txt b/requirements.txt index d9603f1..8a638db 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,6 +3,7 @@ aiohttp==3.9.5 aiosignal==1.3.1 anyio==4.4.0 attrs==23.2.0 +black==24.10.0 certifi==2024.7.4 croniter==2.0.5 discord-py-interactions==5.12.1 diff --git a/token_bot/controller/alerts.py b/token_bot/controller/alerts.py index 1626e55..2865c9b 100644 --- a/token_bot/controller/alerts.py +++ b/token_bot/controller/alerts.py @@ -11,7 +11,9 @@ from token_bot.persistant_database import database as pdb class AlertsController: def __init__(self, session: aiohttp.ClientSession): self._pdb: pdb.Database = pdb.Database(session) - self.table = aiodynamo.client.Table = self._pdb.client.table(os.getenv('ALERTS_TABLE')) + self.table = aiodynamo.client.Table = self._pdb.client.table( + os.getenv("ALERTS_TABLE") + ) @staticmethod def _user_to_obj(user: int | User) -> User: @@ -39,5 +41,3 @@ class AlertsController: alert = self._alert_to_obj(alert) user = self._user_to_obj(user) await alert.remove_user(self.table, user) - - diff --git a/token_bot/controller/users.py b/token_bot/controller/users.py index 4057ced..b0e4027 100644 --- a/token_bot/controller/users.py +++ b/token_bot/controller/users.py @@ -11,8 +11,9 @@ from token_bot.persistant_database.user_schema import User class UsersController: def __init__(self, session: aiohttp.ClientSession): self._pdb: pdb.Database = pdb.Database(session) - self.table: aiodynamo.client.Table = self._pdb.client.table(os.getenv('USERS_TABLE')) - + self.table: aiodynamo.client.Table = self._pdb.client.table( + os.getenv("USERS_TABLE") + ) @staticmethod def _user_to_obj(user: int | User) -> User: @@ -67,4 +68,3 @@ class UsersController: await user.get(self.table) user.subscribed_alerts.remove(alert) await user.put(self.table) - diff --git a/token_bot/core.py b/token_bot/core.py index 7935e1c..b5537c9 100644 --- a/token_bot/core.py +++ b/token_bot/core.py @@ -18,8 +18,8 @@ class Core(Extension): @listen(Startup) async def on_start(self): - self.bot.logger.log(logging.INFO,"TokenBot Core ready") - self.bot.logger.log(logging.INFO,f"This is bot version {VERSION}") + self.bot.logger.log(logging.INFO, "TokenBot Core ready") + self.bot.logger.log(logging.INFO, f"This is bot version {VERSION}") self._tdb = tdb.Database(aiohttp.ClientSession()) @slash_command() diff --git a/token_bot/history_manager/history.py b/token_bot/history_manager/history.py index 8769ece..88e29e6 100644 --- a/token_bot/history_manager/history.py +++ b/token_bot/history_manager/history.py @@ -9,14 +9,16 @@ from token_bot.token_database.region import Region class History: def __init__(self, flavor: Flavor, region: Region): - self._flavor : Flavor = flavor - self._region : Region = region - self._history : List[Tuple[datetime, int]] = [] - self._last_price_movement : int = 0 - self._latest_price_datum : Tuple[datetime.datetime, int] | None = None - self._update_triggers : List[UpdateTrigger] = [] + self._flavor: Flavor = flavor + self._region: Region = region + self._history: List[Tuple[datetime, int]] = [] + self._last_price_movement: int = 0 + self._latest_price_datum: Tuple[datetime.datetime, int] | None = None + self._update_triggers: List[UpdateTrigger] = [] for alert_type in AlertType: - self._update_triggers.append(UpdateTrigger(Alert(alert_type, flavor, self._region))) + self._update_triggers.append( + UpdateTrigger(Alert(alert_type, flavor, self._region)) + ) @property def flavor(self) -> Flavor: @@ -58,5 +60,3 @@ class History: if trigger.alert == alert: return trigger raise ValueError - - diff --git a/token_bot/history_manager/history_manager.py b/token_bot/history_manager/history_manager.py index 5226ce2..9e5804f 100644 --- a/token_bot/history_manager/history_manager.py +++ b/token_bot/history_manager/history_manager.py @@ -9,23 +9,31 @@ from token_bot.token_database.region import Region class HistoryManager: - HIGH_FIDELITY_PERIOD = '72h' + HIGH_FIDELITY_PERIOD = "72h" + def __init__(self, token_db: tdb.Database): - self._history : Dict[Flavor, Dict[Region, History]] = {} - self._tdb : tdb.Database = token_db + self._history: Dict[Flavor, Dict[Region, History]] = {} + self._tdb: tdb.Database = token_db for flavor in Flavor: self._history[flavor] = {} for region in Region: self._history[flavor][Region(region)] = History(flavor, Region(region)) - - async def _retrieve_data(self, flavor: Flavor, region: Region) -> List[Tuple[datetime.datetime, int]]: - high_fidelity_time = datetime.datetime.now(tz=datetime.UTC) - datetime.timedelta(hours=72) + async def _retrieve_data( + self, flavor: Flavor, region: Region + ) -> List[Tuple[datetime.datetime, int]]: + high_fidelity_time = datetime.datetime.now( + tz=datetime.UTC + ) - datetime.timedelta(hours=72) all_history = await self._tdb.history(flavor, region) - high_fidelity_history = await self._tdb.history(flavor, region, self.HIGH_FIDELITY_PERIOD) + high_fidelity_history = await self._tdb.history( + flavor, region, self.HIGH_FIDELITY_PERIOD + ) final_response = [] - def _convert_to_datetime(data: Tuple[str, int]) -> Tuple[datetime.datetime, int]: + def _convert_to_datetime( + data: Tuple[str, int] + ) -> Tuple[datetime.datetime, int]: return datetime.datetime.fromisoformat(data[0]), data[1] for data_point in all_history: @@ -33,11 +41,12 @@ class HistoryManager: if datetime_tuple[0] < high_fidelity_time: final_response.append(datetime_tuple) - final_response.extend(_convert_to_datetime(data_point) for data_point in high_fidelity_history) + final_response.extend( + _convert_to_datetime(data_point) for data_point in high_fidelity_history + ) return final_response - async def load_data(self): for flavor in Flavor: for r in Region: @@ -48,19 +57,17 @@ class HistoryManager: await history.add_price(item) self._history[flavor][region] = history - async def update_data(self, flavor: Flavor, region: Region) -> List[Alert]: history = self._history[flavor][region] current_price_data = await self._tdb.current(flavor) current_region_data = current_price_data[region.value.lower()] datum = ( datetime.datetime.fromisoformat(current_region_data[0]), - current_region_data[1] + current_region_data[1], ) if datum != history.last_price_datum: return await history.add_price(datum) return [] - def get_history(self, flavor, region) -> History: return self._history[flavor][region] diff --git a/token_bot/history_manager/update_trigger.py b/token_bot/history_manager/update_trigger.py index e6db9e4..c187eea 100644 --- a/token_bot/history_manager/update_trigger.py +++ b/token_bot/history_manager/update_trigger.py @@ -8,10 +8,10 @@ from token_bot.token_database.flavor import Flavor class UpdateTrigger: def __init__(self, alert: Alert): - self._alert : Alert = alert - self._last_trigger : Tuple[datetime.datetime, int] | None = None + self._alert: Alert = alert + self._last_trigger: Tuple[datetime.datetime, int] | None = None self._last_alerting: Tuple[datetime.datetime, int] | None = None - self._squelched : bool = False + self._squelched: bool = False @property def alert(self) -> Alert: @@ -29,20 +29,35 @@ class UpdateTrigger: def squelched(self): return self._squelched - def _find_next_trigger(self, comparison_operator: Callable, starting_point: datetime.datetime, history: List[Tuple[datetime.datetime, int]]): - candidate_datum : Tuple[datetime.datetime, int] | None = None + def _find_next_trigger( + self, + comparison_operator: Callable, + starting_point: datetime.datetime, + history: List[Tuple[datetime.datetime, int]], + ): + candidate_datum: Tuple[datetime.datetime, int] | None = None for datum in history: if datum[0] > starting_point and datum != history[-1]: - if candidate_datum is None or comparison_operator(datum[1], candidate_datum[1]): + if candidate_datum is None or comparison_operator( + datum[1], candidate_datum[1] + ): candidate_datum = datum self._last_trigger = candidate_datum - def check_and_update(self, new_datum: Tuple[datetime.datetime, int], history: List[Tuple[datetime.datetime, int]]) -> bool: + def check_and_update( + self, + new_datum: Tuple[datetime.datetime, int], + history: List[Tuple[datetime.datetime, int]], + ) -> bool: match self.alert.flavor: case Flavor.RETAIL: - start_time = datetime.datetime.fromisoformat('2020-11-15 00:00:01.000000000+00:00') + start_time = datetime.datetime.fromisoformat( + "2020-11-15 00:00:01.000000000+00:00" + ) case Flavor.CLASSIC: - start_time = datetime.datetime.fromisoformat('2023-05-23 00:00:01.000000000+00:00') + start_time = datetime.datetime.fromisoformat( + "2023-05-23 00:00:01.000000000+00:00" + ) case _: raise NotImplementedError diff --git a/token_bot/persistant_database/__init__.py b/token_bot/persistant_database/__init__.py index 520dd6c..d2b92f3 100644 --- a/token_bot/persistant_database/__init__.py +++ b/token_bot/persistant_database/__init__.py @@ -1,4 +1,3 @@ from .alert_type import AlertType from .user_schema import User from .alert_schema import Alert - diff --git a/token_bot/persistant_database/alert_category.py b/token_bot/persistant_database/alert_category.py index da2986c..b5c502c 100644 --- a/token_bot/persistant_database/alert_category.py +++ b/token_bot/persistant_database/alert_category.py @@ -7,7 +7,9 @@ class AlertCategory(Enum): CUSTOM = 3 @staticmethod - def from_str(category: str): # It gets mad when I use the Type[AlertCategory] as a type hint + def from_str( + category: str, + ): # It gets mad when I use the Type[AlertCategory] as a type hint match category: case "high_alert_button": return AlertCategory.HIGH @@ -16,4 +18,4 @@ class AlertCategory(Enum): case "sp_add_button": return AlertCategory.CUSTOM case _: - return AlertCategory[category.upper()] \ No newline at end of file + return AlertCategory[category.upper()] diff --git a/token_bot/persistant_database/alert_schema.py b/token_bot/persistant_database/alert_schema.py index adb3de9..8c20785 100644 --- a/token_bot/persistant_database/alert_schema.py +++ b/token_bot/persistant_database/alert_schema.py @@ -11,7 +11,9 @@ import token_bot.persistant_database as pdb class Alert: - def __init__(self, alert: pdb.AlertType, flavor: Flavor, region: Region, price: int = 0) -> None: + def __init__( + self, alert: pdb.AlertType, flavor: Flavor, region: Region, price: int = 0 + ) -> None: # AlertType is the Primary Key self.alert_type: pdb.AlertType = alert # Flavor (Retail, Classic) is the Sort Key @@ -22,18 +24,18 @@ class Alert: self.users: List[pdb.User] = [] @classmethod - def from_item(cls, primary_key: int, sort_key: str, users: List[int]) -> 'Alert': + def from_item(cls, primary_key: int, sort_key: str, users: List[int]) -> "Alert": alert_type = pdb.AlertType(primary_key) - flavor_repr, region_repr, price_repr = sort_key.split('-') + flavor_repr, region_repr, price_repr = sort_key.split("-") flavor = Flavor(int(flavor_repr)) region = Region(region_repr) price = int(price_repr) return cls(alert_type, flavor, region, price) @classmethod - def from_str(cls, string_trinity: str) -> 'Alert': - alert_repr, flavor_repr, region_repr, price_repr = string_trinity.split('-') - if len(string_trinity.split('-')) != 4: + def from_str(cls, string_trinity: str) -> "Alert": + alert_repr, flavor_repr, region_repr, price_repr = string_trinity.split("-") + if len(string_trinity.split("-")) != 4: raise ValueError alert = pdb.AlertType(int(alert_repr)) flavor = Flavor(int(flavor_repr)) @@ -61,20 +63,24 @@ class Alert: def key(self) -> dict[str, str | int]: return { self.primary_key_name: self.primary_key, - self.sort_key_name: self.sort_key + self.sort_key_name: self.sort_key, } def __str__(self): return f"{self.alert_type.value}-{self.flavor.value}-{self.region.value}-{self.price}" def __eq__(self, other): - return self.alert_type == other.alert_type and self.flavor == other.flavor and self.price == other.price + return ( + self.alert_type == other.alert_type + and self.flavor == other.flavor + and self.price == other.price + ) def to_human_string(self): if self.alert_type == AlertType.SPECIFIC_PRICE: raise NotImplementedError else: - alert_type_str = ' '.join(self.alert_type.name.split("_")) + alert_type_str = " ".join(self.alert_type.name.split("_")) return f"{alert_type_str.title()}" async def _lazy_load(self, table: Table, consistent: bool = False) -> None: @@ -95,19 +101,16 @@ class Alert: item={ self.primary_key_name: self.primary_key, self.sort_key_name: self.sort_key, - 'users': user_ids + "users": user_ids, } ) async def get(self, table: Table, consistent: bool = False) -> bool: try: - response = await table.get_item( - key=self.key, - consistent_read=consistent - ) + response = await table.get_item(key=self.key, consistent_read=consistent) except ItemNotFound: return False - self.users = [pdb.User(int(user_id)) for user_id in response['users']] + self.users = [pdb.User(int(user_id)) for user_id in response["users"]] self._loaded = True return True @@ -116,13 +119,17 @@ class Alert: return self.users - async def add_user(self, table: Table, user: pdb.User, consistent: bool = False) -> None: + async def add_user( + self, table: Table, user: pdb.User, consistent: bool = False + ) -> None: await self._lazy_load(table, consistent=consistent) if user not in self.users: await self._append_user(table=table, user=user) - async def remove_user(self, table: Table, user: pdb.User, consistent: bool = True) -> None: + async def remove_user( + self, table: Table, user: pdb.User, consistent: bool = True + ) -> None: await self._lazy_load(table, consistent=consistent) if user in self.users: diff --git a/token_bot/persistant_database/alert_type.py b/token_bot/persistant_database/alert_type.py index 2f9f39f..ab5cd5f 100644 --- a/token_bot/persistant_database/alert_type.py +++ b/token_bot/persistant_database/alert_type.py @@ -1,5 +1,6 @@ from enum import Enum + class AlertType(Enum): ALL_TIME_HIGH = 1 ALL_TIME_LOW = 2 @@ -37,4 +38,4 @@ class AlertType(Enum): case "All Time Low": return AlertType.ALL_TIME_LOW case _: - return AlertType.SPECIFIC_PRICE \ No newline at end of file + return AlertType.SPECIFIC_PRICE diff --git a/token_bot/persistant_database/database.py b/token_bot/persistant_database/database.py index f516d19..ca2e3e1 100644 --- a/token_bot/persistant_database/database.py +++ b/token_bot/persistant_database/database.py @@ -8,5 +8,6 @@ from aiodynamo.http.aiohttp import AIOHTTP class Database: def __init__(self, session: aiohttp.ClientSession): - self.client = Client(AIOHTTP(session), Credentials.auto(), os.getenv('AWS_REGION')) - + self.client = Client( + AIOHTTP(session), Credentials.auto(), os.getenv("AWS_REGION") + ) diff --git a/token_bot/persistant_database/user_schema.py b/token_bot/persistant_database/user_schema.py index 80399ee..c07e8cb 100644 --- a/token_bot/persistant_database/user_schema.py +++ b/token_bot/persistant_database/user_schema.py @@ -8,7 +8,12 @@ from token_bot.token_database.region import Region class User: - def __init__(self, user_id: int, region: Region = None, subscribed_alerts: List['pdb.Alert'] = None) -> None: + def __init__( + self, + user_id: int, + region: Region = None, + subscribed_alerts: List["pdb.Alert"] = None, + ) -> None: self.user_id: int = user_id self._loaded: bool = False self.region: Region = region @@ -21,7 +26,9 @@ class User: return hash(self.user_id) @classmethod - def from_item(cls, primary_key: int, region: Region, subscribed_alerts: List[str]) -> 'User': + def from_item( + cls, primary_key: int, region: Region, subscribed_alerts: List[str] + ) -> "User": alerts = [pdb.Alert.from_str(alert_str) for alert_str in subscribed_alerts] return cls(primary_key, region, alerts) @@ -31,17 +38,18 @@ class User: @property def primary_key_name(self) -> str: - return 'user_id' + return "user_id" @property def key(self) -> Dict[str, str]: - return { - self.primary_key_name: self.primary_key - } - + return {self.primary_key_name: self.primary_key} def _subscribed_alerts_as_trinity_list(self) -> List[str]: - return [str(alert) for alert in self.subscribed_alerts] if self.subscribed_alerts else [] + return ( + [str(alert) for alert in self.subscribed_alerts] + if self.subscribed_alerts + else [] + ) async def _lazy_load(self, table: Table, consistent: bool = False) -> None: if consistent or not self._loaded: @@ -51,8 +59,8 @@ class User: await table.put_item( item={ self.primary_key_name: self.primary_key, - 'region': self.region, - 'subscribed_alerts': self._subscribed_alerts_as_trinity_list() + "region": self.region, + "subscribed_alerts": self._subscribed_alerts_as_trinity_list(), } ) @@ -65,26 +73,27 @@ class User: async def get(self, table: Table, consistent: bool = False) -> bool: try: - response = await table.get_item( - key=self.key, - consistent_read=consistent - ) + response = await table.get_item(key=self.key, consistent_read=consistent) except ItemNotFound: return False self.subscribed_alerts = [] - for string_trinity in response['subscribed_alerts']: + for string_trinity in response["subscribed_alerts"]: self.subscribed_alerts.append(pdb.Alert.from_str(string_trinity)) - self.region = Region(response['region']) + self.region = Region(response["region"]) return True - async def add_alert(self, table: Table, alert: 'pdb.Alert', consistent: bool = False) -> None: + async def add_alert( + self, table: Table, alert: "pdb.Alert", consistent: bool = False + ) -> None: await self._lazy_load(table, consistent=consistent) if alert not in self.subscribed_alerts: self.subscribed_alerts.append(alert) await self.put(table) - async def remove_alert(self, table: Table, alert: 'pdb.Alert', consistent: bool = True) -> None: + async def remove_alert( + self, table: Table, alert: "pdb.Alert", consistent: bool = True + ) -> None: await self._lazy_load(table, consistent=consistent) if alert in self.subscribed_alerts: self.subscribed_alerts.remove(alert) diff --git a/token_bot/token_bot.py b/token_bot/token_bot.py index ca684c5..8aa1037 100644 --- a/token_bot/token_bot.py +++ b/token_bot/token_bot.py @@ -10,16 +10,12 @@ class TokenBot: load_dotenv() print("#### WoW Token Bot Startup ####") logging.basicConfig( - format='%(asctime)s.%(msecs)03d %(levelname)s %(module)s - %(funcName)s: %(message)s', - datefmt='%Y-%m-%d %H:%M:%S', + format="%(asctime)s.%(msecs)03d %(levelname)s %(module)s - %(funcName)s: %(message)s", + datefmt="%Y-%m-%d %H:%M:%S", ) log = logging.getLogger("TokenBotLogger") log.setLevel(logging.INFO) - self.bot = Client( - intents=Intents.DEFAULT, - asyncio_debug=True, - logger=log - ) + self.bot = Client(intents=Intents.DEFAULT, asyncio_debug=True, logger=log) def run(self): self.bot.load_extension("token_bot.core") diff --git a/token_bot/token_database/database.py b/token_bot/token_database/database.py index 98efbf1..77b4702 100644 --- a/token_bot/token_database/database.py +++ b/token_bot/token_database/database.py @@ -34,7 +34,9 @@ class Database: raise TokenHttpException(resp.status) async def current(self, flavor: Flavor) -> dict: - return await self._get_data(f'current/{flavor.name.lower()}.json') + return await self._get_data(f"current/{flavor.name.lower()}.json") - async def history(self, flavor: Flavor, region: Region, relative_time: str = 'all'): - return await self._get_data(f'relative/{flavor.name.lower()}/{region.value.lower()}/{relative_time}.json') \ No newline at end of file + async def history(self, flavor: Flavor, region: Region, relative_time: str = "all"): + return await self._get_data( + f"relative/{flavor.name.lower()}/{region.value.lower()}/{relative_time}.json" + ) diff --git a/token_bot/token_database/flavor.py b/token_bot/token_database/flavor.py index 7782617..4cc5c79 100644 --- a/token_bot/token_database/flavor.py +++ b/token_bot/token_database/flavor.py @@ -4,4 +4,3 @@ from enum import Enum class Flavor(Enum): RETAIL = 1 CLASSIC = 2 - diff --git a/token_bot/token_database/region.py b/token_bot/token_database/region.py index 6e91929..b3ab760 100644 --- a/token_bot/token_database/region.py +++ b/token_bot/token_database/region.py @@ -1,7 +1,8 @@ from enum import Enum + class Region(str, Enum): - US = 'us' - EU = 'eu' - KR = 'kr' - TW = 'tw' + US = "us" + EU = "eu" + KR = "kr" + TW = "tw" diff --git a/token_bot/tracker.py b/token_bot/tracker.py index 41f8dca..d1ef1d3 100644 --- a/token_bot/tracker.py +++ b/token_bot/tracker.py @@ -5,8 +5,19 @@ import logging from typing import Type, Dict, List import aiohttp -from interactions import Extension, SlashContext, component_callback, \ - ComponentContext, StringSelectMenu, Message, Embed, EmbedField, is_owner, check, StringSelectOption +from interactions import ( + Extension, + SlashContext, + component_callback, + ComponentContext, + StringSelectMenu, + Message, + Embed, + EmbedField, + is_owner, + check, + StringSelectOption, +) from interactions import Task, IntervalTrigger from interactions import slash_command, listen from interactions.api.events import Component @@ -29,6 +40,7 @@ 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: @@ -39,7 +51,6 @@ async def gather_alerts_by_flavor(alerts: List[Alert]) -> Dict[Flavor, List[Aler return alerts_by_flavor - class Tracker(Extension): def __init__(self, bot): self._users: UsersController | None = None @@ -47,7 +58,6 @@ class Tracker(Extension): self._tdb: tdb.Database | None = None self._history_manager: HistoryManager | None = None - ################################### # Task Functions # ################################### @@ -68,21 +78,24 @@ class Tracker(Extension): users_alerts[user].append(alert) for user in users_alerts: discord_user = await self.bot.fetch_user(user.user_id) - embeds = [Embed( - title="TokenBot Tracker Alert Triggered", - color=0xb10000, - 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"As a reminder, you can remove an alert via ```/remove-alert```\n" - f"or you can remove all registrations via ```/remove-registration```\n\n" - )] + embeds = [ + Embed( + title="TokenBot Tracker Alert Triggered", + color=0xB10000, + 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"As a reminder, you can remove an alert via ```/remove-alert```\n" + f"or you can remove all registrations via ```/remove-registration```\n\n", + ) + ] alerts_by_flavor = await gather_alerts_by_flavor(users_alerts[user]) for flavor in alerts_by_flavor: - embeds.append(await self.render_alert_flavor(alerts_by_flavor[flavor], user=user)) + embeds.append( + await self.render_alert_flavor(alerts_by_flavor[flavor], user=user) + ) await discord_user.send(embeds=embeds) - ################################### # Slash Commands # ################################### @@ -97,28 +110,30 @@ class Tracker(Extension): self.bot.logger.log(logging.INFO, "TokenBot Tracker: Initialized") self.bot.logger.log(logging.INFO, "TokenBot Tracker: Loading Historical Data") await self._history_manager.load_data() - self.bot.logger.log(logging.INFO, "TokenBot Tracker: Loading Historical Data Finished") + self.bot.logger.log( + logging.INFO, "TokenBot Tracker: Loading Historical Data Finished" + ) self.bot.logger.log(logging.INFO, "TokenBot Tracker: Started") self.update_data.start() - @slash_command( name="register", - description="Register with TokenBot for alerts on token price changes." + description="Register with TokenBot for alerts on token price changes.", ) async def register(self, ctx: SlashContext): - text = ("## Select a region to register with \n\n" - "Please note: \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" - "* You can remove all alerts and registration using ```/remove-registration```") + text = ( + "## Select a region to register with \n\n" + "Please note: \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" + "* You can remove all alerts and registration using ```/remove-registration```" + ) menu = copy.deepcopy(REGION_MENU) await ctx.send(text, components=menu, ephemeral=True) - @slash_command( name="remove-registration", - description="Remove all alerts and registration from TokenBot" + description="Remove all alerts and registration from TokenBot", ) async def remove_registration(self, ctx: SlashContext): if await self._users.exists(ctx.user.id): @@ -127,43 +142,35 @@ class Tracker(Extension): await self._alerts.remove_user(alert, user) await self._users.delete(ctx.user.id) - await ctx.send("All alert subscriptions and user registration deleted", ephemeral=True) - + await ctx.send( + "All alert subscriptions and user registration deleted", ephemeral=True + ) @slash_command( - name="exists", - description="Check if you are registered with TokenBot" + name="exists", description="Check if you are registered with TokenBot" ) @check(is_owner()) async def exists(self, ctx: SlashContext): await ctx.send(str(await self._users.exists(ctx.user.id)), ephemeral=True) - - @slash_command( - description="The current retail token cost" - ) + @slash_command(description="The current retail token cost") async def current(self, ctx: SlashContext): current_str = await self.get_current_token(ctx, tdb.Flavor.RETAIL) await ctx.send(current_str, ephemeral=True) - - @slash_command( - description="The current classic token cost" - ) + @slash_command(description="The current classic token cost") async def current_classic(self, ctx: SlashContext): current_str = await self.get_current_token(ctx, tdb.Flavor.CLASSIC) await ctx.send(current_str, ephemeral=True) - - @slash_command( - name="add-alert", - description="Add an alert listener" - ) + @slash_command(name="add-alert", description="Add an alert listener") async def add_alert(self, ctx: SlashContext): if not await self._users.exists(ctx.user.id): - await ctx.send("You are not registered with any region\n" - "Please register with /register before adding alerts", - ephemeral=True) + await ctx.send( + "You are not registered with any region\n" + "Please register with /register before adding alerts", + ephemeral=True, + ) return user = await self._users.get(ctx.user.id) @@ -186,23 +193,25 @@ class Tracker(Extension): if not await self._users.is_subscribed(user, alert): await asyncio.gather( self._users.add_alert(user, alert), - self._alerts.add_user(alert, user) + self._alerts.add_user(alert, user), ) await ctx.send("Successfully added alert", ephemeral=True) else: - await ctx.send("You are already subscribed to this alert", ephemeral=True) - + await ctx.send( + "You are already subscribed to this alert", ephemeral=True + ) @slash_command( - name="remove-alert", - description="Remove an alert you have signed up for" + name="remove-alert", description="Remove an alert you have signed up for" ) async def remove_alert(self, ctx: SlashContext): if not await self._users.exists(ctx.user.id): - await ctx.send("You are not registered with any region\n" - "Please register with /register before adding alerts", - ephemeral=True) + await ctx.send( + "You are not registered with any region\n" + "Please register with /register before adding alerts", + ephemeral=True, + ) return user = await self._users.get(ctx.user.id) alerts = await self._users.list_alerts(user) @@ -217,20 +226,20 @@ class Tracker(Extension): else: await asyncio.gather( self._users.remove_alert(user, alert), - self._alerts.remove_user(alert, user) + self._alerts.remove_user(alert, user), ) await ctx.send("Successfully removed alert", ephemeral=True) - @slash_command( - name="list-alerts", - description="List all alerts you have signed up for" + name="list-alerts", description="List all alerts you have signed up for" ) async def list_alerts(self, ctx: SlashContext): if not await self._users.exists(ctx.user.id): - await ctx.send("You are not registered with any region\n" - "Please register with /register before adding alerts", - ephemeral=True) + await ctx.send( + "You are not registered with any region\n" + "Please register with /register before adding alerts", + ephemeral=True, + ) return user = await self._users.get(ctx.user.id) alerts = await self._users.list_alerts(user) @@ -238,55 +247,66 @@ class Tracker(Extension): await ctx.send("You do not have any alerts registered", ephemeral=True) return alerts_str = f"You have {len(alerts)} out of 25 maximum alerts registered" - embeds = [Embed( - title="List of TokenBot Tracker Alerts", - color=0x0000b1, - description=alerts_str - )] + embeds = [ + Embed( + title="List of TokenBot Tracker Alerts", + 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], user=user)) + embeds.append( + await self.render_alert_flavor(alerts_by_flavor[flavor], user=user) + ) await ctx.send(embeds=embeds, ephemeral=True) ################################### # Callbacks Commands # ################################### - @component_callback('flavor_menu') + @component_callback("flavor_menu") async def flavor_menu(self, ctx: ComponentContext): await ctx.send(f"Selected Flavor: {ctx.values[0]}", ephemeral=True) - @component_callback('high_alert_menu') + @component_callback("high_alert_menu") async def alert_menu(self, ctx: ComponentContext): await ctx.send(f"Selected Alert: {ctx.values[0]}", ephemeral=True) - @component_callback('low_alert_menu') + @component_callback("low_alert_menu") async def alert_menu(self, ctx: ComponentContext): await ctx.send(f"Selected Alert: {ctx.values[0]}", ephemeral=True) - @component_callback('remove_alert_menu') + @component_callback("remove_alert_menu") async def remove_alert_menu(self, ctx: ComponentContext): - await ctx.send(f"You have selected to remove the following alert: {ctx.values[0].title()}", ephemeral=True) + await ctx.send( + f"You have selected to remove the following alert: {ctx.values[0].title()}", + ephemeral=True, + ) - @component_callback('region_menu') + @component_callback("region_menu") async def region_menu(self, ctx: ComponentContext): user = User(ctx.user.id, Region(ctx.values[0].lower()), subscribed_alerts=[]) await self._users.add(user) discord_user = await self.bot.fetch_user(user.user_id) - await discord_user.send("You have successfully registered with TokenBot!\n" - "Most interactions will happen in direct messages with TokenBot here.\n" - "You can remove your registration and alerts at any time using ```/remove-registration```\n") - await ctx.send(f"Successfully registered with the {ctx.values[0]} region", ephemeral=True) + await discord_user.send( + "You have successfully registered with TokenBot!\n" + "Most interactions will happen in direct messages with TokenBot here.\n" + "You can remove your registration and alerts at any time using ```/remove-registration```\n" + ) + await ctx.send( + f"Successfully registered with the {ctx.values[0]} region", ephemeral=True + ) - @component_callback('high_alert_button') + @component_callback("high_alert_button") async def high_alert_button(self, ctx: ComponentContext): await ctx.send("You selected to add a High Price Alert", ephemeral=True) - @component_callback('low_alert_button') + @component_callback("low_alert_button") async def low_alert_button(self, ctx: ComponentContext): await ctx.send("You selected to add a Low Price Alert", ephemeral=True) - @component_callback('custom_alert_button') + @component_callback("custom_alert_button") async def custom_alert_button(self, ctx: ComponentContext): await ctx.send("You selected to add a Custom Price Alert", ephemeral=True) @@ -298,34 +318,40 @@ class Tracker(Extension): user: User = await self._users.get(ctx.user.id) region = user.region.name region_history = self._history_manager.get_history(flavor, user.region) - price_movement_str = format(region_history.last_price_movement, ',') + price_movement_str = format(region_history.last_price_movement, ",") if region_history.last_price_movement > 0: price_movement_str = f"+{price_movement_str}" - return (f"Last Price Value for {region}: {format(region_history.last_price_datum[1], ",")}\n" - f"Last Update Time: {region_history.last_price_datum[0].strftime('%Y-%m-%d %H:%M:%S UTC')}\n" - f"Last Price Movement: {price_movement_str}") - + return ( + f"Last Price Value for {region}: {format(region_history.last_price_datum[1], ",")}\n" + f"Last Update Time: {region_history.last_price_datum[0].strftime('%Y-%m-%d %H:%M:%S UTC')}\n" + f"Last Price Movement: {price_movement_str}" + ) async def remove_alert_select_menu(self, ctx: SlashContext, user: User): alerts_by_flavor = await gather_alerts_by_flavor(user.subscribed_alerts) select_options: List[StringSelectOption] = [] for flavor in alerts_by_flavor: for alert in alerts_by_flavor[flavor]: - select_options.append(StringSelectOption( - label=f"{alert.flavor.name.lower().title()} {alert.to_human_string()}", - value=f"{alert.flavor.name.lower()} {alert.to_human_string()}" - )) + select_options.append( + StringSelectOption( + label=f"{alert.flavor.name.lower().title()} {alert.to_human_string()}", + value=f"{alert.flavor.name.lower()} {alert.to_human_string()}", + ) + ) menu = StringSelectMenu( select_options, placeholder="Select an alert to remove", - custom_id="remove_alert_menu" + custom_id="remove_alert_menu", + ) + message = await ctx.send( + "Select an alert to remove", components=menu, ephemeral=True ) - message = await ctx.send("Select an alert to remove", components=menu, ephemeral=True) try: - alert_component: Component = await self.bot.wait_for_component(messages=message, - components=menu, timeout=30) + alert_component: Component = await self.bot.wait_for_component( + messages=message, components=menu, timeout=30 + ) except TimeoutError: menu.disabled = True await message.edit(context=ctx, components=menu, content="Timed out") @@ -335,23 +361,24 @@ class Tracker(Extension): await message.edit(context=ctx, components=menu) selection_split = alert_component.ctx.values[0].split(" ") flavor = Flavor[selection_split[0].upper()] - alert_type = AlertType.from_str(' '.join(selection_split[1:])) + alert_type = AlertType.from_str(" ".join(selection_split[1:])) return Alert(alert_type, flavor, user.region) - async def flavor_select_menu(self, ctx: SlashContext) -> Type[Flavor]: flavor_menu = copy.deepcopy(FLAVOR_MENU) flavor_message = await ctx.send( - "Select a flavor to add alerts for", - components=flavor_menu, - ephemeral=True) + "Select a flavor to add alerts for", components=flavor_menu, ephemeral=True + ) try: - flavor_component: Component = await self.bot.wait_for_component(messages=flavor_message, - components=flavor_menu, timeout=30) + flavor_component: Component = await self.bot.wait_for_component( + messages=flavor_message, components=flavor_menu, timeout=30 + ) except TimeoutError: flavor_menu.disabled = True - await flavor_message.edit(context=ctx, components=flavor_menu, content="Timed out") + await flavor_message.edit( + context=ctx, components=flavor_menu, content="Timed out" + ) raise TimeoutError else: flavor = Flavor[flavor_component.ctx.values[0].upper()] @@ -359,21 +386,21 @@ class Tracker(Extension): await flavor_message.edit(context=ctx, components=flavor_menu) return flavor - async def alert_category_select_menu(self, ctx: SlashContext) -> AlertCategory: alert_type_button = copy.deepcopy(ALERT_TYPE_ROW) alert_type_message = await ctx.send( - "Select an alert type to add", - components=alert_type_button, - ephemeral=True) + "Select an alert type to add", components=alert_type_button, ephemeral=True + ) try: - alert_type_component: Component = await self.bot.wait_for_component(messages=alert_type_message, - components=alert_type_button, - timeout=30) + alert_type_component: Component = await self.bot.wait_for_component( + messages=alert_type_message, components=alert_type_button, timeout=30 + ) except TimeoutError: for button in alert_type_button[0].components: button.disabled = True - await alert_type_message.edit(context=ctx, components=alert_type_button, content="Timed out") + await alert_type_message.edit( + context=ctx, components=alert_type_button, content="Timed out" + ) raise TimeoutError else: alert_type = AlertCategory.from_str(alert_type_component.ctx.custom_id) @@ -382,10 +409,13 @@ class Tracker(Extension): await alert_type_message.edit(context=ctx, components=alert_type_button) return alert_type - - async def _alert_select_menu_handler(self, ctx: SlashContext, menu: StringSelectMenu, message: Message) -> AlertType: + async def _alert_select_menu_handler( + self, ctx: SlashContext, menu: StringSelectMenu, message: Message + ) -> AlertType: try: - component: Component = await self.bot.wait_for_component(messages=message, components=menu, timeout=30) + component: Component = await self.bot.wait_for_component( + messages=message, components=menu, timeout=30 + ) except TimeoutError: menu.disabled = True await message.edit(context=ctx, components=menu, content="Timed out") @@ -395,26 +425,27 @@ class Tracker(Extension): await message.edit(context=ctx, components=menu) return AlertType.from_str(component.ctx.values[0]) - async def high_alert_select_menu(self, ctx: SlashContext) -> AlertType: high_menu = copy.deepcopy(HIGH_ALERT_MENU) high_message = await ctx.send( "Select a time range to add a High Alert for", components=high_menu, - ephemeral=True) + ephemeral=True, + ) return await self._alert_select_menu_handler(ctx, high_menu, high_message) - async def low_alert_select_menu(self, ctx: SlashContext) -> AlertType: low_menu = copy.deepcopy(LOW_ALERT_MENU) low_message = await ctx.send( "Select a time range to add a Low Alert for", components=low_menu, - ephemeral=True) + ephemeral=True, + ) return await self._alert_select_menu_handler(ctx, low_menu, low_message) - - async def render_alert_flavor(self, alerts: List[Alert], user: User | None = None) -> Embed: + async def render_alert_flavor( + self, alerts: List[Alert], user: User | None = None + ) -> Embed: region = alerts[0].region flavor = alerts[0].flavor fields: List[EmbedField] = [] @@ -422,28 +453,36 @@ class Tracker(Extension): history = 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_alerting[1], ",")}\n" - f"Last Alerting Time: {trigger.last_alerting[0].strftime('%Y-%m-%d %H:%M:%S UTC')}\n") + alert_str = ( + f"Last Alerting Price Value: {format(trigger.last_alerting[1], ",")}\n" + f"Last Alerting Time: {trigger.last_alerting[0].strftime('%Y-%m-%d %H:%M:%S UTC')}\n" + ) if user is not None and user.user_id == 265678699435655169: - alert_str += (f"\nShowing you some internals since you are the bot owner:\n" - f"```history.last_price_datum:\n" - f"\t{history.last_price_datum[0].strftime('%Y-%m-%d %H:%M:%S UTC')}\n" - f"\t{history.last_price_datum[1]}\n" - f"trigger.last_alerting:\n" - f"\t{trigger.last_alerting[0].strftime('%Y-%m-%d %H:%M:%S UTC')}\n" - f"\t{trigger.last_alerting[1]}\n" - f"trigger.last_trigger:\n" - f"\t{trigger.last_trigger[0].strftime('%Y-%m-%d %H:%M:%S UTC')}\n" - f"\t{trigger.last_trigger[1]}\n" - f"trigger.squelched:\n\t{trigger.squelched}```") + alert_str += ( + f"\nShowing you some internals since you are the bot owner:\n" + f"```history.last_price_datum:\n" + f"\t{history.last_price_datum[0].strftime('%Y-%m-%d %H:%M:%S UTC')}\n" + f"\t{history.last_price_datum[1]}\n" + f"trigger.last_alerting:\n" + f"\t{trigger.last_alerting[0].strftime('%Y-%m-%d %H:%M:%S UTC')}\n" + f"\t{trigger.last_alerting[1]}\n" + f"trigger.last_trigger:\n" + f"\t{trigger.last_trigger[0].strftime('%Y-%m-%d %H:%M:%S UTC')}\n" + f"\t{trigger.last_trigger[1]}\n" + f"trigger.squelched:\n\t{trigger.squelched}```" + ) 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)) + 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 + color=0xB10000, + fields=fields, ) return embed diff --git a/token_bot/ui/action_row/tracker.py b/token_bot/ui/action_row/tracker.py index f404785..a18ebc3 100644 --- a/token_bot/ui/action_row/tracker.py +++ b/token_bot/ui/action_row/tracker.py @@ -1,6 +1,9 @@ from interactions import ActionRow -from token_bot.ui.buttons.tracker.alert_category import HIGH_ALERT_BUTTON, LOW_ALERT_BUTTON +from token_bot.ui.buttons.tracker.alert_category import ( + HIGH_ALERT_BUTTON, + LOW_ALERT_BUTTON, +) ALERT_TYPE_ROW: list[ActionRow] = [ ActionRow( diff --git a/token_bot/ui/buttons/tracker/add.py b/token_bot/ui/buttons/tracker/add.py index 4aa89e6..28fea1c 100644 --- a/token_bot/ui/buttons/tracker/add.py +++ b/token_bot/ui/buttons/tracker/add.py @@ -1,67 +1,45 @@ from interactions import Button, ButtonStyle ATH_ADD_BUTTON = Button( - custom_id='ath_add_button', - style=ButtonStyle.GREEN, - label="All Time High" + custom_id="ath_add_button", style=ButtonStyle.GREEN, label="All Time High" ) ATL_ADD_BUTTON = Button( - custom_id='atl_add_button', - style=ButtonStyle.RED, - label="All Time Low" + custom_id="atl_add_button", style=ButtonStyle.RED, label="All Time Low" ) DH_ADD_BUTTON = Button( - custom_id='dh_add_button', - style=ButtonStyle.GREEN, - label="Daily High" + custom_id="dh_add_button", style=ButtonStyle.GREEN, label="Daily High" ) DL_ADD_BUTTON = Button( - custom_id='dl_add_button', - style=ButtonStyle.RED, - label="Daily Low" + custom_id="dl_add_button", style=ButtonStyle.RED, label="Daily Low" ) WH_ADD_BUTTON = Button( - custom_id='wh_add_button', - style=ButtonStyle.GREEN, - label="Weekly High" + custom_id="wh_add_button", style=ButtonStyle.GREEN, label="Weekly High" ) WL_ADD_BUTTON = Button( - custom_id='wl_add_button', - style=ButtonStyle.RED, - label="Weekly Low" + custom_id="wl_add_button", style=ButtonStyle.RED, label="Weekly Low" ) MH_ADD_BUTTON = Button( - custom_id='mh_add_button', - style=ButtonStyle.GREEN, - label="Monthly High" + custom_id="mh_add_button", style=ButtonStyle.GREEN, label="Monthly High" ) ML_ADD_BUTTON = Button( - custom_id='ml_add_button', - style=ButtonStyle.RED, - label="Monthly Low" + custom_id="ml_add_button", style=ButtonStyle.RED, label="Monthly Low" ) YH_ADD_BUTTON = Button( - custom_id='yh_add_button', - style=ButtonStyle.GREEN, - label="Yearly High" + custom_id="yh_add_button", style=ButtonStyle.GREEN, label="Yearly High" ) YL_ADD_BUTTON = Button( - custom_id='yl_add_button', - style=ButtonStyle.RED, - label="Yearly Low" + custom_id="yl_add_button", style=ButtonStyle.RED, label="Yearly Low" ) SP_ADD_BUTTON = Button( - custom_id='sp_add_button', - style=ButtonStyle.GRAY, - label="Custom Limit Price" + custom_id="sp_add_button", style=ButtonStyle.GRAY, label="Custom Limit Price" ) diff --git a/token_bot/ui/buttons/tracker/alert_category.py b/token_bot/ui/buttons/tracker/alert_category.py index 9212a04..cb4667f 100644 --- a/token_bot/ui/buttons/tracker/alert_category.py +++ b/token_bot/ui/buttons/tracker/alert_category.py @@ -1,19 +1,13 @@ from interactions import Button, ButtonStyle HIGH_ALERT_BUTTON = Button( - custom_id='high_alert_button', - style=ButtonStyle.GREEN, - label="High Price Alert" + custom_id="high_alert_button", style=ButtonStyle.GREEN, label="High Price Alert" ) LOW_ALERT_BUTTON = Button( - custom_id='low_alert_button', - style=ButtonStyle.RED, - label="Low Price Alert" + custom_id="low_alert_button", style=ButtonStyle.RED, label="Low Price Alert" ) CUSTOM_ALERT_BUTTON = Button( - custom_id='sp_add_button', - style=ButtonStyle.GRAY, - label="Custom Price Alert" + custom_id="sp_add_button", style=ButtonStyle.GRAY, label="Custom Price Alert" ) diff --git a/token_bot/ui/buttons/tracker/registration.py b/token_bot/ui/buttons/tracker/registration.py index 9de1230..09c24b1 100644 --- a/token_bot/ui/buttons/tracker/registration.py +++ b/token_bot/ui/buttons/tracker/registration.py @@ -1,19 +1,13 @@ from interactions import Button, ButtonStyle HIGH_ALERT = Button( - custom_id='high_alert_button', - style=ButtonStyle.GREEN, - label="Add High Alert" + custom_id="high_alert_button", style=ButtonStyle.GREEN, label="Add High Alert" ) LOW_ALERT = Button( - custom_id='low_alert_button', - style=ButtonStyle.RED, - label="Add Low Alert" + custom_id="low_alert_button", style=ButtonStyle.RED, label="Add Low Alert" ) CUSTOM_ALERT = Button( - custom_id='custom_alert_button', - style=ButtonStyle.GRAY, - label="Add Custom Alert" -) \ No newline at end of file + custom_id="custom_alert_button", style=ButtonStyle.GRAY, label="Add Custom Alert" +) diff --git a/token_bot/ui/select_menus/alert_menu.py b/token_bot/ui/select_menus/alert_menu.py index 91c759c..2430f42 100644 --- a/token_bot/ui/select_menus/alert_menu.py +++ b/token_bot/ui/select_menus/alert_menu.py @@ -1,15 +1,25 @@ from interactions import StringSelectMenu HIGH_ALERT_MENU = StringSelectMenu( - "Daily High", "Weekly High", "Monthly High", "Yearly High", "All Time High", + "Daily High", + "Weekly High", + "Monthly High", + "Yearly High", + "All Time High", placeholder="Select a time period", - min_values=1, max_values=1, - custom_id='high_alert_menu' + min_values=1, + max_values=1, + custom_id="high_alert_menu", ) LOW_ALERT_MENU = StringSelectMenu( - "Daily Low", "Weekly Low", "Monthly Low", "Yearly Low", "All Time Low", + "Daily Low", + "Weekly Low", + "Monthly Low", + "Yearly Low", + "All Time Low", placeholder="Select a time period", - min_values=1, max_values=1, - custom_id='low_alert_menu' -) \ No newline at end of file + min_values=1, + max_values=1, + custom_id="low_alert_menu", +) diff --git a/token_bot/ui/select_menus/flavor_menu.py b/token_bot/ui/select_menus/flavor_menu.py index 61ed9b2..4b10913 100644 --- a/token_bot/ui/select_menus/flavor_menu.py +++ b/token_bot/ui/select_menus/flavor_menu.py @@ -1,8 +1,10 @@ from interactions import StringSelectMenu FLAVOR_MENU = StringSelectMenu( - "Retail", "Classic", + "Retail", + "Classic", placeholder="Select version of WoW", - min_values=1, max_values=1, - custom_id='flavor_menu' -) \ No newline at end of file + min_values=1, + max_values=1, + custom_id="flavor_menu", +) diff --git a/token_bot/ui/select_menus/region_menu.py b/token_bot/ui/select_menus/region_menu.py index 508896d..44689d9 100644 --- a/token_bot/ui/select_menus/region_menu.py +++ b/token_bot/ui/select_menus/region_menu.py @@ -1,8 +1,12 @@ from interactions import StringSelectMenu REGION_MENU = StringSelectMenu( - "US", "EU", "KR", "TW", + "US", + "EU", + "KR", + "TW", placeholder="Select a region", - min_values=1, max_values=1, - custom_id='region_menu' -) \ No newline at end of file + min_values=1, + max_values=1, + custom_id="region_menu", +)