Compare commits

..

3 Commits

Author SHA1 Message Date
Ross Scroggs
963cbebba0 Improved create|print|show chromeprofilecommand 2025-07-14 15:46:48 -07:00
Ross Scroggs
c0edbfe596 Update Chrome-Profile-Management.md
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2022) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-07-14 09:39:31 -07:00
Ross Scroggs
47617c2823 Updated gam create datatransfer to handle API change 2025-07-14 08:23:12 -07:00
7 changed files with 149 additions and 56 deletions

View File

@@ -685,6 +685,7 @@ If an item contains spaces, it should be surrounded by ".
<CalendarList> ::= "<CalendarItem>(,<CalendarItem>)*"
<ChatSpaceList> ::= "<ChatSpace>(,<ChatSpace>)*"
<ChromeProfileNameList> ::= "<ChromeProfileName>(,<ChromeProfileName>)*"
<ChromeProfileCommandNameList> ::= "<ChromeProfileCommandName>(,<ChromeProfileCommandName>)*"
<CIGroupAliasList> ::= "<CIGroupAlias>(,<CIGroupAlias>)*"
<CIGroupMemberTypeList> ::= "<CIGroupMemberType>(,<CIGroupMemberType>)*"
<CIPolicyNameList> ::= "<CIPolicyName>(,<CIPolicyName>)*"
@@ -2228,12 +2229,14 @@ gam show chromeneedsattn
<ChromeProfilePermanentID> ::= <String>
<ChromeProfileName> ::= customers/<CustomerID>/profiles/<ChromeProfilePermanentID> | <ChromeProfilePermanentID>
<ChromeProfileCommandName> ::= <ChomeProfileName>/commands/<String>
<ChromeProfileNameList> ::= "<ChromeProfileName>(,<ChromeProfileName>)*"
<ChromeProfileCommandName> ::= <ChomeProfileName>/commands/<String>
<ChromeProfileCommandNameList> ::= "<ChromeProfileCommandName>(,<ChromeProfileCommandName>)*"
<ChromeProfileNameEntity> ::=
<ChromeProfileNameList> |
(select <FileSelector>|<CSVFileSelector>) |
(filter <String> (filtertime<String> <Time>)* [orderby <ChromeProfileOrderByFieldName> [ascending|descending]])
(select <ChromeProfileNameList>|<FileSelector>|<CSVFileSelector>) |
(filter <String> (filtertime<String> <Time>)* [orderby <ChromeProfileOrderByFieldName> [ascending|descending]]) |
(commands <ChromeProfileCommandNameList>|<FileSelector>|<CSVFileSelector>)
<ChromeProfileFieldName> ::=
affiliationstate|
@@ -2297,7 +2300,7 @@ gam print chromeprofiles [todrive <ToDriveAttribute>*]
gam create chromeprofilecommand <ChromeProfileNameEntity>
[clearcache [<Boolean>]] [clearcookies [<Boolean>]]
[formatjson]
[csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]]
gam info chromeprofilecommand <ChromeProfileCommandName>
[formatjson]

View File

@@ -1,3 +1,12 @@
7.13.03
Added option `csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]]`
to `gam create chromeprofilecommand` so that command details are displayed in CSV format.
Added option `commands <ChromeProfileCommandNameList>|<FileSelector>|<CSVFileSelector>` to `<ChromeProfileNameEntity>`
so that `gam print|show chromeprofilecommands` can directly display the commands generated by
`gam create chromeprofilecommand` with the `csv` option.
7.13.02
Fixed bug in `gam create chromeprofilecommand` where `select|filter` were not recognized.

View File

@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
"""
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
__version__ = '7.13.02'
__version__ = '7.13.03'
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
#pylint: disable=wrong-import-position
@@ -25677,24 +25677,28 @@ def doPrintShowChromeProfiles():
csvPF.writeCSVfile('Chrome Profiles')
def _getChromeProfileNameList():
if not Cmd.PeekArgumentPresent(['select', 'filter', 'filters']):
if not Cmd.PeekArgumentPresent(['select', 'commands', 'filter', 'filters']):
return getString(Cmd.OB_CHROMEPROFILE_NAME_LIST).replace(',', ' ').split()
return []
def _initChromeProfileNameParameters():
cm = buildGAPIObject(API.CHROMEMANAGEMENT)
return (cm, {'profileNameList': _getChromeProfileNameList(), 'customerId': _getCustomerId(),
return (cm, {'profileNameList': _getChromeProfileNameList(),
'commandNameList': [],
'customerId': _getCustomerId(),
'cbfilter': None, 'filterTimes': {},
'OBY': OrderBy(CHROMEPROFILE_ORDERBY_CHOICE_MAP)})
def _getChromeProfileNameParameters(myarg, parameters):
if not parameters['cbfilter'] and myarg == 'select':
if not parameters['cbfilter'] and not parameters['commandNameList'] and myarg == 'select':
parameters['profileNameList'].extend(getEntityList(Cmd.OB_CHROMEPROFILE_NAME_LIST))
elif not parameters['profileNameList'] and myarg == 'orderby':
elif not parameters['cbfilter'] and not parameters['profileNameList'] and myarg == 'commands':
parameters['commandNameList'].extend(getEntityList(Cmd.OB_CHROMEPROFILE_COMMAND_NAME_LIST))
elif not parameters['profileNameList'] and not parameters['commandNameList'] and myarg == 'orderby':
parameters['OBY'].GetChoice()
elif not parameters['profileNameList'] and myarg.startswith('filtertime'):
elif not parameters['profileNameList'] and not parameters['commandNameList'] and myarg.startswith('filtertime'):
parameters['filterTimes'][myarg] = getTimeOrDeltaFromNow()
elif not parameters['profileNameList'] and myarg in {'filter', 'filters'}:
elif not parameters['profileNameList'] and not parameters['commandNameList'] and myarg in {'filter', 'filters'}:
parameters['cbfilter'] = getString(Cmd.OB_STRING)
else:
return False
@@ -25703,9 +25707,14 @@ def _getChromeProfileNameParameters(myarg, parameters):
def _getChromeProfileNameEntityForCommand(cm, parameters):
if parameters['cbfilter'] is None:
customerId = parameters['customerId']
for i, profileName in enumerate(parameters['profileNameList']):
if not profileName.startswith('customers'):
parameters['profileNameList'][i] = f'customers/{customerId}/profiles/{profileName}'
if parameters['profileNameList']:
for i, profileName in enumerate(parameters['profileNameList']):
if not profileName.startswith('customers'):
parameters['profileNameList'][i] = f'customers/{customerId}/profiles/{profileName}'
elif parameters['commandNameList']:
for i, commandName in enumerate(parameters['commandNameList']):
if not commandName.startswith('customers'):
parameters['commandNameList'][i] = f'customers/{customerId}/profiles/{commandName}'
return
if parameters['filterTimes']:
for filterTimeName, filterTimeValue in iter(parameters['filterTimes'].items()):
@@ -25740,13 +25749,23 @@ def _showChromeProfileCommand(profcmd, FJQC, i=0, count=0):
showJSON(None, profcmd, timeObjects=CHROMEPROFILECOMMAND_TIME_OBJECTS)
Ind.Decrement()
def _printChromeProfileCommand(profcmd, csvPF, FJQC):
row = flattenJSON(profcmd, timeObjects=CHROMEPROFILECOMMAND_TIME_OBJECTS)
if not FJQC.formatJSON:
csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row):
csvPF.WriteRowNoFilter({'name': profcmd['name'],
'JSON': json.dumps(cleanJSON(profcmd, timeObjects=CHROMEPROFILECOMMAND_TIME_OBJECTS),
ensure_ascii=False, sort_keys=True)})
# gam create chromeprofilecommand <ChromeProfileNameEntity>
# [clearcache [<Boolean>]] [clearcookies [<Boolean>]]
# [formatjson]
# [csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]]
def doCreateChromeProfileCommand():
cm, parameters = _initChromeProfileNameParameters()
body = {'commandType': 'clearBrowsingData', 'payload': {}}
FJQC = FormatJSONQuoteChar()
csvPF = None
FJQC = FormatJSONQuoteChar(None)
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if _getChromeProfileNameParameters(myarg, parameters):
@@ -25755,8 +25774,13 @@ def doCreateChromeProfileCommand():
body['payload']['clearCache'] = getBoolean()
elif myarg == 'clearcookies':
body['payload']['clearCookies'] = getBoolean()
elif myarg == 'csv':
csvPF = CSVPrintFile(['name'], 'sortall')
FJQC.SetCsvPF(csvPF)
elif csvPF and myarg == 'todrive':
csvPF.GetTodriveParameters()
else:
FJQC.GetFormatJSON(myarg)
FJQC.GetFormatJSONQuoteChar(myarg, True)
_getChromeProfileNameEntityForCommand(cm, parameters)
count = len(parameters['profileNameList'])
i = 0
@@ -25766,11 +25790,16 @@ def doCreateChromeProfileCommand():
profcmd = callGAPI(cm.customers().profiles().commands(), 'create',
throwReasons=[GAPI.INVALID_ARGUMENT, GAPI.NOT_FOUND, GAPI.PERMISSION_DENIED],
parent=profileName, body=body)
_showChromeProfileCommand(profcmd, FJQC)
if csvPF is None:
_showChromeProfileCommand(profcmd, FJQC, i, count)
else:
_printChromeProfileCommand(profcmd, csvPF, FJQC)
except (GAPI.notFound) as e:
entityActionFailedWarning([Ent.CHROME_PROFILE_COMMAND, profileName], str(e), i, count)
except (GAPI.invalidArgument, GAPI.permissionDenied) as e:
entityActionFailedExit([Ent.CHROME_PROFILE_COMMAND, profileName], str(e))
if csvPF:
csvPF.writeCSVfile('Chrome Profile Commands')
# gam info chromeprofilecommand <ChromeProfileCommandName>
# [formatjson]
@@ -25794,15 +25823,6 @@ def doInfoChromeProfileCommand():
# gam print chromeprofilecommands <ChromeProfilNameEntity> [todrive <ToDriveAttribute>*]
# [formatjson [quotechar <Character>]]
def doPrintShowChromeProfileCommands():
def _printProfileCommand(profcmd):
row = flattenJSON(profcmd, timeObjects=CHROMEPROFILECOMMAND_TIME_OBJECTS)
if not FJQC.formatJSON:
csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row):
csvPF.WriteRowNoFilter({'name': profcmd['name'],
'JSON': json.dumps(cleanJSON(profcmd, timeObjects=CHROMEPROFILECOMMAND_TIME_OBJECTS),
ensure_ascii=False, sort_keys=True)})
csvPF = CSVPrintFile(['name']) if Act.csvFormat() else None
FJQC = FormatJSONQuoteChar(csvPF)
cm, parameters = _initChromeProfileNameParameters()
@@ -25815,32 +25835,50 @@ def doPrintShowChromeProfileCommands():
else:
FJQC.GetFormatJSONQuoteChar(myarg, True)
_getChromeProfileNameEntityForCommand(cm, parameters)
count = len(parameters['profileNameList'])
i = 0
for profileName in parameters['profileNameList']:
i +=1
printGettingEntityItemForWhom(Ent.CHROME_PROFILE_COMMAND, profileName, i, count)
pageMessage = getPageMessage()
try:
profcmds = callGAPIpages(cm.customers().profiles().commands(), 'list', 'chromeBrowserProfileCommands',
pageMessage=pageMessage,
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
parent=profileName, pageSize=100)
if not csvPF:
jcount = len(profcmds)
Ind.Increment()
j = 0
for profcmd in profcmds:
j += 1
_showChromeProfileCommand(profcmd, FJQC, j, jcount)
Ind.Decrement()
else:
for profcmd in profcmds:
_printProfileCommand(profcmd)
except (GAPI.notFound) as e:
entityActionFailedWarning([Ent.CHROME_PROFILE, profileName], str(e), i, count)
except (GAPI.invalidArgument, GAPI.permissionDenied) as e:
entityActionFailedExit([Ent.CHROME_PROFILE, profileName], str(e))
if parameters['profileNameList']:
count = len(parameters['profileNameList'])
i = 0
for profileName in parameters['profileNameList']:
i +=1
printGettingEntityItemForWhom(Ent.CHROME_PROFILE_COMMAND, profileName, i, count)
pageMessage = getPageMessage()
try:
profcmds = callGAPIpages(cm.customers().profiles().commands(), 'list', 'chromeBrowserProfileCommands',
pageMessage=pageMessage,
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
parent=profileName, pageSize=100)
if not csvPF:
jcount = len(profcmds)
Ind.Increment()
j = 0
for profcmd in profcmds:
j += 1
_showChromeProfileCommand(profcmd, FJQC, j, jcount)
Ind.Decrement()
else:
for profcmd in profcmds:
_printChromeProfileCommand(profcmd, csvPF, FJQC)
except GAPI.notFound as e:
entityActionFailedWarning([Ent.CHROME_PROFILE, profileName], str(e), i, count)
except (GAPI.invalidArgument, GAPI.permissionDenied) as e:
entityActionFailedExit([Ent.CHROME_PROFILE, profileName], str(e))
elif parameters['commandNameList']:
count = len(parameters['commandNameList'])
i = 0
for profileCommandName in parameters['commandNameList']:
i +=1
try:
profcmd = callGAPI(cm.customers().profiles().commands(), 'get',
throwReasons=[GAPI.INVALID_ARGUMENT, GAPI.NOT_FOUND, GAPI.PERMISSION_DENIED],
name=profileCommandName)
if not csvPF:
_showChromeProfileCommand(profcmd, FJQC, i, count)
else:
_printChromeProfileCommand(profcmd, csvPF, FJQC)
except GAPI.notFound as e:
entityActionFailedWarning([Ent.CHROME_PROFILE_COMMAND, profileCommandName], str(e), i, count)
except (GAPI.invalidArgument, GAPI.permissionDenied) as e:
entityActionFailedExit([Ent.CHROME_PROFILE, profileCommandName], str(e))
if csvPF:
csvPF.writeCSVfile('Chrome Profile Commands')

View File

@@ -859,6 +859,8 @@ class GamCLArgs():
OB_CHAT_THREAD = 'ChatThread'
OB_CHROMEPROFILE_NAME = 'ChromeProfileName'
OB_CHROMEPROFILE_NAME_LIST = 'ChromeProfileNameList'
OB_CHROMEPROFILE_COMMAND_NAME = 'ChromeProfileCommandName'
OB_CHROMEPROFILE_COMMAND_NAME_LIST = 'ChromeProfileNameCommandList'
OB_CHROME_VERSION = 'ChromeVersion'
OB_CIDR_NETMASK = 'CIDRnetmask'
OB_CIGROUP_ALIAS_LIST = "CIGroupAliasList"

View File

@@ -257,3 +257,39 @@ When using the `formatjson` option, double quotes are used extensively in the da
The `quotechar <Character>` option allows you to choose an alternate quote character, single quote for instance, that makes for readable/processable output.
`quotechar` defaults to `gam.cfg/csv_output_quote_char`. When uploading CSV files to Google, double quote `"` should be used.
### Examples
For Windows PowerShell, replace `\"` with ``` `" ```.
Clear cache and cookies for two specific Chrome profiles:
```
gam create chromeprofilecommand 4c6c0a9f-de78-4285-be86-713fca8cffff,aa03151c-7c1d-41fe-b793-5753e167ffff clearcache clearcookies
```
Display the status for those Chrome profiles:
```
gam show chromeprofilecommand 4c6c0a9f-de78-4285-be86-713fca8cffff,aa03151c-7c1d-41fe-b793-5753e167ffff
gam print chromeprofilecommand 4c6c0a9f-de78-4285-be86-713fca8cffff,aa03151c-7c1d-41fe-b793-5753e167ffff
```
Clear cache and cookies for Chrome profiles in a CSV file named `ChromeProfiles.csv` with a column `name`:
```
gam create chromeprofilecommand select csvfile ChromeProfiles.csv:name clearcache clearcookies
```
Display the status for those Chrome profiles:
```
gam show chromeprofilecommand select csvfile ChromeProfiles.csv:name
gam print chromeprofilecommand select csvfile ChromeProfiles.csv:name
```
Clear cache and cookies for Chrome profiles with last activity more that 60 days ago:
```
gam create chromeprofilecommand filter "lastActivityTime < \"#filtertime1#\"" filtertime1 -60d clearcache clearcookies
```
Display the status for those Chrome profiles:
```
gam show chromeprofilecommand filter "lastActivityTime < \"#filtertime1#\"" filtertime1 -60d
gam print chromeprofilecommand filter "lastActivityTime < \"#filtertime1#\"" filtertime1 -60d
```

View File

@@ -14,6 +14,12 @@ See [Downloads-Installs-GAM7](https://github.com/GAM-team/GAM/wiki/Downloads-Ins
Fixed bug in `gam create chromeprofilecommand` where `select|filter` were not recognized.
Updated `gam create datatransfer <OldOwnerID> datastudio <NewOwnerID>` that generated the following
error due to an unhandled API change.
```
ERROR: Invalid choice (google data studio): Expected <calendar|looker studio|drive and docs>
```
### 7.13.01
Enhanced `gam create|print|show chromeprofilecommand` to allow specification

View File

@@ -13,8 +13,7 @@
```
<DataTransferService> ::=
calendar|
currents|
datastudio|lookerstudio|"google data studio"|
datastudio|lookerstudio|"looker studio"|
drive|gdrive|googledrive|"drive and docs"
<DataTransferServiceList> ::= "<DataTransferService>(,<DataTransferService>)*"
@@ -38,7 +37,7 @@ gam create|add datatransfer|transfer <OldOwnerID> <DataTransferServiceList> <New
(<ParameterKey> <ParameterValue>)*
[wait <Integer> <Integer>]
```
For`datastudio` and `drive`, there are options to control the privacy level of the files to be transferred.
For`lookerstudio` and `drive`, there are options to control the privacy level of the files to be transferred.
* `private` or `privacy_level private` - Transfer files that are not shared with anyone
* `shared` or `privacy_level shared` - Transfer files shared with at least one other user; this is the **default**
* `all` or `privacy_level private,shared` - Transfer all files