Return calendars as real files

This commit is contained in:
Antoine Bartuccio 2025-01-03 01:48:18 +01:00
parent 007080ee48
commit 0a0f44607e

View File

@ -1,7 +1,8 @@
from datetime import timedelta from datetime import datetime, timedelta
from pathlib import Path
import urllib3 import urllib3
from django.core.cache import cache from django.conf import settings
from django.http import HttpResponse from django.http import HttpResponse
from django.urls import reverse from django.urls import reverse
from django.utils import timezone from django.utils import timezone
@ -9,30 +10,37 @@ from ics import Calendar, Event
from ninja_extra import ControllerBase, api_controller, route from ninja_extra import ControllerBase, api_controller, route
from com.models import NewsDate from com.models import NewsDate
from core.views.files import send_raw_file
@api_controller("/calendar") @api_controller("/calendar")
class CalendarController(ControllerBase): class CalendarController(ControllerBase):
CACHE_FOLDER: Path = settings.MEDIA_ROOT / "com" / "calendars"
@route.get("/external.ics") @route.get("/external.ics")
def calendar_external(self): def calendar_external(self):
CACHE_KEY = "external_calendar" file = self.CACHE_FOLDER / "external.ics"
if cached := cache.get(CACHE_KEY): # Return cached file if updated less than an our ago
return HttpResponse( if (
cached, file.exists()
content_type="text/calendar", and timezone.make_aware(datetime.fromtimestamp(file.stat().st_mtime))
status=200, + timedelta(hours=1)
) > timezone.now()
):
return send_raw_file(file)
calendar = urllib3.request( calendar = urllib3.request(
"GET", "GET",
"https://calendar.google.com/calendar/ical/ae.utbm%40gmail.com/public/basic.ics", "https://calendar.google.com/calendar/ical/ae.utbm%40gmail.com/public/basic.ics",
) )
if calendar.status == 200: if calendar.status != 200:
cache.set(CACHE_KEY, calendar.data, 3600) # Cache for one hour return HttpResponse(status=calendar.status)
return HttpResponse(
calendar.data, self.CACHE_FOLDER.mkdir(parents=True, exist_ok=True)
content_type="text/calendar", with open(file, "wb") as f:
status=calendar.status, _ = f.write(calendar.data)
)
return send_raw_file(file)
@route.get("/internal.ics") @route.get("/internal.ics")
def calendar_internal(self): def calendar_internal(self):
@ -50,7 +58,9 @@ class CalendarController(ControllerBase):
) )
calendar.events.add(event) calendar.events.add(event)
return HttpResponse( # Create a file so we can offload the download to the reverse proxy if available
calendar.serialize().encode("utf-8"), file = self.CACHE_FOLDER / "internal.ics"
content_type="text/calendar", 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)