From 0a0f44607e2e0db0c1a4dbbcbd7cd0ff2a61af2e Mon Sep 17 00:00:00 2001 From: Sli Date: Fri, 3 Jan 2025 01:48:18 +0100 Subject: [PATCH] Return calendars as real files --- com/api.py | 50 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/com/api.py b/com/api.py index 95e7fe92..871b0eac 100644 --- a/com/api.py +++ b/com/api.py @@ -1,7 +1,8 @@ -from datetime import timedelta +from datetime import datetime, timedelta +from pathlib import Path import urllib3 -from django.core.cache import cache +from django.conf import settings from django.http import HttpResponse from django.urls import reverse from django.utils import timezone @@ -9,30 +10,37 @@ from ics import Calendar, Event from ninja_extra import ControllerBase, api_controller, route from com.models import NewsDate +from core.views.files import send_raw_file @api_controller("/calendar") class CalendarController(ControllerBase): + CACHE_FOLDER: Path = settings.MEDIA_ROOT / "com" / "calendars" + @route.get("/external.ics") def calendar_external(self): - CACHE_KEY = "external_calendar" - if cached := cache.get(CACHE_KEY): - return HttpResponse( - cached, - content_type="text/calendar", - status=200, - ) + file = self.CACHE_FOLDER / "external.ics" + # Return cached file if updated less than an our ago + if ( + file.exists() + and timezone.make_aware(datetime.fromtimestamp(file.stat().st_mtime)) + + timedelta(hours=1) + > timezone.now() + ): + return send_raw_file(file) + calendar = urllib3.request( "GET", "https://calendar.google.com/calendar/ical/ae.utbm%40gmail.com/public/basic.ics", ) - if calendar.status == 200: - cache.set(CACHE_KEY, calendar.data, 3600) # Cache for one hour - return HttpResponse( - calendar.data, - content_type="text/calendar", - status=calendar.status, - ) + if calendar.status != 200: + return HttpResponse(status=calendar.status) + + self.CACHE_FOLDER.mkdir(parents=True, exist_ok=True) + with open(file, "wb") as f: + _ = f.write(calendar.data) + + return send_raw_file(file) @route.get("/internal.ics") def calendar_internal(self): @@ -50,7 +58,9 @@ class CalendarController(ControllerBase): ) calendar.events.add(event) - return HttpResponse( - calendar.serialize().encode("utf-8"), - content_type="text/calendar", - ) + # Create a file so we can offload the download to the reverse proxy if available + file = self.CACHE_FOLDER / "internal.ics" + self.CACHE_FOLDER.mkdir(parents=True, exist_ok=True) + with open(file, "wb") as f: + _ = f.write(calendar.serialize().encode("utf-8")) + return send_raw_file(file)