<?xml version="1.0" encoding="UTF-8" ?>
<EventGhost Name="Configuration Tree" Expanded="True" Version="1462" Guid="{2C7CC41B-AFB1-4B8F-A0A0-650DC993CE90}" Time="1288786671.29">
    <Autostart Name="Autostart" Expanded="True">
        <Action Name="Watch gCal" Enabled="False">
            EventGhost.PythonScript(u'#This piece of code will trigger events in EG according to what is stored in\n#some google calendars.\n#Full desccription of it can be found in eventghost forums : http://www.eventghost.org/forum/viewtopic.php?f=2&amp;t=2881\n#You can freely use it, distribute it, modify it, but don\'t forget : it\'s my code !\n#So please be kind enough to keep me informed if you post it elsewhere or if you just\n#modify it.\n#Since I am not really fluent with python, it have spent a lot of time to make\n#this work. So if you would like to send me a big "thank you" :\n#-paypal : miljbee at gmail dot com\n#-flattr : http://flattr.com/thing/80135/Get-EG-events-from-Google-Calendar\n#this is the first realease, let\'s call it gCalEG 1.0\n\nimport xml.dom.minidom\nimport urllib2\nimport time\nimport calendar\n\n#simple log system\ndef logThis(msg,level):\n    if eg.globals.gCal_logLevel&gt;=level:\n        print msg\n\n#basic functions to extract data from xml\n#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\ndef GetEltsByTagName(nodeXML,eltTagName):\n    #extract a node from nodeXML. Returns Only level 1 nodes (if eltsXML[x].parentNode.isSameNode(nodeXML):)\n    logThis("Running GetEltsByTagName with params :",4)\n    logThis("nodeXML :" + nodeXML.toxml(),4)\n    logThis("eltTagName :" + eltTagName,4)\n    eltsXML=nodeXML.getElementsByTagName(eltTagName)\n    result=[e for e in eltsXML if e.parentNode.isSameNode(nodeXML)]\n    logThis("Exiting GetEltsByTagName and returning " + str(result),4)\n    return result\n\ndef GetEltData(XML,EltTagName):\n    #extract data from an xmlNode\n    logThis("Running GetEltData with params :",4)\n    logThis("XML :" + XML.toxml(),4)\n    logThis("EltTagName :" + EltTagName,4)\n\n    eltXML=GetEltsByTagName(XML,EltTagName)[0]\n    if len(eltXML.childNodes)!=0:\n        result=eltXML.childNodes[0].data\n    else:\n        result=""\n    logThis("Exiting GetEltData and returning " + str(result),4)\n    return result\n\ndef GetEltAttribute(XML,EltTagName,AttrName):\n    #extract attribute data from an xmlNode\n    logThis("Running GetEltAttribute with params : ",4)\n    logThis("XML :" + XML.toxml(),4)\n    logThis("EltTagName :" + EltTagName,4)\n    logThis("AttrName :" + AttrName,4)\n    eltsXML=GetEltsByTagName(XML,EltTagName)\n    result=""\n    if len(eltsXML)&gt;0:\n        eltXML=eltsXML[0]\n        if eltXML.hasAttribute(AttrName):\n            result = eltXML.getAttribute(AttrName)\n    logThis("Exiting GetEltAttribute and returning " + str(result),4)\n    return result\n#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\n    \n#Talking with google\n#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\ndef SetUpProxy():\n    logThis("Running SetUpProxy",4)\n    passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm()\n    passmgr.add_password(None, \'http://yourProxy.hisDomain:hisPort\', \'username\', \'password\')\n    authinfo = urllib2.ProxyBasicAuthHandler(passmgr)\n    proxy_support = urllib2.ProxyHandler({"http" : "http://yourProxy.hisDomain:hisPort"})\n    \n    opener = urllib2.build_opener(proxy_support, authinfo)\n    urllib2.install_opener(opener)\n    logThis("Exiting SetUpProxy",4)\n\ndef GetGCalEventsByDateXML(gCalPrivateURL,startTime,endTime):\n    logThis("Running GetGCalEventsByDateXML",4)\n    #Params desc is here : http://code.google.com/intl/fr/apis/calendar/data/2.0/reference.html#Parameters\n    paramsString = "?orderby=starttime&amp;"\n    paramsString += "sortorder=a&amp;"\n    paramsString += \'start-min=\'+GetTimeRFC3339(startTime)+"&amp;"\n    paramsString += \'start-max=\'+GetTimeRFC3339(endTime)+"&amp;"\n    paramsString += \'singleevents=true&amp;\'\n    paramsString += \'showhidden=true&amp;\'\n    paramsString += \'ctz=UTC\'\n    \n    gCalFullUrl=gCalPrivateURL+paramsString\n    try:\n        result = urllib2.urlopen(gCalFullUrl)\n        resultTXT = result.read()\n        logThis(resultTXT,3)\n        result.close()\n        resultXML=xml.dom.minidom.parseString(resultTXT)\n        feed=resultXML.getElementsByTagName("feed")[0]\n        logThis("Exiting GetGCalEventsByDateXML and returning : " + feed.toxml(),4)\n    except IOError, e:\n        logThis("GetGCalEventsByDateXML : Pb while requesting google, Please check your internet connection and your private URLs or use an alternate scheduller ! ...",0)\n        if hasattr(e, \'reason\'):\n            logThis("GetGCalEventsByDateXML : exception reason = " + str(e.reason),3)\n        if hasattr(e, \'code\'):\n            logThis("GetGCalEventsByDateXML : exception code = " + str(e.code),3)\n        feed=None\n        logThis("Exiting GetGCalEventsByDateXML and returning : None (oups!)",4)\n    return feed\n#:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::\n    \n#Extracting data from google calendar requests\ndef GetGCalNbResults(gCalXML):\n    logThis("Running GetGCalNbResults with param " + gCalXML.toxml(),4)\n    result=int(GetEltData(gCalXML,"openSearch:totalResults"))\n    logThis("Exiting GetGCalNbResults and returning " + str(result),4)\n    return result\n\ndef GetGCalTitle(gCalXML):\n    result=GetEltData(gCalXML,"title")\n    return result\n\ndef GetGCalNthEntry(gCalXML,nth):\n    logThis("Running GetGCalNthEntry with params :",4)\n    logThis("gCalXML : " + gCalXML.toxml(),4)\n    logThis("nth : " + str(nth),4)\n    result=GetEltsByTagName(gCalXML,"entry")[nth]\n    logThis("Exiting GetGCalNthEntry and returning " + result.toxml(),4)\n    return result\n\n#Get details from entries returned by google\ndef GetEntryTitle(entryXML):\n    logThis("Running GetEntryTitle with param " + entryXML.toxml(),4)\n    result=GetEltData(entryXML,"title")\n    logThis("Exiting GetEntryTitle and returning" + result,4)\n    return result\n\ndef GetEntryContent(entryXML):\n    logThis("Running GetEntryContent with param " + entryXML.toxml(),4)\n    result=GetEltData(entryXML,"content")\n    logThis("Exiting GetEntryContent and returning" + result,4)\n    return result\n\ndef GetEntryLocation(entryXML):\n    logThis("Running GetEntryLocation with param " + entryXML.toxml(),4)\n    result=GetEltAttribute(entryXML,"gd:where","valueString")\n    logThis("Exiting GetEntryLocation and returning" + result,4)\n    return result\n\ndef GetEntryTime(entryXML,startEnd):\n    logThis("Running GetEntryTime with param :",4)\n    logThis("entryXML=" + entryXML.toxml(),4)\n    logThis("startEnd=" + startEnd,4)\n    if startEnd=="start": timeString=GetEltAttribute(entryXML,"gd:when","startTime")\n    elif startEnd=="end": timeString=GetEltAttribute(entryXML,"gd:when","endTime")\n    else: timeString=""\n    if timeString!="":\n        try:\n            time_Struct_UTC=time.strptime(timeString[:-1]+"UTC", \'%Y-%m-%dT%H:%M:%S.%f%Z\')\n        except ValueError:\n            logThis("GetEntryTime : warning time="+timeString,4)\n            timeString+="T00:00:00.000"\n            logThis("GetEntryTime : replacing time="+timeString,4)\n            time_Struct_Local=time.strptime(timeString, \'%Y-%m-%dT%H:%M:%S.%f\')\n            time_EpochSecs=time.mktime(time_Struct_Local)\n            time_Struct_UTC=time.gmtime(time_EpochSecs)\n        time_EpochSecs=calendar.timegm(time_Struct_UTC)\n        result=time.localtime(time_EpochSecs) #struct with local tz\n    else:\n        result=""\n    logThis("Exiting GetEntryTime and returning" + str(result),4)\n    return result\n\n#Storing locally data retrieved from google\n#events in google calendars are stored in a python dict.\n#The keys of the dict are gCalTitle.entryTitle\n#The entries are also python dict withs keys as attributes (entry["startTime"] will give you the starttime)\ndef GetGCalEvents(gCalXML,now_Struct_UTC):\n    #Builds a list of gCalEvents from the xml feed. Output doesn\'t contain any xml\n    #See next func for details on how events are stored\n    logThis("Running GetGCalEvents with params : ",4)\n    logThis("gCalXML = "+gCalXML.toxml(),4)\n    logThis("now_Struct_UTC = "+str(now_Struct_UTC),4)\n    result={}\n    for x in range(0,GetGCalNbResults(gCalXML)):\n        evt=GetGCalEvent(GetGCalNthEntry(gCalXML,x),now_Struct_UTC)\n        if evt:\n            evt["gCalTitle"]=GetGCalTitle(gCalXML)\n            result[evt["gCalTitle"]+"."+evt["title"]]=evt\n    logThis("Exiting GetGCalEvents and returning " + str(result),4)\n    return result\n\ndef GetGCalEvent(gCalEntryXML,now_Struct_UTC):\n    #Builds a list of the attributes of an event : output doesn\'t contain any XML\n    logThis("Running GetGCalEvent with params : ",4)\n    logThis("gCalEntryXML = "+gCalEntryXML.toxml(),4)\n    logThis("now_Struct_UTC = "+str(now_Struct_UTC),4)\n    #if you want to include only particular events or exclude some other, you can do this here\n    #exemple (will retain only events that starts with "something"):\n    #if entryTitle[:len("something")]=="something":\n        #result=dict(title=entryTitle,content=comment,location=location,startTime=startTime,endTime=endTime,isCurrent=isCurrent)\n    #else: result=None\n    entryTitle = GetEntryTitle(gCalEntryXML)\n    comment = GetEntryContent(gCalEntryXML)\n    location = GetEntryLocation(gCalEntryXML)\n    startTime = GetEntryTime(gCalEntryXML,"start")\n    endTime = GetEntryTime(gCalEntryXML,"end")\n    isCurrent=(time.mktime(startTime)&lt;=calendar.timegm(now_Struct_UTC) and time.mktime(endTime)&gt;calendar.timegm(now_Struct_UTC))\n    result=dict(title=entryTitle,content=comment,location=location,startTime=startTime,endTime=endTime,isCurrent=isCurrent)\n    logThis("Exiting GetGCalEvent and returning " + str(result),4)\n    return result\n    \ndef GetTimeRFC3339(epochSecs):\n    #converts time from epoch secs to RFC3339 which is the one google expect\n    logThis("Running GetTimeRFC3339 with param epochSecs = "+str(epochSecs),4)\n    struct_UTC=time.gmtime(epochSecs)\n    result=time.strftime("%Y-%m-%dT%H:%M:%Sz",struct_UTC)\n    logThis("Exiting GetTimeRFC3339 and returning " + str(result),4)\n    return result\n    \n#will return the nearest futur event start/end date/time\ndef GetNextSchedule(gCalEvents,now_EpochSecs):\n    logThis("Running GetNextSchedule with params : ",4)\n    logThis("gCalEvents : " + str(gCalEvents),4)\n    logThis("now_EpochSecs : " + str(now_EpochSecs),4)\n    \n    nextSched_EpochSecs=now_EpochSecs+eg.globals.gCal_checkEvery\n    for k in gCalEvents.keys():\n        someTime_EpochSecs=time.mktime(gCalEvents[k]["startTime"])\n        if someTime_EpochSecs&gt;now_EpochSecs and someTime_EpochSecs&lt;nextSched_EpochSecs:\n            nextSched_EpochSecs=someTime_EpochSecs\n        someTime_EpochSecs=time.mktime(gCalEvents[k]["endTime"])\n        if someTime_EpochSecs&gt;now_EpochSecs and someTime_EpochSecs&lt;nextSched_EpochSecs:\n            nextSched_EpochSecs=someTime_EpochSecs\n    result=nextSched_EpochSecs\n    logThis("Exiting GetNextSchedule and returning " + str(result),4)\n    return result\n\n#Trigger events in EG if needed\ndef TriggerEgEvents(gCalEvents):\n    logThis("Running TriggerEgEvents with param " + str(gCalEvents),4)\n\n    currentEventsFromGCal=dict((k,gCalEvents[k]) for k in gCalEvents if gCalEvents[k]["isCurrent"])\n    newEvents=dict((k,currentEventsFromGCal[k]) for k in currentEventsFromGCal if k not in eg.globals.gCal_currentEvents)\n    pastEvents=dict((k,eg.globals.gCal_currentEvents[k]) for k in eg.globals.gCal_currentEvents if k not in currentEventsFromGCal)\n    eg.globals.gCal_currentEvents=currentEventsFromGCal\n    \n    logThis("Current Events from gCal " + str(currentEventsFromGCal.keys()),3)\n    logThis("New Events from gCal " + str(newEvents.keys()),3)\n    logThis("Past Events from gCal " + str(pastEvents.keys()),3)\n\n    if eg.globals.gCal_fireEvent.find("OnStart")&gt;=0:\n        for evt in newEvents.itervalues():\n            eg.TriggerEvent(evt["gCalTitle"]+"."+evt["title"]+".Start", None, \'gCal\')\n    if eg.globals.gCal_fireEvent.find("OnEnd")&gt;=0:\n        for evt in pastEvents.itervalues():\n            eg.TriggerEvent(evt["gCalTitle"]+"."+evt["title"]+".End", None, \'gCal\')\n            \n    logThis("Exiting TriggerEgEvents",4)\n\n#Gets XML from google, read result, store and arrange entries, compare with what is stored locally, \n#generate EG events if there is diffs between local entries and google entries,\n#compute next check date, schedule next check\ndef WatchGCal():\n    logThis("Running WatchGCal",4)\n    eg.globals.gCal_watchTask=None\n    #SetUpProxy()\n\n    now_Epoch_Secs=time.time()\n    now_Struct_UTC=time.gmtime(now_Epoch_Secs)\n    \n    gCalEvents={}\n    for x in range(0,len(eg.globals.gCal_privateURLs)):\n        gCalPrivateUrl=eg.globals.gCal_privateURLs[x]\n        gCalXML=GetGCalEventsByDateXML(gCalPrivateUrl,now_Epoch_Secs,now_Epoch_Secs+eg.globals.gCal_checkEvery)\n        if gCalXML!=None:\n            gCalEvents.update(GetGCalEvents(gCalXML,now_Struct_UTC))\n            \n    for evt in gCalEvents.values():\n        if evt["isCurrent"]:logLevel=1\n        else:logLevel=2\n        logThis("title : " + evt["title"],logLevel)\n        logThis("   location : " + evt["location"],logLevel)\n        logThis("   comment : " + evt["content"],logLevel)\n        logThis("   Starts on : " + time.strftime("%d/%m/%Y %H:%M:%S",evt["startTime"]),logLevel)\n        logThis("   Ends on : " + time.strftime("%d/%m/%Y %H:%M:%S",evt["endTime"]),logLevel)\n        logThis("   is Current : " + str(evt["isCurrent"]),logLevel)\n        logThis("   Calendar Title : " + str(evt["gCalTitle"]),logLevel)\n            \n    TriggerEgEvents(gCalEvents)\n    eg.globals.gCal_nextCheck=GetNextSchedule(gCalEvents,now_Epoch_Secs)\n    logThis("Next check will occur on :" + time.strftime("%d/%m/%Y %H:%M:%S",time.localtime(eg.globals.gCal_nextCheck)),3)\n    if eg.globals.gCal_watch:\n        eg.globals.gCal_watchTask=eg.scheduler.AddTaskAbsolute(eg.globals.gCal_nextCheck, WatchGCal)\n    logThis("Exiting WatchGCal",4)\n\n#A Simple list of the privates URL of the google calendars you want to monitor\neg.globals.gCal_privateURLs=[]\n#The following URL are just here to show you what they looks like. They don\'t work, this is just random data.\n#You have to replace them with the private URL of your Google calendar(s).\n#You get these URL in the setting page of your google Calendar.\n#To get it, click the last "XML" orange button at the bottom of the setting page of the google Calendar.\n#Once you have it, replace the last "/basic" with "/full" and paste her the full URL\neg.globals.gCal_privateURLs.append(\'http://www.google.com/calendar/feeds/qb6q9h164p3u8uep5n65auoluo%40group.calendar.google.com/private-f64ac8e8c04n40c4926bdb3d51640472/full\')\neg.globals.gCal_privateURLs.append(\'http://www.google.com/calendar/feeds/ftv1livsfssqml3045lo47tklo%40group.calendar.google.com/private-45bc3cd7d912ed54fa3d6447224daec1/full\')\neg.globals.gCal_privateURLs.append(\'http://www.google.com/calendar/feeds/fejn1o16ta1q6cepv6m7bohncc%40group.calendar.google.com/private-f8179a0d16a131630110b58826a5fg34/full\')\neg.globals.gCal_checkEvery=300 #will check your calendars every 5 minutes (300s) max, don\'t worry, you will get the event at its exact time, even if you set up several hours here\neg.globals.gCal_fireEvent="OnStart_OnEnd"\n#eg.globals.gCal_fireEvent="OnStart" if you just want an event in eg when the google entry starts\n#eg.globals.gCal_fireEvent="OnEnd" if you just want an event in eg when the google entry ends\n#eg.globals.gCal_fireEvent="" if you just don\'t want any event in eg !\n\neg.globals.gCal_currentEvents={} #the events from gCal whic are occuring Now will be stored there\neg.globals.gCal_nextCheck=None #date/time of the next check\neg.globals.gCal_watchTask=None #for eg.CancelTask\neg.globals.gCal_watch=True #To stop the process\neg.globals.gCal_logLevel=0 #0=no log;1=display current events;2=display all retrieved events;3=2+a few techie info;4=3+will fill your log window in less than one sec\n\nWatchGCal()')
        </Action>
    </Autostart>
    <Folder Name="gCal" Expanded="True">
        <Macro Name="Display nextCheckDate" Expanded="True">
            <Action Name="Display nextCheck Date">
                EventGhost.PythonScript(u'import time\nprint time.strftime("%d/%m/%Y %H:%M:%S",time.localtime(eg.globals.gCal_nextCheck))')
            </Action>
        </Macro>
        <Macro Name="Display Current Events" Expanded="True">
            <Action Name="Display Current Events">
                EventGhost.PythonScript(u'import time\nfor evt in eg.globals.gCal_currentEvents.values():\n    if evt["isCurrent"]:logLevel=1\n    else:logLevel=2\n    print "Title : " + evt["title"]\n    print "   - Location : " + evt["location"]\n    print "   - Content : " + evt["content"]\n    print "   - Starts on : " + time.strftime("%d/%m/%Y %H:%M:%S",evt["startTime"])\n    print "   - Ends on : " + time.strftime("%d/%m/%Y %H:%M:%S",evt["endTime"])\n    print "   - is Current : " + str(evt["isCurrent"])\n    print "   - Calendar Title : " + str(evt["gCalTitle"])\n\n')
            </Action>
        </Macro>
        <Macro Name="Cancel WatchGCal" Expanded="True">
            <Action Name="Cancel WatchGCal">
                EventGhost.PythonScript(u'if eg.globals.gCal_watchTask:\n    eg.scheduler.CancelTask(eg.globals.gCal_watchTask)\n    eg.globals.gCal_watch=False\nelse:\n    print "Can not Cancel !"\n    eg.globals.gCal_watch=False')
            </Action>
        </Macro>
    </Folder>
</EventGhost>
