Example #1
0
def _make_ics(event, etime):

    cal = Calendar()
    cal.add("prodid", "N1-send-availability-package")
    cal.add("version", "2.0")

    cal.add("method", "REQUEST")  # also have PUBLISH or CANCEL

    evt = Event()
    evt.add("summary", event.title)
    evt.add("location", event.location)
    evt.add("description", event.description)
    evt.add("dtstart", etime.start.replace(tzinfo=pytz.UTC))
    evt.add("dtend", etime.end.replace(tzinfo=pytz.UTC))
    evt.add("dtstamp", datetime.now(pytz.UTC))

    evt["uid"] = "{timestamp}/{email}".format(
        timestamp=time.mktime(datetime.now(pytz.UTC).timetuple()), email=event.organizer.email
    )
    evt.add("priority", 5)

    organizer = vCalAddress("MAILTO:{}".format(event.organizer.email))
    organizer.params["cn"] = vText(event.organizer.name)
    organizer.params["role"] = vText("CHAIR")
    evt["organizer"] = organizer

    for attendee in event.attendees:
        atnd = vCalAddress("MAILTO:{}".format(attendee.email))
        atnd.params["cn"] = vText(attendee.name)
        atnd.params["ROLE"] = vText("REQ-PARTICIPANT")
        evt.add("attendee", atnd, encode=0)

    cal.add_component(evt)

    return cal.to_ical()
Example #2
0
def _make_ics(event, etime):

    cal = Calendar()
    cal.add('prodid', 'N1-send-availability-package')
    cal.add('version', '1.0')

    evt = Event()
    evt.add('summary', event.title)
    evt.add('location', event.location)
    evt.add('description', event.description)
    evt.add('dtstart', etime.start)
    evt.add('dtend', etime.end)
    evt.add('dtstamp', datetime.now())

    evt['uid'] = '{timestamp}/{email}'.format(
        timestamp=time.mktime(datetime.now().timetuple()),
        email=event.organizer.email
    )
    evt.add('priority', 5)

    organizer = vCalAddress('MAILTO:{}'.format(event.organizer.email))
    organizer.params['cn'] = vText(event.organizer.name)
    organizer.params['role'] = vText('CHAIR')
    evt['organizer'] = organizer

    for attendee in event.attendees:
        atnd = vCalAddress('MAILTO:{}'.format(attendee.email))
        atnd.params['cn'] = vText(attendee.name)
        atnd.params['ROLE'] = vText('REQ-PARTICIPANT')
        evt.add('attendee', atnd, encode=0)

    cal.add_component(evt)

    return cal.to_ical()
Example #3
0
File: backend.py Project: zyuyou/N1
def _make_ics(event, etime):

    cal = Calendar()
    cal.add('prodid', 'N1-send-availability-package')
    cal.add('version', '1.0')

    evt = Event()
    evt.add('summary', event.title)
    evt.add('location', event.location)
    evt.add('description', event.description)
    evt.add('dtstart', etime.start)
    evt.add('dtend', etime.end)
    evt.add('dtstamp', datetime.now())

    evt['uid'] = '{timestamp}/{email}'.format(timestamp=time.mktime(
        datetime.now().timetuple()),
                                              email=event.organizer.email)
    evt.add('priority', 5)

    organizer = vCalAddress('MAILTO:{}'.format(event.organizer.email))
    organizer.params['cn'] = vText(event.organizer.name)
    organizer.params['role'] = vText('CHAIR')
    evt['organizer'] = organizer

    for attendee in event.attendees:
        atnd = vCalAddress('MAILTO:{}'.format(attendee.email))
        atnd.params['cn'] = vText(attendee.name)
        atnd.params['ROLE'] = vText('REQ-PARTICIPANT')
        evt.add('attendee', atnd, encode=0)

    cal.add_component(evt)

    return cal.to_ical()
def marshall_event_to_vevent(instance):
    wf = getToolByName(instance, 'portal_workflow')
    dtstamp = utc_strftime(datetime.utcnow(), "%Y%m%dT%H%M%SZ")
    uid_hash = abs(hash(instance))
    state = wf.getInfoFor(instance, 'review_state')
    status = re_status_mapping.get(state, 'TENTATIVE')
    event = VEvent()
    event.add('uid', generateUID(instance))
    event.add('summary', instance.Title(), encode=False)
    event.add('description', instance.Description(), encode=False)
    if hasattr(aq_base(instance), 'getLocation'):
        location = instance.getLocation()
        if location:
            event.add('location', location, encode=False)
    if hasattr(aq_base(instance), 'Subject'):
        subject = instance.Subject()
        if subject:
            for category in subject:
                event.add('categories', category, encode=False)
    if hasattr(aq_base(instance), 'event_url'):
        url = instance.event_url
        if callable(url):
            # Ugh, it's callable in ATContentTypes.
            url = url()
        if url:
            event.add('url', url)
            event['url'].params['value'] = 'URI'
    if hasattr(aq_base(instance), 'getAttendees'):
        for att in instance.getAttendees():
            name, email = parseaddr(att)
            if not name:
                name = att
                email = ''
            if email:
                email = 'mailto:%s' % email
            else:
                email = 'invalid:nomail'
            address = vCalAddress(email)
            address.params['cn'] = name
            event.add('attendee', address, encode=False)
    if (hasattr(aq_base(instance), 'duration')
            and instance.duration == date.resolution):
        # All day event.
        dtstart = vDate.from_ical(utc_strftime(instance.start_date, '%Y%m%d'))
        event.add('dtstart', dtstart)
        dtend = vDate.from_ical(utc_strftime(instance.end_date, '%Y%m%d'))
        event.add('dtend', dtend)
    else:
        # Normal event
        dtstart = vDatetime.from_ical(
            utc_strftime(instance.start_date, '%Y%m%dT%H%M%SZ'))
        event.add('dtstart', dtstart)
        dtend = vDatetime.from_ical(
            utc_strftime(instance.end_date, '%Y%m%dT%H%M%SZ'))
        event.add('dtend', dtend)
    dtstamp = vDatetime.from_ical(dtstamp)
    event.add('dtstamp', dtstamp)
    #event.add('status', status)
    return event
Example #5
0
def _make_ics(event, etime):

    cal = Calendar()
    cal.add('prodid', 'N1-quick-schedule-package')
    cal.add('version', '2.0')

    cal.add('method', 'REQUEST')   # also have PUBLISH or CANCEL

    evt = Event()
    evt.add('summary', event.title)
    evt.add('location', event.location)
    evt.add('description', event.description)
    evt.add('dtstart', etime.start.replace(tzinfo=pytz.UTC))
    evt.add('dtend', etime.end.replace(tzinfo=pytz.UTC))
    evt.add('dtstamp', datetime.now(pytz.UTC))

    evt['uid'] = '{timestamp}/{email}'.format(
        timestamp=time.mktime(datetime.now(pytz.UTC).timetuple()),
        email=event.organizer.email
    )
    evt.add('priority', 5)

    organizer = vCalAddress('MAILTO:{}'.format(event.organizer.email))
    organizer.params['cn'] = vText(event.organizer.name)
    organizer.params['role'] = vText('CHAIR')
    evt['organizer'] = organizer

    for attendee in event.attendees:
        atnd = vCalAddress('MAILTO:{}'.format(attendee.email))
        atnd.params['cn'] = vText(attendee.name)
        atnd.params['ROLE'] = vText('REQ-PARTICIPANT')
        evt.add('attendee', atnd, encode=0)

    cal.add_component(evt)

    return cal.to_ical()
Example #6
0
def generate_calendar(request):
    """http://codespeak.net/icalendar/"""

    cal = Calendar()
    cal.add("prodid", "-//Club Connect//ericleong.me//")
    cal.add("version", "2.0")
    posts = Post.objects.order_by("-created")

    cal["X-WR-CALNAME"] = "Club Connect Events"
    cal["X-PUBLISH-TTL"] = "PT12H"
    cal["CALSCALE"] = "GREGORIAN"
    cal["METHOD"] = "PUBLISH"

    # TODO: separate out private events using a private URL?
    # TODO: switch to using EDT
    for post in posts:
        if post.start_time:
            # Make sure we have a time
            event = Event()
            event.add("summary", vText(post.title))
            event.add("dtstart", post.start_time)
            event.add("dtend", post.end_time if post.end_time else post.start_time)
            # event.add('dtstamp', datetime(2005,4,4,0,10,0,tzinfo=UTC))
            event["uid"] = vText(post.id)
            event["organizer"] = vText(post.author.username)
            event["description"] = vText(post.description)
            event["url"] = vUri(post.get_absolute_url())

            if post.location:
                if post.location.room:
                    event["location"] = vText("%s (%s)" % (post.location.name, post.location.room))
                else:
                    event["location"] = vText(post.location.name)

            for commit in post.committed.all():
                attendee = vCalAddress("MAILTO:" + commit.email)
                name = (
                    ([commit.first_name, commit.last_name])
                    if (commit.first_name and commit.last_name)
                    else commit.username
                )
                attendee.params["cn"] = vText(name)
                event.add("attendee", attendee, encode=0)

            cal.add_component(event)

    return HttpResponse(cal.to_ical().replace("\n", "\r\n"), content_type="text/calendar")
Example #7
0
    def test_cal_Component(self):
        from icalendar.cal import Component, Calendar, Event
        from icalendar import prop

        # A component is like a dictionary with extra methods and attributes.
        c = Component()
        c.name = 'VCALENDAR'

        # Every key defines a property.A property can consist of either a
        # single item. This can be set with a single value...
        c['prodid'] = '-//max m//icalendar.mxm.dk/'
        self.assertEqual(
            c,
            Calendar({'PRODID': '-//max m//icalendar.mxm.dk/'})
        )

        # or with a list
        c['ATTENDEE'] = ['Max M', 'Rasmussen']
        self.assertEqual(
            c,
            Calendar({'ATTENDEE': ['Max M', 'Rasmussen'],
                      'PRODID': '-//max m//icalendar.mxm.dk/'})
        )

        ### ADD MULTIPLE VALUES TO A PROPERTY

        # if you use the add method you don't have to considder if a value is
        # a list or not.
        c = Component()
        c.name = 'VEVENT'

        # add multiple values at once
        c.add('attendee',
              ['*****@*****.**', '*****@*****.**'])

        # or add one per line
        c.add('attendee', '*****@*****.**')
        c.add('attendee', '*****@*****.**')

        # add again multiple values at once to very concatenaton of lists
        c.add('attendee',
              ['*****@*****.**', '*****@*****.**'])

        self.assertEqual(
            c,
            Event({'ATTENDEE': [
                prop.vCalAddress('*****@*****.**'),
                prop.vCalAddress('*****@*****.**'),
                prop.vCalAddress('*****@*****.**'),
                prop.vCalAddress('*****@*****.**'),
                prop.vCalAddress('*****@*****.**'),
                prop.vCalAddress('*****@*****.**')
            ]})
        )

        ###

        # You can get the values back directly ...
        c.add('prodid', '-//my product//')
        self.assertEqual(c['prodid'], prop.vText(u'-//my product//'))

        # ... or decoded to a python type
        self.assertEqual(c.decoded('prodid'), b'-//my product//')

        # With default values for non existing properties
        self.assertEqual(c.decoded('version', 'No Version'), 'No Version')

        c.add('rdate', [datetime(2013, 3, 28), datetime(2013, 3, 27)])
        self.assertTrue(isinstance(c.decoded('rdate'), prop.vDDDLists))

        # The component can render itself in the RFC 2445 format.
        c = Component()
        c.name = 'VCALENDAR'
        c.add('attendee', 'Max M')
        self.assertEqual(
            c.to_ical(),
            b'BEGIN:VCALENDAR\r\nATTENDEE:Max M\r\nEND:VCALENDAR\r\n'
        )

        # Components can be nested, so You can add a subcompont. Eg a calendar
        # holds events.
        e = Component(summary='A brief history of time')
        e.name = 'VEVENT'
        e.add('dtend', '20000102T000000', encode=0)
        e.add('dtstart', '20000101T000000', encode=0)
        self.assertEqual(
            e.to_ical(),
            b'BEGIN:VEVENT\r\nDTEND:20000102T000000\r\n'
            + b'DTSTART:20000101T000000\r\nSUMMARY:A brief history of time\r'
            + b'\nEND:VEVENT\r\n'
        )

        c.add_component(e)
        self.assertEqual(
            c.subcomponents,
            [Event({'DTEND': '20000102T000000', 'DTSTART': '20000101T000000',
                    'SUMMARY': 'A brief history of time'})]
        )

        # We can walk over nested componentes with the walk method.
        self.assertEqual([i.name for i in c.walk()], ['VCALENDAR', 'VEVENT'])

        # We can also just walk over specific component types, by filtering
        # them on their name.
        self.assertEqual([i.name for i in c.walk('VEVENT')], ['VEVENT'])

        self.assertEqual(
            [i['dtstart'] for i in c.walk('VEVENT')],
            ['20000101T000000']
        )

        # We can enumerate property items recursively with the property_items
        # method.
        self.assertEqual(
            c.property_items(),
            [('BEGIN', b'VCALENDAR'), ('ATTENDEE', prop.vCalAddress('Max M')),
             ('BEGIN', b'VEVENT'), ('DTEND', '20000102T000000'),
             ('DTSTART', '20000101T000000'),
             ('SUMMARY', 'A brief history of time'), ('END', b'VEVENT'),
             ('END', b'VCALENDAR')]
        )

        # We can also enumerate property items just under the component.
        self.assertEqual(
            c.property_items(recursive=False),
            [('BEGIN', b'VCALENDAR'),
             ('ATTENDEE', prop.vCalAddress('Max M')),
             ('END', b'VCALENDAR')]
        )

        sc = c.subcomponents[0]
        self.assertEqual(
            sc.property_items(recursive=False),
            [('BEGIN', b'VEVENT'), ('DTEND', '20000102T000000'),
             ('DTSTART', '20000101T000000'),
             ('SUMMARY', 'A brief history of time'), ('END', b'VEVENT')]
        )

        # Text fields which span multiple mulitple lines require proper
        # indenting
        c = Calendar()
        c['description'] = u'Paragraph one\n\nParagraph two'
        self.assertEqual(
            c.to_ical(),
            b'BEGIN:VCALENDAR\r\nDESCRIPTION:Paragraph one\\n\\nParagraph two'
            + b'\r\nEND:VCALENDAR\r\n'
        )

        # INLINE properties have their values on one property line. Note the
        # double quoting of the value with a colon in it.
        c = Calendar()
        c['resources'] = 'Chair, Table, "Room: 42"'
        self.assertEqual(
            c,
            Calendar({'RESOURCES': 'Chair, Table, "Room: 42"'})
        )

        self.assertEqual(
            c.to_ical(),
            b'BEGIN:VCALENDAR\r\nRESOURCES:Chair\\, Table\\, "Room: 42"\r\n'
            + b'END:VCALENDAR\r\n'
        )

        # The inline values must be handled by the get_inline() and
        # set_inline() methods.
        self.assertEqual(
            c.get_inline('resources', decode=0),
            [u'Chair', u'Table', u'Room: 42']
        )

        # These can also be decoded
        self.assertEqual(
            c.get_inline('resources', decode=1),
            [b'Chair', b'Table', b'Room: 42']
        )

        # You can set them directly ...
        c.set_inline('resources', ['A', 'List', 'of', 'some, recources'],
                     encode=1)
        self.assertEqual(c['resources'], 'A,List,of,"some, recources"')

        # ... and back again
        self.assertEqual(
            c.get_inline('resources', decode=0),
            ['A', 'List', 'of', 'some, recources']
        )

        c['freebusy'] = '19970308T160000Z/PT3H,19970308T200000Z/PT1H,'\
                        + '19970308T230000Z/19970309T000000Z'
        self.assertEqual(
            c.get_inline('freebusy', decode=0),
            ['19970308T160000Z/PT3H', '19970308T200000Z/PT1H',
             '19970308T230000Z/19970309T000000Z']
        )

        freebusy = c.get_inline('freebusy', decode=1)
        self.assertTrue(isinstance(freebusy[0][0], datetime))
        self.assertTrue(isinstance(freebusy[0][1], timedelta))
Example #8
0
    def test_cal_Component(self):
        from icalendar.cal import Component, Calendar, Event
        from icalendar import prop

        # A component is like a dictionary with extra methods and attributes.
        c = Component()
        c.name = 'VCALENDAR'

        # Every key defines a property.A property can consist of either a
        # single item. This can be set with a single value...
        c['prodid'] = '-//max m//icalendar.mxm.dk/'
        self.assertEqual(c, Calendar({'PRODID':
                                      '-//max m//icalendar.mxm.dk/'}))

        # or with a list
        c['ATTENDEE'] = ['Max M', 'Rasmussen']
        self.assertEqual(
            c,
            Calendar({
                'ATTENDEE': ['Max M', 'Rasmussen'],
                'PRODID': '-//max m//icalendar.mxm.dk/'
            }))

        ### ADD MULTIPLE VALUES TO A PROPERTY

        # if you use the add method you don't have to considder if a value is
        # a list or not.
        c = Component()
        c.name = 'VEVENT'

        # add multiple values at once
        c.add('attendee', ['*****@*****.**', '*****@*****.**'])

        # or add one per line
        c.add('attendee', '*****@*****.**')
        c.add('attendee', '*****@*****.**')

        # add again multiple values at once to very concatenaton of lists
        c.add('attendee', ['*****@*****.**', '*****@*****.**'])

        self.assertEqual(
            c,
            Event({
                'ATTENDEE': [
                    prop.vCalAddress('*****@*****.**'),
                    prop.vCalAddress('*****@*****.**'),
                    prop.vCalAddress('*****@*****.**'),
                    prop.vCalAddress('*****@*****.**'),
                    prop.vCalAddress('*****@*****.**'),
                    prop.vCalAddress('*****@*****.**')
                ]
            }))

        ###

        # You can get the values back directly ...
        c.add('prodid', '-//my product//')
        self.assertEqual(c['prodid'], prop.vText(u'-//my product//'))

        # ... or decoded to a python type
        self.assertEqual(c.decoded('prodid'), b'-//my product//')

        # With default values for non existing properties
        self.assertEqual(c.decoded('version', 'No Version'), 'No Version')

        c.add('rdate', [datetime(2013, 3, 28), datetime(2013, 3, 27)])
        self.assertTrue(isinstance(c.decoded('rdate'), prop.vDDDLists))

        # The component can render itself in the RFC 2445 format.
        c = Component()
        c.name = 'VCALENDAR'
        c.add('attendee', 'Max M')
        self.assertEqual(
            c.to_ical(),
            b'BEGIN:VCALENDAR\r\nATTENDEE:Max M\r\nEND:VCALENDAR\r\n')

        # Components can be nested, so You can add a subcompont. Eg a calendar
        # holds events.
        e = Component(summary='A brief history of time')
        e.name = 'VEVENT'
        e.add('dtend', '20000102T000000', encode=0)
        e.add('dtstart', '20000101T000000', encode=0)
        self.assertEqual(
            e.to_ical(), b'BEGIN:VEVENT\r\nDTEND:20000102T000000\r\n' +
            b'DTSTART:20000101T000000\r\nSUMMARY:A brief history of time\r' +
            b'\nEND:VEVENT\r\n')

        c.add_component(e)
        self.assertEqual(c.subcomponents, [
            Event({
                'DTEND': '20000102T000000',
                'DTSTART': '20000101T000000',
                'SUMMARY': 'A brief history of time'
            })
        ])

        # We can walk over nested componentes with the walk method.
        self.assertEqual([i.name for i in c.walk()], ['VCALENDAR', 'VEVENT'])

        # We can also just walk over specific component types, by filtering
        # them on their name.
        self.assertEqual([i.name for i in c.walk('VEVENT')], ['VEVENT'])

        self.assertEqual([i['dtstart'] for i in c.walk('VEVENT')],
                         ['20000101T000000'])

        # We can enumerate property items recursively with the property_items
        # method.
        self.assertEqual(c.property_items(),
                         [('BEGIN', b'VCALENDAR'),
                          ('ATTENDEE', prop.vCalAddress('Max M')),
                          ('BEGIN', b'VEVENT'), ('DTEND', '20000102T000000'),
                          ('DTSTART', '20000101T000000'),
                          ('SUMMARY', 'A brief history of time'),
                          ('END', b'VEVENT'), ('END', b'VCALENDAR')])

        # We can also enumerate property items just under the component.
        self.assertEqual(c.property_items(recursive=False),
                         [('BEGIN', b'VCALENDAR'),
                          ('ATTENDEE', prop.vCalAddress('Max M')),
                          ('END', b'VCALENDAR')])

        sc = c.subcomponents[0]
        self.assertEqual(sc.property_items(recursive=False),
                         [('BEGIN', b'VEVENT'), ('DTEND', '20000102T000000'),
                          ('DTSTART', '20000101T000000'),
                          ('SUMMARY', 'A brief history of time'),
                          ('END', b'VEVENT')])

        # Text fields which span multiple mulitple lines require proper
        # indenting
        c = Calendar()
        c['description'] = u'Paragraph one\n\nParagraph two'
        self.assertEqual(
            c.to_ical(),
            b'BEGIN:VCALENDAR\r\nDESCRIPTION:Paragraph one\\n\\nParagraph two'
            + b'\r\nEND:VCALENDAR\r\n')

        # INLINE properties have their values on one property line. Note the
        # double quoting of the value with a colon in it.
        c = Calendar()
        c['resources'] = 'Chair, Table, "Room: 42"'
        self.assertEqual(c, Calendar({'RESOURCES':
                                      'Chair, Table, "Room: 42"'}))

        self.assertEqual(
            c.to_ical(),
            b'BEGIN:VCALENDAR\r\nRESOURCES:Chair\\, Table\\, "Room: 42"\r\n' +
            b'END:VCALENDAR\r\n')

        # The inline values must be handled by the get_inline() and
        # set_inline() methods.
        self.assertEqual(c.get_inline('resources', decode=0),
                         [u'Chair', u'Table', u'Room: 42'])

        # These can also be decoded
        self.assertEqual(c.get_inline('resources', decode=1),
                         [b'Chair', b'Table', b'Room: 42'])

        # You can set them directly ...
        c.set_inline('resources', ['A', 'List', 'of', 'some, recources'],
                     encode=1)
        self.assertEqual(c['resources'], 'A,List,of,"some, recources"')

        # ... and back again
        self.assertEqual(c.get_inline('resources', decode=0),
                         ['A', 'List', 'of', 'some, recources'])

        c['freebusy'] = '19970308T160000Z/PT3H,19970308T200000Z/PT1H,'\
                        + '19970308T230000Z/19970309T000000Z'
        self.assertEqual(c.get_inline('freebusy', decode=0), [
            '19970308T160000Z/PT3H', '19970308T200000Z/PT1H',
            '19970308T230000Z/19970309T000000Z'
        ])

        freebusy = c.get_inline('freebusy', decode=1)
        self.assertTrue(isinstance(freebusy[0][0], datetime))
        self.assertTrue(isinstance(freebusy[0][1], timedelta))
Example #9
0
    def test_cal_Component(self):
        from icalendar.cal import Component, Calendar, Event
        from icalendar import prop

        # A component is like a dictionary with extra methods and attributes.
        c = Component()
        c.name = "VCALENDAR"

        # Every key defines a property.A property can consist of either a
        # single item. This can be set with a single value...
        c["prodid"] = "-//max m//icalendar.mxm.dk/"
        self.assertEqual(c, Calendar({"PRODID": "-//max m//icalendar.mxm.dk/"}))

        # or with a list
        c["ATTENDEE"] = ["Max M", "Rasmussen"]
        self.assertEqual(c, Calendar({"ATTENDEE": ["Max M", "Rasmussen"], "PRODID": "-//max m//icalendar.mxm.dk/"}))

        ### ADD MULTIPLE VALUES TO A PROPERTY

        # if you use the add method you don't have to considder if a value is
        # a list or not.
        c = Component()
        c.name = "VEVENT"

        # add multiple values at once
        c.add("attendee", ["*****@*****.**", "*****@*****.**"])

        # or add one per line
        c.add("attendee", "*****@*****.**")
        c.add("attendee", "*****@*****.**")

        # add again multiple values at once to very concatenaton of lists
        c.add("attendee", ["*****@*****.**", "*****@*****.**"])

        self.assertEqual(
            c,
            Event(
                {
                    "ATTENDEE": [
                        prop.vCalAddress("*****@*****.**"),
                        prop.vCalAddress("*****@*****.**"),
                        prop.vCalAddress("*****@*****.**"),
                        prop.vCalAddress("*****@*****.**"),
                        prop.vCalAddress("*****@*****.**"),
                        prop.vCalAddress("*****@*****.**"),
                    ]
                }
            ),
        )

        ###

        # You can get the values back directly ...
        c.add("prodid", "-//my product//")
        self.assertEqual(c["prodid"], prop.vText(u"-//my product//"))

        # ... or decoded to a python type
        self.assertEqual(c.decoded("prodid"), b"-//my product//")

        # With default values for non existing properties
        self.assertEqual(c.decoded("version", "No Version"), "No Version")

        c.add("rdate", [datetime(2013, 3, 28), datetime(2013, 3, 27)])
        self.assertTrue(isinstance(c.decoded("rdate"), prop.vDDDLists))

        # The component can render itself in the RFC 2445 format.
        c = Component()
        c.name = "VCALENDAR"
        c.add("attendee", "Max M")
        self.assertEqual(c.to_ical(), b"BEGIN:VCALENDAR\r\nATTENDEE:Max M\r\nEND:VCALENDAR\r\n")

        # Components can be nested, so You can add a subcompont. Eg a calendar
        # holds events.
        e = Component(summary="A brief history of time")
        e.name = "VEVENT"
        e.add("dtend", "20000102T000000", encode=0)
        e.add("dtstart", "20000101T000000", encode=0)
        self.assertEqual(
            e.to_ical(),
            b"BEGIN:VEVENT\r\nDTEND:20000102T000000\r\n"
            + b"DTSTART:20000101T000000\r\nSUMMARY:A brief history of time\r"
            + b"\nEND:VEVENT\r\n",
        )

        c.add_component(e)
        self.assertEqual(
            c.subcomponents,
            [Event({"DTEND": "20000102T000000", "DTSTART": "20000101T000000", "SUMMARY": "A brief history of time"})],
        )

        # We can walk over nested componentes with the walk method.
        self.assertEqual([i.name for i in c.walk()], ["VCALENDAR", "VEVENT"])

        # We can also just walk over specific component types, by filtering
        # them on their name.
        self.assertEqual([i.name for i in c.walk("VEVENT")], ["VEVENT"])

        self.assertEqual([i["dtstart"] for i in c.walk("VEVENT")], ["20000101T000000"])

        # We can enumerate property items recursively with the property_items
        # method.
        self.assertEqual(
            c.property_items(),
            [
                ("BEGIN", b"VCALENDAR"),
                ("ATTENDEE", prop.vCalAddress("Max M")),
                ("BEGIN", b"VEVENT"),
                ("DTEND", "20000102T000000"),
                ("DTSTART", "20000101T000000"),
                ("SUMMARY", "A brief history of time"),
                ("END", b"VEVENT"),
                ("END", b"VCALENDAR"),
            ],
        )

        # We can also enumerate property items just under the component.
        self.assertEqual(
            c.property_items(recursive=False),
            [("BEGIN", b"VCALENDAR"), ("ATTENDEE", prop.vCalAddress("Max M")), ("END", b"VCALENDAR")],
        )

        sc = c.subcomponents[0]
        self.assertEqual(
            sc.property_items(recursive=False),
            [
                ("BEGIN", b"VEVENT"),
                ("DTEND", "20000102T000000"),
                ("DTSTART", "20000101T000000"),
                ("SUMMARY", "A brief history of time"),
                ("END", b"VEVENT"),
            ],
        )

        # Text fields which span multiple mulitple lines require proper
        # indenting
        c = Calendar()
        c["description"] = u"Paragraph one\n\nParagraph two"
        self.assertEqual(
            c.to_ical(), b"BEGIN:VCALENDAR\r\nDESCRIPTION:Paragraph one\\n\\nParagraph two" + b"\r\nEND:VCALENDAR\r\n"
        )

        # INLINE properties have their values on one property line. Note the
        # double quoting of the value with a colon in it.
        c = Calendar()
        c["resources"] = 'Chair, Table, "Room: 42"'
        self.assertEqual(c, Calendar({"RESOURCES": 'Chair, Table, "Room: 42"'}))

        self.assertEqual(
            c.to_ical(), b'BEGIN:VCALENDAR\r\nRESOURCES:Chair\\, Table\\, "Room: 42"\r\n' + b"END:VCALENDAR\r\n"
        )

        # The inline values must be handled by the get_inline() and
        # set_inline() methods.
        self.assertEqual(c.get_inline("resources", decode=0), [u"Chair", u"Table", u"Room: 42"])

        # These can also be decoded
        self.assertEqual(c.get_inline("resources", decode=1), [b"Chair", b"Table", b"Room: 42"])

        # You can set them directly ...
        c.set_inline("resources", ["A", "List", "of", "some, recources"], encode=1)
        self.assertEqual(c["resources"], 'A,List,of,"some, recources"')

        # ... and back again
        self.assertEqual(c.get_inline("resources", decode=0), ["A", "List", "of", "some, recources"])

        c["freebusy"] = "19970308T160000Z/PT3H,19970308T200000Z/PT1H," + "19970308T230000Z/19970309T000000Z"
        self.assertEqual(
            c.get_inline("freebusy", decode=0),
            ["19970308T160000Z/PT3H", "19970308T200000Z/PT1H", "19970308T230000Z/19970309T000000Z"],
        )

        freebusy = c.get_inline("freebusy", decode=1)
        self.assertTrue(isinstance(freebusy[0][0], datetime))
        self.assertTrue(isinstance(freebusy[0][1], timedelta))
Example #10
0
    def get_calendar_entry(self):
        """
        Build the iCalendar string for the event
        iCal validator, useful for debugging: http://icalvalid.cloudapp.net/
        """
        event = self.event
        event_tz = event.timezone
        creation_time = django_timezone.now()

        # Generate some description strings
        title, desc_plain, _desc_html = self.get_invite_texts()

        # Generate the Calendar event
        cal = icalendar.Calendar()
        cal.add("prodid", "-//OneEvent event entry//onevent//EN")
        cal.add("version", "2.0")
        cal.add("calscale", "GREGORIAN")
        cal.add("method", "REQUEST")

        # Generate timezone infos relevant to the event
        tzmap = {}
        tzmap = add_to_zones_map(tzmap, event_tz.zone, event.start)
        tzmap = add_to_zones_map(tzmap, event_tz.zone, event.get_real_end())
        tzmap = add_to_zones_map(tzmap,
                                 django_timezone.get_default_timezone_name(),
                                 creation_time)

        for tzid, transitions in tzmap.items():
            cal_tz = icalendar.Timezone()
            cal_tz.add("tzid", tzid)
            cal_tz.add("x-lic-location", tzid)

            for transition, tzinfo in transitions.items():

                if tzinfo["dst"]:
                    cal_tz_sub = icalendar.TimezoneDaylight()
                else:
                    cal_tz_sub = icalendar.TimezoneStandard()

                cal_tz_sub.add("tzname", tzinfo["name"])
                cal_tz_sub.add("dtstart", transition)
                cal_tz_sub.add("tzoffsetfrom", tzinfo["tzoffsetfrom"])
                cal_tz_sub.add("tzoffsetto", tzinfo["tzoffsetto"])
                cal_tz.add_component(cal_tz_sub)
            cal.add_component(cal_tz)

        cal_evt = icalendar.Event()

        cal_evt.add("uid",
                    "event{0}-booking{1}@oneevent".format(event.id, self.id))
        cal_evt.add("dtstamp", creation_time)
        cal_evt.add("dtstart", event.start.astimezone(event_tz))
        cal_evt.add("dtend", event.get_real_end().astimezone(event_tz))
        cal_evt.add("created", creation_time)
        cal_evt.add("sequence", "1")

        cal_evt.add("summary", title)
        cal_evt.add("description", desc_plain)
        cal_evt.add("location", vText(event.location_name))

        cal_evt.add("category", "Event")
        cal_evt.add("status", "CONFIRMED")
        cal_evt.add("transp", "OPAQUE")
        cal_evt.add("priority", "5")
        cal_evt.add("class", "PUBLIC")

        organiser = vCalAddress("mailto:{0}".format(event.owner.email))
        organiser.params["cn"] = vText(event.owner.get_full_name())
        organiser.params["role"] = vText("CHAIR")
        cal_evt.add("organizer", organiser, encode=0)

        attendee = vCalAddress("mailto:{0}".format(self.person.email))
        attendee.params["cutype"] = vText("INDIVIDUAL")
        attendee.params["role"] = vText("REQ-PARTICIPANT")
        attendee.params["partstat"] = vText("NEEDS-ACTION")
        attendee.params["rsvp"] = vText("FALSE")
        attendee.params["cn"] = vText(self.person.get_full_name())
        cal_evt.add("attendee", attendee, encode=0)

        cal.add_component(cal_evt)

        return cal.to_ical()
def marshall_event_to_vevent(instance):
    wf = getToolByName(instance, 'portal_workflow')
    dtstamp = utc_strftime(datetime.utcnow(), "%Y%m%dT%H%M%SZ")
    uid_hash = abs(hash(instance))
    state = wf.getInfoFor(instance, 'review_state')
    status = re_status_mapping.get(state, 'TENTATIVE')
    event = VEvent()
    event.add('uid', generateUID(instance))
    event.add('summary', instance.Title(), encode=False)
    event.add('description', instance.Description(), encode=False)
    if hasattr(aq_base(instance), 'getLocation'):
        location = instance.getLocation()
        if location:
            event.add('location', location, encode=False)
    if hasattr(aq_base(instance), 'Subject'):
        subject = instance.Subject()
        if subject:
            for category in subject:
                event.add('categories', category, encode=False)
    if hasattr(aq_base(instance), 'event_url'):
        url = instance.event_url
        if callable(url):
            # Ugh, it's callable in ATContentTypes.
            url = url()
        if url:
            event.add('url', url)
            event['url'].params['value'] = 'URI'
    if hasattr(aq_base(instance), 'getAttendees'):
        for att in instance.getAttendees():
            name, email = parseaddr(att)
            if not name:
                name = att
                email = ''
            if email:
                email = 'mailto:%s' % email
            else:
                email = 'invalid:nomail'
            address = vCalAddress(email)
            address.params['cn'] = name
            event.add('attendee', address, encode=False)
    if (hasattr(aq_base(instance), 'duration') and
        instance.duration == date.resolution):
        # All day event.
        dtstart = vDate.from_ical(
            utc_strftime(instance.start_date, '%Y%m%d'))
        event.add('dtstart', dtstart)
        dtend = vDate.from_ical(
            utc_strftime(instance.end_date, '%Y%m%d'))
        event.add('dtend', dtend)
    else:
        # Normal event
        dtstart = vDatetime.from_ical(
            utc_strftime(instance.start_date, '%Y%m%dT%H%M%SZ'))
        event.add('dtstart', dtstart)
        dtend = vDatetime.from_ical(
            utc_strftime(instance.end_date, '%Y%m%dT%H%M%SZ'))
        event.add('dtend', dtend)
    dtstamp = vDatetime.from_ical(dtstamp)
    event.add('dtstamp', dtstamp)
    #event.add('status', status)
    return event