def _as_ics(self, citymeo=False): if not self.initialized: self._lazy_init() cal = iCalendar() cal.add('prodid', '-//PonyConf.io//PonyConf//FR') cal.add('version', '2.0') cal.add('x-wr-calname', self.conference.name) cal.add('x-wr-timezone', settings.TIME_ZONE) cal.add('calscale', 'GREGORIAN') talks = self.talks if citymeo and talks.exists(): talks = talks.filter(start_date__gte=now()-timedelta(minutes=5)) if talks.exists(): limit = talks.first().start_date.replace(hour=23, minute=59, second=59) talks = talks.filter(start_date__lte=limit) for talk in talks: event = iEvent() event.add('dtstart', talk.start_date) if not talk.end_date: continue event.add('dtend', talk.end_date) event.add('dtstamp', talk.updated) event.add('summary', talk.title) if talk.room: event.add('location', talk.room) event.add('status', 'CONFIRMED' if talk.accepted else 'TENTATIVE') if not citymeo: event.add('description', talk.description) event.add('uid', '%s/%s' % (self.site.domain, talk.id)) cal.add_component(event) return cal.to_ical()
def _as_ics(self, citymeo=False): if not self.initialized: self._lazy_init() cal = iCalendar() cal.add('prodid', '-//PonyConf.io//PonyConf//FR') cal.add('version', '2.0') cal.add('x-wr-calname', self.conference.name) cal.add('x-wr-timezone', settings.TIME_ZONE) cal.add('calscale', 'GREGORIAN') talks = self.talks if citymeo and talks.exists(): talks = talks.filter(start_date__gte=now() - timedelta(minutes=5)) if talks.exists(): limit = talks.first().start_date.replace(hour=23, minute=59, second=59) talks = talks.filter(start_date__lte=limit) for talk in talks: event = iEvent() event.add('dtstart', talk.start_date) if not talk.end_date: continue event.add('dtend', talk.end_date) event.add('dtstamp', talk.updated) event.add('summary', talk.title) if talk.room: event.add('location', talk.room) event.add('status', 'CONFIRMED' if talk.accepted else 'TENTATIVE') if not citymeo: event.add('description', talk.description) event.add('uid', '%s/%s' % (self.site.domain, talk.id)) cal.add_component(event) return cal.to_ical()
def change(): """ Change (create) or delete an event by POST request """ calendar = Config.calendar() changes = request.get_json() for uid in changes["deleted"]: try: calendar.event_by_uid(uid).delete() except caldav.lib.error.NotFoundError: # the event haven't been in the calendar, maybe was just created and deleted pass for schedule in changes["created"]: c = iCalendar() c.add('prodid', '-//Schedule shift//csirt.cz//') c.add('version', '2.0') event = iEvent() event.add('uid', schedule["id"]) event.add('summary', schedule["calendarId"] + " " + schedule["title"]) # event.add('dtstart', parse(schedule["start"]["_date"]).astimezone().date()+timedelta(1)) # print(schedule) # import ipdb; ipdb.set_trace() event.add('dtstart', parse(schedule["start-ics"])) event.add('dtend', parse(schedule["end-ics"])) # event.add('dtstart', parse(schedule["start"]["_date"])) # event.add('dtend', parse(schedule["end"]["_date"])) c.add_component(event) calendar.add_event(c.to_ical().decode("utf-8")) return "Saved"
def wrap_into_vcalendar(*vevents, **kw): calendar = iCalendar() calendar.add('prodid', "-//Plone/NONSGML Calendaring//EN") calendar.add('version', '2.0') title = kw.get('title') if title: title = unicode(title, 'utf-8') calendar.add('x-wr-calname', title) for vevent in vevents: calendar.add_component(vevent) return calendar.as_string()
def _generate_rsvp(status, account, event): # It seems that Google Calendar requires us to copy a number of fields # in the RVSP reply. I suppose it's for reconciling the reply with the # invite. - karim cal = iCalendar() cal.add('PRODID', '-//Nylas sync engine//nylas.com//') cal.add('METHOD', 'REPLY') cal.add('VERSION', '2.0') cal.add('CALSCALE', 'GREGORIAN') icalevent = icalendar.Event() icalevent['uid'] = event.uid # For ahem, 'historic reasons', we're saving the owner field # as "Organizer <*****@*****.**>". organizer_name, organizer_email = event.owner.split('<') organizer_email = organizer_email[:-1] icalevent['sequence'] = event.sequence_number icalevent['X-MICROSOFT-CDO-APPT-SEQUENCE'] = icalevent['sequence'] if event.status == 'confirmed': icalevent['status'] = 'CONFIRMED' icalevent['dtstamp'] = serialize_datetime(datetime.utcnow()) if event.start is not None: icalevent['dtstart'] = serialize_datetime(event.start) if event.end is not None: icalevent['dtend'] = serialize_datetime(event.end) if event.description is not None: icalevent['description'] = event.description if event.location is not None: icalevent['location'] = event.location if event.title is not None: icalevent['summary'] = event.title attendee = icalendar.vCalAddress(u'MAILTO:{}'.format( account.email_address)) attendee.params['cn'] = account.name attendee.params['partstat'] = status icalevent.add('attendee', attendee, encode=0) cal.add_component(icalevent) ret = {} ret["cal"] = cal ret["organizer_email"] = organizer_email return ret
def export(request, events, year=None): cal = iCalendar() site = Site.objects.get_current() cal.add('prodid', '-//%s Events Calendar//%s//' % (site.name, site.domain)) cal.add('version', '2.0') site_token = site.domain.split('.') site_token.reverse() site_token = '.'.join(site_token) for event in events: show = event.show description = "" if show.info.headliner: description += "Headliner: %s\n" % show.info.headliner elif show.info.headliner_text: description += "Headliner: %s\n" % show.info.headliner_text if show.info.openers_text: description += "Openers: %s\n" % show.info.openers_text if show.info.venue: description += "Venue: %s\n" % show.info.venue else: description += "Venue: %s\n" % show.info.venue_text if show.info.description: description += "Description: %s\n" % show.info.description ical_event = iEvent() ical_event.add('summary', show.info.get_title()) ical_event.add('description', description) ical_event.add('location', show.info.venue) ical_event.add('dtstart', show.date.start) ical_event.add('dtend', show.date.end and show.date.end or show.date.start) ical_event.add('dtstamp', show.date.end and show.date.end or show.date.start) ical_event['uid'] = '%d.event.events.%s' % (show.id, site_token) cal.add_component(ical_event) response = HttpResponse(cal.to_ical(), content_type="text/calendar") # title or headliner if year: response[ 'Content-Disposition'] = 'attachment; filename=%ss-calendar-%s.ics' % ( slugify(request.user.profile), year) else: response[ 'Content-Disposition'] = 'attachment; filename=%s.ics' % slugify( events[0]) return response
def _generate_rsvp(status, account, event): # It seems that Google Calendar requires us to copy a number of fields # in the RVSP reply. I suppose it's for reconciling the reply with the # invite. - karim cal = iCalendar() cal.add("PRODID", "-//Nylas sync engine//nylas.com//") cal.add("METHOD", "REPLY") cal.add("VERSION", "2.0") cal.add("CALSCALE", "GREGORIAN") icalevent = icalendar.Event() icalevent["uid"] = event.uid if event.organizer_email is not None: icalevent["organizer"] = event.organizer_email icalevent["sequence"] = event.sequence_number icalevent["X-MICROSOFT-CDO-APPT-SEQUENCE"] = icalevent["sequence"] if event.status == "confirmed": icalevent["status"] = "CONFIRMED" icalevent["dtstamp"] = serialize_datetime(datetime.utcnow()) if event.start is not None: icalevent["dtstart"] = serialize_datetime(event.start) if event.end is not None: icalevent["dtend"] = serialize_datetime(event.end) if event.description is not None: icalevent["description"] = event.description if event.location is not None: icalevent["location"] = event.location if event.title is not None: icalevent["summary"] = event.title attendee = icalendar.vCalAddress(u"MAILTO:{}".format( account.email_address)) attendee.params["cn"] = account.name attendee.params["partstat"] = status icalevent.add("attendee", attendee, encode=0) cal.add_component(icalevent) ret = {} ret["cal"] = cal return ret
def icalendar(request): from icalendar import Calendar as iCalendar from icalendar import Event from datetime import datetime, date from icalendar import UTC # timezone cal = iCalendar() cal.add("prodid", "-//FWC Kung Fu Calendar //m.fwckungfu.com") cal.add("version", "2.4") cal.add("x-wr-calname", "FWC Kung Fu Calendar") yyyy = datetime.today().year # filter_ = dict(start_date__year=yyyy, start_date__gte=datetime.today()) filter_ = dict() all_datestrings = set() for entry in Calendar.objects.filter(**filter_).order_by("start_date"): event = Event() # print entry.start_date, entry.event event.add("summary", entry.event) st = entry.start_date event.add("dtstart", date(st.year, st.month, st.day)) all_datestrings.add(st.strftime("%Y%m%d")) # event.add('dtstart', datetime(st.year, st.month, st.day, 0, 0, 0, tzinfo=UTC)) et = entry.end_date event.add("dtend", date(et.year, et.month, et.day)) all_datestrings.add(et.strftime("%Y%m%d")) # event.add('dtend', datetime(et.year, et.month, et.day,0,0,0,tzinfo=UTC)) # event.add('dtend', 'TZID=UTC;VALUE=DATE:' + et.strftime('%Y%m%d')) # DOESNOT WORK! event.add("dtstamp", datetime(st.year, st.month, st.day, 0, 0, 0, tzinfo=UTC)) event["uid"] = "fwccalendar2.4-%s" % entry.id cal.add_component(event) as_string = cal.as_string() for datestring in all_datestrings: as_string = as_string.replace(":%s" % datestring, ";TZID=UTC;VALUE=DATE:%s" % datestring) as_string = as_string.replace("\r", "") response = HttpResponse(as_string, mimetype="text/calendar") response["Content-Disposition"] = 'attachment; filename="%s"' % "calendar.ics" return response
def to_icalendar(events): """ Converts events to .ics format :param events = Iterable(cal.schema.Event) :return bytes """ summary = "Calendar for Columbia University made by ADI (adicu.com)" cal = iCalendar(dtstart=vDatetime(datetime.now()), summary=summary) for e in events: # for every event, create an event object organizer = vCalAddress("MAILTO:''") organizer.params['cn'] = e.user.name vevent = iEvent(summary=e.name, organizer=organizer, location=vText(e.location), dtstart=vDatetime(e.start), description=e.url) cal.add_component(vevent) return cal.to_ical()
def __call__(self, *args, **kwargs): self.args = args self.kwargs = kwargs cal = icalendar.iCalendar() cal.add('prodid', '-// django-scheduler //') cal.add('version', '2.0') for item in self.items(): event = icalendar.Event() for vkey, key in EVENT_ITEMS: value = getattr(self, 'item_' + key)(item) if value: event.add(vkey, value) cal.add_component(event) response = HttpResponse(cal.to_ical()) response['Content-Type'] = 'text/calendar' return response
#!/usr/bin/env python3 from icalendar import Calendar as iCalendar, Event import datetime import pytz import requests import os # f = open('importio.json', 'rb') # json = json.loads(f.read().decode()) MOVEAVEIRO_API_ENDPOINT = 'https://api.import.io/store/connector/3efbeeba-cf14-4fdb-af8f-7c6ba6d27f0c/_query?input=webpage/url:https%3A%2F%2Fdocs.google.com%2Fspreadsheets%2Fd%2F12epuwHtZbmF3xpFZydbLVw19xR_c-EDyX2tfzpZTtRo%2Fpubhtml&&_apikey=f2f3cb66f1b6401ebbf5c2a1ba04fdbfb1f94626e5a682059588ee5e282ccb73102540273ee25426ded781d8c39315ddf137df6023b26bcbff811978815bd0e13686a986642c06c408cd4da678cd7aec' json = requests.get(MOVEAVEIRO_API_ENDPOINT).json() json = json['results'] ical = iCalendar() ''' Separate results by path ''' paths = {'1': [], '2': [], '3.1': [], '3.2': [], '4': [], '5': []} for result in json: if 'path' in result: for k in [k for k in result.keys() if k.startswith("union_")]: result[k[6:]] = result[k] del result[k] paths[result['path']].append(result) event = Event() # Note # http://www.ietf.org/rfc/rfc2445.txt # http://icalendar.readthedocs.io
def generate_icalendar_invite(event, invite_type='request'): # Generates an iCalendar invite from an event. assert invite_type in ['request', 'cancel'] cal = iCalendar() cal.add('PRODID', '-//Nylas sync engine//nylas.com//') if invite_type in ['request', 'update']: cal.add('METHOD', 'REQUEST') elif invite_type == 'cancel': cal.add('METHOD', 'CANCEL') cal.add('VERSION', '2.0') cal.add('CALSCALE', 'GREGORIAN') icalendar_event = icalendar.Event() account = event.namespace.account organizer = icalendar.vCalAddress("MAILTO:{}".format( account.email_address)) if account.name is not None: organizer.params['CN'] = account.name icalendar_event['organizer'] = organizer icalendar_event['sequence'] = str(event.sequence_number) icalendar_event['X-MICROSOFT-CDO-APPT-SEQUENCE'] = icalendar_event[ 'sequence'] if invite_type == 'cancel': icalendar_event['status'] = 'CANCELLED' else: icalendar_event['status'] = 'CONFIRMED' icalendar_event['uid'] = "{}@nylas.com".format(event.public_id) icalendar_event['description'] = event.description or '' icalendar_event['summary'] = event.title or '' icalendar_event['last-modified'] = serialize_datetime(event.updated_at) icalendar_event['dtstamp'] = icalendar_event['last-modified'] icalendar_event['created'] = serialize_datetime(event.created_at) icalendar_event['dtstart'] = serialize_datetime(event.start) icalendar_event['dtend'] = serialize_datetime(event.end) icalendar_event['transp'] = 'OPAQUE' if event.busy else 'TRANSPARENT' icalendar_event['location'] = event.location or '' attendees = [] for participant in event.participants: email = participant.get('email', None) # FIXME @karim: handle the case where a participant has no address. # We may have to patch the iCalendar module for this. assert email is not None and email != "" attendee = icalendar.vCalAddress("MAILTO:{}".format(email)) name = participant.get('name', None) if name is not None: attendee.params['CN'] = name attendee.params['RSVP'] = 'TRUE' attendee.params['ROLE'] = 'REQ-PARTICIPANT' attendee.params['CUTYPE'] = 'INDIVIDUAL' status = participant.get('status', 'noreply') attendee.params['PARTSTAT'] = INVERTED_STATUS_MAP.get(status) attendees.append(attendee) if attendees != []: icalendar_event.add('ATTENDEE', attendees) cal.add_component(icalendar_event) return cal
def get(self, request): items = Event.objects.filter(status='ACTIVE') academies = [] ids = request.GET.get('academy', '') slugs = request.GET.get('academy_slug', '') ids = ids.split(",") if ids else [] slugs = slugs.split(",") if slugs else [] if ids: items = Event.objects.filter(academy__id__in=ids, status='ACTIVE').order_by('id') elif slugs: items = Event.objects.filter(academy__slug__in=slugs, status='ACTIVE').order_by('id') else: items = [] if not ids and not slugs: raise ValidationException( "You need to specify at least one academy or academy_slug (comma separated) in the querystring" ) if (Academy.objects.filter(id__in=ids).count() != len(ids) or Academy.objects.filter(slug__in=slugs).count() != len(slugs)): raise ValidationException("Some academy not exist") upcoming = request.GET.get('upcoming') if upcoming == 'true': now = timezone.now() items = items.filter(starting_at__gte=now) academies_repr = ical_academies_repr(ids=ids, slugs=slugs) calendar = iCalendar() calendar.add('prodid', f'-//BreatheCode//Academy Events{academies_repr}//EN') calendar.add('X-WR-CALNAME', f'Academy - Events') calendar.add('X-WR-CALDESC', '') calendar.add('REFRESH-INTERVAL', 'PT15M') calendar.add('version', '2.0') for item in items: event = iEvent() if item.title: event.add('summary', item.title) if item.description: event.add('description', item.description) event.add('uid', f'breathecode_event_{item.id}') event.add('dtstart', item.starting_at) event.add('dtend', item.ending_at) event.add('dtstamp', item.created_at) if item.author and item.author.email: organizer = vCalAddress(f'MAILTO:{item.author.email}') if item.author.first_name and item.author.last_name: organizer.params['cn'] = vText(f'{item.author.first_name} ' f'{item.author.last_name}') elif item.author.first_name: organizer.params['cn'] = vText(item.author.first_name) elif item.author.last_name: organizer.params['cn'] = vText(item.author.last_name) organizer.params['role'] = vText('OWNER') event['organizer'] = organizer if item.venue and (item.venue.country or item.venue.state or item.venue.city or item.venue.street_address): value = '' if item.venue.street_address: value = f'{value}{item.venue.street_address}, ' if item.venue.city: value = f'{value}{item.venue.city}, ' if item.venue.state: value = f'{value}{item.venue.state}, ' if item.venue.country: value = f'{value}{item.venue.country}' value = re.sub(', $', '', value) event['location'] = vText(value) calendar.add_component(event) calendar_text = calendar.to_ical() response = HttpResponse(calendar_text, content_type='text/calendar') response['Content-Disposition'] = 'attachment; filename="calendar.ics"' return response
def get(self, request): items = Cohort.objects.all() ids = request.GET.get('academy', '') slugs = request.GET.get('academy_slug', '') ids = ids.split(",") if ids else [] slugs = slugs.split(",") if slugs else [] if ids: items = Cohort.objects.filter(academy__id__in=ids).order_by('id') elif slugs: items = Cohort.objects.filter( academy__slug__in=slugs).order_by('id') else: items = [] if not ids and not slugs: raise ValidationException( "You need to specify at least one academy or academy_slug (comma separated) in the querystring" ) if (Academy.objects.filter(id__in=ids).count() != len(ids) or Academy.objects.filter(slug__in=slugs).count() != len(slugs)): raise ValidationException("Some academy not exist") items = items.exclude(stage='DELETED') upcoming = request.GET.get('upcoming') if upcoming == 'true': now = timezone.now() items = items.filter(kickoff_date__gte=now) academies_repr = ical_academies_repr(ids=ids, slugs=slugs) calendar = iCalendar() calendar.add('prodid', f'-//BreatheCode//Academy Cohorts{academies_repr}//EN') calendar.add('X-WR-CALNAME', f'Academy - Cohorts') calendar.add('X-WR-CALDESC', '') calendar.add('REFRESH-INTERVAL', 'PT15M') calendar.add('version', '2.0') for item in items: event = iEvent() event.add('summary', item.name) event.add('uid', f'breathecode_cohort_{item.id}') event.add('dtstart', item.kickoff_date) if item.ending_date: event.add('dtend', item.ending_date) event.add('dtstamp', item.created_at) teacher = CohortUser.objects.filter(role='TEACHER', cohort__id=item.id).first() if teacher: organizer = vCalAddress(f'MAILTO:{teacher.user.email}') if teacher.user.first_name and teacher.user.last_name: organizer.params['cn'] = vText( f'{teacher.user.first_name} ' f'{teacher.user.last_name}') elif teacher.user.first_name: organizer.params['cn'] = vText(teacher.user.first_name) elif teacher.user.last_name: organizer.params['cn'] = vText(teacher.user.last_name) organizer.params['role'] = vText('OWNER') event['organizer'] = organizer location = item.academy.name if item.academy.website_url: location = f'{location} ({item.academy.website_url})' event['location'] = vText(item.academy.name) calendar.add_component(event) calendar_text = calendar.to_ical() response = HttpResponse(calendar_text, content_type='text/calendar') response['Content-Disposition'] = 'attachment; filename="calendar.ics"' return response
def generate_icalendar_invite(event, invite_type='request'): # Generates an iCalendar invite from an event. assert invite_type in ['request', 'cancel'] cal = iCalendar() cal.add('PRODID', '-//Nylas sync engine//nylas.com//') if invite_type in ['request', 'update']: cal.add('METHOD', 'REQUEST') elif invite_type == 'cancel': cal.add('METHOD', 'CANCEL') cal.add('VERSION', '2.0') cal.add('CALSCALE', 'GREGORIAN') icalendar_event = icalendar.Event() account = event.namespace.account organizer = icalendar.vCalAddress(u"MAILTO:{}".format( account.email_address)) if account.name is not None: organizer.params['CN'] = account.name icalendar_event['organizer'] = organizer icalendar_event['sequence'] = str(event.sequence_number) icalendar_event['X-MICROSOFT-CDO-APPT-SEQUENCE'] = \ icalendar_event['sequence'] if invite_type == 'cancel': icalendar_event['status'] = 'CANCELLED' else: icalendar_event['status'] = 'CONFIRMED' icalendar_event['uid'] = u"{}@nylas.com".format(event.public_id) icalendar_event['description'] = event.description or '' icalendar_event['summary'] = event.title or '' icalendar_event['last-modified'] = serialize_datetime(event.updated_at) icalendar_event['dtstamp'] = icalendar_event['last-modified'] icalendar_event['created'] = serialize_datetime(event.created_at) icalendar_event['dtstart'] = serialize_datetime(event.start) icalendar_event['dtend'] = serialize_datetime(event.end) icalendar_event['transp'] = 'OPAQUE' if event.busy else 'TRANSPARENT' icalendar_event['location'] = event.location or '' attendees = [] for participant in event.participants: email = participant.get('email', None) # FIXME @karim: handle the case where a participant has no address. # We may have to patch the iCalendar module for this. assert email is not None and email != "" attendee = icalendar.vCalAddress(u"MAILTO:{}".format(email)) name = participant.get('name', None) if name is not None: attendee.params['CN'] = name attendee.params['RSVP'] = 'TRUE' attendee.params['ROLE'] = 'REQ-PARTICIPANT' attendee.params['CUTYPE'] = 'INDIVIDUAL' status = participant.get('status', 'noreply') attendee.params['PARTSTAT'] = INVERTED_STATUS_MAP.get(status) attendees.append(attendee) if attendees != []: icalendar_event.add('ATTENDEE', attendees) cal.add_component(icalendar_event) return cal
def generate_icalendar_invite(event, invite_type="request"): # Generates an iCalendar invite from an event. assert invite_type in ["request", "cancel"] cal = iCalendar() cal.add("PRODID", "-//Nylas sync engine//nylas.com//") if invite_type in ["request", "update"]: cal.add("METHOD", "REQUEST") elif invite_type == "cancel": cal.add("METHOD", "CANCEL") cal.add("VERSION", "2.0") cal.add("CALSCALE", "GREGORIAN") icalendar_event = icalendar.Event() account = event.namespace.account organizer = icalendar.vCalAddress(u"MAILTO:{}".format( account.email_address)) if account.name is not None and account.name != "": organizer.params["CN"] = account.name icalendar_event["organizer"] = organizer icalendar_event["sequence"] = str(event.sequence_number) icalendar_event["X-MICROSOFT-CDO-APPT-SEQUENCE"] = icalendar_event[ "sequence"] if invite_type == "cancel": icalendar_event["status"] = "CANCELLED" else: icalendar_event["status"] = "CONFIRMED" icalendar_event["uid"] = u"{}@nylas.com".format(event.public_id) icalendar_event["description"] = event.description or "" icalendar_event["summary"] = event.title or "" icalendar_event["last-modified"] = serialize_datetime(event.updated_at) icalendar_event["dtstamp"] = icalendar_event["last-modified"] icalendar_event["created"] = serialize_datetime(event.created_at) icalendar_event["dtstart"] = serialize_datetime(event.start) icalendar_event["dtend"] = serialize_datetime(event.end) icalendar_event["transp"] = "OPAQUE" if event.busy else "TRANSPARENT" icalendar_event["location"] = event.location or "" attendees = [] for participant in event.participants: email = participant.get("email", None) # FIXME @karim: handle the case where a participant has no address. # We may have to patch the iCalendar module for this. assert email is not None and email != "" attendee = icalendar.vCalAddress(u"MAILTO:{}".format(email)) name = participant.get("name", None) if name is not None: attendee.params["CN"] = name attendee.params["RSVP"] = "TRUE" attendee.params["ROLE"] = "REQ-PARTICIPANT" attendee.params["CUTYPE"] = "INDIVIDUAL" status = participant.get("status", "noreply") attendee.params["PARTSTAT"] = INVERTED_STATUS_MAP.get(status) attendees.append(attendee) if attendees != []: icalendar_event.add("ATTENDEE", attendees) cal.add_component(icalendar_event) return cal
def get(self, request): items = Cohort.objects.all() ids = request.GET.get('academy', '') slugs = request.GET.get('academy_slug', '') ids = ids.split(",") if ids else [] slugs = slugs.split(",") if slugs else [] if ids: items = Cohort.objects.filter(academy__id__in=ids).order_by('id') elif slugs: items = Cohort.objects.filter( academy__slug__in=slugs).order_by('id') else: items = [] if not ids and not slugs: raise ValidationException( "You need to specify at least one academy or academy_slug (comma separated) in the querystring" ) if (Academy.objects.filter(id__in=ids).count() != len(ids) or Academy.objects.filter(slug__in=slugs).count() != len(slugs)): raise ValidationException("Some academy not exist") items = items.exclude(stage='DELETED') upcoming = request.GET.get('upcoming') if upcoming == 'true': now = timezone.now() items = items.filter(kickoff_date__gte=now) academies_repr = ical_academies_repr(ids=ids, slugs=slugs) key = server_id() calendar = iCalendar() calendar.add( 'prodid', f'-//BreatheCode//Academy Cohorts{academies_repr} {key}//EN') calendar.add('X-WR-CALNAME', f'Academy - Cohorts') calendar.add('X-WR-CALDESC', '') calendar.add('REFRESH-INTERVAL;VALUE=DURATION', 'PT15M') url = os.getenv('API_URL') if url: url = re.sub(r'/$', '', url) + '/v1/events/ical/cohorts' if ids or slugs: url = url + '?' if ids: url = url + 'academy=' + ','.join(ids) if ids and slugs: url = url + '&' if slugs: url = url + 'academy_slug=' + ','.join(slugs) calendar.add('url', url) calendar.add('version', '2.0') for item in items: event = iEvent() event_first_day = iEvent() event_last_day = iEvent() has_last_day = False event.add('summary', item.name) event.add('uid', f'breathecode_cohort_{item.id}_{key}') event.add('dtstart', item.kickoff_date) timeslots = CohortTimeSlot.objects.filter(cohort__id=item.id) first_timeslot = timeslots.order_by('starting_at').first() if first_timeslot: event_first_day.add('summary', f'{item.name} - First day') event_first_day.add( 'uid', f'breathecode_cohort_{item.id}_first_{key}') event_first_day.add('dtstart', first_timeslot.starting_at) event_first_day.add('dtend', first_timeslot.ending_at) event_first_day.add('dtstamp', first_timeslot.created_at) if item.ending_date: event.add('dtend', item.ending_date) timeslots_datetime = [] for timeslot in timeslots: starting_at = timeslot.starting_at ending_at = timeslot.ending_at diff = ending_at - starting_at if timeslot.recurrent: ending_at = fix_datetime_weekday(item.ending_date, ending_at, prev=True) starting_at = ending_at - diff timeslots_datetime.append((starting_at, ending_at)) last_timeslot = None if timeslots_datetime: timeslots_datetime.sort(key=lambda x: x[1], reverse=True) last_timeslot = timeslots_datetime[0] has_last_day = True event_last_day.add('summary', f'{item.name} - Last day') event_last_day.add( 'uid', f'breathecode_cohort_{item.id}_last_{key}') event_last_day.add('dtstart', last_timeslot[0]) event_last_day.add('dtend', last_timeslot[1]) event_last_day.add('dtstamp', item.created_at) event.add('dtstamp', item.created_at) teacher = CohortUser.objects.filter(role='TEACHER', cohort__id=item.id).first() if teacher: organizer = vCalAddress(f'MAILTO:{teacher.user.email}') if teacher.user.first_name and teacher.user.last_name: organizer.params['cn'] = vText( f'{teacher.user.first_name} ' f'{teacher.user.last_name}') elif teacher.user.first_name: organizer.params['cn'] = vText(teacher.user.first_name) elif teacher.user.last_name: organizer.params['cn'] = vText(teacher.user.last_name) organizer.params['role'] = vText('OWNER') event['organizer'] = organizer if first_timeslot: event_first_day['organizer'] = organizer if has_last_day: event_last_day['organizer'] = organizer location = item.academy.name if item.academy.website_url: location = f'{location} ({item.academy.website_url})' event['location'] = vText(item.academy.name) if first_timeslot: event_first_day['location'] = vText(item.academy.name) if has_last_day: event_last_day['location'] = vText(item.academy.name) if first_timeslot: calendar.add_component(event_first_day) calendar.add_component(event) if has_last_day: calendar.add_component(event_last_day) calendar_text = calendar.to_ical() response = HttpResponse(calendar_text, content_type='text/calendar') response['Content-Disposition'] = 'attachment; filename="calendar.ics"' return response
def get(self, request, user_id): items = Cohort.objects.all() if not User.objects.filter(id=user_id).count(): raise ValidationException("Student not exist", 404, slug='student-not-exist') cohort_ids = (CohortUser.objects.filter(user_id=user_id).values_list( 'cohort_id', flat=True).exclude(cohort__stage='DELETED')) items = CohortTimeSlot.objects.filter( cohort__id__in=cohort_ids).order_by('id') items = items upcoming = request.GET.get('upcoming') if upcoming == 'true': now = timezone.now() items = items.filter(cohort__kickoff_date__gte=now) key = server_id() calendar = iCalendar() calendar.add( 'prodid', f'-//BreatheCode//Student Schedule ({user_id}) {key}//EN') calendar.add('X-WR-CALNAME', f'Academy - Schedule') calendar.add('X-WR-CALDESC', '') calendar.add('REFRESH-INTERVAL;VALUE=DURATION', 'PT15M') url = os.getenv('API_URL') if url: url = re.sub(r'/$', '', url) + '/v1/events/ical/student/' + str(user_id) calendar.add('url', url) calendar.add('version', '2.0') for item in items: event = iEvent() event.add('summary', item.cohort.name) event.add('uid', f'breathecode_cohort_time_slot_{item.id}_{key}') event.add('dtstart', item.starting_at) event.add('dtstamp', item.starting_at) until_date = item.cohort.ending_date if not until_date: until_date = timezone.make_aware( datetime(year=2100, month=12, day=31, hour=12, minute=00, second=00)) if item.recurrent: event.add('rrule', { 'freq': item.recurrency_type, 'until': until_date }) event.add('dtend', item.ending_at) teacher = CohortUser.objects.filter( role='TEACHER', cohort__id=item.cohort.id).first() if teacher: organizer = vCalAddress(f'MAILTO:{teacher.user.email}') if teacher.user.first_name and teacher.user.last_name: organizer.params['cn'] = vText( f'{teacher.user.first_name} ' f'{teacher.user.last_name}') elif teacher.user.first_name: organizer.params['cn'] = vText(teacher.user.first_name) elif teacher.user.last_name: organizer.params['cn'] = vText(teacher.user.last_name) organizer.params['role'] = vText('OWNER') event['organizer'] = organizer location = item.cohort.academy.name if item.cohort.academy.website_url: location = f'{location} ({item.cohort.academy.website_url})' event['location'] = vText(item.cohort.academy.name) calendar.add_component(event) calendar_text = calendar.to_ical() response = HttpResponse(calendar_text, content_type='text/calendar') response['Content-Disposition'] = 'attachment; filename="calendar.ics"' return response