Skip to content
Snippets Groups Projects
Select Git revision
  • 005d96fafe88508039fcef0f5254b6c8425bba5c
  • master default protected
  • v2 protected
  • v2-test protected
  • piratiuk
  • regionalSuccess
  • v1
7 results

run.sh

Blame
  • models.py 3.10 KiB
    import logging
    from datetime import date, timedelta
    
    import arrow
    from django.core.serializers.json import DjangoJSONEncoder
    from django.db import models
    from icalevnt import icalevents
    
    from .parser import process_event_list
    
    logger = logging.getLogger(__name__)
    
    
    def _convert_arrow_to_datetime(event):
        event["start"] = event["start"].datetime
        event["end"] = event["end"].datetime
        return event
    
    
    class EventsJSONField(models.JSONField):
        """
        JSONField for lists of events which converts `begin` and `end` to datetime
        on load from DB.
        """
    
        def from_db_value(self, value, expression, connection):
            value = super().from_db_value(value, expression, connection)
            if value:
                for event in value:
                    event["start"] = arrow.get(event.get("start")).datetime
                    event["end"] = arrow.get(event["end"]).datetime
            return value
    
    
    class Calendar(models.Model):
        CURRENT_NUM = 6
    
        url = models.URLField()
        event_hash = models.CharField(max_length=256, null=True)
        last_update = models.DateTimeField(null=True)
        past_events = EventsJSONField(encoder=DjangoJSONEncoder, null=True)
        future_events = EventsJSONField(encoder=DjangoJSONEncoder, null=True)
    
        def current_events(self):
            return self.future_events[: self.CURRENT_NUM]
    
        def handle_event_list(self, event_list):
            event_list_hash = str(hash(str(event_list)))
            if event_list_hash != self.event_hash:
                past, future = process_event_list(event_list)
                self.past_events = past
                self.future_events = future
                self.event_hash = event_list_hash
    
            self.last_update = arrow.utcnow().datetime
            self.save()
    
        def update_source(self):
            event_list = icalevents.events(
                url=self.url,
                start=date.today() - timedelta(days=30),
                end=date.today() + timedelta(days=60),
            )
            self.handle_event_list(event_list)
    
    
    class CalendarMixin(models.Model):
        """
        Mixin to be used in other models, like site settings, which adds relation
        to Calendar.
        """
    
        calendar_url = models.URLField(
            "URL kalendáře ve formátu iCal", blank=True, null=True
        )
        calendar = models.ForeignKey(
            Calendar, null=True, blank=True, on_delete=models.PROTECT
        )
    
        class Meta:
            abstract = True
    
        def save(self, *args, **kwargs):
            # create or update related Calendar
            if self.calendar_url:
                if self.calendar:
                    if self.calendar.url != self.calendar_url:
                        self.calendar.url = self.calendar_url
                        self.calendar.save()
                else:
                    self.calendar = Calendar.objects.create(url=self.calendar_url)
    
                try:
                    self.calendar.update_source()
                except:
                    logger.error(
                        "Calendar update failed for %s", self.calendar.url, exc_info=True
                    )
    
            # delete related Calendar when URL is cleared
            if not self.calendar_url and self.calendar:
                self.calendar = None
    
            super().save(*args, **kwargs)