diff --git a/birthdays-cal.py b/birthdays-cal.py new file mode 100644 index 0000000..f7deb65 --- /dev/null +++ b/birthdays-cal.py @@ -0,0 +1,114 @@ + +# -*- coding: utf-8 -*- + +import sys +import yaml +import datetime +import hashlib +from icalendar import Calendar, Event + +one_day = datetime.date(1, 1, 2) - datetime.date(1, 1, 1) + +event_config = {'description': '', 'categories': '', 'language': ''} + + +def load_config(): + result = dict() + with open('config.yml', 'r', encoding='utf-8') as f: + result = yaml.load(f) + return result + + +def write_calendar(cal, filename): + with open(filename, 'wb') as f: + f.write(cal.to_ical()) + + +def parse_dates(birthdays): + for item in birthdays: + person = item['person'] + birthday_str = person['birthday'] + if len(birthday_str) == 5: + person['birthday_no_year'] = True + birthday_str = birthday_str.replace(birthday_str[2], '.') + birthday_str = birthday_str + '.0001' + person['birthday'] = datetime.datetime.strptime( + birthday_str, '%d.%m.%Y').date() + + +def display(cal): + print(cal.to_ical().decode('utf-8')) + + +def sha1(string): + if isinstance(string, str): + string = string.encode('utf8') + h = hashlib.sha1() + h.update(string) + return h.hexdigest() + + +def age(person, year): + return abs(year - person['birthday'].year) + + +def make_event(person, year): + event_date = person['birthday'].replace(year=year) + description = event_config['description'] + + lang_params = {'language': event_config['language']} + + if 'birthday_no_year' not in person: + description += ', %d' % age(person, year) + + event = Event() + event.add('uid', sha1(person['name'] + ' birthday ' + str(year))) + event.add('summary', person['name'], + encode=True, parameters=lang_params) + event.add('description', description, encode=True, parameters=lang_params) + event.add('categories', event_config['categories']) + event.add('transp', 'TRANSPARENT') + event.add('dtstamp', datetime.datetime( + event_date.year, event_date.month, event_date.day)) + event.add('dtstart', event_date) + event.add('duration', one_day) + return event + + +def add_events(cal, birthdays, year): + for item in birthdays: + event = make_event(item['person'], year) + cal.add_component(event) + + +def make_calendar(calname, timezone, birthdays, scale): + cal = Calendar() + cal.add('version', '2.0') + cal.add('prodid', '-//birthdays calendar generator//b4tman.ru//') + cal.add('calscale', 'GREGORIAN') + cal.add('method', 'PUBLISH') + cal.add('x-wr-timezone', timezone) + cal.add('x-wr-calname', calname) + for year in range(scale['start'], scale['start'] + scale['length']): + add_events(cal, birthdays, year) + return cal + + +config = load_config() +birthdays = config['birthdays'] + +event_config['language'] = config['language'] +event_config['description'] = config['events']['description'] +event_config['categories'] = config['events']['categories'] + +parse_dates(birthdays) +birthdays.sort(key=lambda x: x['person']['birthday'].strftime('%m.%d')) + +cal = make_calendar(config['calname'], + config['timezone'], birthdays, config['scale']) + +if len(sys.argv) > 1: + filename = sys.argv[1] + write_calendar(cal, filename) +else: + display(cal)