mirror of
				https://github.com/ae-utbm/sith.git
				synced 2025-11-04 02:53:06 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			77 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			77 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from pathlib import Path
 | 
						|
 | 
						|
from dateutil.relativedelta import relativedelta
 | 
						|
from django.conf import settings
 | 
						|
from django.contrib.sites.models import Site
 | 
						|
from django.contrib.syndication.views import add_domain
 | 
						|
from django.db.models import F, QuerySet
 | 
						|
from django.http import HttpRequest
 | 
						|
from django.urls import reverse
 | 
						|
from django.utils import timezone
 | 
						|
from ical.calendar import Calendar
 | 
						|
from ical.calendar_stream import IcsCalendarStream
 | 
						|
from ical.event import Event
 | 
						|
 | 
						|
from com.models import NewsDate
 | 
						|
from core.models import User
 | 
						|
 | 
						|
 | 
						|
def as_absolute_url(url: str, request: HttpRequest | None = None) -> str:
 | 
						|
    return add_domain(
 | 
						|
        Site.objects.get_current(request=request),
 | 
						|
        url,
 | 
						|
        secure=request.is_secure() if request is not None else settings.HTTPS,
 | 
						|
    )
 | 
						|
 | 
						|
 | 
						|
class IcsCalendar:
 | 
						|
    _CACHE_FOLDER: Path = settings.MEDIA_ROOT / "com" / "calendars"
 | 
						|
    _INTERNAL_CALENDAR = _CACHE_FOLDER / "internal.ics"
 | 
						|
 | 
						|
    @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
 | 
						|
        # 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(
 | 
						|
                cls.ics_from_queryset(
 | 
						|
                    NewsDate.objects.filter(
 | 
						|
                        news__is_published=True,
 | 
						|
                        end_date__gte=timezone.now() - (relativedelta(months=6)),
 | 
						|
                    )
 | 
						|
                )
 | 
						|
            )
 | 
						|
        return cls._INTERNAL_CALENDAR
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def get_unpublished(cls, user: User) -> bytes:
 | 
						|
        return cls.ics_from_queryset(
 | 
						|
            NewsDate.objects.viewable_by(user).filter(
 | 
						|
                news__is_published=False,
 | 
						|
                end_date__gte=timezone.now() - (relativedelta(months=6)),
 | 
						|
            ),
 | 
						|
        )
 | 
						|
 | 
						|
    @classmethod
 | 
						|
    def ics_from_queryset(cls, queryset: QuerySet[NewsDate]) -> bytes:
 | 
						|
        calendar = Calendar()
 | 
						|
        for news_date in queryset.annotate(news_title=F("news__title")):
 | 
						|
            event = Event(
 | 
						|
                summary=news_date.news_title,
 | 
						|
                start=news_date.start_date,
 | 
						|
                end=news_date.end_date,
 | 
						|
                url=as_absolute_url(
 | 
						|
                    reverse("com:news_detail", kwargs={"news_id": news_date.news_id})
 | 
						|
                ),
 | 
						|
            )
 | 
						|
            calendar.events.append(event)
 | 
						|
 | 
						|
        return IcsCalendarStream.calendar_to_ics(calendar).encode("utf-8")
 |