diff --git a/ical_aggregator/ical_aggregator.py b/ical_aggregator/ical_aggregator.py new file mode 100755 index 0000000..42e910b --- /dev/null +++ b/ical_aggregator/ical_aggregator.py @@ -0,0 +1,112 @@ +#!/usr/bin/env python +# +# vevent keys: url, uid, summary, locations, category, description + +import urllib +import vobject +import sys +import os + +EVENT_KEYS = ["uid", "url", "location", "categories", "summary", "description", "dtstart" , "dtstamp"] +UNIQUE_KEY = ["dtstart", "summary"] + + +def get_syntax(): + return "Syntax: %s ICAL_SOURCES_FILE FINISHED_FILE AUTH_FILE" % (os.path.basename(sys.argv[0])) + + +def get_unique_id(event): + unique_values = [] + for one_val in UNIQUE_KEY: + unique_values.append(unicode(event[one_val])) + return encode_safely(";".join(unique_values)) + + +def encode_safely(text): + return text.encode("iso-8859-15", "replace") + + +def convert_event_to_dict(event): + result = {} + for key in EVENT_KEYS: + # convert lists to a string + value = event.getChildValue(key) + if isinstance(value, list): + value = " ,".join(value) + result[key] = value + return result + + +def fetch_ical(url): + result = [] + try: + handle = urllib.urlopen(url) + content = handle.read() + handle.close() + except IOError, err_msg: + sys.stderr.write("Failed to parse iCal file (%s): %s\n" % (url, err_msg)) + return [] + events = vobject.readComponents(content) + for top_child in events: + for child in top_child.components(): + result.append(convert_event_to_dict(child)) + return result + + +def add_to_processed_list(fileout, event): + fileout.write(get_unique_id(event) + "\n") + + +def submit_event_to_drupal(event): + print "Added event: %s" % encode_safely(event["summary"]) + return True + + +if __name__ == "__main__": + if len(sys.argv) != 4: + sys.stderr.write(get_syntax() + "\n") + sys.exit(1) + + ICAL_SOURCES_FILE = sys.argv[1] + FINISHED_FILE = sys.argv[2] + AUTH_FILE = sys.argv[3] + + # read the file of iCal URLs to be sourced + try: + ical_file = file(ICAL_SOURCES_FILE) + ical_urls = ical_file.read().splitlines() + ical_file.close() + except IOError, err_msg: + sys.write("Failed to open iCal source URL file (%s): %s\n" % (ICAL_SOURCES_FILE, err_msg)) + sys.exit(2) + + finished_items = [] + # read the file of processed events + if os.path.isfile(FINISHED_FILE): + try: + finished_file = file(FINISHED_FILE) + finished_items.extend(finished_file.read().splitlines()) + finished_file.close() + except IOError, err_msg: + sys.write("Failed to open file for finished items (%s) for reading: %s\n" % (FINISHED_FILE, err_msg)) + sys.exit(3) + # reopen the file for appending + try: + finished_file = file(FINISHED_FILE, "a") + except IOError, err_msg: + sys.write("Failed to open file for finished items (%s) for appending: %s\n" % (FINISHED_FILE, err_msg)) + sys.exit(4) + + icals = [] + for ical_url in ical_urls: + icals.extend(fetch_ical(ical_url)) + + for event in icals: + if not get_unique_id(event) in finished_items: + # process new events + if submit_event_to_drupal(event): + add_to_processed_list(finished_file, event) + finished_items.append(get_unique_id(event)) + + finished_file.close() +