Mercurial > hg > gcmultimerge
comparison multimerge.py @ 1:74f172565752
Initial import.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 04 Jul 2016 12:49:37 +0300 |
parents | |
children | 34c3a08a4a37 |
comparison
equal
deleted
inserted
replaced
0:c0e97f27f929 | 1:74f172565752 |
---|---|
1 #!/usr/bin/python | |
2 import os | |
3 import sys | |
4 import signal | |
5 import re | |
6 import time | |
7 import datetime | |
8 import httplib2 | |
9 import ConfigParser | |
10 import oauth2client | |
11 from oauth2client import client | |
12 from oauth2client import tools | |
13 from googleapiclient import discovery | |
14 | |
15 | |
16 ### | |
17 ### Misc. helper functions | |
18 ### | |
19 | |
20 ## Wrapper for print() that does not break when redirecting stdin/out | |
21 ## because of piped output not having a defined encoding. We default | |
22 ## to UTF-8 encoding in output here. | |
23 def gcm_print(smsg): | |
24 gcm_msgbuf.append(smsg.encode("UTF-8")) | |
25 if sys.stdout.encoding != None: | |
26 print(smsg.encode(sys.stdout.encoding)) | |
27 else: | |
28 print(smsg.encode("UTF-8")) | |
29 | |
30 | |
31 ## Fatal errors | |
32 def gcm_fatal(smsg): | |
33 gcm_print(u"ERROR: "+ smsg) | |
34 sys.exit(1) | |
35 | |
36 | |
37 ## Debug messages | |
38 def gcm_debug(smsg): | |
39 if cfg.debug: | |
40 gcm_print(u"DBG: "+ smsg) | |
41 else: | |
42 gcm_msgbuf.append(u"DBG: "+ smsg.encode("UTF-8")) | |
43 | |
44 | |
45 ## Handle SIGINT signals here | |
46 def gcm_signal_handler(signal, frame): | |
47 gcm_print("\nQuitting due to SIGINT / Ctrl+C!") | |
48 sys.exit(0) | |
49 | |
50 | |
51 def gcm_get_credentials(mcfg): | |
52 store = oauth2client.file.Storage(mcfg.credential_file) | |
53 credentials = store.get() | |
54 if not credentials or credentials.invalid: | |
55 flow = client.flow_from_clientsecrets(mcfg.secret_file, mcfg.scope) | |
56 flow.user_agent = mcfg.app_name | |
57 credentials = tools.run_flow(flow, store, mcfg) | |
58 if not credentials or credentials.invalid: | |
59 gcm_fatal("Failed to authenticate / invalid credentials.") | |
60 return credentials | |
61 | |
62 | |
63 def gcm_dump_events(events): | |
64 for event in events: | |
65 ev_start = event["start"].get("dateTime", event["start"].get("date")) | |
66 ev_end = event["end"].get("dateTime", event["end"].get("date")) | |
67 gcm_print(u"{0:25} - {1:25} : {2}".format(ev_start, ev_end, event["summary"])) | |
68 | |
69 | |
70 class GCMSettings(dict): | |
71 def __init__(self): | |
72 self.m_data = {} | |
73 self.m_saveable = {} | |
74 self.m_translate = {} | |
75 | |
76 def __getattr__(self, name): | |
77 if name in self.m_data: | |
78 return self.m_data[name] | |
79 else: | |
80 gcm_fatal("GCMSettings.__getattr__(): No such attribute '"+ name +"'.") | |
81 | |
82 def mtranslate(self, name, value): | |
83 if name in self.m_translate and self.m_translate[name]: | |
84 return self.m_translate[name](value) | |
85 else: | |
86 return value | |
87 | |
88 def mdef(self, name, saveable, validate, translate, value): | |
89 self.m_saveable[name] = saveable | |
90 self.m_data[name] = self.mtranslate(name, value) | |
91 | |
92 def mset(self, name, value): | |
93 if name in self.m_data: | |
94 self.m_data[name] = self.mtranslate(name, value) | |
95 else: | |
96 gcm_fatal("GCMSettings.mset(): No such attribute '"+ name +"'.") | |
97 | |
98 def mget(self, name): | |
99 if name in self.m_data: | |
100 return self.m_data[name] | |
101 else: | |
102 return None | |
103 | |
104 | |
105 ### | |
106 ### Main program starts | |
107 ### | |
108 gcm_msgbuf = [] | |
109 signal.signal(signal.SIGINT, gcm_signal_handler) | |
110 | |
111 | |
112 ## Settings | |
113 cfg = GCMSettings() | |
114 | |
115 cfg.mdef("debug", True, gcm_is_bool, gcm_trans_bool, False) | |
116 | |
117 cfg.mdef("source_regex", True, gcm_is_string, None, "^R:\s*(.*?)\s*\(\s*(.+?)\s*\)\s*$") | |
118 cfg.mdef("source_regmap", False, gcm_is_list, gcm_trans_list, [1, 2]) | |
119 cfg.mdef("source_regmap_len", False, None, None, len(cfg.source_regmap)) | |
120 | |
121 cfg.mdef("dest_name", True, gcm_is_string, None, u"Raahen kansainvälisyystoiminta") | |
122 cfg.mdef("dest_id", True, gcm_is_string, None, None) | |
123 | |
124 cfg.mdef("noauth_local_webserver", False, None, None, True) | |
125 #cfg.mdef("auth_host_name", False, None, None, "localhost") | |
126 #cfg.mdef("auth_host_port", False, None, None, [8080, 8090]) | |
127 cfg.mdef("logging_level", True, gcm_is_log_level, gcm_trans_log_level, "ERROR") | |
128 | |
129 # No need to touch these | |
130 cfg.mdef("app_name", False, None, None, "Google Calendar MultiMerge") | |
131 cfg.mdef("scope", False, None, None, "https://www.googleapis.com/auth/calendar") | |
132 #cfg.mdef("scope", False, None, None, "https://www.googleapis.com/auth/calendar.readonly") | |
133 cfg.mdef("secret_file", True, gcm_is_filename, None, "client_secret.json") | |
134 cfg.mdef("credential_file", True, gcm_is_filename, None, "client_credentials.json") | |
135 | |
136 ## Initialize and authorize API connection | |
137 credentials = gcm_get_credentials(cfg) | |
138 http = credentials.authorize(httplib2.Http()) | |
139 service = discovery.build("calendar", "v3", http=http) | |
140 | |
141 | |
142 ## Fetch complete calendar list | |
143 gcm_debug("Fetching available calendars ..") | |
144 calendars = [] | |
145 calPageToken = None | |
146 while True: | |
147 # We want everything except deleted and hidden calendars | |
148 calResult = service.calendarList().list( | |
149 showHidden=False, | |
150 showDeleted=False, | |
151 pageToken=calPageToken | |
152 ).execute() | |
153 | |
154 calendars.extend(calResult.get("items", [])) | |
155 calPageToken = calResult.get("nextPageToken") | |
156 if not calPageToken: | |
157 break | |
158 | |
159 if len(calendars) == 0: | |
160 gcm_fatal("No calendars found?") | |
161 | |
162 |