diff --git a/app/main.py b/app/main.py index cbb4a5f..5c907f9 100644 --- a/app/main.py +++ b/app/main.py @@ -9,6 +9,7 @@ from app.plugins.album import album_uploade_page, upload_image, delete_image, get_data from app.plugins.weather import get_data as get_data_weather from app.plugins.publictransportation import get_data as get_data_publictransportation +from app.plugins.eoguide import get_data as get_data_eoguide from fastapi.staticfiles import StaticFiles from fastapi_cache import FastAPICache from fastapi_cache.backends.inmemory import InMemoryBackend @@ -38,7 +39,7 @@ async def root(): @app.get("/calendar") -@cache(expire=600) +@cache(expire=10) async def calendar(): return get_events() @@ -97,3 +98,9 @@ async def get_weather( @cache(expire=300) async def get_departures(connections: str = '[["Hölstein, Süd", "Liestal, Bahnhof", "direct"]]'): return get_data_publictransportation(connections) + + +@app.get("/eo-guide") +@cache(expire=21_600) +async def eo_guide(): + return get_data_eoguide() diff --git a/app/plugins/eoguide.py b/app/plugins/eoguide.py new file mode 100644 index 0000000..3400819 --- /dev/null +++ b/app/plugins/eoguide.py @@ -0,0 +1,41 @@ +import re +import httpx +from app import config + + +def get_data(): + client_key = config.get_attribute(["eoguide", "client_key"]) + username = config.get_attribute(["eoguide", "username"]) + password = config.get_attribute(["eoguide", "password"]) + + response = httpx.get( + f"https://api.appfigures.com/v2/reports/sales/?client_key={client_key}", auth=(username, password) + ) + response.raise_for_status() # Raise error if request fails + sales_data = response.json() + + response_review = httpx.get( + f"https://api.appfigures.com/v2/reviews/?count=1&client_key={client_key}", auth=(username, password) + ) + response_review.raise_for_status() # Raise error if request fails + review_data = response_review.json() + + review = review_data["reviews"][0] + total = sales_data["downloads"] + total_formatted = "{:,}".format(total).replace(",", "'") + + review_text = review["review"] + review_formatted = re.sub(r"([\uE000-\uF8FF]|\uD83C[\uDF00-\uDFFF]|\uD83D[\uDC00-\uDDFF])", "", review_text).strip() + stars = float(review["stars"]) + stars_formatted = round(stars * 10) / 10 + + return { + "total": total, + "totalFormatted": total_formatted, + "latestReview": { + "review": review_text, + "reviewFormatted": review_formatted, + "stars": stars, + "starsFormatted": stars_formatted, + }, + } diff --git a/app/plugins/ical.py b/app/plugins/ical.py index c83b929..6b91ef4 100644 --- a/app/plugins/ical.py +++ b/app/plugins/ical.py @@ -1,13 +1,14 @@ import httpx -from datetime import datetime, timedelta +import locale +from datetime import datetime, timedelta, time -from dateutil.tz import gettz from icalendar import Calendar from dateutil.rrule import rrulestr import pytz from app import config -local_time_zone = gettz("Europe/Zurich") +local_time_zone = pytz.timezone("Europe/Zurich") +locale.setlocale(locale.LC_TIME, "de_DE.UTF-8") def parse_webcal(url): @@ -26,9 +27,9 @@ def ensure_timezone(dt, timezone_str="CET"): def get_events_in_next_days(cal, days=3): today_no_tz = datetime.today() - today = today_no_tz.replace(tzinfo=local_time_zone) - three_days_later_no_tz = today_no_tz + timedelta(days=days) - three_days_later = three_days_later_no_tz.replace(tzinfo=local_time_zone) + today = local_time_zone.localize(datetime.combine(today_no_tz, time.min)) + three_days_later_no_tz = today_no_tz + timedelta(days=3) + three_days_later = local_time_zone.localize(datetime.combine(three_days_later_no_tz, time.max)) events_in_next_three_days = [] @@ -83,6 +84,84 @@ def get_events_from_url(url, name, color): return events +def group_events_by_day(events): + grouped_events = [] + today = datetime.now(local_time_zone).date() # Get today's date in the local timezone + tomorrow = today + timedelta(days=1) # Get tomorrow's date + + # Dictionary to temporarily store events grouped by date + temp_grouped_events = {} + + for event in events: + event_date = event["start_date"].date() + + # Check if the event date is today, tomorrow, or another day + if event_date == today: + event_day = "Heute" + elif event_date == tomorrow: + event_day = "Morgen" + else: + event_day = event["start_date"].strftime("%A") # Day name in German + + # Add event to the corresponding day group + if event_date not in temp_grouped_events: + temp_grouped_events[event_date] = {"day": event_day, "date": event_date.strftime("%Y-%m-%d"), "events": []} + + temp_grouped_events[event_date]["events"].append(event) + + # Convert the temporary dictionary to a list of dictionaries + for date, day_info in temp_grouped_events.items(): + grouped_events.append(day_info) + + return grouped_events + + +def handle_birthdays(events): + new_events = [] + for event in events: + age = None + birthday = False + + summary = event["summary"] + + if summary.startswith("Geburtstag"): + birthday = True + + # Remove "Geburtstag " and extract the name part + name_part = summary[11:].strip() + + # Extract the year part from the name_part + parts = name_part.split() + year_part = parts[-1] + + # Remove the year from the name_part to clean the summary + name_without_year = " ".join(parts[:-1]) + summary = f"Geburtstag {name_without_year}" + + try: + year = int(year_part) + + # If it's a 2-digit year, assume it's in the 1900s (e.g., 85 -> 1985) + if year < 100: + year += 1900 + + # Calculate the age based on the current year + current_year = datetime.now().year + age = current_year - year + except ValueError: + age = None + else: + birthday = False + + event["summary"] = summary + event["birthday"] = birthday + event["age"] = age + + new_events.append(event) + + return new_events + + def get_events(): calendars = config.get_attribute(["calendars"]) @@ -93,6 +172,13 @@ def get_events(): ) all_events.extend(events) + # Handle birthdays + all_events = handle_birthdays(all_events) + + # Sort events by start_date sorted_list_of_dicts = sorted(all_events, key=lambda x: x["start_date"]) - return sorted_list_of_dicts + # Group the sorted events by day + grouped_events = group_events_by_day(sorted_list_of_dicts) + + return grouped_events