Mercurial > hg > gcmultimerge
comparison multimerge.py @ 65:1eefa9b5e945
Unicodify.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 11 Jul 2016 18:36:10 +0300 |
parents | c4b8d934d7ab |
children | b08d159e35c7 |
comparison
equal
deleted
inserted
replaced
64:c4b8d934d7ab | 65:1eefa9b5e945 |
---|---|
80 ## Function for handling Google API credentials | 80 ## Function for handling Google API credentials |
81 def gcm_get_credentials(mcfg): | 81 def gcm_get_credentials(mcfg): |
82 try: | 82 try: |
83 store = oauth2client.file.Storage(mcfg.credential_file) | 83 store = oauth2client.file.Storage(mcfg.credential_file) |
84 except Exception as e: | 84 except Exception as e: |
85 gcm_fatal("Failed to read credential file:\n{0}\n\nERROR: {1}\n".format(mcfg.credential_file, str(e))) | 85 gcm_fatal(u"Failed to read credential file:\n{0}\n\nERROR: {1}\n".format(mcfg.credential_file, str(e))) |
86 | 86 |
87 credentials = store.get() | 87 credentials = store.get() |
88 if not credentials or credentials.invalid: | 88 if not credentials or credentials.invalid: |
89 try: | 89 try: |
90 flow = client.flow_from_clientsecrets(mcfg.secret_file, mcfg.scope) | 90 flow = client.flow_from_clientsecrets(mcfg.secret_file, mcfg.scope) |
91 except Exception as e: | 91 except Exception as e: |
92 gcm_fatal("Failed to fetch client secret:\n{0}\n\nERROR: {1}\n".format(mcfg.secret_file, str(e))) | 92 gcm_fatal(u"Failed to fetch client secret:\n{0}\n\nERROR: {1}\n".format(mcfg.secret_file, str(e))) |
93 | 93 |
94 flow.user_agent = mcfg.app_name | 94 flow.user_agent = mcfg.app_name |
95 credentials = tools.run_flow(flow, store, mcfg) | 95 credentials = tools.run_flow(flow, store, mcfg) |
96 if not credentials or credentials.invalid: | 96 if not credentials or credentials.invalid: |
97 gcm_fatal("Failed to authenticate / invalid credentials.") | 97 gcm_fatal(u"Failed to authenticate / invalid credentials.") |
98 return credentials | 98 return credentials |
99 | 99 |
100 | 100 |
101 def gcm_dump_events(events): | 101 def gcm_dump_events(events): |
102 for event in events: | 102 for event in events: |
146 elif len(src) == 7 and src[0] == "#": | 146 elif len(src) == 7 and src[0] == "#": |
147 self.r = int(src[1:3], 16) | 147 self.r = int(src[1:3], 16) |
148 self.g = int(src[3:5], 16) | 148 self.g = int(src[3:5], 16) |
149 self.b = int(src[6:7], 16) | 149 self.b = int(src[6:7], 16) |
150 else: | 150 else: |
151 gcm_fatal("Expected hex-triplet string for GCMColor() initializer: {0}".format(src)) | 151 gcm_fatal(u"Expected hex-triplet string for GCMColor() initializer: {0}".format(src)) |
152 elif isinstance(src, GCMColor): | 152 elif isinstance(src, GCMColor): |
153 self.r = src.r | 153 self.r = src.r |
154 self.g = src.g | 154 self.g = src.g |
155 self.b = src.b | 155 self.b = src.b |
156 else: | 156 else: |
157 gcm_fatal("Invalid initializer for GCMColor() object.") | 157 gcm_fatal(u"Invalid initializer for GCMColor() object.") |
158 | 158 |
159 def delta(self, other): | 159 def delta(self, other): |
160 ctmp = GCMColor() | 160 ctmp = GCMColor() |
161 ctmp.r = other.r - self.r | 161 ctmp.r = other.r - self.r |
162 ctmp.g = other.g - self.g | 162 ctmp.g = other.g - self.g |
201 | 201 |
202 def __getattr__(self, name): | 202 def __getattr__(self, name): |
203 if name in self.m_data: | 203 if name in self.m_data: |
204 return self.m_data[name] | 204 return self.m_data[name] |
205 else: | 205 else: |
206 gcm_fatal("GCMSettings.__getattr__(): No such attribute '"+ name +"'.") | 206 gcm_fatal(u"GCMSettings.__getattr__(): No such attribute '"+ name +"'.") |
207 | 207 |
208 def mvalidate(self, name, value): | 208 def mvalidate(self, name, value): |
209 if name in self.m_validate and self.m_validate[name]: | 209 if name in self.m_validate and self.m_validate[name]: |
210 if not self.m_validate[name](value): | 210 if not self.m_validate[name](value): |
211 gcm_fatal("GCMSettings.mvalidate(): Invalid value for attribute '{0}': {1}".format(name, value)) | 211 gcm_fatal(u"GCMSettings.mvalidate(): Invalid value for attribute '{0}': {1}".format(name, value)) |
212 | 212 |
213 def mtranslate(self, name, value): | 213 def mtranslate(self, name, value): |
214 if name in self.m_translate and self.m_translate[name]: | 214 if name in self.m_translate and self.m_translate[name]: |
215 return self.m_translate[name](value) | 215 return self.m_translate[name](value) |
216 else: | 216 else: |
275 return mvalue | 275 return mvalue |
276 | 276 |
277 def is_bool(self, mvalue): | 277 def is_bool(self, mvalue): |
278 mval = self.trans_bool(mvalue) | 278 mval = self.trans_bool(mvalue) |
279 if not isinstance(mval, bool): | 279 if not isinstance(mval, bool): |
280 gcm_fatal("GCMSettings.is_bool(): Invalid boolean value '{0}', should be true|false|1|0|on|off|yes|no.".format(mvalue)) | 280 gcm_fatal(u"GCMSettings.is_bool(): Invalid boolean value '{0}', should be true|false|1|0|on|off|yes|no.".format(mvalue)) |
281 else: | 281 else: |
282 return True | 282 return True |
283 | 283 |
284 def trans_list(self, mvalue): | 284 def trans_list(self, mvalue): |
285 morig = mvalue | 285 morig = mvalue |
286 if self.is_str(mvalue): | 286 if self.is_str(mvalue): |
287 mvalue = re.split("\s*,\s*", mvalue, flags=re.IGNORECASE) | 287 mvalue = re.split("\s*,\s*", mvalue, flags=re.IGNORECASE) |
288 if not isinstance(mvalue, list): | 288 if not isinstance(mvalue, list): |
289 gcm_fatal("GCMSettings.trans_list(): Could not parse list '{0}'.".format(mvalue)) | 289 gcm_fatal(u"GCMSettings.trans_list(): Could not parse list '{0}'.".format(mvalue)) |
290 elif not isinstance(mvalue, list): | 290 elif not isinstance(mvalue, list): |
291 gcm_fatal("GCMSettings.trans_list(): Invalid value '{0}'.".format(mvalue)) | 291 gcm_fatal(u"GCMSettings.trans_list(): Invalid value '{0}'.".format(mvalue)) |
292 return mvalue | 292 return mvalue |
293 | 293 |
294 def is_list(self, mvalue): | 294 def is_list(self, mvalue): |
295 return self.trans_list(mvalue) | 295 return self.trans_list(mvalue) |
296 | 296 |
309 def is_email_list(self, mvalue): | 309 def is_email_list(self, mvalue): |
310 mvalue = self.trans_email_list(mvalue) | 310 mvalue = self.trans_email_list(mvalue) |
311 if mvalue != None: | 311 if mvalue != None: |
312 for email in mvalue: | 312 for email in mvalue: |
313 if not self.is_email(email): | 313 if not self.is_email(email): |
314 gcm_fatal("Invalid e-mail address '{0}' in list {1}.".format(email, ", ".join(mvalue))) | 314 gcm_fatal(u"Invalid e-mail address '{0}' in list {1}.".format(email, ", ".join(mvalue))) |
315 return True | 315 return True |
316 | 316 |
317 | 317 |
318 ### | 318 ### |
319 ### Main program starts | 319 ### Main program starts |
358 gcm_debug(u"Reading configuration from '{0}'.".format(sys.argv[1])) | 358 gcm_debug(u"Reading configuration from '{0}'.".format(sys.argv[1])) |
359 try: | 359 try: |
360 cfgparser = ConfigParser.RawConfigParser() | 360 cfgparser = ConfigParser.RawConfigParser() |
361 cfgparser.readfp(codecs.open(sys.argv[1], "r", "UTF-8")) | 361 cfgparser.readfp(codecs.open(sys.argv[1], "r", "UTF-8")) |
362 except Exception as e: | 362 except Exception as e: |
363 gcm_fatal("Failed to read configuration file '{0}': {1}".format(sys.argv[1], str(e))) | 363 gcm_fatal(u"Failed to read configuration file '{0}': {1}".format(sys.argv[1], str(e))) |
364 | 364 |
365 # Check that the required section exists | 365 # Check that the required section exists |
366 section = "gcm" | 366 section = "gcm" |
367 if not cfgparser.has_section(section): | 367 if not cfgparser.has_section(section): |
368 gcm_fatal("Invalid configuration, missing '{0}' section.".format(section)) | 368 gcm_fatal(u"Invalid configuration, missing '{0}' section.".format(section)) |
369 | 369 |
370 # Debug setting is a special case, we need to get it | 370 # Debug setting is a special case, we need to get it |
371 # set before everything else, so do it here .. | 371 # set before everything else, so do it here .. |
372 if cfgparser.has_option(section, "debug"): | 372 if cfgparser.has_option(section, "debug"): |
373 cfg.mset("debug", cfgparser.get(section, "debug")) | 373 cfg.mset("debug", cfgparser.get(section, "debug")) |
377 | 377 |
378 | 378 |
379 ## Validate settings | 379 ## Validate settings |
380 if cfg.email: | 380 if cfg.email: |
381 if cfg.email_subject == None or len(cfg.email_subject) == 0: | 381 if cfg.email_subject == None or len(cfg.email_subject) == 0: |
382 gcm_fatal("E-mail enabled but email_subject not set.") | 382 gcm_fatal(u"E-mail enabled but email_subject not set.") |
383 elif cfg.email_sender == None: | 383 elif cfg.email_sender == None: |
384 gcm_fatal("E-mail enabled but email_sender not set.") | 384 gcm_fatal(u"E-mail enabled but email_sender not set.") |
385 elif cfg.email_to == None: | 385 elif cfg.email_to == None: |
386 gcm_fatal("E-mail enabled but email_to not set.") | 386 gcm_fatal(u"E-mail enabled but email_to not set.") |
387 else: | 387 else: |
388 cfg.mset("email_ok", True) | 388 cfg.mset("email_ok", True) |
389 | 389 |
390 | 390 |
391 if len(cfg.source_regmap) != cfg.source_regmap_len: | 391 if len(cfg.source_regmap) != cfg.source_regmap_len: |
392 gcm_fatal("Setting source_regmap list must be {0} items.".format(cfg.source_regmap_len)) | 392 gcm_fatal(u"Setting source_regmap list must be {0} items.".format(cfg.source_regmap_len)) |
393 else: | 393 else: |
394 # Force to integers | 394 # Force to integers |
395 try: | 395 try: |
396 cfg.source_regmap = map(lambda x: int(x), cfg.source_regmap) | 396 cfg.source_regmap = map(lambda x: int(x), cfg.source_regmap) |
397 except Exception as e: | 397 except Exception as e: |
398 gcm_fatal("Invalid source_regmap: {0}".format(str(e))) | 398 gcm_fatal(u"Invalid source_regmap: {0}".format(str(e))) |
399 | 399 |
400 | 400 |
401 if not cfg.dest_name and not cfg.dest_id: | 401 if not cfg.dest_name and not cfg.dest_id: |
402 gcm_fatal("Target calendar ID or name required, but not set.") | 402 gcm_fatal(u"Target calendar ID or name required, but not set.") |
403 | 403 |
404 | 404 |
405 if cfg.dest_name: | 405 if cfg.dest_name: |
406 cfg.mset("dest_name", cfg.mget("dest_name").strip()) | 406 cfg.mset("dest_name", cfg.mget("dest_name").strip()) |
407 | 407 |
428 cal_token = result.get("nextPageToken") | 428 cal_token = result.get("nextPageToken") |
429 if not cal_token: | 429 if not cal_token: |
430 break | 430 break |
431 | 431 |
432 if len(calendars) == 0: | 432 if len(calendars) == 0: |
433 gcm_fatal("No calendars found?") | 433 gcm_fatal(u"No calendars found?") |
434 | 434 |
435 gcm_debug(u"{0} calendars total found.".format(len(calendars))) | 435 gcm_debug(u"{0} calendars total found.".format(len(calendars))) |
436 | 436 |
437 | 437 |
438 ## Filter desired SOURCE calendars based on specified regexp | 438 ## Filter desired SOURCE calendars based on specified regexp |
468 | 468 |
469 ## Fetch colors | 469 ## Fetch colors |
470 try: | 470 try: |
471 colors = service.colors().get().execute() | 471 colors = service.colors().get().execute() |
472 except Exception as e: | 472 except Exception as e: |
473 gcm_fatal("Failed to fetch calendar color settings:\n\n{0}".format(str(e))) | 473 gcm_fatal(u"Failed to fetch calendar color settings:\n\n{0}".format(str(e))) |
474 | 474 |
475 | 475 |
476 ## Now, we fetch and collect events | 476 ## Now, we fetch and collect events |
477 gcm_debug(u"Fetching calendar events .. ") | 477 gcm_debug(u"Fetching calendar events .. ") |
478 src_events = [] | 478 src_events = [] |
486 # orderBy="startTime", | 486 # orderBy="startTime", |
487 ).execute() | 487 ).execute() |
488 | 488 |
489 c_found = None | 489 c_found = None |
490 if "colorId" in calendar and calendar["colorId"] in colors["calendar"]: | 490 if "colorId" in calendar and calendar["colorId"] in colors["calendar"]: |
491 gcm_debug("Calendar color: {0}".format(colors["calendar"][calendar["colorId"]])) | 491 gcm_debug(u"Calendar color: {0}".format(colors["calendar"][calendar["colorId"]])) |
492 c_found = gcm_find_nearest_color(colors["event"], colors["calendar"][calendar["colorId"]], 100) | 492 c_found = gcm_find_nearest_color(colors["event"], colors["calendar"][calendar["colorId"]], 100) |
493 if c_found: | 493 if c_found: |
494 gcm_debug("Found nearest event color ID: {0}, {1}".format(c_found, colors["event"][c_found])) | 494 gcm_debug(u"Found nearest event color ID: {0}, {1}".format(c_found, colors["event"][c_found])) |
495 else: | 495 else: |
496 gcm_debug("No matching event color found!") | 496 gcm_debug(u"No matching event color found!") |
497 | 497 |
498 # Add events, if any, to main list | 498 # Add events, if any, to main list |
499 events = gcm_generate_ids(result.get("items", []), calendar["id"], "___") | 499 events = gcm_generate_ids(result.get("items", []), calendar["id"], "___") |
500 if events: | 500 if events: |
501 for event in events: | 501 for event in events: |
537 event.pop("sequence", None) | 537 event.pop("sequence", None) |
538 event.pop("id", None) | 538 event.pop("id", None) |
539 event["iCalUID"] = event["gcm_id"] | 539 event["iCalUID"] = event["gcm_id"] |
540 new_event = service.events().update(calendarId=cfg.dest_id, eventId=d_event["id"], body=event).execute() | 540 new_event = service.events().update(calendarId=cfg.dest_id, eventId=d_event["id"], body=event).execute() |
541 except Exception as e: | 541 except Exception as e: |
542 gcm_fatal("Failed to update event {0}:\n\n{1}\n\nERROR: {2}\n".format(event["gcm_id"], event, str(e))) | 542 gcm_fatal(u"Failed to update event {0}:\n\n{1}\n\nERROR: {2}\n".format(event["gcm_id"], event, str(e))) |
543 else: | 543 else: |
544 gcm_debug(u"No need to update event {0} : {1}.".format(event["id"], event["gcm_id"])) | 544 gcm_debug(u"No need to update event {0} : {1}.".format(event["id"], event["gcm_id"])) |
545 else: | 545 else: |
546 ## Event does not seem to exist. Insert new event. | 546 ## Event does not seem to exist. Insert new event. |
547 gcm_debug(u"Inserting new event {0}".format(event["gcm_id"])) | 547 gcm_debug(u"Inserting new event {0}".format(event["gcm_id"])) |
548 event.pop("id", None) | 548 event.pop("id", None) |
549 event["iCalUID"] = event["gcm_id"] # Replace Google generated ID with our own | 549 event["iCalUID"] = event["gcm_id"] # Replace Google generated ID with our own |
550 try: | 550 try: |
551 new_event = service.events().insert(calendarId=cfg.dest_id, body=event).execute() | 551 new_event = service.events().insert(calendarId=cfg.dest_id, body=event).execute() |
552 except Exception as e: | 552 except Exception as e: |
553 gcm_fatal("Failed to insert new event:\n\n{0}\n\nERROR: {1}\n".format(event, str(e))) | 553 gcm_fatal(u"Failed to insert new event:\n\n{0}\n\nERROR: {1}\n".format(event, str(e))) |
554 | 554 |
555 | 555 |
556 ## Remove "stale" events | 556 ## Remove "stale" events |
557 gcm_debug(u"Purging stale events ..") | 557 gcm_debug(u"Purging stale events ..") |
558 for event in dst_events: | 558 for event in dst_events: |
560 if not event["gcm_id"] in src_ids and event["status"] != u"cancelled": | 560 if not event["gcm_id"] in src_ids and event["status"] != u"cancelled": |
561 gcm_debug(u"Deleting event {0}".format(event["gcm_id"])) | 561 gcm_debug(u"Deleting event {0}".format(event["gcm_id"])) |
562 try: | 562 try: |
563 service.events().delete(calendarId=cfg.dest_id, eventId=event["id"]).execute() | 563 service.events().delete(calendarId=cfg.dest_id, eventId=event["id"]).execute() |
564 except Exception as e: | 564 except Exception as e: |
565 gcm_fatal("Failed to delete stale event:\n{0}\n\nERROR: {1}\n".format(event, str(e))) | 565 gcm_fatal(u"Failed to delete stale event:\n{0}\n\nERROR: {1}\n".format(event, str(e))) |
566 | 566 |
567 | 567 |
568 gcm_debug(u"Finished.") | 568 gcm_debug(u"Finished.") |