mirror of
https://github.com/GAM-team/GAM.git
synced 2026-07-04 04:41:35 +00:00
2227 lines
100 KiB
Python
2227 lines
100 KiB
Python
"""GAM calendar ACL, event, and settings management."""
|
|
|
|
import re
|
|
import json
|
|
import sys
|
|
|
|
from gam.util.csv_pf import RI_ENTITY, RI_J, RI_JCOUNT, RI_ITEM
|
|
import uuid
|
|
|
|
from gamlib import glaction
|
|
from gamlib import glapi as API
|
|
from gamlib import glcfg as GC
|
|
from gamlib import glclargs
|
|
from gamlib import glentity
|
|
from gamlib import glgapi as GAPI
|
|
from gamlib import glglobals as GM
|
|
from gamlib import glindent
|
|
from gamlib import glmsgs as Msg
|
|
|
|
Act = glaction.GamAction()
|
|
Ent = glentity.GamEntity()
|
|
Ind = glindent.GamIndent()
|
|
Cmd = glclargs.GamCLArgs()
|
|
|
|
|
|
def _getMain():
|
|
return sys.modules['gam']
|
|
|
|
def __getattr__(name):
|
|
"""Fall back to gam module for any undefined names."""
|
|
main = _getMain()
|
|
try:
|
|
return getattr(main, name)
|
|
except AttributeError:
|
|
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
|
|
def normalizeCalendarId(calId, user):
|
|
if not user or calId.lower() != 'primary':
|
|
return _getMain().convertUIDtoEmailAddress(calId, emailTypes=['user', 'resource'])
|
|
return user
|
|
|
|
def checkCalendarExists(cal, calId, i, count, showMessage=False):
|
|
if not cal:
|
|
cal = _getMain().buildGAPIObject(API.CALENDAR)
|
|
try:
|
|
return _getMain().callGAPI(cal.calendars(), 'get',
|
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND],
|
|
calendarId=calId, fields='id')['id']
|
|
except GAPI.notFound as e:
|
|
if showMessage:
|
|
_getMain().entityActionFailedWarning([Ent.CALENDAR, calId], str(e))
|
|
return None
|
|
except GAPI.notACalendarUser:
|
|
if showMessage:
|
|
_getMain().userCalServiceNotEnabledWarning(calId, i, count)
|
|
return None
|
|
|
|
def validateCalendar(calId, i=0, count=0, noClientAccess=False):
|
|
cal = None
|
|
if not calId.endswith('.calendar.google.com'):
|
|
calId, cal = _getMain().buildGAPIServiceObject(API.CALENDAR, calId, i, count, displayError=noClientAccess)
|
|
if not cal:
|
|
if noClientAccess:
|
|
return (calId, None)
|
|
cal = _getMain().buildGAPIObject(API.CALENDAR)
|
|
try:
|
|
_getMain().callGAPI(cal.calendars(), 'get',
|
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND],
|
|
calendarId=calId, fields='')
|
|
return (calId, cal)
|
|
except GAPI.notFound as e:
|
|
_getMain().entityActionFailedWarning([Ent.CALENDAR, calId], str(e), i, count)
|
|
except GAPI.notACalendarUser:
|
|
_getMain().userCalServiceNotEnabledWarning(calId, i, count)
|
|
return (calId, None)
|
|
|
|
def getNormalizedCalIdCal(cal, calId, user, i=0, count=0):
|
|
if not cal:
|
|
return validateCalendar(calId, i, count)
|
|
return (normalizeCalendarId(calId, user), cal)
|
|
|
|
CALENDAR_ACL_ROLES_MAP = {
|
|
'editor': 'writer',
|
|
'freebusy': 'freeBusyReader',
|
|
'freebusyreader': 'freeBusyReader',
|
|
'owner': 'owner',
|
|
'read': 'reader',
|
|
'reader': 'reader',
|
|
'writer': 'writer',
|
|
'writerwithoutprivateaccess': 'writerWithoutPrivateAccess',
|
|
'none': 'none',
|
|
}
|
|
|
|
ACL_SCOPE_CHOICES = ['default', 'user', 'group', 'domain'] # default must be first element
|
|
|
|
def getACLScope():
|
|
scopeType, scopeValue = _getMain().getChoiceAndValue(Cmd.OB_ACL_SCOPE, ACL_SCOPE_CHOICES[1:], ':')
|
|
if scopeType:
|
|
if scopeType != 'domain':
|
|
scopeValue = _getMain().normalizeEmailAddressOrUID(scopeValue, noUid=True)
|
|
else:
|
|
scopeValue = scopeValue.lower()
|
|
return (scopeType, scopeValue)
|
|
scopeType = _getMain().getChoice(ACL_SCOPE_CHOICES, defaultChoice='user')
|
|
if scopeType == 'domain':
|
|
entity = _getMain().getString(Cmd.OB_DOMAIN_NAME, optional=True)
|
|
if entity:
|
|
scopeValue = entity.lower()
|
|
else:
|
|
scopeValue = GC.Values[GC.DOMAIN]
|
|
elif scopeType != 'default':
|
|
scopeValue = _getMain().getEmailAddress(noUid=True)
|
|
else:
|
|
scopeValue = None
|
|
return (scopeType, scopeValue)
|
|
|
|
def getCalendarACLScope():
|
|
scopeType, scopeValue = getACLScope()
|
|
if scopeType != 'default':
|
|
return {'list': [f'{scopeType}:{scopeValue}'], 'dict': None}
|
|
return {'list': [scopeType], 'dict': None}
|
|
|
|
def getCalendarSiteACLScopeEntity():
|
|
ACLScopeEntity = {'list': _getMain().getEntityList(Cmd.OB_ACL_SCOPE_ENTITY), 'dict': None}
|
|
if isinstance(ACLScopeEntity['list'], dict):
|
|
ACLScopeEntity['dict'] = ACLScopeEntity['list']
|
|
return ACLScopeEntity
|
|
|
|
def getCalendarACLSendNotifications():
|
|
return _getMain().getBoolean() if _getMain().checkArgumentPresent('sendnotifications') else True
|
|
|
|
def getCalendarCreateUpdateACLsOptions(getScopeEntity):
|
|
role = _getMain().getChoice(CALENDAR_ACL_ROLES_MAP, mapChoice=True)
|
|
ACLScopeEntity = getCalendarSiteACLScopeEntity() if getScopeEntity else getCalendarACLScope()
|
|
sendNotifications = getCalendarACLSendNotifications()
|
|
_getMain().checkForExtraneousArguments()
|
|
return (role, ACLScopeEntity, sendNotifications)
|
|
|
|
def getCalendarDeleteACLsOptions(getScopeEntity):
|
|
rolesMap = CALENDAR_ACL_ROLES_MAP.copy()
|
|
rolesMap['id'] = 'id'
|
|
role = _getMain().getChoice(rolesMap, defaultChoice=None, mapChoice=True)
|
|
ACLScopeEntity = getCalendarSiteACLScopeEntity() if getScopeEntity else getCalendarACLScope()
|
|
_getMain().checkForExtraneousArguments()
|
|
return (role, ACLScopeEntity)
|
|
|
|
def _normalizeCalIdGetRuleIds(origUser, user, origCal, calId, j, jcount, ACLScopeEntity, showAction=True):
|
|
if ACLScopeEntity['dict']:
|
|
if origUser:
|
|
if not GM.Globals[GM.CSV_SUBKEY_FIELD]:
|
|
ruleIds = ACLScopeEntity['dict'][calId]
|
|
else:
|
|
ruleIds = ACLScopeEntity['dict'][origUser][calId]
|
|
else:
|
|
ruleIds = ACLScopeEntity['dict'][calId]
|
|
else:
|
|
ruleIds = ACLScopeEntity['list']
|
|
calId, cal = getNormalizedCalIdCal(origCal, calId, user, j, jcount)
|
|
if not cal:
|
|
return (calId, cal, None, 0)
|
|
kcount = len(ruleIds)
|
|
if kcount == 0:
|
|
_getMain().setSysExitRC(_getMain().NO_ENTITIES_FOUND_RC)
|
|
if showAction:
|
|
_getMain().entityPerformActionNumItems([Ent.CALENDAR, calId], kcount, Ent.CALENDAR_ACL, j, jcount)
|
|
return (calId, cal, ruleIds, kcount)
|
|
|
|
def _processCalendarACLs(cal, function, entityType, calId, j, jcount, k, kcount, role, ruleId, sendNotifications):
|
|
result = True
|
|
if function == 'insert':
|
|
kwargs = {'body': _getMain().makeRoleRuleIdBody(role, ruleId), 'fields': '', 'sendNotifications': sendNotifications}
|
|
elif function == 'patch':
|
|
kwargs = {'ruleId': ruleId, 'body': {'role': role}, 'fields': '', 'sendNotifications': sendNotifications}
|
|
else: # elif function == 'delete':
|
|
kwargs = {'ruleId': ruleId}
|
|
try:
|
|
_getMain().callGAPI(cal.acl(), function,
|
|
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID, GAPI.INVALID_PARAMETER, GAPI.INVALID_SCOPE_VALUE,
|
|
GAPI.ILLEGAL_ACCESS_ROLE_FOR_DEFAULT, GAPI.CANNOT_CHANGE_OWN_ACL,
|
|
GAPI.CANNOT_CHANGE_OWNER_ACL, GAPI.CANNOT_MODIFY_ACL_OF_CALENDAR_OWNER,
|
|
GAPI.FORBIDDEN, GAPI.AUTH_ERROR, GAPI.CONDITION_NOT_MET],
|
|
calendarId=calId, **kwargs)
|
|
_getMain().entityActionPerformed([entityType, calId, Ent.CALENDAR_ACL, _getMain().formatACLScopeRole(ruleId, role)], k, kcount)
|
|
except GAPI.notFound as e:
|
|
if not checkCalendarExists(cal, calId, j, jcount):
|
|
_getMain().entityUnknownWarning(entityType, calId, j, jcount)
|
|
result = False
|
|
else:
|
|
_getMain().entityActionFailedWarning([entityType, calId, Ent.CALENDAR_ACL, _getMain().formatACLScopeRole(ruleId, role)], str(e), k, kcount)
|
|
except (GAPI.invalid, GAPI.invalidParameter, GAPI.invalidScopeValue,
|
|
GAPI.illegalAccessRoleForDefault, GAPI.cannotChangeOwnAcl,
|
|
GAPI.cannotChangeOwnerAcl, GAPI.cannotModifyAclOfCalendarOwner,
|
|
GAPI.forbidden, GAPI.authError, GAPI.conditionNotMet) as e:
|
|
_getMain().entityActionFailedWarning([entityType, calId, Ent.CALENDAR_ACL, _getMain().formatACLScopeRole(ruleId, role)], str(e), k, kcount)
|
|
return result
|
|
|
|
def _createCalendarACLs(cal, entityType, calId, j, jcount, role, ruleIds, kcount, sendNotifications):
|
|
Ind.Increment()
|
|
k = 0
|
|
for ruleId in ruleIds:
|
|
k += 1
|
|
ruleId = _getMain().normalizeRuleId(ruleId)
|
|
if not _processCalendarACLs(cal, 'insert', entityType, calId, j, jcount, k, kcount, role, ruleId, sendNotifications):
|
|
break
|
|
Ind.Decrement()
|
|
|
|
def _doCalendarsCreateACLs(origUser, user, origCal, calIds, count, role, ACLScopeEntity, sendNotifications):
|
|
i = 0
|
|
for calId in calIds:
|
|
i += 1
|
|
calId, cal, ruleIds, jcount = _normalizeCalIdGetRuleIds(origUser, user, origCal, calId, i, count, ACLScopeEntity)
|
|
if jcount == 0:
|
|
continue
|
|
_createCalendarACLs(cal, Ent.CALENDAR, calId, i, count, role, ruleIds, jcount, sendNotifications)
|
|
|
|
# gam calendar <CalendarEntity> create <CalendarACLRole> <CalendarACLScope> [sendnotifications <Boolean>]
|
|
def doCalendarsCreateACL(calIds):
|
|
role, ACLScopeEntity, sendNotifications = getCalendarCreateUpdateACLsOptions(False)
|
|
_doCalendarsCreateACLs(None, None, None, calIds, len(calIds), role, ACLScopeEntity, sendNotifications)
|
|
|
|
# gam calendars <CalendarEntity> create acls <CalendarACLRole> <CalendarACLScopeEntity> [sendnotifications <Boolean>]
|
|
def doCalendarsCreateACLs(calIds):
|
|
role, ACLScopeEntity, sendNotifications = getCalendarCreateUpdateACLsOptions(True)
|
|
_doCalendarsCreateACLs(None, None, None, calIds, len(calIds), role, ACLScopeEntity, sendNotifications)
|
|
|
|
def _updateDeleteCalendarACLs(cal, function, entityType, calId, j, jcount, role, ruleIds, kcount, sendNotifications):
|
|
Ind.Increment()
|
|
k = 0
|
|
for ruleId in ruleIds:
|
|
k += 1
|
|
ruleId = _getMain().normalizeRuleId(ruleId)
|
|
if not _processCalendarACLs(cal, function, entityType, calId, j, jcount, k, kcount, role, ruleId, sendNotifications):
|
|
break
|
|
Ind.Decrement()
|
|
|
|
def _doUpdateDeleteCalendarACLs(origUser, user, origCal, function, calIds, count, ACLScopeEntity, role, sendNotifications):
|
|
i = 0
|
|
for calId in calIds:
|
|
i += 1
|
|
calId, cal, ruleIds, jcount = _normalizeCalIdGetRuleIds(origUser, user, origCal, calId, i, count, ACLScopeEntity)
|
|
if jcount == 0:
|
|
continue
|
|
_updateDeleteCalendarACLs(cal, function, Ent.CALENDAR, calId, i, count, role, ruleIds, jcount, sendNotifications)
|
|
|
|
# gam calendar <CalendarEntity> update <CalendarACLRole> <CalendarACLScope> [sendnotifications <Boolean>]
|
|
def doCalendarsUpdateACL(calIds):
|
|
role, ACLScopeEntity, sendNotifications = getCalendarCreateUpdateACLsOptions(False)
|
|
_doUpdateDeleteCalendarACLs(None, None, None, 'patch', calIds, len(calIds), ACLScopeEntity, role, sendNotifications)
|
|
|
|
# gam calendars <CalendarEntity> update acls <CalendarACLRole> <CalendarACLScopeEntity> [sendnotifications <Boolean>]
|
|
def doCalendarsUpdateACLs(calIds):
|
|
role, ACLScopeEntity, sendNotifications = getCalendarCreateUpdateACLsOptions(True)
|
|
_doUpdateDeleteCalendarACLs(None, None, None, 'patch', calIds, len(calIds), ACLScopeEntity, role, sendNotifications)
|
|
|
|
# gam calendar <CalendarEntity> delete [<CalendarACLRole>] <CalendarACLScope>
|
|
def doCalendarsDeleteACL(calIds):
|
|
role, ACLScopeEntity = getCalendarDeleteACLsOptions(False)
|
|
_doUpdateDeleteCalendarACLs(None, None, None, 'delete', calIds, len(calIds), ACLScopeEntity, role, False)
|
|
|
|
# gam calendars <CalendarEntity> delete acls <CalendarACLScopeEntity>
|
|
def doCalendarsDeleteACLs(calIds):
|
|
role, ACLScopeEntity = getCalendarDeleteACLsOptions(True)
|
|
_doUpdateDeleteCalendarACLs(None, None, None, 'delete', calIds, len(calIds), ACLScopeEntity, role, False)
|
|
|
|
def _showCalendarACL(user, entityType, calId, acl, k, kcount, FJQC):
|
|
if FJQC.formatJSON:
|
|
if entityType == Ent.CALENDAR:
|
|
if user:
|
|
_getMain().printLine(json.dumps(_getMain().cleanJSON({'primaryEmail': user, 'calendarId': calId, 'acl': acl}),
|
|
ensure_ascii=False, sort_keys=True))
|
|
else:
|
|
_getMain().printLine(json.dumps(_getMain().cleanJSON({'calendarId': calId, 'acl': acl}),
|
|
ensure_ascii=False, sort_keys=True))
|
|
else:
|
|
_getMain().printLine(json.dumps(_getMain().cleanJSON({'resourceId': user, 'resourceEmail': calId, 'acl': acl}),
|
|
ensure_ascii=False, sort_keys=True))
|
|
else:
|
|
_getMain().printKeyValueListWithCount(_getMain().ACLRuleKeyValueList(acl), k, kcount)
|
|
|
|
def _infoCalendarACLs(cal, user, entityType, calId, j, jcount, ruleIds, kcount, FJQC):
|
|
Ind.Increment()
|
|
k = 0
|
|
for ruleId in ruleIds:
|
|
k += 1
|
|
ruleId = _getMain().normalizeRuleId(ruleId)
|
|
try:
|
|
result = _getMain().callGAPI(cal.acl(), 'get',
|
|
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID, GAPI.INVALID_SCOPE_VALUE, GAPI.FORBIDDEN, GAPI.AUTH_ERROR],
|
|
calendarId=calId, ruleId=ruleId, fields='id,role,scope')
|
|
_showCalendarACL(user, entityType, calId, result, k, kcount, FJQC)
|
|
except (GAPI.notFound, GAPI.invalid) as e:
|
|
if not checkCalendarExists(cal, calId, j, jcount):
|
|
_getMain().entityUnknownWarning(entityType, calId, j, jcount)
|
|
break
|
|
_getMain().entityActionFailedWarning([entityType, calId, Ent.CALENDAR_ACL, _getMain().formatACLScopeRole(ruleId, None)], str(e), k, kcount)
|
|
except (GAPI.invalidScopeValue, GAPI.forbidden, GAPI.authError) as e:
|
|
_getMain().entityActionFailedWarning([entityType, calId, Ent.CALENDAR_ACL, _getMain().formatACLScopeRole(ruleId, None)], str(e), k, kcount)
|
|
Ind.Decrement()
|
|
|
|
def _doInfoCalendarACLs(origUser, user, origCal, calIds, count, ACLScopeEntity, FJQC):
|
|
i = 0
|
|
for calId in calIds:
|
|
i += 1
|
|
calId, cal, ruleIds, jcount = _normalizeCalIdGetRuleIds(origUser, user, origCal, calId, i, count, ACLScopeEntity, showAction=not FJQC.formatJSON)
|
|
if jcount == 0:
|
|
continue
|
|
_infoCalendarACLs(cal, user, Ent.CALENDAR, calId, i, count, ruleIds, jcount, FJQC)
|
|
|
|
def _getCalendarInfoACLOptions():
|
|
return _getMain().FormatJSONQuoteChar(formatJSONOnly=True)
|
|
|
|
# gam calendars <CalendarEntity> info acl|acls <CalendarACLScopeEntity>
|
|
# [formatjson]
|
|
def doCalendarsInfoACLs(calIds):
|
|
ACLScopeEntity = getCalendarSiteACLScopeEntity()
|
|
FJQC = _getCalendarInfoACLOptions()
|
|
_doInfoCalendarACLs(None, None, None, calIds, len(calIds), ACLScopeEntity, FJQC)
|
|
|
|
def _printShowCalendarACLs(cal, user, entityType, calId, i, count, csvPF, FJQC, noSelfOwner, addCSVData):
|
|
if csvPF:
|
|
_getMain().printGettingEntityItemForWhom(Ent.CALENDAR_ACL, calId, i, count)
|
|
try:
|
|
acls = _getMain().callGAPIpages(cal.acl(), 'list', 'items',
|
|
throwReasons=[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.AUTH_ERROR],
|
|
calendarId=calId, fields='nextPageToken,items(id,role,scope)')
|
|
except (GAPI.forbidden, GAPI.authError) as e:
|
|
_getMain().entityActionFailedWarning([entityType, calId], str(e), i, count)
|
|
return
|
|
except GAPI.notFound:
|
|
_getMain().entityUnknownWarning(entityType, calId, i, count)
|
|
return
|
|
jcount = len(acls)
|
|
if jcount == 0:
|
|
_getMain().setSysExitRC(_getMain().NO_ENTITIES_FOUND_RC)
|
|
if not csvPF:
|
|
if not FJQC.formatJSON:
|
|
if not noSelfOwner:
|
|
_getMain().entityPerformActionNumItems([entityType, calId], jcount, Ent.CALENDAR_ACL, i, count)
|
|
else:
|
|
_getMain().entityPerformActionModifierNumItems([entityType, calId], Msg.MAXIMUM_OF, jcount, Ent.CALENDAR_ACL, i, count)
|
|
Ind.Increment()
|
|
j = 0
|
|
for rule in acls:
|
|
j += 1
|
|
if noSelfOwner and rule['role'] == 'owner' and rule['scope']['value'] == calId:
|
|
continue
|
|
_showCalendarACL(user, entityType, calId, rule, j, jcount, FJQC)
|
|
Ind.Decrement()
|
|
else:
|
|
if entityType == Ent.CALENDAR:
|
|
if acls:
|
|
for rule in acls:
|
|
if noSelfOwner and rule['role'] == 'owner' and rule['scope']['value'] == calId:
|
|
continue
|
|
row = {'calendarId': calId}
|
|
if user:
|
|
row['primaryEmail'] = user
|
|
if addCSVData:
|
|
row.update(addCSVData)
|
|
_getMain().flattenJSON(rule, flattened=row)
|
|
if not FJQC.formatJSON:
|
|
csvPF.WriteRowTitles(row)
|
|
elif csvPF.CheckRowTitles(row):
|
|
row = {'calendarId': calId,
|
|
'JSON': json.dumps(_getMain().cleanJSON(rule), ensure_ascii=False, sort_keys=False)}
|
|
if user:
|
|
row['primaryEmail'] = user
|
|
if addCSVData:
|
|
row.update(addCSVData)
|
|
csvPF.WriteRowNoFilter(row)
|
|
elif GC.Values[GC.CSV_OUTPUT_USERS_AUDIT] and user:
|
|
csvPF.WriteRowNoFilter({'calendarId': calId, 'primaryEmail': user})
|
|
else: # Ent.RESOURCE_CALENDAR
|
|
for rule in acls:
|
|
if noSelfOwner and rule['role'] == 'owner' and rule['scope']['value'] == calId:
|
|
continue
|
|
row = {'resourceId': user, 'resourceEmail': calId}
|
|
if addCSVData:
|
|
row.update(addCSVData)
|
|
_getMain().flattenJSON(rule, flattened=row)
|
|
if not FJQC.formatJSON:
|
|
csvPF.WriteRowTitles(row)
|
|
elif csvPF.CheckRowTitles(row):
|
|
row = {'resourceId': user, 'resourceEmail': calId,
|
|
'JSON': json.dumps(_getMain().cleanJSON(rule), ensure_ascii=False, sort_keys=False)}
|
|
if addCSVData:
|
|
row.update(addCSVData)
|
|
csvPF.WriteRowNoFilter(row)
|
|
|
|
def _getCalendarPrintShowACLOptions(titles):
|
|
csvPF = _getMain().CSVPrintFile(titles, 'sortall') if Act.csvFormat() else None
|
|
FJQC = _getMain().FormatJSONQuoteChar(csvPF)
|
|
noSelfOwner = False
|
|
addCSVData = {}
|
|
while Cmd.ArgumentsRemaining():
|
|
myarg = _getMain().getArgument()
|
|
if csvPF and myarg == 'todrive':
|
|
csvPF.GetTodriveParameters()
|
|
elif myarg == 'noselfowner':
|
|
noSelfOwner = True
|
|
elif csvPF and myarg == 'addcsvdata':
|
|
_getMain().getAddCSVData(addCSVData)
|
|
else:
|
|
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
|
if csvPF:
|
|
if addCSVData:
|
|
csvPF.AddTitles(sorted(addCSVData.keys()))
|
|
if FJQC.formatJSON:
|
|
csvPF.AddJSONTitles(sorted(addCSVData.keys()))
|
|
csvPF.MoveJSONTitlesToEnd(['JSON'])
|
|
csvPF.SetSortAllTitles()
|
|
return (csvPF, FJQC, noSelfOwner, addCSVData)
|
|
|
|
# gam calendars <CalendarEntity> print acls [todrive <ToDriveAttribute>*]
|
|
# [noselfowner] (addcsvdata <FieldName> <String>)*
|
|
# [formatjson [quotechar <Character>]]
|
|
# gam calendars <CalendarEntity> show acls
|
|
# [noselfowner]
|
|
# [formatjson]
|
|
# gam calendar <CalendarEntity> printacl [todrive <ToDriveAttribute>*]
|
|
# [noselfowner] (addcsvdata <FieldName> <String>)*
|
|
# [formatjson]
|
|
# gam calendar <CalendarEntity> showacl
|
|
# [noselfowner]
|
|
# [formatjson]
|
|
def doCalendarsPrintShowACLs(calIds):
|
|
csvPF, FJQC, noSelfOwner, addCSVData = _getCalendarPrintShowACLOptions(['calendarId'])
|
|
count = len(calIds)
|
|
i = 0
|
|
for calId in calIds:
|
|
i += 1
|
|
calId, cal = validateCalendar(calId, i, count)
|
|
if not cal:
|
|
continue
|
|
_printShowCalendarACLs(cal, None, Ent.CALENDAR, calId, i, count, csvPF, FJQC, noSelfOwner, addCSVData)
|
|
if csvPF:
|
|
csvPF.writeCSVfile('Calendar ACLs')
|
|
|
|
EVENT_TYPE_BIRTHDAY = 'birthday'
|
|
EVENT_TYPE_DEFAULT = 'default'
|
|
EVENT_TYPE_FOCUSTIME = 'focusTime'
|
|
EVENT_TYPE_FROMGMAIL = 'fromGmail'
|
|
EVENT_TYPE_OUTOFOFFICE = 'outOfOffice'
|
|
EVENT_TYPE_WORKINGLOCATION = 'workingLocation'
|
|
|
|
EVENT_TYPES_CHOICE_MAP = {
|
|
'birthday': EVENT_TYPE_BIRTHDAY,
|
|
'default': EVENT_TYPE_DEFAULT,
|
|
'focustime': EVENT_TYPE_FOCUSTIME,
|
|
'fromgmail': EVENT_TYPE_FROMGMAIL,
|
|
'outofoffice': EVENT_TYPE_OUTOFOFFICE,
|
|
'workinglocation': EVENT_TYPE_WORKINGLOCATION,
|
|
}
|
|
|
|
EVENT_TYPE_PROPERTIES_NAME_MAP = {
|
|
EVENT_TYPE_DEFAULT: None,
|
|
EVENT_TYPE_FOCUSTIME: f'{EVENT_TYPE_FOCUSTIME}Properties',
|
|
EVENT_TYPE_FROMGMAIL: None,
|
|
EVENT_TYPE_OUTOFOFFICE: f'{EVENT_TYPE_OUTOFOFFICE}Properties',
|
|
EVENT_TYPE_WORKINGLOCATION: f'{EVENT_TYPE_WORKINGLOCATION}Properties',
|
|
}
|
|
|
|
EVENT_TYPE_ENTITY_MAP = {
|
|
EVENT_TYPE_BIRTHDAY: Ent.EVENT_BIRTHDAY,
|
|
EVENT_TYPE_DEFAULT: None,
|
|
EVENT_TYPE_FOCUSTIME: Ent.EVENT_FOCUSTIME,
|
|
EVENT_TYPE_FROMGMAIL: None,
|
|
EVENT_TYPE_OUTOFOFFICE: Ent.EVENT_OUTOFOFFICE,
|
|
EVENT_TYPE_WORKINGLOCATION: Ent.EVENT_WORKINGLOCATION,
|
|
}
|
|
|
|
def _getEventTypes():
|
|
typesList = []
|
|
for field in _getMain()._getFieldsList():
|
|
if field in EVENT_TYPES_CHOICE_MAP:
|
|
_getMain().addFieldToFieldsList(field, EVENT_TYPES_CHOICE_MAP, typesList)
|
|
else:
|
|
_getMain().invalidChoiceExit(field, EVENT_TYPES_CHOICE_MAP, True)
|
|
# return ','.join(typesList)
|
|
return typesList
|
|
|
|
LIST_EVENTS_DISPLAY_PROPERTIES = {
|
|
'alwaysincludeemail': ('alwaysIncludeEmail', {GC.VAR_TYPE: GC.TYPE_BOOLEAN}),
|
|
'icaluid': ('iCalUID', {GC.VAR_TYPE: GC.TYPE_STRING}),
|
|
'maxattendees': ('maxAttendees', {GC.VAR_TYPE: GC.TYPE_INTEGER, GC.VAR_LIMITS: (1, None)}),
|
|
'orderby': ('orderBy', {GC.VAR_TYPE: GC.TYPE_CHOICE, 'choices': {'starttime': 'startTime', 'updated': 'updated'}}),
|
|
'timezone': ('timeZone', {GC.VAR_TYPE: GC.TYPE_STRING}),
|
|
}
|
|
|
|
LIST_EVENTS_SELECT_PROPERTIES = {
|
|
'after': ('timeMin', {GC.VAR_TYPE: GC.TYPE_DATETIME}),
|
|
'before': ('timeMax', {GC.VAR_TYPE: GC.TYPE_DATETIME}),
|
|
'endtime': ('timeMax', {GC.VAR_TYPE: GC.TYPE_DATETIME}),
|
|
'includedeleted': ('showDeleted', {GC.VAR_TYPE: GC.TYPE_BOOLEAN}),
|
|
'includehidden': ('showHiddenInvitations', {GC.VAR_TYPE: GC.TYPE_BOOLEAN}),
|
|
'privateextendedproperty': ('privateExtendedProperty', {GC.VAR_TYPE: GC.TYPE_STRING}),
|
|
'sharedextendedproperty': ('sharedExtendedProperty', {GC.VAR_TYPE: GC.TYPE_STRING}),
|
|
'showdeletedevents': ('showDeleted', {GC.VAR_TYPE: GC.TYPE_BOOLEAN}),
|
|
'showhiddeninvitations': ('showHiddenInvitations', {GC.VAR_TYPE: GC.TYPE_BOOLEAN}),
|
|
'singleevents': ('singleEvents', {GC.VAR_TYPE: GC.TYPE_BOOLEAN}),
|
|
'starttime': ('timeMin', {GC.VAR_TYPE: GC.TYPE_DATETIME}),
|
|
'timemax': ('timeMax', {GC.VAR_TYPE: GC.TYPE_DATETIME}),
|
|
'timemin': ('timeMin', {GC.VAR_TYPE: GC.TYPE_DATETIME}),
|
|
'updated': ('updatedMin', {GC.VAR_TYPE: GC.TYPE_DATETIME}),
|
|
'updatedmin': ('updatedMin', {GC.VAR_TYPE: GC.TYPE_DATETIME}),
|
|
'eventtype': ('eventTypes', {GC.VAR_TYPE: GC.TYPE_CHOICE_LIST}),
|
|
'eventtypes': ('eventTypes', {GC.VAR_TYPE: GC.TYPE_CHOICE_LIST}),
|
|
}
|
|
|
|
LIST_EVENTS_MATCH_FIELDS = {
|
|
'attendees': ['attendees', 'email'],
|
|
'attendeesorganizer': ['attendees', 'organizer'],
|
|
'attendeesorganiser': ['attendees', 'organizer'],
|
|
'attendeesonlydomainlist': ['attendees', 'onlydomainlist'],
|
|
'attendeesdomainlist': ['attendees', 'domainlist'],
|
|
'attendeesnotdomainlist': ['attendees', 'notdomainlist'],
|
|
'attendeespattern': ['attendees', 'match'],
|
|
'attendeesstatus': ['attendees', 'status'],
|
|
'description': ['description'],
|
|
'hangoutlink': ['hangoutLink'],
|
|
'location': ['location'],
|
|
'summary': ['summary'],
|
|
'creatorname': ['creator', 'displayName'],
|
|
'creatoremail': ['creator', 'email'],
|
|
'organizername': ['organizer', 'displayName'],
|
|
'organizeremail': ['organizer', 'email'],
|
|
'organizerself': ['organizer', 'self'],
|
|
'organisername': ['organizer', 'displayName'],
|
|
'organiseremail': ['organizer', 'email'],
|
|
'organiserself': ['organizer', 'self'],
|
|
'status': ['status'],
|
|
'transparency': ['transparency'],
|
|
'visibility': ['visibility'],
|
|
}
|
|
|
|
def _getCalendarListEventsProperty(myarg, attributes, kwargs):
|
|
attrName, attribute = attributes.get(myarg, (None, None))
|
|
if not attrName:
|
|
return False
|
|
attrType = attribute[GC.VAR_TYPE]
|
|
if attrType == GC.TYPE_BOOLEAN:
|
|
kwargs[attrName] = True
|
|
elif attrType == GC.TYPE_STRING:
|
|
kwargs[attrName] = _getMain().getString(Cmd.OB_STRING)
|
|
elif attrType == GC.TYPE_CHOICE:
|
|
kwargs[attrName] = _getMain().getChoice(attribute['choices'], mapChoice=True)
|
|
elif attrType == GC.TYPE_DATETIME:
|
|
kwargs[attrName] = _getMain().getTimeOrDeltaFromNow()
|
|
elif attrType == GC.TYPE_INTEGER:
|
|
minVal, maxVal = attribute[GC.VAR_LIMITS]
|
|
kwargs[attrName] = _getMain().getInteger(minVal=minVal, maxVal=maxVal)
|
|
else: # elif attrType == GC.TYPE_CHOICE_LIST:
|
|
if attrName == 'eventTypes':
|
|
kwargs[attrName] = _getEventTypes()
|
|
return True
|
|
|
|
def _getCalendarListEventsDisplayProperty(myarg, calendarEventEntity):
|
|
return _getCalendarListEventsProperty(myarg, LIST_EVENTS_DISPLAY_PROPERTIES, calendarEventEntity['kwargs'])
|
|
|
|
def initCalendarEventEntity():
|
|
return {'list': [], 'queries': [], 'kwargs': {}, 'dict': None,
|
|
'matches': [], 'maxinstances': -1, 'showDayOfWeek': False,
|
|
'countsOnly': False, 'eventRowFilter': False, 'countsOnlyTitles': []}
|
|
|
|
def getCalendarEventEntity():
|
|
calendarEventEntity = initCalendarEventEntity()
|
|
while Cmd.ArgumentsRemaining():
|
|
myarg = _getMain().getArgument()
|
|
if myarg in {'event', 'events'}:
|
|
entitySelector = _getMain().getEntitySelector()
|
|
if entitySelector:
|
|
entityList = _getMain().getEntitySelection(entitySelector, False)
|
|
if isinstance(entityList, dict):
|
|
calendarEventEntity['dict'] = entityList
|
|
else:
|
|
calendarEventEntity['list'] = entityList
|
|
else:
|
|
calendarEventEntity['list'].extend(_getMain().convertEntityToList(_getMain().getString(Cmd.OB_EVENT_ID)))
|
|
elif myarg in {'id', 'eventid'}:
|
|
calendarEventEntity['list'].append(_getMain().getString(Cmd.OB_EVENT_ID))
|
|
elif myarg in {'q', 'query', 'eventquery'}:
|
|
calendarEventEntity['queries'].append(_getMain().getString(Cmd.OB_QUERY))
|
|
elif myarg == 'matchfield':
|
|
matchField = _getMain().getChoice(LIST_EVENTS_MATCH_FIELDS, mapChoice=True)
|
|
if matchField[0] == 'organizer' and matchField[1] == 'self':
|
|
calendarEventEntity['matches'].append((matchField, _getMain().getBoolean()))
|
|
elif matchField[0] != 'attendees' or matchField[1] == 'match':
|
|
calendarEventEntity['matches'].append((matchField, _getMain().getREPattern(re.IGNORECASE)))
|
|
elif matchField[0] == 'attendees' and matchField[1] in {'onlydomainlist', 'domainlist', 'notdomainlist'}:
|
|
calendarEventEntity['matches'].append((matchField, set(_getMain().getString(Cmd.OB_DOMAIN_NAME_LIST).replace(',', ' ').split())))
|
|
elif matchField[1] == 'email':
|
|
calendarEventEntity['matches'].append((matchField, _getMain().getNormalizedEmailAddressEntity()))
|
|
elif matchField[1] == 'organizer':
|
|
calendarEventEntity['matches'].append((matchField, _getMain().getBoolean(defaultValue=None), _getMain().getNormalizedEmailAddressEntity()))
|
|
else: #status
|
|
calendarEventEntity['matches'].append((matchField,
|
|
_getMain().getChoice(CALENDAR_ATTENDEE_OPTIONAL_CHOICE_MAP, defaultChoice=False, mapChoice=True),
|
|
_getMain().getChoice(CALENDAR_ATTENDEE_STATUS_CHOICE_MAP, defaultChoice='needsAction', mapChoice=True),
|
|
_getMain().getNormalizedEmailAddressEntity()))
|
|
elif myarg == 'maxinstances':
|
|
calendarEventEntity['maxinstances'] = _getMain().getInteger(minVal=-1)
|
|
elif _getCalendarListEventsProperty(myarg, LIST_EVENTS_SELECT_PROPERTIES, calendarEventEntity['kwargs']):
|
|
pass
|
|
else:
|
|
Cmd.Backup()
|
|
break
|
|
return calendarEventEntity
|
|
|
|
CALENDAR_EVENT_SENDUPDATES_CHOICE_MAP = {'all': 'all', 'externalonly': 'externalOnly', 'none': 'none'}
|
|
|
|
def _getCalendarSendUpdates(myarg, parameters):
|
|
if myarg == 'sendnotifications':
|
|
parameters['sendUpdates'] = 'all' if _getMain().getBoolean() else 'none'
|
|
elif myarg == 'notifyattendees':
|
|
parameters['sendUpdates'] = 'all'
|
|
elif myarg == 'sendupdates':
|
|
parameters['sendUpdates'] = _getMain().getChoice(CALENDAR_EVENT_SENDUPDATES_CHOICE_MAP, mapChoice=True)
|
|
else:
|
|
return False
|
|
return True
|
|
|
|
def _getCalendarEventReminders(myarg, body):
|
|
if myarg == 'noreminders':
|
|
body['reminders'] = {'overrides': [], 'useDefault': False}
|
|
elif myarg == 'reminder':
|
|
body.setdefault('reminders', {'overrides': [], 'useDefault': False})
|
|
body['reminders']['overrides'].append(_getMain().getCalendarReminder())
|
|
else:
|
|
return False
|
|
return True
|
|
|
|
CALENDAR_MIN_COLOR_INDEX = 1
|
|
CALENDAR_MAX_COLOR_INDEX = 24
|
|
|
|
CALENDAR_EVENT_MIN_COLOR_INDEX = 1
|
|
CALENDAR_EVENT_MAX_COLOR_INDEX = 11
|
|
|
|
CALENDAR_ATTENDEE_OPTIONAL_CHOICE_MAP = {
|
|
'optional': True,
|
|
'required': False,
|
|
'true': True,
|
|
'false': False,
|
|
'': None,
|
|
}
|
|
CALENDAR_ATTENDEE_STATUS_CHOICE_MAP = {
|
|
'accepted': 'accepted',
|
|
'declined': 'declined',
|
|
'needsaction': 'needsAction',
|
|
'tentative': 'tentative',
|
|
'': None,
|
|
}
|
|
CALENDAR_EVENT_STATUS_CHOICES = ['confirmed', 'tentative', 'cancelled']
|
|
CALENDAR_EVENT_TRANSPARENCY_CHOICES = ['opaque', 'transparent']
|
|
CALENDAR_EVENT_VISIBILITY_CHOICES = ['default', 'public', 'private', 'confedential']
|
|
|
|
EVENT_JSON_CLEAR_FIELDS = ['created', 'creator', 'endTimeUpspecified', 'hangoutLink', 'htmlLink', 'eventType',
|
|
'privateCopy', 'locked', 'recurringEventId', 'updated']
|
|
EVENT_JSON_INSERT_CLEAR_FIELDS = ['iCalUID', 'id', 'organizer']
|
|
EVENT_JSON_UPDATE_CLEAR_FIELDS = ['iCalUID', 'id', 'organizer']
|
|
EVENT_JSON_SUBFIELD_CLEAR_FIELDS = {
|
|
'attendees': ['id', 'organizer', 'self'],
|
|
'attachments': ['fileId', 'iconLink', 'mimeType', 'title'],
|
|
'organizer': ['id', 'self'],
|
|
}
|
|
EVENT_JSONATTENDEES_SUBFIELD_CLEAR_FIELDS = {
|
|
'attendees': ['id', 'organizer', 'self'],
|
|
}
|
|
|
|
def _getCalendarEventAttribute(myarg, body, parameters, function):
|
|
def clearJSONfields(body, clearFields):
|
|
for field in clearFields:
|
|
body.pop(field, None)
|
|
|
|
def clearJSONsubfields(body, clearFields):
|
|
for field, subfields in clearFields.items():
|
|
if field in body:
|
|
if isinstance(body[field], list):
|
|
for item in body[field]:
|
|
for subfield in subfields:
|
|
item.pop(subfield, None)
|
|
else:
|
|
for subfield in subfields:
|
|
body.pop(subfield, None)
|
|
|
|
cd = None
|
|
if function == 'insert' and myarg in {'id', 'eventid'}:
|
|
body['id'] = _getMain().getEventID()
|
|
elif function == 'import' and myarg == 'icaluid':
|
|
body['iCalUID'] = _getMain().getString(Cmd.OB_ICALUID)
|
|
elif myarg == 'description':
|
|
body['description'] = _getMain().getStringWithCRsNLs()
|
|
elif function == 'update' and myarg == 'replacedescription':
|
|
parameters['replaceDescription'].append(_getMain().getREPatternSubstitution(re.IGNORECASE))
|
|
elif myarg == 'location':
|
|
body['location'] = _getMain().getString(Cmd.OB_STRING, minLen=0)
|
|
elif myarg == 'source':
|
|
body['source'] = {'title': _getMain().getString(Cmd.OB_STRING), 'url': _getMain().getString(Cmd.OB_URL)}
|
|
elif myarg == 'summary':
|
|
body['summary'] = _getMain().getString(Cmd.OB_STRING, minLen=0)
|
|
elif myarg in {'start', 'starttime'}:
|
|
body['start'] = _getMain().getEventTime()
|
|
elif myarg in {'originalstart', 'originalstarttime'}:
|
|
body['originalStart'] = _getMain().getEventTime()
|
|
elif myarg in {'end', 'endtime'}:
|
|
body['end'] = _getMain().getEventTime()
|
|
elif myarg == 'allday':
|
|
body['start'] = body['end'] = {'date': _getMain().getYYYYMMDD()}
|
|
elif myarg == 'range':
|
|
body['start'] = {'date': _getMain().getYYYYMMDD()}
|
|
body['end'] = {'date': _getMain().getYYYYMMDD()}
|
|
elif myarg == 'timerange':
|
|
body['start'] = {'dateTime': _getMain().getTimeOrDeltaFromNow()}
|
|
body['end'] = {'dateTime': _getMain().getTimeOrDeltaFromNow()}
|
|
elif myarg == 'birthday':
|
|
body['eventType'] = EVENT_TYPE_BIRTHDAY
|
|
body['visibility'] = 'private'
|
|
body['transparency'] = 'transparent'
|
|
bday = _getMain().getYYYYMMDD(returnDateTime=True)
|
|
body['start'] = body['end'] = {'date': bday.strftime(_getMain().YYYYMMDD_FORMAT)}
|
|
if bday.month != 2 or bday.day != 29:
|
|
body['recurrence'] = ['RRULE:FREQ=YEARLY']
|
|
else:
|
|
body['recurrence'] = ['RRULE:FREQ=YEARLY;BYMONTH=2;BYMONTHDAY=-1']
|
|
elif myarg == 'attachment':
|
|
body.setdefault('attachments', [])
|
|
body['attachments'].append({'title': _getMain().getString(Cmd.OB_STRING), 'fileUrl': _getMain().getString(Cmd.OB_URL)})
|
|
elif function == 'update' and myarg == 'clearattachments':
|
|
body['attachments'] = []
|
|
elif myarg in {'hangoutsmeet', 'googlemeet'}:
|
|
body['conferenceData'] = {'createRequest': {'conferenceSolutionKey': {'type': 'hangoutsMeet'}, 'requestId': f'{str(uuid.uuid4())}'}}
|
|
elif myarg == 'conferencedata':
|
|
_getMain().checkArgumentPresent(['meet'], True)
|
|
epLabel = _getMain().getString(Cmd.OB_MEET_ID)
|
|
if not _getMain().GOOGLE_MEETID_PATTERN.match(epLabel):
|
|
_getMain().invalidArgumentExit(_getMain().GOOGLE_MEETID_FORMAT_REQUIRED)
|
|
body['conferenceData'] = {"conferenceId": epLabel,
|
|
"conferenceSolution": {"key": {"type": "hangoutsMeet"}},
|
|
"entryPoints": [{"entryPointType": "video", "label": f'meet.google.com/{epLabel}',
|
|
"uri": f'https://meet.google.com/{epLabel}'}]}
|
|
elif function == 'update' and myarg in {'clearhangoutsmeet', 'cleargooglemeet'}:
|
|
body['conferenceData'] = None
|
|
elif myarg == 'recurrence':
|
|
body.setdefault('recurrence', [])
|
|
body['recurrence'].append(_getMain().getString(Cmd.OB_RECURRENCE))
|
|
elif myarg == 'timezone':
|
|
parameters['timeZone'] = _getMain().getString(Cmd.OB_STRING)
|
|
elif function == 'update' and myarg == 'replacemode':
|
|
parameters['replaceMode'] = True
|
|
elif function == 'update' and myarg == 'clearattendees':
|
|
parameters['clearAttendees'] = True
|
|
elif function == 'update' and myarg == 'removeattendee':
|
|
parameters['removeAttendees'].add(_getMain().getEmailAddress(noUid=True))
|
|
elif function == 'update' and myarg == 'selectremoveattendees':
|
|
_, attendeeList = _getMain().getEntityToModify(defaultEntityType=Cmd.ENTITY_USERS)
|
|
for attendee in attendeeList:
|
|
parameters['removeAttendees'].add(_getMain().normalizeEmailAddressOrUID(attendee, noUid=True))
|
|
elif myarg == 'attendee':
|
|
parameters['attendees'].append({'email': _getMain().getEmailAddress(noUid=True)})
|
|
elif myarg == 'optionalattendee':
|
|
parameters['attendees'].append({'email': _getMain().getEmailAddress(noUid=True), 'optional': True})
|
|
elif myarg in {'attendeestatus', 'selectattendees'}:
|
|
optional = _getMain().getChoice(CALENDAR_ATTENDEE_OPTIONAL_CHOICE_MAP, defaultChoice=None, mapChoice=True)
|
|
responseStatus = _getMain().getChoice(CALENDAR_ATTENDEE_STATUS_CHOICE_MAP, defaultChoice=None, mapChoice=True)
|
|
if myarg == 'attendeestatus':
|
|
attendeeList = [_getMain().getEmailAddress(noUid=True)]
|
|
else:
|
|
_, attendeeList = _getMain().getEntityToModify(defaultEntityType=Cmd.ENTITY_USERS)
|
|
for attendee in attendeeList:
|
|
addAttendee = {'email': _getMain().normalizeEmailAddressOrUID(attendee, noUid=True)}
|
|
if optional is not None:
|
|
addAttendee['optional'] = optional
|
|
if responseStatus is not None:
|
|
addAttendee['responseStatus'] = responseStatus
|
|
parameters['attendees'].append(addAttendee)
|
|
elif function == 'update' and myarg == 'clearresources':
|
|
parameters['clearResources'] = True
|
|
elif myarg == 'resource':
|
|
if cd is None:
|
|
cd = _getMain().buildGAPIObject(API.DIRECTORY)
|
|
parameters['attendees'].append({'email': _validateResourceId(cd, _getMain().getString(Cmd.OB_RESOURCE_ID), 0, 0, True),
|
|
'responseStatus': 'accepted', 'resource': True})
|
|
elif myarg == 'removeresource':
|
|
if cd is None:
|
|
cd = _getMain().buildGAPIObject(API.DIRECTORY)
|
|
parameters['removeAttendees'].add(_validateResourceId(cd, _getMain().getString(Cmd.OB_RESOURCE_ID), 0, 0, True))
|
|
elif myarg == 'json':
|
|
jsonData = _getMain().getJSON(EVENT_JSON_CLEAR_FIELDS)
|
|
if function == 'insert':
|
|
body.update(jsonData)
|
|
clearJSONfields(body, EVENT_JSON_INSERT_CLEAR_FIELDS)
|
|
elif function == 'import':
|
|
if 'id' in jsonData:
|
|
jsonData['iCalUID'] = jsonData.pop('id')
|
|
body.update(jsonData)
|
|
elif function == 'update':
|
|
if 'event' in jsonData and 'attendees' in jsonData['event']:
|
|
parameters['attendees'].extend(jsonData['event'].pop('attendees'))
|
|
clearJSONsubfields(parameters, EVENT_JSONATTENDEES_SUBFIELD_CLEAR_FIELDS)
|
|
body.update(jsonData)
|
|
clearJSONfields(body, EVENT_JSON_UPDATE_CLEAR_FIELDS)
|
|
clearJSONsubfields(body, EVENT_JSON_SUBFIELD_CLEAR_FIELDS)
|
|
if ('conferenceData' in body and body['conferenceData'] and
|
|
'createRequest' in body['conferenceData'] and
|
|
'status' in body['conferenceData']['createRequest']):
|
|
body['conferenceData']['createRequest']['status'].pop('statusCode', None)
|
|
elif myarg == 'jsonattendees':
|
|
jsonData = _getMain().getJSON([])
|
|
if 'event' in jsonData and 'attendees' in jsonData['event']:
|
|
parameters['attendees'].extend(jsonData['event']['attendees'])
|
|
elif 'attendees' in jsonData:
|
|
parameters['attendees'].extend(jsonData['attendees'])
|
|
clearJSONsubfields(parameters, EVENT_JSONATTENDEES_SUBFIELD_CLEAR_FIELDS)
|
|
elif function != 'import' and _getCalendarSendUpdates(myarg, parameters):
|
|
pass
|
|
elif myarg == 'anyonecanaddself':
|
|
body['anyoneCanAddSelf'] = _getMain().getBoolean()
|
|
elif myarg == 'guestscaninviteothers':
|
|
body['guestsCanInviteOthers'] = _getMain().getBoolean()
|
|
elif myarg == 'guestscantinviteothers':
|
|
body['guestsCanInviteOthers'] = False
|
|
elif myarg == 'guestscanmodify':
|
|
body['guestsCanModify'] = _getMain().getBoolean()
|
|
elif myarg == 'guestscanseeotherguests':
|
|
body['guestsCanSeeOtherGuests'] = _getMain().getBoolean()
|
|
elif myarg == 'guestscantseeotherguests':
|
|
body['guestsCanSeeOtherGuests'] = False
|
|
elif myarg == 'status':
|
|
body['status'] = _getMain().getChoice(CALENDAR_EVENT_STATUS_CHOICES)
|
|
elif myarg == 'tentative':
|
|
body['status'] = 'tentative'
|
|
elif myarg == 'transparency':
|
|
body['transparency'] = _getMain().getChoice(CALENDAR_EVENT_TRANSPARENCY_CHOICES)
|
|
elif myarg == 'available':
|
|
body['transparency'] = 'transparent'
|
|
elif myarg == 'visibility':
|
|
body['visibility'] = _getMain().getChoice(CALENDAR_EVENT_VISIBILITY_CHOICES)
|
|
elif myarg in {'color', 'colour'}:
|
|
body['colorId'] = _getMain().getChoice(_getMain().CALENDAR_EVENT_COLOR_MAP, mapChoice=True)
|
|
elif myarg in {'colorindex', 'colorid', 'colourindex', 'colourid'}:
|
|
body['colorId'] = _getMain().getInteger(CALENDAR_EVENT_MIN_COLOR_INDEX, CALENDAR_EVENT_MAX_COLOR_INDEX)
|
|
elif _getCalendarEventReminders(myarg, body):
|
|
pass
|
|
elif myarg == 'sequence':
|
|
body['sequence'] = _getMain().getInteger(minVal=0)
|
|
elif myarg == 'privateproperty':
|
|
body.setdefault('extendedProperties', {})
|
|
body['extendedProperties'].setdefault('private', {})
|
|
key = _getMain().getString(Cmd.OB_PROPERTY_KEY)
|
|
body['extendedProperties']['private'][key] = _getMain().getString(Cmd.OB_PROPERTY_VALUE, minLen=0)
|
|
elif myarg == 'sharedproperty':
|
|
body.setdefault('extendedProperties', {})
|
|
body['extendedProperties'].setdefault('shared', {})
|
|
key = _getMain().getString(Cmd.OB_PROPERTY_KEY)
|
|
body['extendedProperties']['shared'][key] = _getMain().getString(Cmd.OB_PROPERTY_VALUE, minLen=0)
|
|
elif function == 'update' and myarg == 'clearprivateproperty':
|
|
body.setdefault('extendedProperties', {})
|
|
body['extendedProperties'].setdefault('private', {})
|
|
body['extendedProperties']['private'][_getMain().getString(Cmd.OB_PROPERTY_KEY)] = None
|
|
elif function == 'update' and myarg == 'clearsharedproperty':
|
|
body.setdefault('extendedProperties', {})
|
|
body['extendedProperties'].setdefault('shared', {})
|
|
body['extendedProperties']['shared'][_getMain().getString(Cmd.OB_PROPERTY_KEY)] = None
|
|
elif function == 'import' and myarg in {'organizername', 'organisername'}:
|
|
body.setdefault('organizer', {})
|
|
body['organizer']['displayName'] = _getMain().getString(Cmd.OB_NAME)
|
|
elif function == 'import' and myarg in {'organizeremail', 'organiseremail'}:
|
|
body.setdefault('organizer', {})
|
|
body['organizer']['email'] = _getMain().getEmailAddress(noUid=True)
|
|
else:
|
|
return False
|
|
return True
|
|
|
|
def _getEventMatchFields(calendarEventEntity, fieldsList):
|
|
for match in calendarEventEntity['matches']:
|
|
if match[0][0] != 'attendees':
|
|
fieldsList.append(match[0][0])
|
|
else:
|
|
fieldsList.append('attendees/email')
|
|
if match[0][1] == 'status':
|
|
fieldsList.extend(['attendees/optional', 'attendees/responseStatus'])
|
|
|
|
def _eventMatches(event, match):
|
|
if match[0][0] != 'attendees':
|
|
eventAttr = event
|
|
for attr in match[0]:
|
|
eventAttr = eventAttr.get(attr, '')
|
|
if not eventAttr:
|
|
break
|
|
if match[0][0] == 'organizer' and match[0][1] == 'self':
|
|
return bool(eventAttr) == match[1]
|
|
if match[0][0] != 'hangoutLink':
|
|
return match[1].search(eventAttr) is not None
|
|
# vkj-przn-nvg or vkjprznnvg
|
|
return match[1].search(eventAttr) is not None or match[1].search(eventAttr.replace('-', '')) is not None
|
|
attendees = [attendee['email'] for attendee in event.get('attendees', []) if 'email' in attendee]
|
|
if not attendees:
|
|
return False
|
|
if match[0][1] == 'email':
|
|
for attendee in match[1]:
|
|
if attendee not in attendees:
|
|
return False
|
|
return True
|
|
if match[0][1] == 'match':
|
|
for attendee in attendees:
|
|
if match[1].search(attendee) is not None:
|
|
return True
|
|
return False
|
|
if match[0][1] == 'onlydomainlist':
|
|
for attendee in attendees:
|
|
_, domain = attendee.lower().split('@', 1)
|
|
if domain not in match[1]:
|
|
return False
|
|
return True
|
|
if match[0][1] == 'domainlist':
|
|
for attendee in attendees:
|
|
_, domain = attendee.lower().split('@', 1)
|
|
if domain in match[1]:
|
|
return True
|
|
return False
|
|
if match[0][1] == 'notdomainlist':
|
|
for attendee in attendees:
|
|
_, domain = attendee.lower().split('@', 1)
|
|
if domain not in match[1]:
|
|
return True
|
|
return False
|
|
if match[0][1] == 'organizer':
|
|
for matchEmail in match[2]:
|
|
for attendee in event['attendees']:
|
|
if 'email' in attendee and matchEmail == attendee['email']:
|
|
if attendee.get('organizer', False) != match[1]:
|
|
return False
|
|
break
|
|
else:
|
|
return False
|
|
return True
|
|
# if match[0][1] == 'status':
|
|
for matchEmail in match[3]:
|
|
for attendee in event['attendees']:
|
|
if 'email' in attendee and matchEmail == attendee['email']:
|
|
if attendee.get('optional', False) != match[1] or attendee.get('responseStatus') != match[2]:
|
|
return False
|
|
break
|
|
else:
|
|
return False
|
|
return True
|
|
|
|
def _validateCalendarGetEventIDs(origUser, user, origCal, calId, j, jcount, calendarEventEntity, doIt=True, showAction=True):
|
|
if calendarEventEntity['dict']:
|
|
if origUser:
|
|
if not GM.Globals[GM.CSV_SUBKEY_FIELD]:
|
|
calEventIds = calendarEventEntity['dict'][calId]
|
|
else:
|
|
calEventIds = calendarEventEntity['dict'][origUser][calId]
|
|
else:
|
|
calEventIds = calendarEventEntity['dict'][calId]
|
|
else:
|
|
calEventIds = calendarEventEntity['list']
|
|
calId, cal = getNormalizedCalIdCal(origCal, calId, user, j, jcount)
|
|
if not cal:
|
|
return (calId, cal, None, 0)
|
|
if not calEventIds:
|
|
fieldsList = ['id']
|
|
_getEventMatchFields(calendarEventEntity, fieldsList)
|
|
fields = ','.join(fieldsList)
|
|
try:
|
|
eventIdsSet = set()
|
|
calEventIds = []
|
|
if len(calendarEventEntity['queries']) <= 1:
|
|
if len(calendarEventEntity['queries']) == 1:
|
|
calendarEventEntity['kwargs']['q'] = calendarEventEntity['queries'][0]
|
|
events = _getMain().callGAPIpages(cal.events(), 'list', 'items',
|
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.INVALID],
|
|
calendarId=calId, fields=f'nextPageToken,items({fields})',
|
|
maxResults=GC.Values[GC.EVENT_MAX_RESULTS], **calendarEventEntity['kwargs'])
|
|
for event in events:
|
|
for match in calendarEventEntity['matches']:
|
|
if not _eventMatches(event, match):
|
|
break
|
|
else:
|
|
calEventIds.append(event['id'])
|
|
else:
|
|
for query in calendarEventEntity['queries']:
|
|
calendarEventEntity['kwargs']['q'] = query
|
|
events = _getMain().callGAPIpages(cal.events(), 'list', 'items',
|
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.INVALID],
|
|
calendarId=calId, fields=f'nextPageToken,items({fields})',
|
|
maxResults=GC.Values[GC.EVENT_MAX_RESULTS], **calendarEventEntity['kwargs'])
|
|
for event in events:
|
|
for match in calendarEventEntity['matches']:
|
|
if not _eventMatches(event, match):
|
|
break
|
|
else:
|
|
eventId = event['id']
|
|
if eventId not in eventIdsSet:
|
|
calEventIds.append(eventId)
|
|
eventIdsSet.add(eventId)
|
|
kcount = len(calEventIds)
|
|
if kcount == 0:
|
|
_getMain().entityNumEntitiesActionNotPerformedWarning([Ent.CALENDAR, calId], Ent.EVENT, kcount, Msg.NO_ENTITIES_MATCHED.format(Ent.Plural(Ent.EVENT)), j, jcount)
|
|
_getMain().setSysExitRC(_getMain().NO_ENTITIES_FOUND_RC)
|
|
return (calId, cal, None, 0)
|
|
except GAPI.notFound:
|
|
_getMain().entityUnknownWarning(Ent.CALENDAR, calId, j, jcount)
|
|
return (calId, cal, None, 0)
|
|
except (GAPI.forbidden, GAPI.invalid) as e:
|
|
_getMain().entityActionFailedWarning([Ent.CALENDAR, calId], str(e), j, jcount)
|
|
return (calId, cal, None, 0)
|
|
except GAPI.notACalendarUser:
|
|
_getMain().userCalServiceNotEnabledWarning(calId, j, jcount)
|
|
return (calId, cal, None, 0)
|
|
else:
|
|
kcount = len(calEventIds)
|
|
if kcount == 0:
|
|
_getMain().setSysExitRC(_getMain().NO_ENTITIES_FOUND_RC)
|
|
if not doIt:
|
|
if showAction:
|
|
_getMain().entityNumEntitiesActionNotPerformedWarning([Ent.CALENDAR, calId], Ent.EVENT, kcount, Msg.USE_DOIT_ARGUMENT_TO_PERFORM_ACTION, j, jcount)
|
|
return (calId, cal, None, 0)
|
|
if showAction:
|
|
_getMain().entityPerformActionNumItems([Ent.CALENDAR, calId], kcount, Ent.EVENT, j, jcount)
|
|
return (calId, cal, calEventIds, kcount)
|
|
|
|
def _validateCalendarGetEvents(origUser, user, origCal, calId, j, jcount, calendarEventEntity,
|
|
fieldsList, showAction):
|
|
if calendarEventEntity['dict']:
|
|
if origUser:
|
|
if not GM.Globals[GM.CSV_SUBKEY_FIELD]:
|
|
calEventIds = calendarEventEntity['dict'][calId]
|
|
else:
|
|
calEventIds = calendarEventEntity['dict'][origUser][calId]
|
|
else:
|
|
calEventIds = calendarEventEntity['dict'][calId]
|
|
else:
|
|
calEventIds = calendarEventEntity['list']
|
|
calId, cal = getNormalizedCalIdCal(origCal, calId, user, j, jcount)
|
|
if not cal:
|
|
return (calId, cal, [], 0)
|
|
eventIdsSet = set()
|
|
eventsList = []
|
|
fields = _getMain().getFieldsFromFieldsList(fieldsList)
|
|
ifields = _getMain().getItemFieldsFromFieldsList('items', fieldsList)
|
|
try:
|
|
if not calEventIds:
|
|
if len(calendarEventEntity['queries']) <= 1:
|
|
if len(calendarEventEntity['queries']) == 1:
|
|
calendarEventEntity['kwargs']['q'] = calendarEventEntity['queries'][0]
|
|
events = _getMain().callGAPIpages(cal.events(), 'list', 'items',
|
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.INVALID],
|
|
calendarId=calId, fields=ifields,
|
|
maxResults=GC.Values[GC.EVENT_MAX_RESULTS], **calendarEventEntity['kwargs'])
|
|
for event in events:
|
|
for match in calendarEventEntity['matches']:
|
|
if not _eventMatches(event, match):
|
|
break
|
|
else:
|
|
eventsList.append(event)
|
|
else:
|
|
for query in calendarEventEntity['queries']:
|
|
calendarEventEntity['kwargs']['q'] = query
|
|
events = _getMain().callGAPIpages(cal.events(), 'list', 'items',
|
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.INVALID],
|
|
calendarId=calId, fields=ifields,
|
|
maxResults=GC.Values[GC.EVENT_MAX_RESULTS], **calendarEventEntity['kwargs'])
|
|
for event in events:
|
|
for match in calendarEventEntity['matches']:
|
|
if not _eventMatches(event, match):
|
|
break
|
|
else:
|
|
eventId = event['id']
|
|
if eventId not in eventIdsSet:
|
|
eventsList.append(event)
|
|
eventIdsSet.add(eventId)
|
|
else:
|
|
k = 0
|
|
for eventId in calEventIds:
|
|
k += 1
|
|
if eventId not in eventIdsSet:
|
|
eventsList.append(_getMain().callGAPI(cal.events(), 'get',
|
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.DELETED, GAPI.FORBIDDEN],
|
|
calendarId=calId, eventId=eventId, fields=fields))
|
|
eventIdsSet.add(eventId)
|
|
kcount = len(eventsList)
|
|
if showAction:
|
|
_getMain().entityPerformActionNumItems([Ent.CALENDAR, calId], kcount, Ent.EVENT, j, jcount)
|
|
if kcount == 0:
|
|
_getMain().setSysExitRC(_getMain().NO_ENTITIES_FOUND_RC)
|
|
return (calId, cal, eventsList, kcount)
|
|
except (GAPI.notFound, GAPI.deleted) as e:
|
|
if not checkCalendarExists(cal, calId, j, jcount):
|
|
_getMain().entityUnknownWarning(Ent.CALENDAR, calId, j, jcount)
|
|
else:
|
|
_getMain().entityActionFailedWarning([Ent.CALENDAR, calId, Ent.EVENT, eventId], str(e), j, jcount)
|
|
except (GAPI.forbidden, GAPI.invalid) as e:
|
|
_getMain().entityActionFailedWarning([Ent.CALENDAR, calId], str(e), j, jcount)
|
|
except GAPI.notACalendarUser:
|
|
_getMain().userCalServiceNotEnabledWarning(calId, j, jcount)
|
|
return (calId, cal, [], 0)
|
|
|
|
def _getCalendarCreateImportUpdateEventOptions(function, entityType):
|
|
body = {}
|
|
parameters = {'clearAttendees': False, 'replaceMode': False, 'clearResources': False,
|
|
'attendees': [], 'removeAttendees': set(),
|
|
'replaceDescription': [], 'sendUpdates': 'none',
|
|
'csvPF': None, 'FJQC': FormatJSONQuoteChar(None), 'showDayOfWeek': False}
|
|
while Cmd.ArgumentsRemaining():
|
|
myarg = _getMain().getArgument()
|
|
if myarg == 'csv':
|
|
parameters['csvPF'] = CSVPrintFile(['primaryEmail', 'calendarId', 'id'] if entityType == Ent.USER else ['calendarId', 'id'], 'sortall', indexedTitles=EVENT_INDEXED_TITLES)
|
|
parameters['FJQC'].SetCsvPF(parameters['csvPF'])
|
|
elif parameters['csvPF'] and myarg == 'todrive':
|
|
parameters['csvPF'].GetTodriveParameters()
|
|
elif myarg == 'showdayofweek':
|
|
parameters['showDayOfWeek'] = True
|
|
elif _getCalendarEventAttribute(myarg, body, parameters, function):
|
|
pass
|
|
else:
|
|
parameters['FJQC'].GetFormatJSONQuoteChar(myarg, True)
|
|
return (body, parameters)
|
|
|
|
def _setEventRecurrenceTimeZone(cal, calId, body, parameters, i, count):
|
|
if ('recurrence' in body) and (('start' in body) or ('end' in body)):
|
|
timeZone = parameters.get('timeZone')
|
|
if not timeZone:
|
|
try:
|
|
timeZone = _getMain().callGAPI(cal.calendars(), 'get',
|
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.INVALID],
|
|
calendarId=calId, fields='timeZone')['timeZone']
|
|
except (GAPI.notFound, GAPI.forbidden, GAPI.invalid) as e:
|
|
_getMain().entityActionFailedWarning([Ent.CALENDAR, calId], str(e), i, count)
|
|
return False
|
|
except GAPI.notACalendarUser:
|
|
_getMain().userCalServiceNotEnabledWarning(calId, i, count)
|
|
return False
|
|
if 'start' in body:
|
|
body['start']['timeZone'] = timeZone
|
|
if 'end' in body:
|
|
body['end']['timeZone'] = timeZone
|
|
return True
|
|
|
|
def _getEventDaysOfWeek(event):
|
|
for attr in ['start', 'end']:
|
|
if attr in event:
|
|
if 'date' in event[attr]:
|
|
try:
|
|
dateTime = arrow.Arrow.strptime(event[attr]['date'], _getMain().YYYYMMDD_FORMAT)
|
|
event[attr]['dayOfWeek'] = _getMain().DAYS_OF_WEEK[dateTime.weekday()]
|
|
except ValueError:
|
|
pass
|
|
elif 'dateTime' in event[attr]:
|
|
try:
|
|
dateTime = arrow.get(event[attr]['dateTime'])
|
|
event[attr]['dayOfWeek'] = _getMain().DAYS_OF_WEEK[dateTime.weekday()]
|
|
except (arrow.parser.ParserError, OverflowError):
|
|
pass
|
|
|
|
def _createCalendarEvents(user, origCal, function, calIds, count, body, parameters):
|
|
if parameters['attendees']:
|
|
body['attendees'] = parameters.pop('attendees')
|
|
fields = 'id' if parameters['csvPF'] is None else '*'
|
|
i = 0
|
|
for calId in calIds:
|
|
i += 1
|
|
calId, cal = getNormalizedCalIdCal(origCal, calId, user, i, count)
|
|
if not cal:
|
|
continue
|
|
if not _setEventRecurrenceTimeZone(cal, calId, body, parameters, i, count):
|
|
continue
|
|
event = {'id': body.get('id', _getMain().UNKNOWN)}
|
|
if function == 'import' and body.get('status', '') == 'cancelled':
|
|
_getMain().entityActionNotPerformedWarning([Ent.CALENDAR, calId, Ent.EVENT, body.get('iCalUID', event['id'])], Msg.EVENT_IS_CANCELED, count)
|
|
continue
|
|
try:
|
|
if function == 'insert':
|
|
event = _getMain().callGAPI(cal.events(), 'insert',
|
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.INVALID, GAPI.REQUIRED, GAPI.TIME_RANGE_EMPTY, GAPI.EVENT_DURATION_EXCEEDS_LIMIT,
|
|
GAPI.REQUIRED_ACCESS_LEVEL, GAPI.DUPLICATE, GAPI.FORBIDDEN,
|
|
GAPI.MALFORMED_WORKING_LOCATION_EVENT, GAPI.BAD_REQUEST],
|
|
calendarId=calId, conferenceDataVersion=1, sendUpdates=parameters['sendUpdates'], supportsAttachments=True, body=body, fields=fields)
|
|
else:
|
|
event = _getMain().callGAPI(cal.events(), 'import_',
|
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.INVALID, GAPI.REQUIRED, GAPI.TIME_RANGE_EMPTY, GAPI.EVENT_DURATION_EXCEEDS_LIMIT,
|
|
GAPI.REQUIRED_ACCESS_LEVEL, GAPI.DUPLICATE, GAPI.FORBIDDEN,
|
|
GAPI.MALFORMED_WORKING_LOCATION_EVENT, GAPI.BAD_REQUEST,
|
|
GAPI.PARTICIPANT_IS_NEITHER_ORGANIZER_NOR_ATTENDEE],
|
|
calendarId=calId, conferenceDataVersion=1, supportsAttachments=True, body=body, fields=fields)
|
|
if parameters['csvPF'] is None:
|
|
_getMain().entityActionPerformed([Ent.CALENDAR, calId, Ent.EVENT, event['id']], i, count)
|
|
else:
|
|
if parameters['showDayOfWeek']:
|
|
_getEventDaysOfWeek(event)
|
|
_printCalendarEvent(user, calId, event, parameters['csvPF'], parameters['FJQC'], {}, False)
|
|
except (GAPI.invalid, GAPI.required, GAPI.timeRangeEmpty, GAPI.eventDurationExceedsLimit,
|
|
GAPI.requiredAccessLevel, GAPI.participantIsNeitherOrganizerNorAttendee,
|
|
GAPI.malformedWorkingLocationEvent, GAPI.badRequest) as e:
|
|
_getMain().entityActionFailedWarning([Ent.CALENDAR, calId, Ent.EVENT, event['id']], str(e), i, count)
|
|
except GAPI.duplicate as e:
|
|
_getMain().entityActionFailedWarning([Ent.CALENDAR, calId, Ent.EVENT, event['id']], str(e), i, count)
|
|
except GAPI.forbidden as e:
|
|
_getMain().entityActionFailedWarning([Ent.CALENDAR, calId], str(e), i, count)
|
|
break
|
|
except GAPI.notACalendarUser:
|
|
_getMain().userCalServiceNotEnabledWarning(calId, i, count)
|
|
break
|
|
if parameters['csvPF']:
|
|
parameters['csvPF'].writeCSVfile('Calendar Created Events')
|
|
|
|
# gam calendars <CalendarEntity> create event [id <String>] <EventAddAttribute>+
|
|
# [showdayofweek]
|
|
# [csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]]
|
|
# gam calendar <UserItem> addevent [id <String>] <EventAddAttribute>+
|
|
# [showdayofweek]
|
|
# [csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]]
|
|
def doCalendarsCreateEvent(calIds):
|
|
body, parameters = _getCalendarCreateImportUpdateEventOptions('insert', Ent.CALENDAR)
|
|
_createCalendarEvents(None, None, 'insert', calIds, len(calIds), body, parameters)
|
|
|
|
# gam calendars <CalendarEntity> import event icaluid <iCalUID> <EventImportAttribute>+
|
|
# [showdayofweek]
|
|
# [csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]]
|
|
def doCalendarsImportEvent(calIds):
|
|
body, parameters = _getCalendarCreateImportUpdateEventOptions('import', Ent.CALENDAR)
|
|
_createCalendarEvents(None, None, 'import', calIds, len(calIds), body, parameters)
|
|
|
|
def _updateCalendarEvents(origUser, user, origCal, calIds, count, calendarEventEntity, body, parameters):
|
|
updateFieldList = []
|
|
if parameters['replaceDescription']:
|
|
updateFieldList.append('description')
|
|
if not parameters['replaceMode'] and (parameters['attendees'] or parameters['removeAttendees'] or parameters['clearResources']):
|
|
updateFieldList.append('attendees')
|
|
updateFields = ','.join(updateFieldList)
|
|
if 'attendees' not in updateFieldList:
|
|
if parameters['attendees']:
|
|
body['attendees'] = parameters.pop('attendees')
|
|
elif parameters['clearAttendees']:
|
|
body['attendees'] = []
|
|
pfields = '' if parameters['csvPF'] is None else '*'
|
|
i = 0
|
|
for calId in calIds:
|
|
i += 1
|
|
calId, cal, calEventIds, jcount = _validateCalendarGetEventIDs(origUser, user, origCal, calId, i, count, calendarEventEntity)
|
|
if jcount == 0:
|
|
continue
|
|
if not _setEventRecurrenceTimeZone(cal, calId, body, parameters, i, count):
|
|
continue
|
|
Ind.Increment()
|
|
j = 0
|
|
for eventId in calEventIds:
|
|
j += 1
|
|
try:
|
|
if updateFieldList:
|
|
event = _getMain().callGAPI(cal.events(), 'get',
|
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.DELETED, GAPI.FORBIDDEN, GAPI.BACKEND_ERROR],
|
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS+[GAPI.BACKEND_ERROR],
|
|
calendarId=calId, eventId=eventId, fields=updateFields)
|
|
if 'description' in updateFieldList and 'description' in event:
|
|
body['description'] = event['description']
|
|
for replacement in parameters['replaceDescription']:
|
|
body['description'] = re.sub(replacement[0], replacement[1], body['description'])
|
|
if 'attendees' in updateFieldList:
|
|
if not parameters['clearAttendees']:
|
|
if 'attendees' in event:
|
|
body['attendees'] = event['attendees']
|
|
for addAttendee in parameters['attendees']:
|
|
for attendee in body['attendees']:
|
|
if attendee['email'].lower() == addAttendee['email']:
|
|
attendee.update(addAttendee)
|
|
break
|
|
else:
|
|
body['attendees'].append(addAttendee)
|
|
elif parameters['attendees']:
|
|
body['attendees'] = parameters['attendees']
|
|
else:
|
|
body['attendees'] = []
|
|
elif parameters['attendees']:
|
|
body['attendees'] = parameters['attendees']
|
|
else:
|
|
body['attendees'] = []
|
|
if parameters['removeAttendees']:
|
|
body['attendees'] = [attendee for attendee in body['attendees'] if attendee['email'].lower() not in parameters['removeAttendees']]
|
|
if parameters['clearResources']:
|
|
body['attendees'] = [attendee for attendee in body['attendees'] if not attendee['email'].lower().endswith('@resource.calendar.google.com')]
|
|
event = _getMain().callGAPI(cal.events(), 'patch',
|
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.DELETED, GAPI.FORBIDDEN, GAPI.BACKEND_ERROR,
|
|
GAPI.INVALID, GAPI.REQUIRED, GAPI.TIME_RANGE_EMPTY, GAPI.EVENT_DURATION_EXCEEDS_LIMIT,
|
|
GAPI.REQUIRED_ACCESS_LEVEL, GAPI.CANNOT_CHANGE_ORGANIZER_OF_INSTANCE,
|
|
GAPI.MALFORMED_WORKING_LOCATION_EVENT, GAPI.EVENT_TYPE_RESTRICTION, GAPI.BAD_REQUEST],
|
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS+[GAPI.BACKEND_ERROR],
|
|
calendarId=calId, eventId=eventId, conferenceDataVersion=1, sendUpdates=parameters['sendUpdates'], supportsAttachments=True,
|
|
body=body, fields=pfields)
|
|
if parameters['csvPF'] is None:
|
|
_getMain().entityActionPerformed([Ent.CALENDAR, calId, Ent.EVENT, eventId], j, jcount)
|
|
else:
|
|
if parameters['showDayOfWeek']:
|
|
_getEventDaysOfWeek(event)
|
|
_printCalendarEvent(user, calId, event, parameters['csvPF'], parameters['FJQC'], {}, False)
|
|
except (GAPI.notFound, GAPI.deleted) as e:
|
|
if not checkCalendarExists(cal, calId, j, jcount):
|
|
_getMain().entityUnknownWarning(Ent.CALENDAR, calId, j, jcount)
|
|
break
|
|
_getMain().entityActionFailedWarning([Ent.CALENDAR, calId, Ent.EVENT, eventId], str(e), j, jcount)
|
|
except (GAPI.forbidden, GAPI.backendError, GAPI.invalid, GAPI.required, GAPI.timeRangeEmpty, GAPI.eventDurationExceedsLimit,
|
|
GAPI.requiredAccessLevel, GAPI.cannotChangeOrganizerOfInstance, GAPI.malformedWorkingLocationEvent,
|
|
GAPI.eventTypeRestriction, GAPI.badRequest) as e:
|
|
_getMain().entityActionFailedWarning([Ent.CALENDAR, calId, Ent.EVENT, eventId], str(e), j, jcount)
|
|
except GAPI.notACalendarUser:
|
|
_getMain().userCalServiceNotEnabledWarning(calId, i, count)
|
|
break
|
|
Ind.Decrement()
|
|
if parameters['csvPF']:
|
|
parameters['csvPF'].writeCSVfile('Calendar Updated Events')
|
|
|
|
# gam calendars <CalendarEntity> update events [<EventEntity>] [replacemode] <EventUpdateAttribute>+ [<EventNotificationAttribute>]
|
|
# [showdayofweek]
|
|
# [csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]]
|
|
def doCalendarsUpdateEvents(calIds):
|
|
calendarEventEntity = getCalendarEventEntity()
|
|
body, parameters = _getCalendarCreateImportUpdateEventOptions('update', Ent.CALENDAR)
|
|
_updateCalendarEvents(None, None, None, calIds, len(calIds), calendarEventEntity, body, parameters)
|
|
|
|
# gam calendar <CalendarEntity> updateevent <EventID> [replacemode] <EventUpdateAttribute>+ [<EventNotificationAttribute>]
|
|
# [showdayofweek]
|
|
# [csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]]
|
|
def doCalendarsUpdateEventsOld(calIds):
|
|
calendarEventEntity = initCalendarEventEntity()
|
|
calendarEventEntity['list'].append(_getMain().getString(Cmd.OB_EVENT_ID))
|
|
body, parameters = _getCalendarCreateImportUpdateEventOptions('update', Ent.CALENDAR)
|
|
_updateCalendarEvents(None, None, None, calIds, len(calIds), calendarEventEntity, body, parameters)
|
|
|
|
def _getCalendarDeleteEventOptions(calendarEventEntity=None):
|
|
parameters = {'sendUpdates': 'none', 'doIt': False, 'batch_size': 0}
|
|
while Cmd.ArgumentsRemaining():
|
|
myarg = _getMain().getArgument()
|
|
if _getCalendarSendUpdates(myarg, parameters):
|
|
pass
|
|
elif calendarEventEntity and myarg in {'id', 'eventid'}:
|
|
calendarEventEntity['list'].append(_getMain().getString(Cmd.OB_EVENT_ID))
|
|
elif myarg == 'doit':
|
|
parameters['doIt'] = True
|
|
elif myarg == 'batchsize':
|
|
parameters['batch_size'] = _getMain().getInteger(minVal=0, maxVal=1000)
|
|
else:
|
|
_getMain().unknownArgumentExit()
|
|
return parameters
|
|
|
|
def _deleteCalendarEvents(origUser, user, origCal, calIds, count, calendarEventEntity, parameters):
|
|
def _callbackDeleteEvents(request_id, _, exception):
|
|
ri = request_id.splitlines()
|
|
if exception is None:
|
|
_getMain().entityActionPerformed([Ent.CALENDAR, ri[RI_ENTITY], Ent.EVENT, ri[RI_ITEM]], int(ri[RI_J]), int(ri[RI_JCOUNT]))
|
|
else:
|
|
http_status, reason, message = _getMain().checkGAPIError(exception)
|
|
errMsg = _getMain().getHTTPError({}, http_status, reason, message)
|
|
_getMain().entityActionFailedWarning([Ent.CALENDAR, ri[RI_ENTITY], Ent.EVENT, ri[RI_ITEM]], errMsg, int(ri[RI_J]), int(ri[RI_JCOUNT]))
|
|
|
|
i = 0
|
|
for calId in calIds:
|
|
i += 1
|
|
calId, cal, calEventIds, jcount = _validateCalendarGetEventIDs(origUser, user, origCal, calId, i, count, calendarEventEntity, doIt=parameters['doIt'])
|
|
if jcount == 0:
|
|
continue
|
|
Ind.Increment()
|
|
if parameters['batch_size'] == 0:
|
|
j = 0
|
|
for eventId in calEventIds:
|
|
j += 1
|
|
try:
|
|
_getMain().callGAPI(cal.events(), 'delete',
|
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.DELETED, GAPI.FORBIDDEN,
|
|
GAPI.INVALID, GAPI.REQUIRED, GAPI.REQUIRED_ACCESS_LEVEL],
|
|
calendarId=calId, eventId=eventId, sendUpdates=parameters['sendUpdates'])
|
|
_getMain().entityActionPerformed([Ent.CALENDAR, calId, Ent.EVENT, eventId], j, jcount)
|
|
except (GAPI.notFound, GAPI.deleted) as e:
|
|
if not checkCalendarExists(cal, calId, i, count):
|
|
_getMain().entityUnknownWarning(Ent.CALENDAR, calId, i, count)
|
|
break
|
|
_getMain().entityActionFailedWarning([Ent.CALENDAR, calId, Ent.EVENT, eventId], str(e), j, jcount)
|
|
except (GAPI.forbidden, GAPI.invalid, GAPI.required, GAPI.requiredAccessLevel) as e:
|
|
_getMain().entityActionFailedWarning([Ent.CALENDAR, calId, Ent.EVENT, eventId], str(e), j, jcount)
|
|
except GAPI.notACalendarUser:
|
|
_getMain().userCalServiceNotEnabledWarning(calId, i, count)
|
|
break
|
|
else:
|
|
svcargs = dict([('calendarId', calId), ('eventId', None), ('sendUpdates', parameters['sendUpdates'])]+GM.Globals[GM.EXTRA_ARGS_LIST])
|
|
method = getattr(cal.events(), 'delete')
|
|
dbatch = cal.new_batch_http_request(callback=_callbackDeleteEvents)
|
|
bcount = 0
|
|
j = 0
|
|
for eventId in calEventIds:
|
|
j += 1
|
|
svcparms = svcargs.copy()
|
|
svcparms['eventId'] = eventId
|
|
dbatch.add(method(**svcparms), request_id=_getMain().batchRequestID(calId, i, count, j, jcount, svcparms['eventId']))
|
|
bcount += 1
|
|
if bcount >= parameters['batch_size']:
|
|
_getMain().executeBatch(dbatch)
|
|
dbatch = cal.new_batch_http_request(callback=_callbackDeleteEvents)
|
|
bcount = 0
|
|
if bcount > 0:
|
|
dbatch.execute()
|
|
Ind.Decrement()
|
|
|
|
# gam calendars <CalendarEntity> delete event <EventEntity>
|
|
# [batchsize <Integer>] [doit] [<EventNotificationAttribute>]
|
|
def doCalendarsDeleteEvents(calIds):
|
|
calendarEventEntity = getCalendarEventEntity()
|
|
parameters = _getCalendarDeleteEventOptions()
|
|
_deleteCalendarEvents(None, None, None, calIds, len(calIds), calendarEventEntity, parameters)
|
|
|
|
# gam calendar <CalendarEntity> deleteevent (id|eventid <EventID>)+
|
|
# [batchsize <Integer>] [doit] [<EventNotificationAttribute>]
|
|
def doCalendarsDeleteEventsOld(calIds):
|
|
calendarEventEntity = initCalendarEventEntity()
|
|
parameters = _getCalendarDeleteEventOptions(calendarEventEntity)
|
|
_deleteCalendarEvents(None, None, None, calIds, len(calIds), calendarEventEntity, parameters)
|
|
|
|
def _getCalendarMoveEventsOptions(calendarEventEntity=None):
|
|
parameters = {'sendUpdates': 'none'}
|
|
newCalId = None
|
|
while Cmd.ArgumentsRemaining():
|
|
myarg = _getMain().getArgument()
|
|
if _getCalendarSendUpdates(myarg, parameters):
|
|
pass
|
|
elif calendarEventEntity and myarg in {'id', 'eventid'}:
|
|
calendarEventEntity['list'].append(_getMain().getString(Cmd.OB_EVENT_ID))
|
|
elif calendarEventEntity and myarg == 'destination':
|
|
newCalId = _getMain().convertUIDtoEmailAddress(_getMain().getString(Cmd.OB_CALENDAR_ITEM))
|
|
else:
|
|
_getMain().unknownArgumentExit()
|
|
return (parameters, newCalId)
|
|
|
|
def _moveCalendarEvents(origUser, user, origCal, calIds, count, calendarEventEntity, newCalId, parameters):
|
|
i = 0
|
|
for calId in calIds:
|
|
i += 1
|
|
calId, cal, calEventIds, jcount = _validateCalendarGetEventIDs(origUser, user, origCal, calId, i, count, calendarEventEntity)
|
|
if jcount == 0:
|
|
continue
|
|
kvList = [Ent.USER, user] if user else []
|
|
kvList.extend([Ent.CALENDAR, calId])
|
|
Ind.Increment()
|
|
j = 0
|
|
for eventId in calEventIds:
|
|
j += 1
|
|
kvListEvent = kvList+[Ent.EVENT, eventId]
|
|
kvListEventNewCal = kvListEvent+[Ent.CALENDAR, newCalId]
|
|
try:
|
|
_getMain().callGAPI(cal.events(), 'move',
|
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.REQUIRED_ACCESS_LEVEL,
|
|
GAPI.INVALID, GAPI.BAD_REQUEST, GAPI.EVENT_TYPE_RESTRICTION,
|
|
GAPI.CANNOT_CHANGE_ORGANIZER, GAPI.CANNOT_CHANGE_ORGANIZER_OF_INSTANCE],
|
|
calendarId=calId, eventId=eventId, destination=newCalId, sendUpdates=parameters['sendUpdates'], fields='')
|
|
_getMain().entityModifierNewValueActionPerformed(kvListEvent, Act.MODIFIER_TO, f'{Ent.Singular(Ent.CALENDAR)}: {newCalId}', j, jcount)
|
|
except GAPI.notFound as e:
|
|
if not checkCalendarExists(cal, calId, i, count):
|
|
_getMain().entityUnknownWarning(Ent.CALENDAR, calId, i, count)
|
|
break
|
|
_getMain().entityActionFailedWarning(kvListEventNewCal, Ent.TypeNameMessage(Ent.EVENT, eventId, str(e)), j, jcount)
|
|
except GAPI.requiredAccessLevel:
|
|
# Correct "You need to have reader access to this calendar." to "Writer access required to both calendars."
|
|
_getMain().entityActionFailedWarning(kvListEventNewCal, Msg.WRITER_ACCESS_REQUIRED_TO_BOTH_CALENDARS, j, jcount)
|
|
except (GAPI.forbidden, GAPI.invalid, GAPI.badRequest, GAPI.eventTypeRestriction,
|
|
GAPI.cannotChangeOrganizer, GAPI.cannotChangeOrganizerOfInstance) as e:
|
|
_getMain().entityActionFailedWarning(kvListEventNewCal, str(e), j, jcount)
|
|
except GAPI.notACalendarUser:
|
|
_getMain().userCalServiceNotEnabledWarning(calId, i, count)
|
|
break
|
|
Ind.Decrement()
|
|
|
|
# gam calendars <CalendarEntity> move events <EventEntity> to|destination <CalendarItem> [<EventNotificationAttribute>]
|
|
def doCalendarsMoveEvents(calIds):
|
|
calendarEventEntity = getCalendarEventEntity()
|
|
_getMain().checkArgumentPresent(['to', 'destination'])
|
|
newCalId = _getMain().convertUIDtoEmailAddress(_getMain().getString(Cmd.OB_CALENDAR_ITEM))
|
|
parameters, _ = _getCalendarMoveEventsOptions()
|
|
if not checkCalendarExists(None, newCalId, 0, 0, True):
|
|
return
|
|
_moveCalendarEvents(None, None, None, calIds, len(calIds), calendarEventEntity, newCalId, parameters)
|
|
|
|
# gam calendars <CalendarEntity> moveevent (id|eventid <EventID>)+ destination <CalendarItem> [<EventNotificationAttribute>]
|
|
def doCalendarsMoveEventsOld(calIds):
|
|
calendarEventEntity = initCalendarEventEntity()
|
|
parameters, newCalId = _getCalendarMoveEventsOptions(calendarEventEntity)
|
|
if not checkCalendarExists(None, newCalId, 0, 0, True):
|
|
return
|
|
_moveCalendarEvents(None, None, None, calIds, len(calIds), calendarEventEntity, newCalId, parameters)
|
|
|
|
def _purgeCalendarEvents(origUser, user, origCal, calIds, count, calendarEventEntity, parameters, emptyTrash):
|
|
body = {'summary': f'GamPurgeCalendar-{random.randint(1, 99999):05}'}
|
|
if user:
|
|
entityValueList = [Ent.USER, user, Ent.CALENDAR, body['summary']]
|
|
else:
|
|
entityValueList = [Ent.CALENDAR, body['summary']]
|
|
i = 0
|
|
for calId in calIds:
|
|
i += 1
|
|
calId, cal = getNormalizedCalIdCal(origCal, calId, user, i, count)
|
|
if not cal:
|
|
continue
|
|
try:
|
|
purgeCalId = _getMain().callGAPI(cal.calendars(), 'insert',
|
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.FORBIDDEN],
|
|
body=body, fields='id')['id']
|
|
Act.Set(Act.CREATE)
|
|
_getMain().entityActionPerformed(entityValueList)
|
|
Ind.Increment()
|
|
if not emptyTrash:
|
|
Act.Set(Act.DELETE)
|
|
_deleteCalendarEvents(origUser, user, cal, [calId], count, calendarEventEntity, parameters)
|
|
Act.Set(Act.MOVE)
|
|
calendarEventEntity['kwargs']['showDeleted'] = True
|
|
_moveCalendarEvents(origUser, user, cal, [calId], count, calendarEventEntity, purgeCalId, parameters)
|
|
calendarEventEntity['kwargs'].pop('showDeleted')
|
|
Ind.Decrement()
|
|
_getMain().callGAPI(cal.calendars(), 'delete',
|
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.FORBIDDEN],
|
|
calendarId=purgeCalId)
|
|
Act.Set(Act.REMOVE)
|
|
_getMain().entityActionPerformed(entityValueList)
|
|
except (GAPI.notFound, GAPI.forbidden) as e:
|
|
_getMain().entityActionFailedWarning([Ent.USER, user, Ent.CALENDAR, body['summary']], str(e))
|
|
except GAPI.notACalendarUser:
|
|
_getMain().userCalServiceNotEnabledWarning(calId, i, count)
|
|
|
|
# gam calendars <CalendarEntity> purge event <EventEntity>
|
|
# [batchsize <Integer>] [doit] [<EventNotificationAttribute>]
|
|
def doCalendarsPurgeEvents(calIds):
|
|
calendarEventEntity = getCalendarEventEntity()
|
|
parameters = _getCalendarDeleteEventOptions()
|
|
_purgeCalendarEvents(None, None, None, calIds, len(calIds), calendarEventEntity, parameters, False)
|
|
|
|
def _wipeCalendarEvents(user, origCal, calIds, count):
|
|
i = 0
|
|
for calId in calIds:
|
|
i += 1
|
|
calId, cal = getNormalizedCalIdCal(origCal, calId, user, i, count)
|
|
if not cal:
|
|
continue
|
|
try:
|
|
_getMain().callGAPI(cal.calendars(), 'clear',
|
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.INVALID,
|
|
GAPI.REQUIRED_ACCESS_LEVEL, GAPI.SERVICE_NOT_AVAILABLE],
|
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
|
calendarId=calId)
|
|
_getMain().entityActionPerformed([Ent.CALENDAR, calId], i, count)
|
|
except (GAPI.notFound, GAPI.forbidden, GAPI.invalid, GAPI.requiredAccessLevel, GAPI.serviceNotAvailable) as e:
|
|
_getMain().entityActionFailedWarning([Ent.CALENDAR, calId], str(e), i, count)
|
|
except GAPI.notACalendarUser:
|
|
_getMain().userCalServiceNotEnabledWarning(calId, i, count)
|
|
|
|
# gam calendars <CalendarEntity> wipe events
|
|
# gam calendar <CalendarEntity> wipe
|
|
def doCalendarsWipeEvents(calIds):
|
|
_getMain().checkArgumentPresent([Cmd.ARG_EVENT, Cmd.ARG_EVENTS])
|
|
_getMain().checkForExtraneousArguments()
|
|
_wipeCalendarEvents(None, None, calIds, len(calIds))
|
|
|
|
def _emptyCalendarTrash(user, origCal, calIds, count):
|
|
i = 0
|
|
for calId in calIds:
|
|
i += 1
|
|
calId, cal = getNormalizedCalIdCal(origCal, calId, user, i, count)
|
|
if not cal:
|
|
continue
|
|
Act.Set(Act.PURGE)
|
|
calendarEventEntity = initCalendarEventEntity()
|
|
try:
|
|
events = _getMain().callGAPIpages(cal.events(), 'list', 'items',
|
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.FORBIDDEN],
|
|
calendarId=calId, showDeleted=True, fields='nextPageToken,items(id,status,organizer(self),recurringEventId)',
|
|
maxResults=GC.Values[GC.EVENT_MAX_RESULTS])
|
|
except (GAPI.notFound, GAPI.forbidden) as e:
|
|
_getMain().entityActionFailedWarning([Ent.CALENDAR, calId], str(e), i, count)
|
|
continue
|
|
except GAPI.notACalendarUser:
|
|
_getMain().userCalServiceNotEnabledWarning(calId, i, count)
|
|
continue
|
|
for event in events:
|
|
if event['status'] == 'cancelled' and event.get('organizer', {}).get('self', user is None) and not event.get('recurringEventId', ''):
|
|
calendarEventEntity['list'].append(event['id'])
|
|
jcount = len(calendarEventEntity['list'])
|
|
if not user:
|
|
_getMain().entityPerformActionNumItems([Ent.CALENDAR, calId], jcount, Ent.TRASHED_EVENT, i, count)
|
|
Ind.Increment()
|
|
if jcount > 0:
|
|
_purgeCalendarEvents(user, user, cal, [calId], 1, calendarEventEntity, {'sendUpdates': 'none', 'doIt': True, 'batch_size': 0}, True)
|
|
if not user:
|
|
Ind.Decrement()
|
|
|
|
# gam calendars <CalendarEntity> empty calendartrash
|
|
def doCalendarsEmptyTrash(calIds):
|
|
_getMain().checkForExtraneousArguments()
|
|
Act.Set(Act.PURGE)
|
|
_emptyCalendarTrash(None, None, calIds, len(calIds))
|
|
|
|
EVENT_SHOW_ORDER = ['id', 'summary', 'status', 'description', 'location',
|
|
'start', 'end', 'endTimeUnspecified',
|
|
'creator', 'organizer', 'created', 'updated', 'iCalUID']
|
|
EVENT_PRINT_ORDER = ['id', 'summary', 'status', 'description', 'location',
|
|
'created', 'updated', 'iCalUID']
|
|
|
|
EVENT_TIME_OBJECTS = {'created', 'updated'}
|
|
|
|
def _showCalendarEvent(primaryEmail, calId, eventEntityType, event, k, kcount, FJQC):
|
|
if FJQC.formatJSON:
|
|
if primaryEmail:
|
|
_getMain().printLine(json.dumps(_getMain().cleanJSON({'primaryEmail': primaryEmail, 'calendarId': calId, 'event': event},
|
|
timeObjects=EVENT_TIME_OBJECTS), ensure_ascii=False, sort_keys=True))
|
|
else:
|
|
_getMain().printLine(json.dumps(_getMain().cleanJSON({'calendarId': calId, 'event': event},
|
|
timeObjects=EVENT_TIME_OBJECTS), ensure_ascii=False, sort_keys=True))
|
|
return
|
|
_getMain().printEntity([eventEntityType, event['id']], k, kcount)
|
|
skipObjects = {'id'}
|
|
Ind.Increment()
|
|
for field in EVENT_SHOW_ORDER:
|
|
if field in event:
|
|
if field != 'description':
|
|
_getMain().showJSON(field, event[field], skipObjects, EVENT_TIME_OBJECTS)
|
|
else:
|
|
_getMain().printKeyValueWithCRsNLs(field, event[field])
|
|
skipObjects.add(field)
|
|
_getMain().showJSON(None, event, skipObjects)
|
|
Ind.Decrement()
|
|
|
|
def _printCalendarEvent(user, calId, event, csvPF, FJQC, addCSVData, attendeesList=False):
|
|
row = {'calendarId': calId, 'id': event['id']}
|
|
if user:
|
|
row['primaryEmail'] = user
|
|
if addCSVData:
|
|
row.update(addCSVData)
|
|
if attendeesList:
|
|
attendees = event.pop('attendees', [])
|
|
row['attendeesList'] = GC.Values[GC.CSV_OUTPUT_FIELD_DELIMITER].join([attendee['email'] for attendee in attendees])
|
|
_getMain().flattenJSON(event, flattened=row, timeObjects=EVENT_TIME_OBJECTS)
|
|
if not FJQC.formatJSON:
|
|
csvPF.WriteRowTitles(row)
|
|
elif csvPF.CheckRowTitles(row):
|
|
row = {'calendarId': calId, 'id': event['id'],
|
|
'JSON': json.dumps(_getMain().cleanJSON(event, timeObjects=EVENT_TIME_OBJECTS),
|
|
ensure_ascii=False, sort_keys=False)}
|
|
if user:
|
|
row['primaryEmail'] = user
|
|
csvPF.WriteRowNoFilter(row)
|
|
|
|
def _printShowCalendarEvents(origUser, user, origCal, calIds, count, calendarEventEntity,
|
|
csvPF, FJQC, fieldsList, addCSVData, attendeesList):
|
|
i = 0
|
|
for calId in calIds:
|
|
i += 1
|
|
if csvPF:
|
|
_getMain().printGettingEntityItemForWhom(Ent.EVENT, calId, i, count)
|
|
calId, _, events, jcount = _validateCalendarGetEvents(origUser, user, origCal, calId, i, count, calendarEventEntity,
|
|
fieldsList, not csvPF and not FJQC.formatJSON and not calendarEventEntity['countsOnly'])
|
|
if not csvPF:
|
|
if not calendarEventEntity['countsOnly']:
|
|
Ind.Increment()
|
|
j = 0
|
|
for event in events:
|
|
j += 1
|
|
if calendarEventEntity['showDayOfWeek']:
|
|
_getEventDaysOfWeek(event)
|
|
_showCalendarEvent(user, calId, Ent.EVENT, event, j, jcount, FJQC)
|
|
Ind.Decrement()
|
|
else:
|
|
_getMain().printKeyValueList([Ent.Singular(Ent.CALENDAR), calId, Ent.Choose(Ent.EVENT, jcount), jcount])
|
|
else:
|
|
if not calendarEventEntity['countsOnly']:
|
|
if events:
|
|
for event in events:
|
|
if calendarEventEntity['showDayOfWeek']:
|
|
_getEventDaysOfWeek(event)
|
|
_printCalendarEvent(user, calId, event, csvPF, FJQC, addCSVData, attendeesList)
|
|
elif GC.Values[GC.CSV_OUTPUT_USERS_AUDIT] and user:
|
|
csvPF.WriteRowNoFilter({'calendarId': calId, 'primaryEmail': user, 'id': ''})
|
|
else:
|
|
if calendarEventEntity['eventRowFilter']:
|
|
jcount = 0
|
|
for event in events:
|
|
if calendarEventEntity['showDayOfWeek']:
|
|
_getEventDaysOfWeek(event)
|
|
row = {'calendarId': calId, 'id': event['id']}
|
|
if user:
|
|
row['primaryEmail'] = user
|
|
_getMain().flattenJSON(event, flattened=row, timeObjects=EVENT_TIME_OBJECTS)
|
|
if csvPF.CheckRowTitles(row):
|
|
jcount += 1
|
|
row = {'calendarId': calId}
|
|
if user:
|
|
row['primaryEmail'] = user
|
|
if addCSVData:
|
|
row.update(addCSVData)
|
|
row['events'] = jcount
|
|
if not calendarEventEntity['eventRowFilter']:
|
|
csvPF.WriteRow(row)
|
|
else:
|
|
csvPF.WriteRowNoFilter(row)
|
|
|
|
EVENT_FIELDS_CHOICE_MAP = {
|
|
'anyonecanaddself': 'anyoneCanAddSelf',
|
|
'attachments': 'attachments',
|
|
'attendees': 'attendees',
|
|
'attendeesomitted': 'attendeesOmitted',
|
|
'colorid': 'colorId',
|
|
'conferencedata': 'conferenceData',
|
|
'created': 'created',
|
|
'creator': 'creator',
|
|
'description': 'description',
|
|
'end': 'end',
|
|
'endtime': 'end',
|
|
'endtimeunspecified': 'endTimeUnspecified',
|
|
'extendedproperties': 'extendedProperties',
|
|
'focustimeproperties': 'focusTimeProperties',
|
|
'gadget': 'gadget',
|
|
'guestscaninviteothers': 'guestsCanInviteOthers',
|
|
'guestscanmodify': 'guestsCanModify',
|
|
'guestscanseeotherguests': 'guestsCanSeeOtherGuests',
|
|
'hangoutlink': 'hangoutLink',
|
|
'htmllink': 'htmlLink',
|
|
'eventtype': 'eventType',
|
|
'icaluid': 'iCalUID',
|
|
'id': 'id',
|
|
'location': 'location',
|
|
'locked': 'locked',
|
|
'organizer': 'organizer',
|
|
'organiser': 'organizer',
|
|
'originalstart': 'originalStartTime',
|
|
'originalstarttime': 'originalStartTime',
|
|
'outofofficeproperties': 'outOfOfficeProperties',
|
|
'privatecopy': 'privateCopy',
|
|
'recurrence': 'recurrence',
|
|
'recurringeventid': 'recurringEventId',
|
|
'reminders': 'reminders',
|
|
'sequence': 'sequence',
|
|
'source': 'source',
|
|
'start': 'start',
|
|
'starttime': 'start',
|
|
'status': 'status',
|
|
'summary': 'summary',
|
|
'transparency': 'transparency',
|
|
'updated': 'updated',
|
|
'visibility': 'visibility',
|
|
'workinglocationproperties': 'workingLocationProperties',
|
|
}
|
|
|
|
EVENT_ATTACHMENTS_SUBFIELDS_CHOICE_MAP = {
|
|
'fileid': 'fileId',
|
|
'fileurl': 'fileUrl',
|
|
'iconlink': 'iconLink',
|
|
'mimetype': 'mimeType',
|
|
'title': 'title',
|
|
}
|
|
|
|
EVENT_ATTENDEES_SUBFIELDS_CHOICE_MAP = {
|
|
'additionalguests': 'additionalGuests',
|
|
'comment': 'comment',
|
|
'displayname': 'displayName',
|
|
'email': 'email',
|
|
'id': 'id',
|
|
'optional': 'optional',
|
|
'organizer': 'organizer',
|
|
'organiser': 'organizer',
|
|
'resource': 'resource',
|
|
'responsestatus': 'responseStatus',
|
|
'self': 'self',
|
|
}
|
|
|
|
EVENT_CONFERENCEDATA_SUBFIELDS_CHOICE_MAP = {
|
|
'conferenceid': 'conferenceId',
|
|
'conferencesolution': 'conferenceSolution',
|
|
'createrequest': 'createRequest',
|
|
'entrypoints': 'entryPoints',
|
|
'notes': 'notes',
|
|
'signature': 'signature',
|
|
}
|
|
|
|
EVENT_CREATOR_SUBFIELDS_CHOICE_MAP = {
|
|
'displayname': 'displayName',
|
|
'email': 'email',
|
|
'id': 'id',
|
|
'self': 'self',
|
|
}
|
|
|
|
EVENT_FOCUSTIME_SUBFIELDS_CHOICE_MAP = {
|
|
'autodeclinemode': 'autoDeclineMode',
|
|
'chatstatus': 'chatStatus',
|
|
'declinemessage': 'declineMessage',
|
|
}
|
|
|
|
EVENT_ORGANIZER_SUBFIELDS_CHOICE_MAP = {
|
|
'displayname': 'displayName',
|
|
'email': 'email',
|
|
'id': 'id',
|
|
'self': 'self',
|
|
}
|
|
|
|
EVENT_OUTOFOFFICE_SUBFIELDS_CHOICE_MAP = {
|
|
'autodeclinemode': 'autoDeclineMode',
|
|
'declinemessage': 'declineMessage',
|
|
}
|
|
|
|
EVENT_WORKINGLOCATION_SUBFIELDS_CHOICE_MAP = {
|
|
'homeoffice': 'homeOffice',
|
|
'customlocation': 'customLocation',
|
|
'officelocation': 'officeLocation',
|
|
}
|
|
|
|
EVENT_SUBFIELDS_CHOICE_MAP = {
|
|
'attachments': EVENT_ATTACHMENTS_SUBFIELDS_CHOICE_MAP,
|
|
'attendees': EVENT_ATTENDEES_SUBFIELDS_CHOICE_MAP,
|
|
'conferencedata': EVENT_CONFERENCEDATA_SUBFIELDS_CHOICE_MAP,
|
|
'creator': EVENT_CREATOR_SUBFIELDS_CHOICE_MAP,
|
|
'focustimeproperties': EVENT_FOCUSTIME_SUBFIELDS_CHOICE_MAP,
|
|
'organizer': EVENT_ORGANIZER_SUBFIELDS_CHOICE_MAP,
|
|
'organiser': EVENT_ORGANIZER_SUBFIELDS_CHOICE_MAP,
|
|
'outofofficeproperties': EVENT_OUTOFOFFICE_SUBFIELDS_CHOICE_MAP,
|
|
'workinglocationproperties': EVENT_WORKINGLOCATION_SUBFIELDS_CHOICE_MAP,
|
|
}
|
|
|
|
def _getEventFields(fieldsList):
|
|
if not fieldsList:
|
|
fieldsList.append('id')
|
|
for field in _getMain()._getFieldsList():
|
|
if field.find('.') == -1:
|
|
if field in EVENT_FIELDS_CHOICE_MAP:
|
|
_getMain().addFieldToFieldsList(field, EVENT_FIELDS_CHOICE_MAP, fieldsList)
|
|
else:
|
|
_getMain().invalidChoiceExit(field, EVENT_FIELDS_CHOICE_MAP, True)
|
|
else:
|
|
field, subField = field.split('.', 1)
|
|
if field in EVENT_SUBFIELDS_CHOICE_MAP:
|
|
if subField in EVENT_SUBFIELDS_CHOICE_MAP[field]:
|
|
fieldsList.append(f'{EVENT_FIELDS_CHOICE_MAP[field]}.{EVENT_SUBFIELDS_CHOICE_MAP[field][subField]}')
|
|
else:
|
|
_getMain().invalidChoiceExit(subField, list(EVENT_SUBFIELDS_CHOICE_MAP[field]), True)
|
|
else:
|
|
_getMain().invalidChoiceExit(field, list(EVENT_SUBFIELDS_CHOICE_MAP), True)
|
|
|
|
def _addEventEntitySelectFields(calendarEventEntity, fieldsList):
|
|
if fieldsList:
|
|
_getEventMatchFields(calendarEventEntity, fieldsList)
|
|
if calendarEventEntity['maxinstances'] != -1:
|
|
fieldsList.append('recurrence')
|
|
|
|
def _getCalendarInfoEventOptions(calendarEventEntity):
|
|
FJQC = _getMain().FormatJSONQuoteChar()
|
|
fieldsList = []
|
|
while Cmd.ArgumentsRemaining():
|
|
myarg = _getMain().getArgument()
|
|
if myarg == 'fields':
|
|
_getEventFields(fieldsList)
|
|
elif myarg == 'showdayofweek':
|
|
calendarEventEntity['showDayOfWeek'] = True
|
|
else:
|
|
FJQC.GetFormatJSON(myarg)
|
|
_addEventEntitySelectFields(calendarEventEntity, fieldsList)
|
|
return (FJQC, fieldsList)
|
|
|
|
def _infoCalendarEvents(origUser, user, origCal, calIds, count, calendarEventEntity, FJQC, fieldsList):
|
|
fields = _getMain().getFieldsFromFieldsList(fieldsList)
|
|
ifields = _getMain().getItemFieldsFromFieldsList('items', fieldsList)
|
|
i = 0
|
|
for calId in calIds:
|
|
i += 1
|
|
calId, cal, calEventIds, jcount = _validateCalendarGetEventIDs(origUser, user, origCal, calId, i, count, calendarEventEntity, showAction=not FJQC.formatJSON)
|
|
if jcount == 0:
|
|
continue
|
|
Ind.Increment()
|
|
j = 0
|
|
for eventId in calEventIds:
|
|
j += 1
|
|
try:
|
|
event = _getMain().callGAPI(cal.events(), 'get',
|
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.DELETED, GAPI.FORBIDDEN],
|
|
calendarId=calId, eventId=eventId, fields=fields)
|
|
if calendarEventEntity['maxinstances'] == -1 or 'recurrence' not in event:
|
|
if calendarEventEntity['showDayOfWeek']:
|
|
_getEventDaysOfWeek(event)
|
|
_showCalendarEvent(user, calId, Ent.EVENT, event, j, jcount, FJQC)
|
|
else:
|
|
instances = _getMain().callGAPIpages(cal.events(), 'instances', 'items',
|
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.DELETED, GAPI.FORBIDDEN],
|
|
calendarId=calId, eventId=eventId, fields=ifields,
|
|
maxItems=calendarEventEntity['maxinstances'], maxResults=GC.Values[GC.EVENT_MAX_RESULTS])
|
|
lcount = len(instances)
|
|
if not FJQC.formatJSON:
|
|
_getMain().entityPerformActionNumItems([Ent.EVENT, event['id']], lcount, Ent.INSTANCE, j, jcount)
|
|
Ind.Increment()
|
|
l = 0
|
|
for instance in instances:
|
|
l += 1
|
|
if calendarEventEntity['showDayOfWeek']:
|
|
_getEventDaysOfWeek(instance)
|
|
_showCalendarEvent(user, calId, Ent.INSTANCE, instance, l, lcount, FJQC)
|
|
Ind.Decrement()
|
|
except (GAPI.notFound, GAPI.deleted) as e:
|
|
if not checkCalendarExists(cal, calId, i, count):
|
|
_getMain().entityUnknownWarning(Ent.CALENDAR, calId, i, count)
|
|
break
|
|
_getMain().entityActionFailedWarning([Ent.CALENDAR, calId, Ent.EVENT, eventId], str(e), j, jcount)
|
|
except (GAPI.forbidden) as e:
|
|
_getMain().entityActionFailedWarning([Ent.CALENDAR, calId], str(e), i, count)
|
|
break
|
|
except GAPI.notACalendarUser:
|
|
_getMain().userCalServiceNotEnabledWarning(calId, i, count)
|
|
break
|
|
Ind.Decrement()
|
|
|
|
# gam calendars <CalendarEntity> info events <EventEntity> [maxinstances <Number>]
|
|
# [fields <EventFieldNameList>] [showdayofweek]
|
|
# [formatjson]
|
|
def doCalendarsInfoEvents(calIds):
|
|
calendarEventEntity = getCalendarEventEntity()
|
|
FJQC, fieldsList = _getCalendarInfoEventOptions(calendarEventEntity)
|
|
_infoCalendarEvents(None, None, None, calIds, len(calIds), calendarEventEntity, FJQC, fieldsList)
|
|
|
|
EVENT_INDEXED_TITLES = ['attendees', 'attachments', 'recurrence']
|
|
|
|
def _getCalendarPrintShowEventOptions(calendarEventEntity, entityType):
|
|
csvPF = _getMain().CSVPrintFile(['primaryEmail', 'calendarId', 'id'] if entityType == Ent.USER else ['calendarId', 'id'], 'sortall', indexedTitles=EVENT_INDEXED_TITLES) if Act.csvFormat() else None
|
|
FJQC = _getMain().FormatJSONQuoteChar(csvPF)
|
|
fieldsList = []
|
|
addCSVData = {}
|
|
addCSVDataLoc = 2 if entityType == Ent.USER else 1
|
|
attendeesList = False
|
|
while Cmd.ArgumentsRemaining():
|
|
myarg = _getMain().getArgument()
|
|
if csvPF and myarg == 'todrive':
|
|
csvPF.GetTodriveParameters()
|
|
elif _getCalendarListEventsDisplayProperty(myarg, calendarEventEntity):
|
|
pass
|
|
elif myarg == 'fields':
|
|
_getEventFields(fieldsList)
|
|
elif csvPF and myarg == 'addcsvdata':
|
|
_getMain().getAddCSVData(addCSVData)
|
|
elif myarg == 'countsonly':
|
|
calendarEventEntity['countsOnly'] = True
|
|
elif myarg == 'showdayofweek':
|
|
calendarEventEntity['showDayOfWeek'] = True
|
|
elif myarg == 'eventrowfilter':
|
|
calendarEventEntity['eventRowFilter'] = True
|
|
elif myarg == 'attendeeslist':
|
|
attendeesList = True
|
|
else:
|
|
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
|
if calendarEventEntity['countsOnly'] and not calendarEventEntity['eventRowFilter']:
|
|
fieldsList = ['id']
|
|
if csvPF:
|
|
if calendarEventEntity['countsOnly']:
|
|
csvPF.SetFormatJSON(False)
|
|
csvPF.RemoveTitles(['id'])
|
|
if addCSVData:
|
|
csvPF.InsertTitles(addCSVDataLoc, sorted(addCSVData.keys()))
|
|
csvPF.AddTitles(['events'])
|
|
csvPF.SetSortAllTitles()
|
|
calendarEventEntity['countsOnlyTitles'] = csvPF.titlesList[:]
|
|
else:
|
|
if addCSVData:
|
|
csvPF.InsertTitles(addCSVDataLoc, sorted(addCSVData.keys()))
|
|
if not FJQC.formatJSON and not fieldsList:
|
|
csvPF.AddTitles(EVENT_PRINT_ORDER)
|
|
csvPF.SetSortAllTitles()
|
|
_addEventEntitySelectFields(calendarEventEntity, fieldsList)
|
|
return (csvPF, FJQC, fieldsList, addCSVData, attendeesList)
|
|
|
|
# gam calendars <CalendarEntity> print events <EventEntity> <EventDisplayProperties>*
|
|
# [fields <EventFieldNameList>] [showdayofweek]
|
|
# (addcsvdata <FieldName> <String>)*
|
|
# [eventrowfilter]
|
|
# [countsonly|(formatjson [quotechar <Character>])] [todrive <ToDriveAttribute>*]
|
|
# gam calendars <CalendarEntity> show events <EventEntity> <EventDisplayProperties>*
|
|
# [fields <EventFieldNameList>] [showdayofweek]
|
|
# [countsonly|formatjson]
|
|
def doCalendarsPrintShowEvents(calIds):
|
|
calendarEventEntity = getCalendarEventEntity()
|
|
csvPF, FJQC, fieldsList, addCSVData, attendeesList = _getCalendarPrintShowEventOptions(calendarEventEntity, Ent.CALENDAR)
|
|
_printShowCalendarEvents(None, None, None, calIds, len(calIds), calendarEventEntity,
|
|
csvPF, FJQC, fieldsList, addCSVData, attendeesList)
|
|
if csvPF:
|
|
if calendarEventEntity['countsOnly'] and calendarEventEntity['eventRowFilter']:
|
|
csvPF.SetTitles(calendarEventEntity['countsOnlyTitles'])
|
|
csvPF.writeCSVfile('Calendar Events', True)
|
|
else:
|
|
csvPF.writeCSVfile('Calendar Events')
|
|
|
|
# <CalendarSettings> ::==
|
|
# [description <String>] [location <String>] [summary <String>] [timezone <TimeZone>]
|
|
# [autoacceptinvitations [<Boolean>]]
|
|
def _getCalendarSetting(myarg, body):
|
|
if myarg == 'description':
|
|
body['description'] = _getMain().getStringWithCRsNLs()
|
|
elif myarg == 'location':
|
|
body['location'] = _getMain().getString(Cmd.OB_STRING, minLen=0)
|
|
elif myarg == 'summary':
|
|
body['summary'] = _getMain().getString(Cmd.OB_STRING)
|
|
elif myarg == 'timezone':
|
|
body['timeZone'] = _getMain().getString(Cmd.OB_STRING)
|
|
elif myarg == 'autoacceptinvitations':
|
|
body['autoAcceptInvitations'] = _getMain().getBoolean()
|
|
else:
|
|
return False
|
|
return True
|
|
|
|
def getCalendarSettings(summaryRequired=False):
|
|
body = {}
|
|
while Cmd.ArgumentsRemaining():
|
|
myarg = _getMain().getArgument()
|
|
if _getCalendarSetting(myarg, body):
|
|
pass
|
|
else:
|
|
_getMain().unknownArgumentExit()
|
|
if summaryRequired and not body.get('summary', None):
|
|
_getMain().missingArgumentExit('summary <String>')
|
|
return body
|
|
|
|
# gam calendars <CalendarEntity> modify <CalendarSettings>
|
|
def doCalendarsModifySettings(calIds):
|
|
body = getCalendarSettings(summaryRequired=False)
|
|
count = len(calIds)
|
|
i = 0
|
|
for calId in calIds:
|
|
i += 1
|
|
calId, cal = validateCalendar(calId, i, count)
|
|
if not cal:
|
|
continue
|
|
try:
|
|
_getMain().callGAPI(cal.calendars(), 'patch',
|
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.INVALID],
|
|
calendarId=calId, body=body)
|
|
_getMain().entityActionPerformed([Ent.CALENDAR, calId], i, count)
|
|
except (GAPI.notFound, GAPI.forbidden, GAPI.invalid) as e:
|
|
_getMain().entityActionFailedWarning([Ent.CALENDAR, calId], str(e), i, count)
|
|
except GAPI.notACalendarUser:
|
|
_getMain().userCalServiceNotEnabledWarning(calId, i, count)
|
|
|
|
def _showCalendarSettings(calendar, j, jcount):
|
|
_getMain().printEntity([Ent.CALENDAR, calendar['id']], j, jcount)
|
|
Ind.Increment()
|
|
if 'dataOwner' in calendar:
|
|
_getMain().printKeyValueList(['Owner', calendar['dataOwner']])
|
|
if 'summaryOverride' in calendar or 'summary' in calendar:
|
|
_getMain().printKeyValueList(['Summary', calendar.get('summaryOverride', calendar.get('summary', ''))])
|
|
if 'description' in calendar:
|
|
_getMain().printKeyValueWithCRsNLs('Description', calendar['description'])
|
|
if 'location' in calendar:
|
|
_getMain().printKeyValueList(['Location', calendar['location']])
|
|
if 'timeZone' in calendar:
|
|
_getMain().printKeyValueList(['Timezone', calendar['timeZone']])
|
|
if 'conferenceProperties' in calendar:
|
|
_getMain().printKeyValueList(['ConferenceProperties', None])
|
|
Ind.Increment()
|
|
_getMain().printKeyValueList(['AllowedConferenceSolutionTypes', ','.join(calendar.get('conferenceProperties', {}).get('allowedConferenceSolutionTypes', []))])
|
|
Ind.Decrement()
|
|
if 'autoAcceptInvitations' in calendar:
|
|
_getMain().printKeyValueList(['AutoAcceptInvitations', calendar['autoAcceptInvitations']])
|
|
Ind.Decrement()
|
|
|
|
CALENDAR_SETTINGS_FIELDS_CHOICE_MAP = {
|
|
'autoacceptinvitations': 'autoAcceptInvitations',
|
|
'conferenceproperties': 'conferenceProperties',
|
|
'dataowner': 'dataOwner',
|
|
'description': 'description',
|
|
'id': 'id',
|
|
'location': 'location',
|
|
'summary': 'summary',
|
|
'timezone': 'timeZone',
|
|
}
|
|
|
|
# gam calendars <CalendarEntity> print settings [todrive <ToDriveAttribute>*]
|
|
# [fields <CalendarSettingsFieldList>]
|
|
# [formatjson] [quotechar <Character>}
|
|
# gam calendars <CalendarEntity> show settings
|
|
# [fields <CalendarSettingsFieldList>]
|
|
# [formatjson]
|
|
def doCalendarsPrintShowSettings(calIds):
|
|
csvPF = _getMain().CSVPrintFile(['calendarId'], 'sortall') if Act.csvFormat() else None
|
|
FJQC = _getMain().FormatJSONQuoteChar(csvPF)
|
|
fieldsList = []
|
|
while Cmd.ArgumentsRemaining():
|
|
myarg = _getMain().getArgument()
|
|
if csvPF and myarg == 'todrive':
|
|
csvPF.GetTodriveParameters()
|
|
elif _getMain().getFieldsList(myarg, CALENDAR_SETTINGS_FIELDS_CHOICE_MAP, fieldsList, initialField='id'):
|
|
pass
|
|
else:
|
|
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
|
fields = _getMain().getFieldsFromFieldsList(fieldsList)
|
|
count = len(calIds)
|
|
i = 0
|
|
for calId in calIds:
|
|
i += 1
|
|
calId, cal = validateCalendar(calId, i, count)
|
|
if not cal:
|
|
continue
|
|
try:
|
|
calendar = _getMain().callGAPI(cal.calendars(), 'get',
|
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.NOT_FOUND, GAPI.FORBIDDEN],
|
|
calendarId=calId, fields=fields)
|
|
if not csvPF:
|
|
if not FJQC.formatJSON:
|
|
_showCalendarSettings(calendar, i, count)
|
|
else:
|
|
_getMain().printLine(json.dumps(_getMain().cleanJSON(calendar), ensure_ascii=False, sort_keys=True))
|
|
else:
|
|
row = _getMain().flattenJSON(calendar)
|
|
if not FJQC.formatJSON:
|
|
row['calendarId'] = row.pop('id')
|
|
csvPF.WriteRowTitles(row)
|
|
elif csvPF.CheckRowTitles(row):
|
|
csvPF.WriteRowNoFilter({'calendarId': calId, 'JSON': json.dumps(_getMain().cleanJSON(calendar), ensure_ascii=False, sort_keys=True)})
|
|
except (GAPI.notFound, GAPI.forbidden) as e:
|
|
_getMain().entityActionFailedWarning([Ent.CALENDAR, calId], str(e), i, count)
|
|
except GAPI.notACalendarUser:
|
|
_getMain().userCalServiceNotEnabledWarning(calId, i, count)
|
|
if csvPF:
|
|
csvPF.writeCSVfile('Calendar Settings')
|
|
|
|
def _validateResourceId(cd, resourceId, i, count, exitOnNotFound):
|
|
try:
|
|
return _getMain().callGAPI(cd.resources().calendars(), 'get',
|
|
throwReasons=[GAPI.BAD_REQUEST, GAPI.RESOURCE_NOT_FOUND, GAPI.FORBIDDEN],
|
|
customer=GC.Values[GC.CUSTOMER_ID], calendarResourceId=resourceId, fields='resourceEmail')['resourceEmail']
|
|
except (GAPI.badRequest, GAPI.resourceNotFound, GAPI.forbidden):
|
|
if exitOnNotFound:
|
|
_getMain().entityDoesNotExistExit(Ent.RESOURCE_CALENDAR, resourceId, i, count)
|
|
_getMain().checkEntityAFDNEorAccessErrorExit(cd, Ent.RESOURCE_CALENDAR, resourceId, i, count)
|
|
return None
|
|
|
|
def _normalizeResourceIdGetRuleIds(cd, resourceId, i, count, ACLScopeEntity, showAction=True):
|
|
calId = _validateResourceId(cd, resourceId, i, count, False)
|
|
if not calId:
|
|
return (None, None, 0)
|
|
if ACLScopeEntity['dict']:
|
|
ruleIds = ACLScopeEntity['dict'][resourceId]
|
|
else:
|
|
ruleIds = ACLScopeEntity['list']
|
|
jcount = len(ruleIds)
|
|
if showAction:
|
|
_getMain().entityPerformActionNumItems([Ent.RESOURCE_CALENDAR, resourceId], jcount, Ent.CALENDAR_ACL, i, count)
|
|
if jcount == 0:
|
|
_getMain().setSysExitRC(_getMain().NO_ENTITIES_FOUND_RC)
|
|
return (calId, ruleIds, jcount)
|
|
|
|
# gam resource <ResourceID> create calendaracls <CalendarACLRole> <CalendarACLScopeEntity> [sendnotifications <Boolean>]
|
|
# gam resources <ResourceEntity> create calendaracls <CalendarACLRole> <CalendarACLScopeEntity> [sendnotifications <Boolean>]
|
|
def doResourceCreateCalendarACLs(entityList):
|
|
cal = _getMain().buildGAPIObject(API.CALENDAR)
|
|
cd = _getMain().buildGAPIObject(API.DIRECTORY)
|
|
role, ACLScopeEntity, sendNotifications = getCalendarCreateUpdateACLsOptions(True)
|
|
i = 0
|
|
count = len(entityList)
|
|
for resourceId in entityList:
|
|
i += 1
|
|
calId, ruleIds, jcount = _normalizeResourceIdGetRuleIds(cd, resourceId, i, count, ACLScopeEntity)
|
|
if jcount == 0:
|
|
continue
|
|
_createCalendarACLs(cal, Ent.RESOURCE_CALENDAR, calId, i, count, role, ruleIds, jcount, sendNotifications)
|
|
|
|
def _resourceUpdateDeleteCalendarACLs(entityList, function, ACLScopeEntity, role, sendNotifications):
|
|
cal = _getMain().buildGAPIObject(API.CALENDAR)
|
|
cd = _getMain().buildGAPIObject(API.DIRECTORY)
|
|
i = 0
|
|
count = len(entityList)
|
|
for resourceId in entityList:
|
|
i += 1
|
|
calId, ruleIds, jcount = _normalizeResourceIdGetRuleIds(cd, resourceId, i, count, ACLScopeEntity)
|
|
if jcount == 0:
|
|
continue
|
|
_updateDeleteCalendarACLs(cal, function, Ent.RESOURCE_CALENDAR, calId, i, count, role, ruleIds, jcount, sendNotifications)
|
|
|
|
# gam resource <ResourceID> update calendaracls <CalendarACLRole> <CalendarACLScopeEntity> [sendnotifications <Boolean>]
|
|
# gam resources <ResourceEntity> update calendaracls <CalendarACLRole> <CalendarACLScopeEntity> [sendnotifications <Boolean>]
|
|
def doResourceUpdateCalendarACLs(entityList):
|
|
role, ACLScopeEntity, sendNotifications = getCalendarCreateUpdateACLsOptions(True)
|
|
_resourceUpdateDeleteCalendarACLs(entityList, 'patch', ACLScopeEntity, role, sendNotifications)
|
|
|
|
# gam resource <ResourceID> delete calendaracls [<CalendarACLRole>] <CalendarACLScopeEntity>
|
|
# gam resources <ResourceEntity> delete calendaracls [<CalendarACLRole>] <CalendarACLScopeEntity>
|
|
def doResourceDeleteCalendarACLs(entityList):
|
|
role, ACLScopeEntity = getCalendarDeleteACLsOptions(True)
|
|
_resourceUpdateDeleteCalendarACLs(entityList, 'delete', ACLScopeEntity, role, False)
|
|
|
|
# gam resource <ResourceID> info calendaracls <CalendarACLScopeEntity>
|
|
# [formatjson]
|
|
# gam resources <ResourceEntity> info calendaracls <CalendarACLScopeEntity>
|
|
# [formatjson]
|
|
def doResourceInfoCalendarACLs(entityList):
|
|
cal = _getMain().buildGAPIObject(API.CALENDAR)
|
|
cd = _getMain().buildGAPIObject(API.DIRECTORY)
|
|
ACLScopeEntity = getCalendarSiteACLScopeEntity()
|
|
FJQC = _getCalendarInfoACLOptions()
|
|
i = 0
|
|
count = len(entityList)
|
|
for resourceId in entityList:
|
|
i += 1
|
|
calId, ruleIds, jcount = _normalizeResourceIdGetRuleIds(cd, resourceId, i, count, ACLScopeEntity, showAction=not FJQC.formatJSON)
|
|
if jcount == 0:
|
|
continue
|
|
_infoCalendarACLs(cal, resourceId, Ent.RESOURCE_CALENDAR, calId, i, count, ruleIds, jcount, FJQC)
|
|
|
|
# gam resource <ResourceID> print calendaracls [todrive <ToDriveAttribute>*]
|
|
# [noselfowner] (addcsvdata <FieldName> <String>)*
|
|
# [formatjson [quotechar <Character>]]
|
|
# gam resources <ResourceEntity> print calendaracls [todrive <ToDriveAttribute>*]
|
|
# [noselfowner] (addcsvdata <FieldName> <String>)*
|
|
# [formatjson [quotechar <Character>]]
|
|
# gam resource <ResourceID> show calendaracls
|
|
# [noselfowner]
|
|
# [formatjson]
|
|
# gam resources <ResourceEntity> show calendaracls
|
|
# [noselfowner]
|
|
# [formatjson]
|
|
def doResourcePrintShowCalendarACLs(entityList):
|
|
cal = _getMain().buildGAPIObject(API.CALENDAR)
|
|
cd = _getMain().buildGAPIObject(API.DIRECTORY)
|
|
csvPF, FJQC, noSelfOwner, addCSVData = _getCalendarPrintShowACLOptions(['resourceId', 'resourceEmail'])
|
|
i = 0
|
|
count = len(entityList)
|
|
for resourceId in entityList:
|
|
i += 1
|
|
calId = _validateResourceId(cd, resourceId, i, count, False)
|
|
if not calId:
|
|
continue
|
|
_printShowCalendarACLs(cal, resourceId, Ent.RESOURCE_CALENDAR, calId, i, count, csvPF, FJQC, noSelfOwner, addCSVData)
|
|
if csvPF:
|
|
csvPF.writeCSVfile('Resource Calendar ACLs')
|
|
|