X-Git-Url: https://git.ucc.asn.au/?p=frenchie%2Ficalparse.git;a=blobdiff_plain;f=parserrules.py;h=4ba71e8a3544d20e9a5502c22d6d059f9bb2a96a;hp=fb2c67e0648060c1b06918362adf106efd0e4d59;hb=HEAD;hpb=763fc87a8fc530dc8ecfa1d8f0c9fd2b70b5ab3c diff --git a/parserrules.py b/parserrules.py index fb2c67e..7db0413 100644 --- a/parserrules.py +++ b/parserrules.py @@ -1,6 +1,6 @@ #!/usr/bin/python # -# Copyright (c) 2010 James French +# Copyright (c) 2011 James French # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal @@ -20,19 +20,169 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -# This file describes a series of rules which will be called on an ics file as -# rule(key, value) - -# Your functions are expected to return a (key, value) tuple or they will be -# treated as if they don't exist (ie, the line will go through unhindered). -# Returning any boolean false value other than a None will return the line from -# the final iCalendar file +# This file describes a series of rules which must handle a vobject object and +# return it to the calling script # The doc string will be presented to the user when run as verbose, so # please be polite -def markEventsPublic(key, value): - '''Marking private events public''' - # Required as google are strict about the CLASS:PRIVATE/CLASS:CONFIDENTIAL - # lines and Facebook like to set them - if key == 'CLASS': return (key, 'PUBLIC') +import vobject + +ruleConfig = {} +ruleConfig["defaultTZ"] = "UTC" + +def facebookOrganiser(cal): + '''Adds organiser details to the body of facebook calendars.''' + + if 'prodid' in cal.contents: + if not "Facebook" in cal.prodid.value: return cal + + if 'vevent_list' not in dir(cal): + return cal + + for event in cal.vevent_list: + if 'organizer' not in event.contents: continue + try: + a = event.organizer.cn_paramlist + organizer = "Organised by: " + event.organizer.cn_param + " (" + organizer += event.organizer.value.lstrip('MAILTO:') + ")\n\n" + event.description.value = organizer + event.description.value + except AttributeError: + organizer = "Organized by: " + event.organizer.value + event.description.value = organizer + "\n\n" + event.description.value + return cal + +def whatPrivacy(cal): + '''Marks events public so google calendar doesn't have a sad about them.''' + + if 'vevent_list' not in dir(cal): + return cal + + for event in cal.vevent_list: + if 'class' in event.contents: + # Bit of a hack as class is a reserved word in python + del event.contents['class'] + event.add('class').value = "PUBLIC" + + return cal + +def dropAttributes(cal): + '''Removing unwanted metadata''' + if "facebook" in ruleConfig: + if ruleConfig["facebook"] == True: return cal + + if 'vevent_list' not in dir(cal): + return cal + + eventBlacklist = [x.lower() for x in [ + "X-ALT-DESC", + "X-MICROSOFT-CDO-BUSYSTATUS", + "X-MICROSOFT-CDO-IMPORTANCE", + "X-MICROSOFT-DISALLOW-COUNTER", + "X-MS-OLK-ALLOWEXTERNCHECK", + "X-MS-OLK-AUTOSTARTCHECK", + "X-MS-OLK-CONFTYPE", + "X-MS-OLK-AUTOFILLLOCATION", + "TRANSP", + "SEQUENCE", + "PRIORITY" + ]] + + mainBlacklist = [x.lower() for x in [ + "X-CLIPSTART", + "X-CALSTART", + "X-OWNER", + "X-MS-OLK-WKHRSTART", + "X-MS-OLK-WKHREND", + "X-WR-RELCALID", + "X-MS-OLK-WKHRDAYS", + "X-MS-OLK-APPTSEQTIME", + "X-CLIPEND", + "X-CALEND", + "VTIMEZONE", + "X-PRIMARY-CALENDAR" + ]] + + for event in cal.vevent_list: + for blacklist in eventBlacklist: + if blacklist in event.contents: del event.contents[blacklist] + + for blkl in mainBlacklist: + while blkl in cal.contents: del cal.contents[blkl] + + return cal + +def exDate(cal): + '''Replacing multi-value EXDATES with multiple single-value EXDATES''' + if "facebook" in ruleConfig: + if ruleConfig["facebook"] == True: return cal + + if 'vevent_list' not in dir(cal): + return cal + + from datetime import datetime + from pytz import timezone + + default = timezone(ruleConfig["defaultTZ"]) + + for event in cal.vevent_list: + if 'exdate' not in event.contents: continue + dates = event.exdate.value + + del event.contents['exdate'] + + for date in dates: + if isinstance(date, datetime): + if date.tzinfo is None: date = date.replace(tzinfo = default) + date = date.astimezone(vobject.icalendar.utc) + entry = event.add('exdate') + entry.value = [date] + + return cal + +def utcise(cal): + '''Removing local timezones in favour of UTC. If the remote calendar specifies a timezone + then use it, otherwise assume it's in the user-specified or default values''' + + if 'vevent_list' not in dir(cal): + return cal + + from datetime import datetime + from pytz import timezone + + default = timezone(ruleConfig["defaultTZ"]) + + for event in cal.vevent_list: + dtstart = getattr(event, 'dtstart', None) + dtend = getattr(event, 'dtend', None) + + for i in (dtstart, dtend): + if not i: continue + dt = i.value + if isinstance(dt, datetime): + if dt.tzinfo is None: dt = dt.replace(tzinfo = default) + i.value = dt.astimezone(vobject.icalendar.utc) + + return cal + +def unwantedParams(cal): + '''Removing unwanted parameters''' + + blklist = [ + "LANGUAGE", + "X-VOBJ-ORIGINAL-TZID", + "TZID" + ] + + if 'vevent_list' not in dir(cal): + return cal + + for event in cal.vevent_list: + for attr in event.contents: + attr = getattr(event, attr) + try: + for i in blklist: + while i in attr.params: del attr.params[i] + except AttributeError: continue + + return cal