def get_ical(self): cal = Calendar() adate = self.start_date for shift in self.shifts: event = Event() if shift not in self.definitions: print('WARNING: Unknown shift: {}'.format(shift), file=sys.stderr) times = None else: if self.definitions[shift]: times = [self.definitions[shift]['start'], self.definitions[shift]['end']] else: times = None if times is not None: starttime = time(int(times[0][:2]), int(times[0][2:4]), tzinfo=self.timezone) event.add('dtstart', datetime.combine(adate, starttime)) if int(times[0]) > int(times[1]): enddate = adate + timedelta(1) else: enddate = adate endtime = time(int(times[1][:2]), int(times[1][2:4]), tzinfo=self.timezone) event.add('dtend', datetime.combine(enddate, endtime)) if 'title' in self.definitions[shift]: event['summary'] = self.definitions[shift]['title'] cal.add_component(event) adate += timedelta(1) return cal.to_ical()
def convert_to_calendar(data): dict_calendar = { "format": CALENDAR, } pattern_frequence = '' if data['frequence'] == EVERYMONTH: pattern_frequence = MONTHLY elif data['frequence'] == EVERYWEEK: pattern_frequence = WEEKLY elif data['frequence'] == EVERYDAY: pattern_frequence = DAILY calendar_event = Event() rule_pattern = { 'freq': pattern_frequence, 'byhour': data["time"].hour, 'byminute': data["time"].minute, } if pattern_frequence == MONTHLY: rule_pattern['bymonthday'] = data["date"] elif pattern_frequence == WEEKLY: rule_pattern['byday'] = CALENDAR_DAY_DICT[data["day"]] calendar_event.add('rrule', rule_pattern) dict_calendar['pattern'] = calendar_event.to_ical() return dict_calendar
def generate_ical(object): cal = Calendar() cal['PRODID'] = 'Kawaz' cal['VERSION'] = '2.0' site = Site.objects.get(pk=settings.SITE_ID) event = CalEvent() event['summary'] = object.title event['description'] = object.body event['class'] = 'PUBLIC' if object.pub_state == 'public' else 'PRIVATE' if object.category: event['categories'] = object.category.label event['dtstamp'] = vDatetime(object.created_at) if object.place: event['location'] = object.place event['dtstart'] = vDatetime(object.period_start).to_ical() if object.period_end: event['dtend'] = vDatetime(object.period_end).to_ical() def create_vaddress(user): va = vCalAddress('MAILTO:{}'.format(user.email)) va.params['cn'] = vText(user.nickname) va.params['ROLE'] = vText(user.role) return va organizer = create_vaddress(object.organizer) event['organizer'] = organizer event['URL'] = 'http://{}{}'.format(site.domain, object.get_absolute_url()) for attendee in object.attendees.all(): event.add('attendee', create_vaddress(attendee), encode=0) cal.add_component(event) return cal
def build_calendar(issues, ics_path): cal = Calendar() for i in issues: event = Event() if "Full" in str(i.status): summary = "[COMPLET] " + i.subject else: summary = i.subject event.add('summary', summary) event.add('description', i.description) event['uid'] = i.id for c in i.custom_fields: if c.id == 20: # 20 is 'debut' start_time = str(c.value).replace(':', '')+"00" if c.id == 21: # 21 is 'fin' end_time = str(c.value).replace(':', '')+"00" event['dtstart'] = i.due_date.replace('/','')+"T"+start_time event['dtend'] = i.due_date.replace('/','')+"T"+end_time event['dtstamp'] = vDatetime(now).to_ical() organizer = vCalAddress('MAILTO:[email protected]') organizer.params['cn'] = vText('Les fruits défendus') event['organizer'] = organizer event['location'] = vText('Montréal, QC') cal.add_component(event) f = open(ics_path, 'wb') f.write(cal.to_ical()) f.close()
def test_escaping(self): # verify that escaped non safe chars are decoded correctly NON_SAFE_CHARS = u',\\;:' for char in NON_SAFE_CHARS: cn_escaped = u"Society\\%s 2014" % char cn_decoded = u"Society%s 2014" % char vevent = Event.from_ical( u'BEGIN:VEVENT\r\n' u'ORGANIZER;CN=%s:that\r\n' u'END:VEVENT\r\n' % cn_escaped ) self.assertEqual(vevent['ORGANIZER'].params['CN'], cn_decoded) vevent = Event.from_ical( 'BEGIN:VEVENT\r\n' 'ORGANIZER;CN=that\\, that\\; %th%%at%\\\\ that\\:' ':это\\, то\\; that\\\\ %th%%at%\\:\r\n' 'END:VEVENT\r\n' ) self.assertEqual( vevent['ORGANIZER'].params['CN'], r'that, that; %th%%at%\ that:' ) self.assertEqual( vevent['ORGANIZER'].to_ical().decode('utf-8'), u'это, то; that\\ %th%%at%:' )
def test_parsers(self): obj = AcademicEvents() cal = Calendar() event = Event() event.add('dtstart', date(2014, 12, 5)) event.add('dtend', date(2014, 12, 6)) event['summary'] = "Test Event" start, end = obj.parse_dates(event) self.assertEquals(start, "2014-12-05") self.assertEquals(end, "2014-12-05") year, quarter = obj.parse_year_quarter(event) self.assertEquals(year, None) self.assertEquals(quarter, None) event['description'] = ' Year: 2018 ' year, quarter = obj.parse_year_quarter(event) self.assertEquals(year, '2018') self.assertEquals(quarter, None) event['description'] = ' Year: 2018\nQuarter: Winter\nMore Content' year, quarter = obj.parse_year_quarter(event) self.assertEquals(year, '2018') self.assertEquals(quarter, 'Winter')
def add_event(calendar, event_data): event = Event() for icalendar_key, model_attribute in icalendar_to_model_keys.items(): if model_attribute in event_data: if event_data[model_attribute] is not None: event.add(icalendar_key, event_data[model_attribute]) calendar.add_component(event)
def get(self, request, **kwargs): client = CachedWaniKani(kwargs['api_key']) queue = client.upcoming() cal = Calendar() cal.add('prodid', '-//Wanikani Reviews//github.com/kfdm/django-wanikani//') cal.add('version', '2.0') newqueue = collections.defaultdict(list) for ts in list(queue.keys()): newts = ts.date() newqueue[newts] += queue.pop(ts) queue = newqueue for ts in sorted(queue): if not len(queue[ts]): continue event = Event() event.add('summary', '復習 {0}'.format(len(queue[ts]))) event.add('dtstart', ts) cal.add_component(event) return HttpResponse( content=cal.to_ical(), content_type='text/calendar; charset=utf-8' )
def make_anc_ical(request, anc=None): # Collect future meetings and sort after collating meetings across ANCs. now = datetime.datetime.now() meetings = [] for mtganc, mtgs in meeting_data.items(): if anc != None and mtganc.lower() != anc: continue for mtgdate, mtginfo in sorted(mtgs['meetings'].items()): mtgdate = dateutil.parser.parse(mtgdate) if mtgdate < now: continue meetings.append( (mtgdate, mtganc, mtginfo) ) meetings.sort() # Make ical. from icalendar import Calendar, Event cal = Calendar() for mtgdate, mtganc, mtginfo in meetings: if mtginfo.get("status") == "invalid": continue event = Event() event.add('dtstart', mtgdate) event['summary'] = "ANC %s Meeting" % mtganc event['description'] = "See ANCFinder.org for details: http://ancfinder.org/%s" % mtganc event['location'] = '; '.join(mtginfo[k] for k in ('building', 'address', 'root') if mtginfo.get(k)) event['link'] = mtginfo.get("link") cal.add_component(event) return HttpResponse(cal.to_ical(), "text/calendar" if "mime" not in request.GET else "text/plain")
def render_ical(rows, schema): calendar = Calendar() for row in rows: event = Event() for key, value in row.items(): if value: event.add(key, value) calendar.add_component(event) return calendar.to_ical()
def vevent(request, talk_id): t = get_object_or_404(Talk, pk=talk_id) event = Event() event.add('description', t.title) ical = event.to_ical response = HttpResponse(ical, mimetype='text/calendar') response['Filename'] = 'filename.ics' # IE needs this response['Content-Disposition'] = 'attachment; filename=talk-%s.ics'%t.start.strftime('%Y%m') return response
def execute(self, quals, columns): ical_file = urllib.urlopen(self.url).read() cal = Calendar.from_string(ical_file) for v in cal.walk('vevent'): e = Event(v) line = {} for column_name in self.columns: line[column_name] = e.decoded(column_name) yield line
def parse_ical_from_url(url, user): """Parses user's ical file from given URL Creates CalendarEntry-instances for each relevant VEVENT and attaches them to the given user """ response = None try: response = urllib2.urlopen(url) except urllib2.URLError: # Try to replace webcal protocol with http response = urllib2.urlopen(url.replace("webcal", "http", 1)) calendar = Calendar.from_ical(response.read()) eventlist = [component for component in calendar.walk('vevent')] now = datetime.now(pytz.utc) # Generate more events from recurrences recurrences = [] for event in eventlist: rrules = None if 'rrule' in event: rrules = event['rrule'] if rrules: duration = event[DTEND].dt - event[DTSTART].dt start = event[DTSTART].dt for recurrence_datetime in (rrulestr( rrules.to_ical(), dtstart=start).between( now, now + timedelta(days=7))): recurrence = Event() recurrence[SUMMARY] = event[SUMMARY] recurrence[LOCATION] = event[LOCATION] recurrence[STATUS] = 'CONFIRMED' recurrence.add('dtstart', recurrence_datetime) recurrence.add('dtend', recurrence_datetime + duration) recurrences.append(recurrence) eventlist += recurrences # Relevant events start from today to 7 days ahead relevanteventlist = [event for event in eventlist if (type(event[DTSTART].dt) is datetime and event[DTSTART].dt > now and event[DTSTART].dt < now + timedelta(days=7) and event[STATUS] == 'CONFIRMED' and not # Facebook participation filtering ('PARTSTAT' in event and event['PARTSTAT'] not in ['ACCEPTED', 'MAYBE']))] # Persist events to database for event in relevanteventlist: entry = create_calendarentry_from_ical_event(event) entry.user = user entry.save()
def as_vevent(value): """Conver an event in to a vevent string""" event = Event() event.add('dtstamp', value.start) event.add('dtstart', value.start) event.add('duration', timezone.timedelta(hours=2, minutes=30)) event.add('summary', value.title) event.add('description', value.presstext) return event.to_ical()
def generate_ics(): cnx = mysql.connector.connect(user=DB['user'], password=DB['password'], host=DB['host'], database=DB['database']) cal = Calendar() cal.add('prodid', '-//Hello Class Yann//yann.ga-fl.net//') cal.add('version', '2.0') cursor = cnx.cursor() query = ("SELECT idassignment, kind_name, kind, text, start, end, modified FROM assignment " "WHERE start > %s") start_date = datetime.datetime.now()-datetime.timedelta(weeks=1) cursor.execute(query, (start_date, )) for (idassignment, kind_name, kind, text, start, end, modified) in cursor: event = Event() event.add('summary', "%s - %s" % (kind_name, text)) event.add('dtstart', start) event.add('dtend', end) event.add('dtstamp', modified) event['uid'] = '%s/[email protected]' % idassignment cal.add_component(event) cursor.close() cnx.close() f = open(HELLO['ics'], 'wb') f.write(cal.to_ical()) f.close()
def ics(): astral = Astral() astral.solar_depression = "civil" astral.depression = 6.0 city = astral["Toronto"] cal = Calendar() cal.add("prodid", "-//Time of Day//time-of-day.herokuapp.com//") cal.add("version", "2.0") today = datetime.date.today() for x in range(-7, 8): date = today + datetime.timedelta(days=x) sun = city.sun(date=date, local=True) for summary, time in sun.items(): event = Event() event.add("summary", summary.capitalize()) event.add("dtstart", time) event.add("dtend", time) event.add("dtstamp", time) cal.add_component(event) resp = make_response(cal.to_ical()) resp.headers["Content-Disposition"] = "attachment; filename=time-of-day.ics" resp.headers["Content-Type"] = "text/calendar" return resp
def addEvent(self, title, location, date, start, end): event = Event() event.add('summary', title) event.add('dtstart', date + start) event.add('dtend', date + end) event.add('location', location) return event
def send_file(request): from icalendar import Calendar, Event as Ev from datetime import datetime import pytz import time cal = Calendar() cal.add('prodid','//Delteps//OurCalendarObjectHackFmi') cal.add('version','2.0') cal.add('method','publish') i = 0 for ev in Event.objects.all(): event = Ev() event.add('summary',ev.subject.name) event.add('dtstart',ev.date_start) event.add('dtend', ev.date_end) event.add('dtstamp',datetime.now()) event['uid']=ev.subject.name+'/'+str(i) i = i+1 cal.add_component(event) icalstream = cal.to_ical() response = HttpResponse(icalstream, mimetype='text/calendar') response['Filename'] = 'filename.ics' response['Content-Disposition'] = 'attachment; filename=filename.ics' return response
def index(): cfg = load_config('config.json') calendar = Calendar() calendar['prodid'] = '-//worker-perlence//Worker calendar' calendar['version'] = '2.0' calendar['x-wr-calname'] = 'Worker calendar' for day, shift in workdays(cfg['FORMULA'], cfg['FIRST_DAY']): if shift == '0': continue event = Event() event.add('uid', 'WORKER-DAY-' + day.isoformat()) event.add('dtstamp', datetime.now()) event.add('dtstart', day) event.add('dtend', day + timedelta(days=1)) event.add('summary', cfg['SUMMARY'][shift]) event['dtstamp'].to_ical() event['dtstart'].to_ical() event['dtend'].to_ical() calendar.add_component(event) data = calendar.to_ical() cache_bust = md5(data).hexdigest()[:7] response = make_response(data) response.headers['Content-Type'] = 'text/calendar;charset=utf-8' response.headers['Content-Disposition'] = ( 'inline; filename="worker-day-%s.ics"' % cache_bust) return response
def calendar(username): access_token = request.args.get("access_token") try: data = urlopen("https://www.beeminder.com/api/v1/users/%s/goals.json?access_token=%s"%(username, access_token)).read() data = json.loads(data.decode(encoding='UTF-8')) except HTTPError: return error_page() cal = Calendar() cal.add('prodid', '-//Beeminder calendar//tevp.net//') cal.add('version', '2.0') cal.add('X-WR-CALNAME', 'Beeminder Calendar for %s'%username) for goal in data: start = datetime.fromtimestamp(goal["losedate"]) startdate = start.date() if start.hour <=4: # Assume that times before 4am are effectively "yesterday" startdate -= timedelta(days = 1) enddate = startdate + timedelta(days = 1) title = goal["title"] event = Event() event.add('summary', "%s fail day" % title) event.add('dtstart', startdate) event.add('dtend', enddate) event.add('last-modified', datetime.now()) event['uid'] = hashlib.md5(title.encode() + str(startdate).encode()).hexdigest() cal.add_component(event) resp = make_response(cal.to_ical()) resp.headers["Content-Type"] = "text/Calendar" resp.headers["Cache-Control"] = "no-cache, must-revalidate" resp.headers["Expires"] = "Sat, 26 Jul 1997 05:00:00 GMT" return resp
def write_calendar(calendardict, title, filename): cal = Calendar() cal.add("prodid", title) cal.add("version", "2.0") for (date, calendarentries) in calendardict.items(): for calendarentry in calendarentries["elements"]: cal_entry = str(calendarentry["html"]) cal_entry = cal_entry.replace("<br/>", "\n") cal_summary = re.search("([A-z]+)<", cal_entry) if cal_summary is not None: cal_summary = cal_summary.group(1) else: cal_summary = "Unknown title" event = Event() event.add("summary", cal_summary) startdate_str = "{0} {1}".format(date, calendarentry["starttime"]) enddate_str = "{0} {1}".format(date, calendarentry["endtime"]) event.add("dtstart", datetime.strptime(startdate_str, "%d.%m.%Y %H:%M")) event.add("dtend", datetime.strptime(enddate_str, "%d.%m.%Y %H:%M")) event.add("description", cal_entry) cal.add_component(event) with open(filename, "wb") as f: f.write(cal.to_ical()) return cal
def export (self): """Export to ical format""" start_date = datetime.date(2011, 10, 30) # first sunday of semester cal = Calendar() cal.add("prodid", "-//NHY//Technion Students' Schedule 1.0//EN") cal.add("version", 2.0) for (day_num, activities) in enumerate(self): for (activity_num, activity) in enumerate(activities): # date and time date = start_date + datetime.timedelta(day_num) time = datetime.time(*self.split_slot(activity.start)) dt_start = datetime.datetime.combine(date, time) time = datetime.time(*self.split_slot(activity.start + activity.length)) dt_end = datetime.datetime.combine(date, time) # add event to calendar file event = Event() event.add("summary", activity.text) event.add("dtstart", dt_start) event.add("dtend", dt_end) event.add("dtstamp", datetime.datetime.today()) event["uid"] = "NHY-TECHNION-STUDENTS-SCHEDULE-%d%d" % (day_num, activity_num) cal.add_component(event) f = open(os.path.expanduser("~/test.ics"), "w") f.write(get_display(cal.as_string())) #f.write((cal.as_string())) f.close()
def ical(request, type='Full'): """ """ cal = Calendar() site = Site.objects.get_current() if type.lower() == 'full': gigs = g.objects.all() else: gigs = g.objects.filter(date__gte=datetime.now()) cal.add('prodid','-//{0} Events Calendar//{1}//EN'.format(type, site.domain)) cal.add('version','2.0') for gig in gigs: performances = p.objects.filter(gig=gig.id) for performance in performances: start = datetime.strptime('{0} {1}'.format(gig.date, performance.time), "%Y-%m-%d %H:%M:%S") end = start + timedelta(hours=2) ical_event = Event() ical_event.add('summary','{0}, {1}, {2}'.format(gig.venue.name, gig.venue.city, gig.venue.state)) ical_event.add('dtstart',start) ical_event.add('dtend',end) url = 'http://{0}{1}'.format(site.domain,gig.get_absolute_url()) ical_event.add('description',url) cal.add_component(ical_event) response = HttpResponse(cal.as_string(), mimetype='text/calendar') response['Filename'] = 'filename.ics' response['Content-Disposition'] = 'attachment; filename=filename.ics' return response
def view_instance_calendar(request, course_url, instance_url): """ Renders a iCalendar feed for a CourseInstance. Unlike most other views in this module, this view does not require the user to be logged in. @param request: the Django HttpRequest object @param course_url: the url value of a Course object @param instance_url: the url value of a CourseInstance object """ course_instance = _get_course_instance(course_url, instance_url) cal = Calendar() cal.add('prodid', '-// A+ calendar //') cal.add('version', '2.0') for course_module in course_instance.course_modules.all(): event = Event() event.add('summary', course_module.name) # FIXME: Currently all times added are the closing time. # The event will need to be longer than 0 seconds in order # to be displayed clearly on calendar applications. event.add('dtstart', course_module.closing_time) event.add('dtend', course_module.closing_time) event.add('dtstamp', course_module.closing_time) event['uid'] = "module/" + str(course_module.id) + "/A+" cal.add_component(event) response = HttpResponse(cal.as_string(), content_type="text/calendar; charset=utf-8") return response
def export_calendar_for_user(cal_user_id=None, filename="export"): """ Create and export iCalendar file with the meetings of the chosen user :param cal_user_id: User ID to create calendar for :param filename: Filename for the ics file :return: ics file wrapped in a response """ if cal_user_id is None: # Defaults to current user cal_user_id = current_user.id meeting_list = Meeting.get_user_meetings(cal_user_id) tz = timezone(app.config['TIMEZONE']) cal = Calendar() for meeting in meeting_list: event = Event() event.add('summary', meeting.title) event.add('dtstart', tz.localize(meeting.start_time)) event.add('dtend', tz.localize(meeting.end_time)) event.add('description', u'Møte generert av %s. Antall deltakere: %s. ' % (app.config['APP_NAME'], meeting.participant_count)) cal.add_component(event) export = StringIO.StringIO() export.writelines(cal.to_ical()) export.seek(0) return send_file(export, attachment_filename=filename + '.ics', as_attachment=True)
def generate_ical(assignments, output_path, SITEURL): from icalendar import Calendar, Event import datetime import pytz cal = Calendar() cal.add('prodid', '-//My calendar product//mxm.dk//') cal.add('version', '2.0') for (count, a) in enumerate(assignments): event = Event() summary = strip_tags(a.summary).strip() event.add('summary', summary) date = datetime.datetime.strptime(a.duedate, '%Y-%m-%d') date += datetime.timedelta(hours=25) description = 'More Info: ' + SITEURL + '/' + a.url + ' DUE: ' + a.duedate event.add('dtstart', date) event.add('uid', str(count) + '*****@*****.**') event.add('description', description) cal.add_component(event) import os f = open(os.path.join(output_path, 'assignments.ics'), 'wb') f.write(cal.to_ical()) f.close()
def icalendar(native_languages, foreign_languages): calendar = calendar_for_languages( native_languages, foreign_languages) def full_names(langs): str = ", ".join([LANGUAGE_DICT(l) for l in langs[:-1]]) if len(langs) > 1: str = " or ".join(str, langs[-1]) return str cal = Calendar() calendar_description = \ ("Dates where we have at least {0} speakers of " "{1} learning {2} scheduled to be online at langolab.com.").format( NOTIFICATION_PARTNER_THRESHOLD, full_names(foreign_languages), full_names(native_languages)) cal.add('prodid', '-//Langolab//langolab.com//EN') cal.add("version", "2.0") cal.add("X-WR-CALNAME", "Langolab Language Pairings") cal.add("X-WR-CALDESC", calendar_description) cal_ranges = calendar.languagecalendarrange_set.filter( end_date__gte=utcnow()).order_by('start_date') for cal_range in cal_ranges: event = Event() event.add('summary', 'Partners online at langolab.com') event.add('dtstart', cal_range.start_date) event.add('dtend', cal_range.end_date + timedelta(hours=1)) event.add('dtstamp', utcnow()) event['uid'] = cal_range.uid cal.add_component(event) return cal.as_string()
def add(self, data): if not (data.home and data.away): logging.error("Invalid match data. %s" % (data.stadium,)) return event = Event() title = u"%s vs. %s" % (data.home.display, data.away.display) if data.fixture: title += u" (第%d節)" % (data.fixture,) # TODO: define message resources to use i18n. if data.status == 'postponed': title = u"[延期]" + title elif data.status == 'stopped': title = u"[中止]" + title elif data.status == 'done': if data.description: event.set('description', u'試合結果:' + data.description) elif data.status == 'yet': pass else: logging.error('Unknown status "%s" on "%s" - "%s"', data.status, data.home, data.away) event.set('summary', title) event['uid'] = uuid.uuid4().hex event.set('location', data.stadium) if data.kickoff.hour > 0: # Consider UTC Offset. t = (data.kickoff - timedelta(hours=9)).timetuple() start = datetime(t[0], t[1], t[2], t[3], t[4], tzinfo=pytz.utc) # TODO: icalendar issue to avoid 'VALUE=DATE' attribute. event['dtstart'] = start.strftime('%Y%m%dT%H%M00Z') e = start + timedelta(hours=2) event['dtend'] = e.strftime('%Y%m%dT%H%M00Z') else: event.set('dtstart', data.kickoff.date()) self.cal.add_component(event)
def write_items(self, calendar): """ Write all events to the calendar """ for item in self.items: event = Event() for ifield, efield in ITEM_EVENT_FIELD_MAP: val = item.get(ifield) if val is not None: event.add(efield, val) calendar.add_component(event)
def get_caldav_event(self, events_exported, partner): """ Returns iCalendar file for the event invitation. @param event: event object (browse record) @return: .ics file content """ ics = Event() event = self[0] def ics_datetime(idate, allday=False): if idate: if allday: return str( vDatetime( datetime.fromtimestamp( mktime( strptime(idate, DEFAULT_SERVER_DATETIME_FORMAT))) ).to_ical())[:8] else: return vDatetime( datetime.fromtimestamp( mktime( strptime(idate, DEFAULT_SERVER_DATETIME_FORMAT) ))).to_ical() + 'Z' return False raise osv.except_osv( _('Warning!'), _("First you have to specify the date of the invitation.")) ics['summary'] = event.name if event.description: ics['description'] = event.description if event.location: ics['location'] = event.location if event.rrule: ics['rrule'] = event.rrule if event.alarm_ids: for alarm in event.alarm_ids: valarm = ics.add('valarm') interval = alarm.interval duration = alarm.duration trigger = valarm.add('TRIGGER') trigger.params['related'] = ["START"] if interval == 'days': delta = timedelta(days=duration) elif interval == 'hours': delta = timedelta(hours=duration) elif interval == 'minutes': delta = timedelta(minutes=duration) trigger.value = delta valarm.add('DESCRIPTION').value = alarm.name or 'Odoo' if event.attendee_ids: for attendee in event.attendee_ids: attendee_add = ics.get('attendee') attendee_add = attendee.cn and ('CN=' + attendee.cn) or '' if attendee.cn and attendee.email: attendee_add += ':' attendee_add += attendee.email and ('MAILTO:' + attendee.email) or '' ics.add('attendee', attendee_add, encode=0) if events_exported: event_not_found = True for event_comparison in events_exported: if str(ics) == event_comparison: event_not_found = False break if event_not_found: events_exported.append(str(ics)) ics['uid'] = '%s@%s-%s' % (event.id, self.env.cr.dbname, partner.id) ics['created'] = ics_datetime( strftime(DEFAULT_SERVER_DATETIME_FORMAT)) tmpStart = ics_datetime(event.start, event.allday) tmpEnd = ics_datetime(event.stop, event.allday) if event.allday: ics['dtstart;value=date'] = tmpStart else: ics['dtstart'] = tmpStart if tmpStart != tmpEnd or not event.allday: if event.allday: ics['dtend;value=date'] = str( vDatetime( datetime.fromtimestamp( mktime( strptime( event.stop, DEFAULT_SERVER_DATETIME_FORMAT))) + timedelta(hours=24)).to_ical())[:8] else: ics['dtend'] = tmpEnd return [ics, events_exported] else: events_exported.append(str(ics)) ics['uid'] = '%s@%s-%s' % (event.id, self.env.cr.dbname, partner.id) ics['created'] = ics_datetime( strftime(DEFAULT_SERVER_DATETIME_FORMAT)) tmpStart = ics_datetime(event.start, event.allday) tmpEnd = ics_datetime(event.stop, event.allday) if event.allday: ics['dtstart;value=date'] = tmpStart else: ics['dtstart'] = tmpStart if tmpStart != tmpEnd or not event.allday: if event.allday: ics['dtend;value=date'] = str( vDatetime( datetime.fromtimestamp( mktime( strptime(event.stop, DEFAULT_SERVER_DATETIME_FORMAT))) + timedelta(hours=24)).to_ical())[:8] else: ics['dtend'] = tmpEnd return [ics, events_exported]
def get_listing(dept): bs = BeautifulSoup( requests.get(wnotice + '/list_notices_p.pl?dept=' + dept + '&time_frame=year').text, 'html5lib') for dd in bs.find_all('dd'): try: dt2 = dd.previous_sibling dt1 = dt2.previous_sibling when = dt1.find('b').text.strip() local_tz = pytz.timezone('America/Toronto') parsed_dt = datetime.datetime.strptime(when, '%A, %d %B %Y, %I:%M%p') local_dt = local_tz.localize(parsed_dt, is_dst=None) utc_dt = local_dt.astimezone(pytz.utc) venue = dt2.find('em').text.strip() where = dt1.text.split('--')[1].replace('true', '').strip() if '--' in dt2.text: dept = dt2.text.split('--')[1].strip() else: dept = "" who = None title = None abstract = None remarks = None for em in dd.find_all('em'): if em.text == 'Speaker:': who = em.next_sibling.strip() elif em.text == 'Title:': title = em.next_sibling.next_sibling.find( 'em').text.strip() if title[:1] == '"': title = title[1:] if title[-1:] == '"': title = title[:-1] title = title.replace('$', '') elif em.text == 'Abstract:': # XXX TODO FIXME: This will cut off at the end of first paragraph abstract = em.next_sibling.strip() elif em.text == 'Remarks:': remarks = em.next_sibling.strip() event = Event() event['dtstart'] = utc_dt.strftime('%Y%m%dT%H%M00Z') event['dtstamp'] = event['dtstart'] event['dtend'] = ( utc_dt + datetime.timedelta(hours=1)).strftime('%Y%m%dT%H%M00Z') event['location'] = where event['summary'] = title + ' - ' + dept + ' (' + venue + ')' # event['description'] = '\n'.join(filter(None,[ # title, # who, # dept, # venue, # '\n', # abstract, # remarks])) text = dd.getText(separator=' ') text = text.replace(" Title:", "\nTitle:") text = text.replace(" Abstract:", "\nAbstract:") text = text.replace(" Remarks:", "\nRemarks:") event['uid'] = event['dtstart'] + '_' + hashlib.md5( text.encode('utf-8')).hexdigest() event['description'] = text yield event except Exception as e: print('#ERROR:', dd, e)
def get_ics(schedule): cal = Calendar() cal['version'] = '2.0' cal['prodid'] = '-//CQUT//Syllabus//CN' # *mandatory elements* where the prodid can be changed, see RFC 5445 start_monday = date( 2017, 2, 20 ) # 开学第一周星期一的时间 TODO: 从 http://cale.dc.cqut.edu.cn/Index.aspx?term=2016-2017 抓取开学时间 dict_week = {'一': 0, '二': 1, '三': 2, '四': 3, '五': 4, '六': 5, '日': 6} dict_day = { 1: relativedelta(hours=8, minutes=0), 3: relativedelta(hours=10, minutes=10), 5: relativedelta(hours=14, minutes=0), 7: relativedelta(hours=16, minutes=10), 9: relativedelta(hours=19, minutes=0) } for line in schedule: event = Event() print(line) # line should be like this: ['汇编语言程序设计', '周三第7~8节', '第10-10周|双周', '第1实验楼B403-A', '刘小洋(刘小洋)'] info_day = re.findall(r'周(.*?)第(\d+)~(\d+)节', line[3], re.S | re.M) info_day = info_day[0] print(info_day) # info_day should be like this: ('三', '7', '8') info_week = re.findall(r'第(\d+)-(\d+)周', line[2], re.S | re.M) info_week = info_week[0] print(info_week) # info_week should be like this: ('10', '10') dtstart_date = start_monday + relativedelta( weeks=(int(info_week[0]) - 1)) + relativedelta(days=int(dict_week[info_day[0]])) dtstart_datetime = datetime.combine(dtstart_date, datetime.min.time()) dtstart = dtstart_datetime + dict_day[int(info_day[1])] dtend = dtstart + relativedelta(hours=1, minutes=40) # 我们的课持续一小时四十分钟(中间有十分钟课间时间) event.add('uid', str(uuid1()) + '@CQUT') event.add('summary', line[0]) event.add('dtstamp', datetime.now()) event.add('dtstart', dtstart) event.add('dtend', dtend) if line[2].find('|') == -1: interval = 1 count = int(info_week[1]) - int(info_week[0]) + 1 else: interval = 2 count = int(info_week[1]) - int(info_week[0]) / 2 + 1 # 如果有单双周的课 那么这些课隔一周上一次 event.add('rrule', { 'freq': 'weekly', 'interval': interval, 'count': count }) # 设定重复次数 event.add('location', line[4]) # 设定重复地点 cal.add_component(event) return cal
def generate_ics(request, instance_id): if request.method == 'POST': instance = get_object_or_404(CourseInstance, pk=instance_id) blocks = json.loads(request.POST['blocks']) max_block_size = int(request.POST['maxBlockSize']) try: skipped_weeks = [ int(x) for x in request.POST['skippedWeeks'].split(',') ] except ValueError: skipped_weeks = [] min_time_between = int(request.POST['minTimeBetween']) dt_blocks = [] for [[startday, starthour], [endday, endhour]] in blocks: startday += 1 endday += 1 start = datetime(1970, 1, startday, starthour) end = datetime(1970, 1, endday, endhour) dt_blocks.append((start, end)) cal = Calendar() cal.add('prodid', '-//UoM//uhm.nl//') cal.add('version', '1.0') weeks = Week.objects.filter(course_id=instance.course.id) actions = Action.objects.filter( course_id=instance.course.id).order_by('ordering') week_number = 1 monday = next_weekday(instance.started, 0) current_week_free = dt_blocks.copy() final_study_blocks = [] last_next_block_min_bound = None for action in actions: if action.week.number < week_number: continue if action.week.number > week_number: diff = action.week.number - week_number week_number += diff current_week_free = dt_blocks.copy() last_next_block_min_bound = None while diff > 0: monday = next_weekday(monday, 0) iso_week_number = monday.isocalendar()[1] if iso_week_number not in skipped_weeks: diff -= 1 study_blocks = [action.load] if (action.splittable): study_blocks = divide_load(max_block_size, action.load) for study_block in study_blocks: scheduled = False for i in range(len(current_week_free)): (start, end) = current_week_free[i] if (last_next_block_min_bound != None): if (last_next_block_min_bound < end and last_next_block_min_bound >= start): start = last_next_block_min_bound elif (last_next_block_min_bound > end): continue # The next study block should be in the next timeslot block_length = (end - start).seconds // 3600 if study_block > block_length: # This free time block is not large enough for the # planned study block continue study_block_end_time = start + timedelta(hours=study_block) next_block_min_bound = study_block_end_time + \ timedelta(hours=min_time_between) final_block = (action.description, to_date(monday, start), to_date(monday, study_block_end_time)) final_study_blocks.append(final_block) current_week_free[i] = ( start + timedelta(seconds=study_block * 3600), end) last_next_block_min_bound = next_block_min_bound if (i > 0): del current_week_free[0:i - 1] scheduled = True break if not scheduled: # TODO: Communicate this to the user print( "Could not schedule study block of %s hours for '%s'" % (study_block, action)) for (descr, start, end) in final_study_blocks: event = Event() event.add('summary', descr) event.add('dtstart', start) event.add('dtend', end) event.add('status', 'CONFIRMED') cal.add_component(event) return HttpResponse(cal.to_ical(), content_type="text/calendar") return HttpResponse('', content_type="text/calendar", status=400)
def get(self, request): """Create a iCal file from the schedule""" # Heavily inspired by https://djangosnippets.org/snippets/2223/ and # the icalendar documentation calendar = Calendar() site = get_current_site(request) calendar.add('prodid', '-//%s Schedule//%s//' % (site.name, site.domain)) calendar.add('version', '2.0') # Since we don't need to format anything here, we can just use a list # of schedule items for item in ScheduleItem.objects.all(): sched_event = Event() sched_event.add('dtstamp', item.last_updated) sched_event.add('summary', item.get_title()) sched_event.add('location', item.venue.name) sched_event.add('dtstart', item.get_start_datetime()) sched_event.add( 'duration', datetime.timedelta(minutes=item.get_duration_minutes())) sched_event.add('class', 'PUBLIC') sched_event.add('uid', '%s@%s' % (item.pk, site.domain)) calendar.add_component(sched_event) response = HttpResponse(calendar.to_ical(), content_type="text/calendar") response['Content-Disposition'] = 'attachment; filename=schedule.ics' return response
def get_ical(client, calendar_url, title_format,google_calendar_id): calendar = client.get_block(calendar_url) for view in calendar.views: if isinstance(view, CalendarView): calendar_view = view break else: raise Exception(f"Couldn't find a calendar view in the following list: {calendar.views}") #print(calendar_view.get('query2')['calendar_by']) #print(calendar_view.get()) calendar_query = calendar_view.build_query() calendar_entries = calendar_query.execute() collection = calendar.collection schema = collection.get_schema_properties() properties_by_name = {} properties_by_slug = {} properties_by_id = {} title_prop = None for prop in schema: name = prop['name'] if name in properties_by_name: print("WARNING: duplicate property with name {}".format(name)) properties_by_name[name] = prop properties_by_slug[prop['slug']] = prop properties_by_id[prop['id']] = prop if prop['type'] == 'title': title_prop = prop assert title_prop is not None, "Couldn't find a title property" dateprop = properties_by_id[calendar_query.calendar_by] #assert dateprop['type'] == 'date', "Property '{}' is not a Date property".format(settings['property']) cal = Calendar() cal.add("summary", "Imported from Notion, via notion-export-ics.") cal.add('version', '2.0') for e in calendar_entries: date = e.get_property(dateprop['id']) if date is None: continue name = e.get_property(title_prop['id']) clean_props = {'NAME': name} # Put in ICS file event = Event() desc = '' event.add('dtstart', date.start) if date.end is not None: event.add('dtend', date.end) desc += e.get_browseable_url() + '\n\n' desc += 'Properties:\n' for k, v in e.get_all_properties().items(): if k != dateprop['slug']: name = properties_by_slug[k]['name'] desc += " - {}: {}\n".format(name, v) clean_props[name] = v title = title_format.format_map(clean_props) event.add('summary', title) event.add('description', desc) cal.add_component(event) start_format = date._format_datetime(date.start) if start_format[1] == None: #no time specified on the date. date.start = date._parse_datetime(str(date.start),"00:00") event_id = m.create_event(calendar_id=google_calendar_id, start=date.start, end=date.end,timezone=str(get_localzone()),description=desc,summary=title) # Print print("{}: {} -> {}".format(title, date.start,date.end)) print(desc) print('--------------') return cal
def toiCal(data, firtMonday): table = json.loads(data) rule = re.compile(ur"[^a-zA-Z0-9\-,]") cal = Calendar() cal['version'] = '2.0' cal['prodid'] = '-//NUC//Syllabus//CN' # *mandatory elements* where the prodid can be changed, see RFC 5445 mondaySplit = firtMonday[0].split('-') start_monday = date(int(mondaySplit[0]), int(mondaySplit[1]), int(mondaySplit[2])) # 开学第一周星期一的时间 dict_day = { 1: relativedelta(hours=8, minutes=0), 3: relativedelta(hours=10, minutes=10), 5: relativedelta(hours=14, minutes=30), 7: relativedelta(hours=16, minutes=40), 9: relativedelta(hours=19, minutes=30) } dict_day2 = { 1: relativedelta(hours=8, minutes=0), 3: relativedelta(hours=10, minutes=10), 5: relativedelta(hours=14, minutes=0), 7: relativedelta(hours=16, minutes=10), 9: relativedelta(hours=19, minutes=0) } #print data for i in table: #print i for j in rule.sub('', i["Course_Week"]).split(','): if j.find('-') != -1: d = j.split('-') for dday in range(int(d[0]), int(d[1]) + 1): event = Event() dtstart_date = start_monday + relativedelta( weeks=(dday - 1)) + relativedelta( days=int(int(i["Course_Time"])) - 1) dtstart_datetime = datetime.combine( dtstart_date, datetime.min.time()) if dtstart_date.month >= 5 and dtstart_date.month < 10: dtstart = dtstart_datetime + dict_day[int( i["Course_Start"])] else: dtstart = dtstart_datetime + dict_day2[int( i["Course_Start"])] dtend = dtstart + relativedelta(hours=1, minutes=40) event.add('uid', str(uuid1()) + '@Dreace') event.add('summary', i["Course_Name"]) event.add('dtstamp', datetime.now()) event.add('dtstart', dtstart) event.add('dtend', dtend) event.add('rrule', { 'freq': 'weekly', 'interval': 1, 'count': 1 }) event.add('location', i["Course_Building"] + i["Course_Classroom"]) cal.add_component(event) else: if j == '': continue event = Event() dtstart_date = start_monday + relativedelta( weeks=(int(j) - 1)) + relativedelta( days=int(int(i["Course_Time"])) - 1) dtstart_datetime = datetime.combine(dtstart_date, datetime.min.time()) if dtstart_date.month >= 5 and dtstart_date.month < 10: dtstart = dtstart_datetime + dict_day[int( i["Course_Start"])] else: dtstart = dtstart_datetime + dict_day2[int( i["Course_Start"])] dtend = dtstart + relativedelta(hours=1, minutes=40) event.add('uid', str(uuid1()) + '@Dreace') event.add('summary', i["Course_Name"]) event.add('dtstamp', datetime.now()) event.add('dtstart', dtstart) event.add('dtend', dtend) event.add('rrule', { 'freq': 'weekly', 'interval': 1, 'count': 1 }) event.add('location', i["Course_Building"] + i["Course_Classroom"]) cal.add_component(event) # print display(cal) filename = generate_random_str(20) + ".ics" write_ics_file(filename, cal) return "https://1.2.3.4/dl/" + filename
def parse_html_table(html, location): def get_utc_datetime(string): local = pytz.timezone('Europe/Paris') naive = datetime.strptime(string, "%d/%m/%Y") local_dt = local.localize(naive, is_dst=None) return local_dt.astimezone(pytz.utc) def parse_event_id(string): re1 = 'javascript:ev\((\\d+)' rg = re.compile(re1, re.IGNORECASE | re.DOTALL) m = rg.search(string) if m: return m.group(1) else: return str(uuid.uuid4()) def duration_to_date(date, string): if string.endswith('h'): string = u"%s00" % string else: string = string.replace('min', '') hours, minutes = 0, 0 items = list(int(i) for i in string.split('h')) if len(items) == 1: minutes = items[0] elif len(items) == 2: hours, minutes = items[0], items[1] return date + timedelta(seconds=((hours) * 3600 + minutes * 60)) soup = BeautifulSoup(html) table = soup.find('table') rows = list(table.findAll('tr')) if len(rows) > 2: for tr in rows[2:]: cols = [(td.find(text=True) or '') for td in tr.findAll('td')] date = get_utc_datetime(cols[0]) start_date = duration_to_date(date, cols[2]) stop_date = duration_to_date(start_date, cols[3]) summary = cols[1] if cols[6]: classroom = cols[6] else: classroom = "Salle inconnue" location_title = "%s - %s" % (location, classroom) if cols[4]: summary = "%s - %s - %s" % (summary, cols[4], location_title) event = Event() event.add('summary', summary) event.add('dtstart', start_date) event.add('dtend', stop_date) event.add('dtstamp', date) event.add('location', location_title) event['uid'] = parse_event_id(str(tr)) yield event
def get(self, request, *args, **kwargs): """ Attaches .ics for webinar to download with response. Returns: HttpResponse: Response with .ics file. """ if not request.GET.get('download_ical'): return super().get(request, *args, **kwargs) webinar = self.get_object() cal = Calendar() event = Event() event.add('summary', webinar.title) event.add('description', webinar.description) event.add('dtstart', webinar.start_time) event.add('duration', webinar.duration) event.add('location', webinar.meeting_link) event.add('uid', uuid.uuid4()) cal.add_component(event) response = HttpResponse(cal.to_ical(), content_type='text/calendar; charset=utf8') response[ 'Content-Disposition'] = f'attachment; filename={webinar.title}.ics' return response
def compute_calendar(panchangam): festival_rules_main = read_old_festival_rules_dict(os.path.join(CODE_ROOT, 'panchangam/data/festival_rules.json')) festival_rules_rel = read_old_festival_rules_dict(os.path.join(CODE_ROOT, 'panchangam/data/relative_festival_rules.json')) festival_rules_desc_only = read_old_festival_rules_dict(os.path.join(CODE_ROOT, 'panchangam/data/festival_rules_desc_only.json')) festival_rules = {**festival_rules_main, **festival_rules_rel, **festival_rules_desc_only} ics_calendar = Calendar() # uid_list = [] alarm = Alarm() alarm.add('action', 'DISPLAY') alarm.add('trigger', timedelta(hours=-4)) # default alarm, with a 4 hour reminder for d in range(1, jyotisha.panchangam.temporal.MAX_SZ - 1): [y, m, dt, t] = swe.revjul(panchangam.jd_start + d - 1) if len(panchangam.festivals[d]) > 0: # Eliminate repeat festivals on the same day, and keep the list arbitrarily sorted panchangam.festivals[d] = sorted(list(set(panchangam.festivals[d]))) summary_text = panchangam.festivals[d] # this will work whether we have one or more events on the same day for stext in sorted(summary_text): desc = '' event = Event() if stext == 'kRttikA-maNDala-pArAyaNam': event.add('summary', jyotisha.custom_transliteration.tr(stext.replace('-', ' '), panchangam.script)) fest_num_loc = stext.find('~\#') if fest_num_loc != -1: stext = stext[:fest_num_loc] event.add('dtstart', date(y, m, dt)) event.add('dtend', (datetime(y, m, dt) + timedelta(48)).date()) if stext in festival_rules: desc = festival.HinduCalendarEventOld.make_from_dict(festival_rules[stext]).get_description_string(script=panchangam.script, include_url=True) else: logging.warning('No description found for festival %s!' % stext) event.add_component(alarm) event.add('description', desc.strip()) event['X-MICROSOFT-CDO-ALLDAYEVENT'] = 'TRUE' event['TRANSP'] = 'TRANSPARENT' event['X-MICROSOFT-CDO-BUSYSTATUS'] = 'FREE' ics_calendar.add_component(event) elif stext.find('RIGHTarrow') != -1: # It's a grahanam/yogam, with a start and end time if stext.find('{}') != -1: # Starting or ending time is empty, e.g. harivasara, so no ICS entry continue [stext, t1, arrow, t2] = stext.split('\\') stext = stext.strip('-~') event.add('summary', jyotisha.custom_transliteration.tr(stext, panchangam.script)) # we know that t1 is something like 'textsf{hh:mm(+1)}{' # so we know the exact positions of min and hour if t1[12] == '(': # (+1), next day event.add('dtstart', datetime(y, m, dt, int(t1[7:9]), int(t1[10:12]), tzinfo=tz(panchangam.city.timezone)) + timedelta(1)) else: event.add('dtstart', datetime(y, m, dt, int(t1[7:9]), int(t1[10:12]), tzinfo=tz(panchangam.city.timezone))) if t2[12] == '(': # (+1), next day event.add('dtend', datetime(y, m, dt, int(t2[7:9]), int(t2[10:12]), tzinfo=tz(panchangam.city.timezone)) + timedelta(1)) else: event.add('dtend', datetime(y, m, dt, int(t2[7:9]), int(t2[10:12]), tzinfo=tz(panchangam.city.timezone))) if stext in festival_rules: festival_event = festival.HinduCalendarEventOld.make_from_dict(festival_rules[stext]) desc = festival_event.get_description_string(script=panchangam.script, include_url=True) else: logging.warning('No description found for festival %s!\n' % stext) event.add('description', desc.strip()) event.add_component(alarm) ics_calendar.add_component(event) elif stext.find('samApanam') != -1: # It's an ending event event.add('summary', jyotisha.custom_transliteration.tr(stext, panchangam.script)) event.add('dtstart', date(y, m, dt)) event.add('dtend', (datetime(y, m, dt) + timedelta(1)).date()) if stext in festival_rules: festival_event = festival.HinduCalendarEventOld.make_from_dict(festival_rules[stext]) desc = festival_event.get_description_string(script=panchangam.script, include_url=True) else: logging.warning('No description found for festival %s!' % stext) event.add_component(alarm) event.add('description', desc.strip()) event['X-MICROSOFT-CDO-ALLDAYEVENT'] = 'TRUE' event['TRANSP'] = 'TRANSPARENT' event['X-MICROSOFT-CDO-BUSYSTATUS'] = 'FREE' ics_calendar.add_component(event) # Find start and add entire event as well event = Event() check_d = d stext_start = stext.replace('samApanam', 'ArambhaH') start_d = None while check_d > 1: check_d -= 1 if stext_start in panchangam.festivals[check_d]: start_d = check_d break if start_d is None: logging.error('Unable to find start date for %s' % stext_start) else: # logging.debug(stext) event_summary_text = stext REPLACEMENTS = {'samApanam': '', 'rAtri-': 'rAtriH', 'nakSatra-': 'nakSatram', 'pakSa-': 'pakSaH', 'puSkara-': 'puSkaram', 'dIpa-': 'dIpaH', 'snAna-': 'snAnam', 'tsava-': 'tsavaH', 'vrata-': 'vratam'} for _orig, _repl in REPLACEMENTS.items(): event_summary_text = event_summary_text.replace(_orig, _repl) event.add('summary', jyotisha.custom_transliteration.tr(event_summary_text, panchangam.script)) event.add('dtstart', (datetime(y, m, dt) - timedelta(d - start_d)).date()) event.add('dtend', (datetime(y, m, dt) + timedelta(1)).date()) # print(event) event.add_component(alarm) event.add('description', desc.strip()) event['X-MICROSOFT-CDO-ALLDAYEVENT'] = 'TRUE' event['TRANSP'] = 'TRANSPARENT' event['X-MICROSOFT-CDO-BUSYSTATUS'] = 'FREE' ics_calendar.add_component(event) else: summary = jyotisha.custom_transliteration.tr(stext.replace('~', ' ').replace('\#', '#').replace('\\To{}', '▶'), panchangam.script) summary = re.sub('.tamil{(.*)}', '\\1', summary) summary = re.sub('{(.*)}', '\\1', summary) # strip braces around numbers event.add('summary', summary) fest_num_loc = stext.find('~\#') if fest_num_loc != -1: stext = stext[:fest_num_loc] event.add('dtstart', date(y, m, dt)) event.add('dtend', (datetime(y, m, dt) + timedelta(1)).date()) if re.match('.*-.*-EkAdazI', stext) is None and stext.find('saGkrAntiH') == -1: if stext in festival_rules: desc = festival.HinduCalendarEventOld.make_from_dict(festival_rules[stext]).get_description_string(script=panchangam.script, include_url=True) else: if re.match('aGgArakI.*saGkaTahara-caturthI-vratam', stext): stext = stext.replace('aGgArakI~', '') if stext in festival_rules: desc = festival.HinduCalendarEventOld.make_from_dict(festival_rules[stext]).get_description_string(script=panchangam.script) desc += 'When `caturthI` occurs on a Tuesday, it is known as `aGgArakI` and is even more sacred.' else: logging.warning('No description found for caturthI festival %s!' % stext) else: logging.warning('No description found for festival %s!' % stext) elif stext.find('saGkrAntiH') != -1: # Handle Sankranti descriptions differently planet_trans = stext.split('~')[0] # get rid of ~(rAshi name) etc. if planet_trans in festival_rules: desc = festival.HinduCalendarEventOld.make_from_dict(festival_rules[planet_trans]).get_description_string(script=panchangam.script, include_url=True) else: logging.warning('No description found for festival %s!' % planet_trans) else: # logging.debug(stext) # Handle ekadashi descriptions differently ekad = '-'.join(stext.split('-')[1:]) # get rid of sarva etc. prefix! if ekad in festival_rules: desc = festival.HinduCalendarEventOld.make_from_dict(festival_rules[ekad]).get_description_string(script=panchangam.script, include_url=True) else: logging.warning('No description found for Ekadashi festival %s (%s)!' % (ekad, stext)) pref = jyotisha.custom_transliteration.romanise(sanscript.transliterate( stext.split('-')[0], sanscript.HK, sanscript.IAST)) + "-" event.add_component(alarm) event.add('description', desc.strip()) event['X-MICROSOFT-CDO-ALLDAYEVENT'] = 'TRUE' event['TRANSP'] = 'TRANSPARENT' event['X-MICROSOFT-CDO-BUSYSTATUS'] = 'FREE' ics_calendar.add_component(event) if m == 12 and dt == 31: break return ics_calendar
def put2Calendar(): dfh = sortEvents() for i in range(0, len(dfh)): evt = Event() evt.add('summary', dfh.iloc[i]['SUMMARY']) evt.add('location', dfh.iloc[i]['LOCATION']) evt.add('description', dfh.iloc[i]['DESCRIPTION']) evt.add('dtstart', dfh.iloc[i]['DTSTART']) evt.add('dtend', dfh.iloc[i]['DTEND']) daftarCuti.add_component(evt)
startdate = date(year, startmonth, startday) startWeekday = startdate.weekday() delta = 0 while (startWeekday not in courseStartWeekdays): delta += 1 startWeekday += 1 if (startWeekday > 6): startWeekday = 0 startdate += timedelta(days=delta) # Make .ics file cal = Calendar() cal.add('prodid', 'I School Course Calendar') cal.add('version', '2.0') event = Event() event.add('summary', coursetitle) event.add('location', course.location) event.add( 'dtstart', datetime(year, startdate.month, startdate.day, starthour, startminute, 0)) event.add( 'dtend', datetime(year, startdate.month, startdate.day, endhour, endminute, 0)) event.add('tzid', 'California-Los_Angeles') finishedt = datetime(year, endmonth, endday, 0, 0, 0) event.add('rrule', vRecur(freq='weekly', byday=coursedays, until=finishedt)) cal.add_component(event) f = open(coursetitle + '.ics', 'wb')
with open('in.csv', 'rt') as csvfile: print("Reading file") reader = csv.reader(csvfile, delimiter=',', quotechar='|') n = -1 for row in reader: n = n + 1 if n == 2: keys = row print("Keys: " + str(keys)) if n > 2: print(row) e = dict(zip(keys, row)) if e['Registration'] != "" and e['Host'] != "": event = Event() event.add('summary', e['Affiliation'] + e['Project']) print(e['date']) mins = 120 if e['duration [minutes - default=120]'] != "": mins = int(e['duration [minutes - default=120]']) print("meeting len " + str(mins)) start_date = datetime.strptime(e['date'] + '+0000', "%Y-%m-%d%z") start_time = get_start_time(start_date, e['UTC slot']) print('start time: ' + str(start_time)) event.add('dtstart', start_time) event.add('dtend', start_time + timedelta(minutes=mins)) event.add('location', e['Registration'] ) event.add('description', 'Host: ' + e['Host'] + "\nPlease refer to the registration URL for the connection details: " + e['Registration'])
from icalendar import UTC # timezone from icalendar import vCalAddress, vText scraperwiki.sqlite.attach('leikdagar-pepsi-deild-karla-2011') keys = scraperwiki.sqlite.execute( 'select * from `leikdagar_pepsi_deild_karla_2011` limit 0')['keys'] data = scraperwiki.sqlite.select('* from leikdagar_pepsi_deild_karla_2011') #print data #print keys cal = Calendar() cal.add('prodid', '-//My calendar product//mxm.dk//') cal.add('version', '2.0') event = Event() event.add('summary', 'Python meeting about calendaring') event.add('dtstart', datetime(2005, 4, 4, 8, 0, 0, tzinfo=UTC)) event.add('dtend', datetime(2005, 4, 4, 10, 0, 0, tzinfo=UTC)) event.add('dtstamp', datetime(2005, 4, 4, 0, 10, 0, tzinfo=UTC)) #organizer = vCalAddress('MAILTO:[email protected]' #organizer.params['cn'] = vText('Max Rasmussen') #organizer.params['role'] = vText('CHAIR') #event['organizer'] = organizer event['location'] = vText('Odense, Denmark') event['uid'] = '20050115T101010/[email protected]' event.add('priority', 5)
def get_icalendar_event(self): """ Builds an icalendar.event object from event data. """ icalendar_event = IEvent() icalendar_event.add('summary'.encode("utf-8"), self.title) icalendar_event.add( 'url', 'http://{domain}{url}'.format( domain=Site.objects.get(id=current_site_id()).domain, url=self.get_absolute_url(), )) if self.location: icalendar_event.add('location'.encode("utf-8"), self.location.address) icalendar_event.add('dtstamp', self.start) icalendar_event.add('dtstart', self.start) if self.end: icalendar_event.add('dtend', self.end) icalendar_event['uid'.encode("utf-8")] = "event-{id}@{domain}".format( id=self.id, domain=Site.objects.get(id=current_site_id()).domain, ).encode("utf-8") return icalendar_event
def to_ics(course_info, date_start_argu): print("正在生成日历……") date_start = date_start_argu cal = Calendar() cal['version'] = '2.0' cal['prodid'] = '-//LZU//roseauhan//CN' for item in course_info: event = Event() ev_start_date = date_start + relativedelta( weeks=(item['sWeek'] - 1), weekday=(item['day_of_week'] - 1)) ev_start_datetime = datetime.combine(ev_start_date, item['sTime']) # 上课时间 ev_end_datetime = datetime.combine(ev_start_date, item['eTime']) ev_interval = item['EvenOddWeek'] ev_count = item['eWeek'] - item['sWeek'] + 1 \ if not item['EvenOddWeek'] == 2 else item['eWeek'] - item['sWeek'] // 2 + 1 # 添加事件 event.add('uid', str(uuid1()) + '@LZU') event.add('summary', item['name']) event.add('dtstamp', datetime.now()) event.add('dtstart', ev_start_datetime) event.add('dtend', ev_end_datetime) event.add('location', item['location']) event.add('rrule', { 'freq': 'weekly', 'interval': ev_interval, 'count': ev_count }) event.add('comment', item['teacher']) cal.add_component(event) with open(filename, 'w+', encoding='utf-8') as file: file.write(cal.to_ical().decode('utf-8').replace('\r\n', '\n').strip()) print("已将所有课程生成日历!")
def make_event( summary:str, description:str, location:str, start_time:datetime, end_time:datetime, organizer:Participant, attendees:List[Participant] ): # make event object event = Event() # event uuid event["uid"] = str(uuid.uuid4()) # event summary event.add("summary", summary) # event description event.add("description", description) # event location event["location"] = vText(location) # event start date event.add("dtstart", start_time) # event end date event.add("dtend", end_time) # event entry creation event.add("dtstamp", datetime.utcnow()) # vent organizer event["organizer"] = organizer.to_ical() # event priority event.add('priority', 5) for attendee in attendees: event.add('attendee', attendee.to_ical(), encode=0) return event
def make_icalendar_data(uid, summary, current, end, begin, account_id, create_flag=False): """ Generate iCalendar data format message body. reference - https://developers.worksmobile.com/jp/document/1007011?lang=en """ cal = Calendar() cal.add('PRODID', 'Works sample bot Calendar') cal.add('VERSION', '2.0') standard = TimezoneStandard() standard.add('DTSTART', datetime(1970, 1, 1, 0, 0, 0, tzinfo=pytz.timezone(TZone))) standard.add('TZOFFSETFROM', current.utcoffset()) standard.add('TZOFFSETTO', current.utcoffset()) standard.add('TZNAME', current.tzname()) tz = Timezone() tz.add_component(standard) tz.add('TZID', tz) event = Event() event.add('UID', uid) if create_flag: event.add('CREATED', current) event.add('DESCRIPTION', account_id) event.add('SUMMARY', summary) event.add('DTSTART', begin) event.add('DTEND', end) event.add('LAST-MODIFIED', current) event.add('DTSTAMP', current) cal.add_component(event) cal.add_component(tz) schedule_local_string = bytes.decode(cal.to_ical()) LOGGER.info("schedule:%s", schedule_local_string) return schedule_local_string
def session_ical(session, rsvp=None): # This function is only called with scheduled sessions. # If for some reason it is used somewhere else and called with an unscheduled session, # this function should fail. if not session.scheduled: raise Exception("{0!r} is not scheduled".format(session)) event = Event() event.add('summary', session.title) organizer = vCalAddress( f'MAILTO:no-reply@{current_app.config["DEFAULT_DOMAIN"]}' # NOQA ) organizer.params['cn'] = vText(session.project.profile.title) event['organizer'] = organizer if rsvp: attendee = vCalAddress('MAILTO:' + str(rsvp.user_email())) attendee.params['RSVP'] = vText('TRUE') if rsvp.state.YES else vText( 'FALSE') attendee.params['cn'] = vText(rsvp.user.fullname) attendee.params['CUTYPE'] = vText('INDIVIDUAL') attendee.params['X-NUM-GUESTS'] = vText('0') event.add('attendee', attendee, encode=0) event.add( 'uid', f'session/{session.uuid_b58}@{current_app.config["DEFAULT_DOMAIN"]}', # NOQA ) # Using localized timestamps will require a `VTIMEZONE` entry in the ics file # Using `session.start_at` without `astimezone` causes it to be localized to # local timezone. We need `astimezone(utc)` to ensure actual UTC timestamps. event.add('dtstart', session.start_at.astimezone(utc)) event.add('dtend', session.end_at.astimezone(utc)) event.add('dtstamp', utcnow()) # Strangely, these two don't need localization with `astimezone` event.add('created', session.created_at) event.add('last-modified', session.updated_at) if session.venue_room: location = [ session.venue_room.title + " - " + session.venue_room.venue.title ] if session.venue_room.venue.city: location.append(session.venue_room.venue.city) if session.venue_room.venue.country: location[len(location) - 1] += ", " + session.venue_room.venue.country else: location.append(session.venue_room.venue.country) event.add('location', "\n".join(location)) if session.venue_room.venue.has_coordinates: event.add('geo', session.venue_room.venue.coordinates) if session.description: event.add('description', session.description.text) if session.proposal: event.add('url', session.url_for(_external=True)) if session.proposal.labels: event.add('categories', [label.title for label in session.proposal.labels]) alarm = Alarm() alarm.add('trigger', timedelta(minutes=-5)) alarm.add('action', 'display') if session.venue_room: desc = _("{session} in {venue} in 5 minutes").format( session=session.title, venue=session.venue_room.title) else: desc = _("{session} in 5 minutes").format(session=session.title) alarm.add('description', desc) event.add_component(alarm) return event
def build_calendar(daily_events, day2abrev, day2key, code2name, end_date, repeat): end_grad = datetime.datetime.strptime(end_date, '%Y-%m-%d') cal = Calendar() now = datetime.datetime.now() year = now.year month = now.month weekday = now.day days_left = end_grad - now if not repeat: weeks_left = int(days_left.days / 7) + 1 else: weeks_left = int(repeat) + 1 for day, events in daily_events.items(): next_day = now + datetime.timedelta(days=(day2key[day] - now.weekday()) % 7) next_day = next_day.day for ev in events: if ev: event = Event() begin = ev[0][0] end = ev[0][1] description = ev[1].split("-")[0] title = code2name[description] place = ev[2] event.add('summary', title) event.add('location', place) event.add('description', description) begin_hour, begin_minute = begin.split(":") end_hour, end_minute, end_second = end.split(":") event.add('dtstart', datetime.datetime(year, month, next_day, \ hour=int(begin_hour), minute=int(begin_minute))) event.add('dtend', datetime.datetime(year, month, next_day, \ hour=int(end_hour), minute=int(end_minute))) event['RRULE'] = vRecur({'COUNT': [weeks_left], \ 'FREQ': ['WEEKLY'], \ 'BYDAY': day2abrev[day]}) cal.add_component(event) return cal
cal.add('prodid', '-//w00d//UIUC Calendar prod//') cal.add('version', '2.0') today = date.today() daymap = ['M', 'T', 'W', 'R', 'F'] daymap_sd = ['MO', 'TU', 'WE', 'TH', 'FR'] lastmonday = today - timedelta(days=today.weekday()) for row in parser.this_table: print row day_study = row[2].split() date = lastmonday + timedelta(daymap.index(day_study[0])) time_start = gettime(row[3]) time_end = gettime(row[4]) byday = ([daymap_sd[daymap.index(d)] for d in day_study]) event = Event() event.add('summary', row[0]) event.add('description', row[1]) event.add('location', row[5]) event.add( 'dtstart', datetime(date.year, date.month, date.day, time_start[0], time_start[1], 0, tzinfo=pytz.timezone('America/Chicago'))) event.add( 'dtend', datetime(date.year,
e.add('last-modified', now) e.add('sequence', 0) for row in reader: if first: first = False continue event, _, _, _, _, _, _, _, _, date, weekno, weeks, lr, ltr, dev, ff, _, _ = row dt = datetime.strptime( date, '%Y-%m-%d').replace(tzinfo=timezone.utc) + timedelta(hours=12) if 'FF' in event: e = Event() e.add('summary', 'QGIS Feature Freeze {}'.format(dev)) e.add('dtstart', dt) e.add('dtend', dt) adduid(e, 'ff-{}@qgis.org'.format(dev)) cal.add_component(e) if 'SF' in event: e = Event() e.add('summary', 'QGIS Soft Freeze', dev) e.add('dtstart', dt) e.add('dtend', dt) adduid(e, 'sf-{}@qgis.org'.format(dev)) cal.add_component(e) if ltr:
def gen_ical(request): cal = Calendar() cal['version'] = '2.0' cal['prodid'] = '-//Prototype//Nanbeige//ZH' # *mandatory elements* where the prodid can be changed, see RFC 5445 user_profile = request.user.get_profile() # get current semester semesters = user_profile.campus.university.semester_set.all() today = date.today() for s in semesters: if today > s.week_start and today < s.week_end: semester = s break course_statuses = user_profile.coursestatus_set.filter( course__semester=semester).exclude(status=CourseStatus.CANCEL) university = user_profile.campus.university for course_status in course_statuses: for lesson in course_status.course.lesson_set.all(): if lesson.weekset == None: weekgroup = listify_int(lesson.weeks) else: weekgroup = listify_int(lesson.weekset.weeks) for recur in weekgroup: event = Event() event.add('summary', unify_brackets(course_status.course.name)) offset = timedelta(days=lesson.day - 1 + 7 * (int(recur) - 1)) classdate = semester.week_start + offset start = university.scheduleunit_set.get( number=lesson.start).start end = university.scheduleunit_set.get(number=lesson.end).end event.add('dtstart', datetime.combine(classdate, start)) event.add('dtend', datetime.combine(classdate, end)) event.add('location', lesson.location) event.add('description', u'教师:' + course_status.course.teacher) event['uid'] = str( uuid1()) + '@Nanbeige' # change after formal name...? cal.add_component(event) return HttpResponse(cal.to_ical(), mimetype="text/calendar")
def process_item(self, item, spider): cal = Calendar() cal.add('calscale', 'GREGORIAN') cal.add('version', '2.0') cal['method'] = 'PUBLISH' if item['exam'] != 'null': exam = Event() exam.add('summary', '%s exam %s' % (item['code'], item['exam']['time'])) starttime = datetime.combine( item['exam']['date'], time() if item['exam']['time'] == 'AM' else time( 12, 0)).replace(tzinfo=SGT()) setstartend(exam, starttime, starttime + 12 * hour) cal.add_component(exam) if item['lecture_time_table'] != 'null': for l in item['lecture_time_table']: for lec in l['sessions']: dow = lec['day'] ts = int(lec['starttime']) te = int(lec['endtime']) ts_hr, ts_min = ts / 100, ts % 100 te_hr, te_min = te / 100, te % 100 combstr = ','.join([ str(WEEK2ACTUAL[i - 1] + startweek - 1) for i in lec['occurence'] ]) lectureday = SEM_START + (dow - 1) * day lecture = Event() lecture.add('summary', '%s %s' % (item['code'], l['name'])) setstartend(lecture, lectureday + ts_hr * hour + ts_min * minute, lectureday + te_hr * hour + te_min * minute) lecture['rrule'] = 'FREQ=YEARLY;BYWEEKNO=%s;BYDAY=%s' % ( combstr, WEEKDAY[lec['day'] - 1]) lecture['location'] = lec['location'] cal.add_component(lecture) if item['tutorial_time_table'] != 'null': for t in item['tutorial_time_table']: for tut in t['sessions']: dow = tut['day'] ts = int(tut['starttime']) te = int(tut['endtime']) ts_hr, ts_min = ts / 100, ts % 100 te_hr, te_min = te / 100, te % 100 combstr = ','.join([ str(WEEK2ACTUAL[i - 1] + startweek - 1) for i in tut['occurence'] if i != 1 ]) #precautionary check tutday = SEM_START + (dow - 1) * day + ( WEEK2ACTUAL[ (tut['occurence'][0] if tut['occurence'][0] != 1 else tut['occurence'][1]) - 1 #another stupid check, tutorials really shouldn't start on 1st week. ] - 1) * week tutorial = Event() tutorial.add('summary', '%s %s' % (item['code'], t['name'])) setstartend(tutorial, tutday + ts_hr * hour + ts_min * minute, tutday + te_hr * hour + te_min * minute) tutorial['rrule'] = 'FREQ=YEARLY;BYWEEKNO=%s;BYDAY=%s' % ( combstr, WEEKDAY[tut['day'] - 1]) tutorial['location'] = tut['location'] cal.add_component(tutorial) f = open(os.path.join('ics', ('%s.ics' % item['code'].split()[0])), 'wb') f.write(cal.as_string()) f.close() return item
def make_ical(self, csv_configs=None): # type: (Dict[str, int]) -> Calendar """ Make iCal entries """ csv_configs = self._generate_configs_from_default(csv_configs) self.cal = Calendar() for row in self.csv_data: event = Event() event.add('summary', row[csv_configs['CSV_NAME']]) event.add('dtstart', row[csv_configs['CSV_START_DATE']]) event.add('dtend', row[csv_configs['CSV_END_DATE']]) event.add('description', row[csv_configs['CSV_DESCRIPTION']]) event.add('location', row[csv_configs['CSV_LOCATION']]) self.cal.add_component(event) return self.cal
if endTime == None: print 'course end time not availble. Skipping. Course_num: ', classId continue endTime = tempStartDate + ' ' + endTime endTime = datetime.strptime(endTime, '%Y-%m-%d %H:%M:%S') startTime = tempStartDate + ' ' + startTime startTime = datetime.strptime(startTime, '%Y-%m-%d %H:%M:%S') endDate = classesInfo[classId]['end_date'] + ' 00:00:00' endDate = datetime.strptime(endDate, '%Y-%m-%d %H:%M:%S') days = (endDate - startTime).days print 'startDate:', startTime print 'startDateEndTime', endTime print 'endDate:', endDate print 'days:', days weeks = days / 7 + 1 event = Event() if (classesInfo[classId]['topic'] != None): event.add( 'summary', classesInfo[classId]['topic'] + classesInfo[classId]['title']) else: event.add('summary', classesInfo[classId]['title']) event.add('dtstart', startTime) event.add('dtend', endTime) event.add('rrule', { 'freq': 'weekly', 'count': weeks }) event.add('location', classesInfo[classId]['room']) cal.add_component(event)
def make_ical(df, dir_output, filename, member): # カレンダーオブジェクトの生成 cal = Calendar() # カレンダーに必須の項目 cal.add('prodid', 'yu-9824') cal.add('version', '2.0') # タイムゾーン tokyo = pytz.timezone('Asia/Tokyo') for name, series in df.iteritems(): series_ = series[series.str.contains(member)] if name == '鍵閉め': start_td = datetime.timedelta(hours=17, minutes=45) # 17時間45分 elif name == 'ゴミ捨て': start_td = datetime.timedelta(hours=14) # 14時間 else: continue need_td = datetime.timedelta(hours=1) for date, cell in zip(series_.index, series_): # 予定の開始時間と終了時間を変数として得る. start_time = datetime.datetime.strptime(date, '%Y/%m/%d') + start_td end_time = start_time + need_td # Eventオブジェクトの生成 event = Event() # 必要情報 event.add('summary', name) # 予定名 event.add('dtstart', tokyo.localize(start_time)) event.add('dtend', tokyo.localize(end_time)) event.add('description', cell) # 誰とやるかを説明欄に記述 event.add('created', tokyo.localize(datetime.datetime.now())) # いつ作ったのか. # カレンダーに追加 cal.add_component(event) # カレンダーのファイルへの書き出し with open(os.path.join(dir_output, filename + member + '.ics'), mode='wb') as f: f.write(cal.to_ical())
def edt2ics( url: str, days_limit=999, # Big number of days by default notifier_type: str = None, notifier_url: str = None, ): """ Retrieves the timetable of the specified classroom for the specified period. """ # Retrieve the ajax token token_retrieve = requests.post(url, params).json()['result'] params['ajax_token'] = re.search(r"!=(\S+)\]", token_retrieve).group(1) params['id_class'] = re.search(r"\d+$", url).group(0) # Retrieve the planning with the new AJAX token edt_retrieve = requests.post(url, params).json()['result'] # Parse the xml and create a python readable object edt = ET.fromstring(edt_retrieve) # Variables for managing the days limit today = datetime.today() limit_date = today + timedelta(days=+days_limit) # Create a new calendar cal = Calendar() for evt in edt: evt = { 'course': evt.attrib['title'], 'teacher': evt.attrib['teacher'], 'date_start': datetime.strptime( evt.attrib['start'], '%Y-%m-%d %H:%M:%S' ), 'date_end': datetime.strptime( evt.attrib['end'], '%Y-%m-%d %H:%M:%S' ), } # fmt: off # (Disable black because it's not make petty things here :/) # Don't record the event if is already passed or if is after the # limit date. if ( evt['date_start'] > today and evt['date_start'] > limit_date or evt['date_start'] < today ): continue # fmt: on # Create iCalendar event and add it to the global calendar cal_event = Event( ) cal_event.add('DTSTART', evt['date_start']) cal_event.add('DTEND', evt['date_end']) if evt['teacher'] != ' ': summary = '{} - {}'.format(evt['course'], evt['teacher']) else: summary = evt['course'] cal_event.add('SUMMARY', summary) cal.add_component(cal_event) # Make a diff if the file already exists and/or write new changes with open('calendar.ics', 'a+', encoding='utf-8') as f: f.seek(0) # Put the cursor on the top file_content = f.read() # Convert CRLF to LF (for the condition) ical = cal.to_ical().decode('utf-8').replace('\r\n', '\n') # Writes the new file if the content have differences and if the new # ical variable have events in there if file_content != ical and ical != 'BEGIN:VCALENDAR\nEND:VCALENDAR\n': print('Writing a new ICS file.') f.truncate(0) f.write(ical) webhook_notifier(notifier_type, notifier_url) else: print('No updates found, nothing to do.') f.close()
def gen_ics(email, password): save_db(email, password) orders = save_db(email, password) cal = Calendar() cal.add('prodid', '-//My calendar product//rlk.cn//') cal.add('version', '2.0') cal.add('summary', '乘车信息') cal.add('X-WR-CALNAME', '乘车信息') for o in orders: (number, date, summary, detail) = o time = datetime.strptime(date, '%Y年%m月%d日%H:%M') event = Event() event.add('summary', summary) event.add('dtstart', time) event.add('dtend', time + timedelta(minutes=30)) event.add('description', detail) event.add('uid', number) create_time = datetime.today() event.add('create', create_time) event.add('last-modified', create_time) event.add('dtstamp', create_time) event.add('sequence', "0") cal.add_component(event) return cal.to_ical()
def events_to_ical(events, identifier): connection = db.connect() cursor = connection.cursor() ical = Calendar() ical.add('calscale', 'GREGORIAN') ical.add('prodid', '-//Oncall//Oncall calendar feed//EN') ical.add('version', '2.0') ical.add('x-wr-calname', '%s Oncall Calendar' % identifier) users = {} for event in events: username = event['user'] if username not in users: cursor.execute( ''' SELECT `user`.`full_name`, `contact_mode`.`name`, `user_contact`.`destination` FROM `user_contact` JOIN `contact_mode` ON `contact_mode`.`id` = `user_contact`.`mode_id` JOIN `user` ON `user`.`id` = `user_contact`.`user_id` WHERE `user`.`name` = %s ''', username) info = {'username': username, 'contacts': {}} for row in cursor: info['full_name'] = row[0] info['contacts'][row[1]] = row[2] users[username] = info user = users[username] # Create the event itself full_name = user.get('full_name', user['username']) cal_event = Event() cal_event.add('uid', 'event-%s@oncall' % event['id']) cal_event.add('dtstart', dt.fromtimestamp(event['start'], utc)) cal_event.add('dtend', dt.fromtimestamp(event['end'], utc)) cal_event.add('dtstamp', dt.utcnow()) cal_event.add( 'summary', '%s %s shift: %s' % (event['team'], event['role'], full_name)) cal_event.add( 'description', '%s\n' % full_name + '\n'.join([ '%s: %s' % (mode, dest) for mode, dest in user['contacts'].items() ])) # Attach info about the user oncall attendee = vCalAddress('MAILTO:%s' % user['contacts'].get('email')) attendee.params['cn'] = vText(full_name) attendee.params['ROLE'] = vText('REQ-PARTICIPANT') cal_event.add('attendee', attendee, encode=0) ical.add_component(cal_event) cursor.close() connection.close() return ical.to_ical()
def contacts_ics(): cal = Calendar() cal.add('prodid', vText('-//choochootrain//Auto-generated//EN')) cal.add('version', vText('2.0')) cal.add('calscale', vText('gregorian')) cal.add('method', vText('publish')) cal.add('x-wr-calname', vText('Birthdays')) cal.add('x-wr-timezone', vText('America/Los_Angeles')) cal.add('x-wr-caldesc', vText('Autogenerated calendar of birthday events')) conn = sqlite3.connect("data/contacts.db") cursor = conn.cursor() cursor.execute("SELECT * FROM contacts order by birthyear, birthmonth, birthday") for id, name, day, month, year in cursor.fetchall(): event = Event() event.add('summary', "%s's birthday" % name) start = datetime.datetime(day=day, month=month, year=year if year is not None else 2014) event.add('dtstart', vDDDTypes(start)) event.add('dtend', vDDDTypes(start + datetime.timedelta(days=1))) event.add('rrule', vRecur(freq='yearly')) cal.add_component(event) return Response(cal.to_ical(), mimetype="text/calendar")