view multimerge.py @ 1:74f172565752

Initial import.
author Matti Hamalainen <ccr@tnsp.org>
date Mon, 04 Jul 2016 12:49:37 +0300
parents
children 34c3a08a4a37
line wrap: on
line source

#!/usr/bin/python
import os
import sys
import signal
import re
import time
import datetime
import httplib2
import ConfigParser
import oauth2client
from oauth2client import client
from oauth2client import tools
from googleapiclient import discovery


###
### Misc. helper functions
###

## Wrapper for print() that does not break when redirecting stdin/out
## because of piped output not having a defined encoding. We default
## to UTF-8 encoding in output here.
def gcm_print(smsg):
    gcm_msgbuf.append(smsg.encode("UTF-8"))
    if sys.stdout.encoding != None:
        print(smsg.encode(sys.stdout.encoding))
    else:
        print(smsg.encode("UTF-8"))


## Fatal errors
def gcm_fatal(smsg):
    gcm_print(u"ERROR: "+ smsg)
    sys.exit(1)


## Debug messages
def gcm_debug(smsg):
    if cfg.debug:
        gcm_print(u"DBG: "+ smsg)
    else:
        gcm_msgbuf.append(u"DBG: "+ smsg.encode("UTF-8"))


## Handle SIGINT signals here
def gcm_signal_handler(signal, frame):
    gcm_print("\nQuitting due to SIGINT / Ctrl+C!")
    sys.exit(0)


def gcm_get_credentials(mcfg):
    store = oauth2client.file.Storage(mcfg.credential_file)
    credentials = store.get()
    if not credentials or credentials.invalid:
        flow = client.flow_from_clientsecrets(mcfg.secret_file, mcfg.scope)
        flow.user_agent = mcfg.app_name
        credentials = tools.run_flow(flow, store, mcfg)
    if not credentials or credentials.invalid:
        gcm_fatal("Failed to authenticate / invalid credentials.")
    return credentials


def gcm_dump_events(events):
    for event in events:
        ev_start = event["start"].get("dateTime", event["start"].get("date"))
        ev_end = event["end"].get("dateTime", event["end"].get("date"))
        gcm_print(u"{0:25} - {1:25} : {2}".format(ev_start, ev_end, event["summary"]))


class GCMSettings(dict):
    def __init__(self):
        self.m_data = {}
        self.m_saveable = {}
        self.m_translate = {}

    def __getattr__(self, name):
        if name in self.m_data:
            return self.m_data[name]
        else:
            gcm_fatal("GCMSettings.__getattr__(): No such attribute '"+ name +"'.")

    def mtranslate(self, name, value):
        if name in self.m_translate and self.m_translate[name]:
            return self.m_translate[name](value)
        else:
            return value

    def mdef(self, name, saveable, validate, translate, value):
        self.m_saveable[name] = saveable
        self.m_data[name] = self.mtranslate(name, value)

    def mset(self, name, value):
        if name in self.m_data:
            self.m_data[name] = self.mtranslate(name, value)
        else:
            gcm_fatal("GCMSettings.mset(): No such attribute '"+ name +"'.")

    def mget(self, name):
        if name in self.m_data:
            return self.m_data[name]
        else:
            return None


###
### Main program starts
###
gcm_msgbuf = []
signal.signal(signal.SIGINT, gcm_signal_handler)


## Settings
cfg = GCMSettings()

cfg.mdef("debug", True, gcm_is_bool, gcm_trans_bool, False)

cfg.mdef("source_regex", True, gcm_is_string, None, "^R:\s*(.*?)\s*\(\s*(.+?)\s*\)\s*$")
cfg.mdef("source_regmap", False, gcm_is_list, gcm_trans_list, [1, 2])
cfg.mdef("source_regmap_len", False, None, None, len(cfg.source_regmap))

cfg.mdef("dest_name", True, gcm_is_string, None, u"Raahen kansainvälisyystoiminta")
cfg.mdef("dest_id", True, gcm_is_string, None, None)

cfg.mdef("noauth_local_webserver", False, None, None, True)
#cfg.mdef("auth_host_name", False, None, None, "localhost")
#cfg.mdef("auth_host_port", False, None, None, [8080, 8090])
cfg.mdef("logging_level", True, gcm_is_log_level, gcm_trans_log_level, "ERROR")

# No need to touch these
cfg.mdef("app_name", False, None, None, "Google Calendar MultiMerge")
cfg.mdef("scope", False, None, None, "https://www.googleapis.com/auth/calendar")
#cfg.mdef("scope", False, None, None, "https://www.googleapis.com/auth/calendar.readonly")
cfg.mdef("secret_file", True, gcm_is_filename, None, "client_secret.json")
cfg.mdef("credential_file", True, gcm_is_filename, None, "client_credentials.json")

## Initialize and authorize API connection
credentials = gcm_get_credentials(cfg)
http = credentials.authorize(httplib2.Http())
service = discovery.build("calendar", "v3", http=http)


## Fetch complete calendar list
gcm_debug("Fetching available calendars ..")
calendars = []
calPageToken = None
while True:
    # We want everything except deleted and hidden calendars
    calResult = service.calendarList().list(
        showHidden=False,
        showDeleted=False,
        pageToken=calPageToken
        ).execute()

    calendars.extend(calResult.get("items", []))
    calPageToken = calResult.get("nextPageToken")
    if not calPageToken:
        break

if len(calendars) == 0:
    gcm_fatal("No calendars found?")