Ejemplo n.º 1
0
 def get_calendar(self):
     calendar = ic.Calendar()
     calendar.add('X-WR-CALNAME', '课程表')
     for c in self.course_list:
         calendar.add_component(c.get_event(self.first_week))
     return calendar
Ejemplo n.º 2
0
def ics_feed():
    log.debug('handling a query')
    if conf is None:
        log.error("No configuration available")
        return flask.Response(status_code=500, status='Missing configuration')

    q_contact = flask.request.args.get('contact')

    cal = icalendar.Calendar()
    cal.add('prodid', '-//danielpocock.com//NagiosIssueFeed//')
    cal.add('version', '1.0')

    s = mk_livestatus.Socket(conf['livestatus_sock'])
    q = s.services.columns('state', 'host_alias', 'description',
                           'plugin_output', 'last_state_change', 'last_check',
                           'action_url_expanded',
                           'acknowledged').filter('state > 0')
    q_contact = flask.request.args.get('contact')
    if q_contact is not None:
        log.debug("Contact: %s" % q_contact)
        q = q.filter('contacts >= %s' % q_contact)
    result = q.call()
    log.debug("services query got %d row(s)" % (len(result)))
    for row in result:
        try:
            todo = icalendar.Todo()
            todo['uid'] = make_uid(row)
            todo['summary'] = make_title(row)
            todo['description'] = row['plugin_output']
            if row['action_url_expanded']:
                todo['url'] = row['action_url_expanded']
            todo.add('created', parse_nagios_ts(row['last_state_change']))
            todo['last-modified'] = parse_nagios_ts(row['last_check'])
            todo['status'] = get_todo_status(row)
            todo['organizer'] = make_contact(row)
            todo['priority'] = make_priority(row)
            cal.add_component(todo)
        except Exception:
            log.error("Failed to parse %r", row, exc_info=True)
            return flask.Response(status_code=500,
                                  status='Error parsing Nagios data')

    q = s.hosts.columns('state', 'alias', 'plugin_output', 'last_state_change',
                        'last_check', 'action_url_expanded',
                        'acknowledged').filter('state > 0')
    if q_contact is not None:
        log.debug("Contact: %s" % q_contact)
        q = q.filter('contacts >= %s' % q_contact)
    result = q.call()
    log.debug("hosts query got %d row(s)" % (len(result)))
    for row in result:
        try:
            todo = icalendar.Todo()
            todo['uid'] = make_uid(row)
            todo['summary'] = make_title(row)
            if row['action_url_expanded']:
                todo['url'] = row['action_url_expanded']
            todo.add('created', parse_nagios_ts(row['last_state_change']))
            todo['last-modified'] = parse_nagios_ts(row['last_check'])
            todo['status'] = get_todo_status(row)
            todo['organizer'] = make_contact(row)
            todo['priority'] = make_priority(row)
            cal.add_component(todo)
        except Exception:
            log.error("Failed to parse %r", row, exc_info=True)
            return flask.Response(status_code=500,
                                  status='Error parsing Nagios data')

    log.debug("done, writing response to stream")
    return flask.Response("%s" % display(cal), mimetype='text/calendar')
Ejemplo n.º 3
0
Archivo: info.py Proyecto: smusa/simian
    def _DisplayAppleSusPromoCalendar(self):
        """Display upcoming Apple SUS updates in iCal format."""
        now = datetime.datetime.utcnow().date()
        query = models.AppleSUSProduct.all().order('-apple_mtime')
        dates = {}
        # NOTE(user): the following adds about 700ms onto the request, so we may
        #             want to pre-calculate this in a cron in the future.
        for p in query:
            if p.manual_override:
                continue
            if not common.UNSTABLE in p.tracks:
                continue
            if common.STABLE not in p.tracks:
                p.stable_promote_date = applesus.GetAutoPromoteDate(
                    common.STABLE, p)
            if common.TESTING not in p.tracks:
                p.testing_promote_date = applesus.GetAutoPromoteDate(
                    common.TESTING, p)

            if hasattr(p,
                       'stable_promote_date') and p.stable_promote_date >= now:
                dates.setdefault(p.stable_promote_date, []).append(p)
            if hasattr(
                    p,
                    'testing_promote_date') and p.testing_promote_date >= now:
                dates.setdefault(p.testing_promote_date, []).append(p)

        dtstamp = datetime.datetime.utcnow()
        cal = icalendar.Calendar()

        for d in dates:
            e = icalendar.Event()
            e.add('dtstamp', dtstamp)
            e.add('summary', 'Apple SUS auto-promote')
            e.add('dtstart', d)
            e.add('transp', 'TRANSPARENT')

            products = {common.TESTING: [], common.STABLE: []}
            for p in dates[d]:
                track = None
                if p.stable_promote_date == d:
                    track = common.STABLE
                elif p.testing_promote_date == d:
                    track = common.TESTING

                products[track].append('  %s %s (%s)' %
                                       (p.name, p.version, p.product_id))

            desc = []
            for track in [common.STABLE, common.TESTING]:
                if not products[track]:
                    continue
                desc.append('Auto-promoting to %s:' % track.upper())
                desc.append('\n'.join(products[track]))

            e.add('description', '\n\n'.join(desc))
            e['uid'] = '%s-simian-applesus' % d.strftime('%Y%m%d')
            cal.add_component(e)

        self.response.headers['Content-Type'] = 'text/calendar'
        self.response.out.write(cal.as_string())
Ejemplo n.º 4
0
def ics_from_list(events, tzs, random_uid=False, default_timezone=None):
    """convert an iterable of icalendar.Events to an icalendar.Calendar

    :params events: list of events all with the same uid
    :type events: list(icalendar.cal.Event)
    :param random_uid: assign random uids to all events
    :type random_uid: bool
    :param tzs: collection of timezones
    :type tzs: dict(icalendar.cal.Vtimzone
    """
    calendar = icalendar.Calendar()
    calendar.add('version', '2.0')
    calendar.add('prodid', '-//PIMUTILS.ORG//NONSGML khal / icalendar //EN')

    if random_uid:
        new_uid = generate_random_uid()

    needed_tz, missing_tz = set(), set()
    for sub_event in events:
        sub_event = sanitize(sub_event, default_timezone=default_timezone)
        if random_uid:
            sub_event['UID'] = new_uid
        # icalendar round-trip converts `TZID=a b` to `TZID="a b"` investigate, file bug XXX
        for prop in [
                'DTSTART', 'DTEND', 'DUE', 'EXDATE', 'RDATE', 'RECURRENCE-ID',
                'DUE'
        ]:
            if isinstance(sub_event.get(prop), list):
                items = sub_event.get(prop)
            else:
                items = [sub_event.get(prop)]

            for item in items:
                if not (hasattr(item, 'dt') or hasattr(item, 'dts')):
                    continue
                # if prop is a list, all items have the same parameters
                datetime_ = item.dts[0].dt if hasattr(item, 'dts') else item.dt
                if not hasattr(datetime_, 'tzinfo'):
                    continue
                # check for datetimes' timezones which are not understood by
                # icalendar
                if datetime_.tzinfo is None and 'TZID' in item.params and \
                        item.params['TZID'] not in missing_tz:
                    logger.warning(
                        f"Cannot find timezone `{item.params['TZID']}` in .ics file, "
                        "using default timezone. This can lead to erroneous time shifts"
                    )
                    missing_tz.add(item.params['TZID'])
                elif datetime_.tzinfo and datetime_.tzinfo != pytz.UTC and \
                        datetime_.tzinfo not in needed_tz:
                    needed_tz.add(datetime_.tzinfo)

    for tzid in needed_tz:
        if str(tzid) in tzs:
            calendar.add_component(tzs[str(tzid)])
        else:
            logger.warning(
                f'Cannot find timezone `{tzid}` in .ics file, this could be a bug, '
                'please report this issue at http://github.com/pimutils/khal/.'
            )
    for sub_event in events:
        calendar.add_component(sub_event)
    return calendar.to_ical().decode('utf-8')
Ejemplo n.º 5
0
        if 'Quinton' in line:
            person = 'Quinton'
    elif 'No ' in line:
        my_date = line.split(':')[0]
        if my_date not in pack_lunches:
            pack_lunches[my_date] = [person]
        else:
            pack_lunches[my_date].append(person)

import parsedatetime as pdt
parser = pdt.Calendar()

import icalendar as ical
from datetime import datetime, timedelta

cal = ical.Calendar()
cal.add('prodid', 'foo')
cal.add('version', '2.0')

for day_str in pack_lunches.keys():
    start = parser.parse(day_str)[0]
    dtstart = datetime(start[0], start[1], start[2]).date()
    dtend   = dtstart + timedelta(days = 1)
    trigger = datetime(start[0], start[1], start[2], 7, 0)
    
    summary = 'Pack lunch for %s' % " & ".join(pack_lunches[day_str])
    
    event = ical.Event()
    event.add('summary', summary)
    event.add('dtstart', dtstart)
    event.add('dtend',   dtend)
Ejemplo n.º 6
0
def construct_icalendar(context, events):
    """Returns an icalendar.Calendar object.

    :param context: A content object, which is used for calendar details like
                    Title and Description. Usually a container, collection or
                    the event itself.

    :param events: The list of event objects, which are included in this
                   calendar.
    """
    cal = icalendar.Calendar()
    cal.add('prodid', PRODID)
    cal.add('version', VERSION)

    cal_tz = default_timezone(context)
    if cal_tz:
        cal.add('x-wr-timezone', cal_tz)

    tzmap = {}
    if not hasattr(events, '__getslice__'):  # LazyMap doesn't have __iter__
        events = [events]
    for event in events:
        if ICatalogBrain.providedBy(event) or\
                IContentListingObject.providedBy(event):
            event = event.getObject()
        acc = IEventAccessor(event)
        tz = acc.timezone
        # TODO: the standard wants each recurrence to have a valid timezone
        # definition. sounds decent, but not realizable.
        if not acc.whole_day:  # whole day events are exported as dates without
            # timezone information
            if isinstance(tz, tuple):
                tz_start, tz_end = tz
            else:
                tz_start = tz_end = tz
            tzmap = add_to_zones_map(tzmap, tz_start, acc.start)
            tzmap = add_to_zones_map(tzmap, tz_end, acc.end)
        cal.add_component(IICalendarEventComponent(event).to_ical())

    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'])
            # TODO: add rrule
            # tzi.add('rrule',
            #         {'freq': 'yearly', 'bymonth': 10, 'byday': '-1su'})
            cal_tz.add_component(cal_tz_sub)
        cal.add_component(cal_tz)

    return cal
Ejemplo n.º 7
0
def serialize_category_ical(category, user, event_filter):
    """Export the events in a category to iCal

    :param category: The category to export
    :param user: The user who needs to be able to access the events
    :param event_filter: A SQLalchemy criterion to restrict which
                         events will be returned.  Usually something
                         involving the start/end date of the event.
    """
    own_room_strategy = joinedload('own_room')
    own_room_strategy.load_only('building', 'floor', 'number', 'name')
    own_room_strategy.lazyload('owner')
    own_venue_strategy = joinedload('own_venue').load_only('name')
    query = (Event.query.filter(Event.category_chain_overlaps(
        category.id), ~Event.is_deleted, event_filter).options(
            load_only('id', 'category_id', 'start_dt', 'end_dt', 'title',
                      'description', 'own_venue_name', 'own_room_name',
                      'protection_mode', 'access_key'),
            subqueryload('acl_entries'), joinedload('person_links'),
            own_room_strategy, own_venue_strategy).order_by(Event.start_dt))
    events = [e for e in query if e.can_access(user)]
    cal = ical.Calendar()
    cal.add('version', '2.0')
    cal.add('prodid', '-//CERN//INDICO//EN')

    now = now_utc(False)
    for event in events:
        url = url_for('event.conferenceDisplay',
                      confId=event.id,
                      _external=True)
        location = ('{} ({})'.format(event.room_name, event.venue_name)
                    if event.venue_name and event.room_name else
                    (event.venue_name or event.room_name))
        cal_event = ical.Event()
        cal_event.add('uid', u'indico-event-{}@cern.ch'.format(event.id))
        cal_event.add('dtstamp', now)
        cal_event.add('dtstart', event.start_dt)
        cal_event.add('dtend', event.end_dt)
        cal_event.add('url', url)
        cal_event.add('summary', event.title)
        cal_event.add('location', location)
        description = []
        if event.person_links:
            speakers = [
                u'{} ({})'.format(x.full_name, x.affiliation)
                if x.affiliation else x.full_name for x in event.person_links
            ]
            description.append(u'Speakers: {}'.format(u', '.join(speakers)))

        if event.description:
            desc_text = unicode(
                event.description) or u'<p/>'  # get rid of RichMarkup
            try:
                description.append(
                    unicode(html.fromstring(desc_text).text_content()))
            except ParserError:
                # this happens e.g. if desc_text contains only a html comment
                pass
        description.append(url)
        cal_event.add('description', u'\n'.join(description))
        cal.add_component(cal_event)
    return BytesIO(cal.to_ical())
Ejemplo n.º 8
0
	def generate_calendar(filename, campus, term, subjects):
		'''
		Generates an iCalendar (RFC 5545) file for the timetable events for the specified subjects
		'''
		
		# Retrieve the dates for each of the weeks in the specified term
		currentYear = arrow.now().date().year
		termWeeks = KeyDates.get_terms(currentYear)[term-1]
		
		# Retrieve the timetable events for the specified subjects
		events = Timetable.get_events(campus, term, subjects)
		
		# Create a calendar to hold our generated calendar events
		calendar = icalendar.Calendar()
		calendar.add('prodid', '-//Adam Rehn//CQU Timetable Tools//EN')
		calendar.add('version', '2.0')
		
		# Iterate over the timetable events and generate corresponding calendar events
		total = 0
		for event in events:
			
			# Generate a calendar event for each week
			for week in event['weeks']:
				
				# Determine the numeric index of the weekday for the event
				dayNum = WEEKDAYS.index(event['day'].capitalize())
				
				# Parse the start time and end time for the event and determine the duration
				startTime = arrow.get(event['start'], 'HH:mm')
				endTime = arrow.get(event['end'], 'HH:mm')
				duration = endTime - startTime
				
				# Compute the start date/time for the event
				start = arrow.get(termWeeks[week-1]['start'])
				start = start.shift(weekday=dayNum, hours=startTime.time().hour, minutes=startTime.time().minute)
				
				# Convert the start date/time from the local campus timezone to UTC
				campusTimezone = Campus.get_timezone(campus)
				start.tzinfo = arrow.parser.TzinfoParser.parse(campusTimezone)
				start = start.to('UTC')
				
				# Compute the end date/time for the event
				end = start.shift(seconds=duration.seconds)
				
				# Create the event and add it to the calendar
				calEvent = icalendar.Event()
				calEvent.add('summary', '{} {} (Week {})'.format(event['code'].upper(), event['type'].capitalize(), week))
				calEvent.add('description', '{} {}'.format(event['code'], event['name']))
				calEvent.add('location', event['location'])
				calEvent.add('dtstart', start.datetime)
				calEvent.add('dtend', end.datetime)
				calEvent.add('dtstamp', arrow.utcnow().datetime)
				calendar.add_component(calEvent)
				
				# Keep track of the total number of generated events
				total += 1
		
		# Write the generated calendar events to file
		with open(filename, 'wb') as f:
			f.write(calendar.to_ical())
		
		# Return the number of generated events
		return total
Ejemplo n.º 9
0
def sendAppointment(attendees, dtstart):
    #Login to SMTP server
    s = smtplib.SMTP('smtp.office365.com', 587)
    s.connect("smtp.office365.com", 587)
    s.ehlo()
    s.starttls()
    s.ehlo()
    username, password = prompt_creds()
    try:
        s.login(username, password)
    except smtplib.SMTPAuthenticationError:
        print("Invalid credentials. Please try again.")
        quit()

    # Timezone to use for our dates - change as needed
    tz = pytz.timezone("US/Eastern")
    reminderHours = 1
    description = "wash dishes"
    start = tz.localize(dtstart)
    cal = icalendar.Calendar()
    cal.add('prodid', '-//My calendar application//example.com//')
    cal.add('version', '2.0')
    cal.add('method', "REQUEST")
    event = icalendar.Event()
    for attendee in attendees:
        event.add('attendee', attendee)
    event.add('organizer', username)
    event.add('status', "confirmed")
    event.add('category', "Event")
    event.add('summary', "wash n wait")
    event.add('description', description)
    event.add('location', "SigEp Kitchen")
    event.add('dtstart', start)
    event.add('dtend', start + dt.timedelta(hours=1))
    event.add('dtstamp', tz.localize(dt.datetime.now()))
    event['uid'] = getUniqueId() # Generate some unique ID
    event.add('priority', 5)
    event.add('sequence', 1)
    event.add('created', tz.localize(dt.datetime.now()))     
    alarm = icalendar.Alarm()
    alarm.add("action", "DISPLAY")
    alarm.add('description', "Reminder")
    alarm.add("trigger", dt.timedelta(hours=-reminderHours))
    # The only way to convince Outlook to do it correctly
    alarm.add("TRIGGER;RELATED=START", "-PT{0}H".format(reminderHours))
    event.add_component(alarm)
    cal.add_component(event)
    msg = MIMEMultipart("alternative")
    msg["Subject"] = "Wash 'n' Wait"
    msg["From"] = username
    msg['To'] = " ".join(attendees)
    msg["Content-class"] = "urn:content-classes:calendarmessage"
    msg.attach(MIMEText(description))
    filename = "invite.ics"
    part = MIMEBase('text', "calendar", method="REQUEST", name=filename)
    part.set_payload( cal.to_ical() )
    encode_base64(part)
    part.add_header('Content-Description', filename)
    part.add_header("Content-class", "urn:content-classes:calendarmessage")
    part.add_header("Filename", filename)
    part.add_header("Path", filename)
    msg.attach(part)
    send = input("Are you sure you want to send invitations? (type \"yes\" to send) ")
    
    if send.lower() != "yes":
        quit()
    try:
        s.sendmail(msg["From"], msg["To"], msg.as_string()) 
        # print("would send mail HERE")
    except smtplib.SMTPDataError:
        print("SMTP failed to send the invite. SMTPDataError Thrown. You cannot send a calendar invite to the account you have logged in with.") 
    except Exception as e:
        print("SMTP failed to send the invite:", e)
    else: 
        print("Outlook invitation successfully sent to", msg['To'])
    s.quit()
Ejemplo n.º 10
0
# -*- coding: utf-8 -*-

import json
from uuid import uuid1
from datetime import date, time, datetime, timedelta, timezone
import icalendar

TERMWEEKS = 16

with open("class.json", 'r') as f:
    entry = json.load(f)

calendar = icalendar.Calendar()
calendar['version'] = '2.0'
calendar['prodid'] = '-//THU//Syllabus//CN'

for klass in entry:
    event = icalendar.Event()

    kl_start = 0
    kl_interval = 1
    if(klass['ClassWeeks'] == '全'):
        kl_count = TERMWEEKS
    elif(klass['ClassWeeks'] == '前八'):
        kl_count = TERMWEEKS // 2
    elif(klass['ClassWeeks'] == '后八'):
        kl_count = TERMWEEKS // 2
        kl_start = TERMWEEKS // 2
    elif(klass['ClassWeeks'] == '单'):
        kl_count = TERMWEEKS // 2
        kl_interval = 2
Ejemplo n.º 11
0
def getCalendarIcsFile(path):
    return icalendar.Calendar.from_ical(open(path).read())

def getUrl(event):
    url = str(event)
    url = url.replace("[Event(","",1)
    url = url.replace(")]","",1)
    return url



calendars_settings = settings.get_all_calendar_settings()
sync_settings = settings.get_all_syncs()

for sync in sync_settings:
    input_calendar = icalendar.Calendar()
    output_calendar = getCalendarCalDav(sync.target)
    if sync.source.connectionType == 'ics':
        getCalendarIcs(sync.source)
    elif sync.source.connectionType == 'caldav':
        print('input from caldav not supproted')
        continue
    elif sync.source.connectionType == 'icsfile':
        input_calendar = getCalendarIcsFile(sync.source.url)
    else :
        print('type not known')
        continue

    empty_input_calendar = icalendar.Calendar()
    for key in input_calendar.keys():
        if key == 'METHOD':
Ejemplo n.º 12
0
    def do_GET(self):
        self.send_response(200)  # Sending an '200 OK' response

        self.send_header("Content-type", "text/calendar")  # Setting the header
        self.end_headers()

        # Extract query param
        query_components = parse_qs(urlparse(self.path).query)
        if 'token' in query_components:
            token = query_components['token'][0]
        else:
            token = open('./config/todoist_token', 'r').read()

        if 'default_duration' in query_components:
            default_duration = query_components['default_duration'][0]
        else:
            default_duration = '1h'

        # Regex
        task_name_regex = re.compile(r'\[(.*)\]\(.*\)', re.IGNORECASE)

        # Write iCal
        cal = ical.Calendar()
        cal.add('prodid', '-//Todoist/iCal//NONSGML v1.0//EN')
        cal.add('version', '2.0')
        cal_stamp = datetime.datetime.today()

        # Connect to Todoist API
        api = TodoistAPI(token)
        api.sync()

        # Get project dict
        projects = {project['id']: project['name'] for project in api.projects.all()}

        # Get label dict
        labels = {label['id']: label['name'] for label in api.labels.all()}

        # Get all current tasks with due dates
        tasks = api.items.all()
        for task in tasks:
            if task['due']:
                # Get labels from task
                task_label = [labels[label] for label in task['labels']]

                # Remove links from task name
                task_name = task_name_regex.sub(r'\1', task['content'])

                # Calculate duration from labels
                duration = next((label for label in task_label if re.search(r'\dm|\dh|$', str(label)).group()), default_duration)
                duration_int = int(re.search('\d+', duration).group())
                duration_timedelta = datetime.timedelta(minutes=duration_int) if duration.endswith('m') else datetime.timedelta(hours=duration_int)

                # Get date from due date
                date = task['due']['date'].replace('Z', '')

                # Debug
                print(f'{task_name}\t|\t{duration}\t|\t{date}')

                # Summarize task properties
                event_summary = f'{task_name} [{projects[task["project_id"]]}]'
                event_start = datetime.datetime.strptime(date, '%Y-%m-%dT%H:%M:%S') if 'T' in date else datetime.datetime.strptime(date, '%Y-%m-%d')
                event_start_uid = re.sub(r'\D', '', str(event_start))
                event_end = event_start + duration_timedelta if 'T' in date else event_start + datetime.timedelta(days=1)

                event = ical.Event()
                event.add('summary', event_summary)
                event.add('dtstart', event_start)
                event.add('dtend', event_end)
                event.add('dtstamp', cal_stamp)
                event.add('uid', f'{task["id"]}{event_start_uid}')
                cal.add_component(event)

        # Writing the HTML contents with UTF-8
        print(cal.to_ical())
        self.wfile.write(cal.to_ical())

        return
Ejemplo n.º 13
0
def json_to_ical(address, obj):
    cal = icalendar.Calendar()
    cal.add("prodid", "-//grahame.dev//mxm.dk//EN")
    cal.add("version", "2.0")
    cal.add("name", "Bayswater Bins")
    cal.add("dtstamp", datetime.date.today())
    cal.add("uid", hashlib.md5(address.encode("utf8")).hexdigest())

    # figure out our binday
    lookup = {
        "MONDAY": 0,
        "TUESDAY": 1,
        "WEDNESDAY": 2,
        "THURSDAY": 3,
        "FRIDAY": 4,
        "SATURDAY": 5,
        "SUNDAY": 6,
    }

    def get_refuse_date(typ):
        attr = obj[typ].rsplit(" - ", 1)[-1]
        return datetime.datetime.strptime(attr, "%d/%m/%Y").date()

    # in reality for now this is general waste; baysie devs might change this though
    redbin_dt = get_refuse_date("NextGreenWasteCollection")

    binday = obj["DomesticWasteCollection"]
    start_dt = next_weekday(datetime.date.today(), lookup[binday])
    for week in range(-12, 13):
        bin_dt = start_dt + datetime.timedelta(days=7 * week)

        if (bin_dt - redbin_dt).days % 14 == 0:
            thisbin = "Red"
        else:
            thisbin = "Yellow"
        event_dt = bin_dt + datetime.timedelta(days=-1)
        # NB hacky timezone conversion, 8 hours offset, timezones in ical are a pain
        start = datetime.datetime(event_dt.year,
                                  event_dt.month,
                                  event_dt.day,
                                  12,
                                  0,
                                  0,
                                  tzinfo=pytz.utc)
        end = datetime.datetime(event_dt.year,
                                event_dt.month,
                                event_dt.day,
                                13,
                                0,
                                0,
                                tzinfo=pytz.utc)
        event = icalendar.Event()
        event.add("summary", "Put the bins out: Green and {}".format(thisbin))
        event.add("dtstart", start)
        event.add("dtend", end)
        event.add("dtstamp", start)
        event.add(
            "uid",
            hashlib.md5(
                (address + ":" + str(bin_dt)).encode("utf8")).hexdigest())
        cal.add_component(event)

    return flask.Response(cal.to_ical(), mimetype="text/calendar", status=200)
Ejemplo n.º 14
0
 def create_calendar(self):
     cal = icalendar.Calendar()
     cal["summary"] = "When do the certs expire?"
     cal["prodid"] = "-//Certficate Expiration//.../"
     cal["version"] = "1.0"
     return cal
Ejemplo n.º 15
0
def write_file(file, contents):
    with open(file, "w") as text_file:
        text_file.write(contents)


def ical_line(v):
    if isinstance(v, icalendar.prop.vDDDTypes):
        return v.dt.isoformat()
    else:
        return v


r = requests.get(calUrl)
if r.status_code == 200:
    result = icalendar.Calendar().from_ical(r.text)

    for key, value in result.property_items():

        if key == "END" and value == "VEVENT":
            listening = False
            events.append(event)

        if listening:
            event[key.lower()] = ical_line(value)

        if key == "BEGIN" and value == "VEVENT":
            listening = True
            event = {}

    write_file(output_dir + "basic.json", json.dumps(events, indent=2))
Ejemplo n.º 16
0
Archivo: O2.py Proyecto: ghyun8/O2
    def create_ical(self, name, summary, description, location, count, st_hr,
                    st_mn, et_hr, et_mn, day, start_date):
        """ Create iCal file with given values """
        cal = ical.Calendar()
        """ Add Timezone """
        timezone = ical.Timezone()
        timezone.add('TZID', pytz.timezone('US/Eastern'))

        timezone_standard = ical.TimezoneStandard()
        timezone_standard.add('DTSTART', dt.datetime(1601, 11, 4, 2, 0, 0))
        timezone_standard.add('RRULE', {
            'FREQ': 'YEARLY',
            'BYDAY': '1SU',
            'BYMONTH': '11'
        })
        timezone_standard.add('TZOFFSETFROM', dt.timedelta(hours=-4))
        timezone_standard.add('TZOFFSETTO', dt.timedelta(hours=-5))

        timezone_daylight = ical.TimezoneDaylight()
        timezone_daylight.add('DTSTART', dt.datetime(1601, 3, 11, 2, 0, 0))
        timezone_daylight.add('RRULE', {
            'FREQ': 'YEARLY',
            'BYDAY': '2SU',
            'BYMONTH': '3'
        })
        timezone_daylight.add('TZOFFSETFROM', dt.timedelta(hours=-5))
        timezone_daylight.add('TZOFFSETTO', dt.timedelta(hours=-4))

        timezone.add_component(timezone_standard)
        timezone.add_component(timezone_daylight)

        cal.add_component(timezone)
        """ Add Event"""
        event = ical.Event()
        event.add(
            'DTSTART',
            dt.datetime(2015,
                        9,
                        start_date,
                        st_hr,
                        st_mn,
                        0,
                        tzinfo=pytz.timezone('US/Eastern')))
        event.add(
            'DTEND',
            dt.datetime(2015,
                        9,
                        start_date,
                        et_hr,
                        et_mn,
                        0,
                        tzinfo=pytz.timezone('US/Eastern')))
        event.add('SUMMARY', summary)
        event.add('DESCRIPTION', description)
        event.add('LOCATION', location)
        event.add('RRULE', {'FREQ': 'weekly', 'COUNT': count, 'BYDAY': day})
        cal.add_component(event)

        f = open(name, "wb")
        f.write(cal.to_ical())
        f.close()
Ejemplo n.º 17
0
def compile_calendar():
    # Obtain our stored sequences
    with open('_compile-calendar-sequences.yml', encoding='utf-8') as f:
        seminar_calendar_sequences = yaml.safe_load(f)['sequences']
    # Iterate over all our seminar files
    seminar_paths = _get_seminar_paths()

    # Maintain the sequence field for each seminar
    for seminar_path_current in seminar_paths:
        # Get the hash and sequence from the file, to compare against our stored data
        with open(seminar_path_current, encoding='utf-8') as f:
            hash = hashlib.md5()
            for line in f:
                hash.update(line.strip().encode(encoding='utf-8'))
            seminar_hash_current = hash.hexdigest()
        with open(seminar_path_current, encoding='utf-8') as f:
            seminar_sequence_current = list(
                yaml.safe_load_all(f))[0]['sequence']

        # Regardless of platform we're on, standardize the path we store (e.g., slashes)
        seminar_path_stored = posixpath.join(
            *os.path.normpath(seminar_path_current).split(os.sep))
        if seminar_path_stored not in seminar_calendar_sequences:
            # This is a seminar that is new to our sequence tracking,
            # decrement the initial sequence so it will be hashed and incremented
            seminar_calendar_sequences[seminar_path_stored] = {
                'hash': 'invalid_hash_to_force_update',
                'sequence': seminar_sequence_current - 1
            }

        seminar_hash_stored = seminar_calendar_sequences[seminar_path_stored][
            'hash']
        seminar_sequence_stored = seminar_calendar_sequences[
            seminar_path_stored]['sequence']
        if seminar_hash_current != seminar_hash_stored:
            # # Change detected, we need to bump the sequence
            # seminar_sequence_current = max(seminar_sequence_current, seminar_sequence_stored) + 1
            #
            # # pyyaml does not preserve comments, so we brute force modification of the seminar yml file
            # with open(seminar_path_current, encoding='utf-8') as f:
            #     seminar_contents = f.read()
            # seminar_contents = re.sub(
            #     'sequence: {}'.format('(\d*)'),
            #     'sequence: {}'.format(seminar_sequence_current),
            #     seminar_contents
            # )
            # with open(seminar_path_current, 'w', encoding='utf-8') as f:
            #     f.write(seminar_contents)
            #
            # # That changed the file, so update our hash, then store the updated sequence
            # with open(seminar_path_current, 'rb') as f:
            #     seminar_hash_current = hashlib.md5(f.read()).hexdigest()
            #
            # seminar_calendar_sequences[seminar_path_stored] = {
            #     'hash': seminar_hash_current,
            #     'sequence': seminar_sequence_current
            # }

            if seminar_sequence_current > seminar_sequence_stored:
                seminar_calendar_sequences[seminar_path_stored] = {
                    'hash': seminar_hash_current,
                    'sequence': seminar_sequence_current
                }

    # Store our updated sequences
    data = {'sequences': seminar_calendar_sequences}
    with open('_compile-calendar-sequences.yml', 'w', encoding='utf-8') as f:
        yaml.dump(data, stream=f, default_flow_style=False)

    # Now generate the ics file from our seminars and their sequences
    ics = icalendar.Calendar()
    ics.add('PRODID', '-//DUB//DUB Calendar')
    ics.add('VERSION', '2.0')
    ics.add('CALSCALE', 'GREGORIAN')
    ics.add('METHOD', 'PUBLISH')
    ics.add('X-WR-CALNAME', 'DUB Calendar')
    ics.add('X-WR-TIMEZONE', 'America/Los_Angeles')
    ics.add('X-WR-CALDESC', 'Calendar of DUB seminars.')

    for seminar_path_current in seminar_paths:
        # Parse the seminar
        with open(seminar_path_current, encoding='utf-8') as f:
            seminar_contents = list(yaml.safe_load_all(f))[0]

        # Add seminar as calendar event
        ics_event = icalendar.Event()

        # Give it a UID
        ics_event.add('UID', seminar_contents['date'] + '@dub.washington.edu')

        # Give it DTSTART and DTEND
        timezone = pytz.timezone('America/Los_Angeles')
        seminar_start_time = timezone.localize(
            datetime.combine(
                datetime.strptime(seminar_contents['date'], '%Y-%m-%d').date(),
                datetime.strptime(seminar_contents['time'],
                                  '%I:%M %p').time()))
        seminar_end_time = timezone.localize(
            datetime.combine(
                datetime.strptime(seminar_contents['date'], '%Y-%m-%d').date(),
                datetime.strptime(seminar_contents['time_end'],
                                  '%I:%M %p').time()))
        ics_event.add('DTSTART', seminar_start_time)
        ics_event.add('DTEND', seminar_end_time)

        # Generate SUMMARY from applicable components
        if seminar_contents.get('no_seminar', False):
            # Flagged as not having a seminar

            # Title should indicate why there's no seminar
            seminar_summary = seminar_contents['title']
        else:
            # We have a seminar, but its data may not yet be complete
            seminar_summary = 'DUB Seminar'

            if not seminar_contents.get('tbd_speakers', False):
                # We have speakers

                # If they all have the same affiliation, we'll collapse it, so let's check
                speaker_affiliations = [
                    speaker_current['affiliation']
                    if not speaker_current.get('affiliation_none', False) else
                    'affiliation_none'
                    for speaker_current in seminar_contents['speakers']
                ]
                if len(set(speaker_affiliations)) == 1:
                    # Everybody has the same affiliation
                    # But it's still possible that affiliation is affiliation_none
                    if not seminar_contents['speakers'][0].get(
                            'affiliation_none', False):
                        # We have a legit affiliation
                        seminar_summary = '{} - {} ({})'.format(
                            seminar_summary, ', '.join([
                                ' '.join(speaker_current['name'][1:] +
                                         [speaker_current['name'][0]]) for
                                speaker_current in seminar_contents['speakers']
                            ]), seminar_contents['speakers'][0]['affiliation'])
                    else:
                        # Everybody has no affiliation
                        seminar_summary = '{} - {}'.format(
                            seminar_summary, ', '.join([
                                ' '.join(speaker_current['name'][1:] +
                                         [speaker_current['name'][0]]) for
                                speaker_current in seminar_contents['speakers']
                            ]))
                else:
                    # Distinct affiliations
                    seminar_summary = '{} - {}'.format(
                        seminar_summary, ', '.join([
                            '{}{}'.format(
                                ' '.join(speaker_current['name'][1:] +
                                         [speaker_current['name'][0]]),
                                '({})'.format(speaker_current['affiliation'])
                                if not speaker_current.get(
                                    'affiliation_none', False) else '')
                            for speaker_current in seminar_contents['speakers']
                        ]))

            if not seminar_contents.get('tbd_title', False):
                # We have a title
                seminar_summary = '{} - "{}"'.format(seminar_summary,
                                                     seminar_contents['title'])

        ics_event.add('SUMMARY', seminar_summary)

        # Add the location unless it has an override
        if not seminar_contents.get('no_seminar', False):
            if seminar_contents.get('location_override_calendar', False):
                ics_event.add('LOCATION',
                              seminar_contents['location_override_calendar'])
            else:
                ics_event.add('LOCATION', seminar_contents['location'])

        # This description generation is still a bit sketchy, should decide what we want
        #
        # Generate description string from applicable components
        if not seminar_contents.get('no_seminar', False):
            description_string = ''
            if 'text_override_seminar_page' in seminar_contents:
                description_string = seminar_contents[
                    'text_override_seminar_page']
            else:
                if 'tbd_bio' not in seminar_contents:
                    if 'tbd_abstract' not in seminar_contents:
                        description_string = seminar_contents[
                            'abstract'] + '\r\n' + seminar_contents['bio']
                    else:
                        description_string = seminar_contents['bio']
                elif 'tbd_abstract' not in seminar_contents:
                    description_string = seminar_contents['abstract']

            # This was crashing, and I couldn't easily determine why, so I've temporarily removed it
            #
            # # Parse description as markdown
            # class SensibleParagraphs(markdown.extensions.Extension):
            #     def extendMarkdown(self, md, md_globals):
            #         br_tag = markdown.inlinepatterns.SubstituteTagPattern(r'\n', None)
            #         md.inlinePatterns.add('nl', br_tag, '_end')
            #
            # ics_event.add('DESCRIPTION', markdown.markdown(description_string, extensions=[SensibleParagraphs()]))

        # That's our complete event
        ics.add_component(ics_event)

    # Store the ics file output
    with open('calendar.ics', 'wb') as f:
        f.write(ics.to_ical())
Ejemplo n.º 18
0
    def generateIcal(self):
        ical = ic.Calendar()

        for dataId, classData in enumerate(self.timetable):
            loopIsLunch = 2 if (classData["classTimeDuration"] > 1) & (
                (classData["classTime"] <= self.lunchBreakAfter) &
                ((classData["classTime"] + classData["classTimeDuration"] -
                  1) > self.lunchBreakAfter)) else 1
            for loopIdLunch in range(loopIsLunch):
                # Event Init
                event = ic.Event()
                event.add(
                    'uid',
                    urllib.parse.quote(
                        "mu-timetable-" + self.univName + "_" +
                        str(self.termStart[classData["classTerm"] -
                                           1].strftime("%Y%m%dT%H%M%S")) +
                        "_" + str(dataId) + "_" + str(loopIdLunch)) +
                    '@dev.386.jp')
                event.add('dtstamp', dt.datetime.now())

                # Event Summary (Title)
                event.add(
                    'summary', '[' + classData["classNumber"] + '] ' +
                    classData["className"])

                # Event Location
                locationText = "Online"
                if classData["onlineURL"] == None:
                    locationText = self.univName + " " + classData["classPlace"]
                event.add('location', locationText)

                # Event Description
                descriptionText = 'Teacher: ' + classData["classTeacher"]
                if classData["onlineURL"] != None:
                    descriptionText += "\nLink for Online Conference: " + classData[
                        "onlineURL"]
                event.add('description', descriptionText)

                # Event Time Start
                ## Date
                week = [
                    "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
                    "Saturday", "Sunday"
                ]
                termStartWeekday = self.termStart[classData["classTerm"] -
                                                  1].weekday()
                classStartWeekday = [
                    wid for wid, w in enumerate(week)
                    if w == classData["classWeekday"]
                ][0]
                dateDelta = classStartWeekday - termStartWeekday
                if termStartWeekday > classStartWeekday:
                    dateDelta = len(
                        week) - termStartWeekday + classStartWeekday
                classDateStart = self.termStart[classData["classTerm"] -
                                                1] + dt.timedelta(
                                                    days=dateDelta)

                ## Time
                classStartTime = self.classTime[classData["classTime"] -
                                                1]["start"]
                classEndTime = self.classTime[classData["classTime"] +
                                              classData["classTimeDuration"] -
                                              2]["end"]
                if loopIsLunch == 2:
                    if loopIdLunch == 0:
                        classEndTime = self.classTime[self.lunchBreakAfter -
                                                      1]["end"]
                    if loopIdLunch == 1:
                        classStartTime = self.classTime[
                            self.lunchBreakAfter]["start"]

                event.add('dtstart', classDateStart + classStartTime)
                event.add('dtend', classDateStart + classEndTime)
                event.add(
                    'rrule', {
                        'freq':
                        'weekly',
                        'until':
                        self.termStart[classData["classTerm"] +
                                       classData["classTermDuration"] - 1] -
                        dt.timedelta(days=1)
                    })
                for skipDate in [
                        d for d in self.skipDates
                        if d.weekday() == classDateStart.weekday()
                ]:
                    event.add('exdate', skipDate + classStartTime)
                ical.add_component(event)

        ical.add('version', '2.0')
        ical.add('prodid', '-//386JP//MuSchoolTimetable//JP')
        return ical
Ejemplo n.º 19
0
import datetime
import pytz
import urllib2

CALENDARS = {
    '[CF] ':
    'https://www.google.com/calendar/ical/br1o1n70iqgrrbc875vcehacjg%40group.calendar.google.com/public/basic.ics',
    '[TC] ':
    'https://www.google.com/calendar/ical/appirio.com_bhga3musitat85mhdrng9035jg%40group.calendar.google.com/public/basic.ics',
    '[GCJ] ':
    'https://www.google.com/calendar/ical/google.com_jqv7qt9iifsaj94cuknckrabd8%40group.calendar.google.com/public/basic.ics',
    '':
    'https://www.google.com/calendar/ical/iqe3kkmf7vltagnjs7fd2sv4a8%40group.calendar.google.com/public/basic.ics'
}

merged = icalendar.Calendar()
merged.add('PRODID', '-//Algospot Calendar//algospot.com//EN')
merged.add('METHOD', 'PUBLISH')

thresh = datetime.date.today() + datetime.timedelta(days=-30)


def recent_enough(c):
    if 'DTSTART' not in c: return True
    dt_start = c['DTSTART'].dt
    if isinstance(dt_start, datetime.datetime):
        dt_start = dt_start.date()
    return dt_start >= thresh


for prefix, url in CALENDARS.items():
Ejemplo n.º 20
0
def siakng_ics():
    if request.method == 'GET':
        return render_template('index.html')

    try:
        raw = request.form.get('tabel-jadwal')
        raw = raw[raw.index(prefix):raw.index(suffix) + len(suffix)]
        raw = raw.replace('<br>', delimiter)
        rows = pandas.read_html(raw)[0].to_dict('records')

        cal = icalendar.Calendar()
        cal.add('prodid', 'PRODID:-//faisalhanif.id//NONSGML SIAKNG.ics//ID')
        cal.add('version', '2.0')

        tzc = icalendar.Timezone()
        tzc.add('tzid', 'Asia/Jakarta')
        tzc.add('x-lic-location', 'Asia/Jakarta')

        tzs = icalendar.TimezoneStandard()
        tzs.add('tzname', 'WIB')
        tzs.add('dtstart', datetime.datetime(1970, 1, 1, 0, 0, 0))
        tzs.add('TZOFFSETFROM', datetime.timedelta(hours=7))
        tzs.add('TZOFFSETTO', datetime.timedelta(hours=7))

        tzc.add_component(tzs)
        cal.add_component(tzc)
        tz = pytz.timezone('Asia/Jakarta')

        for row in rows:
            row = list(row.values())
            periode_raw = row[4]
            kelas_raw = row[2]
            jadwal_raw = row[5]
            ruangan_raw = row[6]

            periodes = periode_raw.split(delimiter)
            kelas = kelas_raw[:kelas_raw.index(delimiter)]
            jadwals = jadwal_raw.split(delimiter)
            ruangans = ruangan_raw.split(delimiter)

            assert len(periodes) == len(jadwals) == len(ruangans)

            for periode, jadwal, ruangan in zip(periodes, jadwals, ruangans):
                event = icalendar.Event()

                jadwal_by, jadwal = jadwal.split(', ')
                periode_op, periode_ed = periode.split(' - ')

                op, ed = [
                    datetime.datetime.strptime(periode_op + ' ' + jam,
                                               '%d/%m/%Y %H.%M')
                    for jam in jadwal.split('-')
                ]
                op = onDay(op, days_i[jadwal_by])
                ed = onDay(ed, days_i[jadwal_by])
                true_ed = datetime.datetime.strptime(
                    periode_ed + ' ' + '23.59.59', '%d/%m/%Y %H.%M.%S')

                event.add('dtstart', tz.localize(op))
                event.add('dtend', tz.localize(ed))
                event.add('dtstamp', tz.localize(datetime.datetime.today()))
                event.add('rrule', {'freq': 'weekly', 'until': true_ed})
                event.add('summary', kelas)
                event.add('location', ruangan)

                status = request.form.get('status')
                event.add('status', status_s[status])

                event_hash = hashlib.sha1(
                    (kelas + str(op)).encode()).hexdigest()
                event.add('uid', uuid.uuid5(uuid.NAMESPACE_URL, event_hash))

                cal.add_component(event)

        return Response(
            cal.to_ical(),
            mimetype='text/calendar',
            headers={'Content-disposition': 'attachment; filename=SIAKNG.ics'})

    except:
        return Response(
            'ERROR',
            mimetype='text/plain',
            headers={'Content-disposition': 'attachment; filename=ERROR'})
Ejemplo n.º 21
0
 def setUp(self):
     self._icalendar = icalendar.Calendar()
     self._icalendar['prodid'] = '-//My calendar product//mxm.dk//'
     self._icalendar['version'] = '2.0'
     self._calendar = None
Ejemplo n.º 22
0
 def __init__(self, icalfilename):
     """open/init icalfilename"""
     super(NotesToIcalConverter, self).__init__()
     self.cal = icalendar.Calendar()
     self.filedescriptor = open(icalfilename, 'wb')
Ejemplo n.º 23
0
    def test_create_to_ical(self):
        cal = icalendar.Calendar()

        cal.add('prodid', u"-//Plone.org//NONSGML plone.app.event//EN")
        cal.add('version', u"2.0")
        cal.add('x-wr-calname', u"test create calendar")
        cal.add('x-wr-caldesc', u"icalendar tests")
        cal.add('x-wr-relcalid', u"12345")
        cal.add('x-wr-timezone', u"Europe/Vienna")

        tzc = icalendar.Timezone()
        tzc.add('tzid', 'Europe/Vienna')
        tzc.add('x-lic-location', 'Europe/Vienna')

        tzs = icalendar.TimezoneStandard()
        tzs.add('tzname', 'CET')
        tzs.add('dtstart', datetime.datetime(1970, 10, 25, 3, 0, 0))
        tzs.add('rrule', {'freq': 'yearly', 'bymonth': 10, 'byday': '-1su'})
        tzs.add('TZOFFSETFROM', datetime.timedelta(hours=2))
        tzs.add('TZOFFSETTO', datetime.timedelta(hours=1))

        tzd = icalendar.TimezoneDaylight()
        tzd.add('tzname', 'CEST')
        tzd.add('dtstart', datetime.datetime(1970, 3, 29, 2, 0, 0))
        tzs.add('rrule', {'freq': 'yearly', 'bymonth': 3, 'byday': '-1su'})
        tzd.add('TZOFFSETFROM', datetime.timedelta(hours=1))
        tzd.add('TZOFFSETTO', datetime.timedelta(hours=2))

        tzc.add_component(tzs)
        tzc.add_component(tzd)
        cal.add_component(tzc)

        event = icalendar.Event()
        tz = pytz.timezone("Europe/Vienna")
        event.add(
            'dtstart',
            tz.localize(datetime.datetime(2012, 2, 13, 10, 00, 00)))
        event.add(
            'dtend',
            tz.localize(datetime.datetime(2012, 2, 17, 18, 00, 00)))
        event.add(
            'dtstamp',
            tz.localize(datetime.datetime(2010, 10, 10, 10, 10, 10)))
        event.add(
            'created',
            tz.localize(datetime.datetime(2010, 10, 10, 10, 10, 10)))
        event.add('uid', u'123456')
        event.add(
            'last-modified',
            tz.localize(datetime.datetime(2010, 10, 10, 10, 10, 10)))
        event.add('summary', u'artsprint 2012')
        # event.add('rrule', u'FREQ=YEARLY;INTERVAL=1;COUNT=10')
        event.add('description', u'sprinting at the artsprint')
        event.add('location', u'aka bild, wien')
        event.add('categories', u'first subject')
        event.add('categories', u'second subject')
        event.add('attendee', u'häns')
        event.add('attendee', u'franz')
        event.add('attendee', u'sepp')
        event.add('contact', u'Max Mustermann, 1010 Wien')
        event.add('url', u'http://plone.org')
        cal.add_component(event)

        test_out = b'|'.join(cal.to_ical().splitlines())
        test_out = test_out.decode('utf-8')

        vtimezone_lines = "BEGIN:VTIMEZONE|TZID:Europe/Vienna|X-LIC-LOCATION:"
        "Europe/Vienna|BEGIN:STANDARD|DTSTART;VALUE=DATE-TIME:19701025T03"
        "0000|RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10|RRULE:FREQ=YEARLY;B"
        "YDAY=-1SU;BYMONTH=3|TZNAME:CET|TZOFFSETFROM:+0200|TZOFFSETTO:+01"
        "00|END:STANDARD|BEGIN:DAYLIGHT|DTSTART;VALUE=DATE-TIME:19700329T"
        "020000|TZNAME:CEST|TZOFFSETFROM:+0100|TZOFFSETTO:+0200|END:DAYLI"
        "GHT|END:VTIMEZONE"
        self.assertTrue(vtimezone_lines in test_out)

        test_str = "DTSTART;TZID=Europe/Vienna;VALUE=DATE-TIME:20120213T100000"
        self.assertTrue(test_str in test_out)
        self.assertTrue("ATTENDEE:sepp" in test_out)

        # ical standard expects DTSTAMP and CREATED in UTC
        self.assertTrue("DTSTAMP;VALUE=DATE-TIME:20101010T081010Z" in test_out)
        self.assertTrue("CREATED;VALUE=DATE-TIME:20101010T081010Z" in test_out)
Ejemplo n.º 24
0
 def test_create_to_ical(self):
     cal = icalendar.Calendar()
     cal.add('X-SOMETIME', datetime.time(17, 20, 10))
     self.assertTrue(
         b'X-SOMETIME;VALUE=TIME:172010' in cal.to_ical().splitlines())
Ejemplo n.º 25
0
def serialize_categories_ical(category_ids, user, event_filter=True, event_filter_fn=None, update_query=None):
    """Export the events in a category to iCal

    :param category_ids: Category IDs to export
    :param user: The user who needs to be able to access the events
    :param event_filter: A SQLalchemy criterion to restrict which
                         events will be returned.  Usually something
                         involving the start/end date of the event.
    :param event_filter_fn: A callable that determines which events to include (after querying)
    :param update_query: A callable that can update the query used to retrieve the events.
                         Must return the updated query object.
    """
    own_room_strategy = joinedload('own_room')
    own_room_strategy.load_only('building', 'floor', 'number', 'name')
    own_room_strategy.lazyload('owner')
    own_venue_strategy = joinedload('own_venue').load_only('name')
    query = (Event.query
             .filter(Event.category_chain_overlaps(category_ids),
                     ~Event.is_deleted,
                     event_filter)
             .options(load_only('id', 'category_id', 'start_dt', 'end_dt', 'title', 'description', 'own_venue_name',
                                'own_room_name', 'protection_mode', 'access_key'),
                      subqueryload('acl_entries'),
                      joinedload('person_links'),
                      own_room_strategy,
                      own_venue_strategy)
             .order_by(Event.start_dt))
    if update_query:
        query = update_query(query)
    it = iter(query)
    if event_filter_fn:
        it = ifilter(event_filter_fn, it)
    events = list(it)
    # make sure the parent categories are in sqlalchemy's identity cache.
    # this avoids query spam from `protection_parent` lookups
    _parent_categs = (Category._get_chain_query(Category.id.in_({e.category_id for e in events}))
                      .options(load_only('id', 'parent_id', 'protection_mode'),
                               joinedload('acl_entries'))
                      .all())
    cal = ical.Calendar()
    cal.add('version', '2.0')
    cal.add('prodid', '-//CERN//INDICO//EN')

    now = now_utc(False)
    for event in events:
        if not event.can_access(user):
            continue
        url = url_for('event.conferenceDisplay', confId=event.id, _external=True)
        location = ('{} ({})'.format(event.room_name, event.venue_name)
                    if event.venue_name and event.room_name
                    else (event.venue_name or event.room_name))
        cal_event = ical.Event()
        cal_event.add('uid', u'indico-event-{}@cern.ch'.format(event.id))
        cal_event.add('dtstamp', now)
        cal_event.add('dtstart', event.start_dt)
        cal_event.add('dtend', event.end_dt)
        cal_event.add('url', url)
        cal_event.add('summary', event.title)
        cal_event.add('location', location)
        description = []
        if event.person_links:
            speakers = [u'{} ({})'.format(x.full_name, x.affiliation) if x.affiliation else x.full_name
                        for x in event.person_links]
            description.append(u'Speakers: {}'.format(u', '.join(speakers)))

        if event.description:
            desc_text = unicode(event.description) or u'<p/>'  # get rid of RichMarkup
            try:
                description.append(unicode(html.fromstring(desc_text).text_content()))
            except ParserError:
                # this happens e.g. if desc_text contains only a html comment
                pass
        description.append(url)
        cal_event.add('description', u'\n'.join(description))
        cal.add_component(cal_event)
    return BytesIO(cal.to_ical())
Ejemplo n.º 26
0
def render_schedule_ical_feed(profile_user_secret_id):
    profile_user = (m.User.objects(secret_id=profile_user_secret_id.upper())
                        .first())

    if profile_user is None:
        logging.error("No profile user with secret id '%s'" %
            profile_user_secret_id)
        return ''

    exams = profile_user.get_current_term_exams()
    schedule_item_dict_list = profile_user.get_schedule_item_dicts(
                                    exam_objs=exams)

    course_ids = set([sid['course_id'] for sid in schedule_item_dict_list])

    limited_course_list = (m.Course.objects(id__in=course_ids)
        .only('id', 'department_id', 'number', 'name'))

    humanized_course_id = {}

    for limited_course in limited_course_list:
        humanized_course_id[limited_course.id] = (
            limited_course.department_id.upper() + ' ' +
            limited_course.number
        )

    course_name_map = {c['id']: c['name'] for c in limited_course_list}

    cal = icalendar.Calendar()
    cal.add('x-wr-calname', 'uwflow.com schedule')
    cal.add('x-wr-caldesc', 'Schedule exported from https://uwflow.com')

    for schedule_item_dict in schedule_item_dict_list:
        event = icalendar.Event()
        course_id = schedule_item_dict['course_id']
        summary_fmt = ('%(course_id)s - %(section_type)s %(section_num)s'
                ' - %(course_name)s')
        summary = summary_fmt % {
            'course_id': humanized_course_id.get(course_id, course_id),
            'section_type': schedule_item_dict['section_type'],
            'section_num': schedule_item_dict['section_num'],
            'course_name': course_name_map.get(course_id, ''),
        }
        event.add('summary', summary)

        # We need to make sure we explicitly specify a timezone in the
        # datetimes we emit to the ICS file, otherwise, some calendars (eg.
        # Calendar.app) will interpret the time as local time (instead of UTC,
        # which is what we store our datetime as).
        to_utc = pytz.utc.localize

        # TODO(jlfwong): DTSTAMP is actually supposed to be when the event was
        # created, not when it is. Not sure what to put here
        event.add('dtstamp', to_utc(schedule_item_dict['start_date']))
        event.add('dtstart', to_utc(schedule_item_dict['start_date']))
        event.add('dtend', to_utc(schedule_item_dict['end_date']))

        # TODO(david): There should be a method on a ScheduleItem to return
        #     a location string, except we have this stupid pattern of
        #     returning dicts from functions instead of objects.
        event.add('location', '%s %s' % (schedule_item_dict['building'],
                schedule_item_dict['room']))

        cal.add_component(event)

    response = flask.make_response(cal.to_ical())
    response.headers["Content-type"] = "text/calendar"
    return response
Ejemplo n.º 27
0
                "day" : get_next_weekday(now, link[0].string)
            })

    return timetables


#
# 
#


# timestamp to give to the generated ICS file
scriptruntime = datetime.datetime.now()

# create the new icalendar
cal = icalendar.Calendar()
cal.add("prodid", "-//Swimming Timetable//" + WEBSITENAME + "//")
cal.add("version", "2.0")

# get the list of timetables to download and parse - one for each day
timetables = get_days(WEBSITEURL)

# for each timetable...
for timetable in timetables:
    # download and parse the timetable and get the session info
    for timetableinfo in get_schedule(timetable['url'], timetable['day']):
        # create an event to represent the session 
        event = icalendar.Event()
        event.add("summary", timetableinfo['type'])
        event.add("dtstart", timetableinfo['start'])
        event.add("dtend", timetableinfo['end'])
Ejemplo n.º 28
0
def send_notify_email(body, start_time, title, attendees, event_uid, patching_duartion_in_min):
    """Function for send Outlook-notifications and save notification to disk"""
    subject = 'Linux Monthly Patching {month} | RFC {rfc_number} | {project}'.format(
        month=datetime.datetime.now().strftime("%B %Y"), rfc_number=rfc_number, project=title)
    start_time_utc=return_utc(start_time)
    
    # create calendar
    cal = icalendar.Calendar()
    cal.add('prodid', '-//My calendar application//example.com//')
    cal.add('version', '2.0')
    cal.add('method', 'REQUEST')
    
    # create event
    event = icalendar.Event()
    event.add('summary', subject)
    event.add('dtstart', datetime.datetime.strptime(start_time_utc, "%d-%m-%Y %H:%M"))
    event.add('dtend', datetime.datetime.strptime(start_time_utc, "%d-%m-%Y %H:%M")+datetime.timedelta(minutes=patching_duartion_in_min))
    event.add('dtstamp', datetime.datetime.now().utcnow())
    event['uid'] = event_uid
    event.add('TZOFFSETFROM', datetime.timedelta(hours=3))
    event.add('TZOFFSETTO', datetime.timedelta(hours=3))
    event.add('TZID', 'Russian Standard Time')
    event.add('priority', 5)
    event.add('organizer', settings['organizer'])
    event.add('status', "confirmed")
    event.add('category', "Event")
    event.add('sequence', 1)
    event.add('X-MICROSOFT-DISALLOW-COUNTER', "TRUE")
    event.add('X-MICROSOFT-CDO-BUSYSTATUS', 'FREE')
    for current_attendee in attendees.split(","):
        event.add('attendee', current_attendee)
        
    # create alarm
    alarm = icalendar.Alarm()
    alarm.add("action", "DISPLAY")
    alarm.add('description', "Reminder")
    alarm.add("TRIGGER;RELATED=START", "-PT15M")
    alarm.add('X-MICROSOFT-CDO-BUSYSTATUS', 'FREE')
    event.add_component(alarm)
    cal.add_component(event)

    filename = "invite.ics"
    msg = MIMEMultipart("mixed")
    msg["Subject"] = subject
    msg["From"] = settings['e_mail_from']
    msg["To"] = attendees

    msg_for_cancel = copy.deepcopy(msg)
    cursor_hashes_db.execute('INSERT INTO "HASHES" (HASH,EMAILS) VALUES (?,?)', (str(event_uid), attendees))
    connect_hashes_db.commit()
    msg_a = MIMEMultipart('alternative')
    msg.attach(msg_a)
    part_calendar = MIMEMultipart('text', "calendar", method="REQUEST", name=filename)
    part_calendar.set_type('text/calendar; charset=UTF-8; method=REQUEST; component = VEVENT')
    part_calendar.add_header('Content-Type', 'text/calendar')
    part_calendar.add_header('charset', 'UTF-8')
    part_calendar.add_header('component', 'VEVENT')
    part_calendar.add_header('method', 'REQUEST')
    part_calendar.add_header('Content-Description', filename)
    part_calendar.add_header('Content-ID', 'calendar_message')
    part_calendar.add_header("Content-class", "urn:content-classes:appointment")
    part_calendar.add_header("Filename", filename)
    part_calendar.add_header("Path", filename)

    part_calendar_before_encode=copy.deepcopy(part_calendar)
    part_calendar.set_payload(cal.to_ical())

    encode_base64(part_calendar)
    msg_a.attach(MIMEText(body, 'html'))
    msg_a.attach(part_calendar)
    recept_list=attendees.split(",")

    try:
        s = smtplib.SMTP(settings['smtp_server'])
        s.sendmail(msg["From"], recept_list, msg.as_string())
        s.quit()
        print("e-mail with '{title}' title has been sent successfully!".format(title=title))
    except Exception as e:
        termcolor.cprint("Error during sending an-email, second try...", color="white", on_color="on_red")
        try:
            s = smtplib.SMTP(settings['smtp_server'])
            print(recept_list)
            s.sendmail(msg["From"], recept_list, msg.as_string())
            s.quit()
            print("e-mail with '{title}' title has been sent successfully!".format(title=title))
        except Exception as e:
            termcolor.cprint("Can not send outlook-notofocation for this {prj} project to {start_date}".format(start_date=start_time, prj=title), color="white", on_color="on_red")
            print("Exception: {e}".format(e=str(e)))

    cal.update({'method' : 'CANCEL'})
    event.update({'summary' : "[CANCELLED] " + subject})
    event.update({'status': "cancelled"})
    
    msg_for_cancel.replace_header('Subject', "[CANCELLED] "  + subject)
    msg_a_for_cancel = MIMEMultipart('alternative')
    msg_for_cancel.attach(msg_a_for_cancel)
    msg_a_for_cancel.attach(MIMEText(body.replace("please, perform this patching", "<font size=12 color='red'>DO NOT DO IT</font>"), 'html'))
    
    part_calendar_before_encode.replace_header('Content-Type', 'text/calendar; charset="UTF-8"; method="CANCEL"; component = "VEVENT"; name="invite.ics"; boundary="calendar"')
    part_calendar_before_encode.replace_header('method', 'CANCEL')
    part_calendar_before_encode.set_payload(cal.to_ical())
    encode_base64(part_calendar_before_encode)
    msg_a_for_cancel.attach(part_calendar_before_encode)
    save_notification_to_disk=open("./archive/" + event_uid + ".msg", 'wb')
    save_notification_to_disk.write(msg_for_cancel.as_bytes())
    save_notification_to_disk.close()
    input("Enter any symbol to proceed...")
Ejemplo n.º 29
0
    def render(self, request):
        cal = icalendar.Calendar()
        cal.add('version', '2.0')
        cal.add('prodid', 'openstates')

        for obj in self.construct():
            if not isinstance(obj, dict):
                continue

            if obj.get('_type') != 'event':
                # We can only serialize events
                continue

            event = icalendar.Event()

            if obj.get('all_day', False):
                event.add('dtstart', obj['when'].date())
                event['X-FUNAMBOL-ALLDAY'] = 1
                event['X-MICROSOFT-CDO-ALLDAYEVENT'] = 1
            else:
                event['dtstart'] = _vDatetime(obj['when'])

                end = obj.get('end')
                if not end:
                    end = obj['when'] + datetime.timedelta(hours=1)
                event['dtend'] = _vDatetime(end)

            if obj['type'] == 'committee:meeting':
                part = obj['participants'][0]
                comm = part['participant']

                chamber = part.get('chamber')
                if chamber:
                    comm = "%s %s" % (chamber_name(obj['state'],
                                                   chamber), comm)

                summary = "%s Committee Meeting" % comm
            elif obj['type'] == 'bill:action':
                summary = obj['description']
            else:
                continue

            event.add('summary', summary)
            event.add('location', obj.get('location', 'Unknown'))
            event['uid'] = obj['_id']

            status = obj.get('status')
            if status:
                event.add('status', status.upper())

            notes = obj.get('notes')
            if notes:
                event.add('description', notes)

            link = obj.get('link')
            if link:
                event.add('attach', link)

            for participant in obj['participants']:
                addr = icalendar.vCalAddress('MAILTO:[email protected]')

                chamber = participant.get('chamber')
                if chamber:
                    cn = chamber_name(obj['state'], chamber) + " "
                else:
                    cn = ""

                cn += participant['participant']

                if participant['type'] == 'committee':
                    cn += ' Committee'

                addr.params['cn'] = icalendar.vText(cn)
                #addr.params['ROLE'] = icalendar.vText('COMMITTEE')
                event.add('attendee', addr, encode=0)
                event['organizer'] = addr

            cal.add_component(event)

        return cal.as_string()
Ejemplo n.º 30
0
def send_attendee_email(start, finish, name, booking_type, notes, uid,
                        mail_address):
    cal = icalendar.Calendar()
    cal.add('prodid', '-//pyappointment//pyappointment//')
    cal.add('version', '2.0')
    cal.add('method', "REQUEST")

    tz = start.tzinfo
    mail_recip = '%s <%s>' % (name, mail_address)

    event = icalendar.Event()
    event.add('attendee', 'MAILTO:%s' % mail_address)
    event.add('organizer', 'MAILTO:%s' % ORGANIZER_EMAIL)
    event.add('status', "confirmed")
    event.add('category', "Event")
    event.add('summary', BOOKING_TYPES[booking_type]['description'])
    event.add('description', 'Additional notes: ' + notes)
    event.add('location', BOOKING_TYPES[booking_type]['location'])
    event.add('dtstart', start)
    event.add('dtend', finish)
    event.add('dtstamp', tz.localize(dt.datetime.now()))
    event.add('created', tz.localize(dt.datetime.now()))
    event.add('priority', 5)
    event.add('sequence', 1)

    event['uid'] = uid  # Generate some unique ID

    cal.add_component(event)

    template_params = {
        'date': start,
        'booking_info': BOOKING_TYPES[booking_type],
        'recipient': name,
        'organizer': ORGANIZER_GREETING
    }

    email_msg = EmailMultiAlternatives(
        'Booking confirmation',
        render_to_string('emails/to-attendee.txt', template_params),
        EMAIL_ADDRESS,
        [mail_recip],
        headers={'Content-class': "urn:content-classes:calendarmessage"},
    )

    email_msg.attach_alternative(
        render_to_string('emails/to-attendee.html', template_params),
        "text/html")

    filename = "invite.ics"
    part = email.mime.base.MIMEBase('text',
                                    "calendar",
                                    method="REQUEST",
                                    name=filename)
    part.set_payload(cal.to_ical())
    email.encoders.encode_base64(part)
    part.add_header('Content-Description', filename)
    part.add_header("Content-class", "urn:content-classes:calendarmessage")
    part.add_header("Filename", filename)
    part.add_header("Path", filename)
    email_msg.attach(part)

    email_msg.send()