Once and for all reformat.
Will be using black code formatter
This commit is contained in:
		
							parent
							
								
									3a06464c29
								
							
						
					
					
						commit
						34badf17eb
					
				| @ -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 | ||||
|  | ||||
| @ -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) | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -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) | ||||
| 
 | ||||
|  | ||||
| @ -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() | ||||
|  | ||||
| @ -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 | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -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] | ||||
|  | ||||
| @ -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 | ||||
| 
 | ||||
|  | ||||
| @ -1,4 +1,3 @@ | ||||
| from .alert_type import AlertType | ||||
| from .user_schema import User | ||||
| from .alert_schema import Alert | ||||
| 
 | ||||
|  | ||||
| @ -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()] | ||||
|                 return AlertCategory[category.upper()] | ||||
|  | ||||
| @ -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: | ||||
|  | ||||
| @ -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 | ||||
|                 return AlertType.SPECIFIC_PRICE | ||||
|  | ||||
| @ -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") | ||||
|         ) | ||||
|  | ||||
| @ -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) | ||||
|  | ||||
| @ -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") | ||||
|  | ||||
| @ -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') | ||||
|     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" | ||||
|         ) | ||||
|  | ||||
| @ -4,4 +4,3 @@ from enum import Enum | ||||
| class Flavor(Enum): | ||||
|     RETAIL = 1 | ||||
|     CLASSIC = 2 | ||||
| 
 | ||||
|  | ||||
| @ -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" | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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( | ||||
|  | ||||
| @ -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" | ||||
| ) | ||||
|  | ||||
| @ -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" | ||||
| ) | ||||
|  | ||||
| @ -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" | ||||
| ) | ||||
|     custom_id="custom_alert_button", style=ButtonStyle.GRAY, label="Add Custom Alert" | ||||
| ) | ||||
|  | ||||
| @ -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' | ||||
| ) | ||||
|     min_values=1, | ||||
|     max_values=1, | ||||
|     custom_id="low_alert_menu", | ||||
| ) | ||||
|  | ||||
| @ -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' | ||||
| ) | ||||
|     min_values=1, | ||||
|     max_values=1, | ||||
|     custom_id="flavor_menu", | ||||
| ) | ||||
|  | ||||
| @ -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' | ||||
| ) | ||||
|     min_values=1, | ||||
|     max_values=1, | ||||
|     custom_id="region_menu", | ||||
| ) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user