Example #1
0
    def get(self, format):
        events = Event.all().filter("status IN", ["approved", "canceled"]).order("start_time")
        if format == "ics":
            cal = Calendar()
            for event in events:
                cal.add_component(event.to_ical())
            self.response.headers["content-type"] = "text/calendar"
            self.response.out.write(cal.as_string())
        elif format == "json":
            self.response.headers["content-type"] = "application/json"
            events = map(lambda x: x.to_dict(summarize=True), Event.get_approved_list())
            self.response.out.write(simplejson.dumps(events))
        elif format == "rss":
            url_base = "http://" + self.request.headers.get("host", "events.hackerdojo.com")
            rss = PyRSS2Gen.RSS2(
                title="Hacker Dojo Events Feed",
                link=url_base,
                description="Upcoming events at the Hacker Dojo in Mountain View, CA",
                lastBuildDate=datetime.now(),
                items=[
                    PyRSS2Gen.RSSItem(
                        title=event.name,
                        link=url_base + event_path(event),
                        description=event.details,
                        guid=url_base + event_path(event),
                        pubDate=event.updated,
                    )
                    for event in events
                ],
            )

            self.response.headers["content-type"] = "application/xml"
            self.response.out.write(rss.to_xml())
Example #2
0
def _make_icalendar():
	ical = ICalendar()
	ical.add('prodid',
            '-//Ross Laird/mezzanine-events//NONSGML V{0}//EN'.format(__version__))		
            #'-//Ross Laird Events//'
	ical.add('version', '2.0') # version of the format, not the product!
	return ical
Example #3
0
    def get_ical(self):
        cal = Calendar()
        adate = self.start_date
        for shift in self.shifts:
            event = Event()
            if shift not in self.definitions:
                print('WARNING: Unknown shift: {}'.format(shift),
                      file=sys.stderr)
                times = None
            else:
                if self.definitions[shift]:
                    times = [self.definitions[shift]['start'],
                             self.definitions[shift]['end']]
                else:
                    times = None
            if times is not None:
                starttime = time(int(times[0][:2]), int(times[0][2:4]),
                                 tzinfo=self.timezone)
                event.add('dtstart', datetime.combine(adate, starttime))
                if int(times[0]) > int(times[1]):
                    enddate = adate + timedelta(1)
                else:
                    enddate = adate
                endtime = time(int(times[1][:2]), int(times[1][2:4]),
                               tzinfo=self.timezone)
                event.add('dtend', datetime.combine(enddate, endtime))
                if 'title' in self.definitions[shift]:
                    event['summary'] = self.definitions[shift]['title']

                cal.add_component(event)
            adate += timedelta(1)
        return cal.to_ical()
Example #4
0
def talk_ics(slug):
    cal = Calendar()
    cal.add('prodid', '-//PyCon Canada 2016//2016.pycon.ca')
    cal.add('version', '2.0')

    if slug == 'schedule':
        schedule = get_data_file('schedule.json')

        # TODO: This should be refactored.
        for day in schedule.get('days'):
            for slot in day.get('entries'):
                if slot.get('talks'):
                    for room, talk in slot.get('talks').iteritems():
                        if talk:
                            cal.add_component(event_ics(talk))
    else:
        cal.add_component(event_ics(slug))

    headers = {
        'Content-Disposition': 'attachment;filename={0}.ics'.format(slug)
    }

    return Response(response=cal.to_ical(),
                    status=200,
                    mimetype='text/calendar',
                    headers=headers)
Example #5
0
 def new(self, cal, uri, event):
 
     if not cal:
     
         print "creating new calendar"
         cal = Calendar()
         cal['prodid'] = myProduct.prodid
         cal['version'] = myProduct.version
         
     if uri == "" or uri == None:
     
         import os
         uri = os.path.join(os.path.expanduser("~"),
                            ".gdesklets",
                            "gdesklets-calendar" + os.extsep + "ics")
         
         print "creating new file %s" % uri
     
     # Add the event to the calendar
     cal.add_component(event)
     
     try:
         tmp_cal_string = cal.as_string()
     except ValueError, error:
         print "ValueError in %s: \"%s\"\n" % (uri, error)
         print "This is a python issue, but could be solved in the icalendar package."
         print "Work around it by removing the offending dates in %s ." % uri
         return
Example #6
0
def make_anc_ical(request, anc=None):
	# Collect future meetings and sort after collating meetings across ANCs.
	now = datetime.datetime.now()
	meetings = []
	for mtganc, mtgs in meeting_data.items():
		if anc != None and mtganc.lower() != anc: continue
		for mtgdate, mtginfo in sorted(mtgs['meetings'].items()):
			mtgdate = dateutil.parser.parse(mtgdate)
			if mtgdate < now: continue
			meetings.append( (mtgdate, mtganc, mtginfo) )
	meetings.sort()

	# Make ical.
	from icalendar import Calendar, Event
	cal = Calendar()
	for mtgdate, mtganc, mtginfo in meetings:
		if mtginfo.get("status") == "invalid": continue
		event = Event()
		event.add('dtstart', mtgdate)
		event['summary'] = "ANC %s Meeting" % mtganc
		event['description'] = "See ANCFinder.org for details: http://ancfinder.org/%s" % mtganc
		event['location'] = '; '.join(mtginfo[k] for k in ('building', 'address', 'root') if mtginfo.get(k))
		event['link'] = mtginfo.get("link")
		cal.add_component(event)

	return HttpResponse(cal.to_ical(), "text/calendar" if "mime" not in request.GET else "text/plain")
class TTParser:
    _cal = Calendar()

    def __init__(self):
        self._cal = Calendar()
        self._cal.add('prodid', '-//University of Lincoln//Room TimeTable ICal Accessor//')
        self._cal.add('version', '2.0')
        self._baseUrl = "http://stafftimetables.lincoln.ac.uk/V2/UL/Reports/"


    def ical(self):
        d = date.today()
        for x in range(0, self._range):
            try:
                self.add_day(d + timedelta(x))
            except Exception as ex:
                logging.getLogger(__name__).warning(
                    'failed to add_day for ' + str(d + timedelta(x)) + ': ' + str(type(ex)) + ': ' + ex.message)
        return self._cal.to_ical()

    def create_event(self, name, room, the_day, time):
        tv = time.replace(' ', '').replace(':', '-').split('-')
        dBegin = datetime(the_day.year, the_day.month, the_day.day, int(tv[0]), int(tv[1]), tzinfo=self._tz_london)
        dEnd = datetime(the_day.year, the_day.month, the_day.day, int(tv[2]), int(tv[3]), tzinfo=self._tz_london)
        event = Event()
        event.add('summary', name)
        event.add('dtstart', dBegin)
        event.add('dtend', dEnd)
        event['location'] = vText(room)
        return event
Example #8
0
def index():
    cfg = load_config('config.json')

    calendar = Calendar()
    calendar['prodid'] = '-//worker-perlence//Worker calendar'
    calendar['version'] = '2.0'
    calendar['x-wr-calname'] = 'Worker calendar'
    for day, shift in workdays(cfg['FORMULA'], cfg['FIRST_DAY']):
        if shift == '0':
            continue
        event = Event()
        event.add('uid', 'WORKER-DAY-' + day.isoformat())
        event.add('dtstamp', datetime.now())
        event.add('dtstart', day)
        event.add('dtend', day + timedelta(days=1))
        event.add('summary', cfg['SUMMARY'][shift])
        event['dtstamp'].to_ical()
        event['dtstart'].to_ical()
        event['dtend'].to_ical()
        calendar.add_component(event)

    data = calendar.to_ical()
    cache_bust = md5(data).hexdigest()[:7]

    response = make_response(data)
    response.headers['Content-Type'] = 'text/calendar;charset=utf-8'
    response.headers['Content-Disposition'] = (
        'inline; filename="worker-day-%s.ics"' % cache_bust)
    return response
Example #9
0
 def __init__(self, ical_string, start_date, end_date, new_events):
     self.ical = Calendar.from_string(ical_string)
     self.simpl_ical = Calendar()
     self.new_events = new_events
     self.new_events.sort(key=lambda x: x.duration, reverse=True)
     self.start_date = start_date - start_date%30 + 30
     self.end_date = end_date - end_date%30 + 30
Example #10
0
    def update_event(self, username, uid, event_name, start_timestamp, quantity):
        """
        Update the info about a specific event on the user calendar.
        :param username: username of the calendar to insert the event.
        :param uid: UID tha identifies the event in the calendar.
        :param event_name: Event name.
        :param start_timestamp: The date where the event are scheduled.
        :param quantity: The quantity reserved.
        :return: Keyword 'OK'
        """
        cal = Calendar()
        cal['version'] = "2.0"
        cal['prodid'] = "//Radicale//NONSGML Radicale Server//EN"

        event = Event()
        event['uid'] = uid
        event['dtstart'] = vDatetime(datetime.fromtimestamp(start_timestamp)).to_ical()
        event['summary'] = event_name
        event['description'] = 'Quantity: ' + str(quantity)
        event['x-radicale-name'] = str(uid) + '.ics'

        cal.add_component(event)

        headers = {'Content-Type': 'text/calendar',
                   'charset': 'utf-8'}
        self.client.put(self.url + username + '/calendar.ics/' + str(uid) + '.ics', cal.to_ical(), headers)
        return 'OK'
Example #11
0
def get_course_calendar(user, course_key_string):
    try:
        from icalendar import Calendar, Event
    except ImportError:
        logging.error('Calendar module not installed')
        return

    course_key = CourseKey.from_string(course_key_string)
    checked = ['course', 'vertical', 'sequential']
    items = modulestore().get_items(course_key)
    hour = timedelta(hours=1)

    cal = Calendar()
    for num, item in enumerate(items):
        if not item.category in checked:
            continue
        if not item.graded:
            continue
        if not has_access(user, 'load', item, course_key=item.location.course_key):
            continue
        if not item.due:
            continue
        if item.category != 'course':
            format = item.format or item.get_parent().format
        else:
            format = 'course'
        url = u'http://{}{}'.format(settings.SITE_NAME, _reverse_usage(item))
        event = Event()
        summary = u'Type: {}; Name: {}({})'.format(format, item.display_name, url).encode('utf-8')
        event.add('summary', summary)
        event.add('dtstart', item.due - hour)
        event.add('dtend', item.due)
        cal.add_component(event)
    text = cal.to_ical().decode('utf-8')
    return text
Example #12
0
def calendar(username):
	access_token = request.args.get("access_token")

	try:
		data = urlopen("https://www.beeminder.com/api/v1/users/%s/goals.json?access_token=%s"%(username, access_token)).read()
		data = json.loads(data.decode(encoding='UTF-8'))
	except HTTPError:
		return error_page()

	cal = Calendar()
	cal.add('prodid', '-//Beeminder calendar//tevp.net//')
	cal.add('version', '2.0')
	cal.add('X-WR-CALNAME', 'Beeminder Calendar for %s'%username)

	for goal in data:
		start = datetime.fromtimestamp(goal["losedate"])
		startdate = start.date()
		if start.hour <=4: # Assume that times before 4am are effectively "yesterday"
			startdate -= timedelta(days = 1)
		enddate = startdate + timedelta(days = 1)
		title = goal["title"]
		event = Event()
		event.add('summary', "%s fail day" % title)
		event.add('dtstart', startdate)
		event.add('dtend', enddate)
		event.add('last-modified', datetime.now())
		event['uid'] = hashlib.md5(title.encode() + str(startdate).encode()).hexdigest()
		cal.add_component(event)

	resp = make_response(cal.to_ical())
	resp.headers["Content-Type"] = "text/Calendar"
	resp.headers["Cache-Control"] = "no-cache, must-revalidate"
	resp.headers["Expires"] = "Sat, 26 Jul 1997 05:00:00 GMT"
	return resp
Example #13
0
def build_calendar(issues, ics_path):
    cal = Calendar()
    for i in issues:
        event = Event()
        if "Full" in str(i.status):
            summary = "[COMPLET] " + i.subject
        else:
            summary = i.subject
        event.add('summary', summary)
        event.add('description', i.description)
        event['uid'] = i.id
        for c in i.custom_fields:
            if c.id == 20: # 20 is 'debut'
                start_time = str(c.value).replace(':', '')+"00"
            if c.id == 21: # 21 is 'fin'
                end_time = str(c.value).replace(':', '')+"00"
        event['dtstart'] = i.due_date.replace('/','')+"T"+start_time
        event['dtend'] = i.due_date.replace('/','')+"T"+end_time
        event['dtstamp'] = vDatetime(now).to_ical()
        organizer = vCalAddress('MAILTO:[email protected]')
        organizer.params['cn'] = vText('Les fruits défendus')
        event['organizer'] = organizer
        event['location'] = vText('Montréal, QC')
        cal.add_component(event)

        f = open(ics_path, 'wb')
        f.write(cal.to_ical())
        f.close()
Example #14
0
def ical_event_delete(task, name=None):
  from icalendar import Calendar
  # Note removes duplicates
  if name is None:
    name = task.name
  calendarname = task.group()
  stat = False
  client, calendar = calendar_load(calendarname)
  events = calendar.events()
  for event in events:
    if str(event).endswith('/'): continue
    try:
      event.load()
    except:
      error('Failed to load caldav event: ' + name)
      continue
    data = Calendar().from_ical(event.get_data())
    for component in data.walk():
      if component.name == "VTODO":
        if component.get('summary') == name:
          if not universe.dry:
            event.delete()
          report(colour.red + '  removed caldav event: ' + name + ' (calendar: ' + calendarname + ')' + colour.end)
          stat = True
  return stat
Example #15
0
 def XtestBla(self):
     from icalendar import Calendar
     c = Calendar()
     c['description']=u'Paragraph one\n\nParagraph two'
     output = c.to_ical()
     self.assertEqual(output, 
             "BEGIN:VCALENDAR\r\nDESCRIPTION:Paragraph one\r\n \r\n Paragraph two\r\nEND:VCALENDAR\r\n")
Example #16
0
 def export_ics(self):
     events = Event.get_recent_past_and_future()
     url_base = 'http://' + self.request.headers.get('host', 'events.hackerdojo.com')
     cal = Calendar()
     for event in events:
         iev = CalendarEvent()
         iev.add('summary', event.name if event.status == 'approved' else event.name + ' (%s)' % event.status.upper())
         # make verbose description with empty fields where information is missing
         ev_desc = '__Status: %s\n__Member: %s\n__Type: %s\n__Estimated size: %s\n__Info URL: %s\n__Fee: %s\n__Contact: %s, %s\n__Rooms: %s\n\n__Details: %s\n\n__Notes: %s' % (
             event.status,
             event.owner(),
             event.type,
             event.estimated_size,
             event.url,
             event.fee,
             event.contact_name,
             event.contact_phone,
             event.roomlist(),
             event.details,
             event.notes)
         # then delete the empty fields with a regex
         ev_desc = re.sub(re.compile(r'^__.*?:[ ,]*$\n*',re.M),'',ev_desc)
         ev_desc = re.sub(re.compile(r'^__',re.M),'',ev_desc)
         ev_url = url_base + event_path(event)
         iev.add('description', ev_desc + '\n--\n' + ev_url)
         iev.add('url', ev_url)
         if event.start_time:
           iev.add('dtstart', event.start_time.replace(tzinfo=pytz.timezone('US/Pacific')))
         if event.end_time:
           iev.add('dtend', event.end_time.replace(tzinfo=pytz.timezone('US/Pacific')))
         cal.add_component(iev)
     return 'text/calendar', cal.as_string()
Example #17
0
def export_calendar_for_user(cal_user_id=None, filename="export"):
    """
    Create and export iCalendar file with the meetings of the chosen user

    :param cal_user_id: User ID to create calendar for
    :param filename: Filename for the ics file
    :return: ics file wrapped in a response
    """
    if cal_user_id is None:
        # Defaults to current user
        cal_user_id = current_user.id

    meeting_list = Meeting.get_user_meetings(cal_user_id)
    tz = timezone(app.config['TIMEZONE'])
    cal = Calendar()
    for meeting in meeting_list:
        event = Event()
        event.add('summary', meeting.title)
        event.add('dtstart', tz.localize(meeting.start_time))
        event.add('dtend', tz.localize(meeting.end_time))
        event.add('description',
                  u'Møte generert av %s. Antall deltakere: %s. ' % (app.config['APP_NAME'],
                                                                    meeting.participant_count))
        cal.add_component(event)

    export = StringIO.StringIO()
    export.writelines(cal.to_ical())
    export.seek(0)
    return send_file(export,
                     attachment_filename=filename + '.ics',
                     as_attachment=True)
Example #18
0
    def get(self, format):
        events = Event.all().filter('status IN', ['approved', 'canceled']).order('start_time')
        if format == 'ics':
            cal = Calendar()
            for event in events:
                cal.add_component(event.to_ical())
            self.response.headers['content-type'] = 'text/calendar'
            self.response.out.write(cal.as_string())
        elif format == 'json':
            self.response.headers['content-type'] = 'application/json'
            events = map(lambda x: x.to_dict(summarize=True), Event.get_approved_list())
            self.response.out.write(simplejson.dumps(events))
        elif format =='rss':
            url_base = 'http://' + self.request.headers.get('host', 'events.hackerdojo.com')
            rss = PyRSS2Gen.RSS2(
                title = "Hacker Dojo Events Feed",
                link = url_base,
                description = "Upcoming events at the Hacker Dojo in Mountain View, CA",
                lastBuildDate = datetime.now(),
                items = [PyRSS2Gen.RSSItem(
                            title = event.name,
                            link = url_base + event_path(event),
                            description = event.details,
                            guid = url_base + event_path(event),
                            pubDate = event.updated,
                         ) for event in events]
            )

            self.response.headers['content-type'] = 'application/xml'
            self.response.out.write(rss.to_xml())
class TTParser:
    _cal = Calendar()
    _tz_london = timezone('Europe/London')
    # the start date has to be the first Monday of the teaching period
    _start_date = date(2015, 9, 14)
    _range = 51 * 7

    def __init__(self):
        self._cal = Calendar()
        self._cal.add('prodid', '-//University of Lincoln//TimeTable//')
        self._cal.add('version', '2.0')
        self._baseUrl = "http://stafftimetables.lincoln.ac.uk/V2/UL/Reports/"

    def ical(self, lecturer):
        for x in range(0, self._range):
        #for x in range(49, 70):
            try:
                self.query(self._start_date + timedelta(x), lecturer)
            except Exception as ex:
                logging.getLogger(__name__).warning(
                    'failed to add_day for '
                    + str(self._start_date + timedelta(x))
                    + ': ' + str(type(ex)) + ': ' + ex.message)
        return self._cal.to_ical()

    def create_event(self, name, room, the_day, dBegin, dEnd):
        event = Event()
        event.add('summary', name)
        event.add('dtstart', dBegin)
        event.add('dtend', dEnd)
        event['location'] = vText(room)
        return event
Example #20
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()
def generate_icalendar_event(event_id):
    """Takes an event id and returns the event in iCal format"""
    cal = Calendar()
    event = icalendar.Event()
    matching_event = Event.query.get(event_id)
    if matching_event is None:
        return api_response(status_code=404, error='Event')
    event.add('summary', matching_event.name)
    event.add('geo', (matching_event.latitude, matching_event.longitude))
    event.add('location', matching_event.location_name)
    event.add('color', matching_event.color)
    event.add('dtstart', matching_event.start_time)
    event.add('dtend', matching_event.end_time)
    event.add('logo', matching_event.logo)
    event.add('email', matching_event.email)
    event.add('description', matching_event.description)
    event.add('url', matching_event.event_url)
    cal.add_component(event)

    #Saving ical in file
    filename = "event_calendar/event-calendar-" + str(event_id) + ".ics"
    f = open(os.path.join(os.path.realpath('.') + '/static/', filename), 'wb')
    f.write(cal.to_ical())
    f.close()

    return api_response(
        data=jsonify(calendar=str(cal.to_ical), filename=filename),
        status_code=event_status_code(event_id),
        error='Event'
    )
    def handle(self, *args, **options):
        url = args[0]
        cal_data = requests.get(url).content
        cal = Calendar().from_ical(cal_data)
        events = cal.walk('vevent')
        Event.objects.filter(from_ics=True).delete()
        for event in events:
            end_time = event.get('dtend')
            if not end_time or not isinstance(end_time.dt, datetime.datetime):
                continue
            start_time = event.get('dtstart').dt.replace(year=2014)
            end_time = event.get('dtend').dt.replace(year=2014)
            name = event.get('summary')
            description = event.get('description')
            location = event.get('location')

            if description:
                description = smart_truncate(description, MAX_DESCRIPTION_LENGTH)

            new = Event.objects.create(
                name=unicode(name),
                location=unicode(location) if location else None,
                description=unicode(description) if description else None,
                start_time=start_time,
                end_time=end_time,
                is_featured=False,
                from_ics=True,
            )
Example #23
0
def makeCal(outputFile, inputFeed):
    cal = Calendar()

    menuRSS = feedparser.parse(inputFeed)
    for item in menuRSS["entries"]:
        title = item["title_detail"]["value"].split()
        jour = title[0]
        service = title[1]
        date = datetime.strptime(title[2], "%d/%m/%Y")
        description = item["summary_detail"]["value"].replace('<br />', '')

        ev = Event()

        if not ((jour=="Vendredi" and service=="soir") or jour=="Samedi" or jour=="Dimanche"):
            ev.add('summary', 'menu RU')
            if service == "midi":
                ev.add('dtstart', datetime(date.year,date.month,date.day,11,30,0,tzinfo=timezone("Europe/Paris")))
                ev.add('dtend', datetime(date.year,date.month,date.day,13,0,0,tzinfo=timezone("Europe/Paris")))
            elif service == "soir":
                ev.add('dtstart', datetime(date.year,date.month,date.day,18,30,0,tzinfo=timezone("Europe/Paris")))
                ev.add('dtend', datetime(date.year,date.month,date.day,20,0,0,tzinfo=timezone("Europe/Paris")))

            ev.add('description', description)
            cal.add_component(ev)

    f = open(outputFile, 'wb')
    f.write(cal.to_ical())
    f.close()
Example #24
0
def favourites_ical():
    code = request.args.get('token', None)
    user = None
    if code:
        user = User.get_by_checkin_code(app.config.get('FEED_SECRET_KEY'), str(code))
    if not current_user.is_anonymous:
        user = current_user
    if not user:
        abort(404)

    schedule = _get_scheduled_proposals(request.args, override_user=user)
    title = 'EMF {} Favourites for {}'.format(event_start().year, user.name)

    cal = Calendar()
    cal.add('summary', title)
    cal.add('X-WR-CALNAME', title)
    cal.add('X-WR-CALDESC', title)
    cal.add('version', '2.0')

    for event in schedule:
        if not event['is_fave']:
            continue
        cal_event = Event()
        cal_event.add('uid', event['id'])
        cal_event.add('summary', event['title'])
        cal_event.add('description', event['description'])
        cal_event.add('location', event['venue'])
        cal_event.add('dtstart', event['start_date'])
        cal_event.add('dtend', event['end_date'])
        cal.add_component(cal_event)

    return Response(cal.to_ical(), mimetype='text/calendar')
Example #25
0
class CalRessource(dict):

    def __init__(self, name, ressouce_path, color='normal', ressource_type="local"):
        self.ressouce_path = ressouce_path
        self.ressource_type = ressource_type
        self.color = COLOR_DICT[color]
        self.name = name
        if self.ressource_type == 'webressource':
            try:
                webcalendar = urlopen(ressouce_path)
                self.ical = Calendar.from_ical(webcalendar.read())
            except IOError:
                self.ical = Calendar()
        elif self.ressource_type == 'local':
            with open(self.ressouce_path, 'rb') as cal_file:
                self.ical = Calendar.from_ical(cal_file.read())
        for component in self.ical.walk():
            if component.name == 'VEVENT':
                iso_date = component['DTSTART'].dt.isoformat().split('T')[0]
                if not iso_date in self.keys():
                    self[iso_date] = [component]
                else:
                    self[iso_date].append(component)

    def save(self):
        if not self.ressource_type == 'webressource':
            with open(self.ressouce_path, 'w') as ressource_file:
                ressource_file.write(self.ical.to_ical())
Example #26
0
def generate_ical(object):
    cal = Calendar()
    cal['PRODID'] = 'Kawaz'
    cal['VERSION'] = '2.0'
    site = Site.objects.get(pk=settings.SITE_ID)

    event = CalEvent()
    event['summary'] = object.title
    event['description'] = object.body
    event['class'] = 'PUBLIC' if object.pub_state == 'public' else 'PRIVATE'
    if object.category:
        event['categories'] = object.category.label
    event['dtstamp'] = vDatetime(object.created_at)
    if object.place:
        event['location'] = object.place
    event['dtstart'] = vDatetime(object.period_start).to_ical()
    if object.period_end:
        event['dtend'] = vDatetime(object.period_end).to_ical()

    def create_vaddress(user):
        va = vCalAddress('MAILTO:{}'.format(user.email))
        va.params['cn'] = vText(user.nickname)
        va.params['ROLE'] = vText(user.role)
        return va

    organizer = create_vaddress(object.organizer)
    event['organizer'] = organizer
    event['URL'] = 'http://{}{}'.format(site.domain, object.get_absolute_url())

    for attendee in object.attendees.all():
        event.add('attendee', create_vaddress(attendee), encode=0)

    cal.add_component(event)

    return cal
Example #27
0
def gen_ical(courses):
    cal = Calendar()
    cal["version"] = "2.0"
    cal[
        "prodid"
    ] = "-//Zhejiang University//LIU Dongyuan//ZH"  # *mandatory elements* where the prodid can be changed, see RFC 5445

    for course in courses:
        for lesson in course["lessons"]:
            weeks = lesson["weeks"]
            for recur in weeks:
                event = Event()
                event.add("summary", unify_brackets(course["name"]))
                offset_days = lesson["day"] - 1 + 7 * (int(recur) - 1)
                offset = timedelta(days=offset_days)
                classdate = week_start + offset
                start = lesson_time[lesson["start"]]["start"]
                end = lesson_time[lesson["end"]]["end"]
                event.add("dtstart", datetime.combine(classdate, start))
                event.add("dtend", datetime.combine(classdate, end))
                event.add("location", lesson["location"])
                event.add("description", u"教师:" + course["teacher"])
                event["uid"] = str(uuid1()) + "@ZJU"
                cal.add_component(event)
    return cal.to_ical()
def to_ical(course_list):
    """This function takes all the data parsed and returns an
    icalendar."""
    ical = Calendar()
    current_tz = timezone("America/Montreal")
    for courses in course_list:
        for course in courses:
            bydays = course.datetime_day.split(',')
            for byday in bydays:
                entry_ical = Event()
                entry_ical.add('summary', course.summary)
                entry_ical.add('description', course.description)
                entry_ical.add('location', course.location)
                dtstart = parser.parse(
                    course.datetime_start).replace(tzinfo=current_tz)
                entry_ical.add('dtstart', dtstart)
                dtend = parser.parse(
                    course.datetime_end).replace(tzinfo=current_tz)
                entry_ical.add('dtend', dtend)
                until = parser.parse(
                    course.datetime_until).replace(tzinfo=current_tz)
                entry_ical.add('rrule', {'freq': 'weekly',
                                         'until': until,
                                         'byday': byday})
                ical.add_component(entry_ical)
    return ical
def send_file(request):
    from icalendar import Calendar, Event as Ev
    from datetime import datetime
    import pytz
    import time

    cal = Calendar()
    cal.add('prodid','//Delteps//OurCalendarObjectHackFmi')
    cal.add('version','2.0')
    cal.add('method','publish')

    i = 0
    for ev in Event.objects.all():
        event = Ev()
        event.add('summary',ev.subject.name)
        event.add('dtstart',ev.date_start)
        event.add('dtend', ev.date_end)
        event.add('dtstamp',datetime.now())        
        event['uid']=ev.subject.name+'/'+str(i)
        i = i+1
        cal.add_component(event)

    icalstream = cal.to_ical()
    response = HttpResponse(icalstream, mimetype='text/calendar')
    response['Filename'] = 'filename.ics'
    response['Content-Disposition'] = 'attachment; filename=filename.ics'
    return response
Example #30
0
def main():
    args = parse_command_line()
    start = dateutil.parser.parse(args.start).date()
    end = dateutil.parser.parse(args.end).date()
    days = list(args.days)

    with file(args.schedule, 'rt') as f:
        schedule = yaml.load(f)
    if args.template is not None:
        with open(args.template,'rt') as f:
            t = Template(f.read())
    if args.ical is not None:
        cal = Calendar()
        cal.add('prodid', '-//MicahSherr@Georgetown//make-syllabus//')
        cal.add('version', '2.0')
        if args.course is not None:  cal.add('X-WR-CALNAME', args.course)
        
    holidays = parse_holidays( args.holidays )

    if args.template is not None and args.header is not None:
        with open(args.header,'rt') as h:
            print h.read()

    if args.starttime is not None and args.endtime is not None:
        st = dateutil.parser.parse(args.starttime).time()
        et = dateutil.parser.parse(args.endtime).time()
            
    day_count = (end - start).days + 1
    class_num = 0
    for single_date in (start + datetime.timedelta(n) for n in range(day_count)):
        class_info = dict()
        day_of_week = str(single_date.weekday())
        if day_of_week in days:
            if single_date in holidays:
                class_info['lec_num'] = "-"
                class_info['lec_date'] = single_date
                class_info['description'] = 'No class'
                class_info['noclass'] = True
            else:
                # not a holiday; we have class.
                if class_num < len(schedule):
                    class_info = schedule[class_num]
                class_num = class_num + 1
                class_info['lec_num'] = class_num
                class_info['lec_date'] = single_date
                
            if args.template is not None:
                print t.render(class_info)
            if args.ical is not None and single_date not in holidays:
                event = make_ical_event(single_date,st,et,class_info,args)
                cal.add_component(event)

    if args.template is not None and args.footer is not None:
        with open(args.footer,'rt') as f:
            print f.read()

    if args.ical is not None:
        with open(args.ical,'wb') as o:
            o.write(cal.to_ical())
Example #31
0
 def __init__(self):
     self.cal = Calendar()
Example #32
0
def main(r, filename):
    data = open(filename, 'rb')  #opens a file to read gets from controller.py

    newStart = datetime.strptime(r, "%m/%d/%Y").date(
    )  # strips the input string for the specific month day and year values
    #print(newStart)
    minDate = date(
        9999, 12, 31
    )  # the maximum possible allowed date all start dates have to be less than this date
    daysList = ["MO", "TU", "WE", "TH", "FR", "SA", "SU"]

    startDateList = []
    endDateList = []
    #eventSummaryList = []
    #eventDescriptionList = []
    tzvalue = ""
    cal = Calendar.from_ical(data.read())
    rrules = []
    for component in cal.walk():
        if component.name == 'VCALENDAR':
            tzvalue = component.get('X-WR-TIMEZONE')
            break

    for event in cal.walk('vevent'):
        start = event.get('dtstart').dt

        startDateList.append(start)
        rrule = event.get('rrule')
        rrules.append(rrule)
        print(type(rrule))
        if (isinstance(start, datetime)):
            newStartDate = date(start.year, start.month, start.day)
        else:
            newStartDate = start
        #print('type newStartDate', type(newStartDate))
        #print('type startDate', type(start))
        #print('type minDate', type(minDate))
        if (newStartDate < minDate):
            minDate = newStartDate
        end = event.get('dtend').dt
        endDateList.append(end)
    newStartDateList = []
    newEndDateList = []
    print("minDate", minDate)
    print("new start", newStart)
    dayOffset = differ_days(minDate, newStart)
    print("offset", dayOffset)
    size = len(startDateList)
    print('size', size)
    for i in range(0, size):
        startDate = startDateList[i]
        # adds the number of offset days to generate a new start date
        newStartDate = startDate + timedelta(days=dayOffset)
        endDate = endDateList[i]

        newEndDate = endDate + timedelta(days=dayOffset)
        newStartDateList.append(newStartDate)
        newEndDateList.append(newEndDate)
    count = 0
    rruleCount = 0
    bigFile = ""
    for i in range(0, size):
        print(i, startDateList[i], newStartDateList[i], endDateList[i],
              newEndDateList[i])
    seenVEVENT = False

    with open(filename) as f:
        with open("answers.ics", "w") as f1:
            for line in f:
                # copies the file into another file line by line if the line contains a DTSTART or DTEND then the date will be replaced
                # also writes the file to a long string so that it can be returned and a user will have the opportunity to either copy and paste or download the file
                if "BEGIN:VEVENT" in line:
                    seenVEVENT = True
                if "RRULE" in line and seenVEVENT:
                    temp = line
                    if 'BYDAY' in line:
                        oldPart = temp[0:-3]
                        oldDay = temp[-3:-1]
                        val = daysList.index(oldDay)
                        val += dayOffset
                        val %= 7
                        newPart = daysList[val]
                        bigFile += oldPart + newPart + '\n'
                        f1.write(oldPart + newPart + '\n')
                        continue
                if "DTSTART;VALUE" in line and seenVEVENT:
                    f1.write("DTSTART;VALUE=DATE:" +
                             newStartDateList[count].strftime("%Y%m%d") + "\n")
                    bigFile += "DTSTART;VALUE=DATE:" + \
                        newStartDateList[count].strftime("%Y%m%d")+"\n"
                elif "DTSTART;TZID" in line and seenVEVENT:
                    f1.write("DTSTART;TZID=" + tzvalue + ":" +
                             newStartDateList[count].strftime("%Y%m%d") + 'T' +
                             newStartDateList[count].strftime("%H%M%S") + '\n')
                    bigFile += "DTSTART;TZID="+tzvalue+":" + \
                        newStartDateList[count].strftime(
                            "%Y%m%d")+'T'+newStartDateList[count].strftime("%H%M%S")+'\n'
                elif "DTSTART:" in line and seenVEVENT:
                    f1.write("DTSTART:" +
                             newStartDateList[count].strftime("%Y%m%d") + 'T' +
                             newStartDateList[count].strftime("%H%M%S") + 'Z' +
                             "\n")
                    bigFile += "DTSTART:" + \
                        newStartDateList[count].strftime(
                            "%Y%m%d") + 'T'+newStartDateList[count].strftime("%H%M%S")+'Z'+"\n"
                elif "DTEND;VALUE" in line and seenVEVENT:
                    f1.write("DTEND;VALUE=DATE:" +
                             newEndDateList[count].strftime("%Y%m%d") + "\n")
                    bigFile += "DTEND;VALUE=DATE:" + \
                        newEndDateList[count].strftime("%Y%m%d")+"\n"
                    count += 1
                elif 'DTEND;TZID' in line and seenVEVENT:
                    f1.write('DTEND;TZID=' + tzvalue + ':' +
                             newEndDateList[count].strftime('%Y%m%d') + 'T' +
                             newEndDateList[count].strftime('%H%M%S') + '\n')
                    bigFile += 'DTEND;TZID='+tzvalue+':' + \
                        newEndDateList[count].strftime(
                            '%Y%m%d')+'T'+newEndDateList[count].strftime('%H%M%S')+'\n'
                    count += 1
                elif "DTEND:" in line and seenVEVENT:
                    f1.write("DTEND:" +
                             newEndDateList[count].strftime("%Y%m%d") + 'T' +
                             newEndDateList[count].strftime("%H%M%S") + 'Z' +
                             "\n")
                    bigFile += "DTEND:" + newEndDateList[count].strftime(
                        "%Y%m%d") + 'T' + newEndDateList[count].strftime(
                            "%H%M%S") + 'Z' + "\n"
                    count += 1
                else:
                    f1.write(line)
                    bigFile += line

    f.close()
    f1.close()
    if os.path.exists(filename):
        os.remove(filename)

    return bigFile
Example #33
0
def ical_feed(request, variant, secret_id):
    if variant not in ('due', 'waiting'):
        return HttpResponseNotFound()
    try:
        store = models.TaskStore.objects.get(secret_id=secret_id)
    except:
        return HttpResponseNotFound()

    if not store.ical_enabled:
        return HttpResponseNotFound()

    if variant == 'due':
        calendar_title = "Tasks Due"
        task_filter = {
            'due.any': None,
            'status': 'pending',
        }
        field = 'due'
    elif variant == 'waiting':
        calendar_title = "Tasks Waiting"
        task_filter = {
            'status': 'waiting',
        }
        field = 'wait'

    tasks = store.client.filter_tasks(task_filter)

    calendar = Calendar()
    calendar.add('version', '2.0')
    calendar.add('prodid', '-//inthe.am//ical.%s//' % variant)
    calendar.add('X-WR-CALNAME', calendar_title)

    for task in tasks:
        if field not in task:
            continue

        event = Event()
        event.add('uid', task['uuid'])
        event.add('dtstart', task[field].date())
        event.add('dtend', task[field].date() + datetime.timedelta(days=1))
        event.add('dtstamp', task.get('modified', task['entry']))
        event.add('summary', task['description'])

        calendar.add_component(event)

    return HttpResponse(
        calendar.to_ical(),
        content_type='text/calendar',
    )
Example #34
0
        "February": 2,
        "March": 3,
        "April": 4,
        "May": 5,
        "June": 6,
        "July": 7,
        "August": 8,
        "September": 9,
        "October": 10,
        "November": 11,
        "December": 12,
    }.get(month_name, 0)


# Create the calendar object and add necessary stuff
cal = Calendar()
cal.add("prodid", "-//My calendar product//mxm.dk//")
cal.add("version", "2.0")

# Loop through 30 euroleague pages containing the games
for i in range(4, 35):
    link = ("http://www.euroleague.net/main/results?gamenumber=" + str(i) +
            "&phasetypecode=RS&seasoncode=E2019")
    myteam = "Zalgiris Kaunas"

    # Extract html from the page
    html = requests.get(link)
    html.encoding = "utf-8"

    # Create soup object from the html text
    soup = BeautifulSoup(html.text, features="lxml")
Example #35
0
from icalendar import Calendar, Event, Alarm
from datetime import datetime, timedelta
from pytz import UTC  # timezone
import csv

contact_file = "mycontacts.csv"
ics_export_file = "birthday.ics"
alert_begin = 8
alert_end = 10

cal = Calendar()
cal.add("prodid", "Birthday-Calendar")
cal.add("version", "1.0")


def openContacts():
    with open(contact_file, newline="") as csvfile:
        reader = csv.DictReader(csvfile)
        for row in reader:
            if (row["Birthday"] != ""):
                print(row["Name"], row["Birthday"])
                year = row["Birthday"][0:4]
                month = row["Birthday"][5:7]
                day = row["Birthday"][8:9]
                # sometimes google saves the birthday of your
                # contacts like this
                #  --.01-01
                # this is why we change the undifined value to 2000
                format_time = row["Birthday"].replace("--", "-").replace(
                    " ", "2000")
                format_time = format_time.split("-")
Example #36
0
class Team(object):
    """
    Object that has all team attributes.

    The information is sent from Competition where it
    has the visibility of the Standings table. It parses
    every row and it gets the data per each column.
    """
    Row = namedtuple('Row', [
        'position', 'name', 'played_games', 'won_games', 'tie_games',
        'lost_games', 'goals', 'diff', 'points'
    ])

    def __init__(self, competition_instance, team_details, division):
        self.logger = logging.getLogger('{base}.{suffix}'.format(
            base=LOGGER_BASENAME, suffix=self.__class__.__name__))
        self.session = competition_instance.session
        self.competition = competition_instance
        self._populate(Team.Row(*[info.text for info in team_details]))
        self._calendar = None
        self.division = division

    def _populate(self, team_details):
        """
        It gets the row from standingstable for the requested Team
        and then it gets the index accordingly to every column.
        :param team_details: BFS object
        """
        try:
            self.position = team_details.position
            self.name = team_details.name.encode('utf-8').strip()
            self.played_games = team_details.played_games
            self.won_games = team_details.won_games
            self.tie_games = team_details.tie_games
            self.lost_games = team_details.lost_games
            self.goals = team_details.goals
            self.diff = team_details.diff
            self.points = team_details.points
        except AttributeError:
            self.logger.exception("Got an exception while populating a team")

    @property
    def matches(self):
        """
        Gets all matches for a Team
        :return: list of Match objects
        """
        return [
            match for match in self.competition.matches
            if self.name in match.title
        ]

    @property
    def events(self):
        """
        :return: list of Event objects for all the matches
                 that a Team is part of
        """
        return [match.event for match in self.matches]

    @property
    def calendar(self):
        """
        Generates a RFC2445 (iCalendar) for all the Events that a Team has
        :return: Calendar string
        """
        if not self._calendar:
            self._calendar = Calendar()
            for event in self.events:
                self._calendar.add_component(event)
        return self._calendar
Example #37
0
class Competition(object):
    """
    Gets competitions from location, url and name.

    Object that has all attributes for a competition

    """
    def __init__(self, footy_instance, url):
        self._logger = logging.getLogger('{base}.{suffix}'.format(
            base=LOGGER_BASENAME, suffix=self.__class__.__name__))
        self.session = footy_instance.session
        self._populate(url)
        self._teams = []
        self._matches = []
        self._calendar = None
        self._soup = None

    def _populate(self, url):
        """
        Fills class variables that are passed from the main page
        """
        try:
            self.url = url
        except KeyError:
            self._logger.exception("Got an exception in Competition")

    @property
    def teams(self):
        """
        Gets all teams that are in a competition.

        The teams are retrieved from each row in the standings table
        :return: list of Team objects
        """
        if not self._teams:
            standings = self._get_table('banner')
            division = standings.h2.text
            for teams in standings.find_all('tr'):
                team = teams.find_all('td')
                if team:
                    self._teams.append(Team(self, team, division))
        return self._teams

    @property
    def matches(self):
        """
        Gets all matches that are in a competition

        The matches are retrieved from all the Rounds
        :return: list of Match objects
        """
        if not self._matches:
            match_tables = self._get_table('previous-matches')
            for matches in match_tables.find_all('tr'):
                match = matches.find_all('td')
                if match:
                    self._matches.append(Match(self, match))
        return self._matches

    def _get_table(self, section_attr):
        """
        Gets according section tag

        This is used for teams and matches
        :param section_attr: name of the section id attribute
        :return: BFS object
        """
        if not self._soup:
            competition_page = self.session.get(self.url)
            self._soup = Bfs(competition_page.text, "html.parser")
        return self._soup.find('section', {'id': '{}'.format(section_attr)})

    @property
    def calendar(self):
        """
        Generates a RFC2445 (iCalendar) for all the matches
        in a competition
        :return: Calendar string
        """
        if not self._calendar:
            self._calendar = Calendar()
            for team in self.teams:
                for event in team.events:
                    self._calendar.add_component(event)
        return self._calendar
Example #38
0
from icalendar import Calendar, Event
from pprint import pprint
events = {}

with open('events.en.ics', 'r') as f:
    cal = Calendar.from_ical(f.read())
    for component in cal.walk():
        if component.name == "VEVENT":
            evs = []
            desc = str(component.get('description'))

            evs = desc.split(', ')

            if len(evs) > 2:
                evs[-1] = evs[-1].split('and ')[-1]
            else:
                evs = desc.split(' and ')
            events.append({component.get('dtstart').dt: evs})

pprint(events)
Example #39
0
def events_from_ics(namespace, calendar, ics_str):
    try:
        cal = Calendar.from_ical(ics_str)
    except ValueError:
        raise MalformedEventError()

    events = []
    for component in cal.walk():
        if component.name == "VEVENT":
            start = component.get('dtstart').dt
            end = component.get('dtend').dt
            title = component.get('summary')
            description = str(component.get('description'))
            if isinstance(start, datetime):
                all_day = False
            else:
                all_day = True
                start = datetime.combine(start, datetime.min.time())
                end = datetime.combine(end, datetime.min.time())

            reccur = component.get('rrule')
            if reccur:
                reccur = reccur.to_ical()
            else:
                reccur = ''
            participants = []
            for attendee in component.get('attendee'):
                email = str(attendee)
                # strip mailto: if it exists
                if email.startswith('mailto:'):
                    email = email[7:]
                try:
                    name = attendee.params['CN']
                except KeyError:
                    name = None

                status_map = {
                    'NEEDS-ACTION': 'noreply',
                    'ACCEPTED': 'yes',
                    'DECLINED': 'no',
                    'TENTATIVE': 'maybe'
                }
                status = 'noreply'
                try:
                    a_status = attendee.params['PARTSTAT']
                    status = status_map[a_status]
                except KeyError:
                    pass

                notes = None
                try:
                    guests = attendee.params['X-NUM-GUESTS']
                    notes = "Guests: {}".format(guests)
                except KeyError:
                    pass

                participants.append({
                    'email_address': email,
                    'name': name,
                    'status': status,
                    'notes': notes,
                    'guests': []
                })

            location = component.get('location')
            organizer = component.get('organizer')
            if (organizer):
                organizer = str(organizer)
                if organizer.startswith('mailto:'):
                    organizer = organizer[7:]

            uid = str(component.get('uid'))
            event = Event(namespace=namespace,
                          calendar=calendar,
                          uid=uid,
                          provider_name='ics',
                          raw_data=component.to_ical(),
                          title=title,
                          description=description,
                          location=location,
                          reminders=str([]),
                          recurrence=reccur,
                          start=start,
                          end=end,
                          busy=True,
                          all_day=all_day,
                          read_only=True,
                          source='local',
                          participants=participants)

            events.append(event)
    return events
Example #40
0
def main(infile=None):
    # The skipinitialspace option eliminates leading
    # spaces and reduces blank cells to '' while the clean_spaces
    # function gets rid of trailing spaces.
    try:
        if infile == None:
            start_dir = '~/'
            if isdir(expanduser("~/Desktop")):
                start_dir = '~/Desktop/'
            msg = 'Please select the .csv file to be converted to .ics'
            infile = easygui.fileopenbox(msg=msg,
                                         title="",
                                         default=expanduser(start_dir),
                                         filetypes=["*.csv"])

        reader_builder = list(
            csv.DictReader(open(infile, 'U'), skipinitialspace=True))

    # For testing comment 4 lines above (2 x if / else) and use this:
    #        reader_builder = list(csv.DictReader(open('path_to_tester.csv', 'rb'), skipinitialspace = True))

    except Exception as e:
        logger.exception(e)
        easygui.msgbox(
            "Looks like there was an error opening the file, didn't even make it to the conversion part. Sorry!"
        )
        sys.exit(1)

    # Filter out events with empty subjects, a required element
    # for a calendar event.
    # Code found here: http://bit.ly/Z4Pg4h
    reader_builder[:] = [d for d in reader_builder if d.get('Subject') != '']

    headers = reader_builder[0].keys()
    logger.debug('reader_builder[0].keys(): {}'.format(headers))
    check_headers(headers)

    reader = clean_spaces(reader_builder)

    # Start calendar file
    cal = Calendar()
    cal.add('prodid', 'n8henrie.com')
    cal.add('version', '2.0')

    # Write the clean list of dictionaries to events.
    rownum = 0
    try:
        for row in reader:
            event = Event()
            event.add('summary', row['Subject'])

            try:
                check_dates_and_times(start_date=row.get('Start Date'),
                                      start_time=row.get('Start Time'),
                                      end_date=row.get('End Date'),
                                      end_time=row.get('End Time'),
                                      all_day=row.get('All Day Event'),
                                      subject=row.get('Subject'))
            except DateTimeError as e:
                sys.exit(e)

        # If marked as an "all day event," ignore times.
        # If start and end date are the same
        # or if end date is blank default to a single 24-hour event.
            if row.get('All Day Event') != None and row['All Day Event'].lower(
            ) == 'true':

                # All-day events will not be marked as 'busy'
                event.add('transp', 'TRANSPARENT')

                event.add(
                    'dtstart',
                    datetime.strptime(row['Start Date'], '%m/%d/%Y').date())

                if row.get('End Date') in ['', None]:
                    event.add(
                        'dtend',
                        (datetime.strptime(row['Start Date'], '%m/%d/%Y') +
                         timedelta(days=1)).date())
                else:
                    event.add('dtend',
                              (datetime.strptime(row['End Date'], '%m/%d/%Y') +
                               timedelta(days=1)).date())

            # Continue processing events not marked as "all day" events.
            else:

                # Events with times should be 'busy' by default
                event.add('transp', 'OPAQUE')

                # Get rid of spaces
                # Note: Must have both start and end times if not all_day, already checked
                row['Start Time'] = row['Start Time'].replace(' ', '')
                row['End Time'] = row['End Time'].replace(' ', '')

                # Allow either 24 hour time or 12 hour + am/pm
                if row['Start Time'][-2:].lower() in ['am', 'pm']:
                    event.add(
                        'dtstart',
                        datetime.strptime(
                            row['Start Date'] + row['Start Time'],
                            '%m/%d/%Y%I:%M%p'))
                else:
                    event.add(
                        'dtstart',
                        datetime.strptime(
                            row['Start Date'] + row['Start Time'],
                            '%m/%d/%Y%H:%M'))

                # Allow blank end dates (assume same day)
                if row.get('End Date') in ['', None]:
                    row['End Date'] = row['Start Date']

                if row['End Time'][-2:].lower() in ['am', 'pm']:
                    event.add(
                        'dtend',
                        datetime.strptime(row['End Date'] + row['End Time'],
                                          '%m/%d/%Y%I:%M%p'))
                else:
                    event.add(
                        'dtend',
                        datetime.strptime(row['End Date'] + row['End Time'],
                                          '%m/%d/%Y%H:%M'))

            if row.get('Description'):
                event.add('description', row['Description'])
            if row.get('Location'):
                event.add('location', row['Location'])

            event.add('dtstamp',
                      datetime.replace(datetime.now(), tzinfo=LocalTimezone()))
            event['uid'] = str(randint(1, 10**30)) + datetime.now().strftime(
                '%Y%m%dT%H%M%S') + '___n8henrie.com'

            cal.add_component(event)
            rownum += 1

    except Exception, e:
        if rownum > 0:
            easygui.msgbox(
                'I had a problem with an event. I think I might have gotten through about {0} events and had trouble with an event with subject: {1}. Sorry!'
                .format(rownum, row['Subject']))
            logger.exception(e)
        elif rownum == 0:
            easygui.msgbox(
                'Looks like I didn\'t even get through the first event. Sorry!'
            )
            logger.exception(e)
        else:
            easygui.msgbox(
                'Somehow it looks like I processed negative events... that shouldn\'t have happened. Sorry!'
            )
            logger.exception(e)
        sys.exit(2)
Example #41
0
def parse_events(content, start=None, end=None, default_span=timedelta(days=7)):
    """
    Query the events occurring in a given time range.

    :param content: iCal URL/file content as String
    :param start: start date for search, default today
    :param end: end date for search
    :param default_span: default query length (one week)
    :return: events as list
    """
    if not start:
        start = now()

    if not end:
        end = start + default_span

    if not content:
        raise ValueError("Content is invalid!")

    calendar = Calendar.from_ical(content)

    # Keep track of the timezones defined in the calendar
    timezones = {}

    # Parse non standard timezone name
    if "X-WR-TIMEZONE" in calendar:
        x_wr_timezone = str(calendar["X-WR-TIMEZONE"])
        timezones[x_wr_timezone] = get_timezone(x_wr_timezone)

    for c in calendar.walk("VTIMEZONE"):
        name = str(c["TZID"])
        try:
            timezones[name] = c.to_tz()
        except IndexError:
            # This happens if the VTIMEZONE doesn't
            # contain start/end times for daylight
            # saving time. Get the system pytz
            # value from the name as a fallback.
            timezones[name] = timezone(name)

    # If there's exactly one timezone in the file,
    # assume it applies globally, otherwise UTC
    if len(timezones) == 1:
        cal_tz = get_timezone(list(timezones)[0])
    else:
        cal_tz = UTC

    start = normalize(start, cal_tz)
    end = normalize(end, cal_tz)

    found = []
    recurrence_ids = []

    # Skip dates that are stored as exceptions.
    exceptions = {}
    for component in calendar.walk():
        if component.name == "VEVENT":
            e = create_event(component, cal_tz)

            if "RECURRENCE-ID" in component:
                recurrence_ids.append(
                    (e.uid, component["RECURRENCE-ID"].dt, e.sequence)
                )

            if "EXDATE" in component:
                # Deal with the fact that sometimes it's a list and
                # sometimes it's a singleton
                exlist = []
                if isinstance(component["EXDATE"], list):
                    exlist = component["EXDATE"]
                else:
                    exlist.append(component["EXDATE"])
                for ex in exlist:
                    exdate = ex.to_ical().decode("UTF-8")
                    exceptions[exdate[0:8]] = exdate

            # Attempt to work out what timezone is used for the start
            # and end times. If the timezone is defined in the calendar,
            # use it; otherwise, attempt to load the rules from pytz.
            start_tz = None
            end_tz = None

            if e.start.tzinfo != UTC:
                if str(e.start.tzinfo) in timezones:
                    start_tz = timezones[str(e.start.tzinfo)]
                else:
                    start_tz = e.start.tzinfo

            if e.end.tzinfo != UTC:
                if str(e.end.tzinfo) in timezones:
                    end_tz = timezones[str(e.end.tzinfo)]
                else:
                    end_tz = e.end.tzinfo

            # If we've been passed or constructed start/end values
            # that are timezone naive, but the actual appointment
            # start and end times are in a timezone, convert start
            # and end to have a timezone. Otherwise, python will
            # raise an exception for comparing timezone naive
            # and offset-aware values.
            if e.start.tzinfo and not start.tzinfo:
                start = normalize(start, e.start.tzinfo)
            if e.start.tzinfo and not end.tzinfo:
                end = normalize(end, e.start.tzinfo)

            duration = e.end - e.start
            if e.recurring:
                # Unfold recurring events according to their rrule
                rule = parse_rrule(component, cal_tz)
                [after] = adjust_timezone(component, [start - duration], start_tz)
                [end] = adjust_timezone(component, [end], start_tz)

                for dt in rule.between(after, end, inc=True):
                    if start_tz is None:
                        # Shrug. If we couldn't work out the timezone, it is what it is.
                        ecopy = e.copy_to(dt, e.uid)
                    else:
                        # Recompute the start time in the current timezone *on* the
                        # date of *this* occurrence. This handles the case where the
                        # recurrence has crossed over the daylight savings time boundary.
                        naive = datetime(
                            dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second
                        )
                        dtstart = normalize(naive, tz=start_tz)

                        ecopy = e.copy_to(dtstart, e.uid)

                        # We're effectively looping over the start time, we might need
                        # to adjust the end time too, but don't have it's recurred value.
                        # Make sure it's adjusted by constructing it from the meeting
                        # duration. Pro: it'll be right. Con: if it was in a different
                        # timezone from the start time, we'll have lost that.
                        ecopy.end = dtstart + duration

                    exdate = "%04d%02d%02d" % (
                        ecopy.start.year,
                        ecopy.start.month,
                        ecopy.start.day,
                    )
                    if exdate not in exceptions:
                        found.append(ecopy)
            elif e.end >= start and e.start <= end:
                exdate = "%04d%02d%02d" % (e.start.year, e.start.month, e.start.day)
                if exdate not in exceptions:
                    found.append(e)
    # Filter out all events that are moved as indicated by the recurrence-id prop
    return [
        event
        for event in found
        if e.sequence is None
        or not (event.uid, event.start, e.sequence) in recurrence_ids
    ]
Example #42
0
def orderFromUs(request):
    if request.method == 'POST':
        form = OrderForm(request.POST)

        if (form.is_valid()):
            orderer = form.cleaned_data['orderer']
            ordererEmail = form.cleaned_data['ordererEmail']
            phoneNumber = form.cleaned_data['phoneNumber']
            association = form.cleaned_data['association']
            numberOfCoffee = form.cleaned_data['numberOfCoffee']
            numberOfTea = form.cleaned_data['numberOfTea']
            numberOfSoda = form.cleaned_data['numberOfSoda']
            numberOfKlagg = form.cleaned_data['numberOfKlagg']
            numberOfJochen = form.cleaned_data['numberOfJochen']
            numberOfMinijochen = form.cleaned_data['numberOfMinijochen']
            numberOfPastasalad = form.cleaned_data['numberOfPastasalad']
            pickup = form.cleaned_data['pickup']
            date = form.cleaned_data['date']

            def extend_sub_types(sub_types):
                return [(field_name, label,
                         form.cleaned_data[f"numberOf{field_name.title()}"])
                        for field_name, label in sub_types]

            order_fields = (
                ("kaffe", numberOfCoffee, None),
                ("te", numberOfTea, None),
                ("läsk/vatten", numberOfSoda, None),
                ("klägg", numberOfKlagg, None),
                ("Jochen", numberOfJochen,
                 extend_sub_types(form.JOCHEN_TYPES)),
                ("Mini Jochen", numberOfMinijochen,
                 extend_sub_types(form.MINI_JOCHEN_TYPES)),
                ("pastasallad", numberOfPastasalad,
                 extend_sub_types(form.PASTA_SALAD_TYPES)),
            )

            subject = f'[Beställning {date.strftime("%Y-%m-%d")} | {orderer} - {association}]'
            from_email = '*****@*****.**'
            to = '*****@*****.**'

            html_content = render_to_string("baljan/email/order.html", {
                "data": form.cleaned_data,
                "order_fields": order_fields,
            })

            htmlpart = MIMEText(html_content.encode('utf-8'), 'html', 'UTF-8')

            msg = EmailMultiAlternatives(subject,
                                         "",
                                         from_email, [to],
                                         headers={'Reply-To': ordererEmail})

            msg.attach(htmlpart)

            description_lines = [
                f"Namn: {orderer}",
                f"Telefon: {phoneNumber}",
                f"Email: {ordererEmail}",
                "",
            ] + [
                f"Antal {name}: {count}"
                for name, count, _ in order_fields if count
            ] + ["", "Mer detaljerad information hittas i mailet."]
            calendar_description = "\n".join(description_lines)

            start, end = time(0, 0), time(0, 0)
            if pickup == '0':  # Morgon
                start, end = time(7, 30), time(8, 0)
            if pickup == '1':  # Lunch
                start, end = time(12, 15), time(13, 0)
            if pickup == '2':  # Eftermiddag
                start, end = time(16, 15), time(17, 0)

            tz = pytz.timezone(settings.TIME_ZONE)

            cal = Calendar()
            cal.add('prodid', '-//Baljan Cafesys//baljan.org//')
            cal.add('version', '2.0')
            cal.add('calscale', "GREGORIAN")
            cal.add('method', 'REQUEST')

            event = Event()
            event.add("summary", subject)
            event.add('dtstart', datetime.combine(date, start, tz))
            event.add('dtend', datetime.combine(date, end, tz))
            event.add('dtstamp', datetime.now(tz))
            event.add("uid", f"{uuid.uuid4()}@baljan.org")
            event.add("description", calendar_description)
            event.add("location", "Baljan")
            event.add("status", "CONFIRMED")

            cal.add_component(event)

            msg.attach('event.ics', cal.to_ical(), 'text/calendar')
            msg.send()
            messages.add_message(request, messages.SUCCESS, _("Thank you!"))
            return HttpResponseRedirect("bestallning")
    else:
        form = OrderForm()

    return render(request, 'baljan/orderForm.html', {
        'form': form,
    })
Example #43
0
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#	Copyright 2014	<Dominique DERRIER>

from icalendar import Event, Calendar
from datetime import datetime
import pytz

cal = Calendar()
evt = Event()

cal['X-CALENDARSERVER-ACCESS'] = "CONFIDENTIAL"
# CONFIDENTIAL | PUBLIC

#evt.add('dtstart',datetime(2014,04,29,20,0,0,tzinfo=pytz.timezone('America/Montreal')))
#evt.add('dtend',datetime(2014,04,29,21,0,0,tzinfo=pytz.timezone('America/Montreal')))
#evt.add('summary','Evenement secret')
#evt.add('description','Generated Evenement')
#
#cal.add_component(evt)

#evt2=Event()
#evt2.add('summary','Multiple Day')
#evt2.add('dtstart;VALUE=DATE','20140429')
Example #44
0
 def get_week_cal(self):
     '''Extracts the weekly calendar from the ical urls on the config file'''
     logger.info('Getting week calendar')
     today = datetime.datetime.utcnow().date()
     next_week = today + datetime.timedelta(7)
     week_cal = Calendar()
     week_cal.add('x-wr-calname', "Weekly Combined Calendar")
     urls = self.get_cal_urls()
     for url in urls:
         logger.debug(url)
         try:
             # Error avoider: Tries to read the calendar several times
             attempts = 0
             while attempts < 5:
                 if attempts < 4:
                     try:
                         req = requests.get(url)
                         attempts = 5
                     except:
                         attempts += 1
                 else:
                     req = requests.get(url)
                     attempts = 5
             # Error avoider finished
             if req.status_code != 200:
                 logger.error("Error {} fetching {}: {}".format(
                     url, req.status_code, req.text))
                 continue
             cal = Calendar.from_ical(req.text)
             for event in cal.walk("VEVENT"):
                 end = event.get('dtend')
                 if end:
                     WEEK_EVENT = False
                     if hasattr(end.dt, 'date'):
                         date = end.dt.date()
                     else:
                         date = end.dt
                     if date >= today and date < next_week:
                         WEEK_EVENT = True
                     elif 'RRULE' in event:
                         try:
                             rrule = event['RRULE']
                             until = rrule.get('until')[0]
                             if today < until.date():
                                 # Only weekly repeated events are supported
                                 if 'WEEKLY' in rrule.get('freq')[0]:
                                     WEEK_EVENT = True
                         except Exception as error:
                             logger.error(("{} rrule\n" + error).format(
                                 sys._getframe().f_code.co_name))
                     if WEEK_EVENT:
                         copied_event = Event()
                         for attr in event:
                             if type(event[attr]) is list:
                                 for element in event[attr]:
                                     copied_event.add(attr, element)
                             else:
                                 copied_event.add(attr, event[attr])
                         week_cal.add_component(copied_event)
         except Exception as error:
             # Add counter to avoid false errors
             logger.warning('Invalid calendar, removing\n' + url + '\n' +
                            error)
             self.remove_cal_url(url)
             for chat_id in self.state.chat_id_list:
                 self.state.bot.sendMessage(
                     chat_id, 'Removed invalid calendar url:\n' + url)
     logger.info('Got calendars')
     return week_cal
Example #45
0
#!/usr/bin/env python3

from icalendar import Calendar, Event
from datetime import datetime
from pytz import UTC

openFile = open('example.ics', 'rb')

openCalendar = Calendar.from_ical(openFile.read())
for component in openCalendar.walk():
    if component.name == "VEVENT" and component.get(
            'summary') is not None and component.get(
                'description') is not None and 'food' in str(
                    component.get('description')):
        #        print("Event==================================")
        #        print("Event:       " + component.get('summary'))
        #        print("Description: " + component.get('description'))
        #        print("Location:    " + component.get('location'))
        start = component.get('dtstart')
        end = component.get('dtend')
        startdt = start.dt
        startstr = startdt.strftime('%Y-%m-%d-%H-%M-%S')
        enddt = end.dt
        endstr = enddt.strftime('%Y-%m-%d-%H-%M-%S')
openFile.close()

print(startstr)
print(endstr)
Example #46
0
        if fn.endswith(".ics"))
data = ((os.stat(path), path) for path in data)

# regular files, insert creation date
data = ((stat[ST_CTIME], path) for stat, path in data
        if S_ISREG(stat[ST_MODE]))

file = sorted(data, reverse=True)[0][1]

try:
    g = open(file, 'rb')
    o = open('C:\\Users\\Alice\\Desktop\\birthdays.txt', 'wb')
except IOError:
    print "Could not open file! Please close Excel!"

gcal = Calendar.from_ical(g.read())
current_date = datetime.now().__str__().split()[0]
i = 0
people = []
for component in gcal.walk():
    if component.name == "VEVENT":
        persone_date = component.get('dtstart').__dict__['dt'].__str__()
        if persone_date == current_date:
            uid = component.get('uid').split('@')[0]
            uid = uid[1:]
            link = 'https://www.facebook.com/profile.php?id='
            link = link + uid
            name = component.get('summary').split()[0]
            simbol = ':*' if name[len(name) - 1] == 'a' else ':)'
            lma = 'La multi ani, ' + name + '! ' + simbol
            people.append((link, lma))
Example #47
0
def write_calendar(summary: str, start: datetime, end: datetime,
                   description: str, location: str, oponent_info: str):
    calname = "ltc-herren1-" + datetime.strftime(start, "%Y%m%d") + ".ics"
    t_cal = Calendar()
    t_cal.add('prodid',
              '-//LTC Herren 1 Kalender//ltc-scraper.py by Bartosz Swiatek//')
    t_cal.add('version', '2.0')
    t_cal.add('method', 'request')
    event = Event()
    event.add('uid', uuid.uuid4().hex)
    event.add('summary', summary)
    event.add('dtstart', start)
    event.add('dtend', end)
    event.add('description', description)
    event.add('last-modified', datetime.now())
    event.add('dtstamp', datetime.now())
    event.add('location', location)
    event.add('comment', oponent_info)
    alarm = Alarm()
    alarm.add('action', 'DISPLAY')
    alarm.add('TRIGGER;RELATED=START', '-P1D')
    alarm.add('description', 'Erinnerung zum Punktspiel')
    event.add_component(alarm)
    t_cal.add_component(event)
    cal.add_component(event)
    cwd = os.getcwd()
    f = open(os.path.join(cwd, calname), 'wb')
    f.write(t_cal.to_ical())
    f.close()
    del alarm
    del event
    del t_cal
Example #48
0
    def isschoolcalendar(self, zone, day, month, year):
        try:
            zoneok = str(zone.upper())
        except:
            return "Wrong Zone (must be A, B or C)"
        if len(zoneok) > 1:
            return "Wrong Zone (must be A, B or C)"
        if zoneok not in ["A", "B", "C"]:
            return "Wrong Zone (must be A, B or C)"
        else:
            URL = "http://media.education.gouv.fr/ics/Calendrier_Scolaire_Zone_" + zoneok + ".ics"
            try:
                ics = urlopen(URL)
                cal = Calendar.from_ical(ics.read())
            except:
                return "Data offline"
            #datenow = datetime.now()
            #year = datenow.year
            #month = datenow.month
            #month = 9
            #day = datenow.day
            #day = 26
            today = date(year, month, day)
            startspring = u"Vacances d'\xe9t\xe9"
            endspring = u"Rentr\xe9e scolaire des \xe9l\xe8ves"
            springd2 = None
            springd3 = None

            for event in cal.walk('vevent'):
                start = event.get('dtstart')
                convertstart = start.to_ical()
                stringconvertstart = str(convertstart)
                startdecode = time.strptime(str(convertstart), '%Y%m%d')
                end = event.get('dtend')
                summary = event.get('summary')
                yearstart = startdecode[0]
                monthstart = startdecode[1]
                daystart = startdecode[2]
                d2 = date(yearstart, monthstart, daystart)
                d3 = None
                description = summary.to_ical().decode('utf-8')
                if str(year) in convertstart:
                    if startspring in summary:
                        if d2 is not None:
                            springd2 = d2
                    if endspring in summary:
                        if d2 is not None:
                            springd3 = d2
                    comparestart = ""
                    compareend = ""
                    if springd2:
                        comparestart = springd2 < today
                    if springd3:
                        compareend = today < springd3
                    if comparestart and compareend:
                        description = startspring.encode('utf-8')
                        return str(description)

                if end:
                    convertend = end.to_ical()
                    enddecode = time.strptime(str(convertend), '%Y%m%d')
                    stringconvertend = str(convertend)
                    yearend = enddecode[0]
                    monthend = enddecode[1]
                    dayend = enddecode[2]
                    d3 = date(yearend, monthend, dayend)
                    if d2 < today < d3:
                        return description
                    else:
                        pass
    def _update(self, provider, update):
        self.provider = provider
        self.path = provider.get('config', {}).get('path', None)

        if not self.path:
            logger.warn(
                'File Feeding Service {} is configured without path. Please check the configuration'
                .format(provider['name']))
            return []

        registered_parser = self.get_feed_parser(provider)
        for filename in get_sorted_files(self.path,
                                         sort_by=FileSortAttributes.created):
            try:
                last_updated = None
                file_path = os.path.join(self.path, filename)
                if os.path.isfile(file_path):
                    stat = os.lstat(file_path)
                    last_updated = datetime.fromtimestamp(stat.st_mtime,
                                                          tz=utc)

                    if self.is_latest_content(last_updated,
                                              provider.get('last_updated')):
                        if isinstance(registered_parser,
                                      NTBEventXMLFeedParser):
                            logger.info('Ingesting xml events')
                            with open(file_path, 'rb') as f:
                                xml = ElementTree.parse(f)
                                parser = self.get_feed_parser(
                                    provider, xml.getroot())
                                item = parser.parse(xml.getroot(), provider)
                        elif isinstance(registered_parser, IcsTwoFeedParser):
                            logger.info('Ingesting ics events')
                            with open(file_path, 'rb') as f:
                                cal = Calendar.from_ical(f.read())
                                parser = self.get_feed_parser(provider, cal)
                                item = parser.parse(cal, provider)
                        else:
                            logger.info('Ingesting events with unknown parser')
                            parser = self.get_feed_parser(provider, file_path)
                            item = parser.parse(file_path, provider)

                        self.after_extracting(item, provider)
                        self.move_file(self.path,
                                       filename,
                                       provider=provider,
                                       success=True)

                        if isinstance(item, list):
                            yield item
                        else:
                            yield [item]
                    else:
                        self.move_file(self.path,
                                       filename,
                                       provider=provider,
                                       success=True)
            except Exception as ex:
                if last_updated and self.is_old_content(last_updated):
                    self.move_file(self.path,
                                   filename,
                                   provider=provider,
                                   success=False)
                raise ParserError.parseFileError(
                    '{}-{}'.format(provider['name'], self.NAME), filename, ex,
                    provider)

        push_notification('ingest:update')
Example #50
0
import os
import uuid
from pathlib import Path
home = str(Path.home())

url = "https://tvbb.liga.nu/cgi-bin/WebObjects/nuLigaTENDE.woa/wa/groupPage?championship=TVBB+Sommer+2021&group=1635442"

xpath = "//*[@id='content-row2']/table[2]"
before_xpath = "//*[@id='content-row2']/table[2]/tbody/tr["
datetime_xpath = "]/td[2]"
host_xpath = "]/td[4]"
guest_xpath = "]/td[5]"

club = "Lichtenberger Tennisclub"

cal = Calendar()
cal.add('prodid',
        '-//LTC Herren 1 Kalender//ltc-scraper.py by Bartosz Swiatek//')
cal.add('version', '2.0')
calendarname = "ltc-herren1-full.ics"

options = Options()
options.headless = True
# driver = webdriver.Firefox(options=options, executable_path=home+'/bin/geckodriver')
# second_driver = webdriver.Firefox(options=options, executable_path=home+'/bin/geckodriver')
driver = webdriver.Chrome(options=options,
                          executable_path=home + '/bin/chromedriver')
second_driver = webdriver.Chrome(options=options,
                                 executable_path=home + '/bin/chromedriver')
driver.get(url)
Example #51
0
def parse_events(content, start=None, end=None, default_span=timedelta(days=7)):
    """
    Query the events occurring in a given time range.

    :param content: iCal URL/file content as String
    :param start: start date for search, default today
    :param end: end date for search
    :param default_span: default query length (one week)
    :return: events as list
    """
    if not start:
        start = now()

    if not end:
        end = start + default_span

    if not content:
        raise ValueError('Content is invalid!')

    calendar = Calendar.from_ical(content)

    # Keep track of the timezones defined in the calendar
    timezones = {}
    for c in calendar.walk('VTIMEZONE'):
        name = str(c['TZID'])
        timezones[name] = c.to_tz()

    # If there's exactly one timezone in the file,
    # assume it applies globally, otherwise UTC
    if len(timezones) == 1:
        cal_tz = gettz(list(timezones)[0])
    else:
        cal_tz = UTC

    start = normalize(start, cal_tz)
    end = normalize(end, cal_tz)

    found = []

    # Skip dates that are stored as exceptions.
    exceptions = {}
    for component in calendar.walk():
        if component.name == "VEVENT":
            e = create_event(component)

            if ('EXDATE' in component):
                # Deal with the fact that sometimes it's a list and
                # sometimes it's a singleton
                exlist = []
                if isinstance(component['EXDATE'], list):
                    exlist = component['EXDATE']
                else:
                    exlist.append(component['EXDATE'])
                for ex in exlist:
                    exdate = ex.to_ical().decode("UTF-8")
                    exceptions[exdate[0:8]] = exdate

            # Attempt to work out what timezone is used for the start
            # and end times. If the timezone is defined in the calendar,
            # use it; otherwise, attempt to load the rules from pytz.
            start_tz = None
            end_tz = None

            # Ignore all-day apointments, they aren't really in a timezone.
            if not e.all_day:
                if e.start.tzinfo != UTC:
                    if str(e.start.tzinfo) in timezones:
                        start_tz = timezones[str(e.start.tzinfo)]
                    else:
                        try:
                            start_tz = timezone(str(e.start.tzinfo))
                        except:
                            pass

                if e.end.tzinfo != UTC:
                    if str(e.end.tzinfo) in timezones:
                        end_tz = timezones[str(e.end.tzinfo)]
                    else:
                        try:
                            end_tz = timezone(str(e.end.tzinfo))
                        except:
                            pass

            duration = e.end - e.start
            if e.recurring:
                # Unfold recurring events according to their rrule
                rule = parse_rrule(component, cal_tz)
                dur = e.end - e.start
                for dt in rule.between(start - dur, end, inc=True):
                    if start_tz is None:
                        # Shrug. If we coudln't work out the timezone, it is what it is.
                        ecopy = e.copy_to(dt, e.uid)
                    else:
                        # Recompute the start time in the current timezone *on* the
                        # date of *this* occurrence. This handles the case where the
                        # recurrence has crossed over the daylight savings time boundary.
                        naive = datetime(dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second)
                        dtstart = start_tz.localize(naive)

                        ecopy = e.copy_to(dtstart, e.uid)

                        # We're effectively looping over the start time, we might need
                        # to adjust the end time too, but don't have it's recurred value.
                        # Make sure it's adjusted by constructing it from the meeting
                        # duration. Pro: it'll be right. Con: if it was in a different
                        # timezone from the start time, we'll have lost that.
                        ecopy.end = dtstart + duration

                    exdate = "%04d%02d%02d" % (ecopy.start.year, ecopy.start.month, ecopy.start.day)
                    if exdate not in exceptions:
                        found.append(ecopy)
            elif e.end >= start and e.start <= end:
                exdate = "%04d%02d%02d" % (e.start.year, e.start.month, e.start.day)
                if exdate not in exceptions:
                    found.append(e)
    return found
Example #52
0
 def test__close(self, ical_writer, fact, path):
     """Make sure the calendar is actually written do disk before file is closed."""
     ical_writer.write_report((fact, ))
     with open(path, 'rb') as fobj:
         result = Calendar.from_ical(fobj.read())
         assert result.walk()
def main():
    time_zone = pytz.timezone('Asia/Shanghai')
    semesters = get_semesters_to_json()
    if semesters == -1:
        print('Program met some wrong, please wait and try again.')
        exit(1)
    print('Semesters:')
    semesters_dict = parse_semesters_json_to_dict(semesters)
    for semester in semesters:
        print(semester['Code'], '->', semester['Name'])
    selester_selected = input(
        'Please select a semester (Just need enter the number before arrow):')
    if not semesters_dict.__contains__(selester_selected):
        print('Please select a correct semester!')
        exit(1)
    username = input('Please input your JiDaTong username:'******'Please input your JiDaTong password:'******'Please input first day of term(Format: Year-month-day):')
    sid = get_jmu_sid(username, password)
    if sid == -1:
        print('Your username or password is error, please try again.')
        exit(1)
    print('Your JiDaTong sid is:', sid)
    schedule_json = get_schedule_to_json(sid, selester_selected)
    if schedule_json == -1:
        print('Program met some wrong, please wait and try again.')
        exit(1)
    name = schedule_json['Name']
    class_name = schedule_json['className']
    courses = schedule_json['courses']
    calendar = Calendar()
    calendar.add('prodid', '-//My calendar product//mxm.dk//')
    calendar.add('version', '2.0')
    for course in courses:
        course_in_day_of_week = int(course['couDayTime'])  # 课程在星期几
        course_take_weeks = get_course_take_weeks(course['allWeek'])
        course_begin_time, course_end_time = get_course_take_time(
            course['coudeTime'])
        for week in course_take_weeks:
            course_date = get_course_date(first_day_date_str,
                                          course_in_day_of_week, week)
            event = Event()
            event.add('summary', course['couName'])
            event.add(
                'dtstart',
                datetime.datetime(course_date.year,
                                  course_date.month,
                                  course_date.day,
                                  course_begin_time[0],
                                  course_begin_time[1],
                                  course_begin_time[2],
                                  tzinfo=time_zone))
            event.add(
                'dtend',
                datetime.datetime(course_date.year,
                                  course_date.month,
                                  course_date.day,
                                  course_end_time[0],
                                  course_end_time[1],
                                  course_end_time[2],
                                  tzinfo=time_zone))
            event.add(
                'dtstamp',
                datetime.datetime(course_date.year,
                                  course_date.month,
                                  course_date.day,
                                  course_begin_time[0],
                                  course_begin_time[1],
                                  course_begin_time[2],
                                  tzinfo=time_zone))
            event.add('location', course['couRoom'])
            calendar.add_component(event)
    output_file_name = '{} - {}.ics'.format(class_name, name)
    output_file = open(output_file_name, 'wb')
    output_file.write(calendar.to_ical())
    output_file.close()
    print('Success write your calendar to', output_file_name)
Example #54
0
def calendar_add(caldav_conn, args):
    cal = Calendar()
    cal.add('prodid', '-//{author_short}//{product}//{language}'.format(author_short=__author_short__, product=__product__, language=args.language))
    cal.add('version', '2.0')
    event = Event()
    ## TODO: timezone
    ## read timestamps from arguments
    event_spec = args.event_time.split('+')
    print(event_spec)

    

    if len(event_spec)>3:
        raise ValueError('Invalid event time "%s" - can max contain 2 plus-signs' % args.event_time)
    elif len(event_spec)==3:
        event_time = '%s+%s' % tuple(event_spec[0:2])
        event_duration = event_spec[2]
    elif len(event_spec)==2 and not event_spec[1][-1:] in time_units:
        event_time = '%s+%s' % tuple(event_spec[0:2])
        event_duration = '1h'
    elif len(event_spec)==2:
        event_time = '%s' % event_spec[0]
        event_duration = event_spec[1]
    else:
        event_time = event_spec[0]
        event_duration = '1h'
    ## TODO: error handling
    event_duration_secs = int(event_duration[:-1]) * time_units[event_duration[-1:]]
    dtstart = dateutil.parser.parse(event_spec[0])
    if args.whole_day:
        if event_spec[1][-1:] != 'd':
            raise ValueError('Duration of whole-day event must be multiple of 1d')
        duration = int(event_spec[1][:-1])
        dtstart = dateutil.parser.parse(event_spec[0])
        dtend = dtstart + timedelta(days=duration)
        event.add('dtstart', _date(dtstart.date()))
        event.add('dtend', _date(dtend.date()))
    else:
        event.add('dtstart', dtstart)
        ## TODO: handle duration and end-time as options.  default 3600s by now.
        event.add('dtend', dtstart + timedelta(0,event_duration_secs))
    event.add('dtstamp', _now())
    uid = uuid.uuid1()
    event.add('uid', str(uid))
    for attr in vcal_txt_one:
        if attr == 'summary':
            continue
        val = getattr(args, 'set_'+attr)
        if val:
            event.add(attr, val)
    
    for attr in vcal_txt_many:
        val = getattr(args, 'set_'+attr)
        if val:
            vals = val.split(',')
            event.add(attr, vals)

    event.add('summary', ' '.join(args.summary))

    if args.alarm is not None:
        alarm = create_alarm(' '.join(args.summary), parse_time_delta(args.alarm))
        event.add_component(alarm)

    cal.add_component(event)
    #print(cal.to_ical())
    _calendar_addics(caldav_conn, cal.to_ical(), uid, args)
    print(uid)
Example #55
0
        for cours in self.liste_cours:
            if d_now < cours.debut:  # Car dans l'ordre chronologique dans .ics

                delta = cours.debut - d_now
                hours = delta.seconds // 3600
                minutes = (delta.seconds - hours * 3600) // 60

                print("\nProchain cours dans ", str(hours), "h", str(minutes),
                      '\n')
                return cours
        return -1  # Pas de prochain cours

    def afficher_cours(self):
        for cours in self.liste_cours:
            cours.afficher()


cal = open("D:\\Python_WS\\20200916173359.ics", 'rb')
lc = Cours_Semaine()
gcal = Calendar.from_ical(cal.read())
for component in gcal.walk():
    if component.name == "VEVENT":
        c = Cours(component.get("DESCRIPTION"),
                  component.get("DTSTART").dt,
                  component.get("DTEND").dt,
                  component.get("DURATION").dt, component.get("LOCATION"))
        lc.ajouter_cours(c)
cal.close()

lc.prochain_cours().afficher()
Example #56
0
def get_caldav(choices: List[Choice], current_poll: Poll, user: BitpollUser,
               request):
    # calendar stuff
    events2 = []
    if not settings.CALENDAR_ENABLED or not (user.is_authenticated and
                                             current_poll.type == 'datetime'
                                             and choices):
        for choice in choices:
            events2.append([])
        return events2
    start = choices[0].date
    end = choices[-1].date

    # experimental: fetch calendar(s)
    events = []
    for calendar_obj in user.davcalendar_set.all():
        cache_key = "calendar_{}_events_{}-{}".format(calendar_obj.id, start,
                                                      end).replace(' ', '_')
        events_calendar = cache.get(cache_key)
        if events_calendar is None:
            events_calendar = []
            try:
                calendar = DavCalendar(client=DAVClient(calendar_obj.url),
                                       url=calendar_obj.url)
                appointments = calendar.date_search(start, end)
                for appointment in appointments:
                    ical = Calendar.from_ical(appointment.data)
                    for event in ical.walk():
                        if event.name == "VEVENT":
                            try:
                                if "DTEND" in event:
                                    end = event.decoded('DTEND')
                                else:
                                    duration = event.decoded("DURATION")
                                    if isinstance(duration, list):
                                        duration = duration[
                                            0]  # todo: use all elements?? what does it mean if there are more than one element?
                                    end = event.decoded('DTSTART') + duration
                                events_calendar.append({
                                    "DTSTART":
                                    event.decoded('DTSTART'),
                                    "DTEND":
                                    end,
                                    "NAME":
                                    event.get('summary').title(),
                                })
                            except (AttributeError, ValueError,
                                    TypeError) as e:
                                # we ignore the event we can not parse, but send it to sentry
                                try:
                                    from raven.contrib.django.raven_compat.models import client
                                    client.captureException()
                                except Exception:
                                    # if the sending of the error does fail we ignore it
                                    pass
                cache.set(cache_key, events_calendar)
            except AuthorizationError as e:
                messages.warning(
                    request,
                    ugettext_lazy(
                        'Could not access your calendar "%s" due to an authorization error'
                        % calendar_obj.name))
        events += events_calendar
    for choice in choices:
        ev_tmp = []
        for event in events:
            if isinstance(event['DTSTART'], type(choice.date)):
                # datetime
                if event['DTSTART'] <= choice.date and event[
                        'DTEND'] >= choice.date:
                    ev_tmp.append(event)
            else:
                # dates
                if event['DTSTART'] <= choice.date.date() <= event['DTEND']:
                    ev_tmp.append(event)
        events2.append(ev_tmp)
    return events2
Example #57
0
def main():
    args = parse_args()

    conn = sqlite3.connect(args.dbpath)

    us_west_start = datetime(2014, 6, 28)
    us_west_end = datetime(2014, 9, 24)
    us_east_start = datetime(2018, 8, 1)

    tz_tw = pytz.timezone('Asia/Taipei')
    tz_us_west = pytz.timezone('US/Pacific')
    tz_us_east = pytz.timezone('US/Eastern')

    cmd = '''SELECT activities.name, categories.name, start_time, end_time
    FROM activities, categories, facts
    WHERE facts.activity_id = activities.id
    AND activities.category_id = categories.id
    ORDER BY facts.start_time'''

    cals = []
    cal = Calendar()
    curr_cnt = 0
    cnt_us_west = cnt_us_east = cnt_tw = 0
    for row in conn.execute(cmd):
        start_time = datetime.strptime(row[-2], '%Y-%m-%d %H:%M:%S')
        if us_west_end >= start_time >= us_west_start:
            tz = tz_us_west
            cnt_us_west += 1
        elif start_time >= us_east_start:
            tz = tz_us_east
            cnt_us_east += 1
        else:
            tz = tz_tw
            cnt_tw += 1

        end_time = datetime(*time.strptime(row[-1], '%Y-%m-%d %H:%M:%S')[:6],
                            tzinfo=tz)
        start_time = datetime(*time.strptime(row[-2], '%Y-%m-%d %H:%M:%S')[:6],
                              tzinfo=tz)
        name = row[0]
        category = row[1]
        event = Event()
        event.add('summary', '%s (%s)' % (name, category))
        event.add('dtstart', start_time)
        event.add('dtend', end_time)
        cal.add_component(event)

        # limit calendar size
        curr_cnt += 1
        if curr_cnt >= args.limit:
            cals.append(cal)
            cal = Calendar()
            curr_cnt = 0
    os.makedirs(args.outdir, exist_ok=True)
    for idx, cal in enumerate(cals):
        with open(os.path.join(args.outdir, 'cal-%04d.ics' % idx),
                  'w') as outfile:
            outfile.write(cal.to_ical().decode('utf8').replace('\r\n',
                                                               '\n').strip())

    conn.close()
Example #58
0
def events_from_ics(namespace, calendar, ics_str):
    try:
        cal = iCalendar.from_ical(ics_str)
    except (ValueError, IndexError, KeyError):
        raise MalformedEventError()

    events = dict(invites=[], rsvps=[])

    # See: https://tools.ietf.org/html/rfc5546#section-3.2
    calendar_method = None

    for component in cal.walk():
        if component.name == "VCALENDAR":
            calendar_method = component.get('method')

        if component.name == "VTIMEZONE":
            tzname = component.get('TZID')
            assert tzname in timezones_table,\
                "Non-UTC timezone should be in table"

        if component.name == "VEVENT":
            # Make sure the times are in UTC.
            try:
                original_start = component.get('dtstart').dt
                original_end = component.get('dtend').dt
            except AttributeError:
                raise MalformedEventError("Event lacks start and/or end time")

            start = original_start
            end = original_end
            original_start_tz = None

            all_day = False
            if isinstance(start, datetime) and isinstance(end, datetime):
                tzid = str(original_start.tzinfo)
                if tzid in timezones_table:
                    original_start_tz = timezones_table[tzid]

                if original_start.tzinfo is None:
                    tzid = component.get('dtstart').params.get('TZID', None)
                    assert tzid in timezones_table,\
                        "Non-UTC timezone should be in table"

                    corresponding_tz = timezones_table[tzid]
                    original_start_tz = corresponding_tz

                    local_timezone = pytz.timezone(corresponding_tz)
                    original_start = local_timezone.localize(original_start)

                if original_end.tzinfo is None:
                    tzid = component.get('dtend').params.get('TZID', None)
                    assert tzid in timezones_table,\
                        "Non-UTC timezone should be in table"

                    corresponding_tz = timezones_table[tzid]
                    local_timezone = pytz.timezone(corresponding_tz)
                    original_end = local_timezone.localize(original_end)

                # Now that we have tz-aware datetimes, convert them to UTC
                start = original_start.astimezone(pytz.UTC)
                end = original_end.astimezone(pytz.UTC)

            elif isinstance(start, date) and isinstance(end, date):
                all_day = True
                start = arrow.get(start)
                end = arrow.get(end)

            assert isinstance(start, type(end)), "Start and end should be of "\
                "the same type"

            # Get the last modification date.
            # Exchange uses DtStamp, iCloud and Gmail LAST-MODIFIED.
            component_dtstamp = component.get('dtstamp')
            component_last_modified = component.get('last-modified')
            last_modified = None

            if component_dtstamp is not None:
                # This is one surprising instance of Exchange doing
                # the right thing by giving us an UTC timestamp. Also note that
                # Google calendar also include the DtStamp field, probably to
                # be a good citizen.
                if component_dtstamp.dt.tzinfo is not None:
                    last_modified = component_dtstamp.dt
                else:
                    raise NotImplementedError("We don't support arcane Windows"
                                              " timezones in timestamps yet")
            elif component_last_modified is not None:
                # Try to look for a LAST-MODIFIED element instead.
                # Note: LAST-MODIFIED is always in UTC.
                # http://www.kanzaki.com/docs/ical/lastModified.html
                last_modified = component_last_modified.dt

            title = None
            summaries = component.get('summary', [])
            if not isinstance(summaries, list):
                summaries = [summaries]

            if summaries != []:
                title = " - ".join(summaries)

            description = component.get('description')
            if description is not None:
                description = unicode(description)

            event_status = component.get('status')
            if event_status is not None:
                event_status = event_status.lower()
            else:
                # Some providers (e.g: iCloud) don't use the status field.
                # Instead they use the METHOD field to signal cancellations.
                method = component.get('method')
                if method and method.lower() == 'cancel':
                    event_status = 'cancelled'
                elif calendar_method and calendar_method.lower() == 'cancel':
                    # So, this particular event was not cancelled. Maybe the
                    # whole calendar was.
                    event_status = 'cancelled'
                else:
                    # Otherwise assume the event has been confirmed.
                    event_status = 'confirmed'

            assert event_status in EVENT_STATUSES

            recur = component.get('rrule')
            if recur:
                recur = "RRULE:{}".format(recur.to_ical())

            participants = []

            organizer = component.get('organizer')
            organizer_name = None
            organizer_email = None
            if organizer:
                organizer_email = unicode(organizer)
                if organizer_email.lower().startswith('mailto:'):
                    organizer_email = organizer_email[7:]

                if 'CN' in organizer.params:
                    organizer_name = organizer.params['CN']

                owner = formataddr([organizer_name, organizer_email.lower()])
            else:
                owner = None

            is_owner = False
            if owner is not None and (
                    namespace.account.email_address
                    == canonicalize_address(organizer_email)):
                is_owner = True

            attendees = component.get('attendee', [])

            # the iCalendar python module doesn't return a list when
            # there's only one attendee. Go figure.
            if not isinstance(attendees, list):
                attendees = [attendees]

            for attendee in attendees:
                email = unicode(attendee)
                # strip mailto: if it exists
                if email.lower().startswith('mailto:'):
                    email = email[7:]
                try:
                    name = attendee.params['CN']
                except KeyError:
                    name = None

                status_map = {
                    'NEEDS-ACTION': 'noreply',
                    'ACCEPTED': 'yes',
                    'DECLINED': 'no',
                    'TENTATIVE': 'maybe'
                }
                status = 'noreply'
                try:
                    a_status = attendee.params['PARTSTAT']
                    status = status_map[a_status]
                except KeyError:
                    pass

                notes = None
                try:
                    guests = attendee.params['X-NUM-GUESTS']
                    notes = u"Guests: {}".format(guests)
                except KeyError:
                    pass

                participants.append({
                    'email': email.lower(),
                    'name': name,
                    'status': status,
                    'notes': notes,
                    'guests': []
                })

            location = component.get('location')
            uid = str(component.get('uid'))
            sequence_number = int(component.get('sequence', 0))

            # Some services (I'm looking at you, http://www.foogi.me/)
            # don't follow the spec and generate icalendar files with
            # ridiculously big sequence numbers. Truncate them to fit in
            # our db.
            if sequence_number > 2147483647:
                sequence_number = 2147483647

            event = Event(namespace=namespace,
                          calendar=calendar,
                          uid=uid,
                          provider_name='ics',
                          raw_data=component.to_ical(),
                          title=title,
                          description=description,
                          location=location,
                          reminders=str([]),
                          recurrence=recur,
                          start=start,
                          end=end,
                          busy=True,
                          all_day=all_day,
                          read_only=True,
                          owner=owner,
                          is_owner=is_owner,
                          last_modified=last_modified,
                          original_start_tz=original_start_tz,
                          source='local',
                          status=event_status,
                          sequence_number=sequence_number,
                          participants=participants)

            # We need to distinguish between invites/updates/cancellations
            # and RSVPs.
            if calendar_method == 'REQUEST' or calendar_method == 'CANCEL':
                events['invites'].append(event)
            elif calendar_method == 'REPLY':
                events['rsvps'].append(event)

    return events
Example #59
0
class Match(object):
    """
    Object that has all attributes for a given match

    The information is sent from Competition where it
    has the visibility of the Matches table. It parses
    every row and it gets the data per each column.
    """
    Row = namedtuple(
        'Row',
        ['datetime', 'location', 'title', 'score', 'referee', 'motm', 'info'])

    def __init__(self, competition_instance, match_details):
        self.logger = logging.getLogger('{base}.{suffix}'.format(
            base=LOGGER_BASENAME, suffix=self.__class__.__name__))
        self._populate(Match.Row(*[detail.text for detail in match_details]))
        self.competitions = competition_instance
        self._calendar = None
        self._visiting_team = None
        self._visiting_team_goals = None
        self._home_team = None
        self._home_team_goals = None
        self.event = FootyEvent(self.datetime, self.title, self.location,
                                self.info)

    def _populate(self, match_details):
        """
        It gets the row from matchtable for the requested Team
        and then it gets the value accordingly to every column.

        :param info: BFS object
        """
        try:
            self.datetime = self.__string_to_datetime(match_details.datetime)
            self.location = match_details.location
            self.title = match_details.title.encode('utf-8')
            self.score = match_details.score
            self.referee = match_details.referee
            self.motm = match_details.motm
            self.info = match_details.info
        except AttributeError:
            self.logger.exception("Got an exception while populating a match")

    @property
    def visiting_team(self):
        """
        :return: Visiting team name in a match
        """
        if not self._visiting_team:
            self._visiting_team = self._get_team(home_team=False)
        return self._visiting_team

    @property
    def home_team(self):
        """
        :return: Home team name in a match
        """
        if not self._home_team:
            self._home_team = self._get_team()
        return self._home_team

    def _get_team(self, home_team=True):
        """
        Method that gets the teams in a match and
        it determines whether it is the home or visiting one.
        - True: Home team
        - False: Visiting team
        :param home_team: Boolean
        :return: home/visiting team name
        """
        home, visiting = self.title.split(' - ')
        match = home.strip()
        if not home_team:
            match = visiting.strip()
        team = next(
            (team for team in self.competitions.teams if team.name == match),
            None)
        return team

    def _get_match_goals(self, home_team_goals=True):
        """
        Method that gets the score in a match and
        it determines whether result is for the home or
        visiting team.
        - True: Home team goals
        - False: Visiting team goals
        :param home_team_goals: Boolean
        :return: home/visiting goals for a team
        """
        try:
            # Match not started (-:-)
            home, visiting = self.score.split(':')
        except ValueError:
            # Played match (0 - 0)
            home, visiting = self.score.split('-')
        score = home.strip()
        if not home_team_goals:
            score = visiting.strip()
        return score

    @property
    def home_team_goals(self):
        """
        :return: home team goals in a match
        """
        if not self._home_team_goals:
            self._home_team_goals = self._get_match_goals()
        return self._home_team_goals

    @property
    def visiting_team_goals(self):
        """
        :return: visiting team goals in a match
        """
        if not self._visiting_team_goals:
            self._visiting_team_goals = self._get_match_goals(
                home_team_goals=False)
        return self._visiting_team_goals

    @property
    def calendar(self):
        """
        Generates a RFC2445 (iCalendar) for a match
        :return: Calendar string
        """
        if not self._calendar:
            self._calendar = Calendar()
            self._calendar.add_component(self.event)
        return self._calendar

    @staticmethod
    def __string_to_datetime(datetime_string):
        """
        Converts date and time string into a datetime object
        :param datetime_string: 05.09.2017 21:30
        :return: datetime object
        """
        datetime_object = None
        try:
            datetime_object = parse(date_string=datetime_string,
                                    date_formats=['%d.%m.%Y %H:%M'],
                                    settings={'TIMEZONE': 'Europe/Amsterdam'})
        except AttributeError:
            LOGGER.exception("Couldn't parse this datetime.")
        return datetime_object
Example #60
0
try:
    args = cgi.parse_qs(os.getenv("QUERY_STRING"))
except AttributeError:
    print "No courses defined"
    sys.exit()
    pass

scraperwiki.utils.httpresponseheader('Content-Type', 'text/calendar')
sourcescraper = 'course_listings'
scraperwiki.sqlite.attach(sourcescraper)

data = scraperwiki.sqlite.select('* from swdata WHERE course_code IN (' +
                                 getCourses(args['courses'][0]) + ')')

cal = Calendar()
cal.add('version', '2.0')
cal.add('prodid', '-//ScraperWiki MB//SOAS Course Listings//EN')
cal.add('X-WR-CALNAME', 'SOAS Course Listings')
cal.add('X-WR-TIMEZONE', 'Europe/London')
cal.add('X-ORIGINAL-URL', 'https://scraperwiki.com/scrapers/course_listings/')

for ev in data:

    # if it's in the request...

    day_adder = {"Mon": 0, "Tue": 1, "Wed": 2, "Thu": 3, "Fri": 4}
    dates = []
    if (ev['term'] == "Term 1"):
        dates = [{
            "start_date": "2012-10-01",