diff --git a/src/commands/faq.py b/src/commands/faq.py index b575933..637ecce 100644 --- a/src/commands/faq.py +++ b/src/commands/faq.py @@ -141,81 +141,76 @@ async def about(self, interaction: Interaction): description="Outputs the date of the next Friday Night Games with food", ) async def food(self, interaction: Interaction): - tz = pytz.timezone("Australia/Adelaide") - # Manually inputting dates - date_stack = [ - tz.localize(dt.datetime(2025, 10, 24, 17)), - tz.localize(dt.datetime(2025, 10, 10, 17)), - tz.localize(dt.datetime(2025, 9, 19, 17)), - tz.localize(dt.datetime(2025, 8, 22, 17)), - tz.localize(dt.datetime(2025, 5, 30, 17)), - tz.localize(dt.datetime(2025, 3, 28, 17)), - ] - - # Checking if the tail date has already passed - curr_date = dt.datetime.now(tz) - if curr_date > date_stack[-1]: - while ( - len(date_stack) > 0 and curr_date > date_stack[-1] - ): # length check was added to prevent access of first element when list was empty - this would cause a compiler error - date_stack.pop() - - # Printing next time for Games Night - if len(date_stack) == 0: - await interaction.response.send_message( - "The next Friday Night Games with food will be next year. Thank you for being a valued member!" - ) - return - # Determining if games night is on the same day as day of function call - time_difference = date_stack[-1] - curr_date - if date_stack[-1].date() == curr_date.date(): - time_difference_hours = floor(time_difference.seconds / 3600) - time_difference_minutes = ceil((time_difference.seconds % 3600) / 60) - message = "" - # Handle hours - if time_difference_hours == 1: - message += f"The next Friday Night Games with food is on today in {time_difference_hours} hour " - else: - message += f"The next Friday Night Games with food is on today in {time_difference_hours} hours " - # Handle minutes - if time_difference_minutes == 1: - message += f"and {time_difference_minutes} minute at 5pm. Join us in the Duck Lounge!" + try: + await interaction.response.defer() + tz = pytz.timezone("Australia/Adelaide") + + fng_dates = cms.get_fng_food_dates() + date_stack = [d.astimezone(tz) for d in fng_dates] + + # Checking if the tail date has already passed + curr_date = dt.datetime.now(tz) + if len(date_stack) > 0 and curr_date > date_stack[-1]: + while len(date_stack) > 0 and curr_date > date_stack[-1]: + date_stack.pop() + + # Printing next time for Games Night + if len(date_stack) == 0: + await interaction.followup.send( + "The next Friday Night Games with food will be next year. Thank you for being a valued member!" + ) + return + # Determining if games night is on the same day as day of function call + time_difference = date_stack[-1] - curr_date + if date_stack[-1].date() == curr_date.date(): + time_difference_hours = floor(time_difference.seconds / 3600) + time_difference_minutes = ceil((time_difference.seconds % 3600) / 60) + message = "" + # Handle hours + if time_difference_hours == 1: + message += f"The next Friday Night Games with food is on today in {time_difference_hours} hour " + else: + message += f"The next Friday Night Games with food is on today in {time_difference_hours} hours " + # Handle minutes + if time_difference_minutes == 1: + message += f"and {time_difference_minutes} minute at 5pm. Join us in the Duck Lounge!" + else: + message += f"and {time_difference_minutes} minutes at 5pm. Join us in the Duck Lounge!" + await interaction.followup.send(message) + return + + # Determining if games night is on the next day of function call + if date_stack[-1].date() == (curr_date + dt.timedelta(days=1)).date(): + await interaction.followup.send( + "The next Friday Night Games with food is on tomorrow. Join us in the Duck Lounge at 5pm!" + ) + return + + # Determining whether date needs a st, nd, rd or rth + date_num = date_stack[-1].strftime("%d") + # Removing zero padding if present + if date_num[0] == "0": + date_num = date_num[1:] + date_day = date_stack[-1].strftime("%B") + time_difference_days = time_difference.days + if curr_date.time().hour >= 17: + time_difference_days += 1 # This allows for a more intuitive display of the difference in days + message = f"The next Friday Night Games with food will be held in {time_difference.days} days on the {date_num}" + if date_num in {"1", "21", "31"}: + message += "st " + elif date_num in {"2", "22"}: + message += "nd " + elif date_num in {"3", "23"}: + message += "rd " else: - message += f"and {time_difference_minutes} minutes at 5pm. Join us in the Duck Lounge!" - await interaction.response.send_message(message) + message += "th " + message += f"of {date_day}" + await interaction.followup.send(message) return - - # Determining if games night is on the next day of function call - if date_stack[-1].date() == (curr_date + dt.timedelta(days=1)).date(): - await interaction.response.send_message( - "The next Friday Night Games with food is on tomorrow. Join us in the Duck Lounge at 5pm!" - ) + except Exception: + await interaction.followup.send("There was an error fetching FNG dates.") return - # Determining whether date needs a st, nd, rd or rth - date_num = date_stack[-1].strftime("%d") - # Removing zero padding if present - if date_num[0] == "0": - date_num = date_num[1:] - date_day = date_stack[-1].strftime("%B") - time_difference_days = time_difference.days - if curr_date.time().hour >= 17: - time_difference_days += ( - 1 # This allows for a more intuitive display of the difference in days - ) - message = f"The next Friday Night Games with food will be held in {time_difference.days} days on the {date_num}" - if date_num in {1, 21, 31}: - message += "st " - elif date_num in {2, 22}: - message += "nd " - elif date_num in {3, 23}: - message += "rd " - else: - message += "th " - message += f"of {date_day}" - await interaction.response.send_message(message) - return - class EventsGroup(app_commands.Group): def __init__(self): diff --git a/src/utils/cms.py b/src/utils/cms.py index b220147..eff8ff1 100644 --- a/src/utils/cms.py +++ b/src/utils/cms.py @@ -13,6 +13,7 @@ COMMITTEE_ENDPOINT = "committee-members" PROJECTS_ENDPOINT = "projects" SPONSORS_ENDPOINT = "sponsors" +COMMON_EVENTS_ENDPOINT = "common-events" _memory_cache = {} _cache_times = {} @@ -82,6 +83,33 @@ def get_cached_events(force: bool = False) -> Optional[Dict[str, Any]]: return _get_cached(EVENTS_ENDPOINT, params=None, cache_key="events", force=force) +def get_fng_food_dates(force: bool = False) -> List[datetime]: + """Return a list of upcoming Friday Night Games with Food dates from CMS""" + data = _get_cached( + COMMON_EVENTS_ENDPOINT, + params={"limit": 500}, + cache_key="common_events", + force=force, + ) + if not data: + return [] + docs = data.get("docs", []) + dates = [] + for doc in docs: + if "Friday Night Games with Food" in doc.get("name", ""): + upcoming = doc.get("upcomingDates", []) + for u in upcoming: + date_str = u.get("date") + dt = _parse_iso(date_str) + if dt: + if dt.tzinfo is None: + dt = dt.replace(tzinfo=timezone.utc) + dates.append(dt) + break + dates.sort(reverse=True) + return dates + + def get_upcoming_events(limit: int = 50, force: bool = False) -> List[Dict[str, Any]]: """Return a list of upcoming events sorted by date.""" data = get_cached_events(force=force)