Beispiel #1
0
def test_issue_188_timezone_dropped():
    assert "DTSTART;TZID={tzid}:20200121T070000".format(tzid=Timezone.from_tzid("Europe/Berlin").tzid) in Calendar(fixture1).serialize()
    assert "DTSTART;TZID={tzid}:20200121T070000".format(tzid="W. Europe Standard Time") in Calendar(fixture2).serialize()
    assert "DTSTART;TZID={tzid}:20200121T070000".format(tzid="Europe/Berlin") in Calendar(fixture3).serialize()

    pacific = Timezone.from_tzid("US/Pacific")
    assert pacific.tzid.endswith("America/Los_Angeles")

    event1 = Event(begin=datetime(2014, 1, 1, 0, 0, 0, tzinfo=gettz("US/Pacific")))
    event1.dtstamp = event1.dtstamp.replace(microsecond=0)
    ser1 = Calendar(events=[event1]).serialize()
    assert "DTSTART:20140101T000000Z" not in ser1
    assert "DTSTART;TZID=%s:20140101T000000" % pacific.tzid in ser1

    event2 = event1.clone()
    event2.begin = datetime(2014, 1, 1, 0, 0, 0, tzinfo=pacific)
    ser2 = Calendar(events=[event1]).serialize()
    assert "DTSTART:20140101T000000Z" not in ser2
    assert "DTSTART;TZID=%s:20140101T000000" % pacific.tzid in ser2

    assert event1 == event2
    assert event1.begin == event2.begin
    assert event1.begin.tzinfo != event2.begin.tzinfo
    assert ser1 == ser2
    deser1 = Calendar(ser1).events[0]
    deser2 = Calendar(ser2).events[0]
    assert deser1 == deser2
    assert deser1 == event2
def main():
    """
    :return: None
    :rtype: None
    """
    ics_url, file, wiki, debug = get_args()
    event_strings = []
    past_events = []

    if file:
        calendar = Calendar(deradicalise_ical(open(file).read()))
    else:
        ics_result = requests.get(ics_url)
        ics_result.encoding = 'utf-8'
        calendar = Calendar(deradicalise_ical(ics_result.text))

    for event in sorted(calendar.events, key=lambda ev: ev.begin):
        event = EntropiaEvent(event)
        if not event.is_past_event:
            event_strings.append("\n" + LINE_SEPARATOR + str(event))
        else:
            past_events.append(event)

    append_past_events(past_events, wiki['user'], wiki['pass'],
                       wiki['archive'])
    termine = BOTWARNING + "\n" + TABLE_HEADER + "\n" + "".join(
        event_strings) + "\n" + "".join(TABLE_FOOTER)
    if debug:
        print(termine)
    site = Site('entropia.de', path='/')
    site.login(wiki['user'], wiki['pass'])
    page = site.pages[wiki['page']]
    if termine:
        page.save(termine, "Terminbot was here")
        page.purge()
Beispiel #3
0
def merge_calendars(filenames, output='all.ics'):
    """
    Given a list of ics filenames, merge calendars together into combined cal.

    Arguments:
    filenames -- A list of .ics files in current working directory to merge
                (list)
    output -- Name of ICS file to output (str) (optional)
    """
    new_cal = Calendar()

    new_cal.extra.append(ContentLine(name='X-WR-CALNAME', value='KQB All'))
    new_cal.extra.append(
        ContentLine(
            name='X-WR-CALDESC',
            value='All matches and events in the Killer Queen Black community.'
        ))
    new_cal.extra.append(ContentLine(name='X-PUBLISHED-TTL', value='PT15M'))
    new_cal.extra.append(ContentLine(name='TZNAME', value='UTC'))

    existing_calendars = []

    for file in filenames:
        with open(file) as f:
            existing_calendars.append(Calendar(f.read()))

    for calendar in existing_calendars:
        for event in calendar.events:
            new_cal.events.add(event)

    with open(output, 'w') as cal_file:
        cal_file.writelines(new_cal)
Beispiel #4
0
def read_google_ics(ics_url):
    """
    Fetch events directly from Google calendar ICS file
    """
    events = []
    try:
        calendar = Calendar(unidecode(requests.get(ics_url).text))
    except:
        calendar = Calendar(
            unidecode(urlopen(ics_url).read().decode('iso-8859-1')))
    for event in calendar.events:
        if event.begin.year >= datetime.today().year:
            date = event.begin.strftime('%d-%m-%Y')
            starttime = event.begin.strftime("%I:%M %p")
            endtime = event.end.strftime("%I:%M %p")
            description = event.description
            description = BeautifulSoup(description, 'html.parser').get_text(
                '\n') if description is not None else ''
            title = event.name
            events.append({
                'title': title,
                #Speaker set later
                'date': date,
                #Location set later
                'description': description,
                'starttime': starttime,
                'endtime': endtime,
                #Owner and URL set later
            })
    return events
Beispiel #5
0
def get_difference_in_calendars(old, new):
    """Get the dates in which an old and new Calendar differ.
    An Event differs if it is not included in the other calendar
    
    Arguments:
        old {str} -- The old calendar
        new {str} -- The new calendar
    
    Returns:
        list(str) -- A list of unique dates in DD.MM.YYYY format
    """
    changed_dates = []
    old_cal = Calendar(old)
    new_cal = Calendar(new)
    old_events = old_cal.events
    new_events = new_cal.events
    for event in old_events:
        if event not in new_events:
            changed_dates.append(event.begin.format("DD.MM.YYYY"))
    for event in new_events:
        if event not in old_events:
            changed_dates.append(event.begin.format("DD.MM.YYYY"))

    changed_dates = list(set(changed_dates))
    changed_dates.sort(key=lambda date: datetime.strptime(date, '%d.%m.%Y'))
    print(changed_dates)
    return changed_dates
Beispiel #6
0
def test_issue_181_timezone_ignored():
    cal1 = Calendar(fixture1)
    cal2 = Calendar(fixture2)
    cal3 = Calendar(fixture3)
    begin1 = cal1.events[0].begin
    begin2 = cal2.events[0].begin
    begin3 = cal3.events[0].begin
    tzinfo1 = begin1.tzinfo
    tzinfo2 = begin2.tzinfo
    tzinfo3 = begin3.tzinfo
    assert isinstance(tzinfo1, Timezone)
    assert tzinfo1 == Timezone.from_tzid("Europe/Berlin")
    assert tzinfo1.tzid.endswith("Europe/Berlin")
    assert tzinfo1.tzname(begin1) == "CET"
    assert tzinfo1.utcoffset(begin1) == timedelta(hours=1)
    assert isinstance(tzinfo2, Timezone)
    assert tzinfo2 == Timezone.from_container(lines_to_container(fixture2_tz))
    assert tzinfo2.tzid == "W. Europe Standard Time"
    assert tzinfo2.tzname(begin2) == "MEZ"
    assert tzinfo2.utcoffset(begin2) == timedelta(hours=1)
    assert isinstance(tzinfo3, Timezone)
    assert tzinfo3 == Timezone.from_container(lines_to_container(fixture3_tz))
    assert tzinfo3.tzid == "Europe/Berlin"
    assert tzinfo3.tzname(begin3) == "MEZ"
    assert tzinfo3.utcoffset(begin3) == timedelta(hours=8)
    def index(self,
              calendar=None,
              filter=None,
              find="",
              replacement=None,
              t=0):
        """ Retrieve calendar, reduce to events matching filter and apply find/replace """
        if calendar:
            if t == 0:
                cherrypy.response.headers['Content-Type'] = 'text/calendar'
            else:
                cherrypy.response.headers['Content-Type'] = 'text/plain'
            # Create new calendar to copy events into
            new_cal = Calendar()
            calendar = calendar.replace('webcal', 'http')
            c = Calendar(urlopen(calendar).read().decode('iso-8859-1'))

            if "," in filter:
                keywords = filter.split(',')
            else:
                keywords = [filter]
            print keywords
            for event in c.events:
                for keyword in keywords:
                    if keyword.lower() in event.name.lower():
                        if replacement:
                            event.name = event.name.replace(find, replacement)
                        new_cal.events.append(event)
            return new_cal
        else:
            return """
Beispiel #8
0
def load_cal(entry: dict) -> Calendar:
    """Load the calendar from the cache or from remote according to the entry.  If the calendar is supposed to be in
    cached but could not be found in cache, an error is thrown


    :param entry: representation of the entry to cache.  This is the Python representation of the corresponding entry
    in the config file
    :type entry: dict


    :return: the calendar corresponding to the entry
    :rtype: Calendar


    :raises FileNotfoundError: if the entry was supposed to be cached but has not been cached before
    """

    if "cache" in entry and entry["cache"]:
        print("Getting", entry["name"], "from cache")
        try:
            return get_from_cache(entry)
        except FileNotFoundError:
            return Calendar()

    else:
        print("Getting", entry["name"], "from remote")
        r = requests.get(entry["url"], allow_redirects=True)
        if "encoding" in entry:
            cal = Calendar(imports=r.content.decode(
                encoding=entry["encoding"]))
        else:
            cal = Calendar(imports=r.content.decode())

        cal = horodate(cal, 'Downloaded at')
        return cal
Beispiel #9
0
def create_calendar(token, enrollment_id, options):
    file_list = []
    if options['academicCal'] or options['careerCal']:
        academic_calendar = Calendar()
        career_calendar = Calendar()
        for sess in get_sessions(token, enrollment_id)['calendarSessions']:
            e = Event()
            if (sess['context']['id'] == 1) and options['academicCal']:
                start_time = datetime.strptime(sess['session']['startTime'], '%Y-%m-%dT%H:%M:%SZ')
                end_time = datetime.strptime(sess['session']['endTime'], '%Y-%m-%dT%H:%M:%SZ')
                e.name = str(sess['session']['chapter']) + ': ' + sess['session']['name']
                e.transparent = True if options['academicIsTrans'] else False
                if options['officeHours']:
                    e.begin = start_time - timedelta(minutes=45)
                    e.end = end_time + timedelta(minutes=30)
                else:
                    e.begin = start_time
                    e.end = end_time
                academic_calendar.events.add(e)

            elif (sess['context']['id'] == 2) and options['careerCal']:
                e.name = sess['session']['name']
                e.begin = sess['session']['startTime']
                e.end = sess['session']['endTime']
                e.transparent = True if options['careerIsTrans'] else False
                career_calendar.events.add(e)

        if len(academic_calendar.events) > 0:
            academic_file_name = str(enrollment_id) + '-academic-calendar'
            academic_file_name = academic_file_name + '-oh.ics' if options['officeHours'] else academic_file_name + '.ics'
            file_list.append(academic_file_name)
            with open('files/' + academic_file_name, 'w') as f:
                f.writelines(academic_calendar)

        if len(career_calendar.events) > 0:
            career_file_name = str(enrollment_id) + '-career-calendar.ics'
            file_list.append(career_file_name)
            with open('files/' + career_file_name, 'w') as f:
                f.writelines(career_calendar)

    if options['assignmentCal']:
        assignment_calendar = Calendar()
        for assignment in get_assignments(token, enrollment_id)['calendarAssignments']:
            e = Event()
            if assignment['context']['id'] == 1:
                e.name = assignment['title']
                e.begin = datetime.strptime(assignment['effectiveDueDate'], '%Y-%m-%dT%H:%M:%SZ') - timedelta(days=1)
                e.end = datetime.strptime(assignment['effectiveDueDate'], '%Y-%m-%dT%H:%M:%SZ') - timedelta(days=1)
                e.make_all_day()
                e.transparent = True if options['assignmentsIsTrans'] else False
                assignment_calendar.events.add(e)
        assignment_file_name = str(enrollment_id) + '-assignment-calendar.ics'
        file_list.append(assignment_file_name)
        with open('files/' + assignment_file_name, 'w') as f:
            f.writelines(assignment_calendar)

    return file_list
Beispiel #10
0
def generate_ics(event_sources, future_only=True):
    calendar = Calendar()
    all_events = list(itertools.chain(*event_sources))

    if future_only:
        all_events = [
            event for event in all_events if event.begin.date() >= datetime.date.today()
        ]

    calendar = Calendar()
    for event in all_events:
        calendar.events.add(event)
    return calendar
Beispiel #11
0
def main():
    with open(SOURCES_PATH) as f:
        content = list(filter(lambda z: len(z) > 0, map(lambda x: x.split('#')[0].strip(), f.readlines())))

    new_c = Calendar()
    for source in content:
        cal_text = requests.get(source).text
        c = Calendar(cal_text)
        new_c.events.update(c.events)

    with open(OUT_PATH, "w") as f:
        f.write(str(new_c))

    print(f"Saved new calendar to `{OUT_PATH}``")
Beispiel #12
0
def main():
    with open(SOURCES_PATH) as f:
        content = f.readlines()
    content = [x.strip() for x in content]

    new_c = Calendar()
    for source in content:
        c = Calendar(requests.get(source).text)
        new_c.events.update(c.events)

    with open("out.ics", "w") as f:
        f.write(str(c))

    print(f"Saved new calendar to `{OUT_PATH}``")
Beispiel #13
0
def create_ics(sender, instance, **kwargs):
    c = Calendar()
    alarm = [DisplayAlarm(trigger=timedelta(minutes=30))]

    e = Event()
    e.name = instance.title
    e.begin = instance.date
    e.end = instance.dateend
    e.alarms = alarm
    if instance.duration != None:
        e.duration = instance.duration
    if (instance.cost == 0 or instance.cost == None):
        cost = 'Бесплатно'
        e.description = str(instance.intro) + ' Стоимость: ' + str(cost)
    else:
        e.description = str(instance.intro) + ' Стоимость: ' + str(instance.cost)+  'р.'
    e.location = instance.location
    if instance.timepad != None:
        e.url = instance.timepad
    c.events.add(e)

    instance.ics.delete(save=False)
    instance.ics.save(instance.title +'.ics', ContentFile(str(c)), save=True)
    #Формирование глобального файла со всеми мероприятиями
    global_ics = EventIndex.objects.all()[0]
    events = global_ics.get_children()
    c = Calendar()
    for event in events:
        if (event.specific.date < timezone.now()):
            pass
        else:
            e = Event()
            e.name = event.title
            e.begin = event.specific.date
            e.end = event.specific.dateend
            e.alarms = alarm
            if event.specific.duration != None:
                e.duration = event.specific.duration
            if (event.specific.cost == 0 or event.specific.cost == None):
                cost = 'Бесплатно'
                e.description = str(event.specific.intro.strip("<p>*</p>")) + ' Стоимость: ' + str(cost)
            else:
                e.description = str(event.specific.intro.strip("<p>*</p>")) + ' Стоимость: ' + str(event.specific.cost)+  'р.'
            e.location = event.specific.location
            if event.specific.timepad != None:
                e.url = event.specific.timepad
            c.events.add(e)
    global_ics.calenadar_file.delete(save=False)
    global_ics.calenadar_file.save('global.ics', ContentFile(str(c)), save=True)
Beispiel #14
0
def cache(entry: dict, scheduler: sched.scheduler = None) -> None:
    """Cache an .ics feed in the app/cache directory.
    Different entries with the same URL will be cached in the same file.
    The cached calendar contains a new line in the description with the current time when cached prefixed by the
    'Cached at' mention



    :param entry: representation of the entry to cache.  This is the Python representation of the corresponding entry
    in the config file
    :type entry: dict

    :param scheduler: scheduler used to relaunch the caching task in the future.  If not scheduler is specified,
    the task will not be relaunched
    :type scheduler: sched.scheduler
    """

    try:
        if not os.path.isdir('app/cache'):
            os.mkdir('app/cache')

        url = entry['url']
        path = "app/cache/" + sha256(url.encode()).hexdigest() + ".ics"

        r = requests.get(entry["url"], allow_redirects=True)

        if "encoding" in entry:
            cal = Calendar(imports=r.content.decode(encoding=entry["encoding"]))
        else:
            cal = Calendar(imports=r.content.decode())

        cal = horodate(cal, 'Cached at')
        open(path, 'w').writelines(cal)
        print(arrow.now().format("YYYY-MM-DD HH:mm:ss"), "Cached", entry['name'])

    except FailedParse:
        print("Could not parse", entry['name'])

    # Save stack trace when an unknown error occurs
    except Exception as e:
        with open("error " + arrow.now().format("YYYY-MM-DD HH:mm:ss")+".txt", 'w') as file:
            file.write(arrow.now().format("YYYY-MM-DD HH:mm:ss") + "\nCould not cache : " + str(entry))
            file.write(str(e))
            file.write(str(traceback.format_exc()))
    finally:
        if scheduler is not None:
            delay = entry['cache'] if entry['cache'] > 0 else 10
            delay *= 60
            scheduler.enter(delay=delay, priority=1, action=cache, argument=(entry, scheduler))
Beispiel #15
0
    def handle_sncf_message(self, message):
        payload = list(message.walk())[1].get_payload()
        payload = payload.replace("\r", "").replace("\n",
                                                    "").replace("=20", "")
        root = fromstring(
            quopri.decodestring(payload).decode("latin1").replace(
                "\t", "").replace("\n", "").replace('\\xa0', ' '))
        departure_city, _, arrival_city, _, seat_info, duration, _ = [
            r.replace("\xa0", " ") for r in root.xpath(
                "//table/tr/td/table/tr/td/table/tr/td/span/text()")
        ]
        departure_time, train_id, ticket_id, arrival_time = [
            r.replace("\xa0", " ") for r in root.xpath(
                "//table/tr/td/table/tr/td/table/tr/td/span/b/text()")
        ]
        departure_date = [
            r.replace("\xa0", " ") for r in root.xpath(
                "//html/body/table/tr/td/table/tr/td/span/text()")
        ]

        c = None
        target_file = os.path.join(self.output_dir, "calendar.ics")

        if os.path.isfile(target_file):
            with open(target_file, "r") as f:
                c = Calendar(f.read())
        if c is None:
            c = Calendar()

        e = Event()
        e.name = "%s: %s -> %s [%s]" % (train_id, departure_city, arrival_city,
                                        ticket_id)
        e.begin = dateparser.parse("%s %s CEST" %
                                   (departure_date, departure_time),
                                   languages=["fr"])
        e.end = dateparser.parse("%s %s CEST    " %
                                 (departure_date, arrival_time),
                                 languages=["fr"])
        e.location = departure_city
        e.description = "%s" % seat_info

        #weird. sometimes it's list, sometime it's set...
        if type(c.events) is list:
            c.events.append(e)
        else:
            c.events.add(e)

        with open(target_file, 'w') as f:
            f.writelines(c)
def handler(event, context):
    try:
        opener = urllib2.build_opener()
        opener.addheaders = [('User-agent', 'Mozilla/5.0')]
        ics = opener.open(iCalURL).read().decode('iso-8859-1')
        c = Calendar(ics)
        lock_code_updated = False
        delete_code = False
        print "Server Local Time: {0}".format(arrow.now())
        print "Server UTC Time: {0}".format(arrow.utcnow())        
        now = arrow.utcnow().to('US/Eastern')
        print "Server UTC Converted to Eastern time: {0}".format(now)
        print "Starting compare of events"
        for event in c.events:
            eventTitle = event.name
            if not lock_code_updated and eventTitle != "Not available":
                begin = event.begin.replace(hour=CheckinHour, minute=0, second=0, tzinfo='US/Eastern')
                end = event.end.replace(hour=CheckOutHour, minute=30, second=0, tzinfo='US/Eastern')
                description = event.description
                print "Comparing Title:{} - Now:{} to EventBegin:{} with EventEnd:{}".format(eventTitle, now, begin, end)
                if now.date() == begin.date():
                    phone = get_phone(description)
                    lock_code = phone[-4:]
                    print "Setting lock code to {0} for {1}".format(lock_code, eventTitle)
                    set_lock_code(lock_code, eventTitle)
                    lock_code_updated = True
                elif now > end and end.date() == now.date():
                    delete_code=True
        if delete_code and not lock_code_updated:
            print "Guest's stay ended today.  Deleting Lock Code"
            delete_lock_code()
        return {'Lock Code Updated': lock_code_updated}
    except Exception as ex:
        print ex
        return False
Beispiel #17
0
def getAvailableBlocks(ical_links, date_range, time_range):
    # Build list of calendars of events
    cals = []  # list of calendars from iCal links

    # Iterative through each user's ical link
    for link in ical_links:
        # Append calendar, extracting only dates within given date_range
        cals.append(
            Calendar(requests.get(link).text).timeline.included(
                arrow.get(date_range[0]), arrow.get(date_range[1])))

    # Build list of datetime tuples from calendar events
    dt_blocks = []

    # convert each ical link into calendar
    for i, cal in enumerate(cals):
        dt_blocks.append([])
        for event in cal:
            begin = datetime.fromtimestamp(event.begin.timestamp)
            end = datetime.fromtimestamp(event.end.timestamp)

            dt_blocks[i].append((begin, end))

    final = set(fillDuration(date_range, time_range))

    # subtract each user's calendar from the filled timeline
    for blocks in dt_blocks:
        final = subtract(final, blocks)

    # for f in sorted(final):
    #     print(f)

    return list(final)
Beispiel #18
0
    def get_current_event(content: str, include_all_day: bool):
        calendar = Calendar(content)

        if calendar is None:
            return None
        temp_event = None
        for event in calendar.timeline.at(utcnow()):
            if event.all_day and not include_all_day:
                continue
            if temp_event is None:
                temp_event = event
            elif temp_event.end > event.end:
                temp_event = event

        if temp_event is None:
            return None

        return {
            "summary": temp_event.name,
            "start": parser_ics.get_hass_date(temp_event.begin,
                                              temp_event.all_day),
            "end": parser_ics.get_hass_date(temp_event.end,
                                            temp_event.all_day),
            "location": temp_event.location,
            "description": temp_event.description,
        }
Beispiel #19
0
    def get_event_list(content: str, start, end, include_all_day: bool):
        event_list = []

        calendar = Calendar(re.sub(parser_ics.re_method, "", content))

        if calendar is not None:
            ar_start = arrowget(start)
            ar_end = arrowget(end)

            for event in calendar.timeline.included(ar_start, ar_end):
                if event.all_day and not include_all_day:
                    continue
                uid = None
                if hasattr(event, "uid"):
                    uid = event.uid
                data = {
                    "uid":
                    uid,
                    "summary":
                    event.name,
                    "start":
                    parser_ics.get_date_formatted(event.begin, event.all_day),
                    "end":
                    parser_ics.get_date_formatted(event.end, event.all_day),
                    "location":
                    event.location,
                    "description":
                    event.description,
                }
                # Note that we return a formatted date for start and end here,
                # but a different format for get_current_event!
                event_list.append(data)

        return event_list