예제 #1
0
def test_compare_simple():
    first = iCalendar()
    first.add('vevent')

    second = iCalendar()
    second.add('vevent')

    second_out = iCalendar()

    compare(first, second, second_out)
    assert len(first.contents) == 0
    assert len(second_out.contents) == 0
예제 #2
0
def test_compare_summary_diff2():
    first = iCalendar()
    first_vevent = first.add('vevent')
    first_vevent.add('summary').value = "Foo"

    second = iCalendar()
    second.add('vevent')
    second_out = iCalendar()

    compare(first, second, second_out)
    assert len(first.contents) == 1
    assert len(second_out.contents) == 1
예제 #3
0
def test_compare_dtend_duration_diff():
    first = iCalendar()
    first_vevent = first.add('vevent')
    first_vevent.add('dtstart').value = datetime(2001, 1, 1, 10, 0)
    first_vevent.add('dtend').value = datetime(2001, 1, 1, 11, 0)

    second = iCalendar()
    second_vevent = second.add('vevent')
    second_vevent.add('dtstart').value = datetime(2001, 1, 1, 10, 0)
    second_vevent.add('duration').value = timedelta(hours=2)
    second_out = iCalendar()

    compare(first, second, second_out)
    assert len(first.contents) == 1
    assert len(second_out.contents) == 1
예제 #4
0
def test_compare_dtend():
    first = iCalendar()
    first_vevent = first.add('vevent')
    first_vevent.add('dtstart').value = datetime(2001, 1, 1, 10, 0)
    first_vevent.add('dtend').value = datetime(2001, 1, 1, 11, 0)

    second = iCalendar()
    second_vevent = second.add('vevent')
    second_vevent.add('dtstart').value = datetime(2001, 1, 1, 10, 0)
    second_vevent.add('dtend').value = datetime(2001, 1, 1, 11, 0)
    second_out = iCalendar()

    compare(first, second, second_out)
    assert len(first.contents) == 0
    assert len(second_out.contents) == 0
예제 #5
0
def events_calendar(request, public=True):
    cache_key = 'calendar_%s' % ('public' if public else 'private')
    cached = cache.get(cache_key)
    if cached:
        return cached
    cal = vobject.iCalendar()
    cal.add('X-WR-CALNAME').value = ('Air Mozilla Public Events' if public
                                     else 'Air Mozilla Private Events')
    now = datetime.datetime.utcnow().replace(tzinfo=utc)
    events = list(Event.objects.approved()
                  .filter(start_time__lt=now, public=public)
                  .order_by('-start_time')[:settings.CALENDAR_SIZE])
    events += list(Event.objects.approved()
                        .filter(start_time__gte=now, public=public)
                        .order_by('start_time')[:settings.CALENDAR_SIZE])
    base_url = '%s://%s/' % (request.is_secure() and 'https' or 'http',
                             RequestSite(request).domain)
    for event in events:
        vevent = cal.add('vevent')
        vevent.add('summary').value = event.title
        vevent.add('dtstart').value = event.start_time
        vevent.add('dtend').value = (event.start_time +
                                     datetime.timedelta(hours=1))
        vevent.add('description').value = event.description
        if event.location:
            vevent.add('location').value = event.location.name
        vevent.add('url').value = base_url + event.slug + '/'
    icalstream = cal.serialize()
    response = http.HttpResponse(icalstream,
                                 mimetype='text/calendar; charset=utf-8')
    filename = 'AirMozillaEvents%s.ics' % ('Public' if public else 'Private')
    response['Content-Disposition'] = (
        'inline; filename=%s' % filename)
    cache.set(cache_key, response)
    return response
예제 #6
0
파일: views.py 프로젝트: mozilla/sheriffs
def all_dates(request, extra_filter=None, filename="Sheriff Duty.ics",
              summary=None):
    # by giving it a verbose filnema like 'Sheriff Duty.css' means it's
    # going to appear very nicely automatically on peoples iCal.
    cal = vobject.iCalendar()

    # always start on the first of this month
    today = datetime.date.today()
    first = datetime.date(today.year, today.month, 1)
    slots = (Slot.objects.filter(date__gte=first)
              .order_by('date')
              .select_related('user'))
    if extra_filter:
        slots = slots.filter(**extra_filter)
    base_url = '%s://%s' % (request.is_secure() and 'https' or 'http',
                            RequestSite(request).domain)
    home_url = base_url + reverse('cal.home')
    for slot in slots[:31]:
        event = cal.add('vevent')
        event.add('summary').value = (summary and summary or get_user_name(slot.user))
        event.add('dtstart').value = slot.date
        event.add('dtend').value = slot.date
        url = (home_url + '?cal_y=%d&cal_m=%d' %
               (slot.date.year, slot.date.month))
        event.add('url').value = url
        event.add('description').value = ('Sheriff Duty on %s' %
         slot.date.strftime(settings.DEFAULT_DATE_FORMAT))

    resp = http.HttpResponse(cal.serialize(),
                             mimetype='text/calendar;charset=utf-8')
    resp['Content-Disposition'] = 'inline; filename="%s"' % filename
    return resp
예제 #7
0
def generateIcal(startDate, endDate, data):
    fileName = 'timetable_%s-%s.ics' % (startDate, endDate)
    startDate = datetime.date(int(startDate[6:]), int(startDate[3:5]), int(startDate[:2]))
      
    cal = vobject.iCalendar()
    local_tz = gettz("Europe/Ljubljana")
    for key in data:
        if len(data[key]) > 0:
                
            for lecture in data[key]:
                delta = datetime.timedelta(days = key - 1)
                date = startDate + delta

                event = cal.add('vevent')
                event.add('summary').value = '%s (%s)' % (lecture[0], lecture[1])
                event.add('location').value = 'FERI - %s' % (lecture[2])
                event.add('dtstart').value = datetime.datetime(date.year, date.month, date.day, int(hours[lecture[3]][:2]), int(hours[lecture[3]][3:]), 0, tzinfo = local_tz)
                event.add('dtend').value = datetime.datetime(date.year, date.month, date.day, int(hours[lecture[4]][:2]), int(hours[lecture[4]][3:]), tzinfo = local_tz)

    icalstream = cal.serialize()

    with open(fileName, 'w') as file:
        file.write(icalstream)
                
    return fileName
예제 #8
0
def create_ical(request, slug):
    """ Creates an ical .ics file for an event using vobject. """
    event = get_object_or_404(Event, slug=slug)
    # convert dates to datetimes.
    # when we change code to datetimes, we won't have to do this.
    start = event.start_date
    start = datetime.datetime(start.year, start.month, start.day)

    if event.end_date:
        end = event.end_date
        end = datetime.datetime(end.year, end.month, end.day)
    else:
        end = start

    cal = vobject.iCalendar()
    cal.add('method').value = 'PUBLISH'
    vevent = cal.add('vevent')
    vevent.add('dtstart').value = start
    vevent.add('dtend').value = end
    vevent.add('dtstamp').value = datetime.datetime.now()
    vevent.add('summary').value = event.name
    response = HttpResponse(cal.serialize(), content_type='text/calendar')
    response['Filename'] = 'filename.ics'
    response['Content-Disposition'] = 'attachment; filename=filename.ics'
    return response
예제 #9
0
	def __init__(self, list):
		if not list:
			raise RuntimeError("You must define at least one GitHubIssue \
				object")


		self.cal = vobject.iCalendar()

		for issues in list:
			if type(issues) != GitHubIssues:
				raise RuntimeError("All arguments have to be GitHubIssues \
					objects")

			for issue in issues.get():
				todo = self.cal.add('vtodo')

				todo.add('summary').value = issue['title']
				todo.add('description').value = issue['body']
				# FIXME: repo name as a location? any better ideas?
				todo.add('location').value = issues.repo

				created = date(issue['created_at'])
				todo.add('dtstart').value = \
				todo.add('dtstamp').value = \
				todo.add('created').value = created

				todo.add('last-modified').value = date(issue['updated_at'])

				# if the issue has a milestone with due on date
				if issue['milestone']:
					if not issue['milestone']['due_on']:
						continue

					todo.add('due').value = date(issue['milestone']['due_on'])
예제 #10
0
 def get(self, request, *args, **kwargs):
     cal = vobject.iCalendar()
     cal.add('x-wr-calname').value = 'Studentenportal Events'
     cal.add('x-wr-timezone').value = 'Europe/Zurich'
     for event in models.Event.objects.all():
         vevent = cal.add('vevent')
         vevent.add('summary').value = event.summary
         vevent.add('description').value = event.description
         if event.start_time:
             dtstart = datetime.datetime.combine(event.start_date,
                                                 event.start_time)
         else:
             dtstart = event.start_date
         vevent.add('dtstart').value = dtstart
         if event.end_date or event.end_time:
             if not event.end_date:
                 dtend = datetime.datetime.combine(event.start_date,
                                                   event.end_time)
             elif event.end_time:
                 dtend = datetime.datetime.combine(event.end_date,
                                                   event.end_time)
             else:
                 dtend = datetime.datetime.combine(
                     event.end_date, datetime.time(23, 59, 59))
             vevent.add('dtend').value = dtend
         if event.author:
             vevent.add(
                 'comment').value = 'Erfasst von %s' % event.author.name()
     return HttpResponse(cal.serialize(), content_type='text/calendar')
예제 #11
0
    def test0050create_event_attendee(self):
        'Create event with attendee'
        ical = vobject.iCalendar()
        vevent = ical.add('vevent')
        vevent.add('summary')
        vevent.summary.value = 'Test event with attendee'
        vevent.add('dtstart')
        vevent.dtstart.value = datetime.datetime.now() + relativedelta(days=10)
        vevent.add('dtend')
        vevent.dtend.value = datetime.datetime.now() + relativedelta(days=10,
            hours=4)
        vevent.add('organizer')
        vevent.organizer.value = '*****@*****.**' % user
        attendees = []
        for name in ('foo', 'bar'):
            attendee = vobject.base.ContentLine('ATTENDEE', [], '')
            attendee.partstat_param = 'TENTATIVE'
            attendee.value = 'MAILTO:%[email protected]' % name
            attendees.append(attendee)
        vevent.attendee_list = attendees
        caldav.Event(self.client, data=ical.serialize(),
            parent=self.calendar).save()

        Event = Model.get('calendar.event')
        owner_event, = Event.find([
                ('calendar.owner.email', '=', '*****@*****.**' % user),
                ('summary', '=', vevent.summary.value),
                ])
        attendee_event, = Event.find([
                ('calendar.owner.email', '=', '*****@*****.**'),
                ])
        self.assertEqual(attendee_event.uuid, owner_event.uuid)
예제 #12
0
def upcomingical(request):
    '''
    upcomingical(request)

    Returns the calendar of conferences as an ical file.
    '''
    try:
        import vobject
    except ImportError:
        return HttpResponse('import vobject failed in confereces/views.py:upcomingical')
    def _add_event(summary, start, end=None):
        if end is None:
            end = start
        rep = cal.add('vevent')
        rep.add('summary').value = summary
        rep.add('dtstart').value = start
        rep.add('dtend').value = end
    events = Conference.objects.filter(start__gte=datetime.datetime.now()).order_by('start')
    cal = vobject.iCalendar()
    for ev in events:
        _add_event(summary=ev.summary(), start=ev.start, end=ev.end)
        if ev.submission_deadline:
            _add_event(summary=('%s deadline' % ev.short_name), start=ev.submission_deadline)
            _add_event(summary=('%s deadline in 21 days' % ev.short_name), start=(ev.submission_deadline - datetime.timedelta(days=21)))
    response = HttpResponse(cal.serialize())
    response['Content-Type'] = 'text/calendar'
    return response
예제 #13
0
def icalFeed(request, tag):
    cal = vobject.iCalendar()
    cal.add('CALSCALE').value = 'GREGORIAN'
    cal.add('METHOD').value = 'PUBLISH'
    cal.add('X-WR-CALNAME').value = tag + ' Events'
    cal.add('X-WR-TIMEZONE').value = 'America/New_York'
    cal.add('X-WR-CALDESC').value = 'Calendar of campus events. Filter:'+tag
    
    filteredEvents = Event.objects.filter(event_date_time_end__lte=datetime.now()).order_by('event_date_time_start')
    if not tag == "All":
        filteredEvents = filteredEvents.filter(event_cluster__cluster_tags__category_name=tag)
    
    for event in filteredEvents[0:200]:
        vevent = cal.add('VEVENT')
        vevent.add('SUMMARY').value = smart_unicode(str(event))
        vevent.add('DTSTART').value = event.event_date_time_start
        vevent.add('DTEND').value = event.event_date_time_end
        
        vevent.add('LOCATION').value = unicode(event.getGCalLocation())
        vevent.add('DESCRIPTION').value = unicode(event.getGCalClusterDes() + "\n\n" + event.getGCalEventDes())

    icalstream = cal.serialize()
    response = HttpResponse(icalstream, mimetype='text/calendar')
    response['Content-Type'] = 'text/calendar; charset=utf-8'
#     response['Transfer-Encoding'] = 'chunked'
    response['Connection'] = 'close'
    response['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate'
    response['Pragma'] = 'no-cache'
    return response
예제 #14
0
파일: views.py 프로젝트: jeKnowledge/gestor
def action_ical(request,username):
	user = get_object_or_404(User,username=username)
	todos = user.actionitem_todo.filter(done=False)
	filename = "JK_Gestor_ActionItems.ics"
	
	import vobject
	import datetime
	
	cal = vobject.iCalendar()
	cal.add('method').value = 'PUBLISH'  # IE/Outlook needs this
	
	for actionitem in todos:
		vtodo = cal.add('vtodo')
		vtodo.add('summary').value = actionitem.title
		
		# TODO: escaping this stuff
		# vtodo.add('description').value = actionitem.description
		
		vtodo.add('due;value=date').value = actionitem.due_date.strftime("%Y%m%d")
		vtodo.add('priority').value = "0"
		
	
	icalstream = cal.serialize()
	response = HttpResponse(icalstream, mimetype='text/calendar')
	response['Filename'] = filename  # IE needs this
	response['Content-Disposition'] = 'attachment; filename='+filename
	return response
예제 #15
0
파일: events.py 프로젝트: kichkasch/pisi
    def initFromAttributes(self,  rrule,  dtstart,  dtend = None,  isAllDay = False):   
        """
        Initialize a recurrence from the information chunks
        """
        self._rrule = rrule
        self._dtstart = dtstart
        self._dtend = dtend
        self._allDay = isAllDay
                                
        data = self._rrule.serialize() + self._dtstart.serialize()
        if self._dtend:
            data += dtend.serialize()
            
        if type(self._dtstart.value) == datetime.date or self._dtstart.serialize().strip().endswith("Z"):  # special handling for all day recurrences and UTCs
            frame = vobject.iCalendar()
            frame.add("standard")
            frame.standard = vobject.icalendar.TimezoneComponent(UTC())
            data += frame.standard.serialize()

#        file = open("/tmp/pisi-ics.data", "w")
#        file.write("from attributes")
#        file.write(data)
#        file.close()
#        import os
#        os.system("gedit /tmp/pisi-ics.data")
        self._data = data
예제 #16
0
파일: views.py 프로젝트: esteluk/reinhardt
def ical_feed2(request):
    '''
    Generates an ical sync of all events in the future
    '''
    cal = vobject.iCalendar()

    tz = timezone(TIME_ZONE)
    utc = timezone('GMT')
    # IE/Outlook needs this:
    cal.add('method').value = 'PUBLISH'
    # Only publish events in the future
    for event in filter(lambda e: e.is_in_future(),Event.objects.order_by('start').exclude(displayFrom__gte=datetime.now())):
        total = str(event.signup_total()) if event.signup_total() else u'\u221E'
        signups = u' [%i/%s]' % (event.signup_count(),total) if event.has_signups() else u''
        vevent = cal.add('vevent')
        vevent.add('summary').value = event.type.name + (' - ' + event.shortDescription if event.shortDescription else event.type.name) + signups
        vevent.add('location').value = str(event.location)
        vevent.add('dtstart').value = tz.localize(event.start).astimezone(utc)
        vevent.add('dtend').value = tz.localize(event.finish).astimezone(utc)
        vevent.add('dtstamp').value = tz.localize(event.creation_time()).astimezone(utc) # again, for Outlook
        vevent.add('description').value = event.longDescription
        vevent.add('sequence').value = str(event.update_count()) # for updates
        vevent.add('categories').value = [event.type.get_target_display()]
        url = "http://%s/events/details/%i/" % (Site.objects.get_current() , event.id)
        vevent.add('uid').value = url
        vevent.add('url').value = url
    response = HttpResponse(cal.serialize(), mimetype='text/calendar; charset=UTF-8')
    response['Filename'] = 'compsoc.ics'  # IE needs this
    response['Content-Disposition'] = 'attachment; filename=compsoc.ics'
    return response
예제 #17
0
 def create_collection(cls, href, collection=None, tag=None):
     folder = os.path.expanduser(
         cls.configuration.get("storage", "filesystem_folder"))
     path = path_to_filesystem(folder, href)
     if not os.path.exists(path):
         os.makedirs(path)
     if not tag and collection:
         tag = collection[0].name
     self = cls(href)
     if tag == "VCALENDAR":
         self.set_meta("tag", "VCALENDAR")
         if collection:
             collection, = collection
             for content in ("vevent", "vtodo", "vjournal"):
                 if content in collection.contents:
                     for item in getattr(collection, "%s_list" % content):
                         new_collection = vobject.iCalendar()
                         new_collection.add(item)
                         self.upload(uuid4().hex, new_collection)
     elif tag == "VCARD":
         self.set_meta("tag", "VADDRESSBOOK")
         if collection:
             for card in collection:
                 self.upload(uuid4().hex, card)
     return self
예제 #18
0
def response_as_ical(request, occurrences):

    ical = iCalendar()

    cal_name = settings.ICAL_CALNAME
    # If multiple occurrences with one event, name the calendar after the event
    if hasattr(occurrences, "__iter__"):
        events = list(set([o.event for o in occurrences]))
        if len(events) == 1:
            cal_name = unicode(events[0])
    # If a single occurrence with an event
    elif getattr(occurrences, "event", None):
        cal_name = unicode(occurrences.event)

    ical.add("X-WR-CALNAME").value = cal_name
    ical.add("X-WR-CALDESC").value = settings.ICAL_CALDESC
    ical.add("method").value = "PUBLISH"  # IE/Outlook needs this

    if hasattr(occurrences, "__iter__"):
        for occ in occurrences:
            ical = occ.as_icalendar(ical, request)
    else:
        ical = occurrences.as_icalendar(ical, request)

    icalstream = ical.serialize()
    response = HttpResponse(icalstream, mimetype="text/calendar")
    response["Filename"] = "events.ics"  # IE needs this
    response["Content-Disposition"] = "attachment; filename=events.ics"
    return response
예제 #19
0
    def get_ical(self, obj, request):
        """ Returns a populated iCalendar instance. """
        cal = vobject.iCalendar()
        cal.add('method').value = 'PUBLISH'  # IE/Outlook needs this
        items = self.__get_dynamic_attr("items", obj)
        cal_name = self.__get_dynamic_attr("cal_name", obj)
        cal_desc = self.__get_dynamic_attr("cal_desc", obj)
        # Add calendar name and description if set 
        if cal_name:
            cal.add('x-wr-calname').value = cal_name
        if cal_desc:
            cal.add('x-wr-caldesc').value = cal_desc

        if get_current_site:
            current_site = get_current_site(request)
        else:
            current_site = None

        for item in items:
            event = cal.add('vevent')
            for vkey, key in EVENT_ITEMS:
                value = self.__get_dynamic_attr(key, item)
                if value:
                    if vkey == 'rruleset':
                        event.rruleset = value
                    else:
                        if vkey == 'url' and current_site:
                            value = add_domain(
                                current_site.domain,
                                value,
                                request.is_secure(),
                            )
                        event.add(vkey).value = value
        return cal
예제 #20
0
 def calendar_ics(self,**kwargs):
     #Build list of courses.
     courses = []
     for i in range(1,MAX_COURSES +1):
         if kwargs['course%dname' % i] == '':
             continue
         courses.append({
             'name':kwargs['course%dname' %i],
             'location':kwargs['course%dlocation' %i],
             'slot':kwargs['course%dslot' %i],
             'tutlocation':kwargs['tutorial%dlocation' %i],
             'tutslot':kwargs['tutorial%dslot' %i]
             })
     for course in courses:
         if course['slot'] not in self.slots:
             try:
                 self.parseTimes(course['slot'])
             except:
                 return self.invalidSlot(course)
         if course['tutslot'] != '' and course['tutslot'] not in self.slots:
             try:
                 self.parseTimes(course['tutslot'])
             except:
                 return self.invalidSlot(course)
     cal = vobject.iCalendar()
     for course in courses:
         self.addToCalendar(cal,course)
     cherrypy.response.headers['Content-Type']= 'text/calendar'
     return cal.serialize()
예제 #21
0
파일: stupl.py 프로젝트: janLo/htw-schedule
def make_ical(data, sources):
    calweek_regex = re.compile(r'^(\d+)\. KW$')
    time_regex = re.compile(r'^(\d+)\.(\d+) - (\d+)\.(\d+)$')
    room_regex = re.compile(r'^(.*) - (.*)$')

    times = {}
    for time in data[0]['order']:
        matches = time_regex.match(time)
        if not matches:
            raise CannotParseTime("String was: %s" % time)
        newtime = {'start': rd.relativedelta(hour=int(matches.group(1)), minute=int(matches.group(2))),
                   'end': rd.relativedelta(hour=int(matches.group(3)), minute=int(matches.group(4)))}
        times[time] = newtime

    calendar = vobject.iCalendar()

    cat_map = {u"V": u"Vorlesung",
               u"Ü": u"Übung",
               u"P": u"Praktikum"}

    begin_date = None
    for week in data:
        if not begin_date:
            calweek = calweek_regex.match(week['week'])
            if not calweek:
                raise CannotParseCalweek("String was: %s" % week['week'])
            calweek = int(calweek.group(1))
            begin_date = datetime.now() + rd.relativedelta(month=1, day=4, weekday=rd.MO(-1), weeks=+(calweek - 1), hour=0, minute=0, second=0, microsecond=0)
        else:
            begin_date = begin_date + rd.relativedelta(weeks=+1)

        for day in range(0,5):
            day_data = week['data'][day]
            day_date = begin_date + rd.relativedelta(days=+day)
            for time in day_data:
                for entry in day_data[time]:
                    event = calendar.add('vevent')
                    event.add('dtstart').value = day_date + times[time]["start"]
                    event.add('dtend').value = day_date + times[time]["end"]
                    cat = ""
                    if entry["typ"][0] in cat_map:
                        event.add('categories').value = ["UNI:" + cat_map[entry["typ"][0]]]
                        cat = " (%s)" % cat_map[entry["typ"][0]]

                    teacher = entry["room"]
                    room_match = room_regex.match(entry["room"])
                    if room_match:
                        event.add('location').value = room_match.group(1).strip()
                        teacher = room_match.group(2)

                    event.add('summary').value = "%s%s" % (entry['name'], cat)
                    event.add('description').value = u"Kürzel: %s\nDozent: %s\nVeranstaltungsdyp: %s\nQuelle:%s" % (entry["short"],
                                                                     teacher,
                                                                     entry["typ"],
                                                                     sources[entry['source']].string)
                    uid = uuid.uuid3(uuid.NAMESPACE_DNS, '%s %s' % (str(event.location.value),
                                                                    str(event.dtstart.value)))
                    event.add("uid").value = str(uid)

    return calendar.serialize()
예제 #22
0
파일: views.py 프로젝트: peterbe/airmozilla
def events_calendar(request, public=True):
    cache_key = "calendar_%s" % ("public" if public else "private")
    cached = cache.get(cache_key)
    if cached:
        return cached
    cal = vobject.iCalendar()
    cal.add("X-WR-CALNAME").value = "Air Mozilla Public Events" if public else "Air Mozilla Private Events"
    now = datetime.datetime.utcnow().replace(tzinfo=utc)
    events = list(
        Event.objects.approved()
        .filter(start_time__lt=now, public=public)
        .order_by("-start_time")[: settings.CALENDAR_SIZE]
    )
    events += list(
        Event.objects.approved()
        .filter(start_time__gte=now, public=public)
        .order_by("start_time")[: settings.CALENDAR_SIZE]
    )
    base_url = "%s://%s/" % (request.is_secure() and "https" or "http", RequestSite(request).domain)
    for event in events:
        vevent = cal.add("vevent")
        vevent.add("summary").value = event.title
        vevent.add("dtstart").value = event.start_time
        vevent.add("dtend").value = event.start_time + datetime.timedelta(hours=1)
        vevent.add("description").value = unhtml(short_desc(event))
        if event.location:
            vevent.add("location").value = event.location.name
        vevent.add("url").value = base_url + event.slug + "/"
    icalstream = cal.serialize()
    response = http.HttpResponse(icalstream, mimetype="text/calendar; charset=utf-8")
    filename = "AirMozillaEvents%s.ics" % ("Public" if public else "Private")
    response["Content-Disposition"] = "inline; filename=%s" % filename
    cache.set(cache_key, response)
    return response
예제 #23
0
파일: ical.py 프로젝트: mattoc/slug
def handler(request):
    """Handler which outputs an iCal feed."""

    cal = vobject.iCalendar()

    # /ical/<key>
    try:
        # If a key is passed, return just that Event
        unused_ical, key = request.path_info.split('/')

        event = shortcuts.get_object_or_404(models.Event, pk=key)
        self.add_event(request.get_host(), event, cal)
    except IndexError:
        # else whole calendar.
        future_events = event_lists.get_future_events()
        current_events = event_lists.get_current_events()

        for event, _, _ in current_events.events:
            self.add_event(request.get_host(), event, cal)
        for event, _, _ in future_events.events:
            self.add_event(event, cal)

    response = http.HttpResponse()
    response['Content-Type'] = 'text/x-vCalendar'
    response.write(cal.serialize())
    return response
예제 #24
0
def event_ical(request):
    event_list = Event.objects.filter(date__gte=datetime.now()-timedelta(weeks=4)).order_by('date')
    cal = vobject.iCalendar()
    cal.add('method').value = 'PUBLISH'  # IE/Outlook needs this
    cal.add('x-wr-calname').value = "Subterrarium intern"
    for event in event_list:
        url = settings.SITE_URL + reverse('event', args=[event.id])
        date = event.date - settings.EVENT_TIMEZONE.utcoffset(event.date)
        vevent = cal.add('vevent')
        if event.date.hour == 0 and event.date.minute == 0:
            vevent.add('X-FUNAMBOL-ALLDAY').value = '1'
            vevent.add('dtstart').value = datetime.date(event.date)
            vevent.add('dtend').value = datetime.date(event.date) + timedelta(days=1)
        else:
            vevent.add('dtstart').value = date
            vevent.add('dtend').value = date + timedelta(hours = 2)
        vevent.add('dtstamp').value = datetime.now()
        vevent.add('summary').value = event.title
        vevent.add('url').value = url
        vevent.add('uid').value = "%s-%s" % (event.id, settings.EVENT_REMINDER_FROM)
        vevent.add('description').value = url + "\n" + event.info
    icalstream = cal.serialize()
    response = HttpResponse(icalstream, mimetype='text/calendar; charset=utf-8')
    response['Filename'] = 'subkoordinator.ics'  # IE needs this
    response['Content-Disposition'] = 'attachment; filename=subkoordinator.ics'
    return response
예제 #25
0
    def __call__(self, *args, **kwargs):
        response = HttpResponse()

        cal = vobject.iCalendar()
        cal.add('X-WR-CALNAME').value = getattr(self, "name")()
        cal.add('X-WR-CALDESC').value = getattr(self, "description")()
        cal.add('X-WR-TIMEZONE').value = getattr(self, "timezone")()
        cal.add('CALSCALE').value = "GREGORIAN"
        cal.add('METHOD').value = "PUBLISH"

        for item in self.items():

            event = cal.add('vevent')

            for vkey, key in EVENT_ITEMS:
                value = getattr(self, 'item_' + key)(item)
                if isinstance(value, str):
                    value = smart_unicode(value)
                if value:
                    event.add(vkey).value = value

        locale.setlocale(locale.LC_ALL, 'fr_CA.UTF8')
        response = HttpResponse(cal.serialize())
        response['Content-Type'] = 'application/octet-stream; charset=utf-8'
        return response
예제 #26
0
    def __call__(self, *args, **kwargs):
        self.args = args
        self.kwargs = kwargs

        cal = vobject.iCalendar()
        tz = pytz.timezone(settings.TIME_ZONE)

        for item in self.items():

            event = cal.add('vevent')

            for vkey, key in EVENT_ITEMS:
                value = getattr(self, 'item_' + key)(item)
                if value:
                    event.add(vkey).value = value

            rule = item.get_rrule_object(tz)
            if rule:
                event.add('rrule').value = reqstr(rule)


        response = HttpResponse(cal.serialize())
        response['Content-Type'] = 'text/calendar'

        return response
예제 #27
0
파일: views.py 프로젝트: bettse/pygl
def total_cal(request, account):
    parameters = ['-E', '-p', 'daily', '-J', '-d', 'd>=[today]-14 & d < [tomorrow]',  '--sort', 'd', 'reg', '^' + account]
    output = runledger(parameters)

    cal = vobject.iCalendar()
    cal.add('method').value = 'PUBLISH'  # IE/Outlook needs this
    cal.add('x-wr-calname').value = prettyname(account) + " Balance"
    cal.add('X-WR-TIMEZONE').value = "US/Pacific"
    cal.add('X-WR-CALDESC').value = "Daily Balance of account " + account

    for line in output.split('\n'):
        if(line == ""):
            continue
        date, total = line.split(' ')

        vevent = cal.add('vevent')
        vevent.add('summary').value = moneyFmt(float(total), 0)
        vevent.add('dtstart').value = datetime.datetime.strptime(date, "%Y-%m-%d").date()

    icalstream = cal.serialize()
    response = HttpResponse(icalstream, mimetype='text/calendar')
    response['Filename'] = 'ledger-balance.ics'  # IE needs this
    response['Content-Disposition'] = 'attachment; filename=ledger-balance.ics'

    return response
예제 #28
0
def send(dbcal, calendar, client):
    n = 0
    for obj in dbcal.event_set.filter(user_modified=True):
        dblogger.info("Gonna send %s", obj)
        n += 1

        mycal = vobject.iCalendar()
        #~ mycal.add('vevent')

        #~ mycal = vobject.iCalendar()
        #~ vevent = vobject.newFromBehavior('vevent', '2.0')
        vevent = mycal.add('vevent')
        vevent.add('uid').value = obj.uid
        vevent.add('dtstamp').value = obj.modified
        if obj.start_time:
            vevent.add('dtstart').value = datetime.datetime.combine(
                obj.start_date, obj.start_time)
        else:
            vevent.add('dtstart').value = obj.start_date
        if obj.end_time:
            vevent.add('dtend').value = datetime.datetime.combine(
                obj.end_date, obj.end_time)
        else:
            vevent.add('dtend').value = obj.end_date
        vevent.add('transp').value = iif(
            obj.transparent, 'TRANSPARENT', 'OPAQUE')
        vevent.add('summary').value = obj.summary
        if obj.place:
            vevent.add('location').value = obj.place.name
        vevent.add('description').value = obj.description
        event = caldav.Event(
            client, data=mycal.serialize(), parent=calendar).save()
    dblogger.info("--> Sent %d events to calendar server.", n)
예제 #29
0
파일: views.py 프로젝트: bettse/pygl
def xacts_cal(request, account):
    parameters = ['-F', '%(date)\t%(payee)\t%(amount)\n', '-d', 'd>=[today]-14 & d < [tomorrow]',  '--sort', 'd', 'reg', '^' + account]
    output = runledger(parameters)

    cal = vobject.iCalendar()
    cal.add('method').value = 'PUBLISH'  # IE/Outlook needs this
    cal.add('x-wr-calname').value = prettyname(account) + " Events"
    cal.add('X-WR-TIMEZONE').value = "US/Pacific"
    cal.add('X-WR-CALDESC').value = "Daily events of account " + account

    for line in output.split('\n'):
        if(line == ""):
            continue
        date, payee, amount = line.split('\t')

        vevent = cal.add('vevent')
        vevent.add('summary').value = payee + "\t" + amount
        vevent.add('dtstart').value = datetime.datetime.strptime(date, "%Y/%m/%d").date()

    icalstream = cal.serialize()
    response = HttpResponse(icalstream, mimetype='text/calendar')
    response['Filename'] = 'ledger-events.ics'  # IE needs this
    response['Content-Disposition'] = 'attachment; filename=ledger-events.ics'

    return response
예제 #30
0
def schedule():
    form = FORM(
            INPUT(_name='user_email', requires=IS_NOT_EMPTY()),
            TEXTAREA(_name="schedule_text", requires=IS_NOT_EMPTY()),
            INPUT(_type='submit'))
    if form.process().accepted:
        session.user_email = form.vars.user_email
        session.raw_schedule = form.vars.schedule_text
        #redirect(URL('second'))
        #Here is where we process the raw form data and create a vobject ical object


        m = re.search("(\w{1,})\s(\d{1,}),\s(\d{4})", session.raw_schedule)
        dt = m.group(0)

        start_date = datetime.strptime(dt, "%b %d, %Y")
        
        return dict(result="success", email=session.user_email, raw_schedule=session.raw_schedule)

    cal = vobject.iCalendar()
    cal.add('vevent')
    cal.vevent.add('summary').value = "This is a note"

       # return dict(email=session.user_email, text=session.schedule_text)
    return dict(form=form)
예제 #31
0
    def process_read(self, cr, uid, node, context=None):
        """
            @param self: The object pointer
            @param cr: the current row, from the database cursor,
            @param uid: the current user’s ID for security checks,
            @param node: pass the node
            @param context: A standard dictionary for contextual values
        """
        def ics_datetime(idate, short=False):
            if short:
                return datetime.date.fromtimestamp(
                    time.mktime(time.strptime(idate, '%Y-%m-%d')))
            else:
                return datetime.datetime.strptime(idate, '%Y-%m-%d %H:%M:%S')

        if node.extension != '.ics':
            return super(document_directory_content,
                         self).process_read(cr, uid, node, context)

        import vobject
        ctx = (context or {})
        ctx.update(node.context.context.copy())
        ctx.update(node.dctx)
        content = self.browse(cr, uid, node.cnt_id, ctx)
        if not content.object_id:
            return super(document_directory_content,
                         self).process_read(cr, uid, node, context)
        obj_class = self.pool.get(content.object_id.model)

        if content.ics_domain:
            domain = safe_eval(content.ics_domain, ctx)
        else:
            domain = []
        if node.act_id:
            domain.append(('id', '=', node.act_id))
        # print "process read clause:",domain
        ids = obj_class.search(cr, uid, domain, context=ctx)
        cal = vobject.iCalendar()
        for obj in obj_class.browse(cr, uid, ids):
            event = cal.add('vevent')
            # Fix dtstamp et last-modified with create and write date on the object line
            perm = obj_class.perm_read(cr, uid, [obj.id], context)
            event.add('created').value = ics_datetime(
                time.strftime('%Y-%m-%d %H:%M:%S'))
            event.add('dtstamp').value = ics_datetime(
                perm[0]['create_date'][:19])
            if perm[0]['write_date']:
                event.add('last-modified').value = ics_datetime(
                    perm[0]['write_date'][:19])
            for field in content.ics_field_ids:
                if field.field_id.name:
                    value = getattr(obj, field.field_id.name)
                else:
                    value = None
                if (not value) and field.name == 'uid':
                    value = 'OpenERP-%s_%s@%s' % (
                        content.object_id.model,
                        str(obj.id),
                        cr.dbname,
                    )
                    # Why? obj_class.write(cr, uid, [obj.id], {field.field_id.name: value})
                if ICS_TAGS[field.name] == 'normal':
                    if type(value) == type(obj):
                        value = value.name
                    event.add(field.name).value = tools.ustr(value) or ''
                elif ICS_TAGS[field.name] == 'date' and value:
                    if field.name == 'dtstart':
                        date_start = start_date = datetime.datetime.fromtimestamp(
                            time.mktime(
                                time.strptime(value, "%Y-%m-%d %H:%M:%S")))
                    if field.name == 'dtend' and (isinstance(value, float)
                                                  or field.fn == 'hours'):
                        value = (start_date + datetime.timedelta(hours=value)
                                 ).strftime('%Y-%m-%d %H:%M:%S')
                    if len(value) == 10:
                        value = ics_datetime(value, True)
                    else:
                        value = ics_datetime(value)
                    event.add(field.name).value = value
        s = cal.serialize()
        return s
parser.add_argument("input", help="Flat JSON input file")
parser.add_argument("output", help="Output folder for calendar files")

args = parser.parse_args()

print("Using flat data file: " + args.input)

# Read flat data
with open(args.input) as input_file:
    data = load(input_file)

# Generate calendar file for each tour
for tour in data:
    tour_id = tour["tour_id"]

    cal = vobject.iCalendar()

    for event in tour["events"]:

        event_id = str(uuid.uuid4())
        event_start = datetime.strptime(event, "%Y-%m-%d")
        event_start = date(event_start.year, event_start.month,
                           event_start.day)
        event_end = event_start + timedelta(days=1)

        e = cal.add('vevent')
        e.add('uid').value = event_id
        e.add('summary').value = 'Blaue Tonne'
        e.add('dtstart').value = event_start
        e.add('dtend').value = event_end
예제 #33
0
    def ical(self, id):
        c.schedule_collection = Location.find_by_id(id).schedule

        ical = vobject.iCalendar()
        for schedule in c.schedule_collection:
            if not schedule.time_slot.heading:
                event = ical.add('vevent')
                event.add('uid').value = str(
                    schedule.id) + '@' + Config.get('event_host')
                # Created
                tz = timezone(Config.get('time_zone'))
                event.add(
                    'created').value = schedule.creation_timestamp.replace(
                        tzinfo=tz)
                # Last Modified
                event.add(
                    'dtstamp'
                ).value = schedule.last_modification_timestamp.replace(
                    tzinfo=tz)
                event.add(
                    'last-modified'
                ).value = schedule.last_modification_timestamp.replace(
                    tzinfo=tz)
                # Start and End Time
                event.add(
                    'dtstart').value = schedule.time_slot.start_time.replace(
                        tzinfo=tz)
                event.add('dtend').value = schedule.time_slot.end_time.replace(
                    tzinfo=tz)
                # Title and Author (need to add Author here)
                event.add('summary').value = schedule.event.computed_title(
                ) + '. ' + h.list_to_string(schedule.event.computed_speakers())
                # Abstract, if we have one
                event.add(
                    'description').value = schedule.event.computed_abstract()
                # Add a URL
                if schedule.event.proposal:
                    event.add('url').value = h.url_for(
                        qualified=True,
                        controller='schedule',
                        action='view_talk',
                        id=schedule.event.proposal.id)
                elif not (schedule.event.url is None
                          or schedule.event.url == ''):
                    if schedule.event.url.startswith(
                            'https://') or schedule.event.url.startswith(
                                'http://'):
                        event.add('url').value = h.url_for(
                            str(schedule.event.url))
                    else:
                        event.add('url').value = h.url_for(str(
                            schedule.event.url),
                                                           qualified=True)

                concurrent_schedules = schedule.event.schedule_by_time_slot(
                    schedule.time_slot)
                for concurrent_schedule in concurrent_schedules:
                    if concurrent_schedule != schedule:
                        if concurrent_schedule in c.schedule_collection:
                            c.schedule_collection.remove(concurrent_schedule)

                locations = [
                    concurrent_schedule.location.display_name
                    for concurrent_schedule in concurrent_schedules
                ]
                event.add('location').value = h.list_to_string(locations)

        response.charset = 'utf8'
        response.headers['content-type'] = 'text/calendar; charset=utf8'
        response.headers.add('content-transfer-encoding', 'binary')
        response.headers.add('Pragma', 'cache')
        response.headers.add('Cache-Control', 'max-age=3600,public')
        return ical.serialize()
예제 #34
0
def events_calendar_ical(request, privacy=None):
    cache_key = 'calendar'
    if privacy:
        cache_key += '_%s' % privacy
    if request.GET.get('location'):
        if request.GET.get('location').isdigit():
            location = get_object_or_404(Location,
                                         pk=request.GET.get('location'))
        else:
            location = get_object_or_404(Location,
                                         name=request.GET.get('location'))
        cache_key += str(location.pk)
        cached = None
    else:
        location = None
        cached = cache.get(cache_key)

    if cached:
        # additional response headers aren't remembered so add them again
        cached['Access-Control-Allow-Origin'] = '*'
        return cached
    cal = vobject.iCalendar()

    now = timezone.now()
    base_qs = Event.objects.approved()
    if privacy == 'public':
        base_qs = base_qs.filter(privacy=Event.PRIVACY_PUBLIC)
        title = 'Air Mozilla Public Events'
    elif privacy == 'private':
        base_qs = base_qs.exclude(privacy=Event.PRIVACY_PUBLIC)
        title = 'Air Mozilla Private Events'
    else:
        title = 'Air Mozilla Events'
    if location:
        base_qs = base_qs.filter(location=location)
    cal.add('X-WR-CALNAME').value = title
    events = list(
        base_qs.filter(start_time__lt=now).order_by('-start_time')
        [:settings.CALENDAR_SIZE])
    events += list(base_qs.filter(start_time__gte=now).order_by('start_time'))
    base_url = get_base_url(request)
    for event in events:
        vevent = cal.add('vevent')
        vevent.add('summary').value = event.title
        vevent.add('dtstart').value = event.start_time
        vevent.add('dtend').value = (
            event.start_time +
            datetime.timedelta(seconds=(event.duration or 3600)))
        vevent.add('description').value = short_desc(event, strip_html=True)
        if event.location:
            vevent.add('location').value = event.location.name
        vevent.add('url').value = base_url + event.slug + '/'
    icalstream = cal.serialize()
    # response = http.HttpResponse(
    #     icalstream,
    #     content_type='text/plain; charset=utf-8'
    # )
    response = http.HttpResponse(icalstream,
                                 content_type='text/calendar; charset=utf-8')
    filename = 'AirMozillaEvents%s' % (privacy and privacy or '')
    if location:
        filename += '_%s' % slugify(location.name)
    filename += '.ics'
    response['Content-Disposition'] = ('inline; filename=%s' % filename)
    if not location:
        cache.set(cache_key, response, 60 * 10)  # 10 minutes

    # https://bugzilla.mozilla.org/show_bug.cgi?id=909516
    response['Access-Control-Allow-Origin'] = '*'

    return response
예제 #35
0
                      action="store",
                      type="string",
                      dest="icalfile",
                      help="iCalendar file output")

    (options, args) = parser.parse_args()

    if options.icalfile == "":
        options.icalfile = None

    if options.icalfile != None:
        options.icalfile = os.path.realpath(options.icalfile)

        files = glob.glob(options.files)

        combinedCalendar = vobject.iCalendar()

        for i in files:
            if (DEBUG):
                print("Opening '%s'.." % i)
            f = open(i, 'rb')
            if (DEBUG):
                print("Reading '%s'.." % i)
            contents = f.read()
            out = open('%s_modded.ics' % i, 'w')
            s = []
            for sentence in contents:
                s.append(sentence)
                if (sentence == "\n"):
                    check_property = (''.join([str(x) for x in s]))
                    check_property = check_property.replace(
예제 #36
0
    def create_collection(cls, href, collection=None, props=None):
        folder = cls._get_collection_root_folder()

        # Path should already be sanitized
        sane_path = sanitize_path(href).strip("/")
        attributes = sane_path.split("/")
        if not attributes[0]:
            attributes.pop()
        principal = len(attributes) == 1
        filesystem_path = path_to_filesystem(folder, sane_path)

        if not props:
            props = {}
        if not props.get("tag") and collection:
            props["tag"] = collection[0].name
        if not props:
            cls._makedirs_synced(filesystem_path)
            return cls(sane_path, principal=principal)

        parent_dir = os.path.dirname(filesystem_path)
        cls._makedirs_synced(parent_dir)

        # Create a temporary directory with an unsafe name
        with TemporaryDirectory(prefix=".Radicale.tmp-",
                                dir=parent_dir) as tmp_dir:
            # The temporary directory itself can't be renamed
            tmp_filesystem_path = os.path.join(tmp_dir, "collection")
            os.makedirs(tmp_filesystem_path)
            self = cls("/", principal=principal, folder=tmp_filesystem_path)
            self.set_meta(props)

            if collection:
                if props.get("tag") == "VCALENDAR":
                    collection, = collection
                    items = []
                    for content in ("vevent", "vtodo", "vjournal"):
                        items.extend(
                            getattr(collection, "%s_list" % content, []))
                    items_by_uid = groupby(sorted(items, key=get_uid), get_uid)
                    vobject_items = {}
                    for uid, items in items_by_uid:
                        new_collection = vobject.iCalendar()
                        for item in items:
                            new_collection.add(item)
                        href = self._find_available_file_name(
                            vobject_items.get)
                        vobject_items[href] = new_collection
                    self.upload_all_nonatomic(vobject_items)
                elif props.get("tag") == "VCARD":
                    vobject_items = {}
                    for card in collection:
                        href = self._find_available_file_name(
                            vobject_items.get)
                        vobject_items[href] = card
                    self.upload_all_nonatomic(vobject_items)

            # This operation is not atomic on the filesystem level but it's
            # very unlikely that one rename operations succeeds while the
            # other fails or that only one gets written to disk.
            if os.path.exists(filesystem_path):
                os.rename(filesystem_path, os.path.join(tmp_dir, "delete"))
            os.rename(tmp_filesystem_path, filesystem_path)
            cls._sync_directory(parent_dir)

        return cls(sane_path, principal=principal)
예제 #37
0
def event_assignments_ical(request):
    cache_key = 'event_assignements_ical'
    assignee = request.GET.get('assignee')

    if assignee:
        assignee = get_object_or_404(User, email=assignee)
        cache_key += str(assignee.pk)

    cached = cache.get(cache_key)
    if cached:
        # additional response headers aren't remembered so add them again
        cached['Access-Control-Allow-Origin'] = '*'
        return cached

    cal = vobject.iCalendar()

    now = timezone.now()
    base_qs = EventAssignment.objects.all().order_by('-event__start_time')
    if assignee:
        base_qs = base_qs.filter(users=assignee)

    title = 'Airmo'
    if assignee:
        title += ' for %s' % assignee.email
    else:
        title += ' crew assignments'

    cal.add('X-WR-CALNAME').value = title
    assignments = list(
        base_qs
        .filter(event__start_time__lt=now)
        [:settings.CALENDAR_SIZE]
    )
    assignments += list(
        base_qs
        .filter(event__start_time__gte=now)
    )
    base_url = get_base_url(request)

    for assignment in assignments:
        event = assignment.event
        vevent = cal.add('vevent')
        vevent.add('summary').value = "[AirMo crew] %s" % event.title

        # Adjusted start times for Event Assignment iCal feeds
        # to allow staff sufficient time for event set-up.
        vevent.add('dtstart').value = (
            event.start_time - datetime.timedelta(minutes=30)
        )
        vevent.add('dtend').value = (
            event.start_time + datetime.timedelta(hours=1)
        )
        emails = [u.email for u in assignment.users.all().order_by('email')]
        vevent.add('description').value = 'Assigned to: ' + ', '.join(emails)

        locations = []
        if event.location:
            locations.append(event.location.name)
        locations.extend([
            x.name for x in assignment.locations.all().order_by('name')
        ])
        locations.sort()
        vevent.add('location').value = ', '.join(locations)
        vevent.add('url').value = (
            base_url + reverse('main:event', args=(event.slug,))
        )
    icalstream = cal.serialize()
    # return http.HttpResponse(icalstream,
    #                          content_type='text/plain; charset=utf-8')
    response = http.HttpResponse(icalstream,
                                 content_type='text/calendar; charset=utf-8')
    filename = 'AirMozillaEventAssignments'
    filename += '.ics'
    response['Content-Disposition'] = (
        'inline; filename=%s' % filename)
    cache.set(cache_key, response, 60 * 10)  # 10 minutes

    # https://bugzilla.mozilla.org/show_bug.cgi?id=909516
    response['Access-Control-Allow-Origin'] = '*'

    return response
예제 #38
0
weeksToSearch = 6
resultCal = None

if (os.path.isfile(os.getcwd() + '/calendar.cal')):
    print('Found cached calendar response')
    with open('calendar.cal', 'r') as cal:
        resultCal = vobject.readOne(cal)
    stale=time() - os.path.getmtime(os.getcwd() + '/calendar.cal') > (1*60*60)

if stale:
    print('Calender data is stale, calling', calDavServer)
    try:
        client = caldav.DAVClient(calDavServer, username=user, password=passwd)
        principal = client.principal()
        start = datetime.utcnow()
        resultCal = vobject.iCalendar()
        for calendar in principal.calendars():
            events = calendar.date_search(
                start=start,
                end=(start + timedelta(weeks=weeksToSearch)),
                expand=True)  # expands recurring events to their _next_ occurrence
            for comp in events:
                vevent = comp.vobject_instance.vevent
                # Expanded recurring events contain 2 DTSTAMP lines, which is illegal,
                # leading to errors on .serialize(). Fix is to remove one such line (or all?)
                vevent.remove(vevent.dtstamp)
                resultCal.add(vevent)
            with open('calendar.cal', 'w') as cal:
                cal.write(resultCal.serialize())
    except:
        print('Failed to get new API response, will use older response')
예제 #39
0
def main():
    """Command line tool to upload a Remind file to CalDAV"""

    parser = ArgumentParser(
        description='Command line tool to upload a Remind file to CalDAV')
    parser.add_argument(
        '-z',
        '--zone',
        default='Europe/Berlin',
        help='Timezone of Remind file (default: Europe/Berlin)')
    parser.add_argument(
        '-s',
        '--startdate',
        type=lambda s: parse(s).date(),
        default=date.today() - timedelta(weeks=12),
        help='Start offset for remind call (default: -12 weeks)')
    parser.add_argument(
        '-m',
        '--month',
        type=int,
        default=15,
        help=
        'Number of month to generate calendar beginning wit stadtdate (default: 15)'
    )
    parser.add_argument('-d',
                        '--delete',
                        action='store_true',
                        help='Delete old events')
    parser.add_argument('-r',
                        '--davurl',
                        required=True,
                        help='The URL of the CalDAV server')
    parser.add_argument('-u',
                        '--davuser',
                        help='The username for the CalDAV server')
    parser.add_argument('-p',
                        '--davpass',
                        help='The password for the CalDAV server')
    parser.add_argument('-i',
                        '--insecure',
                        action='store_true',
                        help='Ignore SSL certificate')
    parser.add_argument(
        'infile',
        nargs='?',
        default=expanduser('~/.reminders'),
        help='The Remind file to process (default: ~/.reminders)')
    parser.add_argument(
        '-o',
        '--old',
        default=None,
        help=
        'The old reference Remind file (entries not in the current one will be deleted from dav)'
    )
    args = parser.parse_args()

    zone = gettz(args.zone)
    # Manually set timezone name to generate correct ical files
    # (python-vobject tests for the zone attribute)
    zone.zone = args.zone

    if args.infile == '-':
        remind = Remind(args.infile, zone, args.startdate, args.month)
        vobject = remind.stdin_to_vobject(stdin.read())
    else:
        remind = Remind(args.infile, zone, args.startdate, args.month)
        vobject = remind.to_vobject()

    if hasattr(vobject, 'vevent_list'):
        ldict = {event.uid.value: event for event in vobject.vevent_list}
    else:
        ldict = {}

    if args.davuser and args.davpass:
        user = args.davuser
        passwd = args.davpass
    else:
        try:
            (user, _,
             passwd) = netrc().authenticators(urlparse(args.davurl).netloc)
        except (IOError, TypeError):
            if not args.davuser:
                print(
                    'rem2dav: Error, argument -u/--davuser or netrc is required'
                )
                return 1
            user = args.davuser
            try:
                from keyring import get_password
                passwd = get_password(urlparse(args.davurl).netloc, user)
            except ImportError:
                passwd = None
            if not passwd:
                passwd = getpass()

    client = DAVClient(args.davurl,
                       username=user,
                       password=passwd,
                       ssl_verify_cert=not args.insecure)
    calendar = Calendar(client, args.davurl)

    rdict = {
        splitext(basename(event.canonical_url))[0].replace('%40', '@'): event
        for event in calendar.events()
    }

    if args.old:
        old = Remind(args.old, zone, args.startdate, args.month)
        old_vobject = old.to_vobject()

        if hasattr(old_vobject, 'vevent_list'):
            odict = {
                event.uid.value: event
                for event in old_vobject.vevent_list
            }
            intersect = rdict.keys() & odict.keys()
            rdict = {key: rdict[key] for key in intersect}
        else:
            rdict = {}

    local = ldict.keys() - rdict.keys()
    for uid in local:
        ncal = iCalendar()
        ncal.add(ldict[uid])
        calendar.add_event(ncal.serialize())

    if args.delete or args.old:
        remote = rdict.keys() - ldict.keys()
        for uid in remote:
            rdict[uid].delete()
예제 #40
0
파일: ical.py 프로젝트: salvadordev/pretix
def get_private_icals(event, positions):
    """
    Return a list of ical objects based on a sequence of positions.

    Unlike get_public_ical, this will

    - Generate multiple ical files instead of one (but with deduplication applied)
    - Respect the mail_attach_ical_description setting

    It is private in the sense that mail_attach_ical_description may contain content not suited for
    public display.

    We however intentionally do not allow using placeholders based on the order and position
    specifically. This is for two reasons:

    - In reality, many people will add their invite to their calendar which is shared with a larger
      team. People are probably not aware that they're sharing sensitive information such as their
      secret ticket link with everyone they share their calendar with.

    - It would be pretty hard to implement it in a way that doesn't require us to use distinct
      settings fields for emails to customers and to attendees, which feels like an overcomplication.
    """

    from pretix.base.services.mail import TolerantDict

    tz = pytz.timezone(event.settings.timezone)

    creation_time = datetime.datetime.now(pytz.utc)
    calobjects = []

    evs = set(p.subevent or event for p in positions)
    for ev in evs:
        if isinstance(ev, Event):
            url = build_absolute_uri(event, 'presale:event.index')
        else:
            url = build_absolute_uri(event, 'presale:event.index', {
                'subevent': ev.pk
            })

        if event.settings.mail_attach_ical_description:
            ctx = get_email_context(event=event, event_or_subevent=ev)
            description = str(event.settings.mail_attach_ical_description).format_map(TolerantDict(ctx))
        else:
            # Default description
            descr = []
            descr.append(_('Tickets: {url}').format(url=url))
            if ev.date_admission:
                descr.append(str(_('Admission: {datetime}')).format(
                    datetime=date_format(ev.date_admission.astimezone(tz), 'SHORT_DATETIME_FORMAT')
                ))

            descr.append(_('Organizer: {organizer}').format(organizer=event.organizer.name))
            description = '\n'.join(descr)

        cal = vobject.iCalendar()
        cal.add('prodid').value = '-//pretix//{}//'.format(settings.PRETIX_INSTANCE_NAME.replace(" ", "_"))

        vevent = cal.add('vevent')
        vevent.add('summary').value = str(ev.name)
        vevent.add('description').value = description
        vevent.add('dtstamp').value = creation_time
        if ev.location:
            vevent.add('location').value = str(ev.location)

        vevent.add('uid').value = 'pretix-{}-{}-{}@{}'.format(
            event.organizer.slug,
            event.organizer.slug, event.slug,
            ev.pk if not isinstance(ev, Event) else '0',
            urlparse(url).netloc
        )

        if event.settings.show_times:
            vevent.add('dtstart').value = ev.date_from.astimezone(tz)
        else:
            vevent.add('dtstart').value = ev.date_from.astimezone(tz).date()

        if event.settings.show_date_to and ev.date_to:
            if event.settings.show_times:
                vevent.add('dtend').value = ev.date_to.astimezone(tz)
            else:
                # with full-day events date_to in pretix is included (e.g. last day)
                # whereas dtend in vcalendar is non-inclusive => add one day for export
                vevent.add('dtend').value = ev.date_to.astimezone(tz).date() + datetime.timedelta(days=1)

        calobjects.append(cal)
    return calobjects
예제 #41
0
    def create_collection(cls, href, collection=None, props=None):
        """Create a collection.

        If the collection already exists and neither ``collection`` nor
        ``props`` are set, this method shouldn't do anything. Otherwise the
        existing collection must be replaced.

        ``collection`` is a list of vobject components.

        ``props`` are metadata values for the collection.

        ``props["tag"]`` is the type of collection (VCALENDAR or
        VADDRESSBOOK). If the key ``tag`` is missing, it is guessed from the
        collection.

        """
        # Path should already be sanitized
        attributes = _get_attributes_from_path(href)
        if len(attributes) <= 1:
            raise PrincipalNotAllowedError

        # Try to infer tag
        if not props:
            props = {}
        if not props.get("tag") and collection:
            props["tag"] = collection[0].name

        # Try first getting the collection if exists, or create a new one otherwise.
        try:
            self = cls(href, principal=False, tag=props.get("tag"))
        except api.exceptions.DoesNotExist:
            user_path = posixpath.join('/', cls.user)
            collection_name = hashlib.sha256(str(time.time()).encode()).hexdigest()
            sane_path = posixpath.join(user_path, collection_name)

            if props.get("tag") == "VCALENDAR":
                inst = api.Calendar.create(cls.etesync, collection_name, None)
            elif props.get("tag") == "VADDRESSBOOK":
                inst = api.AddressBook.create(cls.etesync, collection_name, None)
            else:
                raise RuntimeError("Bad tag.")

            inst.save()
            self = cls(sane_path, principal=False)

        self.set_meta(props)

        if collection:
            if props.get("tag") == "VCALENDAR":
                collection, = collection
                items = []
                for content in ("vevent", "vtodo", "vjournal"):
                    items.extend(
                        getattr(collection, "%s_list" % content, []))
                items_by_uid = groupby(sorted(items, key=get_uid), get_uid)
                vobject_items = {}
                for uid, items in items_by_uid:
                    new_collection = vobject.iCalendar()
                    for item in items:
                        new_collection.add(item)
                    href = self._find_available_file_name(
                        vobject_items.get)
                    vobject_items[href] = new_collection
                self.upload_all_nonatomic(vobject_items)
            elif props.get("tag") == "VADDRESSBOOK":
                vobject_items = {}
                for card in collection:
                    href = self._find_available_file_name(
                        vobject_items.get)
                    vobject_items[href] = card
                self.upload_all_nonatomic(vobject_items)

        return self
예제 #42
0
def ical(request, event_pk=None):
    """Return an ICS file for the given event, or for all events if no event
    primary key is provided.

    If a "term" URL parameter is given and no event pk is given, the view
    returns all events for that term.

    The view only shows events that the user is allowed to see, based on the
    "user" and "key" URL parameters (which correspond to the user's PK and API
    key, respectively). If the "user" and "key" parameters are not valid or are
    not provided, only publicly visible events are included.
    """
    cal = vobject.iCalendar()

    cal.add('calscale').value = 'Gregorian'
    cal.add('X-WR-TIMEZONE').value = 'America/Los_Angeles'
    calendar_name = '{} Events'.format(settings.SITE_TAG)
    cal.add('X-WR-CALNAME').value = calendar_name
    cal.add('X-WR-CALDESC').value = calendar_name

    vtimezone = cal.add('vtimezone')
    vtimezone.add('tzid').value = 'America/Los_Angeles'
    vtimezone.add('X-LIC-LOCATION').value = 'America/Los_Angeles'
    dst = vtimezone.add('daylight')
    dst.add('tzoffsetfrom').value = '-0800'
    dst.add('tzoffsetto').value = '-0700'
    dst.add('tzname').value = 'PDT'
    dst.add('dtstart').value = datetime(
        1970, 3, 8, 2, 0, 0, 0, tz('US/Pacific'))  # '19700308T020000'
    dst.add('rrule').value = 'FREQ=YEARLY;BYMONTH=3;BYDAY=2SU'
    std = vtimezone.add('standard')
    std.add('tzoffsetfrom').value = '-0700'
    std.add('tzoffsetto').value = '-0800'
    std.add('tzname').value = 'PST'
    std.add('dtstart').value = datetime(
        1970, 11, 1, 2, 0, 0, 0, tz('US/Pacific'))  # '19701101T020000'
    std.add('rrule').value = 'FREQ=YEARLY;BYMONTH=11;BYDAY=1SU'

    user = None
    user_pk = request.GET.get('user', None)
    key = request.GET.get('key', None)
    if user_pk and key:
        try:
            api_key = APIKey.objects.get(user__pk=user_pk, key=key)
            user = api_key.user
        except APIKey.DoesNotExist:
            pass

    if event_pk is None:
        # We want multiple events
        filename = 'events.ics'
        term = request.GET.get('term', '')
        events = Event.objects.get_user_viewable(user).filter(cancelled=False)
        if term:
            # Filter by the given term
            term_obj = Term.objects.get_by_url_name(term)
            events = events.filter(term=term_obj)
        for event in events:
            add_event_to_ical(event, cal)
    else:
        # We want a specific event
        event = get_object_or_404(Event, pk=event_pk)
        if not event.can_user_view(user):
            raise PermissionDenied
        filename = 'event.ics'
        add_event_to_ical(event, cal)

    response = HttpResponse(cal.serialize(), content_type='text/calendar')
    response['Filename'] = filename  # IE needs this
    response['Content-Disposition'] = 'attachment; filename={}'.format(filename)
    return response
예제 #43
0
    def _get_ics_file(self):
        """ Returns iCalendar file for the event invitation.
            :returns a dict of .ics file content for each meeting
        """
        result = {}

        def ics_datetime(idate, allday=False):
            if idate:
                if allday:
                    return idate
                else:
                    return idate.replace(tzinfo=pytz.timezone('UTC'))
            return False

        try:
            # FIXME: why isn't this in CalDAV?
            import vobject
        except ImportError:
            _logger.warning(
                "The `vobject` Python module is not installed, so iCal file generation is unavailable. Please install the `vobject` Python module"
            )
            return result

        for meeting in self:
            cal = vobject.iCalendar()
            cal.add('method').value = 'REQUEST'
            cal.add('calscale').value = 'GREGORIAN'
            event = cal.add('vevent')
            if not meeting.start or not meeting.stop:
                raise UserError(
                    _("First you have to specify the date of the invitation."))

            event.add('created').value = ics_datetime(fields.Datetime.now())
            event.add('dtstart').value = ics_datetime(meeting.start,
                                                      meeting.allday)
            event.add('dtend').value = ics_datetime(meeting.stop,
                                                    meeting.allday)
            event.add('summary').value = meeting.name
            event.add('class').value = 'PUBLIC'
            event.add('trans').value = 'OPAQUE'
            event.add('location').value = 'COLOMBIA'

            #event already cancel state
            if self.state == 'cancel':
                event.add('status').value = 'CANCELLED'
            else:
                event.add('status').value = 'CONFIRMED'
            #event.add('uid').value = self.appointment_id.process_number + datetime.datetime.now().strftime("%Y%m%Y/%H:%M:%S")
            event.add(
                'uid'
            ).value = self.appointment_id.process_number + self.appointment_id.calendar_datetime.strftime(
                "%Y%m%d %H%M%S")

            event.add('sequence').value = str(
                self.appointment_id.sequence_icsfile_ctl)
            if meeting.description:
                event.add('description').value = meeting.description
            if meeting.location:
                event.add('location').value = meeting.location
            if meeting.rrule:
                event.add('rrule').value = meeting.rrule

            organizer_add = event.add('organizer')

            cn_value = "*****@*****.**"
            for server_id in self.env['ir.mail_server'].search([]):
                for user_id in server_id.user_ids:
                    if self.env.uid == user_id.id:
                        cn_value = server_id.smtp_user

            organizer_add.params['CN'] = [
                "sistemaaudiencias.ramajudicial.gov.co"
            ]
            organizer_add.params['ROLE'] = ["CHAIR"]
            organizer_add.params['RSVP'] = ["TRUE"]
            organizer_add.value = cn_value

            if meeting.alarm_ids:
                for alarm in meeting.alarm_ids:
                    valarm = event.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 u'Odoo'
            for attendee in meeting.attendee_ids:
                attendee_add = event.add('attendee')
                attendee_add.params['CUTYPE'] = ["INDIVIDUAL"]
                attendee_add.params['ROLE'] = ["REQ-PARTICIPANT"]
                attendee_add.params['PARTSTAT'] = ["ACCEPTED"]
                #attendee_add.params['PARTSTAT'] = ["NEEDS-ACTION"]
                attendee_add.params['RSVP'] = ["TRUE"]
                attendee_add.params['CN'] = [attendee.email]
                attendee_add.params['X-NUM-GUESTS'] = ["0"]
                attendee_add.value = (attendee.email or u'')

            result[meeting.id] = cal.serialize().encode('utf-8')

        return result
예제 #44
0
def events_calendar(request, privacy=None):
    cache_key = 'calendar'
    if privacy:
        cache_key += '_%s' % privacy
    if request.GET.get('location'):
        location = get_object_or_404(Location,
                                     name=request.GET.get('location'))
        cache_key += str(location.pk)
        cached = None
    else:
        location = None
        cached = cache.get(cache_key)

    if cached:
        return cached
    cal = vobject.iCalendar()

    now = datetime.datetime.utcnow().replace(tzinfo=utc)
    base_qs = Event.objects.approved()
    if privacy == 'public':
        base_qs = base_qs.filter(privacy=Event.PRIVACY_PUBLIC)
        title = 'Air Mozilla Public Events'
    elif privacy == 'private':
        base_qs = base_qs.exclude(privacy=Event.PRIVACY_PUBLIC)
        title = 'Air Mozilla Private Events'
    else:
        title = 'Air Mozilla Events'
    if location:
        base_qs = base_qs.filter(location=location)
    cal.add('X-WR-CALNAME').value = title
    events = list(
        base_qs.filter(start_time__lt=now).order_by('-start_time')
        [:settings.CALENDAR_SIZE])
    events += list(
        base_qs.filter(start_time__gte=now).order_by('start_time')
        [:settings.CALENDAR_SIZE])
    base_url = '%s://%s/' % (request.is_secure() and 'https'
                             or 'http', RequestSite(request).domain)
    for event in events:
        vevent = cal.add('vevent')
        vevent.add('summary').value = event.title
        vevent.add('dtstart').value = event.start_time
        vevent.add('dtend').value = (event.start_time +
                                     datetime.timedelta(hours=1))
        vevent.add('description').value = unhtml(short_desc(event))
        if event.location:
            vevent.add('location').value = event.location.name
        vevent.add('url').value = base_url + event.slug + '/'
    icalstream = cal.serialize()
    #response = http.HttpResponse(icalstream,
    #                          mimetype='text/plain; charset=utf-8')

    response = http.HttpResponse(icalstream,
                                 mimetype='text/calendar; charset=utf-8')
    filename = 'AirMozillaEvents%s' % (privacy and privacy or '')
    if location:
        filename += '_%s' % slugify(location.name)
    filename += '.ics'
    response['Content-Disposition'] = ('inline; filename=%s' % filename)
    if not location:
        cache.set(cache_key, response)
    return response
예제 #45
0
 def __init__(self):
     self._cal = vobject.iCalendar()
     self._cal.add(vobject.readOne(TIMEZONE, validate=True))
예제 #46
0
def icalendar(request, queryset, date_field, ical_filename, 
              title_field='title', description_field='description',
              last_modified_field=None, location_field=None,
              start_time_field=None, end_time_field=None,
              num_objects=15, extra_context=None,
              mimetype=None, context_processors=None):
    
    now = datetime.now()      
    queryset = queryset.filter(begin_date__gte=now - timedelta(days=1))
    
    cal = vobject.iCalendar()
    utc = vobject.icalendar.utc
    
    cal.add('method').value = 'PUBLISH'  # IE/Outlook needs this
    
    # Timezone code borrowed from 
    now = datetime.now()
    utcnow = datetime.utcnow()
    # Must always subtract smaller time from larger time here.
    if utcnow > now:
        sign = -1
        tzDifference = (utcnow - now)
    else:
        sign = 1
        tzDifference = (now - utcnow)
    
    # Round the timezone offset to the nearest half hour.
    tzOffsetMinutes = sign * ((tzDifference.seconds / 60 + 15) / 30) * 30
    tzOffset = timedelta(minutes=tzOffsetMinutes)
    
    #cal.add('vtimezone').value = FixedOffset(tzOffset)

    mytz = FixedOffset(tzOffset)
    
    for event in queryset:
        vevent = cal.add('vevent')

        vevent.add('summary').value = strip_tags(getattr(event, title_field))
        vevent.add('description').value = strip_tags(getattr(event, description_field))

        start_time = getattr(event, start_time_field, None)
        if start_time:
            start_date = datetime.combine(getattr(event, date_field), event.start_time)
            
            end_time = getattr(event, end_time_field, None)
            if end_time:
                end_date = datetime.combine(getattr(event, date_field), event.end_time)
                vevent.add('dtend').value = end_date.replace(tzinfo = mytz)
            
        else:
            start_date = getattr(event, date_field)
        
        
        vevent.add('dtstart').value = start_date.replace(tzinfo = mytz)
        
        last_modified = getattr(event, last_modified_field, None)
        if last_modified:
            vevent.add('last-modified').value = last_modified.replace(tzinfo = mytz)
            
        location = getattr(event, location_field, None)
        if location:
            vevent.add('location').value = strip_tags(location)

    icalstream = cal.serialize()
    response = HttpResponse(icalstream, mimetype='text/calendar')
    response['Filename'] = ical_filename  # IE needs this
    response['Content-Disposition'] = 'attachment; filename=%s' % ical_filename

    return response
예제 #47
0
    def _get_ics_file(self):
        """ Returns iCalendar file for the event invitation.
            :returns a dict of .ics file content for each meeting
        """
        result = {}

        def ics_datetime(idate, allday=False):
            if idate:
                if allday:
                    return idate
                return idate.replace(tzinfo=pytz.timezone('UTC'))
            return False

        try:
            # FIXME: why isn't this in CalDAV?
            import vobject
        except ImportError:
            _logger.warning(
                "The `vobject` Python module is not installed, so iCal file generation is unavailable. Please install the `vobject` Python module"
            )
            return result

        for meeting in self:
            cal = vobject.iCalendar()
            event = cal.add('vevent')

            if not meeting.start or not meeting.stop:
                raise UserError(
                    _("First you have to specify the date of the invitation."))
            event.add('created').value = ics_datetime(fields.Datetime.now())
            event.add('dtstart').value = ics_datetime(meeting.start,
                                                      meeting.allday)
            event.add('dtend').value = ics_datetime(meeting.stop,
                                                    meeting.allday)
            event.add('summary').value = meeting.name
            if meeting.description:
                event.add('description').value = meeting.description
            if meeting.location:
                event.add('location').value = meeting.location
            if meeting.rrule:
                event.add('rrule').value = meeting.rrule

            if meeting.alarm_ids:
                for alarm in meeting.alarm_ids:
                    valarm = event.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 u'Odoo'
            for attendee in meeting.attendee_ids:
                attendee_add = event.add('attendee')
                attendee_add.value = u'MAILTO:' + (attendee.email or u'')
            result[meeting.id] = cal.serialize().encode('utf-8')

        return result
예제 #48
0
    def _get_ics_file(self):
        """ Returns iCalendar file for the event invitation.
            :returns a dict of .ics file content for each meeting
        """
        result = {}

        def ics_datetime(idate, allday=False):
            if idate:
                if allday:
                    return idate
                return idate.replace(tzinfo=pytz.timezone('UTC'))
            return False

        if not vobject:
            return result

        for meeting in self:
            cal = vobject.iCalendar()
            event = cal.add('vevent')

            if not meeting.start or not meeting.stop:
                raise UserError(
                    _("First you have to specify the date of the invitation."))
            event.add('created').value = ics_datetime(fields.Datetime.now())
            event.add('dtstart').value = ics_datetime(meeting.start,
                                                      meeting.allday)
            event.add('dtend').value = ics_datetime(meeting.stop,
                                                    meeting.allday)
            event.add('summary').value = meeting.name
            if not is_html_empty(meeting.description):
                if 'appointment_type_id' in meeting._fields and self.appointment_type_id:
                    # convert_online_event_desc_to_text method for correct data formatting in external calendars
                    event.add('description'
                              ).value = self.convert_online_event_desc_to_text(
                                  meeting.description)
                else:
                    event.add('description').value = html2plaintext(
                        meeting.description)
            if meeting.location:
                event.add('location').value = meeting.location
            if meeting.rrule:
                event.add('rrule').value = meeting.rrule

            if meeting.alarm_ids:
                for alarm in meeting.alarm_ids:
                    valarm = event.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 u'Odoo'
            for attendee in meeting.attendee_ids:
                attendee_add = event.add('attendee')
                attendee_add.value = u'MAILTO:' + (attendee.email or u'')
            result[meeting.id] = cal.serialize().encode('utf-8')

        return result
예제 #49
0
    def handle_add_appoint(self, message):
        event = message.data.get("event")
        while not event:
            #We need to get the event
            event = self.get_response("new.event.name")

        utterance = message.data['utterance']
        date, rest = extract_datetime(utterance, datetime.now(), self.lang)
        while rest == normalize(utterance):
            utterance = self.get_response("new.event.date")
            date, rest = extract_datetime(utterance)

        self.log.info(" Calendar skill new event: date: " + str(date) +
                      " event: " + event)
        #ADD EVENT
        server_type = self.check_server()
        if server_type == "Handled":
            return
        elif server_type == True:
            #Home
            server_address = self.settings.get("server_address")
            port = self.settings.get("port")
            username = self.settings.get("username")
            password = self.settings.get("password")
            #start creating a vevent:
            cal = vobject.iCalendar()
            cal.add("vevent")
            #add name
            cal.vevent.add("summary").value = str(event)
            #add date
            cal.vevent.add('dtstart').value = date
            # add it to the calendar
            url = "http://{}:{}@{}:{}/".format(username, password,
                                               server_address, port)
            try:
                client = caldav.DAVClient(url)
                principal = client.principal()

                #Select calendar
                events = []
                for calendar in principal.calendars():
                    calendar.add_event(str(cal.serialize()))
                self.speak_dialog("new.event.summary",
                                  data={"event": str(event)})
            except:
                self.speak_dialog("error.logging.in")
                return None

        elif server_type is None:
            # Password local
            server_address = self.settings.get("server_address")
            calendar = self.settings.get("calendar")
            port = self.settings.get("port")
            account_config = self.config_core.get("calendar", {})
            username = account_config.get("username")
            password = account_config.get("password")

            # start creating a vevent:
            cal = vobject.iCalendar()
            cal.add("vevent")
            # add name
            cal.vevent.add("summary").value = str(event)
            # add date
            cal.vevent.add('dtstart').value = date
            # add it to the calendar
            url = "http://{}:{}@{}:{}/".format(username, password,
                                               server_address, port)
            try:
                client = caldav.DAVClient(url)
                principal = client.principal()

                # Select calendar
                events = []
                for calendar in principal.calendars():
                    calendar.add_event(str(cal.serialize()))
                self.speak_dialog("new.event.summary",
                                  data={"event": str(event)})
            except:
                self.speak_dialog("error.logging.in")
                return None

        elif server_type == False:
            #Local
            #The calendar is on the device
            #Check if it needs to be made...
            fs = FileSystemAccess(str(self.skill_id))
            if fs.exists("calendar.ics"):
                #YAY! exists
                calendar = self.read_file("calendar.ics")
                c = ics.Calendar(calendar)
                e = ics.Event()
                #add event
                e.name = str(event)
                e.begin = str(arrow.get(date))
                c.events.apaddpend(e)
                self.write_file("calendar.ics", str(c))
                self.speak_dialog("new.event.summary",
                                  data={"event": str(event)})
            else:
                #create calendar
                c = ics.Calendar()
                e = ics.Event()
                #add event
                e.name = str(event)
                e.begin = str(arrow.get(date))
                c.events.add(e)
                self.write_file("calendar.ics", str(c))
                self.speak_dialog("new.event.summary",
                                  data={"event": str(event)})
예제 #50
0
def calendar_vcal(request, key):
    base_url = '%s://%s' % (request.is_secure() and 'https'
                            or 'http', RequestSite(request).domain)
    home_url = base_url + '/'
    cal = vobject.iCalendar()
    cal.add('x-wr-calname').value = 'Mozilla PTO'

    try:
        user = UserKey.objects.get(key=key).user
    except UserKey.DoesNotExist:
        # instead of raising a HTTP error, respond a calendar
        # that urges the user to update the stale URL
        event = cal.add('vevent')
        event.add('summary').value = (
            "Calendar expired. Visit %s#calendarurl to get the "
            "new calendar URL" % home_url)
        today = datetime.date.today()
        event.add('dtstart').value = today
        event.add('dtend').value = today
        event.add('url').value = '%s#calendarurl' % (home_url, )
        event.add('description').value = (
            "The calendar you used has expired "
            "and is no longer associated with any user")
        return _render_vcalendar(cal, key)

    # always start on the first of this month
    today = datetime.date.today()
    #first = datetime.date(today.year, today.month, 1)

    user_ids = [user.pk]
    for user_ in get_observed_users(user, max_depth=2):
        user_ids.append(user_.pk)

    entries = (Entry.objects.filter(user__in=user_ids,
                                    total_hours__gte=0,
                                    total_hours__isnull=False,
                                    end__gte=today).select_related('user'))

    _list_base_url = base_url + reverse('dates.list')

    def make_list_url(entry):
        name = entry.user.get_full_name()
        if not name:
            name = entry.user.username
        data = {
            'date_from': entry.start.strftime('%d %B %Y'),
            'date_to': entry.end.strftime('%d %B %Y'),
            'name': name
        }
        return _list_base_url + '?' + urlencode(data, True)

    for entry in entries:
        event = cal.add('vevent')
        event.add('summary').value = '%s PTO' % make_entry_title(
            entry, user, include_details=False)
        event.add('dtstart').value = entry.start
        event.add('dtend').value = entry.end
        #url = (home_url + '?cal_y=%d&cal_m=%d' %
        #       (slot.date.year, slot.date.month))
        event.add('url').value = make_list_url(entry)
        #event.add('description').value = entry.details
        event.add('description').value = "Log in to see the details"

    return _render_vcalendar(cal, key)
예제 #51
0
 def _get_new_vcal(cls) -> iCalendar:
     vcal = iCalendar()
     vcal.add('PRODID').value = cls.GTG_PRODID
     vcal.add('vtodo')
     return vcal
예제 #52
0
    def createExamEvent(self,
                        exam: Exam,
                        lesson: Lesson,
                        title: str = "",
                        body: str = ""):
        calendar = vobject.iCalendar()
        _title = exam.subject.name + ": " + exam.description
        if title != "":
            _title += " " + title

        calendar.add('vevent').add('summary').value = _title

        calendar.vevent.add(
            'description'
        ).value = "Teacher: " + exam.teacher.name + "(" + exam.teacher.short + ")\n" + "Description: " + exam.description

        calendar.vevent.add("dtstart").value = timezone(
            "Europe/Warsaw").localize(
                datetime.datetime(lesson.from_.year, lesson.from_.month,
                                  lesson.from_.day, lesson.from_.hour,
                                  lesson.from_.minute,
                                  lesson.from_.second)).astimezone(
                                      timezone("UTC"))
        calendar.vevent.add("dtend").value = timezone(
            "Europe/Warsaw").localize(
                datetime.datetime(
                    lesson.to.year, lesson.to.month, lesson.to.day,
                    lesson.to.hour, lesson.to.minute,
                    lesson.to.second)).astimezone(timezone("UTC"))
        if exam.type == ExamType.EXAM:
            valarm = calendar.vevent.add('valarm')
            valarm.add('action').value = "AUDIO"
            valarm.add("trigger").value = lesson.from_ - datetime.timedelta(
                days=14)
            valarm = calendar.vevent.add('valarm')
            valarm.add('action').value = "AUDIO"
            valarm.add("trigger").value = lesson.from_ - datetime.timedelta(
                days=7)
            valarm = calendar.vevent.add('valarm')
            valarm.add('action').value = "AUDIO"
            valarm.add("trigger").value = lesson.from_ - datetime.timedelta(
                days=3)
            valarm = calendar.vevent.add('valarm')
            valarm.add('action').value = "AUDIO"
            valarm.add("trigger").value = lesson.from_ - datetime.timedelta(
                days=2)
            valarm = calendar.vevent.add('valarm')
            valarm.add('action').value = "AUDIO"
            valarm.add("trigger").value = lesson.from_ - datetime.timedelta(
                days=1)
            valarm = calendar.vevent.add('valarm')
            valarm.add('action').value = "AUDIO"
            valarm.add("trigger").value = lesson.from_ - datetime.timedelta(
                days=0)
        elif exam.type == ExamType.SHORT_TEST:
            valarm = calendar.vevent.add('valarm')
            valarm.add('action').value = "AUDIO"
            valarm.add("trigger").value = lesson.from_ - datetime.timedelta(
                days=3)
            valarm = calendar.vevent.add('valarm')
            valarm.add('action').value = "AUDIO"
            valarm.add("trigger").value = lesson.from_ - datetime.timedelta(
                days=2)
            valarm = calendar.vevent.add('valarm')
            valarm.add('action').value = "AUDIO"
            valarm.add("trigger").value = lesson.from_ - datetime.timedelta(
                days=1)
            valarm = calendar.vevent.add('valarm')
            valarm.add('action').value = "AUDIO"
            valarm.add("trigger").value = lesson.from_ - datetime.timedelta(
                days=0)
        else:
            valarm = calendar.vevent.add('valarm')
            valarm.add('action').value = "AUDIO"
            valarm.add("trigger").value = lesson.from_ - datetime.timedelta(
                days=1)
            valarm = calendar.vevent.add('valarm')
            valarm.add('action').value = "AUDIO"
            valarm.add("trigger").value = lesson.from_ - datetime.timedelta(
                days=0)

        return calendar
예제 #53
0
        def prepare(vobject_items, tag=None, write_whole_collection=None):
            if (write_whole_collection
                    or permissions and not parent_permissions):
                write_whole_collection = True
                content_type = environ.get("CONTENT_TYPE", "").split(";")[0]
                tags = {
                    value: key
                    for key, value in xmlutils.MIMETYPES.items()
                }
                tag = radicale_item.predict_tag_of_whole_collection(
                    vobject_items, tags.get(content_type))
                if not tag:
                    raise ValueError("Can't determine collection tag")
                collection_path = pathutils.strip_path(path)
            elif (write_whole_collection is not None
                  and not write_whole_collection
                  or not permissions and parent_permissions):
                write_whole_collection = False
                if tag is None:
                    tag = radicale_item.predict_tag_of_parent_collection(
                        vobject_items)
                collection_path = posixpath.dirname(pathutils.strip_path(path))
            props = None
            stored_exc_info = None
            items = []
            try:
                if tag:
                    radicale_item.check_and_sanitize_items(
                        vobject_items,
                        is_collection=write_whole_collection,
                        tag=tag)
                    if write_whole_collection and tag == "VCALENDAR":
                        vobject_components = []
                        vobject_item, = vobject_items
                        for content in ("vevent", "vtodo", "vjournal"):
                            vobject_components.extend(
                                getattr(vobject_item, "%s_list" % content, []))
                        vobject_components_by_uid = itertools.groupby(
                            sorted(vobject_components,
                                   key=radicale_item.get_uid),
                            radicale_item.get_uid)
                        for uid, components in vobject_components_by_uid:
                            vobject_collection = vobject.iCalendar()
                            for component in components:
                                vobject_collection.add(component)
                            item = radicale_item.Item(
                                collection_path=collection_path,
                                vobject_item=vobject_collection)
                            item.prepare()
                            items.append(item)
                    elif write_whole_collection and tag == "VADDRESSBOOK":
                        for vobject_item in vobject_items:
                            item = radicale_item.Item(
                                collection_path=collection_path,
                                vobject_item=vobject_item)
                            item.prepare()
                            items.append(item)
                    elif not write_whole_collection:
                        vobject_item, = vobject_items
                        item = radicale_item.Item(
                            collection_path=collection_path,
                            vobject_item=vobject_item)
                        item.prepare()
                        items.append(item)

                if write_whole_collection:
                    props = {}
                    if tag:
                        props["tag"] = tag
                    if tag == "VCALENDAR" and vobject_items:
                        if hasattr(vobject_items[0], "x_wr_calname"):
                            calname = vobject_items[0].x_wr_calname.value
                            if calname:
                                props["D:displayname"] = calname
                        if hasattr(vobject_items[0], "x_wr_caldesc"):
                            caldesc = vobject_items[0].x_wr_caldesc.value
                            if caldesc:
                                props["C:calendar-description"] = caldesc
                    radicale_item.check_and_sanitize_props(props)
            except Exception:
                stored_exc_info = sys.exc_info()

            # Use generator for items and delete references to free memory
            # early
            def items_generator():
                while items:
                    yield items.pop(0)

            return (items_generator(), tag, write_whole_collection, props,
                    stored_exc_info)
예제 #54
0
    def testInvitationDelegation(self):
        """ invitation delegation """

        ics_name = "test-delegation.ics"
        self.ics_list += [ics_name]

        # the invitation must not exist
        self._deleteEvent(self.client, "%s%s" % (self.user_calendar, ics_name),
                          None)
        self._deleteEvent(self.attendee1_client,
                          "%s%s" % (self.attendee1_calendar, ics_name), None)
        self._deleteEvent(
            self.attendee1_delegate_client,
            "%s%s" % (self.attendee1_delegate_calendar, ics_name), None)

        # 1. org -> attendee => org: 1, attendee: 1 (pst=N-A), delegate: 0

        invitation = self._newEvent()
        invitation.add("method").value = "REQUEST"
        organizer = invitation.vevent.add('organizer')
        organizer.cn_param = self.user_name
        organizer.value = self.user_email
        attendee = invitation.vevent.add('attendee')
        attendee.cn_param = self.attendee1_name
        attendee.rsvp_param = "TRUE"
        attendee.partstat_param = "NEEDS-ACTION"
        attendee.value = self.attendee1_email

        self._postEvent(self.client, self.user_calendar, invitation,
                        self.user_email, [self.attendee1_email])
        del invitation.method
        self._putEvent(self.client,
                       "%stest-delegation.ics" % self.user_calendar,
                       invitation)

        att_inv = self._getEvent(
            self.attendee1_client,
            "%stest-delegation.ics" % self.attendee1_calendar)
        self._compareAttendees(att_inv, invitation)

        # 2. attendee delegates to delegate
        #    => org: 1 (updated), attendee: 1 (updated,pst=D),
        #       delegate: 1 (new,pst=N-A)

        invitation.add("method").value = "REQUEST"
        attendee1 = invitation.vevent.attendee
        attendee1.partstat_param = "DELEGATED"
        attendee1.delegated_to_param = self.attendee1_delegate_email
        delegate = invitation.vevent.add('attendee')
        delegate.delegated_from_param = self.attendee1_email
        delegate.cn_param = self.attendee1_delegate_name
        delegate.rsvp_param = "TRUE"
        delegate.partstat_param = "NEEDS-ACTION"
        delegate.value = self.attendee1_delegate_email

        self._postEvent(self.attendee1_client, self.attendee1_calendar,
                        invitation, self.attendee1_email,
                        [self.attendee1_delegate_email])
        invitation.method.value = "REPLY"
        self._postEvent(self.attendee1_client, self.attendee1_calendar,
                        invitation, self.attendee1_email, [self.user_email])
        del invitation.method
        self._putEvent(self.attendee1_client,
                       "%stest-delegation.ics" % self.attendee1_calendar,
                       invitation, 204)

        del_inv = self._getEvent(
            self.attendee1_delegate_client,
            "%stest-delegation.ics" % self.attendee1_delegate_calendar)
        self._compareAttendees(del_inv, invitation)
        org_inv = self._getEvent(self.client,
                                 "%stest-delegation.ics" % self.user_calendar)
        self._compareAttendees(org_inv, invitation)

        # 3. delegate accepts
        #    => org: 1 (updated), attendee: 1 (updated,pst=D),
        #       delegate: 1 (accepted,pst=A)

        invitation.add("method").value = "REPLY"
        delegate.partstat_param = "ACCEPTED"
        self._postEvent(self.attendee1_delegate_client,
                        self.attendee1_delegate_calendar, invitation,
                        self.attendee1_delegate_email,
                        [self.user_email, self.attendee1_email])
        del invitation.method
        self._putEvent(
            self.attendee1_delegate_client,
            "%stest-delegation.ics" % self.attendee1_delegate_calendar,
            invitation, 204)

        org_inv = self._getEvent(self.client,
                                 "%stest-delegation.ics" % self.user_calendar)
        self._compareAttendees(org_inv, invitation)
        att_inv = self._getEvent(
            self.attendee1_client,
            "%stest-delegation.ics" % self.attendee1_calendar)
        self._compareAttendees(att_inv, invitation)

        # 4. attendee accepts
        # => org: 1 (updated), attendee: 1 (updated,pst=A),
        #    delegate: 0 (cancelled, deleted)

        cancellation = vobject.iCalendar()
        cancellation.copy(invitation)
        cancellation.add("method").value = "CANCEL"
        cancellation.vevent.sequence.value = "1"
        self._postEvent(self.attendee1_client, self.attendee1_calendar,
                        cancellation, self.attendee1_email,
                        [self.attendee1_delegate_email])

        attendee1 = invitation.vevent.attendee
        attendee1.partstat_param = "ACCEPTED"
        del attendee1.delegated_to_param
        invitation.add("method").value = "REPLY"
        invitation.vevent.remove(delegate)
        self._postEvent(self.attendee1_client, self.attendee1_calendar,
                        invitation, self.attendee1_email, [self.user_email])

        del invitation.method
        self._putEvent(self.attendee1_client,
                       "%stest-delegation.ics" % self.attendee1_calendar,
                       invitation, 204)

        org_inv = self._getEvent(self.client,
                                 "%stest-delegation.ics" % self.user_calendar)
        self._compareAttendees(org_inv, invitation)

        del_inv = self._getEvent(
            self.attendee1_delegate_client,
            "%stest-delegation.ics" % self.attendee1_delegate_calendar, 404)

        # 5. org updates inv.
        #    => org: 1 (updated), attendee: 1 (updated), delegate: 0

        invitation.add("method").value = "REQUEST"
        invitation.vevent.summary.value = "Updated invitation"
        invitation.vevent.sequence.value = "1"
        attendee.partstat_param = "NEEDS-ACTION"
        now = datetime.datetime.now()
        invitation.vevent.last_modified.value = now
        invitation.vevent.dtstamp.value = now

        self._postEvent(self.client, self.user_calendar, invitation,
                        self.user_email, [self.attendee1_email])

        del invitation.method
        self._putEvent(self.client,
                       "%stest-delegation.ics" % self.user_calendar,
                       invitation, 204)

        att_inv = self._getEvent(
            self.attendee1_client,
            "%stest-delegation.ics" % self.attendee1_calendar)
        self._compareAttendees(att_inv, invitation)

        # 6. attendee delegates to delegate
        #    => org: 1 (updated), attendee: 1 (updated), delegate: 1 (new)

        invitation.add("method").value = "REQUEST"
        attendee1.partstat_param = "DELEGATED"
        attendee1.delegated_to_param = self.attendee1_delegate_email

        delegate = invitation.vevent.add('attendee')
        delegate.delegated_from_param = self.attendee1_email
        delegate.cn_param = self.attendee1_delegate_name
        delegate.rsvp_param = "TRUE"
        delegate.partstat_param = "NEEDS-ACTION"
        delegate.value = self.attendee1_delegate_email

        self._postEvent(self.attendee1_client, self.attendee1_calendar,
                        invitation, self.attendee1_email,
                        [self.attendee1_delegate_email])
        invitation.method.value = "REPLY"
        self._postEvent(self.attendee1_client, self.attendee1_calendar,
                        invitation, self.attendee1_email, [self.user_email])
        del invitation.method
        self._putEvent(self.attendee1_client,
                       "%stest-delegation.ics" % self.attendee1_calendar,
                       invitation, 204)

        org_inv = self._getEvent(self.client,
                                 "%stest-delegation.ics" % self.user_calendar)
        self._compareAttendees(org_inv, invitation)
        del_inv = self._getEvent(
            self.attendee1_delegate_client,
            "%stest-delegation.ics" % self.attendee1_delegate_calendar)
        self._compareAttendees(del_inv, invitation)

        # 7. delegate accepts
        #    => org: 1 (updated), attendee: 1 (updated), delegate: 1 (accepted)

        invitation.add("method").value = "REPLY"
        delegate.partstat_param = "ACCEPTED"
        self._postEvent(self.attendee1_delegate_client,
                        self.attendee1_delegate_calendar, invitation,
                        self.attendee1_delegate_email,
                        [self.user_email, self.attendee1_email])
        del invitation.method
        self._putEvent(
            self.attendee1_delegate_client,
            "%stest-delegation.ics" % self.attendee1_delegate_calendar,
            invitation, 204)

        org_inv = self._getEvent(self.client,
                                 "%stest-delegation.ics" % self.user_calendar)
        self._compareAttendees(org_inv, invitation)
        att_inv = self._getEvent(
            self.attendee1_client,
            "%stest-delegation.ics" % self.attendee1_calendar)
        self._compareAttendees(att_inv, invitation)

        # 8. org updates inv.
        #    => org: 1 (updated), attendee: 1 (updated,partstat unchanged),
        #       delegate: 1 (updated,partstat reset)

        invitation.add("method").value = "REQUEST"
        now = datetime.datetime.now()
        invitation.vevent.last_modified.value = now
        invitation.vevent.dtstamp.value = now
        invitation.vevent.summary.value = "Updated invitation (again)"
        invitation.vevent.sequence.value = "2"
        delegate.partstat_param = "NEEDS-ACTION"

        self._postEvent(self.client, self.user_calendar, invitation,
                        self.user_email,
                        [self.attendee1_email, self.attendee1_delegate_email])

        del invitation.method
        self._putEvent(self.client,
                       "%stest-delegation.ics" % self.user_calendar,
                       invitation, 204)

        att_inv = self._getEvent(
            self.attendee1_client,
            "%stest-delegation.ics" % self.attendee1_calendar)
        self._compareAttendees(att_inv, invitation)
        del_inv = self._getEvent(
            self.attendee1_client,
            "%stest-delegation.ics" % self.attendee1_calendar)
        self._compareAttendees(del_inv, invitation)

        # 9. org cancels invitation
        #    => org: 1 (updated), attendee: 0 (cancelled, deleted),
        #       delegate: 0 (cancelled, deleted)

        invitation.add("method").value = "CANCEL"
        now = datetime.datetime.now()
        invitation.vevent.last_modified.value = now
        invitation.vevent.dtstamp.value = now
        invitation.vevent.summary.value = "Cancelled invitation (again)"
        invitation.vevent.sequence.value = "3"

        self._postEvent(self.client, self.user_calendar, invitation,
                        self.user_email,
                        [self.attendee1_email, self.attendee1_delegate_email])

        del invitation.method
        invitation.vevent.remove(attendee)
        invitation.vevent.remove(delegate)
        self._putEvent(self.client,
                       "%stest-delegation.ics" % self.user_calendar,
                       invitation, 204)

        att_inv = self._getEvent(
            self.attendee1_client,
            "%stest-delegation.ics" % self.attendee1_calendar, 404)
        del_inv = self._getEvent(
            self.attendee1_delegate_client,
            "%stest-delegation.ics" % self.attendee1_delegate_calendar, 404)
예제 #55
0
def itemsToVObject(view, items, cal=None, filters=None):
    """Iterate through items, add to cal, create a new vcalendar if needed.

    Chandler doesn't do recurrence yet, so for now we don't worry
    about timezones.

    """
    taskKind = view.findPath(ICalendarFormat._taskPath)
    eventKind = view.findPath(ICalendarFormat._calendarEventPath)
    if cal is None:
        cal = vobject.iCalendar()
    for item in items:
        if item.isItemOf(taskKind):
            taskorevent = 'TASK'
            comp = cal.add('vtodo')
        elif item.isItemOf(eventKind):
            taskorevent = 'EVENT'
            comp = cal.add('vevent')
        else:
            continue

        if item.getAttributeValue('icalUID', default=None) is None:
            item.icalUID = unicode(item.itsUUID)
        comp.add('uid').value = item.icalUID

        try:
            comp.add('summary').value = item.displayName
        except AttributeError:
            pass
        try:
            comp.add('dtstart').value = dateForVObject(item.startTime,
                                                       item.allDay)
        except AttributeError:
            pass
        try:
            if taskorevent == 'TASK':
                comp.add('due').value = dateForVObject(item.dueDate,
                                                       item.allDay)
            else:
                comp.add('dtend').value = dateForVObject(
                    item.endTime, item.allDay)
        except AttributeError:
            pass

        if not filters or "transparency" not in filters:
            try:
                if taskorevent == 'EVENT':
                    status = item.transparency.upper()
                    if status == 'FYI': status = 'CANCELLED'
                    comp.add('status').value = status
            except AttributeError:
                pass

        try:
            comp.add('description').value = item.body.getReader().read()
        except AttributeError:
            pass
        try:
            comp.add('location').value = item.location.displayName
        except AttributeError:
            pass

        if not filters or "reminderTime" not in filters:
            try:
                comp.add('valarm').add('trigger').value = \
                  dateForVObject(item.reminderTime) - \
                  dateForVObject(item.startTime)
            except AttributeError:
                pass

    return cal
예제 #56
0
def itemsToVObject(view, items, cal=None, filters=None):
    """
    Iterate through items, add to cal, create a new vcalendar if needed.

    Consider only master events (then serialize all modifications).  For now,
    set all timezones to Pacific.

    """

    if filters is None:
        filters = () # we want filters to be iterable
    
    def makeDateTimeValue(dt, asDate=False):
        if asDate:
            return dt.date()
        elif dt.tzinfo == view.tzinfo.floating:
            return dt.replace(tzinfo=None)
        else:
            return dt

    
    def populateCommon(comp, item):
        """
        Populate the given vevent or vtodo vobject with values for
        attributes common to Events or Tasks).
        """
        
        if getattr(item, Note.icalUID.name, None) is None:
            item.icalUID = unicode(item.itsUUID)
        comp.add('uid').value = item.icalUID

        # displayName --> SUMMARY
        try:
            summary = item.displayName
        except AttributeError:
            pass
        else:
            comp.add('summary').value = summary
            
        # body --> DESCRIPTION
        try:
            description = item.body
        except AttributeError:
            pass
        else:
            if description:
                comp.add('description').value = description
                
        # userReminder --> VALARM
        if Remindable.reminders.name not in filters:
            firstReminder = item.getUserReminder()
            if firstReminder is not None:
                if firstReminder.absoluteTime is not None:
                    value = firstReminder.absoluteTime
                else:
                    # @@@ For now, all relative reminders are relative to starttime
                    assert firstReminder.relativeTo == EventStamp.effectiveStartTime.name
                    value = firstReminder.delta
                comp.add('valarm').add('trigger').value = value
                
    def populateCustom(comp, item):
        # custom properties
        for name, value in item.icalendarProperties.iteritems():
            prop = comp.add(name)

            # for unrecognized properties, import stores strings, not
            # native types like datetimes.  So value should just be a
            # string, not a more complicated python data structure.  Don't
            # try to transform the value when serializing
            prop.isNative = False
            
            # encoding escapes characters like backslash and comma and
            # combines list values into a single string.  This was already
            # done when the icalendar was imported, so don't escape again
            prop.encoded = True
            
            prop.value = value
                
        for name, paramstring in item.icalendarParameters.iteritems():
            paramdict = comp.contents[name][0].params
            for paramlist in vobject.base.parseParams(paramstring):
                # parseParams gives a list of lists of parameters, with the
                # first element of each list being the name of the
                # parameter, followed by the parameter values, if any
                paramname = paramlist[0].upper()
                if paramname.lower() in parametersUnderstood:
                    # parameters understood by Chandler shouldn't be stored
                    # in icalendarParameters, but changes to which
                    # parameters Chandler understands can lead to spurious
                    # parameters, ignore them
                    continue
                paramvalues = paramdict.setdefault(paramname, [])
                paramvalues.extend(paramlist[1:])
        
        

    
    def populateEvent(comp, event):
        """Populate the given vobject vevent with data from event."""
        
        populateCommon(comp, event.itsItem)
        
        try:
            dtstartLine = comp.add('dtstart')
            
            # allDay-ness overrides anyTime-ness
            if event.anyTime and not event.allDay:
                dtstartLine.x_osaf_anytime_param = 'TRUE'
                
            dtstartLine.value = makeDateTimeValue(event.startTime,
                                    event.anyTime or event.allDay)

        except AttributeError:
            comp.dtstart = [] # delete the dtstart that was added
        
        try:
            if not (event.duration == datetime.timedelta(0) or (
                    (event.anyTime or event.allDay) and 
                    event.duration <= oneDay)):
                dtendLine = comp.add('dtend')
                #convert Chandler's notion of allDay duration to iCalendar's
                if event.allDay:
                    dtendLine.value = event.endTime.date() + oneDay
                else:
                    if event.anyTime:
                        dtendLine.x_osaf_anytime_param = 'TRUE'

                    # anyTime should be exported as allDay for non-Chandler apps
                    dtendLine.value = makeDateTimeValue(event.endTime,
                                                        event.anyTime)

        except AttributeError:
            comp.dtend = [] # delete the dtend that was added
            

        if EventStamp.transparency.name not in filters:
            try:
                status = event.transparency.upper()
                # anytime events should be interpreted as not taking up time,
                # but all-day shouldn't
                if status == 'FYI' or (not event.allDay and event.anyTime):
                    status = 'CANCELLED'
                comp.add('status').value = status
            except AttributeError:
                pass

        try:
            comp.add('location').value = event.location.displayName
        except AttributeError:
            pass
        
        view = event.itsItem.itsView
        timestamp = datetime.datetime.utcnow()
        comp.add('dtstamp').value = timestamp.replace(tzinfo=view.tzinfo.UTC)

        if event.modificationFor is not None:
            recurrenceid = comp.add('recurrence-id')
            masterEvent = event.getMaster()
            allDay = masterEvent.allDay or masterEvent.anyTime
            
            recurrenceid.value = makeDateTimeValue(event.recurrenceID, allDay)
        
        # logic for serializing rrules needs to move to vobject
        try: # hack, create RRULE line last, because it means running transformFromNative
            if event.getMaster() == event and event.rruleset is not None:
                # False because we don't want to ignore isCount for export
                # True because we don't want to use view.tzinfo.floating
                cal.vevent_list[-1].rruleset = event.createDateUtilFromRule(False, True, False)
        except AttributeError:
            logger.error('Failed to export RRULE for %s' % event.itsItem.itsUUID)
        # end of populateEvent function
        
        populateCustom(comp, event.itsItem)


    def populateModifications(event, cal):
        for modification in itertools.imap(EventStamp, event.modifications):
            for attr, val in modification.itsItem.iterModifiedAttributes():
                if attr in attributesUsedWhenExporting and attr not in filters:
                    populateEvent(cal.add('vevent'), modification)
                    break
        #end helper functions
        
    def populateTask(comp, task):
        """Populate the given vobject vtodo with data from task."""
        populateCommon(comp, task.itsItem)

        # @@@ [grant] Once we start writing out Event+Tasks as
        # VTODO, write out DUE (or maybe DTSTART) here.

        if Note._triageStatus.name not in filters:
            triageStatus = task.itsItem._triageStatus
            
            # VTODO STATUS mapping:
            # ---------------------
            #
            #  [ICalendar]            [Triage Enum]
            #  <no value>/IN-PROCESS    now  (needsReply=False)
            #  NEEDS-ACTION             now  (needsReply=True)
            #  COMPLETED                done
            #  CANCELLED                later
            
            if triageStatus == TriageEnum.now:
                if task.itsItem.needsReply:
                    comp.add('status').value = 'needs-action'
                else:
                    comp.add('status').value = 'in-process'
            elif triageStatus == TriageEnum.later:
                comp.add('status').value = 'cancelled'
            else:
                comp.add('status').value = 'completed'
                
        populateCustom(comp, task.itsItem)

    if cal is None:
        cal = vobject.iCalendar()
    for item in items: # main loop
        try:
            # ignore any events that aren't masters
            #
            # Note: [grant]
            # At the moment, we allow Event-ness to take precedence over
            # Task-ness. So, we serialize Event+Task objects as VEVENTs.
            # Part of the reason for this is that recurring VTODOs aren't
            # so well-supported by other iCalendar clients. For RFC 2445
            # issues with VTODO+RRULE, see e.g.
            # <http://lists.osafoundation.org/pipermail/ietf-calsify/2006-August/001134.html>
            if has_stamp(item, EventStamp):
                event = EventStamp(item)
                if event.getMaster() == event:
                  populateEvent(cal.add('vevent'), event)
                populateModifications(event, cal)
            elif has_stamp(item, TaskStamp):
                  populateTask(cal.add('vtodo'), TaskStamp(item))
        except:
            logger.exception("Exception while exporting %s" % item)
            continue

    return cal
예제 #57
0
    def testResourceBookingOverlapDetection(self):
        """ Resource booking overlap detection - bug #1837"""

        # There used to be some problems with recurring events and resources booking
        # This test implements these edge cases

        # 1. Create recurring event (with resource)
        # 2. Create single event overlaping one instance for the previous event
        #    (should fail)
        # 3. Create recurring event which _doesn't_ overlap the first event
        #    (should be OK, used to fail pre1.3.17)
        # 4. Create recurring event overlapping the previous recurring event
        #    (should fail)

        # make sure there are no events in the resource calendar
        self._deleteAllEvents(self.superuser_client, self.res_calendar)

        # make sure the event doesn't exist
        ics_name = "test-res-overlap-detection.ics"
        self.ics_list += [ics_name]
        self._deleteEvent(self.client, "%s%s" % (self.user_calendar, ics_name),
                          None)

        overlap_ics_name = "test-res-overlap-detection-overlap.ics"
        self.ics_list += [overlap_ics_name]
        self._deleteEvent(self.client,
                          "%s%s" % (self.attendee1_calendar, overlap_ics_name),
                          None)

        nooverlap_recurring_ics_name = "test-res-overlap-detection-nooverlap.ics"
        self.ics_list += [nooverlap_recurring_ics_name]
        self._deleteEvent(
            self.client,
            "%s%s" % (self.user_calendar, nooverlap_recurring_ics_name), None)

        overlap_recurring_ics_name = "test-res-overlap-detection-overlap-recurring.ics"
        self.ics_list += [overlap_recurring_ics_name]
        self._deleteEvent(
            self.client,
            "%s%s" % (self.user_calendar, overlap_recurring_ics_name), None)

        # 1. create recurring event with resource
        event = self._newEvent(summary="recurring event with resource",
                               uid="recurring event w resource")
        event.vevent.add('rrule').value = "FREQ=DAILY;COUNT=5"
        organizer = event.vevent.add('organizer')
        organizer.cn_param = self.user_name
        organizer.value = self.user_email
        attendee = event.vevent.add('attendee')
        attendee.cn_param = self.res_no_ob_name
        attendee.rsvp_param = "TRUE"
        attendee.partstat_param = "NEEDS-ACTION"
        attendee.value = self.res_no_ob_email

        # keep a copy around for #3
        nooverlap_event = vobject.iCalendar()
        nooverlap_event.copy(event)

        self._putEvent(self.client, "%s%s" % (self.user_calendar, ics_name),
                       event)

        # 2. Create single event overlaping one instance for the previous event
        event = self._newEvent(summary="recurring event with resource",
                               uid="recurring event w resource - overlap")
        organizer = event.vevent.add('organizer')
        organizer.cn_param = self.attendee1_name
        organizer.value = self.attendee1_email
        attendee = event.vevent.add('attendee')
        attendee.cn_param = self.res_no_ob_name
        attendee.rsvp_param = "TRUE"
        attendee.partstat_param = "NEEDS-ACTION"
        attendee.value = self.res_no_ob_email
        # should fail
        self._putEvent(self.attendee1_client,
                       "%s%s" % (self.attendee1_calendar, overlap_ics_name),
                       event,
                       exp_status=409)

        # 3. Create recurring event which _doesn't_ overlap the first event
        #    (should be OK, used to fail pre1.3.17)
        # shift the start date to one hour after the original event end time
        nstartdate = nooverlap_event.vevent.dtend.value + datetime.timedelta(
            0, 3600)
        nooverlap_event.vevent.dtstart.value = nstartdate
        nooverlap_event.vevent.dtend.value = nstartdate + datetime.timedelta(
            0, 3600)
        nooverlap_event.vevent.uid.value = "recurring - nooverlap"

        self._putEvent(
            self.client,
            "%s%s" % (self.user_calendar, nooverlap_recurring_ics_name),
            nooverlap_event)

        # 4. Create recurring event overlapping the previous recurring event
        #    should fail with a 409
        nstartdate = nooverlap_event.vevent.dtstart.value + datetime.timedelta(
            0, 300)
        nooverlap_event.vevent.dtstart.value = nstartdate
        nooverlap_event.vevent.dtend.value = nstartdate + datetime.timedelta(
            0, 3600)
        nooverlap_event.vevent.uid.value = "recurring - overlap"
        self._putEvent(self.client,
                       "%s%s" %
                       (self.user_calendar, overlap_recurring_ics_name),
                       nooverlap_event,
                       exp_status=409)
예제 #58
0
    def vevent_list(self, for_print=False, include_section_events=True):
        """
        Return the vevent object list for all classes in this section.
        This specifically DOES NOT take into account cancelled classes,
            midterm, final exam, due dates, or office hours UNLESS
            ``include_section_events`` is ``True`` and there is something
            else that the calendar generator can use.
        """
        cal = vobject.iCalendar()
        if not self.active:
            return []
        if not self.section.active:
            return []
        if not self.section.course.active:
            return []
        if not self.section.course.department.active:
            return []

        def _get_class_schedule():
            if self.timeslot.name.lower() == "none":
                return []
            if not self.date_range:
                return []

            term_dtstart = utils.blend_date_and_time(self.date_range.start,
                                                     self.timeslot.start_time)
            term_dtfinish = utils.blend_date_and_time(self.date_range.finish,
                                                      self.timeslot.start_time)

            rrs = dateutil.rrule.rruleset()
            for impdate in ImportantDate.objects.filter(
                    active=True,
                    date__gte=self.date_range.start,
                    date__lte=self.date_range.finish,
                    no_class=True,
            ):
                dt = utils.blend_date_and_time(impdate.date,
                                               self.timeslot.start_time)
                rrs.exdate(dt)
                if impdate.end_date is not None:
                    enddt = utils.blend_date_and_time(
                        impdate.end_date,
                        datetime.time(hour=23, minute=59, second=59))
                    while dt <= enddt:
                        dt += datetime.timedelta(days=1)
                        rrs.exdate(dt)
            term = dateutil.rrule.rrule(
                dateutil.rrule.WEEKLY,  # count=26,
                wkst=dateutil.rrule.SU,
                byweekday=self.timeslot.get_rrule_days(),
                dtstart=term_dtstart,
            )
            rrs.rrule(term)

            for dtstart in rrs.between(term_dtstart, term_dtfinish, inc=True):
                ev = cal.add("vevent")
                ev.add("dtstamp").value = dtstart
                ev.add("dtstart").value = dtstart
                ev.add("dtend").value = utils.blend_date_and_time(
                    datetime.date(*(dtstart.timetuple()[:3])),
                    self.timeslot.stop_time)
                if not for_print:
                    ev.add("location").value = "{}".format(self.room)
                if for_print:
                    summary = (self.section.course.label + " " +
                               self.section.section_name + " " +
                               self.lab_section_name)
                    if self.instructor:
                        summary += " " + self.section.instructor.cn
                    ev.add("summary").value = summary
                else:
                    ev.add("summary").value = "{}".format(self.section)
            return cal.vevent_list if cal.vevent_list is not None else []

        def _get_related_events():
            # include other section events
            if not include_section_events:
                return []
            # add events of objects that relate to this object
            related_sets = [
                attr for attr in dir(self.section)
                if attr.endswith("_set") and attr != "sectionschedule_set"
            ]
            for attr in related_sets:
                related = getattr(self.section, attr)
                if hasattr(related.model, "vevent"):
                    for subobj in related.all():
                        ev = subobj.vevent()
                        if ev is not None:
                            cal.add(ev)
                if hasattr(related.model, "vevent_list"):
                    for subobj in related.all():
                        for ev in subobj.vevent_list():
                            cal.add(ev)

        _get_class_schedule()
        _get_related_events()
        return getattr(cal, "vevent_list", [])
예제 #59
0
def serializeTimeZone(tzinfo):
    """Given a tzinfo class, return a VTIMEZONE in an iCalendar object."""
    cal = vobject.iCalendar()
    cal.add(vobject.icalendar.TimezoneComponent(tzinfo=tzinfo))
    return cal.serialize()
예제 #60
0
def setup():
    global calendar

    c = vobject.iCalendar()
    calendar = c

    e = c.add('vevent')
    e.add('summary').value = "weekly expired"
    start = e.add('dtstart')
    start.value = datetime.datetime(2008, 11, 26, 13, 00, tzinfo=local)
    end = e.add('dtend')
    end.value = datetime.datetime(2008, 11, 26, 14, 00, tzinfo=local)
    rrule = e.add('rrule')
    rrule.value = 'FREQ=WEEKLY;INTERVAL=1;UNTIL=20090101T045959Z'

    e = c.add('vevent')
    e.add('summary').value = "daily expired"
    start = e.add('dtstart')
    start.value = datetime.datetime(2008, 11, 26, 13, 00, tzinfo=local)
    end = e.add('dtend')
    end.value = datetime.datetime(2008, 11, 26, 14, 00, tzinfo=local)
    rrule = e.add('rrule')
    rrule.value = 'FREQ=DAILY;INTERVAL=1;UNTIL=20090101T045959Z'

    e = c.add('vevent')
    e.add('summary').value = "weekly"
    start = e.add('dtstart')
    start.value = datetime.datetime(2009, 11, 26, 13, 00, tzinfo=local)
    end = e.add('dtend')
    end.value = datetime.datetime(2009, 11, 26, 14, 00, tzinfo=local)
    rrule = e.add('rrule')
    rrule.value = 'FREQ=WEEKLY;INTERVAL=1'

    e = c.add('vevent')
    e.add('summary').value = "daily"
    start = e.add('dtstart')
    start.value = datetime.datetime(2009, 11, 26, 13, 00, tzinfo=local)
    end = e.add('dtend')
    end.value = datetime.datetime(2009, 11, 26, 14, 00, tzinfo=local)
    rrule = e.add('rrule')
    rrule.value = 'FREQ=DAILY;INTERVAL=1'

    e = c.add('vevent')
    e.add('summary').value = "weekly future"
    start = e.add('dtstart')
    start.value = datetime.datetime(2010, 11, 26, 13, 00, tzinfo=local)
    end = e.add('dtend')
    end.value = datetime.datetime(2010, 11, 26, 14, 00, tzinfo=local)
    rrule = e.add('rrule')
    rrule.value = 'FREQ=WEEKLY;INTERVAL=1'

    e = c.add('vevent')
    e.add('summary').value = "daily future"
    start = e.add('dtstart')
    start.value = datetime.datetime(2010, 11, 26, 13, 00, tzinfo=local)
    end = e.add('dtend')
    end.value = datetime.datetime(2010, 11, 26, 14, 00, tzinfo=local)
    rrule = e.add('rrule')
    rrule.value = 'FREQ=DAILY;INTERVAL=1'

    return