Compare commits

...

28 Commits

Author SHA1 Message Date
Ross Scroggs
c9c0cac57e Google renamed an error: cannotModifyInheritedTeamDrivePermission became cannotModifyInheritedPermission
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
2025-06-24 15:39:55 -07:00
Ross Scroggs
8ca3717f97 Updated gam report <ActivityApplicationName>
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
Check for Google Root CA Updates / check-apis (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-06-22 12:32:52 -07:00
Ross Scroggs
cd0d82e994 Updated gam report <ActivityApplicationName> 2025-06-22 12:31:13 -07:00
Ross Scroggs
f29f27577c Update Users-Gmail-Send-As-Signature-Vacation.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
2025-06-22 06:41:43 -07:00
Ross Scroggs
cb5e5d1943 Update Users-Gmail-Send-As-Signature-Vacation.md 2025-06-22 06:34:31 -07:00
Ross Scroggs
88bdfd2883 _finalizeMessageSelectParameter
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
2025-06-21 06:32:12 -07:00
Ross Scroggs
e875acf428 Fixed labelids <LabelIdList> bug
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
2025-06-21 06:31:58 -07:00
Ross Scroggs
5d213e9951 Added option labelids <LabelIdList> to all commands that process messages
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-06-20 10:22:05 -07:00
Ross Scroggs
35d61da0a0 Added option labelids <LabelIdList> to all commands that process messages 2025-06-20 10:21:32 -07:00
Ross Scroggs
da04ead86d Updated gam <UserTypeEntity> print|show forms 2025-06-20 07:40:36 -07:00
Ross Scroggs
5526c987ea Updated gam <UserTypeEntity> print|show forms 2025-06-20 07:40:22 -07:00
Ross Scroggs
d9795b3f83 Update Users-Forms.md 2025-06-20 06:34:41 -07:00
Ross Scroggs
39a17bacb1 Added ispublished and isacceptingresponses to create|update form
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-06-19 09:00:41 -07:00
Ross Scroggs
af94ea6e54 Added ispublished and isacceptingresponses to create|update form 2025-06-19 09:00:09 -07:00
Ross Scroggs
c220f41cbe Implement the Chat Custom Emojis API #1787
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-06-18 08:08:38 -07:00
Ross Scroggs
8a32e53652 Implement the Chat Custom Emojis API #1787 2025-06-18 07:44:57 -07:00
Ross Scroggs
372f86a79a Implement the Chat Custom Emojis API #1787 2025-06-18 07:44:40 -07:00
Ross Scroggs
7f307254bf Implement the Chat Custom Emojis API #1787 2025-06-17 23:12:32 -07:00
Ross Scroggs
2ae7b4a4b5 Implement the Chat Custom Emojis API #1787
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-06-17 23:12:15 -07:00
Ross Scroggs
6dde273ee9 Update Users-Chat.md 2025-06-17 21:53:12 -07:00
Ross Scroggs
b66f6f60fe Update Licenses.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
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
Check for Google Root CA Updates / check-apis (push) Has been cancelled
2025-06-17 11:21:15 -07:00
Ross Scroggs
01fcefc647 Added webviewlink to <FileTreeFieldName>
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
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
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-06-16 11:27:17 -07:00
Ross Scroggs
a59e3008c5 Added webviewlink to <FileTreeFieldName> 2025-06-16 09:55:44 -07:00
Ross Scroggs
eb82da4ff2 Sort output by Shared Drive name 2025-06-16 09:33:39 -07:00
Ross Scroggs
c4aa399446 Sort output by Shared Drive name 2025-06-16 08:47:35 -07:00
Ross Scroggs
f1713ec685 Sort output by Shared Drive name 2025-06-16 08:47:14 -07:00
Ross Scroggs
74924c9c0e Update Chrome-Policies.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
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
Check for Google Root CA Updates / check-apis (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-06-13 11:55:03 -07:00
Ross Scroggs
8d3b65f5f1 Update chromeschema/chromepolicy commands
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
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
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-06-12 12:54:46 -07:00
20 changed files with 677 additions and 98 deletions

View File

@@ -1,4 +1,4 @@
This document describes the GAM command line syntax in modified BNF, see https://en.wikipedia.org/wiki/Backus-Naur_Form his document describes the GAM command line syntax in modified BNF, see https://en.wikipedia.org/wiki/Backus-Naur_Form
Skip the History section and start reading at Introduction. Skip the History section and start reading at Introduction.
Items on the command line are space separated, when an actual space character is required, it will be indicated by <Space>. Items on the command line are space separated, when an actual space character is required, it will be indicated by <Space>.
@@ -380,6 +380,8 @@ If an item contains spaces, it should be surrounded by ".
domain:<DomainName>|domain|default domain:<DomainName>|domain|default
<CalendarItem> ::= <EmailAddress> <CalendarItem> ::= <EmailAddress>
<ChannelCustomerID> ::= <String> <ChannelCustomerID> ::= <String>
<ChatEmojiName> ::= :<String>:
<ChatEmoji> ::= emojiname <ChatEmojiName> | customemojis/<String>
<ChatMember> ::= spaces/<String>/members/<String> <ChatMember> ::= spaces/<String>/members/<String>
<ChatMessage> ::= spaces/<String>/messages/<String> <ChatMessage> ::= spaces/<String>/messages/<String>
<ChatSpace> ::= spaces/<String> | space <String> | space spaces/<String> <ChatSpace> ::= spaces/<String> | space <String> | space spaces/<String>
@@ -664,6 +666,7 @@ If an item contains spaces, it should be surrounded by ".
(gdoc|ghtml <UserGoogleDoc>)| (gdoc|ghtml <UserGoogleDoc>)|
(gcsdoc|gcshtml <StorageBucketObjectName>) (gcsdoc|gcshtml <StorageBucketObjectName>)
<YouTubeChannelID> ::= <String> <YouTubeChannelID> ::= <String>
## Lists of basic items ## Lists of basic items
<APIScopeURLList> ::= "<APIScopeURL>(,<APIScopeURL>)*" <APIScopeURLList> ::= "<APIScopeURL>(,<APIScopeURL>)*"
@@ -4432,19 +4435,18 @@ gam report usage customer [todrive <ToDriveAttribute>*]
[convertmbtogb] [convertmbtogb]
<ActivityApplicationName> ::= <ActivityApplicationName> ::=
access|accesstransparency| accesstransparency|access|
admin| admin|
calendar|calendars| calendar|calendars|
chat| chat|
chrome| chrome|
classroom|
contextawareaccess| contextawareaccess|
currents|gplus|google+| gplus|currents|google+|
datastudio| datastudio|
devices|mobile|
domain|
drive|doc|docs| drive|doc|docs|
gcp| gcp|cloud|
gemini|geminiforworkspace| geminiinworkspaceapps|gemini|geminiforworkspace|
groups|group| groups|group|
groupsenterprise|enterprisegroups| groupsenterprise|enterprisegroups|
jamboard| jamboard|
@@ -4462,7 +4464,7 @@ gam report <ActivityApplicationName> [todrive <ToDriveAttribute>*]
[(user all|<UserItem>)|(orgunit|org|ou <OrgUnitPath> [showorgunit])|(select <UserTypeEntity>)] [(user all|<UserItem>)|(orgunit|org|ou <OrgUnitPath> [showorgunit])|(select <UserTypeEntity>)]
[([start <Time>] [end <Time>])|(range <Time> <Time>)| [([start <Time>] [end <Time>])|(range <Time> <Time>)|
yesterday|today|thismonth|(previousmonths <Integer>)] yesterday|today|thismonth|(previousmonths <Integer>)]
[filtertime.* <Time>] [filter|filters <String>] [filtertime.<String> <Time>] [filter|filters <String>]
[event|events <EventNameList>] [ip <String>] [event|events <EventNameList>] [ip <String>]
[groupidfilter <String>] [groupidfilter <String>]
[maxactivities <Number>] [maxevents <Number>] [maxresults <Number>] [maxactivities <Number>] [maxevents <Number>] [maxresults <Number>]
@@ -5031,18 +5033,18 @@ gam <UserTypeEntity> delete permissions <SharedDriveEntityAdmin> <DriveFilePermi
In these commands, the Google administrator named in oauth2.txt is used. In these commands, the Google administrator named in oauth2.txt is used.
gam copy teamdriveacls <SharedDriveEntity> to <SharedDriveEntity> gam copy shareddriveacls <SharedDriveEntity> to <SharedDriveEntity>
[adminaccess|asadmin] [adminaccess|asadmin]
[showpermissionsmessages [<Boolean>]] [showpermissionsmessages [<Boolean>]]
[excludepermissionsfromdomains|includepermissionsfromdomains <DomainNameList>] [excludepermissionsfromdomains|includepermissionsfromdomains <DomainNameList>]
(mappermissionsdomain <DomainName> <DomainName>)* (mappermissionsdomain <DomainName> <DomainName>)*
gam sync teamdriveacls <SharedDriveEntity> with <SharedDriveEntity> gam sync shareddriveacls <SharedDriveEntity> with <SharedDriveEntity>
[adminaccess|asadmin] [adminaccess|asadmin]
[showpermissionsmessages [<Boolean>]] [showpermissionsmessages [<Boolean>]]
[excludepermissionsfromdomains|includepermissionsfromdomains <DomainNameList>] [excludepermissionsfromdomains|includepermissionsfromdomains <DomainNameList>]
(mappermissionsdomain <DomainName> <DomainName>)* (mappermissionsdomain <DomainName> <DomainName>)*
gam print teamdriveacls [todrive <ToDriveAttribute>*] gam print shareddriveacls [todrive <ToDriveAttribute>*]
[teamdriveadminquery|query <QueryTeamDrive>] [teamdriveadminquery|query <QueryTeamDrive>]
[matchname <REMatchPattern>] [orgunit|org|ou <OrgUnitPath>] [matchname <REMatchPattern>] [orgunit|org|ou <OrgUnitPath>]
[user|group <EmailAddress> [checkgroups]] (role|roles <SharedDriveACLRoleList>)* [user|group <EmailAddress> [checkgroups]] (role|roles <SharedDriveACLRoleList>)*
@@ -5050,7 +5052,7 @@ gam print teamdriveacls [todrive <ToDriveAttribute>*]
[oneitemperrow] [<DrivePermissionsFieldName>*|(fields <DrivePermissionsFieldNameList>)] [oneitemperrow] [<DrivePermissionsFieldName>*|(fields <DrivePermissionsFieldNameList>)]
(addcsvdata <FieldName> <String>)* (addcsvdata <FieldName> <String>)*
[formatjson [quotechar <Character>]] [formatjson [quotechar <Character>]]
gam show teamdriveacls gam show shareddriveacls
[teamdriveadminquery|query <QueryTeamDrive>] [teamdriveadminquery|query <QueryTeamDrive>]
[matchname <REMatchPattern>] [orgunit|org|ou <OrgUnitPath>] [matchname <REMatchPattern>] [orgunit|org|ou <OrgUnitPath>]
[user|group <EmailAddress> [checkgroups]] (role|roles <SharedDriveACLRoleList>)* [user|group <EmailAddress> [checkgroups]] (role|roles <SharedDriveACLRoleList>)*
@@ -5060,18 +5062,18 @@ gam show teamdriveacls
In these commands, you specify an administrator and then indicate that you want domain administrator access with the adminaccess option. In these commands, you specify an administrator and then indicate that you want domain administrator access with the adminaccess option.
gam <UserTypeEntity> copy teamdriveacls <SharedDriveEntity> to <SharedDriveEntity> gam <UserTypeEntity> copy shareddriveacls <SharedDriveEntity> to <SharedDriveEntity>
[adminaccess|asadmin] [adminaccess|asadmin]
[showpermissionsmessages [<Boolean>]] [showpermissionsmessages [<Boolean>]]
[excludepermissionsfromdomains|includepermissionsfromdomains <DomainNameList>] [excludepermissionsfromdomains|includepermissionsfromdomains <DomainNameList>]
(mappermissionsdomain <DomainName> <DomainName>)* (mappermissionsdomain <DomainName> <DomainName>)*
gam <UserTypeEntity> sync teamdriveacls <SharedDriveEntity> with <SharedDriveEntity> gam <UserTypeEntity> sync shareddriveacls <SharedDriveEntity> with <SharedDriveEntity>
[adminaccess|asadmin] [adminaccess|asadmin]
[showpermissionsmessages [<Boolean>]] [showpermissionsmessages [<Boolean>]]
[excludepermissionsfromdomains|includepermissionsfromdomains <DomainNameList>] [excludepermissionsfromdomains|includepermissionsfromdomains <DomainNameList>]
(mappermissionsdomain <DomainName> <DomainName>)* (mappermissionsdomain <DomainName> <DomainName>)*
gam <UserTypeEntity> print teamdriveacls [todrive <ToDriveAttribute>*] gam <UserTypeEntity> print shareddriveacls [todrive <ToDriveAttribute>*]
[adminaccess|asadmin] [teamdriveadminquery|query <QueryTeamDrive>] [adminaccess|asadmin] [teamdriveadminquery|query <QueryTeamDrive>]
[matchname <REMatchPattern>] [orgunit|org|ou <OrgUnitPath>] [matchname <REMatchPattern>] [orgunit|org|ou <OrgUnitPath>]
[user|group <EmailAddress> [checkgroups]] (role|roles <SharedDriveACLRoleList>)* [user|group <EmailAddress> [checkgroups]] (role|roles <SharedDriveACLRoleList>)*
@@ -5080,7 +5082,7 @@ gam <UserTypeEntity> print teamdriveacls [todrive <ToDriveAttribute>*]
[shownopermissionsdrives false|true|only] [shownopermissionsdrives false|true|only]
(addcsvdata <FieldName> <String>)* (addcsvdata <FieldName> <String>)*
[formatjson [quotechar <Character>]] [formatjson [quotechar <Character>]]
gam <UserTypeEntity> show teamdriveacls gam <UserTypeEntity> show shareddriveacls
[adminaccess|asadmin] [teamdriveadminquery|query <QueryTeamDrive>] [adminaccess|asadmin] [teamdriveadminquery|query <QueryTeamDrive>]
[matchname <REMatchPattern>] [orgunit|org|ou <OrgUnitPath>] [matchname <REMatchPattern>] [orgunit|org|ou <OrgUnitPath>]
[user|group <EmailAddress> [checkgroups]] (role|roles <SharedDriveACLRoleList>)* [user|group <EmailAddress> [checkgroups]] (role|roles <SharedDriveACLRoleList>)*
@@ -6436,6 +6438,22 @@ gam <UserTypeEntity> print chatevents [todrive <ToDriveAttribute>*]
filter <String> filter <String>
[formatjson [quotechar <Character>]] [formatjson [quotechar <Character>]]
<ChatEmojiName> ::= :[0-9a-z_-]+:
<ChatEmoji> ::= emojiname <ChatEmojiName> | customemojis/<String>
gam <UserTypeEntity> create chatemoji <ChatEmojiName>
([drivedir|(sourcefolder <FilePath>)] [filename <FileNamePattern>])
[formatjson]
gam <UserTypeEntity> delete chatemoji <ChatEmoji>
gam <UserTypeEntity> info chatemoji <ChatEmoji>
[formatjson]
gam <UserTypeEntity> show chatemojis
[showcreatedby any|me|others]
[formatjson]
gam <UserTypeEntity> print chatemojis [todrive <ToDriveAttribute>*]
[showcreatedby any|me|others]
[formatjson [quotechar <Character>]]
# Users - Drive # Users - Drive
<DriveFileOrderByFieldName> ::= <DriveFileOrderByFieldName> ::=
@@ -7204,7 +7222,8 @@ gam <UserTypeEntity> show filesharecounts
owners| owners|
parents| parents|
size| size|
trashed trashed|
webviewlink
<FileTreeFieldNameList> ::= "<FileTreeFieldName>(,<FileTreeFieldName>)*" <FileTreeFieldNameList> ::= "<FileTreeFieldName>(,<FileTreeFieldName>)*"
gam <UserTypeEntity> print filetree [todrive <ToDriveAttribute>*] gam <UserTypeEntity> print filetree [todrive <ToDriveAttribute>*]
@@ -7397,10 +7416,12 @@ gam <UserTypeEntity> print filters [labelidsonly] [todrive <ToDriveAttribute>*]
gam <UserTypeEntity> create form gam <UserTypeEntity> create form
title <String> [description <String>] [isquiz [<Boolean>]] [<JSONData>] title <String> [description <String>] [isquiz [<Boolean>]] [<JSONData>]
[ispublished [<Boolean>] isacceptingresponses [<Boolean>]]
[drivefilename <DriveFileName>] [<DriveFileParentAttribute>] [drivefilename <DriveFileName>] [<DriveFileParentAttribute>]
[(csv [todrive <ToDriveAttribute>*]) | returnidonly] [(csv [todrive <ToDriveAttribute>*]) | returnidonly]
gam <UserTypeEntity> update form <DriveFileEntity> gam <UserTypeEntity> update form <DriveFileEntity>
[title <String>] [description <String>] [isquiz [<Boolean>]] [<JSONData>] [title <String>] [description <String>] [isquiz [<Boolean>]] [<JSONData>]
[ispublished [<Boolean>] isacceptingresponses [<Boolean>]]
gam <UserTypeEntity> print forms <DriveFileEntity> [todrive <ToDriveAttribute>*] gam <UserTypeEntity> print forms <DriveFileEntity> [todrive <ToDriveAttribute>*]
(addcsvdata <FieldName> <String>)* (addcsvdata <FieldName> <String>)*
@@ -7592,48 +7613,61 @@ gam <UserTypeEntity> insert message
gam <UserTypeEntity> archive messages <GroupItem> gam <UserTypeEntity> archive messages <GroupItem>
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
[labelids <LabelIDList>]
[quick|notquick] [doit] [max_to_archive <Number>])|(ids <MessageIDEntity>) [quick|notquick] [doit] [max_to_archive <Number>])|(ids <MessageIDEntity>)
[csv [todrive <ToDriveAttribute>*]] [csv [todrive <ToDriveAttribute>*]]
gam <UserTypeEntity> delete messages|threads gam <UserTypeEntity> delete messages|threads
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
[labelids <LabelIDList>]
[quick|notquick] [doit] [max_to_delete <Number>])|(ids <MessageIDEntity>) [quick|notquick] [doit] [max_to_delete <Number>])|(ids <MessageIDEntity>)
[csv [todrive <ToDriveAttribute>*]] [csv [todrive <ToDriveAttribute>*]]
gam <UserTypeEntity> modify messages|threads gam <UserTypeEntity> modify messages|threads
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
[labelids <LabelIDList>]
[quick|notquick] [doit] [max_to_modify <Number>])|(ids <MessageIDEntity>) [quick|notquick] [doit] [max_to_modify <Number>])|(ids <MessageIDEntity>)
((addlabel <LabelName>)|(removelabel <LabelName>))+ ((addlabel <LabelName>)|(removelabel <LabelName>))+
[csv [todrive <ToDriveAttribute>*]] [csv [todrive <ToDriveAttribute>*]]
gam <UserTypeEntity> spam messages|threads gam <UserTypeEntity> spam messages|threads
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
[labelids <LabelIDList>]
[quick|notquick] [doit] [max_to_spam <Number>])|(ids <MessageIDEntity>) [quick|notquick] [doit] [max_to_spam <Number>])|(ids <MessageIDEntity>)
[csv [todrive <ToDriveAttribute>*]] [csv [todrive <ToDriveAttribute>*]]
gam <UserTypeEntity> trash messages|threads gam <UserTypeEntity> trash messages|threads
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
[labelids <LabelIDList>]
[quick|notquick] [doit] [max_to_trash <Number>])|(ids <MessageIDEntity>) [quick|notquick] [doit] [max_to_trash <Number>])|(ids <MessageIDEntity>)
[csv [todrive <ToDriveAttribute>*]] [csv [todrive <ToDriveAttribute>*]]
gam <UserTypeEntity> untrash messages|threads gam <UserTypeEntity> untrash messages|threads
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
[labelids <LabelIDList>]
[quick|notquick] [doit] [max_to_untrash <Number>])|(ids <MessageIDEntity>) [quick|notquick] [doit] [max_to_untrash <Number>])|(ids <MessageIDEntity>)
[csv [todrive <ToDriveAttribute>*]] [csv [todrive <ToDriveAttribute>*]]
gam <UserTypeEntity> export message|messages gam <UserTypeEntity> export message|messages
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_export <Number>])|(ids <MessageIDEntity>) (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
[labelids <LabelIDList>]
[quick|notquick] [doit] [max_to_export <Number>])|(ids <MessageIDEntity>)
[targetfolder <FilePath>] [targetname <FileName>] [overwrite [<Boolean>]] [targetfolder <FilePath>] [targetname <FileName>] [overwrite [<Boolean>]]
gam <UserTypeEntity> export thread|threads gam <UserTypeEntity> export thread|threads
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [doit] [max_to_export <Number>])|(ids <ThreadIDEntity>) (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
[labelids <LabelIDList>]
[quick|notquick] [doit] [max_to_export <Number>])|(ids <ThreadIDEntity>)
[targetfolder <FilePath>] [targetname <FileName>] [overwrite [<Boolean>]] [targetfolder <FilePath>] [targetname <FileName>] [overwrite [<Boolean>]]
gam <UserTypeEntity> forward message|messages recipient|to <RecipientEntity> gam <UserTypeEntity> forward message|messages recipient|to <RecipientEntity>
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
[labelids <LabelIDList>]
[quick|notquick] [doit] [max_to_forward <Number>])|(ids <MessageIDEntity>) [quick|notquick] [doit] [max_to_forward <Number>])|(ids <MessageIDEntity>)
[subject <String>] [addorigfieldstosubject [<Boolean>]] [altcharset <String>] [subject <String>] [addorigfieldstosubject [<Boolean>]] [altcharset <String>]
gam <UserTypeEntity> forward thread|thtreads recipient|to <RecipientEntity> gam <UserTypeEntity> forward thread|thtreads recipient|to <RecipientEntity>
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
[labelids <LabelIDList>]
quick|notquick] [doit] [max_to_forward <Number>])|(ids <ThreadIDEntity>) quick|notquick] [doit] [max_to_forward <Number>])|(ids <ThreadIDEntity>)
[subject <String>] [addorigfieldstosubject [<Boolean>]] [altcharset <String>] [subject <String>] [addorigfieldstosubject [<Boolean>]] [altcharset <String>]
gam <UserTypeEntity> show messages|threads gam <UserTypeEntity> show messages|threads
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])* (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])*
[labelids <LabelIDList>]
[quick|notquick] [max_to_show <Number>] [includespamtrash])|(ids <MessageIDEntity>) [quick|notquick] [max_to_show <Number>] [includespamtrash])|(ids <MessageIDEntity>)
[labelmatchpattern <REMatchPattern>] [sendermatchpattern <REMatchPattern>] [labelmatchpattern <REMatchPattern>] [sendermatchpattern <REMatchPattern>]
[countsonly|positivecountsonly] [useronly] [countsonly|positivecountsonly] [useronly]
@@ -7646,6 +7680,7 @@ gam <UserTypeEntity> show messages|threads
[uploadattachments [<DriveFileParentAttribute>]]] [uploadattachments [<DriveFileParentAttribute>]]]
gam <UserTypeEntity> print messages|threads [todrive <ToDriveAttribute>*] gam <UserTypeEntity> print messages|threads [todrive <ToDriveAttribute>*]
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])* (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])*
[labelids <LabelIDList>]
[quick|notquick] [max_to_print <Number>] [includespamtrash])|(ids <MessageIDEntity>) [quick|notquick] [max_to_print <Number>] [includespamtrash])|(ids <MessageIDEntity>)
[labelmatchpattern <REMatchPattern>] [sendermatchpattern <REMatchPattern>] [labelmatchpattern <REMatchPattern>] [sendermatchpattern <REMatchPattern>]
[countsonly|positivecountsonly] [useronly] [countsonly|positivecountsonly] [useronly]

View File

@@ -1,3 +1,54 @@
7.10.05
Google renamed an error: cannotModifyInheritedTeamDrivePermission became cannotModifyInheritedPermission.
GAM will now handle the new error.
7.10.04
Updated `gam report <ActivityApplicationName>` to accept accept application names as defined
in the Reports API discovery document; this means that GAM does not have to be updated when
Google defines a new application name.
`gemini_in_workspace_apps` is now available in `gam report`.
7.10.03
Fixed bug in commands that modify messages where the `labelids <LabelIdList>` option
was not being applied.
7.10.02
Added option `labelids <LabelIdList>` to all commands that process messages;
this option causes GAM to only return messages with labels that match all of the specified label IDs.
Updated `gam <UserTypeEntity> print|show forms` to always display `isPublished` and
`isAcceptingResponses` in `publishSettings/publishState` regardless of their value;
the API doesn't return these values when they are False.
7.10.01
Added options `ispublished [<Boolean>]` and `isacceptingresponses [<Boolean>]` to
`gam <UserTypeEntity> create|update form`.
7.10.00
Added commands to manage/display Chat Custom Emojis.
* See: https://github.com/GAM-team/GAM/wiki/Users-Chat#manage-chat-emojis
* See: https://github.com/GAM-team/GAM/wiki/Users-Chat#display-chat-emojis
Updated `gam <UserItem> print|show chatspaces|chatmembers asadmin` to display
the spaces in ascending display name order.
7.09.07
Added `webviewlink` to `<FileTreeFieldName>` for use in `gam <UserTypeEntity> print|show filetree`.
7.09.06
Upddated `gam print|show shareddrives`, `gam print|show shareddriveacls`, `gam print shareddriveorganizers`
to display the Shared Drives in ascending name order; the API returns them in an unidentifiable order.
7.09.05 7.09.05
Improved output of `gam info|show chromeschemas [std]` to more accurately display the schemas. Improved output of `gam info|show chromeschemas [std]` to more accurately display the schemas.

View File

@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
""" """
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>' __author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
__version__ = '7.09.05' __version__ = '7.10.05'
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)' __license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
#pylint: disable=wrong-import-position #pylint: disable=wrong-import-position
@@ -13548,49 +13548,55 @@ def doReportUsage():
NL_SPACES_PATTERN = re.compile(r'\n +') NL_SPACES_PATTERN = re.compile(r'\n +')
DISABLED_REASON_TIME_PATTERN = re.compile(r'.*(\d{4}/\d{2}/\d{2}-\d{2}:\d{2}:\d{2})') DISABLED_REASON_TIME_PATTERN = re.compile(r'.*(\d{4}/\d{2}/\d{2}-\d{2}:\d{2}:\d{2})')
REPORT_ALIASES_CHOICE_MAP = {
'access': 'accesstransparency',
'calendars': 'calendar',
'cloud': 'gcp',
'currents': 'gplus',
'customers': 'customer',
'domain': 'customer',
'devices': 'mobile',
'doc': 'drive',
'docs': 'drive',
'enterprisegroups': 'groupsenterprise',
'gemini': 'geminiinworkspaceapps',
'geminiforworkspace': 'geminiinworkspaceapps',
'group': 'groups',
'google+': 'gplus',
'hangoutsmeet': 'meet',
'logins': 'login',
'lookerstudio': 'datastudio',
'oauthtoken': 'token',
'tokens': 'token',
'users': 'user',
}
REPORT_CHOICE_MAP = { REPORT_CHOICE_MAP = {
'access': 'access_transparency',
'accesstransparency': 'access_transparency', 'accesstransparency': 'access_transparency',
'admin': 'admin', 'admin': 'admin',
'calendar': 'calendar', 'calendar': 'calendar',
'calendars': 'calendar',
'chat': 'chat', 'chat': 'chat',
'chrome': 'chrome', 'chrome': 'chrome',
'contextawareaccess': 'context_aware_access', 'contextawareaccess': 'context_aware_access',
'customer': 'customer', 'customer': 'customer',
'customers': 'customer',
'datastudio': 'data_studio', 'datastudio': 'data_studio',
'devices': 'mobile',
'doc': 'drive',
'docs': 'drive',
'domain': 'customer',
'drive': 'drive', 'drive': 'drive',
'enterprisegroups': 'groups_enterprise',
'gcp': 'gcp', 'gcp': 'gcp',
'gemini': 'gemini_for_workspace', 'geminiinworkspaceapps': 'gemini_in_workspace_apps',
'geminiforworkspace': 'gemini_for_workspace',
'gplus': 'gplus', 'gplus': 'gplus',
'google+': 'gplus',
'group': 'groups',
'groups': 'groups', 'groups': 'groups',
'groupsenterprise': 'groups_enterprise', 'groupsenterprise': 'groups_enterprise',
'hangoutsmeet': 'meet',
'jamboard': 'jamboard', 'jamboard': 'jamboard',
'keep': 'keep', 'keep': 'keep',
'login': 'login', 'login': 'login',
'logins': 'login',
'lookerstudio': 'data_studio',
'meet': 'meet', 'meet': 'meet',
'mobile': 'mobile', 'mobile': 'mobile',
'oauthtoken': 'token',
'rules': 'rules', 'rules': 'rules',
'saml': 'saml', 'saml': 'saml',
'token': 'token', 'token': 'token',
'tokens': 'token',
'usage': 'usage', 'usage': 'usage',
'usageparameters': 'usageparameters', 'usageparameters': 'usageparameters',
'user': 'user', 'user': 'user',
'users': 'user',
'useraccounts': 'user_accounts', 'useraccounts': 'user_accounts',
'vault': 'vault', 'vault': 'vault',
} }
@@ -13880,7 +13886,7 @@ def doReport():
if dyn_choice.replace('_', '') not in REPORT_CHOICE_MAP and \ if dyn_choice.replace('_', '') not in REPORT_CHOICE_MAP and \
dyn_choice not in REPORT_CHOICE_MAP.values(): dyn_choice not in REPORT_CHOICE_MAP.values():
REPORT_CHOICE_MAP[dyn_choice.replace('_', '')] = dyn_choice REPORT_CHOICE_MAP[dyn_choice.replace('_', '')] = dyn_choice
report = getChoice(REPORT_CHOICE_MAP, mapChoice=True) report = getChoice(REPORT_CHOICE_MAP, choiceAliases=REPORT_ALIASES_CHOICE_MAP, mapChoice=True)
if report == 'usage': if report == 'usage':
doReportUsage() doReportUsage()
return return
@@ -22786,7 +22792,7 @@ def _processPeopleContactPhotos(users, function):
if function == 'GetContactPhoto' and not os.path.isdir(targetFolder): if function == 'GetContactPhoto' and not os.path.isdir(targetFolder):
os.makedirs(targetFolder) os.makedirs(targetFolder)
elif myarg == 'filename': elif myarg == 'filename':
filenamePattern = getString(Cmd.OB_PHOTO_FILENAME_PATTERN) filenamePattern = getString(Cmd.OB_FILE_NAME_PATTERN)
else: else:
unknownArgumentExit() unknownArgumentExit()
subForContactId = filenamePattern.find('#contactid#') != -1 subForContactId = filenamePattern.find('#contactid#') != -1
@@ -25990,6 +25996,8 @@ def _printChatItem(user, citem, parent, entityType, csvPF, FJQC, addCSVData=None
if entityType == Ent.CHAT_SPACE: if entityType == Ent.CHAT_SPACE:
_cleanChatSpace(citem) _cleanChatSpace(citem)
baserow = {'User': user} if user is not None else {} baserow = {'User': user} if user is not None else {}
elif entityType == Ent.CHAT_EMOJI:
baserow = {'User': user, 'name': citem['name'], 'emojiName': citem['emojiName']}
else: else:
if user is not None: if user is not None:
baserow = {'User': user, 'space.name': parent['name'], 'space.displayName': parent['displayName']} baserow = {'User': user, 'space.name': parent['name'], 'space.displayName': parent['displayName']}
@@ -26009,6 +26017,190 @@ def _printChatItem(user, citem, parent, entityType, csvPF, FJQC, addCSVData=None
'JSON': json.dumps(cleanJSON(citem, timeObjects=CHAT_TIME_OBJECTS), ensure_ascii=False, sort_keys=True)}) 'JSON': json.dumps(cleanJSON(citem, timeObjects=CHAT_TIME_OBJECTS), ensure_ascii=False, sort_keys=True)})
csvPF.WriteRowNoFilter(row) csvPF.WriteRowNoFilter(row)
def _getValidateEmojiName():
name = getString(Cmd.OB_CHAT_EMOJI_NAME)
if re.match(r'^:[0-9a-z_-]+:$', name):
return name
Cmd.Backup()
usageErrorExit(Msg.INVALID_EMOJI_NAME.format(name))
# gam <UserTypeEntity> create chatemoji <ChatEmojiName>
# ([drivedir|(sourcefolder <FilePath>)] [filename <FileNamePattern>])
# [formatjson]
def createChatEmoji(users):
FJQC = FormatJSONQuoteChar()
name = _getValidateEmojiName()
body = {'emojiName': name, 'payload': {'filename': '', 'fileContent': ''}}
sourceFolder = os.getcwd()
filenamePattern = '#email#.jpg'
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if myarg == 'drivedir':
sourceFolder = GC.Values[GC.DRIVE_DIR]
elif myarg == 'sourcefolder':
sourceFolder = os.path.expanduser(getString(Cmd.OB_FILE_PATH))
if not os.path.isdir(sourceFolder):
entityDoesNotExistExit(Ent.DIRECTORY, sourceFolder)
elif myarg == 'filename':
filenamePattern = getString(Cmd.OB_FILE_NAME_PATTERN)
else:
FJQC.GetFormatJSON(myarg)
i, count, users = getEntityArgument(users)
for user in users:
i += 1
user, chat, kvList = buildChatServiceObject(API.CHAT_CUSTOM_EMOJIS, user, i, count, [Ent.CHAT_EMOJI, name])
if not chat:
continue
user, userName, _ = splitEmailAddressOrUID(user)
filename = _substituteForUser(filenamePattern, user, userName)
if sourceFolder is not None:
filename = os.path.join(sourceFolder, filename)
filename = os.path.expanduser(filename)
try:
with open(filename, 'rb') as f:
image_data = f.read()
except (OSError, IOError) as e:
entityActionFailedWarning([Ent.USER, user, Ent.CHAT_EMOJI, filename], str(e), i, count)
continue
body['payload'] = {'filename': os.path.basename(filename),
'fileContent':base64.urlsafe_b64encode(image_data).decode(UTF8)}
try:
emoji = callGAPI(chat.customEmojis(), 'create',
throwReasons=[GAPI.ALREADY_EXISTS, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
body=body)
_showChatItem(emoji, Ent.CHAT_EMOJI, FJQC, i, count)
except (GAPI.alreadyExists, GAPI.invalidArgument, GAPI.permissionDenied) as e:
exitIfChatNotConfigured(chat, kvList, str(e), i, count)
except GAPI.failedPrecondition:
userChatServiceNotEnabledWarning(user, i, count)
def getEmojiName(myarg):
if myarg == 'emojiname':
name = _getValidateEmojiName()
return 'customEmojis/'+name
_, chatEmoji = Cmd.Previous().split('/', 1)
return 'customEmojis/'+chatEmoji
# gam <UserTypeEntity> delete chatemoji <ChatEmoji>
def deleteChatEmoji(users):
name = None
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if myarg == 'emojiname':
name = getEmojiName(myarg)
elif myarg.startswith('customemojis/'):
name = getEmojiName(myarg)
else:
unknownArgumentExit()
if not name:
missingArgumentExit('ChatEmoji')
i, count, users = getEntityArgument(users)
for user in users:
i += 1
user, chat, kvList = buildChatServiceObject(API.CHAT_CUSTOM_EMOJIS, user, i, count, [Ent.CHAT_EMOJI, name])
if not chat:
continue
try:
callGAPI(chat.customEmojis(), 'delete',
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
name=name)
entityActionPerformed(kvList, i, count)
except (GAPI.notFound, GAPI.invalidArgument, GAPI.permissionDenied) as e:
exitIfChatNotConfigured(chat, kvList, str(e), i, count)
except GAPI.failedPrecondition:
userChatServiceNotEnabledWarning(user, i, count)
# gam <UserTypeEntity> info chatemoji <ChatEmoji>
# [formatjson]
def infoChatEmoji(users):
FJQC = FormatJSONQuoteChar()
name = None
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if myarg == 'emojiname':
name = getEmojiName(myarg)
elif myarg.startswith('customemojis/'):
name = getEmojiName(myarg)
else:
FJQC.GetFormatJSON(myarg)
if not name:
missingArgumentExit('ChatEmoji')
i, count, users = getEntityArgument(users)
for user in users:
i += 1
user, chat, kvList = buildChatServiceObject(API.CHAT_CUSTOM_EMOJIS, user, i, count, [Ent.CHAT_EMOJI, name])
if not chat:
continue
try:
emoji = callGAPI(chat.customEmojis(), 'get',
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
name=name)
if not FJQC.formatJSON:
entityPerformAction(kvList, i, count)
_showChatItem(emoji, Ent.CHAT_EMOJI, FJQC, i, count)
except (GAPI.notFound, GAPI.invalidArgument, GAPI.permissionDenied) as e:
exitIfChatNotConfigured(chat, kvList, str(e), i, count)
except GAPI.failedPrecondition:
userChatServiceNotEnabledWarning(user, i, count)
CHAT_EMOJI_SHOW_CREATED_BY_CHOICE_MAP = {
'any': None,
'me': 'creator("users/me")',
'others': 'NOT creator("users/me")'
}
# gam <UserTypeEntity> show chatemojis
# [showcreatedby any|me|others]
# [formatjson]
# gam <UserTypeEntity> print chatemojis [todrive <ToDriveAttribute>*]
# [showcreatedby any|me|others]
# [formatjson [quotechar <Character>]]
def printShowChatEmojis(users):
csvPF = CSVPrintFile(['User', 'name', 'emojiName']) if Act.csvFormat() else None
FJQC = FormatJSONQuoteChar(csvPF)
pfilter = CHAT_EMOJI_SHOW_CREATED_BY_CHOICE_MAP['me']
while Cmd.ArgumentsRemaining():
myarg = getArgument()
if csvPF and myarg == 'todrive':
csvPF.GetTodriveParameters()
elif myarg =='showcreatedby':
pfilter = getChoice(CHAT_EMOJI_SHOW_CREATED_BY_CHOICE_MAP, mapChoice=True)
else:
FJQC.GetFormatJSONQuoteChar(myarg, True)
i, count, users = getEntityArgument(users)
for user in users:
i += 1
user, chat, kvList = buildChatServiceObject(API.CHAT_CUSTOM_EMOJIS, user, i, count, [Ent.CHAT_EMOJI, None])
if not chat:
continue
try:
emojis = callGAPIpages(chat.customEmojis(), 'list', 'customEmojis',
pageMessage=_getChatPageMessage(Ent.CHAT_EMOJI, user, i, count, pfilter),
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
pageSize=CHAT_PAGE_SIZE, filter=pfilter)
except (GAPI.notFound, GAPI.invalidArgument, GAPI.permissionDenied) as e:
exitIfChatNotConfigured(chat, kvList, str(e), i, count)
continue
except GAPI.failedPrecondition:
userChatServiceNotEnabledWarning(user, i, count)
break
if not csvPF:
jcount = len(emojis)
if not FJQC.formatJSON:
entityPerformActionNumItems(kvList, jcount, Ent.CHAT_EMOJI, i, count)
Ind.Increment()
j = 0
for emoji in sorted(emojis, key=lambda k: k['emojiName']):
j += 1
_showChatItem(emoji, Ent.CHAT_EMOJI, FJQC, j, jcount)
Ind.Decrement()
else:
for emoji in sorted(emojis, key=lambda k: k['emojiName']):
_printChatItem(user, emoji, '', Ent.CHAT_EMOJI, csvPF, FJQC)
if csvPF:
csvPF.writeCSVfile('Chat Custom Emojis')
# gam setup chat # gam setup chat
def doSetupChat(): def doSetupChat():
checkForExtraneousArguments() checkForExtraneousArguments()
@@ -26472,6 +26664,9 @@ def printShowChatSpaces(users):
substituteQueryTimes(queries, queryTimes) substituteQueryTimes(queries, queryTimes)
pfilter = kwargsCS['query'] = queries[0] pfilter = kwargsCS['query'] = queries[0]
kwargsCS['useAdminAccess'] = True kwargsCS['useAdminAccess'] = True
sortName = 'displayName'
else:
sortName = 'name'
for user in users: for user in users:
i += 1 i += 1
user, chat, kvList = buildChatServiceObject(api, user, i, count, None, useAdminAccess) user, chat, kvList = buildChatServiceObject(api, user, i, count, None, useAdminAccess)
@@ -26499,12 +26694,12 @@ def printShowChatSpaces(users):
entityPerformActionNumItems(kvList, jcount, Ent.CHAT_SPACE, i, count) entityPerformActionNumItems(kvList, jcount, Ent.CHAT_SPACE, i, count)
Ind.Increment() Ind.Increment()
j = 0 j = 0
for space in spaces: for space in sorted(spaces, key=lambda k: k[sortName]):
j += 1 j += 1
_showChatItem(space, Ent.CHAT_SPACE, FJQC, j, jcount) _showChatItem(space, Ent.CHAT_SPACE, FJQC, j, jcount)
Ind.Decrement() Ind.Decrement()
else: else:
for space in spaces: for space in sorted(spaces, key=lambda k: k[sortName]):
_printChatItem(user, space, None, Ent.CHAT_SPACE, csvPF, FJQC) _printChatItem(user, space, None, Ent.CHAT_SPACE, csvPF, FJQC)
if csvPF: if csvPF:
csvPF.writeCSVfile('Chat Spaces') csvPF.writeCSVfile('Chat Spaces')
@@ -27139,6 +27334,9 @@ def printShowChatMembers(users):
i, count, users = getEntityArgument(users) i, count, users = getEntityArgument(users)
if useAdminAccess: if useAdminAccess:
_chkChatAdminAccess(count) _chkChatAdminAccess(count)
sortName = 'displayName'
else:
sortName = 'name'
for user in users: for user in users:
i += 1 i += 1
user, chat, kvList = buildChatServiceObject(api, user, i, count, [Ent.CHAT_SPACE, None], useAdminAccess) user, chat, kvList = buildChatServiceObject(api, user, i, count, [Ent.CHAT_SPACE, None], useAdminAccess)
@@ -27161,7 +27359,7 @@ def printShowChatMembers(users):
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS, retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
fields="nextPageToken,spaces(name,displayName,spaceType,membershipCount)", pageSize=CHAT_PAGE_SIZE, fields="nextPageToken,spaces(name,displayName,spaceType,membershipCount)", pageSize=CHAT_PAGE_SIZE,
**kwargsCS) **kwargsCS)
for space in spaces: for space in sorted(spaces, key=lambda k: k[sortName]):
if space['spaceType'] == 'SPACE' and 'membershipCount' in space: if space['spaceType'] == 'SPACE' and 'membershipCount' in space:
parentList.append({'name': space['name'], 'displayName': space.get('displayName', 'None')}) parentList.append({'name': space['name'], 'displayName': space.get('displayName', 'None')})
except (GAPI.notFound, GAPI.invalidArgument, GAPI.internalError, except (GAPI.notFound, GAPI.invalidArgument, GAPI.internalError,
@@ -27178,7 +27376,7 @@ def printShowChatMembers(users):
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS, retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
fields="nextPageToken,spaces(name,displayName,spaceType,membershipCount)", pageSize=CHAT_PAGE_SIZE, fields="nextPageToken,spaces(name,displayName,spaceType,membershipCount)", pageSize=CHAT_PAGE_SIZE,
**kwargsCS) **kwargsCS)
for space in spaces: for space in sorted(spaces, key=lambda k: k[sortName]):
# if 'membershipCount' in space: # if 'membershipCount' in space:
# parentList.append({'name': space['name'], 'displayName': space.get('displayName', 'None')}) # parentList.append({'name': space['name'], 'displayName': space.get('displayName', 'None')})
parentList.append({'name': space['name'], 'displayName': space.get('displayName', 'None')}) parentList.append({'name': space['name'], 'displayName': space.get('displayName', 'None')})
@@ -57618,9 +57816,10 @@ FILETREE_FIELDS_CHOICE_MAP = {
'parents': 'parents', 'parents': 'parents',
'size': 'size', 'size': 'size',
'trashed': 'trashed', 'trashed': 'trashed',
'webviewlink': 'webViewLink',
} }
FILETREE_FIELDS_PRINT_ORDER = ['id', 'parents', 'owners', 'mimeType', 'size', 'explicitlyTrashed', 'trashed'] FILETREE_FIELDS_PRINT_ORDER = ['id', 'parents', 'owners', 'mimeType', 'size', 'explicitlyTrashed', 'trashed', 'webViewLink']
# gam <UserTypeEntity> print filetree [todrive <ToDriveAttribute>*] # gam <UserTypeEntity> print filetree [todrive <ToDriveAttribute>*]
# [select <DriveFileEntity> [selectsubquery <QueryDriveFile>] [depth <Number>]] # [select <DriveFileEntity> [selectsubquery <QueryDriveFile>] [depth <Number>]]
@@ -57785,7 +57984,7 @@ def printShowFileTree(users):
else: else:
unknownArgumentExit() unknownArgumentExit()
fieldsList = ['driveId', 'id', 'name', 'parents', 'mimeType', 'ownedByMe', 'owners(emailAddress)', fieldsList = ['driveId', 'id', 'name', 'parents', 'mimeType', 'ownedByMe', 'owners(emailAddress)',
'shared', sizeField, 'explicitlyTrashed', 'trashed'] 'shared', sizeField, 'explicitlyTrashed', 'trashed', 'webViewLink']
if csvPF: if csvPF:
if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]: if not GC.Values[GC.DRIVE_V3_NATIVE_NAMES]:
fileNameTitle = 'title' fileNameTitle = 'title'
@@ -59328,7 +59527,8 @@ def _copyPermissions(drive, user, i, count, j, jcount,
entityActionPerformed(kvList, k, kcount) entityActionPerformed(kvList, k, kcount)
except (GAPI.notFound, GAPI.permissionNotFound, except (GAPI.notFound, GAPI.permissionNotFound,
GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.unknownError, GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.unknownError,
GAPI.fileNeverWritable, GAPI.badRequest, GAPI.cannotRemoveOwner, GAPI.cannotModifyInheritedTeamDrivePermission, GAPI.fileNeverWritable, GAPI.badRequest, GAPI.cannotRemoveOwner,
GAPI.cannotModifyInheritedTeamDrivePermission, GAPI.cannotModifyInheritedPermission,
GAPI.insufficientAdministratorPrivileges, GAPI.sharingRateLimitExceeded, GAPI.cannotDeletePermission) as e: GAPI.insufficientAdministratorPrivileges, GAPI.sharingRateLimitExceeded, GAPI.cannotDeletePermission) as e:
entityActionFailedWarning(kvList, str(e), k, kcount) entityActionFailedWarning(kvList, str(e), k, kcount)
except (GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e: except (GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e:
@@ -59355,7 +59555,8 @@ def _copyPermissions(drive, user, i, count, j, jcount,
entityActionPerformed(kvList, k, kcount) entityActionPerformed(kvList, k, kcount)
except (GAPI.notFound, GAPI.permissionNotFound, except (GAPI.notFound, GAPI.permissionNotFound,
GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.unknownError, GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.unknownError,
GAPI.fileNeverWritable, GAPI.badRequest, GAPI.cannotRemoveOwner, GAPI.cannotModifyInheritedTeamDrivePermission, GAPI.fileNeverWritable, GAPI.badRequest, GAPI.cannotRemoveOwner,
GAPI.cannotModifyInheritedTeamDrivePermission, GAPI.cannotModifyInheritedPermission,
GAPI.insufficientAdministratorPrivileges, GAPI.sharingRateLimitExceeded) as e: GAPI.insufficientAdministratorPrivileges, GAPI.sharingRateLimitExceeded) as e:
entityActionFailedWarning(kvList, str(e), k, kcount) entityActionFailedWarning(kvList, str(e), k, kcount)
except (GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e: except (GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e:
@@ -60362,7 +60563,8 @@ def _updateMoveFilePermissions(drive, user, i, count,
entityActionPerformed(kvList, k, kcount) entityActionPerformed(kvList, k, kcount)
except (GAPI.notFound, GAPI.permissionNotFound, except (GAPI.notFound, GAPI.permissionNotFound,
GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.unknownError, GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.unknownError,
GAPI.fileNeverWritable, GAPI.badRequest, GAPI.cannotRemoveOwner, GAPI.cannotModifyInheritedTeamDrivePermission, GAPI.fileNeverWritable, GAPI.badRequest, GAPI.cannotRemoveOwner,
GAPI.cannotModifyInheritedTeamDrivePermission, GAPI.cannotModifyInheritedPermission,
GAPI.insufficientAdministratorPrivileges, GAPI.sharingRateLimitExceeded, GAPI.cannotDeletePermission) as e: GAPI.insufficientAdministratorPrivileges, GAPI.sharingRateLimitExceeded, GAPI.cannotDeletePermission) as e:
entityActionFailedWarning(kvList, str(e), k, kcount) entityActionFailedWarning(kvList, str(e), k, kcount)
except (GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e: except (GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e:
@@ -63785,7 +63987,8 @@ def updateDriveFileACLs(users, useDomainAdminAccess=False):
GAPI.targetUserRoleLimitedByLicenseRestriction, GAPI.insufficientAdministratorPrivileges, GAPI.targetUserRoleLimitedByLicenseRestriction, GAPI.insufficientAdministratorPrivileges,
GAPI.publishOutNotPermitted, GAPI.shareInNotPermitted, GAPI.shareOutNotPermitted, GAPI.shareOutNotPermittedToUser, GAPI.publishOutNotPermitted, GAPI.shareInNotPermitted, GAPI.shareOutNotPermitted, GAPI.shareOutNotPermittedToUser,
GAPI.organizerOnNonTeamDriveItemNotSupported, GAPI.fileOrganizerOnNonTeamDriveNotSupported, GAPI.organizerOnNonTeamDriveItemNotSupported, GAPI.fileOrganizerOnNonTeamDriveNotSupported,
GAPI.cannotUpdatePermission, GAPI.cannotModifyInheritedTeamDrivePermission, GAPI.fieldNotWritable) as e: GAPI.cannotUpdatePermission, GAPI.cannotModifyInheritedTeamDrivePermission, GAPI.cannotModifyInheritedPermission,
GAPI.fieldNotWritable) as e:
entityActionFailedWarning([Ent.USER, user, entityType, fileName], str(e), j, jcount) entityActionFailedWarning([Ent.USER, user, entityType, fileName], str(e), j, jcount)
except (GAPI.notFound, GAPI.teamDriveDomainUsersOnlyRestriction, GAPI.teamDriveTeamMembersOnlyRestriction, except (GAPI.notFound, GAPI.teamDriveDomainUsersOnlyRestriction, GAPI.teamDriveTeamMembersOnlyRestriction,
GAPI.cannotShareTeamDriveTopFolderWithAnyoneOrDomains, GAPI.ownerOnTeamDriveItemNotSupported, GAPI.cannotShareTeamDriveTopFolderWithAnyoneOrDomains, GAPI.ownerOnTeamDriveItemNotSupported,
@@ -64058,7 +64261,8 @@ def deleteDriveFileACLs(users, useDomainAdminAccess=False):
if updateSheetProtectedRanges and mimeType == MIMETYPE_GA_SPREADSHEET: if updateSheetProtectedRanges and mimeType == MIMETYPE_GA_SPREADSHEET:
_updateSheetProtectedRangesACLchange(sheet, user, i, count, j, jcount, fileId, fileName, False, permission) _updateSheetProtectedRangesACLchange(sheet, user, i, count, j, jcount, fileId, fileName, False, permission)
except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.unknownError, except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.unknownError,
GAPI.fileNeverWritable, GAPI.badRequest, GAPI.cannotRemoveOwner, GAPI.cannotModifyInheritedTeamDrivePermission, GAPI.fileNeverWritable, GAPI.badRequest, GAPI.cannotRemoveOwner,
GAPI.cannotModifyInheritedTeamDrivePermission, GAPI.cannotModifyInheritedPermission,
GAPI.insufficientAdministratorPrivileges, GAPI.sharingRateLimitExceeded, GAPI.cannotDeletePermission) as e: GAPI.insufficientAdministratorPrivileges, GAPI.sharingRateLimitExceeded, GAPI.cannotDeletePermission) as e:
entityActionFailedWarning([Ent.USER, user, entityType, fileName], str(e), j, jcount) entityActionFailedWarning([Ent.USER, user, entityType, fileName], str(e), j, jcount)
except GAPI.notFound as e: except GAPI.notFound as e:
@@ -64114,7 +64318,8 @@ def deletePermissions(users, useDomainAdminAccess=False):
fileId=ri[RI_ENTITY], permissionId=ri[RI_ITEM], supportsAllDrives=True) fileId=ri[RI_ENTITY], permissionId=ri[RI_ITEM], supportsAllDrives=True)
entityActionPerformed([Ent.DRIVE_FILE_OR_FOLDER_ID, ri[RI_ENTITY], Ent.PERMISSION_ID, ri[RI_ITEM]], int(ri[RI_J]), int(ri[RI_JCOUNT])) entityActionPerformed([Ent.DRIVE_FILE_OR_FOLDER_ID, ri[RI_ENTITY], Ent.PERMISSION_ID, ri[RI_ITEM]], int(ri[RI_J]), int(ri[RI_JCOUNT]))
except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.unknownError, except (GAPI.fileNotFound, GAPI.forbidden, GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.unknownError,
GAPI.badRequest, GAPI.cannotRemoveOwner, GAPI.cannotModifyInheritedTeamDrivePermission, GAPI.badRequest, GAPI.cannotRemoveOwner,
GAPI.cannotModifyInheritedTeamDrivePermission, GAPI.cannotModifyInheritedPermission,
GAPI.insufficientAdministratorPrivileges, GAPI.sharingRateLimitExceeded, GAPI.permissionNotFound, GAPI.cannotDeletePermission, GAPI.insufficientAdministratorPrivileges, GAPI.sharingRateLimitExceeded, GAPI.permissionNotFound, GAPI.cannotDeletePermission,
GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e: GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy) as e:
entityActionFailedWarning([Ent.DRIVE_FILE_OR_FOLDER_ID, ri[RI_ENTITY], Ent.PERMISSION_ID, ri[RI_ITEM]], str(e), int(ri[RI_J]), int(ri[RI_JCOUNT])) entityActionFailedWarning([Ent.DRIVE_FILE_OR_FOLDER_ID, ri[RI_ENTITY], Ent.PERMISSION_ID, ri[RI_ITEM]], str(e), int(ri[RI_J]), int(ri[RI_JCOUNT]))
@@ -65775,13 +65980,13 @@ def printShowSharedDrives(users, useDomainAdminAccess=False):
entityPerformActionNumItems([Ent.USER, user], jcount, Ent.SHAREDDRIVE, i, count) entityPerformActionNumItems([Ent.USER, user], jcount, Ent.SHAREDDRIVE, i, count)
Ind.Increment() Ind.Increment()
j = 0 j = 0
for shareddrive in matchedFeed: for shareddrive in sorted(matchedFeed, key=lambda k: k['name']):
j += 1 j += 1
shareddrive = stripNonShowFields(shareddrive) shareddrive = stripNonShowFields(shareddrive)
_showSharedDrive(user, shareddrive, j, jcount, FJQC) _showSharedDrive(user, shareddrive, j, jcount, FJQC)
Ind.Decrement() Ind.Decrement()
else: else:
for shareddrive in matchedFeed: for shareddrive in sorted(matchedFeed, key=lambda k: k['name']):
shareddrive = stripNonShowFields(shareddrive) shareddrive = stripNonShowFields(shareddrive)
if FJQC.formatJSON: if FJQC.formatJSON:
row = {'User': user, 'id': shareddrive['id'], 'name': shareddrive['name']} row = {'User': user, 'id': shareddrive['id'], 'name': shareddrive['name']}
@@ -66156,7 +66361,7 @@ def printShowSharedDriveACLs(users, useDomainAdminAccess=False):
entityPerformActionNumItems([Ent.USER, user], jcount, Ent.SHAREDDRIVE, i, count) entityPerformActionNumItems([Ent.USER, user], jcount, Ent.SHAREDDRIVE, i, count)
Ind.Increment() Ind.Increment()
j = 0 j = 0
for shareddrive in matchFeed: for shareddrive in sorted(matchFeed, key=lambda k: k['name']):
j += 1 j += 1
if not FJQC.formatJSON: if not FJQC.formatJSON:
_showDriveFilePermissions(Ent.SHAREDDRIVE, f'{shareddrive["name"]} ({shareddrive["id"]}) - {shareddrive["createdTime"]}', _showDriveFilePermissions(Ent.SHAREDDRIVE, f'{shareddrive["name"]} ({shareddrive["id"]}) - {shareddrive["createdTime"]}',
@@ -66170,7 +66375,7 @@ def printShowSharedDriveACLs(users, useDomainAdminAccess=False):
Ind.Decrement() Ind.Decrement()
elif matchFeed: elif matchFeed:
if oneItemPerRow: if oneItemPerRow:
for shareddrive in matchFeed: for shareddrive in sorted(matchFeed, key=lambda k: k['name']):
baserow = {'User': user, 'id': shareddrive['id'], 'name': shareddrive['name'], 'createdTime': shareddrive['createdTime']} baserow = {'User': user, 'id': shareddrive['id'], 'name': shareddrive['name'], 'createdTime': shareddrive['createdTime']}
if addCSVData: if addCSVData:
baserow.update(addCSVData) baserow.update(addCSVData)
@@ -66191,7 +66396,7 @@ def printShowSharedDriveACLs(users, useDomainAdminAccess=False):
baserow['JSON'] = json.dumps({}) baserow['JSON'] = json.dumps({})
csvPF.WriteRowNoFilter(baserow) csvPF.WriteRowNoFilter(baserow)
else: else:
for shareddrive in matchFeed: for shareddrive in sorted(matchFeed, key=lambda k: k['name']):
baserow = {'User': user, 'id': shareddrive['id'], 'name': shareddrive['name'], 'createdTime': shareddrive['createdTime']} baserow = {'User': user, 'id': shareddrive['id'], 'name': shareddrive['name'], 'createdTime': shareddrive['createdTime']}
if addCSVData: if addCSVData:
baserow.update(addCSVData) baserow.update(addCSVData)
@@ -66392,7 +66597,7 @@ def printSharedDriveOrganizers(users, useDomainAdminAccess=False):
pass pass
if len(matchFeed) == 0: if len(matchFeed) == 0:
setSysExitRC(NO_ENTITIES_FOUND_RC) setSysExitRC(NO_ENTITIES_FOUND_RC)
for shareddrive in matchFeed: for shareddrive in sorted(matchFeed, key=lambda k: k['name']):
row = {'id': shareddrive['id'], 'name': shareddrive['name'], row = {'id': shareddrive['id'], 'name': shareddrive['name'],
'organizers': delimiter.join(shareddrive['organizers']), 'organizers': delimiter.join(shareddrive['organizers']),
'createdTime': shareddrive['createdTime']} 'createdTime': shareddrive['createdTime']}
@@ -67870,7 +68075,7 @@ def updatePhoto(users):
baseFileIdEntity = drive = owner = None baseFileIdEntity = drive = owner = None
sourceFolder = os.getcwd() sourceFolder = os.getcwd()
if Cmd.NumArgumentsRemaining() == 1: if Cmd.NumArgumentsRemaining() == 1:
filenamePattern = getString(Cmd.OB_PHOTO_FILENAME_PATTERN) filenamePattern = getString(Cmd.OB_FILE_NAME_PATTERN)
else: else:
filenamePattern = '#email#.jpg' filenamePattern = '#email#.jpg'
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
@@ -67882,7 +68087,7 @@ def updatePhoto(users):
if not os.path.isdir(sourceFolder): if not os.path.isdir(sourceFolder):
entityDoesNotExistExit(Ent.DIRECTORY, sourceFolder) entityDoesNotExistExit(Ent.DIRECTORY, sourceFolder)
elif myarg == 'filename': elif myarg == 'filename':
filenamePattern = getString(Cmd.OB_PHOTO_FILENAME_PATTERN) filenamePattern = getString(Cmd.OB_FILE_NAME_PATTERN)
elif myarg == 'gphoto': elif myarg == 'gphoto':
owner, drive = buildGAPIServiceObject(API.DRIVE3, getEmailAddress()) owner, drive = buildGAPIServiceObject(API.DRIVE3, getEmailAddress())
if not drive: if not drive:
@@ -67983,7 +68188,7 @@ def getPhoto(users, profileMode):
if not os.path.isdir(targetFolder): if not os.path.isdir(targetFolder):
os.makedirs(targetFolder) os.makedirs(targetFolder)
elif myarg == 'filename': elif myarg == 'filename':
filenamePattern = getString(Cmd.OB_PHOTO_FILENAME_PATTERN) filenamePattern = getString(Cmd.OB_FILE_NAME_PATTERN)
elif myarg == 'nofile': elif myarg == 'nofile':
writeFileData = False writeFileData = False
elif myarg == 'noshow': elif myarg == 'noshow':
@@ -69937,6 +70142,7 @@ def _initMessageThreadParameters(entityType, doIt, maxToProcess):
'query': '', 'queryTimes': {}, 'query': '', 'queryTimes': {},
'entityType': entityType, 'messageEntity': None, 'doIt': doIt, 'quick': True, 'entityType': entityType, 'messageEntity': None, 'doIt': doIt, 'quick': True,
'labelMatchPattern': None, 'senderMatchPattern': None, 'labelMatchPattern': None, 'senderMatchPattern': None,
'labelIds': [],
'maxToProcess': maxToProcess, 'maxItems': 0, 'maxMessagesPerThread': 0, 'maxToProcess': maxToProcess, 'maxItems': 0, 'maxMessagesPerThread': 0,
'maxToKeywords': [MESSAGES_MAX_TO_KEYWORDS[Act.Get()], 'maxtoprocess'], 'maxToKeywords': [MESSAGES_MAX_TO_KEYWORDS[Act.Get()], 'maxtoprocess'],
'listType': listType, 'fields': f'nextPageToken,{listType}(id)'} 'listType': listType, 'fields': f'nextPageToken,{listType}(id)'}
@@ -69969,6 +70175,8 @@ def _getMessageSelectParameters(myarg, parameters):
parameters['labelMatchPattern'] = getREPattern(re.IGNORECASE) parameters['labelMatchPattern'] = getREPattern(re.IGNORECASE)
elif myarg == 'sendermatchpattern': elif myarg == 'sendermatchpattern':
parameters['senderMatchPattern'] = getREPattern(re.IGNORECASE) parameters['senderMatchPattern'] = getREPattern(re.IGNORECASE)
elif myarg == 'labelids':
parameters['labelIds'].extend(getEntityList(Cmd.OB_LABEL_ID_LIST))
elif myarg == 'ids': elif myarg == 'ids':
parameters['messageEntity'] = getUserObjectEntity(Cmd.OB_MESSAGE_ID, parameters['entityType']) parameters['messageEntity'] = getUserObjectEntity(Cmd.OB_MESSAGE_ID, parameters['entityType'])
elif myarg == 'quick': elif myarg == 'quick':
@@ -70068,7 +70276,8 @@ def archiveMessages(users):
listResult = callGAPIpages(service, 'list', parameters['listType'], listResult = callGAPIpages(service, 'list', parameters['listType'],
pageMessage=getPageMessageForWhom(), maxItems=parameters['maxItems'], pageMessage=getPageMessageForWhom(), maxItems=parameters['maxItems'],
throwReasons=GAPI.GMAIL_THROW_REASONS+GAPI.GMAIL_LIST_THROW_REASONS, throwReasons=GAPI.GMAIL_THROW_REASONS+GAPI.GMAIL_LIST_THROW_REASONS,
userId='me', q=parameters['query'], fields=parameters['fields'], userId='me', q=parameters['query'], labelIds=parameters['labelIds'],
fields=parameters['fields'],
maxResults=GC.Values[GC.MESSAGE_MAX_RESULTS]) maxResults=GC.Values[GC.MESSAGE_MAX_RESULTS])
messageIds = [message['id'] for message in listResult] messageIds = [message['id'] for message in listResult]
except (GAPI.failedPrecondition, GAPI.permissionDenied, GAPI.invalid, GAPI.invalidArgument) as e: except (GAPI.failedPrecondition, GAPI.permissionDenied, GAPI.invalid, GAPI.invalidArgument) as e:
@@ -70257,7 +70466,8 @@ def _processMessagesThreads(users, entityType):
listResult = callGAPIpages(service, 'list', parameters['listType'], listResult = callGAPIpages(service, 'list', parameters['listType'],
pageMessage=getPageMessageForWhom(), maxItems=parameters['maxItems'], pageMessage=getPageMessageForWhom(), maxItems=parameters['maxItems'],
throwReasons=GAPI.GMAIL_THROW_REASONS+GAPI.GMAIL_LIST_THROW_REASONS, throwReasons=GAPI.GMAIL_THROW_REASONS+GAPI.GMAIL_LIST_THROW_REASONS,
userId='me', q=parameters['query'], fields=parameters['fields'], includeSpamTrash=includeSpamTrash, userId='me', q=parameters['query'], labelIds=parameters['labelIds'],
fields=parameters['fields'], includeSpamTrash=includeSpamTrash,
maxResults=GC.Values[GC.MESSAGE_MAX_RESULTS]) maxResults=GC.Values[GC.MESSAGE_MAX_RESULTS])
messageIds = [message['id'] for message in listResult] messageIds = [message['id'] for message in listResult]
else: else:
@@ -70373,7 +70583,8 @@ def exportMessagesThreads(users, entityType):
listResult = callGAPIpages(service, 'list', parameters['listType'], listResult = callGAPIpages(service, 'list', parameters['listType'],
pageMessage=getPageMessageForWhom(), maxItems=parameters['maxItems'], pageMessage=getPageMessageForWhom(), maxItems=parameters['maxItems'],
throwReasons=GAPI.GMAIL_THROW_REASONS+GAPI.GMAIL_LIST_THROW_REASONS, throwReasons=GAPI.GMAIL_THROW_REASONS+GAPI.GMAIL_LIST_THROW_REASONS,
userId='me', q=parameters['query'], fields=parameters['fields'], includeSpamTrash=includeSpamTrash, userId='me', q=parameters['query'], labelIds=parameters['labelIds'],
fields=parameters['fields'], includeSpamTrash=includeSpamTrash,
maxResults=GC.Values[GC.MESSAGE_MAX_RESULTS]) maxResults=GC.Values[GC.MESSAGE_MAX_RESULTS])
entityIds = [entity['id'] for entity in listResult] entityIds = [entity['id'] for entity in listResult]
except (GAPI.failedPrecondition, GAPI.permissionDenied, GAPI.invalid, GAPI.invalidArgument) as e: except (GAPI.failedPrecondition, GAPI.permissionDenied, GAPI.invalid, GAPI.invalidArgument) as e:
@@ -70508,7 +70719,8 @@ def forwardMessagesThreads(users, entityType):
listResult = callGAPIpages(service, 'list', parameters['listType'], listResult = callGAPIpages(service, 'list', parameters['listType'],
pageMessage=getPageMessageForWhom(), maxItems=parameters['maxItems'], pageMessage=getPageMessageForWhom(), maxItems=parameters['maxItems'],
throwReasons=GAPI.GMAIL_THROW_REASONS+GAPI.GMAIL_LIST_THROW_REASONS, throwReasons=GAPI.GMAIL_THROW_REASONS+GAPI.GMAIL_LIST_THROW_REASONS,
userId='me', q=parameters['query'], fields=parameters['fields'], includeSpamTrash=includeSpamTrash, userId='me', q=parameters['query'], labelIds=parameters['labelIds'],
fields=parameters['fields'], includeSpamTrash=includeSpamTrash,
maxResults=GC.Values[GC.MESSAGE_MAX_RESULTS]) maxResults=GC.Values[GC.MESSAGE_MAX_RESULTS])
entityIds = [entity['id'] for entity in listResult] entityIds = [entity['id'] for entity in listResult]
except (GAPI.failedPrecondition, GAPI.permissionDenied, GAPI.invalid, GAPI.invalidArgument) as e: except (GAPI.failedPrecondition, GAPI.permissionDenied, GAPI.invalid, GAPI.invalidArgument) as e:
@@ -71613,7 +71825,8 @@ def printShowMessagesThreads(users, entityType):
listResult = callGAPIpages(service, 'list', parameters['listType'], listResult = callGAPIpages(service, 'list', parameters['listType'],
pageMessage=getPageMessageForWhom(), maxItems=parameters['maxItems'], pageMessage=getPageMessageForWhom(), maxItems=parameters['maxItems'],
throwReasons=GAPI.GMAIL_THROW_REASONS+GAPI.GMAIL_LIST_THROW_REASONS, throwReasons=GAPI.GMAIL_THROW_REASONS+GAPI.GMAIL_LIST_THROW_REASONS,
userId='me', q=parameters['query'], fields=parameters['fields'], includeSpamTrash=includeSpamTrash, userId='me', q=parameters['query'], labelIds=parameters['labelIds'],
fields=parameters['fields'], includeSpamTrash=includeSpamTrash,
maxResults=GC.Values[GC.MESSAGE_MAX_RESULTS]) maxResults=GC.Values[GC.MESSAGE_MAX_RESULTS])
messageIds = [message['id'] for message in listResult] messageIds = [message['id'] for message in listResult]
else: else:
@@ -72410,8 +72623,28 @@ def updateFormRequestUpdateMasks(ubody):
v['updateMask'] = ','.join(v['updateMask']) v['updateMask'] = ','.join(v['updateMask'])
break break
def _initPublishSettings():
return {'publishSettings': {'publishState': {}}, 'updateMask': ''}
def _getPublishSettings(myarg, pbody):
if myarg == 'ispublished':
bval = getBoolean()
pbody['publishSettings']['publishState']['isPublished'] = bval
if not bval:
pbody['publishSettings']['publishState']['isAcceptingResponses'] = bval
elif myarg == 'isacceptingresponses':
bval = getBoolean()
pbody['publishSettings']['publishState']['isAcceptingResponses'] = bval
if bval:
pbody['publishSettings']['publishState']['isPublished'] = bval
else:
return False
pbody['updateMask'] = 'publishState'
return True
# gam <UserTypeEntity> create form # gam <UserTypeEntity> create form
# title <String> [description <String>] [isquiz [<Boolean>]] [<JSONData>] # title <String> [description <String>] [isquiz [<Boolean>]] [<JSONData>]
# [ispublished [<Boolean>] isacceptingresponses [<Boolean>]]
# [drivefilename <DriveFileName>] [<DriveFileParentAttribute>] # [drivefilename <DriveFileName>] [<DriveFileParentAttribute>]
# [(csv [todrive <ToDriveAttribute>*]) | returnidonly] # [(csv [todrive <ToDriveAttribute>*]) | returnidonly]
def createForm(users): def createForm(users):
@@ -72420,6 +72653,7 @@ def createForm(users):
title = '' title = ''
body = {'mimeType': MIMETYPE_GA_FORM} body = {'mimeType': MIMETYPE_GA_FORM}
ubody = {'includeFormInResponse': True, 'requests': []} ubody = {'includeFormInResponse': True, 'requests': []}
pbody = _initPublishSettings()
parentParms = initDriveFileAttributes() parentParms = initDriveFileAttributes()
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
myarg = getArgument() myarg = getArgument()
@@ -72433,6 +72667,8 @@ def createForm(users):
elif myarg == 'json': elif myarg == 'json':
jsonData = getJSON([]) jsonData = getJSON([])
ubody['requests'].extend(jsonData.get('requests', [])) ubody['requests'].extend(jsonData.get('requests', []))
elif _getPublishSettings(myarg, pbody):
pass
elif myarg == 'drivefilename': elif myarg == 'drivefilename':
body['name'] = getString(Cmd.OB_DRIVE_FILE_NAME) body['name'] = getString(Cmd.OB_DRIVE_FILE_NAME)
elif getDriveFileParentAttribute(myarg, parentParms): elif getDriveFileParentAttribute(myarg, parentParms):
@@ -72473,6 +72709,10 @@ def createForm(users):
form = callGAPI(gform.forms(), 'batchUpdate', form = callGAPI(gform.forms(), 'batchUpdate',
throwReasons=[GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED], throwReasons=[GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
formId=formId, body=ubody) formId=formId, body=ubody)
if pbody['updateMask']:
callGAPI(gform.forms(), 'setPublishSettings',
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
formId=formId, body=pbody)
if returnIdOnly: if returnIdOnly:
writeStdout(f'{formId}\n') writeStdout(f'{formId}\n')
elif not csvPF: elif not csvPF:
@@ -72497,8 +72737,10 @@ def createForm(users):
# gam <UserTypeEntity> update form <DriveFileEntity> # gam <UserTypeEntity> update form <DriveFileEntity>
# [title <String>] [description <String>] [isquiz [Boolean>]] [<JSONData>] # [title <String>] [description <String>] [isquiz [Boolean>]] [<JSONData>]
# [ispublished [<Boolean>] isacceptingresponses [<Boolean>]]
def updateForm(users): def updateForm(users):
ubody = {'includeFormInResponse': False, 'requests': []} ubody = {'includeFormInResponse': False, 'requests': []}
pbody = _initPublishSettings()
fileIdEntity = getDriveFileEntity() fileIdEntity = getDriveFileEntity()
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
myarg = getArgument() myarg = getArgument()
@@ -72511,10 +72753,12 @@ def updateForm(users):
elif myarg == 'json': elif myarg == 'json':
jsonData = getJSON([]) jsonData = getJSON([])
ubody['requests'].extend(jsonData.get('requests', [])) ubody['requests'].extend(jsonData.get('requests', []))
elif _getPublishSettings(myarg, pbody):
pass
else: else:
unknownArgumentExit() unknownArgumentExit()
updateFormRequestUpdateMasks(ubody) updateFormRequestUpdateMasks(ubody)
if not ubody['requests']: if not ubody['requests'] and not pbody['updateMask']:
return return
i, count, users = getEntityArgument(users) i, count, users = getEntityArgument(users)
for user in users: for user in users:
@@ -72530,9 +72774,14 @@ def updateForm(users):
for formId in fileIdEntity['list']: for formId in fileIdEntity['list']:
j += 1 j += 1
try: try:
if ubody['requests']:
callGAPI(gform.forms(), 'batchUpdate', callGAPI(gform.forms(), 'batchUpdate',
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED], throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
formId=formId, body=ubody) formId=formId, body=ubody)
if pbody['updateMask']:
callGAPI(gform.forms(), 'setPublishSettings',
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
formId=formId, body=pbody)
entityActionPerformed([Ent.USER, user, Ent.FORM, formId], j, jcount) entityActionPerformed([Ent.USER, user, Ent.FORM, formId], j, jcount)
except (GAPI.notFound, GAPI.invalidArgument) as e: except (GAPI.notFound, GAPI.invalidArgument) as e:
entityActionFailedWarning([Ent.USER, user, Ent.FORM, formId], str(e), j, jcount) entityActionFailedWarning([Ent.USER, user, Ent.FORM, formId], str(e), j, jcount)
@@ -72581,6 +72830,9 @@ def printShowForms(users):
result = callGAPI(gform.forms(), 'get', result = callGAPI(gform.forms(), 'get',
throwReasons=[GAPI.NOT_FOUND, GAPI.PERMISSION_DENIED], throwReasons=[GAPI.NOT_FOUND, GAPI.PERMISSION_DENIED],
formId=formId) formId=formId)
if 'publishSettings' in result and 'publishState' in result['publishSettings']:
result['publishSettings']['publishState'].setdefault('isPublished', False)
result['publishSettings']['publishState'].setdefault('isAcceptingResponses', False)
if not csvPF: if not csvPF:
if not FJQC.formatJSON: if not FJQC.formatJSON:
printEntity([Ent.FORM, result['formId']], j, jcount) printEntity([Ent.FORM, result['formId']], j, jcount)
@@ -76982,6 +77234,7 @@ USER_ADD_CREATE_FUNCTIONS = {
Cmd.ARG_CALENDAR: addCreateCalendars, Cmd.ARG_CALENDAR: addCreateCalendars,
Cmd.ARG_GROUP: addUserToGroups, Cmd.ARG_GROUP: addUserToGroups,
Cmd.ARG_CALENDARACL: createCalendarACLs, Cmd.ARG_CALENDARACL: createCalendarACLs,
Cmd.ARG_CHATEMOJI: createChatEmoji,
Cmd.ARG_CHATMEMBER: createChatMember, Cmd.ARG_CHATMEMBER: createChatMember,
Cmd.ARG_CHATMESSAGE: createChatMessage, Cmd.ARG_CHATMESSAGE: createChatMessage,
Cmd.ARG_CHATSPACE: createChatSpace, Cmd.ARG_CHATSPACE: createChatSpace,
@@ -77098,6 +77351,7 @@ USER_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_BACKUPCODE: deleteBackupCodes, Cmd.ARG_BACKUPCODE: deleteBackupCodes,
Cmd.ARG_CALENDAR: deleteCalendars, Cmd.ARG_CALENDAR: deleteCalendars,
Cmd.ARG_CALENDARACL: deleteCalendarACLs, Cmd.ARG_CALENDARACL: deleteCalendarACLs,
Cmd.ARG_CHATEMOJI: deleteChatEmoji,
Cmd.ARG_CHATMEMBER: deleteUpdateChatMember, Cmd.ARG_CHATMEMBER: deleteUpdateChatMember,
Cmd.ARG_CHATMESSAGE: deleteChatMessage, Cmd.ARG_CHATMESSAGE: deleteChatMessage,
Cmd.ARG_CHATSPACE: deleteChatSpace, Cmd.ARG_CHATSPACE: deleteChatSpace,
@@ -77202,6 +77456,7 @@ USER_COMMANDS_WITH_OBJECTS = {
(Act.INFO, (Act.INFO,
{Cmd.ARG_CALENDAR: infoCalendars, {Cmd.ARG_CALENDAR: infoCalendars,
Cmd.ARG_CALENDARACL: infoCalendarACLs, Cmd.ARG_CALENDARACL: infoCalendarACLs,
Cmd.ARG_CHATEMOJI: infoChatEmoji,
Cmd.ARG_CHATEVENT: infoChatEvent, Cmd.ARG_CHATEVENT: infoChatEvent,
Cmd.ARG_CHATMEMBER: infoChatMember, Cmd.ARG_CHATMEMBER: infoChatMember,
Cmd.ARG_CHATMESSAGE: infoChatMessage, Cmd.ARG_CHATMESSAGE: infoChatMessage,
@@ -77274,6 +77529,7 @@ USER_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_CALENDAR: printShowCalendars, Cmd.ARG_CALENDAR: printShowCalendars,
Cmd.ARG_CALENDARACL: printShowCalendarACLs, Cmd.ARG_CALENDARACL: printShowCalendarACLs,
Cmd.ARG_CALSETTINGS: printShowCalSettings, Cmd.ARG_CALSETTINGS: printShowCalSettings,
Cmd.ARG_CHATEMOJI: printShowChatEmojis,
Cmd.ARG_CHATEVENT: printShowChatEvents, Cmd.ARG_CHATEVENT: printShowChatEvents,
Cmd.ARG_CHATMEMBER: printShowChatMembers, Cmd.ARG_CHATMEMBER: printShowChatMembers,
Cmd.ARG_CHATMESSAGE: printShowChatMessages, Cmd.ARG_CHATMESSAGE: printShowChatMessages,
@@ -77381,6 +77637,7 @@ USER_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_CALENDAR: printShowCalendars, Cmd.ARG_CALENDAR: printShowCalendars,
Cmd.ARG_CALENDARACL: printShowCalendarACLs, Cmd.ARG_CALENDARACL: printShowCalendarACLs,
Cmd.ARG_CALSETTINGS: printShowCalSettings, Cmd.ARG_CALSETTINGS: printShowCalSettings,
Cmd.ARG_CHATEMOJI: printShowChatEmojis,
Cmd.ARG_CHATEVENT: printShowChatEvents, Cmd.ARG_CHATEVENT: printShowChatEvents,
Cmd.ARG_CHATMEMBER: printShowChatMembers, Cmd.ARG_CHATMEMBER: printShowChatMembers,
Cmd.ARG_CHATMESSAGE: printShowChatMessages, Cmd.ARG_CHATMESSAGE: printShowChatMessages,
@@ -77597,6 +77854,7 @@ USER_COMMANDS_OBJ_ALIASES = {
Cmd.ARG_CLASSIFICATIONLABELPERMISSION: Cmd.ARG_DRIVELABELPERMISSION, Cmd.ARG_CLASSIFICATIONLABELPERMISSION: Cmd.ARG_DRIVELABELPERMISSION,
Cmd.ARG_CLASSIFICATIONLABELPERMISSIONS: Cmd.ARG_DRIVELABELPERMISSION, Cmd.ARG_CLASSIFICATIONLABELPERMISSIONS: Cmd.ARG_DRIVELABELPERMISSION,
Cmd.ARG_CLASSROOMINVITATIONS: Cmd.ARG_CLASSROOMINVITATION, Cmd.ARG_CLASSROOMINVITATIONS: Cmd.ARG_CLASSROOMINVITATION,
Cmd.ARG_CHATEMOJIS: Cmd.ARG_CHATEMOJI,
Cmd.ARG_CHATEVENTS: Cmd.ARG_CHATEVENT, Cmd.ARG_CHATEVENTS: Cmd.ARG_CHATEVENT,
Cmd.ARG_CHATMEMBERS: Cmd.ARG_CHATMEMBER, Cmd.ARG_CHATMEMBERS: Cmd.ARG_CHATMEMBER,
Cmd.ARG_CHATMESSAGES: Cmd.ARG_CHATMESSAGE, Cmd.ARG_CHATMESSAGES: Cmd.ARG_CHATMESSAGE,

View File

@@ -26,6 +26,7 @@ ANALYTICS_ADMIN = 'analyticsadmin'
CALENDAR = 'calendar' CALENDAR = 'calendar'
CBCM = 'cbcm' CBCM = 'cbcm'
CHAT = 'chat' CHAT = 'chat'
CHAT_CUSTOM_EMOJIS = 'chatcustomemojis'
CHAT_EVENTS = 'chatevents' CHAT_EVENTS = 'chatevents'
CHAT_MEMBERSHIPS = 'chatmemberships' CHAT_MEMBERSHIPS = 'chatmemberships'
CHAT_MEMBERSHIPS_ADMIN = 'chatmembershipsadmin' CHAT_MEMBERSHIPS_ADMIN = 'chatmembershipsadmin'
@@ -210,6 +211,7 @@ _INFO = {
CALENDAR: {'name': 'Calendar API', 'version': 'v3', 'v2discovery': True, 'mappedAPI': 'calendar-json'}, CALENDAR: {'name': 'Calendar API', 'version': 'v3', 'v2discovery': True, 'mappedAPI': 'calendar-json'},
CBCM: {'name': 'Chrome Browser Cloud Management API', 'version': 'v1.1beta1', 'v2discovery': True, 'localjson': True}, CBCM: {'name': 'Chrome Browser Cloud Management API', 'version': 'v1.1beta1', 'v2discovery': True, 'localjson': True},
CHAT: {'name': 'Chat API', 'version': 'v1', 'v2discovery': True}, CHAT: {'name': 'Chat API', 'version': 'v1', 'v2discovery': True},
CHAT_CUSTOM_EMOJIS: {'name': 'Chat API - Custom Emojis', 'version': 'v1', 'v2discovery': True, 'mappedAPI': CHAT},
CHAT_EVENTS: {'name': 'Chat API - Events', 'version': 'v1', 'v2discovery': True, 'mappedAPI': CHAT}, CHAT_EVENTS: {'name': 'Chat API - Events', 'version': 'v1', 'v2discovery': True, 'mappedAPI': CHAT},
CHAT_MEMBERSHIPS: {'name': 'Chat API - Memberships', 'version': 'v1', 'v2discovery': True, 'mappedAPI': CHAT}, CHAT_MEMBERSHIPS: {'name': 'Chat API - Memberships', 'version': 'v1', 'v2discovery': True, 'mappedAPI': CHAT},
CHAT_MEMBERSHIPS_ADMIN: {'name': 'Chat API - Memberships Admin', 'version': 'v1', 'v2discovery': True, 'mappedAPI': CHAT}, CHAT_MEMBERSHIPS_ADMIN: {'name': 'Chat API - Memberships Admin', 'version': 'v1', 'v2discovery': True, 'mappedAPI': CHAT},
@@ -544,6 +546,10 @@ _SVCACCT_SCOPES = [
'api': CALENDAR, 'api': CALENDAR,
'subscopes': READONLY, 'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/calendar'}, 'scope': 'https://www.googleapis.com/auth/calendar'},
{'name': 'Chat API - Custom Emojis',
'api': CHAT_CUSTOM_EMOJIS,
'subscopes': READONLY,
'scope': 'https://www.googleapis.com/auth/chat.customemojis'},
{'name': 'Chat API - Memberships', {'name': 'Chat API - Memberships',
'api': CHAT_MEMBERSHIPS, 'api': CHAT_MEMBERSHIPS,
'subscopes': READONLY, 'subscopes': READONLY,

View File

@@ -461,6 +461,8 @@ class GamCLArgs():
ARG_CHANNELSKU = 'channelsku' ARG_CHANNELSKU = 'channelsku'
ARG_CHANNELSKUS = 'channelskus' ARG_CHANNELSKUS = 'channelskus'
ARG_CHAT = 'chat' ARG_CHAT = 'chat'
ARG_CHATEMOJI = 'chatemoji'
ARG_CHATEMOJIS = 'chatemojis'
ARG_CHATEVENT = 'chatevent' ARG_CHATEVENT = 'chatevent'
ARG_CHATEVENTS = 'chatevents' ARG_CHATEVENTS = 'chatevents'
ARG_CHATMEMBER = 'chatmember' ARG_CHATMEMBER = 'chatmember'
@@ -843,6 +845,8 @@ class GamCLArgs():
OB_CHARACTER = 'Character' OB_CHARACTER = 'Character'
OB_CHAR_SET = 'CharacterSet' OB_CHAR_SET = 'CharacterSet'
OG_CHAT_ATTACHMENT = 'ChatAttachment' OG_CHAT_ATTACHMENT = 'ChatAttachment'
OB_CHAT_EMOJI = 'ChatEmoji'
OB_CHAT_EMOJI_NAME = 'ChatEmojiName'
OB_CHAT_EVENT = 'ChatEvent' OB_CHAT_EVENT = 'ChatEvent'
OB_CHAT_MEMBER = 'ChatMember' OB_CHAT_MEMBER = 'ChatMember'
OB_CHAT_MESSAGE = 'ChatMessage' OB_CHAT_MESSAGE = 'ChatMessage'
@@ -930,6 +934,7 @@ class GamCLArgs():
OB_FILE_NAME = 'FileName' OB_FILE_NAME = 'FileName'
OB_FILE_NAME_FIELD_NAME = OB_FILE_NAME+'(:'+OB_FIELD_NAME+')+' OB_FILE_NAME_FIELD_NAME = OB_FILE_NAME+'(:'+OB_FIELD_NAME+')+'
OB_FILE_NAME_OR_URL = 'FileName|URL' OB_FILE_NAME_OR_URL = 'FileName|URL'
OB_FILE_NAME_PATTERN = 'FileNamePattern'
OB_FILE_PATH = 'FilePath' OB_FILE_PATH = 'FilePath'
OB_FILTER_ID_ENTITY = 'FilterIDEntity' OB_FILTER_ID_ENTITY = 'FilterIDEntity'
OB_FORMAT_LIST = 'FormatList' OB_FORMAT_LIST = 'FormatList'
@@ -975,7 +980,6 @@ class GamCLArgs():
OB_PERMISSION_ID_LIST = 'PermissionIDList' OB_PERMISSION_ID_LIST = 'PermissionIDList'
OB_PERMISSION_ROLE_LIST = 'PermissionRoleList' OB_PERMISSION_ROLE_LIST = 'PermissionRoleList'
OB_PERMISSION_TYPE_LIST = 'PermissionTypeList' OB_PERMISSION_TYPE_LIST = 'PermissionTypeList'
OB_PHOTO_FILENAME_PATTERN = 'FilenameNamePattern'
OB_PRINTER_ID = 'PrinterID' OB_PRINTER_ID = 'PrinterID'
OB_PRIVILEGE_LIST = 'PrivilegeList' OB_PRIVILEGE_LIST = 'PrivilegeList'
OB_PRODUCT_ID = 'ProductID' OB_PRODUCT_ID = 'ProductID'

View File

@@ -86,6 +86,7 @@ class GamEntity():
CHANNEL_SKU = 'chsk' CHANNEL_SKU = 'chsk'
CHAT_BOT = 'chbo' CHAT_BOT = 'chbo'
CHAT_ADMIN = 'chad' CHAT_ADMIN = 'chad'
CHAT_EMOJI = 'chem'
CHAT_EVENT = 'chev' CHAT_EVENT = 'chev'
CHAT_MANAGER_USER = 'chgu' CHAT_MANAGER_USER = 'chgu'
CHAT_MEMBER = 'chme' CHAT_MEMBER = 'chme'
@@ -436,6 +437,7 @@ class GamEntity():
CHANNEL_SKU: ['Channel SKUs', 'Channel SKU'], CHANNEL_SKU: ['Channel SKUs', 'Channel SKU'],
CHAT_BOT: ['Chat BOTs', 'Chat BOT'], CHAT_BOT: ['Chat BOTs', 'Chat BOT'],
CHAT_ADMIN: ['Chat Admins', 'Chat Admin'], CHAT_ADMIN: ['Chat Admins', 'Chat Admin'],
CHAT_EMOJI: ['Chat Emojis', 'Chat Emoji'],
CHAT_EVENT: ['Chat Events', 'Chat Event'], CHAT_EVENT: ['Chat Events', 'Chat Event'],
CHAT_MANAGER_USER: ['Chat User Managers', 'Chat User Manager'], CHAT_MANAGER_USER: ['Chat User Managers', 'Chat User Manager'],
CHAT_MESSAGE: ['Chat Messages', 'Chat Message'], CHAT_MESSAGE: ['Chat Messages', 'Chat Message'],

View File

@@ -41,6 +41,7 @@ CANNOT_DELETE_PERMISSION = 'cannotDeletePermission'
CANNOT_DELETE_PRIMARY_CALENDAR = 'cannotDeletePrimaryCalendar' CANNOT_DELETE_PRIMARY_CALENDAR = 'cannotDeletePrimaryCalendar'
CANNOT_DELETE_PRIMARY_SENDAS = 'cannotDeletePrimarySendAs' CANNOT_DELETE_PRIMARY_SENDAS = 'cannotDeletePrimarySendAs'
CANNOT_DELETE_RESOURCE_WITH_CHILDREN = 'cannotDeleteResourceWithChildren' CANNOT_DELETE_RESOURCE_WITH_CHILDREN = 'cannotDeleteResourceWithChildren'
CANNOT_MODIFY_INHERITED_PERMISSION = 'cannotModifyInheritedPermission'
CANNOT_MODIFY_INHERITED_TEAMDRIVE_PERMISSION = 'cannotModifyInheritedTeamDrivePermission' CANNOT_MODIFY_INHERITED_TEAMDRIVE_PERMISSION = 'cannotModifyInheritedTeamDrivePermission'
CANNOT_MODIFY_RESTRICTED_LABEL = 'cannotModifyRestrictedLabel' CANNOT_MODIFY_RESTRICTED_LABEL = 'cannotModifyRestrictedLabel'
CANNOT_MODIFY_VIEWERS_CAN_COPY_CONTENT = 'cannotModifyViewersCanCopyContent' CANNOT_MODIFY_VIEWERS_CAN_COPY_CONTENT = 'cannotModifyViewersCanCopyContent'
@@ -248,10 +249,10 @@ DRIVE3_UPDATE_ACL_THROW_REASONS = [BAD_REQUEST, INVALID_OWNERSHIP_TRANSFER, CANN
FILE_ORGANIZER_ON_FOLDERS_IN_SHARED_DRIVE_ONLY, FILE_ORGANIZER_ON_FOLDERS_IN_SHARED_DRIVE_ONLY,
FILE_ORGANIZER_ON_NON_TEAMDRIVE_NOT_SUPPORTED, FILE_ORGANIZER_ON_NON_TEAMDRIVE_NOT_SUPPORTED,
CANNOT_UPDATE_PERMISSION, CANNOT_UPDATE_PERMISSION,
CANNOT_MODIFY_INHERITED_TEAMDRIVE_PERMISSION, CANNOT_MODIFY_INHERITED_TEAMDRIVE_PERMISSION, CANNOT_MODIFY_INHERITED_PERMISSION,
FIELD_NOT_WRITABLE, PERMISSION_NOT_FOUND] FIELD_NOT_WRITABLE, PERMISSION_NOT_FOUND]
DRIVE3_DELETE_ACL_THROW_REASONS = [BAD_REQUEST, CANNOT_REMOVE_OWNER, DRIVE3_DELETE_ACL_THROW_REASONS = [BAD_REQUEST, CANNOT_REMOVE_OWNER,
CANNOT_MODIFY_INHERITED_TEAMDRIVE_PERMISSION, CANNOT_MODIFY_INHERITED_TEAMDRIVE_PERMISSION, CANNOT_MODIFY_INHERITED_PERMISSION,
INSUFFICIENT_ADMINISTRATOR_PRIVILEGES, SHARING_RATE_LIMIT_EXCEEDED, INSUFFICIENT_ADMINISTRATOR_PRIVILEGES, SHARING_RATE_LIMIT_EXCEEDED,
NOT_FOUND, PERMISSION_NOT_FOUND, CANNOT_DELETE_PERMISSION] NOT_FOUND, PERMISSION_NOT_FOUND, CANNOT_DELETE_PERMISSION]
DRIVE3_MODIFY_LABEL_THROW_REASONS = DRIVE_USER_THROW_REASONS+[FILE_NOT_FOUND, NOT_FOUND, FORBIDDEN, INTERNAL_ERROR, DRIVE3_MODIFY_LABEL_THROW_REASONS = DRIVE_USER_THROW_REASONS+[FILE_NOT_FOUND, NOT_FOUND, FORBIDDEN, INTERNAL_ERROR,
@@ -398,6 +399,8 @@ class cannotDeletePrimarySendAs(Exception):
pass pass
class cannotDeleteResourceWithChildren(Exception): class cannotDeleteResourceWithChildren(Exception):
pass pass
class cannotModifyInheritedPermission(Exception):
pass
class cannotModifyInheritedTeamDrivePermission(Exception): class cannotModifyInheritedTeamDrivePermission(Exception):
pass pass
class cannotModifyRestrictedLabel(Exception): class cannotModifyRestrictedLabel(Exception):
@@ -698,6 +701,7 @@ REASON_EXCEPTION_MAP = {
CANNOT_DELETE_PRIMARY_CALENDAR: cannotDeletePrimaryCalendar, CANNOT_DELETE_PRIMARY_CALENDAR: cannotDeletePrimaryCalendar,
CANNOT_DELETE_PRIMARY_SENDAS: cannotDeletePrimarySendAs, CANNOT_DELETE_PRIMARY_SENDAS: cannotDeletePrimarySendAs,
CANNOT_DELETE_RESOURCE_WITH_CHILDREN: cannotDeleteResourceWithChildren, CANNOT_DELETE_RESOURCE_WITH_CHILDREN: cannotDeleteResourceWithChildren,
CANNOT_MODIFY_INHERITED_PERMISSION: cannotModifyInheritedPermission,
CANNOT_MODIFY_INHERITED_TEAMDRIVE_PERMISSION: cannotModifyInheritedTeamDrivePermission, CANNOT_MODIFY_INHERITED_TEAMDRIVE_PERMISSION: cannotModifyInheritedTeamDrivePermission,
CANNOT_MODIFY_RESTRICTED_LABEL: cannotModifyRestrictedLabel, CANNOT_MODIFY_RESTRICTED_LABEL: cannotModifyRestrictedLabel,
CANNOT_MODIFY_VIEWERS_CAN_COPY_CONTENT: cannotModifyViewersCanCopyContent, CANNOT_MODIFY_VIEWERS_CAN_COPY_CONTENT: cannotModifyViewersCanCopyContent,

View File

@@ -309,6 +309,7 @@ INVALID_ALIAS = 'Invalid Alias'
INVALID_ATTENDEE_CHANGE = 'Invalid attendee change "{0}"' INVALID_ATTENDEE_CHANGE = 'Invalid attendee change "{0}"'
INVALID_CHARSET = 'Invalid charset "{0}"' INVALID_CHARSET = 'Invalid charset "{0}"'
INVALID_DATE_TIME_RANGE = '{0} {1} must be greater than/equal to {2} {3}' INVALID_DATE_TIME_RANGE = '{0} {1} must be greater than/equal to {2} {3}'
INVALID_EMOJI_NAME = '{0} does not match pattern :[0-9a-z_-]:'
INVALID_ENTITY = 'Invalid {0}, {1}' INVALID_ENTITY = 'Invalid {0}, {1}'
INVALID_EVENT_TIMERANGE = '{0} {1} must be less than {2}' INVALID_EVENT_TIMERANGE = '{0} {1} must be less than {2}'
INVALID_FILE_SELECTION_WITH_ADMIN_ACCESS = 'Invalid file selection with adminaccess|asadmin' INVALID_FILE_SELECTION_WITH_ADMIN_ACCESS = 'Invalid file selection with adminaccess|asadmin'

View File

@@ -96,7 +96,7 @@
banana|basil|blueberry|flamingo|graphite|grape| banana|basil|blueberry|flamingo|graphite|grape|
lavender|peacock|sage|tangerine|tomato lavender|peacock|sage|tangerine|tomato
<FileFormat> ::= <FileFormat> ::=
csv|doc|dot|docx|dotx|epub|html|jpeg|jpg|mht|odp|ods|odt| csv|doc|dot|docx|dotx|epub|html|jpeg|jpg|json|mht|odp|ods|odt|
pdf|png|ppt|pot|potx|pptx|rtf|svg|tsv|txt|xls|xlt|xlsx|xltx|zip| pdf|png|ppt|pot|potx|pptx|rtf|svg|tsv|txt|xls|xlt|xlsx|xltx|zip|
ms|microsoft|openoffice| ms|microsoft|openoffice|
<LabelColorHex> ::= <LabelColorHex> ::=
@@ -278,6 +278,8 @@
domain:<DomainName>|domain|default domain:<DomainName>|domain|default
<CalendarItem> ::= <EmailAddress> <CalendarItem> ::= <EmailAddress>
<ChannelCustomerID> ::= <String> <ChannelCustomerID> ::= <String>
<ChatEmojiName> ::= :[0-9a-z_-]+:
<ChatEmoji> ::= emojiname <ChatEmojiName> | customemojis/<String>
<ChatMember> ::= spaces/<String>/members/<String> <ChatMember> ::= spaces/<String>/members/<String>
<ChatMessage> ::= spaces/<String>/messages/<String> <ChatMessage> ::= spaces/<String>/messages/<String>
<ChatSpace> ::= spaces/<String> | space <String> | space spaces/<String> <ChatSpace> ::= spaces/<String> | space <String> | space spaces/<String>

View File

@@ -4266,6 +4266,13 @@ chrome.devices.MobileDataRoaming: Mobile data roaming.
true: Allow mobile data roaming. true: Allow mobile data roaming.
false: Do not allow mobile data roaming. false: Do not allow mobile data roaming.
chrome.devices.PartnerAccess: Allow EMM partners access to device management.
chromeDeviceManagementApiEnabled: TYPE_BOOL
true: Enable Chrome management - partner access.
false: Disable Chrome management - partner access.
ackNoticeForChromeDeviceManagementApiEnabledSetToTrue: TYPE_BOOL
This field must be set to true to acknowledge the notice message associated with the field 'chrome_device_management_api_enabled' set to value 'true'. Please sse the notices listed with this policy for more information.
chrome.devices.PowerManagement: Power management. chrome.devices.PowerManagement: Power management.
loginScreenPowerManagement: TYPE_BOOL loginScreenPowerManagement: TYPE_BOOL
true: Allow device to sleep/shut down when idle on the sign-in screen. true: Allow device to sleep/shut down when idle on the sign-in screen.
@@ -5979,6 +5986,9 @@ chrome.users.appsconfig.AllowedAppTypes: Allowed types of apps and extensions.
platform_app: Chrome packaged app. platform_app: Chrome packaged app.
chrome.users.appsconfig.AllowedInstallSources: Allows setting of the allowed install sources for apps. Note these must be set together. chrome.users.appsconfig.AllowedInstallSources: Allows setting of the allowed install sources for apps. Note these must be set together.
playStoreInstallSources: TYPE_ENUM
ALLOW_ALL_APPS: All apps allowed, admin manages blocklist.
BLOCK_ALL_APPS: All apps blocked, admin manages allowlist.
chromeWebStoreInstallSources: TYPE_ENUM chromeWebStoreInstallSources: TYPE_ENUM
ALLOW_ALL_APPS: All apps allowed, admin manages blocklist. ALLOW_ALL_APPS: All apps allowed, admin manages blocklist.
BLOCK_ALL_APPS: All apps blocked, admin manages allowlist. BLOCK_ALL_APPS: All apps blocked, admin manages allowlist.
@@ -7855,6 +7865,11 @@ chrome.users.InsertKeyModifier: Control the shortcut used to trigger the Insert
MANDATORY: Do not allow users to override. MANDATORY: Do not allow users to override.
RECOMMENDED: Allow users to override. RECOMMENDED: Allow users to override.
chrome.users.InstantTetheringAllowed: Instant Tethering.
instantTetheringAllowed: TYPE_BOOL
true: Allow users to use Instant Tethering.
false: Do not allow users to use Instant Tethering.
chrome.users.IntegratedWebAuthenticationAllowed: Login credentials for network authentication. chrome.users.IntegratedWebAuthenticationAllowed: Login credentials for network authentication.
integratedWebAuthenticationAllowed: TYPE_BOOL integratedWebAuthenticationAllowed: TYPE_BOOL
true: Use login credentials for network authentication to a managed proxy. true: Use login credentials for network authentication to a managed proxy.
@@ -8991,6 +9006,11 @@ chrome.users.SecondaryGoogleAccountSignin: Sign-in to secondary accounts.
allowedDomainsForApps: TYPE_LIST allowedDomainsForApps: TYPE_LIST
Whether the OS version updates will be set to a version defined in the manifest of a kiosk app. Whether the OS version updates will be set to a version defined in the manifest of a kiosk app.
chrome.users.SecondaryGoogleAccountUsage: Managed account as secondary account.
secondaryGoogleAccountUsage: TYPE_ENUM
ALL: All usages of managed accounts are allowed.
PRIMARY_ACCOUNT_SIGNIN: Block addition of a managed account as secondary account (in-session).
chrome.users.SecurityKeyAttestation: Security key attestation. chrome.users.SecurityKeyAttestation: Security key attestation.
securityKeyPermitAttestation: TYPE_LIST securityKeyPermitAttestation: TYPE_LIST
Enter URL or domain. Specifies URLs and domains for which no prompt will be shown when attestation certificates from security keys are requested. Additionally, a signal will be sent to the security key indicating that individual attestation may be used. Without this, users will be prompted in Chrome 65+ when sites request attestation of security keys. URLs (like "https://example.com/some/path") will only match as U2F AppIDs. Domains (like "example.com") only match as WebAuthn RP IDs. Thus, to cover both U2F and WebAuthn APIs for a given site, both the AppID URL and domain would need to be listed. Enter URL or domain. Specifies URLs and domains for which no prompt will be shown when attestation certificates from security keys are requested. Additionally, a signal will be sent to the security key indicating that individual attestation may be used. Without this, users will be prompted in Chrome 65+ when sites request attestation of security keys. URLs (like "https://example.com/some/path") will only match as U2F AppIDs. Domains (like "example.com") only match as WebAuthn RP IDs. Thus, to cover both U2F and WebAuthn APIs for a given site, both the AppID URL and domain would need to be listed.
@@ -9211,6 +9231,7 @@ chrome.users.SiteSearchSettings: Site search.
name: TYPE_STRING name: TYPE_STRING
shortcut: TYPE_STRING shortcut: TYPE_STRING
url: TYPE_STRING url: TYPE_STRING
allowUserOverride: TYPE_BOOL
chrome.users.SmartLockAllowed: Smart Lock. chrome.users.SmartLockAllowed: Smart Lock.
smartLockAllowed: TYPE_BOOL smartLockAllowed: TYPE_BOOL
@@ -9226,6 +9247,11 @@ chrome.users.SmartScreenDimDelay: Delay screen dim on user activity.
true: Enable smart dim model. true: Enable smart dim model.
false: Disable smart dim model. false: Disable smart dim model.
chrome.users.SmsMessagesAllowed: Messages.
smsMessagesAllowed: TYPE_BOOL
true: Allow users to sync SMS messages between their phone and Chromebook.
false: Do not allow users to sync SMS messages between their phone and Chromebook.
chrome.users.SpellcheckEnabled: Spell check. chrome.users.SpellcheckEnabled: Spell check.
spellcheckEnabled: TYPE_ENUM spellcheckEnabled: TYPE_ENUM
UNSET: Allow the user to decide. UNSET: Allow the user to decide.
@@ -9919,4 +9945,5 @@ chrome.users.ZstdContentEncodingEnabled: Zstd compression.
true: Allow zstd-compressed web content. true: Allow zstd-compressed web content.
false: Do not allow zstd-compressed web content. false: Do not allow zstd-compressed web content.
``` ```

View File

@@ -10,6 +10,58 @@ Add the `-s` option to the end of the above commands to suppress creating the `g
See [Downloads-Installs-GAM7](https://github.com/GAM-team/GAM/wiki/Downloads-Installs) for Windows or other options, including manual installation See [Downloads-Installs-GAM7](https://github.com/GAM-team/GAM/wiki/Downloads-Installs) for Windows or other options, including manual installation
### 7.10.04
Updated `gam report <ActivityApplicationName>` to accept accept application names as defined
in the Reports API discovery document; this means that GAM does not have to be updated when
Google defines a new application name.
`gemini_in_workspace_apps` is now available in `gam report`.
### 7.10.03
Fixed bug in commands that modify messages where the `labelids <LabelIdList>` option
was not being applied.
### 7.10.02
Added option `labelids <LabelIdList>` to all commands that process messages;
this option causes GAM to only return messages with labels that match all of the specified label IDs.
Updated `gam <UserTypeEntity> print|show forms` to always display `isPublished` and
`isAcceptingResponses` in `publishSettings/publishState` regardless of their value;
the API doesn't return these values when they are False.
### 7.10.01
Added options `ispublished [<Boolean>]` and `isacceptingresponses [<Boolean>]` to
`gam <UserTypeEntity> create|update form`.
### 7.10.00
Added commands to manage/display Chat Custom Emojis.
* See: https://github.com/GAM-team/GAM/wiki/Users-Chat#manage-chat-emojis
* See: https://github.com/GAM-team/GAM/wiki/Users-Chat#display-chat-emojis
Updated `gam <UserItem> print|show chatspaces|chatmembers asadmin` to display
the spaces in ascending display name order.
### 7.09.07
Added `webviewlink` to `<FileTreeFieldName>` for use in `gam <UserTypeEntity> print|show filetree`.
### 7.09.06
Upddated `gam print|show shareddrives`, `gam print|show shareddriveacls`, `gam print shareddriveorganizers`
to display the Shared Drives in ascending name order; the API returns them in an unidentifiable order.
### 7.09.05
Improved output of `gam info|show chromeschemas [std]` to more accurately display the schemas.
Fixed bugs in `gam update chromepolicy` that caused invalid error messaages.
### 7.09.04 ### 7.09.04
Fixed bug in `gam whatis <EmailItem>` where the check for an invitable user always failed. Fixed bug in `gam whatis <EmailItem>` where the check for an invitable user always failed.

View File

@@ -251,7 +251,7 @@ writes the credentials into the file oauth2.txt.
admin@server:/Users/admin$ rm -f /Users/admin/GAMConfig/oauth2.txt admin@server:/Users/admin$ rm -f /Users/admin/GAMConfig/oauth2.txt
admin@server:/Users/admin$ gam version admin@server:/Users/admin$ gam version
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
GAM 7.09.04 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.10.04 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.5 64-bit final Python 3.13.5 64-bit final
MacOS Sequoia 15.5 x86_64 MacOS Sequoia 15.5 x86_64
@@ -989,7 +989,7 @@ writes the credentials into the file oauth2.txt.
C:\>del C:\GAMConfig\oauth2.txt C:\>del C:\GAMConfig\oauth2.txt
C:\>gam version C:\>gam version
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
GAM 7.09.04 - https://github.com/GAM-team/GAM - pythonsource GAM 7.10.04 - https://github.com/GAM-team/GAM - pythonsource
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.5 64-bit final Python 3.13.5 64-bit final
Windows-10-10.0.17134 AMD64 Windows-10-10.0.17134 AMD64

View File

@@ -11,7 +11,7 @@
- [Synchronize licenses](#synchronize-licenses) - [Synchronize licenses](#synchronize-licenses)
## API documentation ## API documentation
* [License Manager API](https://developers.google.com/admin-sdk/licensing/rest/v1/licenseAssignments) * [License Manager API](https://developers.google.com/workspace/admin/licensing/reference/rest/v1/licenseAssignments)
## License Products and SKUs ## License Products and SKUs
* [Product and SKU IDs](https://developers.google.com/admin-sdk/licensing/v1/how-tos/products) * [Product and SKU IDs](https://developers.google.com/admin-sdk/licensing/v1/how-tos/products)

View File

@@ -39,19 +39,18 @@ config csv_output_row_filter "'\"accounts:used_quota_in_mb\":count>15000'"
## Activity reports ## Activity reports
``` ```
<ActivityApplicationName> ::= <ActivityApplicationName> ::=
access|accesstransparency| accesstransparency|access|
admin| admin|
calendar|calendars| calendar|calendars|
chat| chat|
chrome| chrome|
classroom|
contextawareaccess| contextawareaccess|
currents|gplus|google+| gplus|currents|google+|
datastudio| datastudio|
devices|mobile|
domain|
drive|doc|docs| drive|doc|docs|
gcp| gcp|cloud|
gemini|geminiforworkspace| geminiinworkspaceapps|gemini|geminiforworkspace|
groups|group| groups|group|
groupsenterprise|enterprisegroups| groupsenterprise|enterprisegroups|
jamboard| jamboard|

View File

@@ -12,6 +12,8 @@
- [Manage Chat Messages](#manage-chat-messages) - [Manage Chat Messages](#manage-chat-messages)
- [Display Chat Messages](#display-chat-messages) - [Display Chat Messages](#display-chat-messages)
- [Display Chat Events](#display-chat-events) - [Display Chat Events](#display-chat-events)
- [Manage Chat Emojis](#manage-chat-emojis)
- [Display Chat Emojis](#display-chat-emojis)
- [Bulk Operations](#bulk-operations) - [Bulk Operations](#bulk-operations)
## Introduction ## Introduction
@@ -19,6 +21,7 @@ To use these commands you must update your service account authorization.
``` ```
gam user user@domain.com update serviceaccount gam user user@domain.com update serviceaccount
[*] 3) Chat API - Custom Emojis (supports readonly)
[*] 4) Chat API - Memberships (supports readonly) [*] 4) Chat API - Memberships (supports readonly)
[*] 5) Chat API - Memberships Admin (supports readonly) [*] 5) Chat API - Memberships Admin (supports readonly)
[*] 6) Chat API - Messages (supports readonly) [*] 6) Chat API - Messages (supports readonly)
@@ -51,10 +54,12 @@ Google requires that you have a Chat Bot configured in order to use the Chat API
## API documentation ## API documentation
* [Overview](https://developers.google.com/workspace/chat/overview) * [Overview](https://developers.google.com/workspace/chat/overview)
* [Chat API](https://developers.google.com/workspace/chat/api/reference/rest) * [Chat API](https://developers.google.com/workspace/chat/api/reference/rest)
* [Chat API - Custom Emojis](https://developers.google.com/workspace/chat/api/reference/rest/v1/customEmojis)
* [Chat API - Members](https://developers.google.com/workspace/chat/api/reference/rest/v1/spaces.members/list) * [Chat API - Members](https://developers.google.com/workspace/chat/api/reference/rest/v1/spaces.members/list)
* [Chat API - Messages](https://developers.google.com/workspace/chat/api/reference/rest/v1/spaces.messages/list) * [Chat API - Messages](https://developers.google.com/workspace/chat/api/reference/rest/v1/spaces.messages/list)
* [Chat API - Events](https://developers.google.com/workspace/chat/api/reference/rest/v1/spaces.spaceEvents/list) * [Chat API - Events](https://developers.google.com/workspace/chat/api/reference/rest/v1/spaces.spaceEvents/list)
* [Apps in Google Chat](https://support.google.com/chat/answer/7655820) * [Apps in Google Chat](https://support.google.com/chat/answer/7655820)
* [Manage customemoji permissions](https://support.google.com/a/answer/12850085)
* [Manage Spaces in Admin Console](https://support.google.com/a/answer/13369245) * [Manage Spaces in Admin Console](https://support.google.com/a/answer/13369245)
* [Predefined permission settings](https://developers.google.com/workspace/chat/api/reference/rest/v1/spaces#Space.FIELDS.predefined_permission_settings) * [Predefined permission settings](https://developers.google.com/workspace/chat/api/reference/rest/v1/spaces#Space.FIELDS.predefined_permission_settings)
@@ -83,6 +88,8 @@ Google requires that you have a Chat Bot configured in order to use the Chat API
(gdoc <UserGoogleDoc>)| (gdoc <UserGoogleDoc>)|
(gcsdoc <StorageBucketObjectName>)) (gcsdoc <StorageBucketObjectName>))
<ChatEmojiName> ::= :[0-9a-z_-]+:
<ChatEmoji> ::= emojiname <ChatEmojiName> | customemojis/<String>
<ChatEvent> ::= spaces/<String>/spaceEvents/<String> <ChatEvent> ::= spaces/<String>/spaceEvents/<String>
<ChatMember> ::= spaces/<String>/members/<String> <ChatMember> ::= spaces/<String>/members/<String>
<ChatMemberList> ::= "<ChatMember>(,<ChatMember>)*" <ChatMemberList> ::= "<ChatMember>(,<ChatMember>)*"
@@ -896,6 +903,75 @@ filter 'start_time=\"2024-03-15T11:30:00-04:00\" AND event_types:\"google.worksp
filter 'start_time=\"2024-03-15T11:30:00+00:00\" AND end_time=\"2024-03-3100:00:00+00:00\" AND event_types:\"google.workspace.chat.message.v1.created\"' filter 'start_time=\"2024-03-15T11:30:00+00:00\" AND end_time=\"2024-03-3100:00:00+00:00\" AND event_types:\"google.workspace.chat.message.v1.created\"'
``` ```
## Manage Chat Emojis
### Create a Chat Emoji
```
gam <UserTypeEntity> create chatemoji <ChatEmojiName>
([drivedir|(sourcefolder <FilePath>)] [filename <FileNamePattern>])
[formatjson]
```
Emoji names must start and end with colons, must be lowercase and can only contain alphanumeric characters, hyphens, and underscores.
Hyphens and underscores should be used to separate words and cannot be used consecutively.
By default, the emoji file will be uploaded from the current working directory.
* `drivedir` - The emoji file will be uploaded from the directory specified by `drive_dir` in gam.cfg
* `sourcefolder <FilePath>` - The emoji file will be uploaded from `<FilePath>`
Specify the emoji file name; the following substitutions will be made:
* `#email#` and `#user#` will be replaced by the user's full email address
* `#username#` will be replaced by the local part of the user's email address
### Delete a Chat Emoji
Deletes the given Chat emoji.
```
gam <UserTypeEntity> delete chatemoji <Chatemoji>
```
## Display Chat Emojis
### Display a specific Chat emoji
```
gam <UserTypeEntity> info chatemoji <Chatemoji>
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
### Display information about all chat emojis
```
gam <UserTypeEntity> show chatemojis
[showcreatedby any|me|others]
[formatjson]
```
Select emojis to display:
* `showcreatedby any` - Display all emojis regardless of creator
* `showcreatedby ` - Display all emojis created by the user; this is the default
* `showcreatedby others` - Display all emojis not created by the user
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam <UserTypeEntity> print chatemojis [todrive <ToDriveAttribute>*]
[showcreatedby any|me|others]
[formatjson [quotechar <Character>]]
```
Select emojis to display:
* `showcreatedby any` - Display all emojis regardless of creator
* `showcreatedby ` - Display all emojis created by the user; this is the default
* `showcreatedby others` - Display all emojis not created by the user
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
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.
## Bulk Operations ## Bulk Operations
### Display information about all chat spaces for a collection of users ### Display information about all chat spaces for a collection of users
``` ```

View File

@@ -968,7 +968,8 @@ Display a list of file/folder names indented to show structure.
owners| owners|
parents| parents|
size| size|
trashed trashed|
webviewlink
<FileTreeFieldNameList> ::= "<FileTreeFieldName>(,<FileTreeFieldName>)*" <FileTreeFieldNameList> ::= "<FileTreeFieldName>(,<FileTreeFieldName>)*"
gam <UserTypeEntity> print filetree [todrive <ToDriveAttribute>*] gam <UserTypeEntity> print filetree [todrive <ToDriveAttribute>*]

View File

@@ -49,10 +49,19 @@ gam user user@domain.com update serviceaccount
``` ```
gam <UserTypeEntity> create form gam <UserTypeEntity> create form
title <String> [description <String>] [isquiz [Boolean>]] [<JSONData>] title <String> [description <String>] [isquiz [Boolean>]] [<JSONData>]
[ispublished [<Boolean>] isacceptingresponses [<Boolean>]]
[drivefilename <DriveFileName>] [<DriveFileParentAttribute>] [drivefilename <DriveFileName>] [<DriveFileParentAttribute>]
[(csv [todrive <ToDriveAttribute>*]) | returnidonly] [(csv [todrive <ToDriveAttribute>*]) | returnidonly]
``` ```
The valid combinations of `ispublished` and `isacceptingresponses` are:
* `ispublished true isacceptingresponses true`
* `ispublished true isacceptingresponses false`
* `ispublished false isacceptingresponses false`
* `ispublished false` - Sets `isacceptingresponses false`
* `isacceptingresponses false` - Sets `ispublished false`
* `isacceptingresponses true` - Sets `ispublished true`
`<JSONData>` is a list of form update requests. `<JSONData>` is a list of form update requests.
* See: https://developers.google.com/forms/api/reference/rest/v1/forms/batchUpdate * See: https://developers.google.com/forms/api/reference/rest/v1/forms/batchUpdate
@@ -79,15 +88,24 @@ Select forms with `<DriveFileEntity>`:
``` ```
gam <UserTypeEntity> update form <DriveFileEntity> gam <UserTypeEntity> update form <DriveFileEntity>
[title <String>] [description <String>] [isquiz [Boolean>]] [<JSONData>] [title <String>] [description <String>] [isquiz [Boolean>]] [<JSONData>]
[ispublished [<Boolean>] isacceptingresponses [<Boolean>]]
``` ```
The valid combinations of `ispublished` and `isacceptingresponses` are:
* `ispublished true isacceptingresponses true`
* `ispublished true isacceptingresponses false`
* `ispublished false isacceptingresponses false`
* `ispublished false` - Sets `isacceptingresponses false`
* `isacceptingresponses false` - Sets `ispublished false`
* `isacceptingresponses true` - Sets `ispublished true`
`<JSONData>` is a list of form update requests. `<JSONData>` is a list of form update requests.
* See: https://developers.google.com/forms/api/reference/rest/v1/forms/batchUpdate * See: https://developers.google.com/forms/api/reference/rest/v1/forms/batchUpdate
## Extended Example ## Extended Example
This example illustrates the use of JSN data to create and update forms This example illustrates the use of JSON data to create and update forms
concerning student classtoom attendance. concerning student classtoom attendance.
The form has two items: Absences and Notes. The form has two items: Absences and Notes.
In `Absences`, the teacher can check `All present.` or check individual student absences. In `Absences`, the teacher can check `All present.` or check individual student absences.

View File

@@ -72,6 +72,8 @@ This table and other suggestions came from:
<EmailAddress> ::= <String>@<DomainName> <EmailAddress> ::= <String>@<DomainName>
<UniqueID> ::= id:<String> <UniqueID> ::= id:<String>
<GroupItem> ::= <EmailAddress>|<UniqueID>|<String> <GroupItem> ::= <EmailAddress>|<UniqueID>|<String>
<LabelID> ::= <String>
<LabelIDList> ::= "<LabelID>(,<LabelID)*"
<LabelName> ::= <String> <LabelName> ::= <String>
<QueryGmail> ::= <String> See: https://support.google.com/mail/answer/7190 <QueryGmail> ::= <String> See: https://support.google.com/mail/answer/7190
<Time> ::= <Time> ::=
@@ -389,6 +391,7 @@ Your command line will have: `embedimage file1.jpg image1` embedimage file2.jpg
``` ```
gam <UserTypeEntity> archive messages <GroupItem> gam <UserTypeEntity> archive messages <GroupItem>
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
[labelids <LabelIDList>]
[quick|notquick] [doit] [max_to_archive <Number>])|(ids <MessageIDEntity>) [quick|notquick] [doit] [max_to_archive <Number>])|(ids <MessageIDEntity>)
[csv [todrive <ToDriveAttribute>*]] [csv [todrive <ToDriveAttribute>*]]
``` ```
@@ -400,6 +403,7 @@ Messages are archived to the group specified by `<GroupItem>`.
### Archive a selected set of messages ### Archive a selected set of messages
* `((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+` - Criteria to select messages * `((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+` - Criteria to select messages
* `labelids <LabelIDList>` - Select messages with labels that match all of the specified label IDs.
* `max_to_archive` - Limit the number of messages that will be archived; use a value of 0 for no limit * `max_to_archive` - Limit the number of messages that will be archived; use a value of 0 for no limit
* `doit` - No messages are archived unless you specify `doit`. By not specifying `doit`, you can preview the messages selected to verify that the results match your expectations. * `doit` - No messages are archived unless you specify `doit`. By not specifying `doit`, you can preview the messages selected to verify that the results match your expectations.
@@ -432,10 +436,14 @@ See below for message selection.
Export messages in EML format. Export messages in EML format.
``` ```
gam <UserTypeEntity> export message|messages gam <UserTypeEntity> export message|messages
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [max_to_export <Number>])|(ids <MessageIDEntity>) (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
[labelids <LabelIDList>]
[quick|notquick] [max_to_export <Number>])|(ids <MessageIDEntity>)
[targetfolder <FilePath>] [targetname <FileName>] [overwrite [<Boolean>]] [targetfolder <FilePath>] [targetname <FileName>] [overwrite [<Boolean>]]
gam <UserTypeEntity> export thread|threads gam <UserTypeEntity> export thread|threads
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ [quick|notquick] [max_to_export <Number>])|(ids <ThreadIDEntity>) (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
[labelids <LabelIDList>]
[quick|notquick] [max_to_export <Number>])|(ids <MessageIDEntity>)
[targetfolder <FilePath>] [targetname <FileName>] [overwrite [<Boolean>]] [targetfolder <FilePath>] [targetname <FileName>] [overwrite [<Boolean>]]
``` ```
@@ -459,10 +467,12 @@ See below for message selection.
``` ```
gam <UserTypeEntity> forward message|messages recipient|to <RecipientEntity> gam <UserTypeEntity> forward message|messages recipient|to <RecipientEntity>
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
[labelids <LabelIDList>]
[quick|notquick] [doit] [max_to_forward <Number>])|(ids <MessageIDEntity>) [quick|notquick] [doit] [max_to_forward <Number>])|(ids <MessageIDEntity>)
[subject <String>] [addorigfieldstosubject] [subject <String>] [addorigfieldstosubject]
gam <UserTypeEntity> forward thread|threads recipient|to <RecipientEntity> gam <UserTypeEntity> forward thread|threads recipient|to <RecipientEntity>
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
[labelids <LabelIDList>]
[quick|notquick] [doit] [max_to_forward <Number>])|(ids <ThreadIDEntity>) [quick|notquick] [doit] [max_to_forward <Number>])|(ids <ThreadIDEntity>)
[subject <String>] [addorigfieldstosubject] [subject <String>] [addorigfieldstosubject]
``` ```
@@ -482,23 +492,28 @@ See below for message selection.
``` ```
gam <UserTypeEntity> delete messages|threads gam <UserTypeEntity> delete messages|threads
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
[labelids <LabelIDList>]
[quick|notquick] [doit] [max_to_delete <Number>])|(ids <MessageIDEntity>) [quick|notquick] [doit] [max_to_delete <Number>])|(ids <MessageIDEntity>)
[csv [todrive <ToDriveAttribute>*]] [csv [todrive <ToDriveAttribute>*]]
gam <UserTypeEntity> modify messages|threads gam <UserTypeEntity> modify messages|threads
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
[labelids <LabelIDList>]
[quick|notquick] [doit] [max_to_modify <Number>])|(ids <MessageIDEntity>) [quick|notquick] [doit] [max_to_modify <Number>])|(ids <MessageIDEntity>)
((addlabel <LabelName>)|(removelabel <LabelName>))+ ((addlabel <LabelName>)|(removelabel <LabelName>))+
[csv [todrive <ToDriveAttribute>*]] [csv [todrive <ToDriveAttribute>*]]
gam <UserTypeEntity> spam messages|threads gam <UserTypeEntity> spam messages|threads
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
[labelids <LabelIDList>]
[quick|notquick] [doit] [max_to_spam <Number>])|(ids <MessageIDEntity>) [quick|notquick] [doit] [max_to_spam <Number>])|(ids <MessageIDEntity>)
[csv [todrive <ToDriveAttribute>*]] [csv [todrive <ToDriveAttribute>*]]
gam <UserTypeEntity> trash messages|threads gam <UserTypeEntity> trash messages|threads
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
[labelids <LabelIDList>]
[quick|notquick] [doit] [max_to_trash <Number>])|(ids <MessageIDEntity>) [quick|notquick] [doit] [max_to_trash <Number>])|(ids <MessageIDEntity>)
[csv [todrive <ToDriveAttribute>*]] [csv [todrive <ToDriveAttribute>*]]
gam <UserTypeEntity> untrash messages|threads gam <UserTypeEntity> untrash messages|threads
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+ (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+
[labelids <LabelIDList>]
[quick|notquick] [doit] [max_to_untrash <Number>])|(ids <MessageIDEntity>) [quick|notquick] [doit] [max_to_untrash <Number>])|(ids <MessageIDEntity>)
[csv [todrive <ToDriveAttribute>*]] [csv [todrive <ToDriveAttribute>*]]
``` ```
@@ -522,6 +537,7 @@ user@domain.com,18e9fc58c5491f4c,Deleted,
### Manage a selected set of messages ### Manage a selected set of messages
* `((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+` - Criteria to select messages * `((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+` - Criteria to select messages
* `labelids <LabelIDList>` - Select messages with labels that match all of the specified label IDs.
* `max_to_xxx` - Limit the number of messages that will be processed; use a value of 0 for no limit * `max_to_xxx` - Limit the number of messages that will be processed; use a value of 0 for no limit
* `doit` - No messages are processed unless you specify `doit`. By not specifying `doit`, you can preview the messages selected to verify that the results match your expectations. * `doit` - No messages are processed unless you specify `doit`. By not specifying `doit`, you can preview the messages selected to verify that the results match your expectations.
@@ -570,6 +586,7 @@ gam config auto_batch_min 1 groups_inde EastOffice delete message query "rfc822m
``` ```
gam <UserTypeEntity> show messages|threads gam <UserTypeEntity> show messages|threads
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])* (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])*
[labelids <LabelIDList>]
[quick|notquick] [max_to_show <Number>] [includespamtrash])|(ids <MessageIDEntity>) [quick|notquick] [max_to_show <Number>] [includespamtrash])|(ids <MessageIDEntity>)
[labelmatchpattern <REMatchPattern>] [sendermatchpattern <REMatchPattern>] [labelmatchpattern <REMatchPattern>] [sendermatchpattern <REMatchPattern>]
[countsonly|positivecountsonly] [useronly] [countsonly|positivecountsonly] [useronly]
@@ -581,6 +598,7 @@ gam <UserTypeEntity> show messages|threads
[targetfolder <FilePath>] [overwrite [<Boolean>]] [targetfolder <FilePath>] [overwrite [<Boolean>]]
gam <UserTypeEntity> print messages|threads [todrive <ToDriveAttribute>*] gam <UserTypeEntity> print messages|threads [todrive <ToDriveAttribute>*]
(((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])* (((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])*
[labelids <LabelIDList>]
[quick|notquick] [max_to_print <Number>] [includespamtrash])|(ids <MessageIDEntity>) [quick|notquick] [max_to_print <Number>] [includespamtrash])|(ids <MessageIDEntity>)
[labelmatchpattern <REMatchPattern>] [sendermatchpattern <REMatchPattern>] [labelmatchpattern <REMatchPattern>] [sendermatchpattern <REMatchPattern>]
[countsonly|positivecountsonly] [useronly] [countsonly|positivecountsonly] [useronly]
@@ -607,6 +625,7 @@ gam user user@domain.com print|show threads maxmessagesperthread 1
## Display a selected set of messages ## Display a selected set of messages
* `((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+` - Criteria to select messages * `((query <QueryGmail> [querytime<String> <Date>]*) (matchlabel <LabelName>) [or|and])+` - Criteria to select messages
* `labelids <LabelIDList>` - Select messages with labels that match all of the specified label IDs.
* `max_to_xxx` - Limit the number of messages that will be displayed * `max_to_xxx` - Limit the number of messages that will be displayed
* `includespamtrash` - Include messages in the Spam and Trash folders * `includespamtrash` - Include messages in the Spam and Trash folders
* `labelmatchpattern <REMatchPattern>` - Only display messages with some label that matches `<REMatchPattern>` * `labelmatchpattern <REMatchPattern>` - Only display messages with some label that matches `<REMatchPattern>`

View File

@@ -108,7 +108,7 @@ Paul shall send emails from the marketing email address with the name Paul from
``` gam user paul add sendas marketing@example.com "Paul from Example" replyto paul``` ``` gam user paul add sendas marketing@example.com "Paul from Example" replyto paul```
## Display sendas ## Display sendas
### Display the information as an indented list of keys and values. ### Display the sendas information as an indented list of keys and values.
``` ```
gam <UserTypeEntity> info sendas <EmailAddressEntity> [compact|format|html] gam <UserTypeEntity> info sendas <EmailAddressEntity> [compact|format|html]
gam <UserTypeEntity> show sendas [compact|format|html] gam <UserTypeEntity> show sendas [compact|format|html]
@@ -126,7 +126,19 @@ By default, all sendas addresses are shown, use these options to limit the displ
Use the `verifyonly` option to display `True` or `False` in the signature field based on whether the signature is non-blank. Use the `verifyonly` option to display `True` or `False` in the signature field based on whether the signature is non-blank.
### Display the information in CSV form. To capture a signature for use as input to GAM, do the following.
```
gam redirect stdout ./signature.html user user@domain.com show sendas compact
```
Edit signature.html and remove the following data leaving just the HTML.
```
SendAs Address: <user@domain.com>
IsPrimary: True
Default: True
Signature:
```
### Display the sendas information in CSV form.
``` ```
gam <UserTypeEntity> print sendas [compact] gam <UserTypeEntity> print sendas [compact]
[primary|default] [verifyonly] [todrive <ToDriveAttribute>*] [primary|default] [verifyonly] [todrive <ToDriveAttribute>*]
@@ -170,7 +182,7 @@ email address signature rather than the alias signature to be set.
If you have a current default signature, the API will update that, but if you delete it, it seems that the API will not over-write any of the other signatures, but instead add a new signature called `My signature`. If you rename that signature, the API will keep on updating that same signature, and not touch the other signatures. If you have a current default signature, the API will update that, but if you delete it, it seems that the API will not over-write any of the other signatures, but instead add a new signature called `My signature`. If you rename that signature, the API will keep on updating that same signature, and not touch the other signatures.
## Display signature ## Display signature
### Display the information as an indented list of keys and values. ### Display the signature as an indented list of keys and values.
``` ```
gam <UserTypeEntity> show signature|sig [compact|format|html] gam <UserTypeEntity> show signature|sig [compact|format|html]
[primary|default] [verifyonly] [primary|default] [verifyonly]
@@ -187,7 +199,19 @@ By default, the signature for `<UserTypeEntity>` is displayed, use these options
Use the `verifyonly` option to display `True` or `False` in the signature field based on whether the signature is non-blank. Use the `verifyonly` option to display `True` or `False` in the signature field based on whether the signature is non-blank.
### Display the information in CSV form. To capture a signature for use as input to GAM, do the following.
```
gam redirect stdout ./signature.html user user@domain.com show signature compact
```
Edit signature.html and remove the following data leaving just the HTML.
```
SendAs Address: <user@domain.com>
IsPrimary: True
Default: True
Signature:
```
### Display the signature in CSV form.
``` ```
gam <UserTypeEntity> print signature [compact] gam <UserTypeEntity> print signature [compact]
[primary|default] [verifyonly] [todrive <ToDriveAttribute>*] [primary|default] [verifyonly] [todrive <ToDriveAttribute>*]

View File

@@ -3,7 +3,7 @@
Print the current version of Gam with details Print the current version of Gam with details
``` ```
gam version gam version
GAM 7.09.04 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.10.04 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.5 64-bit final Python 3.13.5 64-bit final
MacOS Sequoia 15.5 x86_64 MacOS Sequoia 15.5 x86_64
@@ -15,7 +15,7 @@ Time: 2023-06-02T21:10:00-07:00
Print the current version of Gam with details and time offset information Print the current version of Gam with details and time offset information
``` ```
gam version timeoffset gam version timeoffset
GAM 7.09.04 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.10.04 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.5 64-bit final Python 3.13.5 64-bit final
MacOS Sequoia 15.5 x86_64 MacOS Sequoia 15.5 x86_64
@@ -27,7 +27,7 @@ Your system time differs from www.googleapis.com by less than 1 second
Print the current version of Gam with extended details and SSL information Print the current version of Gam with extended details and SSL information
``` ```
gam version extended gam version extended
GAM 7.09.04 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.10.04 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.5 64-bit final Python 3.13.5 64-bit final
MacOS Sequoia 15.5 x86_64 MacOS Sequoia 15.5 x86_64
@@ -64,7 +64,7 @@ MacOS High Sierra 10.13.6 x86_64
Path: /Users/Admin/bin/gam7 Path: /Users/Admin/bin/gam7
Version Check: Version Check:
Current: 5.35.08 Current: 5.35.08
Latest: 7.09.04 Latest: 7.10.04
echo $? echo $?
1 1
``` ```
@@ -72,7 +72,7 @@ echo $?
Print the current version number without details Print the current version number without details
``` ```
gam version simple gam version simple
7.09.04 7.10.04
``` ```
In Linux/MacOS you can do: In Linux/MacOS you can do:
``` ```
@@ -82,7 +82,7 @@ echo $VER
Print the current version of Gam and address of this Wiki Print the current version of Gam and address of this Wiki
``` ```
gam help gam help
GAM 7.09.04 - https://github.com/GAM-team/GAM GAM 7.10.04 - https://github.com/GAM-team/GAM
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.5 64-bit final Python 3.13.5 64-bit final
MacOS Sequoia 15.5 x86_64 MacOS Sequoia 15.5 x86_64