示例#1
0
文件: fb2cal.py 项目: ppiacez/fb2cal
def populate_birthdays_calendar(birthdays):
    """ Populate a birthdays calendar using birthday objects """

    c = Calendar()
    c.scale = 'GREGORIAN'
    c.method = 'PUBLISH'
    c.creator = f'fb2cal v{__version__} ({__status__}) [{__website__}]'
    c.extra.append(
        ContentLine(name='X-WR-CALNAME', value='Facebook Birthdays (fb2cal)'))
    c.extra.append(ContentLine(name='X-PUBLISHED-TTL', value='PT12H'))
    c.extra.append(
        ContentLine(name='X-ORIGINAL-URL', value='/events/birthdays/'))

    cur_date = datetime.now()

    for birthday in birthdays:
        e = Event()
        e.uid = birthday.uid
        e.name = f"{birthday.name}'s Birthday"

        # Calculate the year as this year or next year based on if its past current month or not
        # Also pad day, month with leading zeros to 2dp
        year = cur_date.year if birthday.month >= cur_date.month else (
            cur_date + relativedelta(years=1)).year
        month = '{:02d}'.format(birthday.month)
        day = '{:02d}'.format(birthday.day)
        e.begin = f'{year}-{month}-{day} 00:00:00'
        e.make_all_day()
        e.duration = timedelta(days=1)
        e.extra.append(ContentLine(name='RRULE', value='FREQ=YEARLY'))

        c.events.add(e)

    return c
示例#2
0
def populate_birthdays_calendar(birthdays):
    """ Populate a birthdays calendar using birthday objects """

    c = Calendar()
    c.scale = 'GREGORIAN'
    c.method = 'PUBLISH'
    c.creator = f'fb2cal v{__version__} ({__status__}) [{__website__}]'
    c.extra.append(
        ContentLine(name='X-WR-CALNAME', value='Facebook Birthdays (fb2cal)'))
    c.extra.append(ContentLine(name='X-PUBLISHED-TTL', value='PT12H'))
    c.extra.append(
        ContentLine(name='X-ORIGINAL-URL', value='/events/birthdays/'))

    cur_date = datetime.now()
    backburner = []
    rearrange = False

    logger.info("Saving birthdays to local cache...")
    with open('birthdays.pkl', 'wb') as pkl_file:
        pickle.dump(birthdays, pkl_file)
        logger.info("Saved to cache (src/birthdays.pkl)")

    for birthday_i in range(0, len(birthdays)):

        birthday = birthdays[birthday_i]

        if (birthday.month == 2 and birthday.day == 29):
            rearrange = True
            backburner.append(birthday)
            del birthdays[birthday_i]
            birthday_i -= 1
            continue
        if rearrange:
            if not (birthday.month == 2 and birthday.day == 28):
                birthdays.insert(birthday_i, backburner)
                rearrange = False
                birthday_i -= 1
                continue

        e = Event()
        e.uid = birthday.uid
        e.name = f"{birthday.name}'s Birthday"

        # Calculate the year as this year or next year based on if its past current month or not
        # Also pad day, month with leading zeros to 2dp
        year = cur_date.year if birthday.month >= cur_date.month else (
            cur_date + relativedelta(years=1)).year
        month = '{:02d}'.format(birthday.month)
        day = '{:02d}'.format(birthday.day)
        e.begin = f'{year}-{month}-{day} 00:00:00'
        e.make_all_day()
        e.duration = timedelta(days=1)
        e.extra.append(ContentLine(name='RRULE', value='FREQ=YEARLY'))

        c.events.add(e)

    return c
示例#3
0
    def generate(self):
        c = Calendar()
        c.scale = 'GREGORIAN'
        c.method = 'PUBLISH'
        c.creator = f'fb2cal v{__version__} ({__status__}) [{__website__}]'
        c.extra.append(
            ContentLine(name='X-WR-CALNAME',
                        value='Facebook Birthdays (fb2cal)'))
        c.extra.append(ContentLine(name='X-PUBLISHED-TTL', value='PT12H'))
        c.extra.append(
            ContentLine(name='X-ORIGINAL-URL', value='/events/birthdays/'))

        cur_date = datetime.now()

        for facebook_user in self.facebook_users:
            # Don't add extra 's' if name already ends with 's'
            formatted_username = f"{facebook_user.name}'s" if facebook_user.name[
                -1] != 's' else f"{facebook_user.name}'"
            formatted_username = f'{formatted_username} Birthday'

            # Set date components
            day = facebook_user.birthday_day
            month = facebook_user.birthday_month
            year = facebook_user.birthday_year

            # Feb 29 special case:
            # If event year is not a leap year, use Feb 28 as birthday date instead
            if facebook_user.birthday_month == 2 and facebook_user.birthday_day == 29 and not calendar.isleap(
                    year):
                day = 28

            # The birth year may not be visible due to privacy settings
            # In this case, calculate the year as this year or next year based on if its past current month or not
            if year is None:
                year = cur_date.year if facebook_user.birthday_month >= cur_date.month else (
                    cur_date + relativedelta(years=1)).year

            # Format date components as needed
            month = f'{month:02}'
            day = f'{day:02}'

            # Event meta data
            e = Event()

            e.uid = facebook_user.id
            e.name = formatted_username
            e.created = cur_date
            e.description = f'{facebook_user}\n{generate_facebook_profile_url_permalink(facebook_user)}'
            e.begin = f'{year}-{month}-{day} 00:00:00'
            e.make_all_day()
            e.duration = timedelta(days=1)
            e.extra.append(ContentLine(name='RRULE', value='FREQ=YEARLY'))

            c.events.add(e)

        self.birthday_calendar = c
示例#4
0
def populate_birthdays_calendar(birthdays):
    """ Populate a birthdays calendar using birthday objects """

    c = Calendar()
    c.scale = 'GREGORIAN'
    c.method = 'PUBLISH'
    c.creator = f'fb2cal v{__version__} ({__status__}) [{__website__}]'
    c.extra.append(
        ContentLine(name='X-WR-CALNAME', value='Facebook Birthdays (fb2cal)'))
    c.extra.append(ContentLine(name='X-PUBLISHED-TTL', value='PT12H'))
    c.extra.append(
        ContentLine(name='X-ORIGINAL-URL', value='/events/birthdays/'))

    cur_date = datetime.now()

    for birthday in birthdays:
        e = Event()
        e.uid = birthday.uid
        e.name = f"{birthday.name}'s Birthday"

        # Calculate the year as this year or next year based on if its past current month or not
        # Also pad day, month with leading zeros to 2dp
        year = cur_date.year if birthday.month >= cur_date.month else (
            cur_date + relativedelta(years=1)).year
        month = '{:02d}'.format(birthday.month)
        day = '{:02d}'.format(birthday.day)
        try:
            e.begin = f'{year}-{month}-{day} 00:00:00'
        except ValueError as err:
            # Check if this is due to leap year. If so, move to Feb 28.
            if birthday.month == 2 and birthday.day == 29:
                day = '{:02d}'.format(birthday.day - 1)
                logger.warning(
                    f"{birthday.name}'s birthday landed on a missing leap day. Moving 1 day earlier ({year}-{month}-{day}) instead."
                )
                e.begin = f'{year}-{month}-{day} 00:00:00'
            else:
                raise err
        e.make_all_day()
        e.duration = timedelta(days=1)
        e.extra.append(ContentLine(name='RRULE', value='FREQ=YEARLY'))

        c.events.add(e)

    return c
示例#5
0
    def generate(self):
        c = Calendar()
        c.scale = 'GREGORIAN'
        c.method = 'PUBLISH'
        c.creator = f'fb2cal v{__version__} ({__status__}) [{__website__}]'
        c.extra.append(
            ContentLine(name='X-WR-CALNAME',
                        value='Facebook Birthdays (fb2cal)'))
        c.extra.append(ContentLine(name='X-PUBLISHED-TTL', value='PT12H'))
        c.extra.append(
            ContentLine(name='X-ORIGINAL-URL', value='/events/birthdays/'))

        cur_date = datetime.now()

        for facebook_user in self.facebook_users:
            e = Event()
            e.uid = facebook_user.id
            e.created = cur_date

            # Don't add extra 's' if name already ends with 's'
            formatted_username = f"{facebook_user.name}'s" if facebook_user.name[
                -1] != 's' else f"{facebook_user.name}'"
            e.name = f"{formatted_username} Birthday"

            # Calculate the year as this year or next year based on if its past current month or not
            # Also pad day, month with leading zeros to 2dp
            year = cur_date.year if facebook_user.birthday_month >= cur_date.month else (
                cur_date + relativedelta(years=1)).year

            # Feb 29 special case:
            # If event year is not a leap year, use Feb 28 as birthday date instead
            if facebook_user.birthday_month == 2 and facebook_user.birthday_day == 29 and not calendar.isleap(
                    year):
                facebook_user.birthday_day = 28

            month = '{:02d}'.format(facebook_user.birthday_month)
            day = '{:02d}'.format(facebook_user.birthday_day)
            e.begin = f'{year}-{month}-{day} 00:00:00'
            e.make_all_day()
            e.duration = timedelta(days=1)
            e.extra.append(ContentLine(name='RRULE', value='FREQ=YEARLY'))

            c.events.add(e)

        self.birthday_calendar = c
示例#6
0
def calendar_for_branch(branch):
    events = fetch_next_days_for_branch(branch)

    cal_events = [calendar_event_for_event(branch, e) for e in events]

    cal = Calendar(events=cal_events, creator="sfymca")
    cal.method = "PUBLISH"
    cal.scale = "GREGORIAN"

    lines = str(cal).split("\r\n")
    indicies = [i for i, s in enumerate(lines) if s.startswith("BEGIN:")]

    if len(indicies) > 1:
        second_index = indicies[1]
        lines.insert(second_index, f"X-WR-CALNAME:{branch.name} YMCA Pool")
        lines.insert(second_index + 1, "X-WR-TIMEZONE:America/Los_Angeles")

    return "\r\n".join(lines)
示例#7
0
def ics_parser(bday_info_tuple, enable_date_swap):

    # Set calender info.
    c = Calendar()
    c.scale = 'GREGORIAN'
    c.method = 'PUBLISH'
    c.creator = 'Hardeep Singh Narang @hardeepnarang10'
    c._unused.append(ContentLine(name='X-WR-CALNAME', params={}, value='Facebook Birthdays Calendar (fb2ics)'))
    c._unused.append(ContentLine(name='X-PUBLISHED-TTL', params={}, value='PT12H'))
    c._unused.append(ContentLine(name='X-ORIGINAL-URL', params={}, value='/events/birthdays/'))

    # Get present date.
    present_date = datetime.now()

    # Process and add individual Events to the Calender object.
    for each_tuple in bday_info_tuple:
        # Calculate year for next birthday.
        # Add padding for day and month (2 digits - leading zero).
        tuple_date = each_tuple[2]
        year = present_date.year if int(tuple_date[0:tuple_date.index('/')]) >= present_date.month else (present_date + relativedelta(years=1)).year

        if enable_date_swap:
            day = '{:02d}'.format(int(tuple_date[0:tuple_date.index('/')]))
            month = '{:02d}'.format(int(tuple_date[tuple_date.index('/') + 1:]))
        else:
            month = '{:02d}'.format(int(tuple_date[0:tuple_date.index('/')]))
            day = '{:02d}'.format(int(tuple_date[tuple_date.index('/')+1:]))

        # Create Event object.
        e = Event()
        e.uid = each_tuple[0]
        e.name = f"{each_tuple[1]}'s Birthday!"
        e.description = "Facebook friend's birthday! Wish them well!"
        e.begin = f'{year}-{month}-{day} 00:00:00'
        e.make_all_day()
        e.duration = timedelta(days=1)
        e._unused.append(ContentLine(name='RRULE', params={}, value='FREQ=YEARLY'))

        c.events.add(e)

    return c
示例#8
0
文件: ical.py 项目: Olen/Spond
async def main():
    s = spond.Spond(username=username, password=password)
    c = Calendar()
    c.method = 'PUBLISH'
    events = await s.getEvents()
    for event in events:
        e = Event()
        e.uid = event['id']
        e.name = event['heading']
        e.description = event['description']
        e.begin = event['startTimestamp']
        e.end = event['endTimestamp']
        e.sequence = event['updated']
        if 'cancelled' in event and event['cancelled']:
            e.status = 'Cancelled'
        if 'location' in event:
            e.location = "{}, {}".format(event['location']['feature'], event['location']['address'])
        c.events.add(e)
    with open(ics_file, 'w') as out_file:
        out_file.writelines(c)
    await s.clientsession.close()
示例#9
0
def ProcessEventsintoICS(root, xpath, eventcount, namePrefix, synonymPrefix,
                         locationPrefix):
    # if no prefix then just look for location
    if (namePrefix):
        # also add the eventor message location if available
        if (synonymPrefix):
            xpath += " | /EventList/Event[(starts-with(Name,'{0}')) or (starts-with(Name,'{1}'))]/HashTableEntry[(Key='Eventor_Message') and contains(Value,'{2}') ]/Value".format(
                namePrefix, synonymPrefix, locationPrefix)
        else:
            xpath += " | /EventList/Event[starts-with(Name,'{0}')]/HashTableEntry[(Key='Eventor_Message') and contains(Value, '{1}'}) ]/Value".format(
                namePrefix, locationPrefix)
    else:
        xpath += " | /EventList/Event/HashTableEntry[(Key='Eventor_Message') and contains(Value, '{0}') ]/Value".format(
            locationPrefix)

    eventids = root.xpath(xpath)
    locCount = len(eventids) - eventcount
    print("Found {0} locations".format(locCount))

    # create a list of event locations
    eventdata = {}

    # for each event then add a location based on the eventid
    for eventid in eventids:
        if (eventid.tag == 'EventId'):
            eventdata[eventid.text] = ""
            lasteventid = eventid.text
        if (eventid.tag == "Value"):
            # default is no location
            location = "location unknown (not found in the eventor message)"
            # look for end of lines
            if "\n" in eventid.text:
                # split into lines looking for location
                eventormessagelines = eventid.text.split('\n')
                for line in eventormessagelines:
                    if (line.startswith(locationPrefix)):
                        location = line.replace(locationPrefix, "")
                        break
            else:
                # look in the text for prefix
                if locationPrefix in eventid.text:
                    location = eventid.text.replace(locationPrefix, "")
            eventdata[lasteventid] = location

    # now the locations are extracted properly add each location to an event in the calendar
    from ics import Calendar
    mainCal = None
    for key, value in eventdata.items():
        # get the calendar from eventor
        icsURL = "https://eventor.orienteering.asn.au/Events/ICalendar/{0}".format(
            key)
        print("Reading ICS file for event id {0}".format(key))
        c = Calendar(requests.get(icsURL).text)

        # create main calendar if it doesn't exist
        if mainCal is None:
            mainCal = c
            for event in c.events:
                event.location = value
        else:
            for event in c.events:
                event.location = value
                mainCal.events.add(event)
        # for the calendar to be used it must be published
        c.method = "PUBLISH"
        # TODO: add in  X-WR-CALNAME e.g. "Sydney Summer Series Season 29 "Map Running Sydney"

    print("Writing combined {0} events".format(len(mainCal.events)))

    if (namePrefix):
        filename = namePrefix
    else:
        filename = "OrganisationEvents"

    with open('{0}.ics'.format(filename), 'w', newline='') as f:
        f.writelines(mainCal)
        print(str(mainCal))
示例#10
0
def ical(request):

    # This should be a comma-separated list with values corresponding to
    # Committee's abbreviation_short field.
    abbreviations = request.GET.get(
        'committee', '').split(',') if 'committee' in request.GET else []

    committees = Committee.objects.filter(
        parliaments__parliament_num=CURRENT_PARLIAMENT_NUM)

    if len(abbreviations) > 0:
        committees = committees.filter(abbreviation_short__in=abbreviations)

    cal = Calendar()
    cal.creator = '-//Alþingi//NONSGML Fastanefndir Alþingis//IS'
    cal.scale = 'GREGORIAN'
    cal.method = 'PUBLISH'

    agendas = CommitteeAgenda.objects.select_related(
        'committee').prefetch_related('committee_agenda_items').filter(
            parliament__parliament_num=CURRENT_PARLIAMENT_NUM,
            committee__in=committees).order_by('timing_start_planned')

    for agenda in agendas:
        # Short-hand.
        agenda_id = agenda.committee_agenda_xml_id

        description = 'Dagskrá:\n\n'
        for item in agenda.committee_agenda_items.select_related(
                'issue__parliament'):
            description += '%d. %s\n' % (item.order, capfirst(item.name))
            # Add URL of issue, if any.
            if item.issue is not None:
                description += '%s\n' % external_issue_url(
                    item.issue.parliament.parliament_num, item.issue.issue_num)
            description += '\n'

        event = Event()
        event.uid = '*****@*****.**' % agenda_id
        event.name = capfirst(agenda.committee.name)
        event.description = description
        event.begin = agenda.timing_start_planned
        event.end = agenda.timing_end
        event.url = 'https://www.althingi.is/thingnefndir/dagskra-nefndarfunda/?nfaerslunr=%d' % agenda_id

        # Committee agendas are never planned at midnight (or damn well
        # hopefully not). So when a committee agenda is planned without a time
        # factor, or in other words, is timed at midnight, we'll assume that
        # the timing is actually not precisely determined and turn it into an
        # all-day event instead, using the timing text (determined below) to
        # elaborate instead.
        if event.begin.hour == 0 and event.begin.minute == 0 and event.begin.second == 0:
            event.make_all_day()

        if agenda.timing_text:
            # If agenda.timing_text is just a representation of what is
            # already known from the planned starting time, we'll want to
            # nullify it so that we don't clutter the name with it
            # unnecessarily. To do this, we have to re-construct the text that
            # is typically provided and compare it against agenda.timing_text.
            # If they match, we won't include it. If they don't match, then
            # what's provided in agenda.timing_text is presumably more
            # meaningful than simply a (badly) reformatted version of
            # agenda.timing_start_planned.

            timing = agenda.timing_start_planned

            day = timing.day
            month_name = ICELANDIC_MONTHS[timing.month]
            year = str(timing.year)[2:]
            time = timing.strftime('%-I:%M')
            am_pm = icelandic_am_pm(timing)

            # Known inconsistencies are whether there is a space in the
            # beginning, and whether there is one space or two between "kl."
            # and the time-of-day. We strip and replace to compensate.
            timing_text_test = '%d. %s %s, kl. %s %s' % (day, month_name, year,
                                                         time, am_pm)
            if agenda.timing_text.strip().replace('  ',
                                                  ' ') != timing_text_test:
                event.name += ' (%s)' % agenda.timing_text.strip()

        cal.events.add(event)

    ical_text = monkey_patch_ical(
        cal.__str__(), 'Fastanefndir Alþingis',
        'Dagatal sem inniheldur boðaða fundi fastanefnda Alþingis ásamt dagskrá í lýsingu.',
        'Reykjavik/Iceland', 'PT10M')

    if request.GET.get('plaintext', False):
        content_type = 'text/plain'
    else:
        content_type = 'text/calendar'

    return HttpResponse(ical_text,
                        content_type='%s; charset=utf-8' % content_type)