Files
GoogleDriveManagement/src/gam/cmd/people.py
2026-07-03 09:05:51 -04:00

2094 lines
96 KiB
Python

"""GAM People API contacts management."""
import re
import json
import sys
import google.auth
import google.auth.exceptions
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
from gam.cmd.contacts import (
CONTACTS_ORDERBY_CHOICE_MAP, CONTACTS_PROJECTION_CHOICE_MAP,
PEOPLE_ADDRESSES, PEOPLE_ADD_GROUPS_LIST, PEOPLE_BIOGRAPHIES,
PEOPLE_BIRTHDAYS, PEOPLE_CALENDAR_URLS, PEOPLE_CLIENT_DATA,
PEOPLE_COVER_PHOTOS, PEOPLE_DIRECTORY_MERGE_SOURCES_CHOICE_MAP,
PEOPLE_DIRECTORY_SOURCES_CHOICE_MAP, PEOPLE_EMAIL_ADDRESSES,
PEOPLE_EVENTS, PEOPLE_EXTERNAL_IDS, PEOPLE_FILE_ASES,
PEOPLE_GENDERS, PEOPLE_GROUPS_LIST, PEOPLE_GROUP_NAME,
PEOPLE_IM_CLIENTS, PEOPLE_INTERESTS, PEOPLE_LOCALES,
PEOPLE_LOCATIONS, PEOPLE_MEMBERSHIPS, PEOPLE_METADATA,
PEOPLE_MISC_KEYWORDS, PEOPLE_NAMES, PEOPLE_NICKNAMES,
PEOPLE_OCCUPATIONS, PEOPLE_ORGANIZATIONS, PEOPLE_PHONE_NUMBERS,
PEOPLE_PHOTOS, PEOPLE_READ_SOURCES_CHOICE_MAP, PEOPLE_RELATIONS,
PEOPLE_REMOVE_GROUPS_LIST, PEOPLE_SIP_ADDRESSES, PEOPLE_SKILLS,
PEOPLE_UPDATE_TIME, PEOPLE_URLS, PEOPLE_USER_DEFINED,
)
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 _initPeopleContactQueryAttributes(printShowCmd):
return {'query': None, 'updateTime': None,
'contactGroupSelect': None, 'contactGroupFilter': None, 'group': None, 'dropMemberships': False,
'mainContacts': True, 'otherContacts': printShowCmd, 'emailMatchPattern': None, 'emailMatchType': None}
def _getPeopleContactQueryAttributes(contactQuery, myarg, entityType, unknownAction, printShowCmd):
if myarg == 'query':
contactQuery['query'] = _getMain().getString(Cmd.OB_QUERY)
elif myarg in {'contactgroup', 'selectcontactgroup'}:
if entityType == Ent.USER:
contactQuery['contactGroupSelect'] = _getMain().getString(Cmd.OB_CONTACT_GROUP_ITEM)
contactQuery['contactGroupFilter'] = None
contactQuery['mainContacts'] = True
contactQuery['otherContacts'] = False
else:
_getMain().unknownArgumentExit()
elif myarg == 'emailmatchpattern':
contactQuery['emailMatchPattern'] = _getMain().getREPattern(re.IGNORECASE)
elif myarg == 'emailmatchtype':
contactQuery['emailMatchType'] = _getMain().getString(Cmd.OB_CONTACT_EMAIL_TYPE)
elif myarg == 'updatedmin':
_getMain().deprecatedArgument(myarg)
_getMain().getYYYYMMDD()
elif myarg == 'endquery':
return False
elif not printShowCmd:
if unknownAction < 0:
_getMain().unknownArgumentExit()
if unknownAction > 0:
Cmd.Backup()
return False
elif myarg == 'filtercontactgroup':
if entityType == Ent.USER:
contactQuery['contactGroupFilter'] = _getMain().getString(Cmd.OB_CONTACT_GROUP_ITEM)
contactQuery['contactGroupSelect'] = None
contactQuery['mainContacts'] = True
contactQuery['otherContacts'] = False
else:
_getMain().unknownArgumentExit()
elif myarg in {'maincontacts', 'selectmaincontacts'}:
if entityType == Ent.USER:
contactQuery['contactGroupSelect'] = None
contactQuery['contactGroupFilter'] = None
contactQuery['mainContacts'] = True
contactQuery['otherContacts'] = False
else:
_getMain().unknownArgumentExit()
elif myarg in {'othercontacts', 'selectothercontacts'}:
if entityType == Ent.USER:
contactQuery['contactGroupSelect'] = None
contactQuery['contactGroupFilter'] = None
contactQuery['mainContacts'] = False
contactQuery['otherContacts'] = True
else:
_getMain().unknownArgumentExit()
elif myarg == 'orderby':
_getMain().getOrderBySortOrder(CONTACTS_ORDERBY_CHOICE_MAP, 'ascending', False)
_getMain().deprecatedArgument(myarg)
elif myarg in CONTACTS_PROJECTION_CHOICE_MAP:
_getMain().deprecatedArgument(myarg)
elif myarg == 'showdeleted':
_getMain().deprecatedArgument(myarg)
else:
if unknownAction < 0:
_getMain().unknownArgumentExit()
if unknownAction > 0:
Cmd.Backup()
return False
return True
PEOPLE_CONTACT_SELECT_ARGUMENTS = {
'query', 'contactgroup', 'selectcontactgroup',
'maincontacts', 'selectmaincontacts',
'othercontacts', 'selectothercontacts',
'emailmatchpattern', 'emailmatchtype',
}
PEOPLE_CONTACT_DEPRECATED_SELECT_ARGUMENTS = {
'orderby', 'basic', 'thin', 'full', 'showdeleted',
}
def _getPeopleContactEntityList(entityType, unknownAction, noEntityArguments=None):
contactQuery = _initPeopleContactQueryAttributes(False)
if noEntityArguments is not None and (not Cmd.ArgumentsRemaining() or Cmd.PeekArgumentPresent(noEntityArguments)):
# <PeopleResourceNameEntity>|<PeopleUserContactSelection> are optional in dedup|replacedomain contacts
entityList = None
queriedContacts = True
elif Cmd.PeekArgumentPresent(PEOPLE_CONTACT_SELECT_ARGUMENTS.union(PEOPLE_CONTACT_DEPRECATED_SELECT_ARGUMENTS)):
entityList = None
queriedContacts = True
while Cmd.ArgumentsRemaining():
myarg = _getMain().getArgument()
if not _getPeopleContactQueryAttributes(contactQuery, myarg, entityType, unknownAction, False):
break
else:
entityList = _getMain().getEntityList(Cmd.OB_CONTACT_ENTITY)
queriedContacts = False
if unknownAction < 0:
_getMain().checkForExtraneousArguments()
return (entityList, entityList if isinstance(entityList, dict) else None, contactQuery, queriedContacts)
def _initPeopleOtherContactQueryAttributes():
return {'query': None,
'otherContacts': True, 'emailMatchPattern': None, 'emailMatchType': None}
def _getPeopleOtherContactQueryAttributes(contactQuery, myarg, unknownAction):
if myarg == 'query':
contactQuery['query'] = _getMain().getString(Cmd.OB_QUERY)
elif myarg == 'emailmatchpattern':
contactQuery['emailMatchPattern'] = _getMain().getREPattern(re.IGNORECASE)
elif myarg == 'emailmatchtype':
contactQuery['emailMatchType'] = _getMain().getString(Cmd.OB_CONTACT_EMAIL_TYPE)
elif myarg == 'endquery':
return False
else:
if unknownAction < 0:
_getMain().unknownArgumentExit()
if unknownAction > 0:
Cmd.Backup()
return False
return True
PEOPLE_OTHERCONTACT_SELECT_ARGUMENTS = {'query', 'emailmatchpattern', 'emailmatchtype'}
def _getPeopleOtherContactEntityList(unknownAction):
contactQuery = _initPeopleOtherContactQueryAttributes()
if Cmd.PeekArgumentPresent(PEOPLE_OTHERCONTACT_SELECT_ARGUMENTS):
entityList = None
queriedContacts = True
while Cmd.ArgumentsRemaining():
myarg = _getMain().getArgument()
if not _getPeopleOtherContactQueryAttributes(contactQuery, myarg, unknownAction):
break
else:
entityList = _getMain().getEntityList(Cmd.OB_CONTACT_ENTITY)
queriedContacts = False
if unknownAction < 0:
_getMain().checkForExtraneousArguments()
return (entityList, entityList if isinstance(entityList, dict) else None, contactQuery, queriedContacts)
def _getPeopleOtherContacts(people, entityType, user, i=0, count=0):
try:
_getMain().printGettingAllEntityItemsForWhom(Ent.OTHER_CONTACT, user, i, count)
results = _getMain().callGAPIpages(people.otherContacts(), 'list', 'otherContacts',
pageMessage=_getMain().getPageMessageForWhom(),
throwReasons=GAPI.PEOPLE_ACCESS_THROW_REASONS,
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
pageSize=1000,
readMask='emailAddresses', fields='nextPageToken,otherContacts(etag,resourceName,emailAddresses(value,type))')
otherContacts = {}
for contact in results:
resourceName = contact.pop('resourceName')
otherContacts[resourceName] = contact
return otherContacts
except GAPI.permissionDenied as e:
ClientAPIAccessDeniedExit(str(e))
except (GAPI.serviceNotAvailable, GAPI.forbidden):
_getMain().entityUnknownWarning(entityType, user, i, count)
return None
def queryPeopleContacts(people, contactQuery, fields, sortOrder, entityType, user, i=0, count=0):
sources = [PEOPLE_READ_SOURCES_CHOICE_MAP['domaincontact' if entityType == Ent.DOMAIN else 'contact']]
_getMain().printGettingAllEntityItemsForWhom(Ent.PEOPLE_CONTACT, user, i, count, query=contactQuery['query'])
pageMessage = _getMain().getPageMessageForWhom()
try:
# Contact group not selected
if not contactQuery['contactGroupSelect']:
if not contactQuery['query']:
results = _getMain().callGAPIpages(people.people().connections(), 'list', 'connections',
pageMessage=pageMessage,
throwReasons=GAPI.PEOPLE_ACCESS_THROW_REASONS,
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
pageSize=GC.Values[GC.PEOPLE_MAX_RESULTS],
resourceName='people/me', sources=sources, personFields=fields,
sortOrder=sortOrder, fields='nextPageToken,connections')
if contactQuery['contactGroupFilter']:
entityList = []
for person in results:
for membership in person.get(PEOPLE_MEMBERSHIPS, []):
if membership.get('contactGroupMembership', {}).get('contactGroupResourceName', '') == contactQuery['group']:
if contactQuery['dropMemberships']:
person.pop(PEOPLE_MEMBERSHIPS)
entityList.append(person)
break
else:
entityList = results
else:
results = _getMain().callGAPI(people.people(), 'searchContacts',
throwReasons=GAPI.PEOPLE_ACCESS_THROW_REASONS,
sources=sources, readMask=fields, query=contactQuery['query'])
entityList = [person['person'] for person in results.get('results', [])]
totalItems = len(entityList)
# Contact group selected
else:
totalItems = _getMain().callGAPI(people.contactGroups(), 'get',
throwReasons=GAPI.PEOPLE_ACCESS_THROW_REASONS,
resourceName=contactQuery['group'], groupFields='memberCount').get('memberCount', 0)
entityList = []
if totalItems > 0:
results = _getMain().callGAPI(people.contactGroups(), 'get',
throwReasons=GAPI.PEOPLE_ACCESS_THROW_REASONS,
resourceName=contactQuery['group'], maxMembers=totalItems, groupFields='name')
for resourceName in results.get('memberResourceNames', []):
result = _getMain().callGAPI(people.people(), 'get',
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
resourceName=resourceName, sources=sources, personFields=fields)
entityList.append(result)
if pageMessage and (contactQuery['contactGroupSelect'] or contactQuery['contactGroupFilter'] or contactQuery['query']):
showMessage = pageMessage.replace(TOTAL_ITEMS_MARKER, str(totalItems))
_getMain().writeGotMessage(showMessage.replace('{0}', str(Ent.Choose(Ent.PEOPLE_CONTACT, totalItems))))
return entityList
except (GAPI.permissionDenied, GAPI.failedPrecondition) as e:
ClientAPIAccessDeniedExit(str(e))
except (GAPI.serviceNotAvailable, GAPI.forbidden):
_getMain().entityUnknownWarning(entityType, user, i, count)
return None
def queryPeopleOtherContacts(people, contactQuery, fields, entityType, user, i=0, count=0):
sources = [PEOPLE_READ_SOURCES_CHOICE_MAP['contact']]
_getMain().printGettingAllEntityItemsForWhom(Ent.OTHER_CONTACT, user, i, count, query=contactQuery['query'])
pageMessage = _getMain().getPageMessageForWhom()
try:
if not contactQuery['query']:
entityList = _getMain().callGAPIpages(people.otherContacts(), 'list', 'otherContacts',
pageMessage=pageMessage,
throwReasons=GAPI.PEOPLE_ACCESS_THROW_REASONS,
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
pageSize=GC.Values[GC.PEOPLE_MAX_RESULTS],
readMask=fields, fields='nextPageToken,otherContacts', sources=sources)
else:
results = _getMain().callGAPI(people.otherContacts(), 'search',
throwReasons=GAPI.PEOPLE_ACCESS_THROW_REASONS,
pageSize=30, readMask=fields, query=contactQuery['query'])
entityList = [person['person'] for person in results.get('results', [])]
totalItems = len(entityList)
if pageMessage:
showMessage = pageMessage.replace(TOTAL_ITEMS_MARKER, str(totalItems))
_getMain().writeGotMessage(showMessage.replace('{0}', str(Ent.Choose(Ent.OTHER_CONTACT, totalItems))))
return entityList
except GAPI.permissionDenied as e:
ClientAPIAccessDeniedExit(str(e))
except GAPI.forbidden:
_getMain().userPeopleServiceNotEnabledWarning(user, i, count)
except GAPI.serviceNotAvailable:
_getMain().entityUnknownWarning(entityType, user, i, count)
return None
def getPeopleContactGroupsInfo(people, entityType, entityName, i, count):
contactGroupIDs = {}
contactGroupNames = {}
try:
groups = _getMain().callGAPIpages(people.contactGroups(), 'list', 'contactGroups',
throwReasons=GAPI.PEOPLE_ACCESS_THROW_REASONS,
pageSize=GC.Values[GC.PEOPLE_MAX_RESULTS],
groupFields='name', fields='nextPageToken,contactGroups(resourceName,name,formattedName)')
if groups:
for group in groups:
contactGroupIDs[group['resourceName']] = group['formattedName']
contactGroupNames.setdefault(group['formattedName'], [])
contactGroupNames[group['formattedName']].append(group['resourceName'])
if group['formattedName'] != group['name']:
contactGroupNames.setdefault(group['name'], [])
contactGroupNames[group['name']].append(group['resourceName'])
except GAPI.permissionDenied as e:
ClientAPIAccessDeniedExit(str(e))
except GAPI.forbidden:
_getMain().userPeopleServiceNotEnabledWarning(entityName, i, count)
return (contactGroupIDs, False)
except GAPI.serviceNotAvailable:
_getMain().entityUnknownWarning(entityType, entityName, i, count)
return (contactGroupIDs, False)
return (contactGroupIDs, contactGroupNames)
def validatePeopleContactGroup(people, contactGroupName,
contactGroupIDs, contactGroupNames, entityType, entityName, i, count):
if not contactGroupNames:
contactGroupIDs, contactGroupNames = getPeopleContactGroupsInfo(people, entityType, entityName, i, count)
if contactGroupNames is False:
return (None, contactGroupIDs, contactGroupNames)
if contactGroupName == 'clear':
return (contactGroupName, contactGroupIDs, contactGroupNames)
cg = _getMain().UID_PATTERN.match(contactGroupName)
if cg:
contactGroupName = cg.group(1)
if contactGroupName in contactGroupIDs:
return (contactGroupName, contactGroupIDs, contactGroupNames)
normalizedContactGroupName = _getMain().normalizeContactGroupResourceName(contactGroupName)
if normalizedContactGroupName in contactGroupIDs:
return (normalizedContactGroupName, contactGroupIDs, contactGroupNames)
else:
if contactGroupName in contactGroupIDs:
return (contactGroupName, contactGroupIDs, contactGroupNames)
if contactGroupName in contactGroupNames:
return (contactGroupNames[contactGroupName][0], contactGroupIDs, contactGroupNames)
normalizedContactGroupName = _getMain().normalizeContactGroupResourceName(contactGroupName)
if normalizedContactGroupName != contactGroupName and normalizedContactGroupName in contactGroupIDs:
return (normalizedContactGroupName, contactGroupIDs, contactGroupNames)
return (None, contactGroupIDs, contactGroupNames)
def validatePeopleContactGroupsList(people, contactId,
contactGroupsList, entityType, entityName, i, count):
result = True
contactGroupIDs = contactGroupNames = None
validatedContactGroupsList = []
for contactGroup in contactGroupsList:
groupId, contactGroupIDs, contactGroupNames = validatePeopleContactGroup(people, contactGroup,
contactGroupIDs, contactGroupNames, entityType, entityName, i, count)
if groupId:
validatedContactGroupsList.append(groupId)
else:
if contactGroupNames:
_getMain().entityActionNotPerformedWarning([entityType, entityName, Ent.CONTACT, contactId],
Ent.TypeNameMessage(Ent.CONTACT_GROUP, contactGroup, Msg.DOES_NOT_EXIST))
result = False
return (result, validatedContactGroupsList, contactGroupIDs)
# gam <UserTypeEntity> create contact <PeopleContactAttribute>+
# (contactgroup <ContactGroupItem>)*
# [(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> <String>)*))| returnidonly]
def createUserPeopleContact(users):
entityType = Ent.USER
peopleManager = _getMain().PeopleManager()
peopleEntityType = Ent.CONTACT
sources = PEOPLE_READ_SOURCES_CHOICE_MAP['contact']
parameters = {'csvPF': None, 'titles': ['User', 'resourceName'], 'addCSVData': {}, 'returnIdOnly': False}
body, personFields, contactGroupsLists = peopleManager.GetPersonFields(entityType, False, parameters)
csvPF = parameters['csvPF']
addCSVData = parameters['addCSVData']
if addCSVData:
csvPF.AddTitles(sorted(addCSVData.keys()))
returnIdOnly = parameters['returnIdOnly']
i, count, users = _getMain().getEntityArgument(users)
for user in users:
i += 1
user, people = _getMain().buildGAPIServiceObject(API.PEOPLE, user, i, count)
if not people:
continue
if contactGroupsLists[PEOPLE_GROUPS_LIST]:
result, validatedContactGroupsList, _ = validatePeopleContactGroupsList(people, '',
contactGroupsLists[PEOPLE_GROUPS_LIST], entityType, user, i, count)
if not result:
continue
peopleManager.AddContactGroupsToContact(body, validatedContactGroupsList)
personFields.add(PEOPLE_MEMBERSHIPS)
else:
personFields.discard(PEOPLE_MEMBERSHIPS)
try:
result = _getMain().callGAPI(people.people(), 'createContact',
throwReasons=GAPI.PEOPLE_ACCESS_THROW_REASONS+[GAPI.INVALID_ARGUMENT],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
personFields=','.join(personFields), body=body, sources=sources)
resourceName = result['resourceName']
if returnIdOnly:
_getMain().writeStdout(f'{resourceName}\n')
elif not csvPF:
_getMain().entityActionPerformed([entityType, user, peopleEntityType, resourceName], i, count)
else:
row = {'User': user, 'resourceName': resourceName}
if addCSVData:
row.update(addCSVData)
csvPF.WriteRow(row)
except GAPI.invalidArgument as e:
_getMain().entityActionFailedWarning([entityType, user, peopleEntityType, None], str(e), i, count)
except (GAPI.serviceNotAvailable, GAPI.forbidden, GAPI.permissionDenied, GAPI.failedPrecondition) as e:
ClientAPIAccessDeniedExit(str(e))
if csvPF:
csvPF.writeCSVfile('People Contacts')
def localPeopleContactSelects(contactQuery, contact):
if contactQuery['emailMatchPattern']:
emailMatchType = contactQuery['emailMatchType']
for item in contact.get(PEOPLE_EMAIL_ADDRESSES, []):
if contactQuery['emailMatchPattern'].match(item['value']):
if (not emailMatchType or emailMatchType == item.get('type', '')):
break
else:
return False
return True
def countLocalPeopleContactSelects(contactQuery, contacts):
if contacts is not None and contactQuery['emailMatchPattern']:
jcount = 0
for contact in contacts:
if localPeopleContactSelects(contactQuery, contact):
jcount += 1
else:
jcount = len(contacts) if contacts is not None else 0
return jcount
def clearPeopleEmailAddressMatches(contactClear, contact):
savedAddresses = []
updateRequired = False
emailMatchType = contactClear['emailClearType']
for item in contact.get(PEOPLE_EMAIL_ADDRESSES, []):
if (contactClear['emailClearPattern'].match(item['value']) and
(not emailMatchType or emailMatchType == item.get('type', ''))):
updateRequired = True
else:
savedAddresses.append(item)
if updateRequired:
contact[PEOPLE_EMAIL_ADDRESSES] = savedAddresses
return updateRequired
def _clearUpdatePeopleContacts(users, updateContacts):
action = Act.Get()
entityType = Ent.USER
peopleManager = _getMain().PeopleManager()
peopleEntityType = Ent.PEOPLE_CONTACT
sources = PEOPLE_READ_SOURCES_CHOICE_MAP['contact']
entityList, resourceNameLists, contactQuery, queriedContacts = _getPeopleContactEntityList(entityType, 1)
if updateContacts:
body, updatePersonFields, contactGroupsLists = peopleManager.GetPersonFields(entityType, True)
else:
contactClear = {'emailClearPattern': contactQuery['emailMatchPattern'], 'emailClearType': contactQuery['emailMatchType']}
deleteClearedContactsWithNoEmails = False
while Cmd.ArgumentsRemaining():
myarg = _getMain().getArgument()
if myarg == 'emailclearpattern':
contactClear['emailClearPattern'] = _getMain().getREPattern(re.IGNORECASE)
elif myarg == 'emailcleartype':
contactClear['emailClearType'] = _getMain().getString(Cmd.OB_CONTACT_EMAIL_TYPE)
elif myarg == 'deleteclearedcontactswithnoemails':
deleteClearedContactsWithNoEmails = True
else:
_getMain().unknownArgumentExit()
if not contactClear['emailClearPattern']:
_getMain().missingArgumentExit('emailclearpattern')
i, count, users = _getMain().getEntityArgument(users)
for user in users:
i += 1
if resourceNameLists:
entityList = resourceNameLists[user]
user, people = _getMain().buildGAPIServiceObject(API.PEOPLE, user, i, count)
if not people:
continue
if contactQuery['contactGroupSelect']:
groupId, _, contactGroupNames = validatePeopleContactGroup(people, contactQuery['contactGroupSelect'],
None, None, entityType, user, i, count)
if not groupId:
if contactGroupNames:
_getMain().entityActionFailedWarning([entityType, user, Ent.CONTACT_GROUP, contactQuery['contactGroupSelect']], Msg.DOES_NOT_EXIST, i, count)
continue
contactQuery['group'] = groupId
if queriedContacts:
entityList = queryPeopleContacts(people, contactQuery, 'emailAddresses,memberships', None, entityType, user, i, count)
if entityList is None:
continue
Act.Set(action)
j = 0
jcount = len(entityList)
_getMain().entityPerformActionModifierNumItems([entityType, user], Msg.MAXIMUM_OF, jcount, peopleEntityType, i, count)
if jcount == 0:
_getMain().setSysExitRC(_getMain().NO_ENTITIES_FOUND_RC)
continue
validatedContactGroupsLists = {
PEOPLE_GROUPS_LIST: [],
PEOPLE_ADD_GROUPS_LIST: [],
PEOPLE_REMOVE_GROUPS_LIST: []
}
Ind.Increment()
for contact in entityList:
j += 1
try:
if not queriedContacts:
resourceName = contact
contact = _getMain().callGAPI(people.people(), 'get',
bailOnInternalError=True,
throwReasons=[GAPI.NOT_FOUND, GAPI.INTERNAL_ERROR]+GAPI.PEOPLE_ACCESS_THROW_REASONS,
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
resourceName=contact, sources=sources, personFields='emailAddresses,memberships')
else:
if not localPeopleContactSelects(contactQuery, contact):
continue
resourceName = contact['resourceName']
if updateContacts:
body['etag'] = contact['etag']
existingContactGroupsList = []
for contactGroup in contact.get(PEOPLE_MEMBERSHIPS, []):
if 'contactGroupMembership' in contactGroup:
existingContactGroupsList.append(contactGroup['contactGroupMembership']['contactGroupResourceName'])
groupError = False
for field in [PEOPLE_GROUPS_LIST, PEOPLE_ADD_GROUPS_LIST, PEOPLE_REMOVE_GROUPS_LIST]:
if contactGroupsLists[field] and not validatedContactGroupsLists[field]:
status, validatedContactGroupsLists[field], _ = validatePeopleContactGroupsList(people, resourceName,
contactGroupsLists[field], entityType, user, i, count)
if not status:
groupError = True
if groupError:
break
if validatedContactGroupsLists[PEOPLE_GROUPS_LIST]:
peopleManager.AddContactGroupsToContact(body, validatedContactGroupsLists[PEOPLE_GROUPS_LIST])
updatePersonFields.add(PEOPLE_MEMBERSHIPS)
elif validatedContactGroupsLists[PEOPLE_ADD_GROUPS_LIST] or validatedContactGroupsLists[PEOPLE_REMOVE_GROUPS_LIST]:
body[PEOPLE_MEMBERSHIPS] = []
if contact.get(PEOPLE_MEMBERSHIPS):
peopleManager.AddFilteredContactGroupsToContact(body, existingContactGroupsList,
validatedContactGroupsLists[PEOPLE_REMOVE_GROUPS_LIST])
if validatedContactGroupsLists[PEOPLE_ADD_GROUPS_LIST]:
peopleManager.AddAdditionalContactGroupsToContact(body, validatedContactGroupsLists[PEOPLE_ADD_GROUPS_LIST])
updatePersonFields.add(PEOPLE_MEMBERSHIPS)
elif existingContactGroupsList:
updatePersonFields.discard(PEOPLE_MEMBERSHIPS)
else:
if not clearPeopleEmailAddressMatches(contactClear, contact):
continue
if deleteClearedContactsWithNoEmails and not contact[PEOPLE_EMAIL_ADDRESSES]:
Act.Set(Act.DELETE)
_getMain().callGAPI(people.people(), 'deleteContact',
bailOnInternalError=True,
throwReasons=[GAPI.NOT_FOUND, GAPI.INTERNAL_ERROR]+GAPI.PEOPLE_ACCESS_THROW_REASONS,
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
resourceName=resourceName)
_getMain().entityActionPerformed([entityType, user, peopleEntityType, resourceName], j, jcount)
continue
body = contact
updatePersonFields = [PEOPLE_EMAIL_ADDRESSES]
person = _getMain().callGAPI(people.people(), 'updateContact',
throwReasons=[GAPI.INVALID_ARGUMENT, GAPI.NOT_FOUND, GAPI.INTERNAL_ERROR]+GAPI.PEOPLE_ACCESS_THROW_REASONS,
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
resourceName=resourceName,
updatePersonFields=','.join(updatePersonFields), body=body, sources=sources)
_getMain().entityActionPerformed([entityType, user, peopleEntityType, person['resourceName']], j, jcount)
except GAPI.invalidArgument as e:
_getMain().entityActionFailedWarning([entityType, user, peopleEntityType, resourceName], str(e), j, jcount)
except (GAPI.notFound, GAPI.internalError):
_getMain().entityActionFailedWarning([entityType, user, peopleEntityType, resourceName], Msg.DOES_NOT_EXIST, j, jcount)
except (GAPI.serviceNotAvailable, GAPI.forbidden, GAPI.permissionDenied, GAPI.failedPrecondition) as e:
ClientAPIAccessDeniedExit(str(e))
Ind.Decrement()
# gam <UserTypeEntity> clear contacts <PeopleResourceNameEntity>|<PeopleUserContactSelection>
# [emailclearpattern <REMatchPattern>] [emailcleartype work|home|other|<String>]
# [deleteclearedcontactswithnoemails]
def clearUserPeopleContacts(users):
_clearUpdatePeopleContacts(users, False)
# gam <UserTypeEntity> update contacts <PeopleResourceNameEntity>|(<PeopleUserContactSelection> endquery)
# <PeopleContactAttribute>+
# (contactgroup <ContactGroupItem>)*|((addcontactgroup <ContactGroupItem>)* (removecontactgroup <ContactGroupItem>)*)
# gam <UserTypeEntity> update contacts
def updateUserPeopleContacts(users):
_clearUpdatePeopleContacts(users, True)
def dedupPeopleEmailAddressMatches(emailMatchType, contact):
sai = -1
savedAddresses = []
matches = {}
updateRequired = False
for item in contact.get(PEOPLE_EMAIL_ADDRESSES, []):
emailAddr = item['value']
emailType = item.get('type', '')
if (emailAddr in matches) and (not emailMatchType or emailType in matches[emailAddr]['types']):
if item['metadata'].get('primary', False):
savedAddresses[matches[emailAddr]['sai']]['metadata']['primary'] = True
updateRequired = True
else:
savedAddresses.append(item)
sai += 1
matches.setdefault(emailAddr, {'types': set(), 'sai': sai})
matches[emailAddr]['types'].add(emailType)
if updateRequired:
contact[PEOPLE_EMAIL_ADDRESSES] = savedAddresses
return updateRequired
def replaceDomainPeopleEmailAddressMatches(contactQuery, contact, replaceDomains):
updateRequired = False
if contactQuery['emailMatchPattern']:
emailMatchType = contactQuery['emailMatchType']
for item in contact.get(PEOPLE_EMAIL_ADDRESSES, []):
emailAddr = item['value']
emailType = item.get('type', '')
if contactQuery['emailMatchPattern'].match(emailAddr):
userName, domain = _getMain().splitEmailAddress(emailAddr)
domain = domain.lower()
if ((domain in replaceDomains) and
(not emailMatchType or emailType == emailMatchType)):
item['value'] = f'{userName}@{replaceDomains[domain]}'
updateRequired = True
else:
for item in contact.get(PEOPLE_EMAIL_ADDRESSES, []):
emailAddr = item['value']
emailType = item.get('type', '')
userName, domain = _getMain().splitEmailAddress(emailAddr)
domain = domain.lower()
if domain in replaceDomains:
item['value'] = f'{userName}@{replaceDomains[domain]}'
updateRequired = True
return updateRequired
# gam <UserTypeEntity> dedup contacts
# [<PeopleResourceNameEntity>|<PeopleUserContactSelection>]
# [matchType [<Boolean>]]
# gam <UserTypeEntity> replacedomain contacts
# [<PeopleResourceNameEntity>|<PeopleUserContactSelection>]
# (domain <DomainName> <DomainName>)+
def dedupReplaceDomainUserPeopleContacts(users):
action = Act.Get()
entityType = Ent.USER
peopleEntityType = Ent.PEOPLE_CONTACT
sources = PEOPLE_READ_SOURCES_CHOICE_MAP['contact']
entityList, resourceNameLists, contactQuery, queriedContacts = _getPeopleContactEntityList(entityType, 1, {'matchtype', 'domain'})
emailMatchType = False
replaceDomains = {}
while Cmd.ArgumentsRemaining():
myarg = _getMain().getArgument()
if action == Act.DEDUP and myarg == 'matchtype':
emailMatchType = _getMain().getBoolean()
elif action == Act.REPLACE_DOMAIN and myarg == 'domain':
domain = _getMain().getString(Cmd.OB_DOMAIN_NAME).lower()
replaceDomains[domain] = _getMain().getString(Cmd.OB_DOMAIN_NAME).lower()
else:
_getMain().unknownArgumentExit()
if action == Act.REPLACE_DOMAIN and not replaceDomains:
_getMain().missingArgumentExit('domain')
i, count, users = _getMain().getEntityArgument(users)
for user in users:
i += 1
if resourceNameLists:
entityList = resourceNameLists[user]
user, people = _getMain().buildGAPIServiceObject(API.PEOPLE, user, i, count)
if not people:
continue
if contactQuery['contactGroupSelect']:
groupId, _, contactGroupNames = validatePeopleContactGroup(people, contactQuery['contactGroupSelect'],
None, None, entityType, user, i, count)
if not groupId:
if contactGroupNames:
_getMain().entityActionFailedWarning([entityType, user, Ent.CONTACT_GROUP, contactQuery['contactGroupSelect']], Msg.DOES_NOT_EXIST, i, count)
continue
contactQuery['group'] = groupId
if queriedContacts:
entityList = queryPeopleContacts(people, contactQuery, 'emailAddresses,memberships', None, entityType, user, i, count)
if entityList is None:
continue
Act.Set(action)
j = 0
jcount = len(entityList)
_getMain().entityPerformActionModifierNumItems([entityType, user], Msg.MAXIMUM_OF, jcount, peopleEntityType, i, count)
if jcount == 0:
_getMain().setSysExitRC(_getMain().NO_ENTITIES_FOUND_RC)
continue
Act.Set(Act.UPDATE)
Ind.Increment()
for contact in entityList:
j += 1
try:
if not queriedContacts:
resourceName = contact
contact = _getMain().callGAPI(people.people(), 'get',
bailOnInternalError=True,
throwReasons=[GAPI.NOT_FOUND, GAPI.INTERNAL_ERROR]+GAPI.PEOPLE_ACCESS_THROW_REASONS,
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
resourceName=contact, sources=sources, personFields='emailAddresses,memberships')
else:
if action == Act.DEDUP and not localPeopleContactSelects(contactQuery, contact):
continue
resourceName = contact['resourceName']
if action == Act.DEDUP:
if not dedupPeopleEmailAddressMatches(emailMatchType, contact):
continue
else:
if not replaceDomainPeopleEmailAddressMatches(contactQuery, contact, replaceDomains):
continue
Act.Set(Act.UPDATE)
_getMain().callGAPI(people.people(), 'updateContact',
throwReasons=[GAPI.INVALID_ARGUMENT, GAPI.NOT_FOUND, GAPI.INTERNAL_ERROR]+GAPI.PEOPLE_ACCESS_THROW_REASONS,
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
resourceName=resourceName,
updatePersonFields='emailAddresses', body=contact)
_getMain().entityActionPerformed([entityType, user, peopleEntityType, resourceName], j, jcount)
except GAPI.invalidArgument as e:
_getMain().entityActionFailedWarning([entityType, user, peopleEntityType, resourceName], str(e), j, jcount)
except (GAPI.notFound, GAPI.internalError):
_getMain().entityActionFailedWarning([entityType, user, peopleEntityType, resourceName], Msg.DOES_NOT_EXIST, j, jcount)
except (GAPI.serviceNotAvailable, GAPI.forbidden, GAPI.permissionDenied, GAPI.failedPrecondition) as e:
ClientAPIAccessDeniedExit(str(e))
Ind.Decrement()
# gam <UserTypeEntity> delete contacts <PeopleResourceNameEntity>|<PeopleUserContactSelection>
def deleteUserPeopleContacts(users):
entityType = Ent.USER
peopleEntityType = Ent.PEOPLE_CONTACT
entityList, resourceNameLists, contactQuery, queriedContacts = _getPeopleContactEntityList(entityType, -1)
i, count, users = _getMain().getEntityArgument(users)
for user in users:
i += 1
if resourceNameLists:
entityList = resourceNameLists[user]
user, people = _getMain().buildGAPIServiceObject(API.PEOPLE, user, i, count)
if not people:
continue
if contactQuery['contactGroupSelect']:
groupId, _, contactGroupNames = validatePeopleContactGroup(people, contactQuery['contactGroupSelect'],
None, None, entityType, user, i, count)
if not groupId:
if contactGroupNames:
_getMain().entityActionFailedWarning([entityType, user, Ent.CONTACT_GROUP, contactQuery['contactGroupSelect']], Msg.DOES_NOT_EXIST, i, count)
continue
contactQuery['group'] = groupId
if queriedContacts:
entityList = queryPeopleContacts(people, contactQuery, 'emailAddresses', None, entityType, user, i, count)
if entityList is None:
continue
j = 0
jcount = len(entityList)
_getMain().entityPerformActionModifierNumItems([entityType, user], Msg.MAXIMUM_OF, jcount, peopleEntityType, i, count)
if jcount == 0:
_getMain().setSysExitRC(_getMain().NO_ENTITIES_FOUND_RC)
continue
Ind.Increment()
for contact in entityList:
j += 1
if isinstance(contact, dict):
if not localPeopleContactSelects(contactQuery, contact):
continue
resourceName = contact['resourceName']
else:
resourceName = _getMain().normalizePeopleResourceName(contact)
try:
_getMain().callGAPI(people.people(), 'deleteContact',
bailOnInternalError=True,
throwReasons=[GAPI.NOT_FOUND, GAPI.INTERNAL_ERROR]+GAPI.PEOPLE_ACCESS_THROW_REASONS,
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
resourceName=resourceName)
_getMain().entityActionPerformed([entityType, user, peopleEntityType, resourceName], j, jcount)
except (GAPI.notFound, GAPI.internalError):
_getMain().entityActionFailedWarning([entityType, user, peopleEntityType, resourceName], Msg.DOES_NOT_EXIST, j, jcount)
except (GAPI.serviceNotAvailable, GAPI.forbidden, GAPI.permissionDenied, GAPI.failedPrecondition) as e:
ClientAPIAccessDeniedExit(str(e))
Ind.Decrement()
def _initPersonMetadataParameters():
return {'strip': True, 'mapUpdateTime': False, 'sourceTypes': set()}
def _processPersonMetadata(person, parameters):
metadata = person.get(PEOPLE_METADATA, None)
if metadata is not None:
if parameters['mapUpdateTime']:
sources = person[PEOPLE_METADATA].get('sources', [])
if sources and sources[0].get(PEOPLE_UPDATE_TIME, None) is not None:
person[PEOPLE_UPDATE_TIME] = _getMain().formatLocalTime(sources[0][PEOPLE_UPDATE_TIME])
if parameters['sourceTypes']:
stripKeys = []
for k, v in person.items():
if isinstance(v, list):
person[k] = []
for entry in v:
if isinstance(entry, dict):
if entry.get('metadata', {}).get('source', {}).get('type', None) in parameters['sourceTypes']:
person[k].append(entry)
else:
person[k].append(entry)
if not person[k]:
stripKeys.append(k)
for k in stripKeys:
person.pop(k, None)
if parameters['strip']:
person.pop(PEOPLE_METADATA, None)
for v in person.values():
if isinstance(v, list):
for entry in v:
if isinstance(entry, dict):
entry.pop(PEOPLE_METADATA, None)
def addContactGroupNamesToContacts(contacts, contactGroupIDs, showContactGroupNamesList):
for contact in contacts:
if showContactGroupNamesList:
contact[PEOPLE_GROUPS_LIST] = []
for membership in contact.get('memberships', []):
if 'contactGroupMembership' in membership:
membership['contactGroupMembership']['contactGroupName'] = contactGroupIDs.get(membership['contactGroupMembership']['contactGroupResourceName'], _getMain().UNKNOWN)
if showContactGroupNamesList:
contact[PEOPLE_GROUPS_LIST].append(membership['contactGroupMembership']['contactGroupName'])
def _printPerson(entityTypeName, user, person, csvPF, FJQC, parameters):
_processPersonMetadata(person, parameters)
row = _getMain().flattenJSON(person, flattened={entityTypeName: user})
if not FJQC.formatJSON:
csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row):
csvPF.WriteRowNoFilter({entityTypeName: user, 'resourceName': person['resourceName'],
'JSON': json.dumps(_getMain().cleanJSON(person),
ensure_ascii=False, sort_keys=True)})
PEOPLE_CONTACT_OBJECT_KEYS = {
'addresses': 'type',
'calendarUrls': 'type',
'emailAddresses': 'type',
'events': 'type',
'externalIds': 'type',
'genders': 'value',
'imClients': 'type',
'locations': 'type',
'miscKeywords': 'type',
'nicknames': 'type',
'organizations': 'type',
'relations': 'type',
'urls': 'type',
'userDefined': 'key',
}
def _showPerson(userEntityType, user, entityType, person, i, count, FJQC, parameters):
_processPersonMetadata(person, parameters)
if not FJQC.formatJSON:
_getMain().printEntity([userEntityType, user, entityType, person['resourceName']], i, count)
Ind.Increment()
_getMain().showJSON(None, person, dictObjectsKey=PEOPLE_CONTACT_OBJECT_KEYS)
Ind.Decrement()
else:
_getMain().printLine(json.dumps(_getMain().cleanJSON(person), ensure_ascii=False, sort_keys=True))
def _printPersonEntityList(entityType, entityList, userEntityType, user, i, count, csvPF, FJQC, parameters, contactQuery):
if not csvPF:
jcount = len(entityList)
if not FJQC.formatJSON:
_getMain().entityPerformActionModifierNumItems([userEntityType, user], Msg.MAXIMUM_OF, jcount, entityType, i, count)
Ind.Increment()
j = 0
for person in entityList:
j += 1
if not contactQuery or localPeopleContactSelects(contactQuery, person):
_showPerson(userEntityType, user, entityType, person, j, jcount, FJQC, parameters)
Ind.Decrement()
elif entityList:
entityTypeName = Ent.Singular(userEntityType)
for person in entityList:
if not contactQuery or localPeopleContactSelects(contactQuery, person):
_printPerson(entityTypeName, user, person, csvPF, FJQC, parameters)
elif GC.Values[GC.CSV_OUTPUT_USERS_AUDIT]:
csvPF.WriteRowNoFilter({userEntityType: user})
PEOPLE_FIELDS_CHOICE_MAP = {
'additionalname': PEOPLE_NAMES,
'address': PEOPLE_ADDRESSES,
'addresses': PEOPLE_ADDRESSES,
'ageranges': 'ageRanges',
'billinginfo': PEOPLE_MISC_KEYWORDS,
'biography': PEOPLE_BIOGRAPHIES,
'biographies': PEOPLE_BIOGRAPHIES,
'birthday': PEOPLE_BIRTHDAYS,
'birthdays': PEOPLE_BIRTHDAYS,
'calendar': PEOPLE_CALENDAR_URLS,
'calendars': PEOPLE_CALENDAR_URLS,
'calendarurls': PEOPLE_CALENDAR_URLS,
'clientdata': PEOPLE_CLIENT_DATA,
'coverphotos': PEOPLE_COVER_PHOTOS,
'directoryserver': PEOPLE_MISC_KEYWORDS,
'email': PEOPLE_EMAIL_ADDRESSES,
'emails': PEOPLE_EMAIL_ADDRESSES,
'emailaddresses': PEOPLE_EMAIL_ADDRESSES,
'event': PEOPLE_EVENTS,
'events': PEOPLE_EVENTS,
'externalid': PEOPLE_EXTERNAL_IDS,
'externalids': PEOPLE_EXTERNAL_IDS,
'familyname': PEOPLE_NAMES,
'fileas': PEOPLE_FILE_ASES,
'firstname': PEOPLE_NAMES,
'gender': PEOPLE_GENDERS,
'genders': PEOPLE_GENDERS,
'givenname': PEOPLE_NAMES,
'hobby': PEOPLE_INTERESTS,
'hobbies': PEOPLE_INTERESTS,
'im': PEOPLE_IM_CLIENTS,
'ims': PEOPLE_IM_CLIENTS,
'imclients': PEOPLE_IM_CLIENTS,
'initials': PEOPLE_NICKNAMES,
'interests': PEOPLE_INTERESTS,
'jot': PEOPLE_MISC_KEYWORDS,
'jots': PEOPLE_MISC_KEYWORDS,
'language': PEOPLE_LOCALES,
'languages': PEOPLE_LOCALES,
'lastname': PEOPLE_NAMES,
'locales': PEOPLE_LOCALES,
'location': PEOPLE_LOCATIONS,
'locations': PEOPLE_LOCATIONS,
'maidenname': PEOPLE_NAMES,
'memberships': PEOPLE_MEMBERSHIPS,
'metadata': PEOPLE_METADATA,
'middlename': PEOPLE_NAMES,
'mileage': PEOPLE_MISC_KEYWORDS,
'misckeywords': PEOPLE_MISC_KEYWORDS,
'name': PEOPLE_NAMES,
'names': PEOPLE_NAMES,
'nickname': PEOPLE_NICKNAMES,
'nicknames': PEOPLE_NICKNAMES,
'note': PEOPLE_BIOGRAPHIES,
'notes': PEOPLE_BIOGRAPHIES,
'occupation': PEOPLE_OCCUPATIONS,
'occupations': PEOPLE_OCCUPATIONS,
'organization': PEOPLE_ORGANIZATIONS,
'organizations': PEOPLE_ORGANIZATIONS,
'organisation': PEOPLE_ORGANIZATIONS,
'organisations': PEOPLE_ORGANIZATIONS,
'phone': PEOPLE_PHONE_NUMBERS,
'phones': PEOPLE_PHONE_NUMBERS,
'phonenumbers': PEOPLE_PHONE_NUMBERS,
'photo': PEOPLE_PHOTOS,
'photos': PEOPLE_PHOTOS,
'prefix': PEOPLE_NAMES,
'priority': PEOPLE_MISC_KEYWORDS,
'relation': PEOPLE_RELATIONS,
'relations': PEOPLE_RELATIONS,
'sensitivity': PEOPLE_MISC_KEYWORDS,
'shortname': PEOPLE_NICKNAMES,
'sipaddress': PEOPLE_SIP_ADDRESSES,
'sipaddresses': PEOPLE_SIP_ADDRESSES,
'skills': PEOPLE_SKILLS,
'subject': PEOPLE_MISC_KEYWORDS,
'suffix': PEOPLE_NAMES,
'updated': PEOPLE_UPDATE_TIME,
'updatetime': PEOPLE_UPDATE_TIME,
'urls': PEOPLE_URLS,
'userdefined': PEOPLE_USER_DEFINED,
'userdefinedfield': PEOPLE_USER_DEFINED,
'userdefinedfields': PEOPLE_USER_DEFINED,
'website': PEOPLE_URLS,
'websites': PEOPLE_URLS,
}
PEOPLE_OTHER_CONTACTS_FIELDS_CHOICE_MAP = {
'email': PEOPLE_EMAIL_ADDRESSES,
'emails': PEOPLE_EMAIL_ADDRESSES,
'emailaddresses': PEOPLE_EMAIL_ADDRESSES,
'metadata': PEOPLE_METADATA,
'names': PEOPLE_NAMES,
'phone': PEOPLE_PHONE_NUMBERS,
'phones': PEOPLE_PHONE_NUMBERS,
'phonenumbers': PEOPLE_PHONE_NUMBERS,
'photo': PEOPLE_PHOTOS,
'photos': PEOPLE_PHOTOS,
}
PEOPLE_CONTACTS_DEFAULT_FIELDS = ['names', 'emailaddresses', 'phonenumbers']
PEOPLE_ORDERBY_CHOICE_MAP = {
'firstname': 'FIRST_NAME_ASCENDING',
'lastname': 'LAST_NAME_ASCENDING',
'lastmodified': 'LAST_MODIFIED_',
}
def getPersonFieldsList(myarg, fieldsChoiceMap, fieldsList, initialField=None, fieldsArg='fields'):
if fieldsList is None:
fieldsList = []
return _getMain().getFieldsList(myarg, fieldsChoiceMap, fieldsList, initialField, fieldsArg)
def _getPersonFields(fieldsChoiceMap, defaultFields, fieldsList, parameters):
if fieldsList is None:
fieldsList = []
for field in fieldsChoiceMap:
_getMain().addFieldToFieldsList(field, fieldsChoiceMap, fieldsList)
elif not fieldsList:
for field in defaultFields:
_getMain().addFieldToFieldsList(field, fieldsChoiceMap, fieldsList)
fieldsList = list(set(fieldsList))
if PEOPLE_UPDATE_TIME in fieldsList:
parameters['mapUpdateTime'] = True
fieldsList.remove(PEOPLE_UPDATE_TIME)
fieldsList.append(PEOPLE_METADATA)
return ','.join(fieldsList)
def _infoPeople(users, entityType, source):
if entityType == Ent.DOMAIN:
people = _getMain().buildGAPIObject(API.PEOPLE)
peopleEntityType = Ent.DOMAIN_PROFILE if source == 'profile' else Ent.PEOPLE_CONTACT
sources = [PEOPLE_READ_SOURCES_CHOICE_MAP[source]]
entityList = _getMain().getEntityList(Cmd.OB_CONTACT_ENTITY)
resourceNameLists = entityList if isinstance(entityList, dict) else None
showContactGroups = False
FJQC = _getMain().FormatJSONQuoteChar()
fieldsList = []
parameters = _initPersonMetadataParameters()
while Cmd.ArgumentsRemaining():
myarg = _getMain().getArgument()
if myarg == 'allfields':
fieldsList = None
elif getPersonFieldsList(myarg, PEOPLE_FIELDS_CHOICE_MAP, fieldsList):
pass
elif myarg == 'showgroups':
showContactGroups = True
elif myarg == 'showmetadata':
parameters['strip'] = False
else:
FJQC.GetFormatJSON(myarg)
fields = _getPersonFields(PEOPLE_FIELDS_CHOICE_MAP, PEOPLE_CONTACTS_DEFAULT_FIELDS, fieldsList, parameters)
i, count, users = _getMain().getEntityArgument(users)
for user in users:
i += 1
if resourceNameLists:
entityList = resourceNameLists[user]
contactGroupIDs = contactGroupNames = None
if entityType != Ent.DOMAIN:
user, people = _getMain().buildGAPIServiceObject(API.PEOPLE, user, i, count)
if not people:
continue
if showContactGroups:
contactGroupIDs, contactGroupNames = getPeopleContactGroupsInfo(people, entityType, user, i, count)
if contactGroupNames is False:
continue
j = 0
jcount = len(entityList)
if not FJQC.formatJSON:
_getMain().entityPerformActionNumItems([entityType, user], jcount, peopleEntityType, i, count)
if jcount == 0:
_getMain().setSysExitRC(_getMain().NO_ENTITIES_FOUND_RC)
continue
Ind.Increment()
for contact in entityList:
j += 1
if isinstance(contact, dict):
resourceName = contact['resourceName']
else:
resourceName = _getMain().normalizePeopleResourceName(contact)
try:
result = _getMain().callGAPI(people.people(), 'get',
bailOnInternalError=True,
throwReasons=[GAPI.NOT_FOUND, GAPI.INTERNAL_ERROR, GAPI.INVALID_ARGUMENT]+GAPI.PEOPLE_ACCESS_THROW_REASONS,
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
resourceName=resourceName, sources=sources, personFields=fields)
except (GAPI.notFound, GAPI.internalError):
_getMain().entityActionFailedWarning([entityType, user, peopleEntityType, resourceName], Msg.DOES_NOT_EXIST, j, jcount)
continue
except GAPI.invalidArgument as e:
_getMain().entityActionFailedWarning([entityType, user, peopleEntityType, resourceName], str(e), j, jcount)
continue
except (GAPI.serviceNotAvailable, GAPI.forbidden, GAPI.permissionDenied, GAPI.failedPrecondition) as e:
ClientAPIAccessDeniedExit(str(e))
if showContactGroups and contactGroupIDs:
addContactGroupNamesToContacts([result], contactGroupIDs, False)
_showPerson(entityType, user, peopleEntityType, result, j, jcount, FJQC, parameters)
Ind.Decrement()
# gam <UserTypeEntity> info contacts <PeopleResourceNameEntity>
# [showgroups]
# [allFields|(fields <PeopleFieldNameList>)] [showmetadata]
# [formatjson]
def infoUserPeopleContacts(users):
_infoPeople(users, Ent.USER, 'contact')
# gam <UserTypeEntity> print contacts [todrive <ToDriveAttribute>*] <PeoplePrintShowUserContactSelection>
# [showgroups|showgroupnameslist] [orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
# [allfields|fields <PeopleFieldNameList>] [showmetadata]
# [countsonly|(formatjson [quotechar <Character>])]
# gam <UserTypeEntity> show contacts <PeoplePrintShowUserContactSelection>
# [showgroups] [orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
# [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
# [countsonly|formatjson]
def printShowUserPeopleContacts(users):
entityType = Ent.USER
entityTypeName = Ent.Singular(entityType)
csvPF = _getMain().CSVPrintFile([entityTypeName, 'resourceName'], 'sortall') if Act.csvFormat() else None
FJQC = _getMain().FormatJSONQuoteChar(csvPF)
CSVTitle = 'People Contacts'
fieldsList = []
parameters = _initPersonMetadataParameters()
sortOrder = None
countsOnly = showContactGroups = showContactGroupNamesList = False
contactQuery = _initPeopleContactQueryAttributes(True)
while Cmd.ArgumentsRemaining():
myarg = _getMain().getArgument()
if csvPF and myarg == 'todrive':
csvPF.GetTodriveParameters()
elif myarg == 'showgroups':
showContactGroups = True
elif myarg == 'showgroupnameslist':
showContactGroups = showContactGroupNamesList = True
elif myarg == 'allfields':
fieldsList = None
elif getPersonFieldsList(myarg, PEOPLE_FIELDS_CHOICE_MAP, fieldsList):
pass
elif myarg == 'countsonly':
countsOnly = True
if csvPF:
csvPF.SetTitles([entityTypeName, CSVTitle])
elif myarg == 'showmetadata':
parameters['strip'] = False
elif myarg == 'orderby':
sortOrder = _getMain().getChoice(PEOPLE_ORDERBY_CHOICE_MAP, mapChoice=True)
if sortOrder == 'LAST_MODIFIED_':
sortOrder += _getMain().getChoice(_getMain().SORTORDER_CHOICE_MAP, defaultChoice='DESCENDING', mapChoice=True)
elif _getPeopleContactQueryAttributes(contactQuery, myarg, entityType, 0, True):
pass
else:
FJQC.GetFormatJSONQuoteChar(myarg, True)
if countsOnly:
if csvPF:
csvPF.SetFormatJSON(False)
fieldsList = ['emailAddresses']
if contactQuery['mainContacts']:
fields = _getPersonFields(PEOPLE_FIELDS_CHOICE_MAP, PEOPLE_CONTACTS_DEFAULT_FIELDS, fieldsList, parameters)
if contactQuery['contactGroupFilter'] and 'memberships' not in fields:
fields += ',memberships'
contactQuery['dropMemberships'] = True
if contactQuery['otherContacts']:
if not fieldsList:
ofields = _getPersonFields(PEOPLE_OTHER_CONTACTS_FIELDS_CHOICE_MAP, PEOPLE_CONTACTS_DEFAULT_FIELDS, fieldsList, parameters)
else:
ofields = _getMain().getFieldsFromFieldsList([PEOPLE_OTHER_CONTACTS_FIELDS_CHOICE_MAP[field.lower()] for field in fieldsList if field.lower() in PEOPLE_OTHER_CONTACTS_FIELDS_CHOICE_MAP])
i, count, users = _getMain().getEntityArgument(users)
for user in users:
i += 1
user, people = _getMain().buildGAPIServiceObject(API.PEOPLE, user, i, count)
if not people:
continue
if contactQuery['otherContacts']:
_, opeople = _getMain().buildGAPIServiceObject(API.PEOPLE_OTHERCONTACTS, user, i, count)
if not opeople:
continue
contactGroupIDs = contactGroupNames = None
if showContactGroups:
contactGroupIDs, contactGroupNames = getPeopleContactGroupsInfo(people, entityType, user, i, count)
if contactGroupNames is False:
continue
contactGroupSelectFilter = contactQuery['contactGroupSelect'] or contactQuery['contactGroupFilter']
if contactGroupSelectFilter:
groupId, _, contactGroupNames =\
validatePeopleContactGroup(people, contactGroupSelectFilter,
contactGroupIDs, contactGroupNames, entityType, user, i, count)
if not groupId:
if contactGroupNames:
_getMain().entityActionFailedWarning([entityType, user, Ent.CONTACT_GROUP, contactGroupSelectFilter], Msg.DOES_NOT_EXIST, i, count)
continue
contactQuery['group'] = groupId
if contactQuery['mainContacts']:
contacts = queryPeopleContacts(people, contactQuery, fields, sortOrder, entityType, user, i, count)
else:
contacts = []
if contactQuery['otherContacts']:
ocontacts = queryPeopleOtherContacts(opeople, contactQuery, ofields, entityType, user, i, count)
else:
ocontacts = []
if countsOnly:
jcount = countLocalPeopleContactSelects(contactQuery, contacts)+countLocalPeopleContactSelects(contactQuery, ocontacts)
if csvPF:
csvPF.WriteRowTitles({entityTypeName: user, CSVTitle: jcount})
else:
_getMain().printEntityKVList([entityType, user], [CSVTitle, jcount], i, count)
elif contacts is not None or ocontacts is not None:
if not csvPF:
if contacts is not None and contactQuery['mainContacts']:
if showContactGroups and contactGroupIDs:
addContactGroupNamesToContacts(contacts, contactGroupIDs, False)
_printPersonEntityList(Ent.PEOPLE_CONTACT, contacts, entityType, user, i, count, csvPF, FJQC, parameters, contactQuery)
if ocontacts is not None and contactQuery['otherContacts']:
_printPersonEntityList(Ent.OTHER_CONTACT, ocontacts, entityType, user, i, count, csvPF, FJQC, parameters, contactQuery)
elif contacts or ocontacts:
if contacts:
if showContactGroups and contactGroupIDs:
addContactGroupNamesToContacts(contacts, contactGroupIDs, showContactGroupNamesList and FJQC.formatJSON)
_printPersonEntityList(Ent.PEOPLE_CONTACT, contacts, entityType, user, i, count, csvPF, FJQC, parameters, contactQuery)
if ocontacts:
_printPersonEntityList(Ent.OTHER_CONTACT, ocontacts, entityType, user, i, count, csvPF, FJQC, parameters, contactQuery)
elif GC.Values[GC.CSV_OUTPUT_USERS_AUDIT]:
csvPF.WriteRowNoFilter({Ent.Singular(entityType): user})
if csvPF:
csvPF.writeCSVfile(CSVTitle)
CONTACTGROUPS_MYCONTACTS_ID = 'contactGroups/myContacts'
CONTACTGROUPS_MYCONTACTS_NAME = 'My Contacts'
# gam <UserTypeEntity> copy othercontacts
# <OtherContactResourceNameEntity>|<OtherContactSelection>
def copyUserPeopleOtherContacts(users):
entityType = Ent.USER
peopleEntityType = Ent.OTHER_CONTACT
sources = [PEOPLE_READ_SOURCES_CHOICE_MAP['contact']]
copyMask = ['emailAddresses', 'names', 'phoneNumbers']
entityList, resourceNameLists, contactQuery, queriedContacts = _getPeopleOtherContactEntityList(-1)
_getMain().checkForExtraneousArguments()
i, count, users = _getMain().getEntityArgument(users)
for user in users:
i += 1
if resourceNameLists:
entityList = resourceNameLists[user]
user, people = _getMain().buildGAPIServiceObject(API.PEOPLE_OTHERCONTACTS, user, i, count)
if not people:
continue
if queriedContacts:
entityList = queryPeopleOtherContacts(people, contactQuery, 'emailAddresses', entityType, user, i, count)
if entityList is None:
continue
j = 0
jcount = len(entityList)
_getMain().entityPerformActionModifierNumItems([entityType, user], Msg.MAXIMUM_OF, jcount, peopleEntityType, i, count)
if jcount == 0:
_getMain().setSysExitRC(_getMain().NO_ENTITIES_FOUND_RC)
continue
Ind.Increment()
for contact in entityList:
j += 1
if isinstance(contact, dict):
if not localPeopleContactSelects(contactQuery, contact):
continue
resourceName = contact['resourceName']
else:
resourceName = _getMain().normalizeOtherContactsResourceName(contact)
try:
_getMain().callGAPI(people.otherContacts(), 'copyOtherContactToMyContactsGroup',
bailOnInternalError=True,
throwReasons=[GAPI.NOT_FOUND, GAPI.INTERNAL_ERROR]+GAPI.PEOPLE_ACCESS_THROW_REASONS,
resourceName=resourceName, body={'copyMask': ','.join(copyMask), 'sources': sources})
_getMain().entityModifierNewValueActionPerformed([entityType, user, peopleEntityType, resourceName], Act.MODIFIER_TO, CONTACTGROUPS_MYCONTACTS_NAME)
except (GAPI.notFound, GAPI.internalError):
_getMain().entityActionFailedWarning([entityType, user, peopleEntityType, resourceName], Msg.DOES_NOT_EXIST, j, jcount)
continue
except (GAPI.serviceNotAvailable, GAPI.forbidden, GAPI.permissionDenied, GAPI.failedPrecondition) as e:
ClientAPIAccessDeniedExit(str(e))
Ind.Decrement()
# gam <UserTypeEntity> delete othercontacts
# <OtherContactResourceNameEntity>|<OtherContactSelection>
# gam <UserTypeEntity> move othercontacts
# <OtherContactResourceNameEntity>|<OtherContactSelection>
# gam <UserTypeEntity> update othercontacts
# <OtherResourceNameEntity>|<OtherContactSelection>
# <PeopleContactAttribute>*
# (contactgroup <ContactGroupItem>)*
def processUserPeopleOtherContacts(users):
action = Act.Get()
entityType = Ent.USER
peopleEntityType = Ent.OTHER_CONTACT
sources = PEOPLE_READ_SOURCES_CHOICE_MAP['contact']
entityList, resourceNameLists, contactQuery, queriedContacts = _getPeopleOtherContactEntityList(1)
if action == Act.UPDATE:
Act.Set(Act.UPDATE_MOVE)
peopleManager = _getMain().PeopleManager()
body, updatePersonFields, contactGroupsLists = peopleManager.GetPersonFields(entityType, False)
else:
body = {PEOPLE_MEMBERSHIPS: [{'contactGroupMembership': {'contactGroupResourceName': CONTACTGROUPS_MYCONTACTS_ID}}]}
updatePersonFields = [PEOPLE_MEMBERSHIPS]
_getMain().checkForExtraneousArguments()
validatedContactGroupsList = [CONTACTGROUPS_MYCONTACTS_ID]
contactGroupIDs = {CONTACTGROUPS_MYCONTACTS_ID: CONTACTGROUPS_MYCONTACTS_NAME}
i, count, users = _getMain().getEntityArgument(users)
for user in users:
i += 1
if resourceNameLists:
entityList = resourceNameLists[user]
user, people = _getMain().buildGAPIServiceObject(API.PEOPLE_OTHERCONTACTS, user, i, count)
if not people:
continue
_, upeople = _getMain().buildGAPIServiceObject(API.PEOPLE, user, i, count)
if not upeople:
continue
if queriedContacts:
entityList = queryPeopleOtherContacts(people, contactQuery, 'emailAddresses', entityType, user, i, count)
if entityList is None:
continue
else:
otherContacts = _getPeopleOtherContacts(people, entityType, user, i=0, count=0)
if otherContacts is None:
continue
if action == Act.UPDATE:
if contactGroupsLists[PEOPLE_GROUPS_LIST]:
result, validatedContactGroupsList, contactGroupIDs =\
validatePeopleContactGroupsList(people, '', contactGroupsLists[PEOPLE_GROUPS_LIST], entityType, user, i, count)
if not result:
continue
if CONTACTGROUPS_MYCONTACTS_ID not in validatedContactGroupsList:
validatedContactGroupsList.insert(0, CONTACTGROUPS_MYCONTACTS_ID)
updatePersonFields.add(PEOPLE_MEMBERSHIPS)
contactGroupNamesList = []
for resourceName in validatedContactGroupsList:
contactGroupNamesList.append(contactGroupIDs[resourceName])
contactGroupNames = ','.join(contactGroupNamesList)
j = 0
jcount = len(entityList)
_getMain().entityPerformActionModifierNumItems([entityType, user], Msg.MAXIMUM_OF, jcount, peopleEntityType, i, count)
if jcount == 0:
_getMain().setSysExitRC(_getMain().NO_ENTITIES_FOUND_RC)
continue
Ind.Increment()
for contact in entityList:
j += 1
if isinstance(contact, dict):
if not localPeopleContactSelects(contactQuery, contact):
continue
resourceName = contact['resourceName']
else:
resourceName = _getMain().normalizeOtherContactsResourceName(contact)
contact = otherContacts.get(resourceName)
if contact is None:
_getMain().entityActionFailedWarning([entityType, user, peopleEntityType, resourceName], Msg.DOES_NOT_EXIST, j, jcount)
continue
peopleResourceName = resourceName.replace('otherContacts', 'people')
body['etag'] = contact['etag']
if action == Act.UPDATE and validatedContactGroupsList:
peopleManager.AddContactGroupsToContact(body, validatedContactGroupsList)
try:
_getMain().callGAPI(upeople.people(), 'updateContact',
throwReasons=[GAPI.INVALID_ARGUMENT, GAPI.NOT_FOUND, GAPI.INTERNAL_ERROR]+GAPI.PEOPLE_ACCESS_THROW_REASONS,
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
resourceName=peopleResourceName,
updatePersonFields=','.join(updatePersonFields), body=body, sources=sources)
if action != Act.DELETE:
_getMain().entityModifierNewValueActionPerformed([entityType, user, peopleEntityType, resourceName],
Act.MODIFIER_TO, contactGroupNames, j, jcount)
else:
maxRetries = 5
for retry in range(1, maxRetries+1):
try:
_getMain().callGAPI(upeople.people(), 'deleteContact',
bailOnInternalError=True,
throwReasons=[GAPI.NOT_FOUND, GAPI.INTERNAL_ERROR]+GAPI.PEOPLE_ACCESS_THROW_REASONS,
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
resourceName=peopleResourceName)
_getMain().entityActionPerformed([entityType, user, peopleEntityType, resourceName], j, jcount)
break
except (GAPI.notFound, GAPI.internalError):
if retry == maxRetries:
_getMain().entityActionFailedWarning([entityType, user, peopleEntityType, resourceName], Msg.DOES_NOT_EXIST, j, jcount)
break
time.sleep(retry*2)
except GAPI.invalidArgument as e:
_getMain().entityActionFailedWarning([entityType, user, peopleEntityType, resourceName], str(e), j, jcount)
continue
except (GAPI.notFound, GAPI.internalError):
_getMain().entityActionFailedWarning([entityType, user, peopleEntityType, resourceName], Msg.DOES_NOT_EXIST, j, jcount)
continue
except (GAPI.serviceNotAvailable, GAPI.forbidden, GAPI.permissionDenied, GAPI.failedPrecondition) as e:
ClientAPIAccessDeniedExit(str(e))
Ind.Decrement()
# gam <UserTypeEntity> print othercontacts [todrive <ToDriveAttribute>*] <OtherContactSelection>
# [allfields|(fields <OtherContactFieldNameList>)] [showmetadata]
# [countsonly|(formatjson [quotechar <Character>])]
# gam <UserTypeEntity> show othercontacts <OtherContactSelection>
# [allfields|(fields <OtherContactFieldNameList>)] [showmetadata]
# [countsonly|formatjson]
def printShowUserPeopleOtherContacts(users):
entityType = Ent.USER
entityTypeName = Ent.Singular(entityType)
csvPF = _getMain().CSVPrintFile([entityTypeName, 'resourceName'], 'sortall') if Act.csvFormat() else None
FJQC = _getMain().FormatJSONQuoteChar(csvPF)
CSVTitle = 'Other Contacts'
fieldsList = []
parameters = _initPersonMetadataParameters()
countsOnly = False
contactQuery = _initPeopleOtherContactQueryAttributes()
while Cmd.ArgumentsRemaining():
myarg = _getMain().getArgument()
if csvPF and myarg == 'todrive':
csvPF.GetTodriveParameters()
elif myarg == 'allfields':
fieldsList = None
elif getPersonFieldsList(myarg, PEOPLE_OTHER_CONTACTS_FIELDS_CHOICE_MAP, fieldsList):
pass
elif myarg == 'countsonly':
countsOnly = True
if csvPF:
csvPF.SetTitles([entityTypeName, CSVTitle])
elif myarg == 'showmetadata':
parameters['strip'] = False
elif _getPeopleOtherContactQueryAttributes(contactQuery, myarg, 0):
pass
else:
FJQC.GetFormatJSONQuoteChar(myarg, True)
if countsOnly:
if csvPF:
csvPF.SetFormatJSON(False)
fieldsList = ['emailAddresses']
fields = _getPersonFields(PEOPLE_OTHER_CONTACTS_FIELDS_CHOICE_MAP, PEOPLE_CONTACTS_DEFAULT_FIELDS, fieldsList, parameters)
i, count, users = _getMain().getEntityArgument(users)
for user in users:
i += 1
user, people = _getMain().buildGAPIServiceObject(API.PEOPLE_OTHERCONTACTS, user, i, count)
if not people:
continue
contacts = queryPeopleOtherContacts(people, contactQuery, fields, entityType, user, i, count)
if countsOnly:
jcount = countLocalPeopleContactSelects(contactQuery, contacts)
if csvPF:
csvPF.WriteRowTitles({entityTypeName: user, CSVTitle: jcount})
else:
_getMain().printEntityKVList([entityType, user], [CSVTitle, jcount], i, count)
elif contacts is not None:
if not csvPF:
_printPersonEntityList(Ent.OTHER_CONTACT, contacts, entityType, user, i, count, csvPF, FJQC, parameters, contactQuery)
elif contacts:
_printPersonEntityList(Ent.OTHER_CONTACT, contacts, entityType, user, i, count, csvPF, FJQC, parameters, contactQuery)
elif GC.Values[GC.CSV_OUTPUT_USERS_AUDIT]:
csvPF.WriteRowNoFilter({Ent.Singular(entityType): user})
if csvPF:
csvPF.writeCSVfile(CSVTitle)
def _printShowPeople(source):
people = _getMain().buildGAPIObject(API.PEOPLE_DIRECTORY)
entityType = Ent.DOMAIN
entityTypeName = Ent.Singular(entityType)
sources = [PEOPLE_DIRECTORY_SOURCES_CHOICE_MAP[source]]
if sources[0] == 'DIRECTORY_SOURCE_TYPE_DOMAIN_PROFILE':
peopleEntityType = Ent.DOMAIN_PROFILE
CSVTitle = 'People Profiles'
else:
peopleEntityType = Ent.DOMAIN_PEOPLE_CONTACT
CSVTitle = 'People Contacts'
function = 'listDirectoryPeople'
csvPF = _getMain().CSVPrintFile([entityTypeName, 'resourceName'], 'sortall') if Act.csvFormat() else None
FJQC = _getMain().FormatJSONQuoteChar(csvPF)
parameters = _initPersonMetadataParameters()
mergeSources = []
fieldsList = []
parameters = _initPersonMetadataParameters()
countsOnly = False
kwargs = {}
while Cmd.ArgumentsRemaining():
myarg = _getMain().getArgument()
if csvPF and myarg == 'todrive':
csvPF.GetTodriveParameters()
elif source is None and myarg in {'source', 'sources'}:
sources = [_getMain().getChoice(PEOPLE_DIRECTORY_SOURCES_CHOICE_MAP, mapChoice=True)]
elif myarg in {'mergesource', 'mergesources'}:
mergeSources = [_getMain().getChoice(PEOPLE_DIRECTORY_MERGE_SOURCES_CHOICE_MAP, mapChoice=True)]
elif myarg == 'showmetadata':
parameters['strip'] = False
elif myarg == 'allfields':
fieldsList = None
elif getPersonFieldsList(myarg, PEOPLE_FIELDS_CHOICE_MAP, fieldsList):
pass
elif myarg == 'countsonly':
countsOnly = True
fieldsList = [PEOPLE_METADATA]
if csvPF:
csvPF.SetTitles([entityTypeName, CSVTitle])
elif myarg == 'query':
kwargs['query'] = _getMain().getString(Cmd.OB_QUERY)
function = 'searchDirectoryPeople'
else:
FJQC.GetFormatJSONQuoteChar(myarg, True)
if countsOnly and csvPF:
csvPF.SetFormatJSON(False)
fields = _getPersonFields(PEOPLE_FIELDS_CHOICE_MAP, PEOPLE_CONTACTS_DEFAULT_FIELDS, fieldsList, parameters)
_getMain().printGettingAllEntityItemsForWhom(peopleEntityType, GC.Values[GC.DOMAIN], query=kwargs.get('query'))
try:
entityList = _getMain().callGAPIpages(people.people(), function, 'people',
pageMessage=_getMain().getPageMessageForWhom(),
throwReasons=GAPI.PEOPLE_ACCESS_THROW_REASONS,
pageSize=GC.Values[GC.PEOPLE_MAX_RESULTS],
sources=sources, mergeSources=mergeSources,
readMask=fields, fields='nextPageToken,people', **kwargs)
except (GAPI.serviceNotAvailable, GAPI.forbidden, GAPI.permissionDenied, GAPI.failedPrecondition) as e:
ClientAPIAccessDeniedExit(str(e))
if not countsOnly:
_printPersonEntityList(peopleEntityType, entityList, Ent.DOMAIN, GC.Values[GC.DOMAIN], 0, 0, csvPF, FJQC, parameters, None)
else:
jcount = len(entityList)
if csvPF:
csvPF.WriteRowTitles({entityTypeName: GC.Values[GC.DOMAIN], CSVTitle: jcount})
else:
_getMain().printEntityKVList([entityType, GC.Values[GC.DOMAIN]], [CSVTitle, jcount])
if csvPF:
csvPF.writeCSVfile(CSVTitle)
# gam info people|peopleprofile <PeopleResourceNameEntity>
# [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
# [formatjson]
def doInfoDomainPeopleProfile():
_infoPeople([GC.Values[GC.DOMAIN]], Ent.DOMAIN, 'profile')
# gam info peoplecontact <PeopleResourceNameEntity>
# [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
# [formatjson]
def doInfoDomainPeopleContacts():
_infoPeople([GC.Values[GC.DOMAIN]], Ent.DOMAIN, 'domaincontact')
# gam print people|peopleprofile [todrive <ToDriveAttribute>*]
# [query <String>]
# [mergesources <PeopleMergeSourceName>]
# [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
# [countsonly|(formatjson [quotechar <Character>])]
# gam show people|peopleprofile
# [query <String>]
# [mergesources <PeopleMergeSourceName>]
# [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
# [countsonlyformatjson]
# gam print domaincontacts|peoplecontacts [todrive <ToDriveAttribute>*]
# [sources <PeopleSourceName>]
# [query <String>]
# [mergesources <PeopleMergeSourceName>]
# [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
# [countsonly|(formatjson [quotechar <Character>])]
# gam show domaincontacts|peoplecontacts
# [sources <PeopleSourceName>]
# [query <String>]
# [mergesources <PeopleMergeSourceName>]
# [countsonlyformatjson]
def doPrintShowDomainPeopleProfiles():
_printShowPeople('profile')
def doPrintShowDomainPeopleContacts():
_printShowPeople('domaincontact')
PEOPLE_PROFILE_SOURCETYPE_CHOICE_MAP = {
'account': 'ACCOUNT',
'accounts': 'ACCOUNT',
'domain': 'DOMAIN_PROFILE',
'domains': 'DOMAIN_PROFILE',
'profile': 'PROFILE',
'profiles': 'PROFILE',
}
# gam <UserTypeEntity> print peopleprofile [todrive <ToDriveAttribute>*]
# [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
# [sources <PeopleProfileSourceNameList>]
# [formatjson [quotechar <Character>]]
# gam <UserTypeEntity> show peopleprofile
# [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
# [sources <PeopleProfileSourceNameList>]
# [formatjson]
def printShowUserPeopleProfiles(users):
entityType = Ent.USER
entityTypeName = Ent.Singular(entityType)
sources = [PEOPLE_READ_SOURCES_CHOICE_MAP['profile']]
csvPF = _getMain().CSVPrintFile([entityTypeName, 'resourceName'], 'sortall') if Act.csvFormat() else None
FJQC = _getMain().FormatJSONQuoteChar(csvPF)
fieldsList = []
parameters = _initPersonMetadataParameters()
while Cmd.ArgumentsRemaining():
myarg = _getMain().getArgument()
if csvPF and myarg == 'todrive':
csvPF.GetTodriveParameters()
elif myarg == 'allfields':
fieldsList = None
elif getPersonFieldsList(myarg, PEOPLE_FIELDS_CHOICE_MAP, fieldsList):
pass
elif myarg in {'source', 'sources'}:
for field in _getMain()._getFieldsList():
if field in PEOPLE_PROFILE_SOURCETYPE_CHOICE_MAP:
parameters['sourceTypes'].add(PEOPLE_PROFILE_SOURCETYPE_CHOICE_MAP[field])
else:
_getMain().invalidChoiceExit(field, PEOPLE_PROFILE_SOURCETYPE_CHOICE_MAP, True)
elif myarg == 'showmetadata':
parameters['strip'] = False
elif myarg == 'peoplelookupuser':
_getMain().deprecatedArgument(myarg)
else:
FJQC.GetFormatJSONQuoteChar(myarg, True)
fields = _getPersonFields(PEOPLE_FIELDS_CHOICE_MAP, PEOPLE_CONTACTS_DEFAULT_FIELDS, fieldsList, parameters)
i, count, users = _getMain().getEntityArgument(users)
for user in users:
i += 1
# user, people = buildGAPIServiceObject(API.PEOPLE_DIRECTORY, user, i, count)
user, people = _getMain().buildGAPIServiceObject(API.PEOPLE, user, i, count)
if not people:
continue
if csvPF:
_getMain().printGettingEntityItemForWhom(Ent.PEOPLE_PROFILE, user, i, count)
try:
result = _getMain().callGAPI(people.people(), 'get',
throwReasons=[GAPI.NOT_FOUND]+GAPI.PEOPLE_ACCESS_THROW_REASONS,
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
resourceName='people/me', sources=sources, personFields=fields)
except GAPI.notFound:
_getMain().entityUnknownWarning(Ent.PEOPLE_PROFILE, user, i, count)
continue
except (GAPI.serviceNotAvailable, GAPI.forbidden, GAPI.permissionDenied, GAPI.failedPrecondition) as e:
ClientAPIAccessDeniedExit(str(e))
if not csvPF:
_showPerson(entityType, user, Ent.PEOPLE_PROFILE, result, i, count, FJQC, parameters)
else:
_printPerson(entityTypeName, user, result, csvPF, FJQC, parameters)
if csvPF:
csvPF.writeCSVfile('People Profiles')
def _processPeopleContactPhotos(users, function):
def _makeFilenameFromPattern(resourceName):
filename = filenamePattern[:]
if subForContactId:
filename = filename.replace('#contactid#', resourceName.split('/')[1])
if subForEmail:
for email in result.get(PEOPLE_EMAIL_ADDRESSES, []):
if email.get(PEOPLE_METADATA, {}).get('primary', False):
filename = filename.replace('#email#', email['value'])
break
else:
filename = filename.replace('#email#', resourceName.split('/')[1])
return filename
if users is not None:
entityType = Ent.USER
peopleEntityType = Ent.PEOPLE_CONTACT
sources = [PEOPLE_READ_SOURCES_CHOICE_MAP['contact']]
else:
users = [None]
people = _getMain().buildGAPIObject(API.PEOPLE_DIRECTORY)
entityType = Ent.DOMAIN
peopleEntityType = Ent.PEOPLE_CONTACT
sources = [PEOPLE_READ_SOURCES_CHOICE_MAP['domaincontact']]
entityList, resourceNameLists, contactQuery, queriedContacts = _getPeopleContactEntityList(entityType, 1)
if function in {'updateContactPhoto', 'getContactPhoto'}:
sourceFolder = targetFolder = os.getcwd()
filenamePattern = '#contactid#.jpg'
while Cmd.ArgumentsRemaining():
myarg = _getMain().getArgument()
if myarg == 'drivedir':
targetFolder = GC.Values[GC.DRIVE_DIR]
elif myarg == 'sourcefolder':
sourceFolder = _getMain().setFilePath(_getMain().getString(Cmd.OB_FILE_PATH), GC.INPUT_DIR)
elif myarg == 'targetfolder':
targetFolder = _getMain().setFilePath(_getMain().getString(Cmd.OB_FILE_PATH), GC.DRIVE_DIR)
if not os.path.isdir(targetFolder):
os.makedirs(targetFolder)
elif myarg == 'filename':
filenamePattern = _getMain().getString(Cmd.OB_FILE_NAME_PATTERN)
else:
_getMain().unknownArgumentExit()
subForContactId = filenamePattern.find('#contactid#') != -1
subForEmail = filenamePattern.find('#email#') != -1
if not subForContactId and not subForEmail:
filename = filenamePattern
else: #elif function == 'deleteContactPhoto':
_getMain().checkForExtraneousArguments()
subForContactId = subForEmail = False
i, count, users = _getMain().getEntityArgument(users)
for user in users:
i += 1
if resourceNameLists:
entityList = resourceNameLists[user]
if user is not None:
user, people = _getMain().buildGAPIServiceObject(API.PEOPLE, user, i, count)
if not people:
continue
else:
user = Ent.Singular(entityType)
if contactQuery['contactGroupSelect']:
groupId, _, contactGroupNames = validatePeopleContactGroup(people, contactQuery['contactGroupSelect'],
None, None, entityType, user, i, count)
if not groupId:
if contactGroupNames:
_getMain().entityActionFailedWarning([entityType, user, Ent.CONTACT_GROUP, contactQuery['contactGroupSelect']], Msg.DOES_NOT_EXIST, i, count)
continue
contactQuery['group'] = groupId
if queriedContacts:
entityList = queryPeopleContacts(people, contactQuery, 'emailAddresses,photos', None, entityType, user, i, count)
if entityList is None:
continue
j = 0
jcount = len(entityList)
_getMain().entityPerformActionModifierNumItems([entityType, user], Msg.MAXIMUM_OF, jcount, Ent.PHOTO, i, count)
if jcount == 0:
_getMain().setSysExitRC(_getMain().NO_ENTITIES_FOUND_RC)
continue
Ind.Increment()
for contact in entityList:
j += 1
if isinstance(contact, dict):
if not localPeopleContactSelects(contactQuery, contact):
continue
resourceName = contact['resourceName']
else:
resourceName = _getMain().normalizePeopleResourceName(contact)
try:
if subForEmail:
result = _getMain().callGAPI(people.people(), 'get',
bailOnInternalError=True,
throwReasons=[GAPI.NOT_FOUND, GAPI.INTERNAL_ERROR]+GAPI.PEOPLE_ACCESS_THROW_REASONS,
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
resourceName=resourceName, sources=sources, personFields='emailAddresses')
if function == 'updateContactPhoto':
if subForContactId or subForEmail:
filename = _makeFilenameFromPattern(resourceName)
filename = os.path.join(sourceFolder, filename)
with open(filename, 'rb') as f:
image_data = f.read()
_getMain().callGAPI(people.people(), function,
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.INTERNAL_ERROR]+GAPI.PEOPLE_ACCESS_THROW_REASONS,
resourceName=resourceName,
body={'photoBytes': base64.urlsafe_b64encode(image_data).decode(_getMain().UTF8)})
_getMain().entityActionPerformed([entityType, user, peopleEntityType, resourceName, Ent.PHOTO, filename], j, jcount)
elif function == 'getContactPhoto':
if subForContactId or subForEmail:
filename = _makeFilenameFromPattern(resourceName)
filename = os.path.join(targetFolder, filename)
result = _getMain().callGAPI(people.people(), 'get',
throwReasons=[GAPI.NOT_FOUND, GAPI.INTERNAL_ERROR]+GAPI.PEOPLE_ACCESS_THROW_REASONS,
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
resourceName=resourceName, personFields='photos')
url = None
for photo in result.get('photos', []):
if photo['metadata']['source']['type'] == 'CONTACT':
url = photo['url']
break
if not url:
_getMain().entityActionFailedWarning([entityType, user, peopleEntityType, resourceName, Ent.PHOTO, None], Msg.CONTACT_PHOTO_NOT_FOUND, j, jcount)
continue
try:
status, photo_data = _getMain().getHttpObj().request(url, 'GET')
if status['status'] != '200':
_getMain().entityActionFailedWarning([entityType, user, Ent.PHOTO, filename], Msg.NOT_ALLOWED, j, jcount)
continue
except (httplib2.HttpLib2Error, google.auth.exceptions.TransportError, RuntimeError) as e:
_getMain().entityActionFailedWarning([entityType, user, peopleEntityType, resourceName, Ent.PHOTO, filename], str(e), j, jcount)
continue
status, e = _getMain().writeFileReturnError(filename, photo_data, mode='wb')
if status:
_getMain().entityActionPerformed([entityType, user, peopleEntityType, resourceName, Ent.PHOTO, filename], j, jcount)
else:
_getMain().entityActionFailedWarning([entityType, user, peopleEntityType, resourceName, Ent.PHOTO, filename], str(e), j, jcount)
else: #elif function == 'deleteContactPhoto':
filename = ''
_getMain().callGAPI(people.people(), function,
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.INTERNAL_ERROR, GAPI.PHOTO_NOT_FOUND]+GAPI.PEOPLE_ACCESS_THROW_REASONS,
resourceName=resourceName)
_getMain().entityActionPerformed([entityType, user, peopleEntityType, resourceName, Ent.PHOTO, filename], j, jcount)
except (GAPI.notFound, GAPI.internalError):
_getMain().entityActionFailedWarning([entityType, user, peopleEntityType, resourceName], Msg.DOES_NOT_EXIST, j, jcount)
continue
except GAPI.photoNotFound:
_getMain().entityDoesNotHaveItemWarning([entityType, user, peopleEntityType, resourceName, Ent.PHOTO, filename], j, jcount)
except (GAPI.invalidArgument, OSError, IOError) as e:
_getMain().entityActionFailedWarning([entityType, user, peopleEntityType, resourceName, Ent.PHOTO, filename], str(e), j, jcount)
except (GAPI.serviceNotAvailable, GAPI.forbidden, GAPI.permissionDenied, GAPI.failedPrecondition) as e:
ClientAPIAccessDeniedExit(str(e))
break
Ind.Decrement()
# gam <UserTypeEntity> update contactphotos <PeopleResourceNameEntity>|<PeopleUserContactSelection>
# [drivedir|(sourcefolder <FilePath>)] [filename <FileNamePattern>]
def updateUserPeopleContactPhoto(users):
_processPeopleContactPhotos(users, 'updateContactPhoto')
# gam <UserTypeEntity> get contactphotos <PeopleResourceNameEntity>|<PeopleUserContactSelection>
# [drivedir|(targetfolder <FilePath>)] [filename <FileNamePattern>]
def getUserPeopleContactPhoto(users):
_processPeopleContactPhotos(users, 'getContactPhoto')
# gam <UserTypeEntity> delete contactphotos <PeopleResourceNameEntity>|<PeopleUserContactSelection>
def deleteUserPeopleContactPhoto(users):
_processPeopleContactPhotos(users, 'deleteContactPhoto')
# gam update contactphotos <PeopleResourceNameEntity>|<PeopleUserContactSelection>
# [drivedir|(sourcefolder <FilePath>)] [filename <FileNamePattern>]
def doUpdateDomainContactPhoto():
_processPeopleContactPhotos(None, 'updateContactPhoto')
# gam get contactphotos <PeopleResourceNameEntity>|<PeopleUserContactSelection>
# [drivedir|(targetfolder <FilePath>)] [filename <FileNamePattern>]
def doGetDomainContactPhoto():
_processPeopleContactPhotos(None, 'getContactPhoto')
# gam delete contactphoto <PeopleResourceNameEntity>|<PeopleUserContactSelection>
def doDeleteDomainContactPhoto():
_processPeopleContactPhotos(None, 'deleteContactPhoto')
# gam <UserTypeEntity> create contactgroup <ContactGroupAttribute>+
# [(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> <String>)*))| returnidonly]
def createUserPeopleContactGroup(users):
peopleManager = _getMain().PeopleManager()
entityType = Ent.USER
parameters = {'csvPF': None, 'titles': ['User', 'resourceName'], 'addCSVData': {}, 'returnIdOnly': False}
body, _ = peopleManager.GetContactGroupFields(parameters)
if PEOPLE_GROUP_NAME not in body:
return
csvPF = parameters['csvPF']
addCSVData = parameters['addCSVData']
if addCSVData:
csvPF.AddTitles(sorted(addCSVData.keys()))
returnIdOnly = parameters['returnIdOnly']
i, count, users = _getMain().getEntityArgument(users)
for user in users:
i += 1
user, people = _getMain().buildGAPIServiceObject(API.PEOPLE, user, i, count)
if not people:
continue
_, contactGroupNames = getPeopleContactGroupsInfo(people, entityType, user, i, count)
if contactGroupNames is False:
continue
contactGroup = body[PEOPLE_GROUP_NAME]
if contactGroup in contactGroupNames:
_getMain().entityActionFailedWarning([entityType, user], Ent.TypeNameMessage(Ent.CONTACT_GROUP, contactGroup, Msg.DUPLICATE), i, count)
continue
try:
result = _getMain().callGAPI(people.contactGroups(), 'create',
throwReasons=GAPI.PEOPLE_ACCESS_THROW_REASONS,
body={'contactGroup': body}, fields='resourceName')
resourceName = result['resourceName']
if returnIdOnly:
_getMain().writeStdout(f'{resourceName}\n')
elif not csvPF:
_getMain().entityActionPerformed([entityType, user, Ent.CONTACT_GROUP, resourceName], i, count)
else:
row = {'User': user, 'resourceName': resourceName}
if addCSVData:
row.update(addCSVData)
csvPF.WriteRow(row)
except (GAPI.forbidden, GAPI.permissionDenied):
_getMain().userPeopleServiceNotEnabledWarning(user, i, count)
except GAPI.serviceNotAvailable:
_getMain().entityUnknownWarning(entityType, user, i, count)
if csvPF:
csvPF.writeCSVfile('People Contact Groups')
# gam <UserTypeEntity> update contactgroups <ContactGroupItem> <ContactAttribute>+
def updateUserPeopleContactGroup(users):
peopleManager = _getMain().PeopleManager()
entityType = Ent.USER
entityList = _getMain().getStringReturnInList(Cmd.OB_CONTACT_GROUP_ITEM)
body, fields = peopleManager.GetContactGroupFields()
i, count, users = _getMain().getEntityArgument(users)
for user in users:
i += 1
user, people = _getMain().buildGAPIServiceObject(API.PEOPLE, user, i, count)
if not people:
continue
contactGroupIDs = contactGroupNames = None
j = 0
jcount = len(entityList)
_getMain().entityPerformActionNumItems([entityType, user], jcount, Ent.CONTACT_GROUP, i, count)
if jcount == 0:
_getMain().setSysExitRC(_getMain().NO_ENTITIES_FOUND_RC)
continue
Ind.Increment()
for contactGroup in entityList:
j += 1
try:
groupId, contactGroupIDs, contactGroupNames = validatePeopleContactGroup(people, contactGroup,
contactGroupIDs, contactGroupNames, entityType, user, i, count)
if not groupId:
if contactGroupNames:
_getMain().entityActionFailedWarning([entityType, user, Ent.CONTACT_GROUP, contactGroup], Msg.DOES_NOT_EXIST, j, jcount)
continue
break
result = _getMain().callGAPI(people.contactGroups(), 'get',
bailOnInternalError=True,
throwReasons=[GAPI.NOT_FOUND, GAPI.INTERNAL_ERROR]+GAPI.PEOPLE_ACCESS_THROW_REASONS,
resourceName=groupId)
body['etag'] = result['etag']
newContactGroup = body.get(PEOPLE_GROUP_NAME)
if newContactGroup:
if newContactGroup in contactGroupNames and groupId not in contactGroupNames[newContactGroup]:
_getMain().entityActionFailedWarning([entityType, user, Ent.CONTACT_GROUP, contactGroup],
Ent.TypeNameMessage(Ent.CONTACT_GROUP, newContactGroup, Msg.DUPLICATE), i, count)
continue
_getMain().callGAPI(people.contactGroups(), 'update',
throwReasons=[GAPI.NOT_FOUND]+GAPI.PEOPLE_ACCESS_THROW_REASONS,
resourceName=groupId, body={'contactGroup': body, 'updateGroupFields': fields})
_getMain().entityActionPerformed([entityType, user, Ent.CONTACT_GROUP, contactGroup], j, jcount)
except (GAPI.notFound, GAPI.internalError) as e:
_getMain().entityActionFailedWarning([entityType, user, Ent.CONTACT_GROUP, contactGroup], str(e), j, jcount)
except (GAPI.forbidden, GAPI.permissionDenied):
_getMain().userPeopleServiceNotEnabledWarning(user, i, count)
break
except GAPI.serviceNotAvailable:
_getMain().entityUnknownWarning(entityType, user, i, count)
break
Ind.Decrement()
# gam <UserTypeEntity> delete contactgroups <ContactGroupEntity>
def deleteUserPeopleContactGroups(users):
entityType = Ent.USER
entityList = _getMain().getEntityList(Cmd.OB_CONTACT_GROUP_ENTITY, shlexSplit=True)
contactGroupIdLists = entityList if isinstance(entityList, dict) else None
i, count, users = _getMain().getEntityArgument(users)
for user in users:
i += 1
if contactGroupIdLists:
entityList = contactGroupIdLists[user]
user, people = _getMain().buildGAPIServiceObject(API.PEOPLE, user, i, count)
if not people:
continue
contactGroupIDs = contactGroupNames = None
j = 0
jcount = len(entityList)
_getMain().entityPerformActionNumItems([entityType, user], jcount, Ent.CONTACT_GROUP, i, count)
if jcount == 0:
_getMain().setSysExitRC(_getMain().NO_ENTITIES_FOUND_RC)
continue
Ind.Increment()
for contactGroup in entityList:
j += 1
try:
groupId, contactGroupIDs, contactGroupNames = validatePeopleContactGroup(people, contactGroup,
contactGroupIDs, contactGroupNames, entityType, user, i, count)
if not groupId:
if contactGroupNames:
_getMain().entityActionFailedWarning([entityType, user, Ent.CONTACT_GROUP, contactGroup], Msg.DOES_NOT_EXIST, j, jcount)
continue
break
_getMain().callGAPI(people.contactGroups(), 'delete',
throwReasons=[GAPI.NOT_FOUND]+GAPI.PEOPLE_ACCESS_THROW_REASONS,
resourceName=groupId)
_getMain().entityActionPerformed([entityType, user, Ent.CONTACT_GROUP, contactGroup], j, jcount)
except GAPI.notFound as e:
_getMain().entityActionFailedWarning([entityType, user, Ent.CONTACT_GROUP, contactGroup], str(e), j, jcount)
except (GAPI.forbidden, GAPI.permissionDenied):
_getMain().userPeopleServiceNotEnabledWarning(user, i, count)
break
except GAPI.serviceNotAvailable:
_getMain().entityUnknownWarning(entityType, user, i, count)
break
Ind.Decrement()
PEOPLE_GROUP_TIME_OBJECTS = {'updateTime'}
def _normalizeContactGroupMetadata(contactGroup):
normalizedContactGroup = contactGroup.copy()
for k, v in normalizedContactGroup.pop('metadata', {}).items():
normalizedContactGroup[k] = v
return normalizedContactGroup
def _showContactGroup(userEntityType, user, entityType, contactGroup, i, count, FJQC):
if FJQC.formatJSON:
_getMain().printLine(json.dumps(_getMain().cleanJSON(contactGroup, timeObjects=PEOPLE_GROUP_TIME_OBJECTS),
ensure_ascii=False, sort_keys=True))
return
normalizedContactGroup = _normalizeContactGroupMetadata(contactGroup)
_getMain().printEntity([userEntityType, user, entityType, contactGroup['resourceName']], i, count)
Ind.Increment()
_getMain().showJSON(None, normalizedContactGroup, timeObjects=PEOPLE_GROUP_TIME_OBJECTS)
Ind.Decrement()
def _printContactGroup(entityTypeName, user, contactGroup, csvPF, FJQC):
normalizedContactGroup = _normalizeContactGroupMetadata(contactGroup)
row = _getMain().flattenJSON(normalizedContactGroup, flattened={entityTypeName: user}, timeObjects=PEOPLE_GROUP_TIME_OBJECTS)
if not FJQC.formatJSON:
csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row):
csvPF.WriteRowNoFilter({entityTypeName: user, 'resourceName': contactGroup['resourceName'],
'JSON': json.dumps(_getMain().cleanJSON(contactGroup, timeObjects=PEOPLE_GROUP_TIME_OBJECTS),
ensure_ascii=False, sort_keys=True)})
PEOPLE_CONTACTGROUPS_FIELDS_CHOICE_MAP = {
'clientdata': 'clientData',
'grouptype': 'groupType',
'membercount': 'memberCount',
'metadata': 'metadata',
'name': 'name',
}
PEOPLE_CONTACTGROUPS_DEFAULT_FIELDS = ['name', 'metadata', 'grouptype', 'membercount']
# gam <UserTypeEntity> info contactgroups <PeopleContactGroupEntity>
# [allfields|(fields <PeoplaContactGroupFieldList>)] [showmetadata]
# [formatjson]
def infoUserPeopleContactGroups(users):
entityType = Ent.USER
entityList = _getMain().getEntityList(Cmd.OB_CONTACT_GROUP_ENTITY, shlexSplit=True)
contactGroupIdLists = entityList if isinstance(entityList, dict) else None
FJQC = _getMain().FormatJSONQuoteChar()
fieldsList = []
parameters = _initPersonMetadataParameters()
while Cmd.ArgumentsRemaining():
myarg = _getMain().getArgument()
if myarg == 'allfields':
fieldsList = None
elif getPersonFieldsList(myarg, PEOPLE_CONTACTGROUPS_FIELDS_CHOICE_MAP, fieldsList):
pass
elif myarg == 'showmetadata':
parameters['strip'] = False
else:
FJQC.GetFormatJSON(myarg)
fields = _getPersonFields(PEOPLE_CONTACTGROUPS_FIELDS_CHOICE_MAP, PEOPLE_CONTACTGROUPS_DEFAULT_FIELDS, fieldsList, parameters)
i, count, users = _getMain().getEntityArgument(users)
for user in users:
i += 1
if contactGroupIdLists:
entityList = contactGroupIdLists[user]
user, people = _getMain().buildGAPIServiceObject(API.PEOPLE, user, i, count)
if not people:
continue
contactGroupIDs = contactGroupNames = None
j = 0
jcount = len(entityList)
if not FJQC.formatJSON:
_getMain().entityPerformActionNumItems([entityType, user], jcount, Ent.CONTACT_GROUP, i, count)
if jcount == 0:
_getMain().setSysExitRC(_getMain().NO_ENTITIES_FOUND_RC)
continue
Ind.Increment()
for contactGroup in entityList:
j += 1
try:
groupId, contactGroupIDs, contactGroupNames = validatePeopleContactGroup(people, contactGroup,
contactGroupIDs, contactGroupNames, entityType, user, i, count)
if not groupId:
if contactGroupNames:
_getMain().entityActionFailedWarning([entityType, user, Ent.CONTACT_GROUP, contactGroup], Msg.DOES_NOT_EXIST, j, jcount)
continue
break
group = _getMain().callGAPI(people.contactGroups(), 'get',
throwReasons=[GAPI.NOT_FOUND]+GAPI.PEOPLE_ACCESS_THROW_REASONS,
resourceName=groupId, groupFields=fields)
_showContactGroup(entityType, user, Ent.CONTACT_GROUP, group, j, jcount, FJQC)
except GAPI.notFound as e:
_getMain().entityActionFailedWarning([entityType, user, Ent.CONTACT_GROUP, contactGroup], str(e), j, jcount)
except (GAPI.forbidden, GAPI.permissionDenied):
_getMain().userPeopleServiceNotEnabledWarning(user, i, count)
break
except GAPI.serviceNotAvailable:
_getMain().entityUnknownWarning(entityType, user, i, count)
break
Ind.Decrement()
# gam <UserTypeEntity> print contactgroups [todrive <ToDriveAttribute>*]
# [allfields|(fields <PeoplaContactGroupFieldList>)] [showmetadata]
# [formatjson [quotechar <Character>]]
# gam <UserTypeEntity> show contactgroups
# [allfields|(fields <PeoplaContactGroupFieldList>)] [showmetadata]
# [formatjson]
def printShowUserPeopleContactGroups(users):
entityType = Ent.USER
entityTypeName = Ent.Singular(entityType)
csvPF = _getMain().CSVPrintFile([entityTypeName, 'resourceName'], 'sortall') if Act.csvFormat() else None
if csvPF:
csvPF.SetNoEscapeChar(True)
FJQC = _getMain().FormatJSONQuoteChar(csvPF)
fieldsList = []
parameters = _initPersonMetadataParameters()
while Cmd.ArgumentsRemaining():
myarg = _getMain().getArgument()
if csvPF and myarg == 'todrive':
csvPF.GetTodriveParameters()
elif myarg == 'allfields':
fieldsList = None
elif getPersonFieldsList(myarg, PEOPLE_CONTACTGROUPS_FIELDS_CHOICE_MAP, fieldsList):
pass
elif myarg == 'showmetadata':
parameters['strip'] = False
else:
FJQC.GetFormatJSONQuoteChar(myarg, True)
fields = _getPersonFields(PEOPLE_CONTACTGROUPS_FIELDS_CHOICE_MAP, PEOPLE_CONTACTGROUPS_DEFAULT_FIELDS, fieldsList, parameters)
i, count, users = _getMain().getEntityArgument(users)
for user in users:
i += 1
user, people = _getMain().buildGAPIServiceObject(API.PEOPLE, user, i, count)
if not people:
continue
_getMain().printGettingAllEntityItemsForWhom(Ent.PEOPLE_CONTACT_GROUP, user, i, count)
try:
entityList = _getMain().callGAPIpages(people.contactGroups(), 'list', 'contactGroups',
pageMessage=_getMain().getPageMessageForWhom(),
throwReasons=GAPI.PEOPLE_ACCESS_THROW_REASONS,
pageSize=GC.Values[GC.PEOPLE_MAX_RESULTS],
groupFields=fields, fields='nextPageToken,contactGroups')
except (GAPI.serviceNotAvailable, GAPI.forbidden, GAPI.permissionDenied) as e:
ClientAPIAccessDeniedExit(str(e))
_printPersonEntityList(Ent.PEOPLE_CONTACT_GROUP, entityList, entityType, user, i, count, csvPF, FJQC, parameters, None)
if csvPF:
csvPF.writeCSVfile('People Contact Groups')
# Delegate command utilities