mirror of
https://github.com/ae-utbm/sith.git
synced 2025-01-06 15:11:21 +00:00
Move IcsCalendar to it's own file
This commit is contained in:
parent
5d0fc38107
commit
1887a2790f
@ -4,7 +4,7 @@ from django.conf import settings
|
||||
from django.http import Http404
|
||||
from ninja_extra import ControllerBase, api_controller, route
|
||||
|
||||
from com.models import IcsCalendar
|
||||
from com.calendar import IcsCalendar
|
||||
from core.views.files import send_raw_file
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ class CalendarController(ControllerBase):
|
||||
def calendar_external(self):
|
||||
"""Return the ICS file of the AE Google Calendar
|
||||
|
||||
Because of Google's cors rules, we can't "just" do a request to google ics
|
||||
Because of Google's cors rules, we can't just do a request to google ics
|
||||
from the frontend. Google is blocking CORS request in it's responses headers.
|
||||
The only way to do it from the frontend is to use Google Calendar API with an API key
|
||||
This is not especially desirable as your API key is going to be provided to the frontend.
|
||||
|
74
com/calendar.py
Normal file
74
com/calendar.py
Normal file
@ -0,0 +1,74 @@
|
||||
from datetime import datetime, timedelta
|
||||
from pathlib import Path
|
||||
from typing import final
|
||||
|
||||
import urllib3
|
||||
from django.conf import settings
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from ics import Calendar, Event
|
||||
|
||||
from com.models import NewsDate
|
||||
|
||||
|
||||
@final
|
||||
class IcsCalendar:
|
||||
_CACHE_FOLDER: Path = settings.MEDIA_ROOT / "com" / "calendars"
|
||||
_EXTERNAL_CALENDAR = _CACHE_FOLDER / "external.ics"
|
||||
_INTERNAL_CALENDAR = _CACHE_FOLDER / "internal.ics"
|
||||
|
||||
@classmethod
|
||||
def get_external(cls, expiration: timedelta = timedelta(hours=1)) -> Path | None:
|
||||
if (
|
||||
cls._EXTERNAL_CALENDAR.exists()
|
||||
and timezone.make_aware(
|
||||
datetime.fromtimestamp(cls._EXTERNAL_CALENDAR.stat().st_mtime)
|
||||
)
|
||||
+ expiration
|
||||
> timezone.now()
|
||||
):
|
||||
return cls._EXTERNAL_CALENDAR
|
||||
return cls.make_external()
|
||||
|
||||
@classmethod
|
||||
def make_external(cls) -> Path | None:
|
||||
calendar = urllib3.request(
|
||||
"GET",
|
||||
"https://calendar.google.com/calendar/ical/ae.utbm%40gmail.com/public/basic.ics",
|
||||
)
|
||||
if calendar.status != 200:
|
||||
return None
|
||||
|
||||
cls._CACHE_FOLDER.mkdir(parents=True, exist_ok=True)
|
||||
with open(cls._EXTERNAL_CALENDAR, "wb") as f:
|
||||
_ = f.write(calendar.data)
|
||||
return cls._EXTERNAL_CALENDAR
|
||||
|
||||
@classmethod
|
||||
def get_internal(cls) -> Path:
|
||||
if not cls._INTERNAL_CALENDAR.exists():
|
||||
return cls.make_internal()
|
||||
return cls._INTERNAL_CALENDAR
|
||||
|
||||
@classmethod
|
||||
def make_internal(cls) -> Path:
|
||||
# Updated through a post_save signal on News in com.signals
|
||||
calendar = Calendar()
|
||||
for news_date in NewsDate.objects.filter(
|
||||
news__is_moderated=True,
|
||||
end_date__gte=timezone.now()
|
||||
- (timedelta(days=30) * 60), # Roughly get the last 6 months
|
||||
).prefetch_related("news"):
|
||||
event = Event(
|
||||
name=news_date.news.title,
|
||||
begin=news_date.start_date,
|
||||
end=news_date.end_date,
|
||||
url=reverse("com:news_detail", kwargs={"news_id": news_date.news.id}),
|
||||
)
|
||||
calendar.events.add(event)
|
||||
|
||||
# Create a file so we can offload the download to the reverse proxy if available
|
||||
cls._CACHE_FOLDER.mkdir(parents=True, exist_ok=True)
|
||||
with open(cls._INTERNAL_CALENDAR, "wb") as f:
|
||||
_ = f.write(calendar.serialize().encode("utf-8"))
|
||||
return cls._INTERNAL_CALENDAR
|
@ -22,11 +22,7 @@
|
||||
#
|
||||
#
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from pathlib import Path
|
||||
from typing import final
|
||||
|
||||
import urllib3
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.core.mail import EmailMultiAlternatives
|
||||
@ -37,75 +33,11 @@ from django.templatetags.static import static
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from ics import Calendar, Event
|
||||
|
||||
from club.models import Club
|
||||
from core.models import Notification, Preferences, User
|
||||
|
||||
|
||||
@final
|
||||
class IcsCalendar:
|
||||
_CACHE_FOLDER: Path = settings.MEDIA_ROOT / "com" / "calendars"
|
||||
_EXTERNAL_CALENDAR = _CACHE_FOLDER / "external.ics"
|
||||
_INTERNAL_CALENDAR = _CACHE_FOLDER / "internal.ics"
|
||||
|
||||
@classmethod
|
||||
def get_external(cls, expiration: timedelta = timedelta(hours=1)) -> Path | None:
|
||||
if (
|
||||
cls._EXTERNAL_CALENDAR.exists()
|
||||
and timezone.make_aware(
|
||||
datetime.fromtimestamp(cls._EXTERNAL_CALENDAR.stat().st_mtime)
|
||||
)
|
||||
+ expiration
|
||||
> timezone.now()
|
||||
):
|
||||
return cls._EXTERNAL_CALENDAR
|
||||
return cls.make_external()
|
||||
|
||||
@classmethod
|
||||
def make_external(cls) -> Path | None:
|
||||
calendar = urllib3.request(
|
||||
"GET",
|
||||
"https://calendar.google.com/calendar/ical/ae.utbm%40gmail.com/public/basic.ics",
|
||||
)
|
||||
if calendar.status != 200:
|
||||
return None
|
||||
|
||||
cls._CACHE_FOLDER.mkdir(parents=True, exist_ok=True)
|
||||
with open(cls._EXTERNAL_CALENDAR, "wb") as f:
|
||||
_ = f.write(calendar.data)
|
||||
return cls._EXTERNAL_CALENDAR
|
||||
|
||||
@classmethod
|
||||
def get_internal(cls) -> Path:
|
||||
if not cls._INTERNAL_CALENDAR.exists():
|
||||
return cls.make_internal()
|
||||
return cls._INTERNAL_CALENDAR
|
||||
|
||||
@classmethod
|
||||
def make_internal(cls) -> Path:
|
||||
# Updated through a post_save signal on News in com.signals
|
||||
calendar = Calendar()
|
||||
for news_date in NewsDate.objects.filter(
|
||||
news__is_moderated=True,
|
||||
end_date__gte=timezone.now()
|
||||
- (timedelta(days=30) * 60), # Roughly get the last 6 months
|
||||
).prefetch_related("news"):
|
||||
event = Event(
|
||||
name=news_date.news.title,
|
||||
begin=news_date.start_date,
|
||||
end=news_date.end_date,
|
||||
url=reverse("com:news_detail", kwargs={"news_id": news_date.news.id}),
|
||||
)
|
||||
calendar.events.add(event)
|
||||
|
||||
# Create a file so we can offload the download to the reverse proxy if available
|
||||
cls._CACHE_FOLDER.mkdir(parents=True, exist_ok=True)
|
||||
with open(cls._INTERNAL_CALENDAR, "wb") as f:
|
||||
_ = f.write(calendar.serialize().encode("utf-8"))
|
||||
return cls._INTERNAL_CALENDAR
|
||||
|
||||
|
||||
class Sith(models.Model):
|
||||
"""A one instance class storing all the modifiable infos."""
|
||||
|
||||
|
@ -1,7 +1,8 @@
|
||||
from django.db.models.base import post_save
|
||||
from django.dispatch import receiver
|
||||
|
||||
from com.models import IcsCalendar, News
|
||||
from com.calendar import IcsCalendar
|
||||
from com.models import News
|
||||
|
||||
|
||||
@receiver(post_save, sender=News, dispatch_uid="update_internal_ics")
|
||||
|
@ -46,7 +46,8 @@ from accounting.models import (
|
||||
SimplifiedAccountingType,
|
||||
)
|
||||
from club.models import Club, Membership
|
||||
from com.models import IcsCalendar, News, NewsDate, Sith, Weekmail
|
||||
from com.calendar import IcsCalendar
|
||||
from com.models import News, NewsDate, Sith, Weekmail
|
||||
from core.models import Group, Page, PageRev, SithFile, User
|
||||
from core.utils import resize_image
|
||||
from counter.models import Counter, Product, ProductType, StudentCard
|
||||
|
Loading…
Reference in New Issue
Block a user