Пример #1
0
def do_import(username, password, calendar, server, ics_url):
  base_url = CALDAVURL % (server, username, calendar)

  # fetch events from target cal
  target_fetch_url = '%s?export' % base_url
  r = requests.get(target_fetch_url, auth=(username, password))
  r.raise_for_status()
  try:
    target_cal = Calendar.from_ical(r.text)
  except ValueError as e:
    print('Warning: Could not parse iCal (%s)' % target_fetch_url,
          file=sys.stderr)
    print(e, file=sys.stderr)
    return

  existing_uids = []
  for e in target_cal.walk('VEVENT'):
    uid = bytes.decode(e['UID'].to_ical()).replace('\'', '').replace('/', 'slash')
    existing_uids.append(uid)

  # fetch webcal
  sourceRequest = requests.get(ics_url)
  sourceRequest.encoding = 'utf-8'
  sourceContent = sourceRequest.text
  c = Calendar.from_ical(sourceContent)

  # import webcal
  imported_uids = []
  for e in c.walk('VEVENT'):
    uid = bytes.decode(e['UID'].to_ical())
    uid.replace('\'','')
    uid.replace('/','slash')
    cal = Calendar()
    cal.add_component(e)
    r = requests.put('%s/%s.ics' % (base_url, uid),
                     data=cal.to_ical(),
                     auth=(username, password),
                     headers={'content-type':'text/calendar; charset=UTF-8'}
                     )
    if r.status_code == 500 and r'Sabre\VObject\Recur\NoInstancesException' in r.text:
      # ignore the NoInstancesException
      print('Warning: No valid instances: %s' % uid, file=sys.stdout)
    elif r.status_code == 201 or r.status_code == 204:
      print('Imported: %s (%d)' % (uid, r.status_code), file=sys.stdout)
      imported_uids.append(uid)
    else:
      r.raise_for_status()

  # remove events not in webcal
  for uid in existing_uids:
    if not uid in imported_uids:
      r = requests.delete('%s/%s.ics' % (base_url, uid),
                          auth=(username, password))
      if r.status_code == 204:
        print('Deleted %s' % uid, file=sys.stdout)
        # ignore 404 - not found (seems to be a manually created event)
      elif r.status_code == 404:
        pass
      else:
        r.raise_for_status()
Пример #2
0
    async def report(self, environ, body, resources_by_hrefs,
                     properties, base_href, base_resource, depth):
        requested = None
        for el in body:
            if el.tag == '{urn:ietf:params:xml:ns:caldav}time-range':
                requested = el
            else:
                raise AssertionError("unexpected XML element")
        tz = get_calendar_timezone(base_resource)

        def tzify(dt):
            return as_tz_aware_ts(dt, tz).astimezone(pytz.utc)
        (start, end) = _parse_time_range(requested)
        assert start.tzinfo
        assert end.tzinfo
        ret = ICalendar()
        ret['VERSION'] = '2.0'
        ret['PRODID'] = PRODID
        fb = FreeBusy()
        fb['DTSTAMP'] = vDDDTypes(tzify(datetime.datetime.now()))
        fb['DTSTART'] = vDDDTypes(start)
        fb['DTEND'] = vDDDTypes(end)
        fb['FREEBUSY'] = [item async for item in iter_freebusy(
            webdav.traverse_resource(base_resource, base_href, depth),
            start, end, tzify)]
        ret.add_component(fb)
        return webdav.Response(status='200 OK', body=[ret.to_ical()])
Пример #3
0
 def extractEqual(self, incal_str, outcal_str):
     incal = ICalendar.from_ical(incal_str)
     expected_outcal = ICalendar.from_ical(outcal_str)
     outcal = ICalendar()
     caldav.extract_from_calendar(incal, outcal, self.requested)
     self.assertEqual(expected_outcal.to_ical().decode(),
                      outcal.to_ical().decode(),
                      ET.tostring(self.requested))
Пример #4
0
def do_import(username, password, calendar, server, ics_url):
  base_url = CALDAVURL % (server, username, calendar)

  # fetch events from target cal
  target_fetch_url = '%s?export' % base_url
  r = requests.get(target_fetch_url, auth=(username, password))
  r.raise_for_status()
  try:
    target_cal = Calendar.from_ical(r.text)
  except ValueError as e:
    print('Warning: Could not parse iCal (%s)' % target_fetch_url,
          file=sys.stderr)
    print(e, file=sys.stderr)
    return

  existing_uids = [e['UID'].to_ical() for e in target_cal.walk('VEVENT')]

  # replace markers
  today = date.today()
  ics_url = ics_url.replace('###YEAR###', today.strftime("%Y"))
  ics_url = ics_url.replace('###YEAR+1###', date(today.year + 1, today.month, today.day).strftime("%Y"))
  print('Used ics_url: %s' % (ics_url))

  # fetch webcal
  c = Calendar.from_ical(requests.get(ics_url).text)

  # import webcal
  imported_uids = []
  for e in c.walk('VEVENT'):
    uid = e['UID'].to_ical()
    cal = Calendar()
    cal.add_component(e)
    r = requests.put('%s/%s.ics' % (base_url, uid),
                     data=cal.to_ical(),
                     auth=(username, password),
                     headers={'content-type':'text/calendar; charset=UTF-8'}
                     )
    if r.status_code == 500 and 'Sabre\VObject\Recur\NoInstancesException' in r.text:
      # ignore the NoInstancesException
      print('Warning: No valid instances: %s' % uid, file=sys.stdout)
    elif r.status_code == 201 or r.status_code == 204:
      print('Imported: %s (%d)' % (uid, r.status_code), file=sys.stdout)
      imported_uids.append(uid)
    else:
      r.raise_for_status()

  # remove events not in webcal
  for uid in existing_uids:
    if not uid in imported_uids:
      r = requests.delete('%s/%s.ics' % (base_url, uid),
                          auth=(username, password))
      if r.status_code == 204:
        print('Deleted %s' % uid, file=sys.stdout)
        # ignore 404 - not found (seems to be a manually created event)
      elif r.status_code == 404:
        pass
      else:
        r.raise_for_status()
Пример #5
0
def do_import(username, password, calendar, server, ics_url):
    base_url = CALDAVURL % (server, username, calendar)

    # fetch events from target cal
    target_fetch_url = '%s?export' % base_url
    r = requests.get(target_fetch_url, auth=(username, password))
    r.raise_for_status()
    try:
        target_cal = Calendar.from_ical(r.text)
    except ValueError as e:
        print('Warning: Could not parse iCal (%s)' % target_fetch_url,
              file=sys.stderr)
        print(e, file=sys.stderr)
        return

    existing_uids = [e['UID'].to_ical() for e in target_cal.walk('VEVENT')]

    # fetch webcal
    sourceRequest = requests.get(ics_url)
    sourceRequest.encoding = 'utf-8'
    sourceContent = sourceRequest.text
    c = Calendar.from_ical(sourceContent)

    # import webcal
    imported_uids = []
    for e in c.walk('VEVENT'):
        uid = bytes.decode(e['UID'].to_ical())
        uid.replace('\'', '')
        uid.replace('/', 'slash')
        cal = Calendar()
        cal.add_component(e)
        r = requests.put(
            '%s/%s.ics' % (base_url, uid),
            data=cal.to_ical(),
            auth=(username, password),
            headers={'content-type': 'text/calendar; charset=UTF-8'})
        if r.status_code == 500 and r'Sabre\VObject\Recur\NoInstancesException' in r.text:
            # ignore the NoInstancesException
            print('Warning: No valid instances: %s' % uid, file=sys.stdout)
        elif r.status_code == 201 or r.status_code == 204:
            print('Imported: %s (%d)' % (uid, r.status_code), file=sys.stdout)
            imported_uids.append(uid)
        else:
            r.raise_for_status()

    # remove events not in webcal
    for uid in existing_uids:
        if not uid in imported_uids:
            r = requests.delete('%s/%s.ics' % (base_url, uid),
                                auth=(username, password))
            if r.status_code == 204:
                print('Deleted %s' % uid, file=sys.stdout)
                # ignore 404 - not found (seems to be a manually created event)
            elif r.status_code == 404:
                pass
            else:
                r.raise_for_status()
Пример #6
0
 def extractEqual(self, incal_str, outcal_str):
     incal = ICalendar.from_ical(incal_str)
     expected_outcal = ICalendar.from_ical(outcal_str)
     outcal = ICalendar()
     outcal = caldav.extract_from_calendar(incal, self.requested)
     self.maxDiff = None
     self.assertMultiLineEqual(
         expected_outcal.to_ical().decode(),
         outcal.to_ical().decode(),
         ET.tostring(self.requested),
     )
Пример #7
0
 def get_value_ext(self, base_href, resource, el, environ, requested):
     if len(requested) == 0:
         serialized_cal = b''.join(resource.get_body())
     else:
         c = ICalendar()
         calendar = calendar_from_resource(resource)
         if calendar is None:
             raise KeyError
         extract_from_calendar(calendar, c, requested)
         serialized_cal = c.to_ical()
     # TODO(jelmer): Don't hardcode encoding
     el.text = serialized_cal.decode('utf-8')
Пример #8
0
def do_import(username, password, calendar, server, ics_url, ics_username, ics_password):
    logging.info('  Working with calendar %s...' % calendar)
    base_url = CALDAVURL % (server, username, calendar)

    target_fetch_url = '%s?export' % base_url
    r = requests.get(target_fetch_url, auth=(username, password))
    r.raise_for_status()
    try:
        target_cal = Calendar.from_ical(r.text)
    except ValueError as e:
        logging.error('    Warning: Could not parse iCal (%s)' % target_fetch_url)
        logging.error(e)
        return

    existing_uids = [bytes.decode(e['UID'].to_ical()).replace('\'', '').replace('/', 'slash') for e in target_cal.walk('VEVENT')]

    sourceRequest = requests.get(ics_url, auth=(ics_username, ics_password))
    sourceRequest.encoding = 'utf-8'
    sourceContent = sourceRequest.text
    c = Calendar.from_ical(sourceContent)

    distant_uids = [bytes.decode(e['UID'].to_ical()).replace('\'', '').replace('/', 'slash') for e in c.walk('VEVENT')]

    imported_uids = []
    for e in c.walk('VEVENT'):
        uid = bytes.decode(e['UID'].to_ical()).replace('\'', '').replace('/', 'slash')
        name = bytes.decode(e['SUMMARY'].to_ical())
        if uid not in existing_uids:
            cal = Calendar()
            cal.add_component(e)
            r = requests.put('%s/%s.ics' % (base_url, uid),
                             data=cal.to_ical(),
                             auth=(username, password),
                             headers={'content-type': 'text/calendar; charset=UTF-8'}
                             )
            if r.status_code == 500 and r'Sabre\VObject\Recur\NoInstancesException' in r.text:
                logging.warning('   No valid instances: %s (%s)' % (uid, name))
            elif r.status_code == 201 or r.status_code == 204:
                logging.info('   Imported: %s (%s)' % (uid, name))
                imported_uids.append(uid)
            else:
                r.raise_for_status()

    for euid in existing_uids:
        if not euid in distant_uids:
            r = requests.delete('%s/%s.ics' % (base_url, euid), auth=(username, password))
        if r.status_code == 204:
            logging.info('Deleted %s' % euid)
        elif r.status_code == 404:
            pass
        else:
            r.raise_for_status()
    logging.info('  Done.')
Пример #9
0
def generate_calendar(request):
    """http://codespeak.net/icalendar/"""

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

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

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

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

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

            cal.add_component(event)

    return HttpResponse(cal.to_ical().replace("\n", "\r\n"), content_type="text/calendar")
Пример #10
0
GOING_PREFIX = "You’re going.\n\n"


def fix_vevent(vevent):
    status = None
    if str(vevent['DESCRIPTION']).startswith(TRACKING_PREFIX):
        vevent['DESCRIPTION'] = vevent['DESCRIPTION'][len(TRACKING_PREFIX):]
        vevent['STATUS'] = 'TENTATIVE'
    if str(vevent['DESCRIPTION']).startswith(GOING_PREFIX):
        vevent['STATUS'] = 'CONFIRMED'
        vevent['DESCRIPTION'] = vevent['DESCRIPTION'][len(GOING_PREFIX):]
    if str(vevent['DESCRIPTION']).startswith(str(vevent['URL'])):
        vevent['DESCRIPTION'] = vevent['DESCRIPTION'][len(str(vevent['URL'])):]
    if not vevent['DESCRIPTION']:
        del vevent['DESCRIPTION']
    lpts = str(vevent['LOCATION']).split(',')
    for i in reversed(list(range(len(lpts)))):
        loc = (' at ' + ','.join(
            lpts[:i])) + ' (' + vevent['DTSTART'].dt.strftime('%d %b %y') + ')'
        vevent['SUMMARY'] = vevent['SUMMARY'].replace(loc, '')
    return vevent


out = Calendar()
for component in orig.subcomponents:
    if component.name == 'VEVENT':
        component = fix_vevent(component)
    out.add_component(component)

sys.stdout.buffer.write(out.to_ical())
Пример #11
0
    duration = datetime.timedelta(1)


props = {
    'categories': opts.categories.split(','),
    'dtstart': vDate(dtstart.date()),
    'created': vDatetime(datetime.datetime.now()),
    'class': 'PUBLIC',
    }
if status is not None:
    props['status'] = status
if location is not None:
    props['location'] = vText(location)
if opts.event_url:
    props['url'] = vUri(opts.event_url)
if description is not None:
    props['summary'] = vText(description)
if dtend is not None:
    props['dtend'] = vDate(dtend.date())
if duration is not None:
    props['duration'] = vDuration(duration)

uid = str(uuid.uuid1())
props['UID'] = uid
ev = Event(**props)

c = Calendar()
c.add_component(ev)

utils.add_member(opts.url, 'text/calendar', c.to_ical())
def do_import(username, password, calendar, server, ics_url):
  base_url = CALDAVURL % (server, username, calendar)

  # fetch events from target cal
  target_fetch_url = '%s?export' % base_url
  r = requests.get(target_fetch_url, auth=(username, password))
  r.raise_for_status()
  try:
    target_cal = Calendar.from_ical(r.text)
  except ValueError as e:
    print('Warning: Could not parse iCal (%s)' % target_fetch_url,
          file=sys.stderr)
    print(e, file=sys.stderr)
    return

  existing_uids = [e['UID'].to_ical() for e in target_cal.walk('VEVENT')]

  # fetch webcal
  if ics_url.startswith('file://'):
    # Special handling for file:// URLs: substring to strip the file:// prefix,
    # then read it using normal file-reading functionality.
    sourceFile = open(ics_url[7:], 'r')
    sourceContent = sourceFile.read()
    sourceFile.close()
  else:
    sourceRequest = requests.get(ics_url)
    sourceRequest.encoding = 'utf-8'
    sourceContent = sourceRequest.text
    
  c = Calendar.from_ical(sourceContent)

  # import webcal
  imported_uids = []
  for e in c.walk('VEVENT'):
    uid = e['UID'].to_ical()
    cal = Calendar()
    cal.add_component(e)
    r = requests.put('%s/%s.ics' % (base_url, uid),
                     data=cal.to_ical(),
                     auth=(username, password),
                     headers={'content-type':'text/calendar; charset=UTF-8'}
                     )
    if r.status_code == 500 and 'Sabre\VObject\Recur\NoInstancesException' in r.text:
      # ignore the NoInstancesException
      print('Warning: No valid instances: %s' % uid, file=sys.stdout)
    elif r.status_code == 201 or r.status_code == 204:
      print('Imported: %s (%d)' % (uid, r.status_code), file=sys.stdout)
      imported_uids.append(uid)
    else:
      r.raise_for_status()

  # remove events not in webcal
  for uid in existing_uids:
    if not uid in imported_uids:
      r = requests.delete('%s/%s.ics' % (base_url, uid),
                          auth=(username, password))
      if r.status_code == 204:
        print('Deleted %s' % uid, file=sys.stdout)
        # ignore 404 - not found (seems to be a manually created event)
      elif r.status_code == 404:
        pass
      else:
        r.raise_for_status()
Пример #13
0
        out.add_component(c)
    if opts.category:
        if isinstance(ev.get('categories', ''), vText):
            ev['categories'] = [ev['categories']]
        ev.setdefault('categories', []).append(vText(opts.category))
    if opts.status and not 'status' in ev:
        ev['status'] = opts.status.upper()
    out.add_component(ev)
    try:
        old = Calendar.from_ical(open(path, 'rb').read())
    except IOError:
        old = None
        write = True
    else:
        write = hasChanged(old, out)
    if write:
        if not os.path.exists(path):
           added += 1
        else:
           changed += 1
        with open(path, 'wb') as f:
            f.write(out.to_ical())
        porcelain.add(opts.outdir, [str(fname)])

if changed or added:
    porcelain.commit(opts.outdir, 'Processing %s. Updated: %d, new: %d.' %
                     (opts.prefix, changed, added))

logger.info('Processed %s. Seen %d, updated %d, new %d', opts.prefix,
             seen, changed, added)
Пример #14
0
def main():
    semester_selector = "WS20/21"
    # semester_selector = "SS20"

    group_selector = "EuiDE-9-NT1"

    assert (semester_selector[0:2] == "WS" and len(semester_selector)
            == 7) or (semester_selector[0:2] == "SS"
                      and len(semester_selector) == 4)

    timetable_url = timetable_base_url.replace("%semester%",
                                               semester_selector).replace(
                                                   "%group%", group_selector)
    academic_year_url = academic_year_base_url.replace(
        "%year%",
        f"20{int(semester_selector[2:4]) - 1}-{int(semester_selector[2:4])}"
        if semester_selector[0:2] == "SS" else
        f"20{semester_selector[2:7].replace('/', '-')}")

    fp = urllib.request.urlopen(timetable_url)
    mybytes = fp.read()
    html_doc = mybytes.decode("utf-8").replace("<BR>", seperator)
    fp.close()

    fp = urllib.request.urlopen(academic_year_url)
    mybytes = fp.read()
    html_doc2 = mybytes.decode("utf8")
    fp.close()

    academic_year = Calendar.from_ical(html_doc2)

    semester_date_spans = []
    recess_date_spans = []

    for component in academic_year.walk():
        if component.name == 'VEVENT':
            if component['summary'].startswith(
                    expand_semester(semester_selector)):
                semester_date_spans.append(
                    (component['DTSTART'].dt, component['DTEND'].dt))

            if any(r.lower() in component['summary'].lower() for r in recess):
                recess_date_spans.append(
                    (component['DTSTART'].dt, component['DTEND'].dt))

    weekdates_semester = []

    for start_date, end_date in semester_date_spans:
        delta = end_date - start_date
        for i in range(delta.days + 1):
            day = start_date + timedelta(days=i)
            if not day.weekday() == SATURDAY and not day.weekday() == SUNDAY:
                weekdates_semester.append(day)

    recess_dates_semester = []

    for start_date, end_date in recess_date_spans:
        delta = end_date - start_date
        for i in range(delta.days + 1):
            day = start_date + timedelta(days=i)
            if not day.weekday() == SATURDAY and not day.weekday() == SUNDAY:
                recess_dates_semester.append(day)

    dfs = pd.read_html(html_doc)
    dfs = [
        df.applymap(lambda x: x.replace(u"\xa0", u" ")
                    if isinstance(x, str) else x) for df in dfs
    ]

    timetable = dfs[1].values.tolist()

    cal = Calendar()

    index = 2

    class_list = []
    for i, row in enumerate(timetable):
        if i == 0:
            continue
        for j, cell in enumerate(row):
            if j == 0 or isinstance(cell, float):
                continue
            classes = dfs[index].values.tolist()

            for c in classes:
                print(c[0])
                lecturer, name, room, *_ = c[0].split(seperator)
                if not name in class_list:
                    class_list.append(name)
            index += 1

    print("[")
    for c in class_list:
        print(f"    \"{c}\",")
    print("]")

    index = 2

    for i, row in enumerate(timetable):
        if i == 0:
            continue
        for j, cell in enumerate(row):
            if j == 0 or isinstance(cell, float):
                continue

            time_info = timetable[i][0]
            weekday_tt = timetable[0][j]

            classes = dfs[index].values.tolist()

            for c in classes:
                lecturer, name, room, *_ = c[0].split(seperator)
                odd_even, time_start, time_end = time_info.split(seperator)

                time_start_hour, time_start_minutes = [
                    int(x) for x in time_start.split(COLON)
                ]
                time_end_hour, time_end_minutes = [
                    int(x) for x in time_end.split(COLON)
                ]

                if odd_even == "1.WO":
                    week_mod = 1
                elif odd_even == "2.WO":
                    week_mod = 0
                else:
                    print(f"Error. Invalid odd_even identifier {odd_even}")
                    exit()

                for day in weekdates_semester:
                    _, weeknumber, weekday = day.isocalendar()

                    if not weekday - 1 == WEEKDAYS[weekday_tt.lower()]:
                        continue
                    if not weeknumber % 2 == week_mod:
                        continue
                    if any([
                            d.day == day.day and d.month == day.day
                            and d.year == day.year
                            for d in recess_dates_semester
                    ]):
                        continue

                    e = Event()
                    e.add('summary', name)
                    e.add(
                        'dtstart',
                        datetime(day.year,
                                 day.month,
                                 day.day,
                                 time_start_hour,
                                 time_start_minutes,
                                 0,
                                 tzinfo=pytz.timezone("Europe/Berlin")))
                    e.add(
                        'dtstart',
                        datetime(day.year,
                                 day.month,
                                 day.day,
                                 time_end_hour,
                                 time_end_minutes,
                                 0,
                                 tzinfo=pytz.timezone("Europe/Berlin")))
                    e.add('location', room)
                    e.add('description', f"Dozent: {flip_name(lecturer)}")

                    cal.add_component(e)

            index += 1

    print(cal.to_ical().decode('utf-8'))

    with open('my.ics', 'w', encoding='utf-8') as f:
        f.write(cal.to_ical().decode('utf-8'))
Пример #15
0
def create_cal_from_classes(dfs_list, class_list: List[str],
                            semester_selector: str):
    assert (semester_selector[0:2] == "WS" and len(semester_selector)
            == 7) or (semester_selector[0:2] == "SS"
                      and len(semester_selector) == 4)

    academic_year_url = academic_year_base_url.replace(
        "%year%",
        f"20{int(semester_selector[2:4]) - 1}-{int(semester_selector[2:4])}"
        if semester_selector[0:2] == "SS" else
        f"20{semester_selector[2:7].replace('/', '-')}")

    fp = urllib.request.urlopen(academic_year_url)
    mybytes = fp.read()
    html_doc2 = mybytes.decode("utf8")
    fp.close()

    academic_year = Calendar.from_ical(html_doc2)

    semester_date_spans = []
    recess_date_spans = []

    for component in academic_year.walk():
        if component.name == 'VEVENT':
            if component['summary'].startswith(
                    expand_semester(semester_selector)):
                semester_date_spans.append(
                    (component['DTSTART'].dt, component['DTEND'].dt))

            if any(r.lower() in component['summary'].lower() for r in recess):
                recess_date_spans.append(
                    (component['DTSTART'].dt, component['DTEND'].dt))

    weekdates_semester = []

    for start_date, end_date in semester_date_spans:
        delta = end_date - start_date
        for i in range(delta.days + 1):
            day = start_date + timedelta(days=i)
            if not day.weekday() == SATURDAY and not day.weekday() == SUNDAY:
                weekdates_semester.append(day)

    recess_dates_semester = []

    for start_date, end_date in recess_date_spans:
        delta = end_date - start_date
        for i in range(delta.days + 1):
            day = start_date + timedelta(days=i)
            if not day.weekday() == SATURDAY and not day.weekday() == SUNDAY:
                recess_dates_semester.append(day)

    cal = Calendar()
    cal.add("version", 2.0)
    cal.add("prodid", "-//flmann.de//timetable//DE")
    cal.add('x-wr-calname', "Stundenplan")
    cal.add('x-wr-caldesc', "Stundenplan TU Dresden ET")
    cal.add('x-wr-timezone', "Europe/Berlin")

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

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

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

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

    dates_added = set()

    for dfs in dfs_list:
        timetable = dfs[1].values.tolist()
        index = 2

        for i, row in enumerate(timetable):
            if i == 0:
                continue
            for j, cell in enumerate(row):
                if j == 0 or isinstance(cell, float):
                    continue

                time_info = timetable[i][0]
                weekday_tt = timetable[0][j]

                classes = dfs[index].values.tolist()

                for c in classes:
                    lecturer, name, room, *_ = c[0].split(seperator)
                    odd_even, time_start, time_end = time_info.split(seperator)

                    print(f"{name=} {name in class_list}")

                    if not name in class_list:
                        continue

                    time_start_hour, time_start_minutes = [
                        int(x) for x in time_start.split(COLON)
                    ]
                    time_end_hour, time_end_minutes = [
                        int(x) for x in time_end.split(COLON)
                    ]

                    if odd_even == "1.WO":
                        week_mod = 1
                    elif odd_even == "2.WO":
                        week_mod = 0
                    else:
                        print(f"Error. Invalid odd_even identifier {odd_even}")
                        exit()

                    id = f"{c[0]}{time_info}"
                    if id in dates_added:
                        continue
                    dates_added.add(id)

                    for day in weekdates_semester:
                        _, weeknumber, weekday = day.isocalendar()
                        if not weekday - 1 == WEEKDAYS[weekday_tt.lower()]:
                            continue
                        if not weeknumber % 2 == week_mod:
                            continue
                        if any([
                                d.day == day.day and d.month == day.day
                                and d.year == day.year
                                for d in recess_dates_semester
                        ]):
                            continue

                        e = Event()
                        e.add('summary', name)
                        e.add(
                            'dtstart',
                            datetime(day.year,
                                     day.month,
                                     day.day,
                                     time_start_hour,
                                     time_start_minutes,
                                     0,
                                     tzinfo=pytz.timezone("Europe/Berlin")))
                        e.add(
                            'dtend',
                            datetime(day.year,
                                     day.month,
                                     day.day,
                                     time_end_hour,
                                     time_end_minutes,
                                     0,
                                     tzinfo=pytz.timezone("Europe/Berlin")))
                        e.add('dtstamp', datetime.now())
                        e.add('uid', uuid.uuid4())
                        e.add('location', room)
                        e.add('description', f"Dozent: {flip_name(lecturer)}")

                        cal.add_component(e)

                index += 1

    return cal.to_ical().decode('utf-8').replace('\n\n',
                                                 '\n').replace('\r\n', '\n')
Пример #16
0
#!/usr/bin/python

from icalendar.cal import Calendar, FreeBusy
import optparse
import os
import sys

sys.path.insert(0, os.path.dirname(__file__))

from dystros import utils

parser = optparse.OptionParser("travel")
collection_set_options = utils.CollectionSetOptionGroup(parser)
parser.add_option_group(collection_set_options)
opts, args = parser.parse_args()

collections = utils.CollectionSet.from_options(opts)
vevents = collections.iter_vevents()

out = Calendar()
freebusy = FreeBusy()
for vevent in vevents:
    freebusy['UID'] = vevent['UID']
    freebusy['DTSTART'] = vevent['DTSTART']
    freebusy['DTEND'] = vevent['DTEND']
    out.add_component(freebusy)

print out.to_ical()
Пример #17
0
if opts.url:
    props['url'] = vUri(opts.url)
if description is not None:
    props['summary'] = vText(description)
if dtend is not None:
    props['dtend'] = vDate(dtend.date())
if duration is not None:
    props['duration'] = vDuration(duration)

ev = Event(**props)

c = Calendar()
c.add_component(ev)

md5 = hashlib.md5()
md5.update(c.to_ical())

uid = md5.hexdigest()

props['UID'] = uid

fname = uid + '.ics'
path = os.path.join(opts.outputdir, fname)
porcelain.add(opts.outputdir, path)
porcelain.commit(opts.outputdir, 'Add %s.' % description)

with open(path, 'w') as f:
    f.write(c.to_ical())

logging.info('Wrote %s', path)
Пример #18
0
    seen += 1
    (old, todo, new, href, etag, ev) = utils.create_or_update_calendar_item(
        target_collection_url, "VEVENT", uid)
    out = Calendar()
    if import_url is not None:
        out['X-IMPORTED-FROM-URL'] = vUri(import_url)
    # If this is not an iTIP request, then make it one.
    if "METHOD" not in out and opts.invite:
        out["METHOD"] = "REQUEST"
    out.update(list(orig.items()))
    for c in other:
        out.add_component(c)
    if opts.category:
        if isinstance(ev.get('CATEGORIES', ''), vText):
            ev['CATEGORIES'] = [ev['CATEGORIES']]
        ev.setdefault('categories', []).append(vText(opts.category))
    if opts.status and 'STATUS' not in ev:
        ev['STATUS'] = opts.status.upper()
    out.add_component(ev)
    write = hasChanged(old, out)
    if write:
        if old is None:
           added += 1
           utils.add_member(target_collection_url, 'text/calendar', out.to_ical())
        else:
           changed += 1
           utils.put(href, 'text/calendar', out.to_ical(), if_match=[etag])

logger.info('Processed %s. Seen %d, updated %d, new %d', opts.prefix,
             seen, changed, added)
Пример #19
0
url = args[0]
orig = Calendar.from_ical(urllib.urlopen(url).read())

TRACKING_PREFIX = u"You’re tracking this event.\n\n"
GOING_PREFIX = u"You’re going.\n\n"

def fix_vevent(vevent):
    status = None
    if unicode(vevent['DESCRIPTION']).startswith(TRACKING_PREFIX):
        vevent['DESCRIPTION'] = vevent['DESCRIPTION'][len(TRACKING_PREFIX):]
    if unicode(vevent['DESCRIPTION']).startswith(GOING_PREFIX):
        vevent['STATUS'] = 'CONFIRMED'
        vevent['DESCRIPTION'] = vevent['DESCRIPTION'][len(GOING_PREFIX):]
    if unicode(vevent['DESCRIPTION']).startswith(unicode(vevent['URL'])):
        vevent['DESCRIPTION'] = vevent['DESCRIPTION'][len(unicode(vevent['URL'])):]
    if not vevent['DESCRIPTION']:
        del vevent['DESCRIPTION']
    lpts = unicode(vevent['LOCATION']).split(',')
    for i in reversed(range(len(lpts))):
        loc = (' at ' + ','.join(lpts[:i])) + ' (' + vevent['DTSTART'].dt.strftime('%d %b %y') + ')'
        vevent['SUMMARY'] = vevent['SUMMARY'].replace(loc, '')
    return vevent

out = Calendar()
for component in orig.subcomponents:
    if component.name == 'VEVENT':
        component = fix_vevent(component)
    out.add_component(component)

sys.stdout.write(out.to_ical())