Compare commits

...

65 Commits

Author SHA1 Message Date
Ross Scroggs
b4677585bb Added option types <AdminAssigneeTypeList> to gam print|show admins 2025-10-02 16:47:40 -07:00
Ross Scroggs
3a1437872c Update Administrators.md
Some checks failed
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14-dev freethread, 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-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-10-02 13:33:48 -07:00
Ross Scroggs
602dce2f5a Update Administrators.md 2025-10-02 13:26:42 -07:00
Ross Scroggs
8ce930f01b Added option recursive to gam print|show admins 2025-10-02 13:24:19 -07:00
Ross Scroggs
9631882be0 Added option recursive to gam print|show admins 2025-10-02 12:27:06 -07:00
Jay Lee
32d2858e4b Update build.yml 2025-10-02 13:16:14 -04:00
Jay Lee
98370925e7 actions: fix caching excludes 2025-10-02 12:35:49 -04:00
Jay Lee
1ef5d030f6 actions: exclude .git folder from caching, rebuild
Some checks failed
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14-dev freethread, 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-certs (push) Has been cancelled
2025-10-02 09:57:58 -04:00
Jay Lee
d50b5fb61e actions: update dependent action versions 2025-10-02 09:25:20 -04:00
Jay Lee
e070e92be2 Update pypi.yml 2025-10-02 09:15:29 -04:00
Ross Scroggs
b3b6fff2f1 Added option addcsvdata <FieldName> <String> to print events
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
2025-10-01 18:36:25 -07:00
Ross Scroggs
fea94fcc1c Added option addcsvdata <FieldName> <String> to 1print events`
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14-dev freethread, 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-certs (push) Has been cancelled
2025-10-01 16:03:32 -07:00
Ross Scroggs
a0cd228110 Merge branch 'main' of https://github.com/GAM-team/GAM 2025-10-01 12:52:06 -07:00
Jay Lee
acfcd8b723 actions: do export on OU level also 2025-10-01 13:42:54 -04:00
Jay Lee
a26494e5c6 Update build.yml 2025-10-01 13:26:54 -04:00
Jay Lee
5605e5d1b6 actions: place vault hold on OU not user to try to avoid license delays 2025-10-01 13:16:35 -04:00
Ross Scroggs
e0fdac6e17 Merge branch 'main' of https://github.com/GAM-team/GAM 2025-10-01 10:07:06 -07:00
Ross Scroggs
53dc8e3265 Update Domain-SharedContacts.md 2025-10-01 10:06:55 -07:00
Jay Lee
993a0b403e Update build.yml 2025-10-01 11:42:25 -04:00
Jay Lee
2d7d118d32 actions: rebuild for OpenSSL 3.6.0
Some checks failed
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14-dev freethread, 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-certs (push) Has been cancelled
2025-10-01 08:30:58 -04:00
Ross Scroggs
f2bc704fd6 Upgraded to OpenSSL 3.5.4.
Some checks failed
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14-dev freethread, 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-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-09-30 18:55:52 -07:00
Jay Lee
46e0c85308 Update build.yml 2025-09-30 20:11:46 -04:00
Jay Lee
9221d075fe Update build.yml 2025-09-30 20:10:11 -04:00
Jay Lee
12b84a5fcf Update build.yml 2025-09-30 19:47:26 -04:00
Jay Lee
6d411972ac Update build.yml 2025-09-30 19:45:23 -04:00
Jay Lee
d665a66d3e Update build.yml 2025-09-30 19:43:04 -04:00
Jay Lee
b2a340d99d Update build.yml 2025-09-30 19:34:36 -04:00
Jay Lee
c76164fbef actions: re-enable some python version testing 2025-09-30 19:29:02 -04:00
Jay Lee
3d22891052 Update build.yml 2025-09-30 19:00:50 -04:00
Jay Lee
48de06613f Update build.yml 2025-09-30 18:50:05 -04:00
Ross Scroggs
4d1879a9a8 Upgraded to OpenSSL 3.5.4.
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 x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, 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, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (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-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-09-30 15:14:40 -07:00
Jay Lee
454caa5a76 [no ci] actions: cleanup some debug output and unnecessary commands 2025-09-30 17:27:09 -04:00
Jay Lee
12ffa7e823 Update build.yml 2025-09-30 16:35:26 -04:00
Jay Lee
8fc41cbc64 Update build.yml 2025-09-30 16:32:01 -04:00
Jay Lee
dd16c29ee7 Update build.yml 2025-09-30 16:22:20 -04:00
Jay Lee
1a24b4c855 Update build.yml 2025-09-30 16:10:14 -04:00
Jay Lee
f9dfc7d094 Update build.yml 2025-09-30 16:00:51 -04:00
Jay Lee
bc64a292c3 Update build.yml 2025-09-30 15:41:31 -04:00
Ross Scroggs
524ef0df55 Merge branch 'main' of https://github.com/GAM-team/GAM 2025-09-30 11:02:41 -07:00
Ross Scroggs
38f7f39b44 Version info updates 2025-09-30 11:02:35 -07:00
Jay Lee
183e40ef4e Update build.yml 2025-09-30 13:22:53 -04:00
Jay Lee
ba43c4ea5f Update build.yml 2025-09-30 13:17:06 -04:00
Jay Lee
70c88dacf3 Update build.yml 2025-09-30 13:05:30 -04:00
Jay Lee
cc883b6bb7 Update build.yml 2025-09-30 12:47:17 -04:00
Jay Lee
4c320110b3 Update build.yml 2025-09-30 11:40:58 -04:00
Jay Lee
fe7c46e04d Update build.yml 2025-09-30 11:37:05 -04:00
Jay Lee
5b1c3a3a46 Update build.yml 2025-09-30 11:34:05 -04:00
Jay Lee
ce728a991f Update build.yml 2025-09-30 11:32:19 -04:00
Jay Lee
502bda4fe9 Update build.yml 2025-09-30 11:27:39 -04:00
Jay Lee
3f3d882c74 Update build.yml 2025-09-30 11:21:48 -04:00
Jay Lee
a1948eb3ca Update build.yml 2025-09-30 11:16:06 -04:00
Jay Lee
f0fb6336d1 Update build.yml 2025-09-30 11:04:55 -04:00
Jay Lee
71e5ef2399 Update build.yml 2025-09-30 11:01:46 -04:00
Jay Lee
9d9698a669 actions: use a venv for build and test 2025-09-30 10:59:02 -04:00
Jay Lee
eeb180f1f2 actions: rebuild for OpenSSL 3.5.4
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 x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, 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, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (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-certs (push) Has been cancelled
2025-09-30 10:13:33 -04:00
Ross Scroggs
6079ab20b3 Added option oneitemperrow to 'gam print course-materials|course-work`
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 x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, 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, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (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-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-09-29 20:52:00 -07:00
Ross Scroggs
6189ca92ab Added option oneitemperrow to 'gam print course-materials|course-work` 2025-09-29 19:23:50 -07:00
Ross Scroggs
33b60c4b14 Added option oneitemperrow to 'gam print course-materials|course-work` 2025-09-29 19:18:57 -07:00
Ross Scroggs
0c5f747c36 Added option oneitemperrow to 'gam print course-materials|course-work` 2025-09-29 17:13:39 -07:00
Ross Scroggs
826619857c Bump version 2025-09-29 17:09:41 -07:00
Ross Scroggs
9a2880e411 Added chat_max_results variable to gam.cfg.
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 x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, 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, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (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-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-09-29 13:33:20 -07:00
Ross Scroggs
95caeaba5e Added chat_max_results variable to gam.cfg. 2025-09-29 12:07:13 -07:00
Ross Scroggs
d8ad1b27a4 Update Reports.md 2025-09-29 10:25:55 -07:00
Ross Scroggs
fefeae7c60 Update Vault-Takeout.md 2025-09-29 07:23:45 -07:00
Ross Scroggs
65f7b82d53 Vault query updates
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 x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, 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, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (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-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-09-28 20:26:46 -07:00
22 changed files with 565 additions and 206 deletions

View File

@@ -41,78 +41,101 @@ jobs:
include: include:
- os: ubuntu-22.04 - os: ubuntu-22.04
jid: 1 jid: 1
freethreaded: false
goal: build goal: build
name: Build Intel Ubuntu Jammy name: Build Intel Ubuntu Jammy
- os: ubuntu-24.04 - os: ubuntu-24.04
jid: 2 jid: 2
freethreaded: false
goal: build goal: build
name: Build Intel Ubuntu Noble name: Build Intel Ubuntu Noble
- os: ubuntu-24.04-arm - os: ubuntu-24.04-arm
jid: 3 jid: 3
freethreaded: false
goal: build goal: build
name: Build Arm Ubuntu Noble name: Build Arm Ubuntu Noble
- os: ubuntu-22.04-arm - os: ubuntu-22.04-arm
jid: 4 jid: 4
freethreaded: false
goal: build goal: build
name: Build Arm Ubuntu Jammy name: Build Arm Ubuntu Jammy
- os: ubuntu-22.04 - os: ubuntu-22.04
jid: 5 jid: 5
freethreaded: false
goal: build goal: build
staticx: yes staticx: yes
name: Build Intel StaticX Legacy name: Build Intel StaticX Legacy
- os: ubuntu-22.04-arm - os: ubuntu-22.04-arm
jid: 6 jid: 6
freethreaded: false
goal: build goal: build
staticx: yes staticx: yes
name: Build Arm StaticX Legacy name: Build Arm StaticX Legacy
- os: macos-13 - os: macos-13
jid: 7 jid: 7
freethreaded: false
goal: build goal: build
name: Build Intel MacOS name: Build Intel MacOS
- os: macos-14 - os: macos-14
jid: 8 jid: 8
freethreaded: false
goal: build goal: build
name: Build Arm MacOS 14 name: Build Arm MacOS 14
- os: macos-15 - os: macos-15
jid: 9 jid: 9
freethreaded: false
goal: build goal: build
name: Build Arm MacOS 15 name: Build Arm MacOS 15
- os: macos-15-intel - os: macos-15-intel
jid: 10 jid: 10
freethreaded: false
goal: build goal: build
name: Build x86_64 macOS 15 name: Build x86_64 macOS 15
- os: macos-26 - os: macos-26
jid: 11 jid: 11
freethreaded: false
goal: build goal: build
name: Build Arm MacOS 26 name: Build Arm MacOS 26
- os: windows-2025 - os: windows-2025
jid: 12 jid: 12
freethreaded: false
goal: build goal: build
name: Build Intel Windows name: Build Intel Windows
- os: windows-11-arm - os: windows-11-arm
jid: 13 jid: 13
freethreaded: false
goal: build goal: build
name: Build Arm Windows name: Build Arm Windows
- os: ubuntu-24.04 - os: ubuntu-24.04
goal: test goal: test
python: "3.10" python: "3.10"
freethreaded: false
jid: 14 jid: 14
name: Test Python 3.10 name: Test Python 3.10
- os: ubuntu-24.04 - os: ubuntu-24.04
goal: test goal: test
python: "3.11" python: "3.11"
freethreaded: false
jid: 15 jid: 15
name: Test Python 3.11 name: Test Python 3.11
#- os: ubuntu-24.04 - os: ubuntu-24.04
# goal: test goal: test
# python: "3.12" python: "3.12"
# jid: 16 freethreaded: false
# name: Test Python 3.12 jid: 16
#- os: ubuntu-24.04 name: Test Python 3.12
# goal: test - os: ubuntu-24.04
# python: "3.14-dev" goal: test
# jid: 16 python: "3.14-dev"
# name: Test Python 3.14-dev freethreaded: false
jid: 17
name: Test Python 3.14-dev
- os: ubuntu-24.04
goal: test
python: "3.14-dev"
freethreaded: true
jid: 18
name: Test Python 3.14-dev freethread
steps: steps:
@@ -135,7 +158,7 @@ jobs:
with: with:
path: | path: |
cache.tar.xz cache.tar.xz
key: gam-${{ matrix.jid }}-20250922 key: gam-${{ matrix.jid }}-20251002
- name: Untar Cache archive - name: Untar Cache archive
if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit == 'true' if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit == 'true'
@@ -145,17 +168,19 @@ jobs:
- name: Use pre-compiled Python for testing - name: Use pre-compiled Python for testing
if: matrix.python != '' if: matrix.python != ''
uses: actions/setup-python@3d1e2d2ca0a067f27da6fec484fce7f5256def85 # v5.6.0 uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
with: with:
python-version: ${{ matrix.python }} python-version: ${{ matrix.python }}
allow-prereleases: true allow-prereleases: true
check-latest: true check-latest: true
freethreaded: ${{ matrix.freethreaded }}
- name: common variables for all runs - name: common variables for all runs
env: env:
JID: ${{ matrix.jid }} JID: ${{ matrix.jid }}
ACTIONS_CACHE: ${{ steps.cache-python-ssl.outputs.cache-hit }} ACTIONS_CACHE: ${{ steps.cache-python-ssl.outputs.cache-hit }}
ACTIONS_GOAL: ${{ matrix.goal }} ACTIONS_GOAL: ${{ matrix.goal }}
freethreaded: ${{ matrix.freethreaded }}
run: | run: |
case $RUNNER_ARCH in case $RUNNER_ARCH in
X64) X64)
@@ -169,6 +194,12 @@ jobs:
;; ;;
esac esac
echo "JID=${JID}" >> $GITHUB_ENV echo "JID=${JID}" >> $GITHUB_ENV
echo "freethreaded=${freethreaded}" >> $GITHUB_ENV
if "$freethreaded"; then
# Hush some warnings while we test
export PYTHON_GIL=0
echo "PYTHON_GIL=${PYTHON_GIL}" >> $GITHUB_ENV
fi
echo "ACTIONS_CACHE=${ACTIONS_CACHE}" >> $GITHUB_ENV echo "ACTIONS_CACHE=${ACTIONS_CACHE}" >> $GITHUB_ENV
echo "ACTIONS_GOAL=${ACTIONS_GOAL}" >> $GITHUB_ENV echo "ACTIONS_GOAL=${ACTIONS_GOAL}" >> $GITHUB_ENV
curl_version=$(curl --version | head -n 1 | awk '{ print $2 }') curl_version=$(curl --version | head -n 1 | awk '{ print $2 }')
@@ -194,13 +225,9 @@ jobs:
if: matrix.goal == 'test' if: matrix.goal == 'test'
run: | run: |
export PYTHON=$(which python3) export PYTHON=$(which python3)
export PIP=$(which pip3)
export gam="${PYTHON} -m gam"
export gampath="$(readlink -e .)/gam" export gampath="$(readlink -e .)/gam"
echo -e "PYTHON: ${PYTHON}\nPIP: ${PIP}\gam: ${gam}\ngampath: ${gampath}" echo -e "PYTHON: ${PYTHON}\ngam: ${gam}\ngampath: ${gampath}"
echo "PYTHON=${PYTHON}" >> $GITHUB_ENV echo "PYTHON=${PYTHON}" >> $GITHUB_ENV
echo "PIP=${PIP}" >> $GITHUB_ENV
echo "gam=${gam}" >> $GITHUB_ENV
echo "gampath=${gampath}" >> $GITHUB_ENV echo "gampath=${gampath}" >> $GITHUB_ENV
- name: Install necessary Github-hosted Linux packages - name: Install necessary Github-hosted Linux packages
@@ -261,14 +288,15 @@ jobs:
MAKEOPT="" MAKEOPT=""
PERL="c:\strawberry\perl\bin\perl.exe" PERL="c:\strawberry\perl\bin\perl.exe"
if [[ "$RUNNER_ARCH" == "ARM64" ]]; then if [[ "$RUNNER_ARCH" == "ARM64" ]]; then
PYEXTERNALS_PATH="arm64" PYEXTERNALS_ARCH="arm64"
WIX_ARCH="arm64" WIX_ARCH="arm64"
elif [[ "$RUNNER_ARCH" == "X64" ]]; then elif [[ "$RUNNER_ARCH" == "X64" ]]; then
PYEXTERNALS_PATH="amd64" PYEXTERNALS_ARCH="amd64"
WIX_ARCH="x64" WIX_ARCH="x64"
fi fi
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${PYTHON_SOURCE_PATH}/PCbuild/${PYEXTERNALS_PATH}" PYEXTERNALS_PATH=$(cygpath -u "${PYTHON_SOURCE_PATH}/PCbuild/${PYEXTERNALS_ARCH}")
echo "PYTHON=${PYTHON_SOURCE_PATH}/PCbuild/${PYEXTERNALS_PATH}/python.exe" >> $GITHUB_ENV LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${PYEXTERNALS_PATH}"
echo "PYTHON=${PYTHON_SOURCE_PATH}/PCbuild/${PYEXTERNALS_ARCH}/python.exe" >> $GITHUB_ENV
echo "WIX_ARCH=${WIX_ARCH}" >> $GITHUB_ENV echo "WIX_ARCH=${WIX_ARCH}" >> $GITHUB_ENV
fi fi
echo "We'll run make with: ${MAKEOPT}" echo "We'll run make with: ${MAKEOPT}"
@@ -457,15 +485,36 @@ jobs:
"$PYTHON" get-pip.py "$PYTHON" get-pip.py
"$PYTHON" -m pip install --upgrade pip "$PYTHON" -m pip install --upgrade pip
"$PYTHON" -m pip install --upgrade wheel "$PYTHON" -m pip install --upgrade wheel
"$PYTHON" -m pip install setuptools "$PYTHON" -m pip install --upgrade setuptools
"$PYTHON" -m pip install --upgrade importlib-metadata "$PYTHON" -m pip install --upgrade importlib-metadata
"$PYTHON" -m pip install --upgrade setuptools-scm "$PYTHON" -m pip install --upgrade setuptools-scm
"$PYTHON" -m pip list "$PYTHON" -m pip list
- name: Create and use Python venv
run: |
cd "$GITHUB_WORKSPACE"
"$PYTHON" -m venv venv
if [[ "$RUNNER_OS" == "Windows" ]]; then
# hack till pyscard has a wheel for win arm64
"$PYTHON" -m pip install --upgrade --force-reinstall pyscard
export PYTHON="${GITHUB_WORKSPACE}/venv/scripts/python.exe"
else
export PYTHON="${GITHUB_WORKSPACE}/venv/bin/python3"
fi
echo "PYTHON=${PYTHON}" >> $GITHUB_ENV
if [[ "$ACTIONS_GOAL" == "test" ]]; then
export gam="${PYTHON} gam.py"
echo "gam=${gam}" >> $GITHUB_ENV
fi
- name: Install pip requirements - name: Install pip requirements
run: | run: |
echo "before anything..." echo "before anything..."
"$PYTHON" -m pip list "$PYTHON" -m pip list
echo "--info--"
"$PYTHON" -m pip cache info
echo "--list--"
"$PYTHON" -m pip cache list
"$PYTHON" -m pip install --upgrade ..[yubikey] "$PYTHON" -m pip install --upgrade ..[yubikey]
echo "after everything..." echo "after everything..."
"$PYTHON" -m pip list "$PYTHON" -m pip list
@@ -894,11 +943,11 @@ jobs:
$gam calendar $gam_user printevents after -0d $gam calendar $gam_user printevents after -0d
$gam config enable_dasa false save $gam config enable_dasa false save
matterid=uid:$($gam create vaultmatter name "GHA matter $newbase" description "test matter" returnidonly) matterid=uid:$($gam create vaultmatter name "GHA matter $newbase" description "test matter" returnidonly)
$gam create vaulthold matter $matterid name "GHA hold $newbase" corpus mail accounts $newuser $gam create vaulthold matter $matterid name "GHA hold ${newbase}" corpus mail ou "$newou"
$gam print vaultmatters matterstate open $gam print vaultmatters matterstate open
$gam print vaultholds matter $matterid $gam print vaultholds matter $matterid
$gam print vaultcount matter $matterid corpus mail everyone todrive tdnobrowser $gam print vaultcount matter $matterid corpus mail everyone todrive tdnobrowser
$gam create vaultexport matter $matterid name "GHA export $newbase" corpus mail accounts $newuser $gam create vaultexport matter $matterid name "GHA export $newbase" corpus mail ou "$newou"
$gam print exports matter $matterid | $gam csv - gam info export $matterid id:~~id~~ $gam print exports matter $matterid | $gam csv - gam info export $matterid id:~~id~~
$gam config enable_dasa true save $gam config enable_dasa true save
$gam csv sample.csv gam user ~email add calendar id:$newresource $gam csv sample.csv gam user ~email add calendar id:$newresource
@@ -978,7 +1027,8 @@ jobs:
else else
tar_folders="bin/" tar_folders="bin/"
fi fi
tar cJvvf cache.tar.xz $tar_folders echo '.git*' > ./excludes.txt
tar cJvvf cache.tar.xz --exclude-from=excludes.txt $tar_folders
merge: merge:
if: (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') if: (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
@@ -1028,7 +1078,7 @@ jobs:
echo "dateversion=${dateversion}" >> $GITHUB_OUTPUT echo "dateversion=${dateversion}" >> $GITHUB_OUTPUT
- name: Publish draft release - name: Publish draft release
uses: softprops/action-gh-release@fbadcc90e88ecface60a0a0d123795b784ceb239 # v2.3.2 uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836 # v2.3.3
with: with:
draft: true draft: true
prerelease: false prerelease: false

View File

@@ -30,6 +30,6 @@ jobs:
python -m build python -m build
- name: Publish package distributions to PyPI - name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1 uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
with: with:
attestation: true attestation: true

View File

@@ -368,6 +368,7 @@ If an item contains spaces, it should be surrounded by ".
## Named items ## Named items
<AccessToken> ::= <String> <AccessToken> ::= <String>
<AdminAssigneeType> ::= group|user|serviceaccount|unknown
<AlertID> ::= <String> <AlertID> ::= <String>
<APIScopeURL> ::= <String> <APIScopeURL> ::= <String>
<APPID> ::= <String> <APPID> ::= <String>
@@ -691,6 +692,7 @@ If an item contains spaces, it should be surrounded by ".
## Lists of basic items ## Lists of basic items
<AdminAssigneeTypeList> ::= "<AdminAssigneeType>(,<AdminAssigneeType>)*"
<APIScopeURLList> ::= "<APIScopeURL>(,<APIScopeURL>)*" <APIScopeURLList> ::= "<APIScopeURL>(,<APIScopeURL>)*"
<ASPIDList> ::= "<ASPID>(,<ASPID>)*" <ASPIDList> ::= "<ASPID>(,<ASPID>)*"
<AssetTagList> ::= "<AssetTag>(,<AssetTag>)*" <AssetTagList> ::= "<AssetTag>(,<AssetTag>)*"
@@ -1552,10 +1554,13 @@ gam create|add admin <EmailAddress>|<UniqueID> <RoleItem> customer|(org_unit <Or
gam delete admin <RoleAssignmentId> gam delete admin <RoleAssignmentId>
gam print admins [todrive <ToDriveAttribute>*] gam print admins [todrive <ToDriveAttribute>*]
[user|group <EmailAddress>|<UniqueID>] [role <RoleItem>] [condition] [user|group <EmailAddress>|<UniqueID>] [role <RoleItem>]
[privileges] [oneitemperrow] [types <AdminAssigneeTypeList>]
[recursive] [condition] [privileges] [oneitemperrow]
gam show admins gam show admins
[user|group <EmailAddress>|<UniqueID>] [role <RoleItem>] [condition] [privileges] [user|group <EmailAddress>|<UniqueID>] [role <RoleItem>]
[types <AdminAssigneeTypeList>]
[recursive] [condition] [privileges]
# Alert Center # Alert Center
@@ -1932,12 +1937,12 @@ gam calendar|calendars <CalendarEntity> info events [<EventEntity>] [maxinstance
[formatjson] [formatjson]
gam calendar|calendars <CalendarEntity> show events [<EventEntity>] <EventDisplayProperty>* gam calendar|calendars <CalendarEntity> show events [<EventEntity>] <EventDisplayProperty>*
[fields <EventFieldNameList>] [showdayofweek] [fields <EventFieldNameList>] [showdayofweek]
[countsonly] [countsonly|formatjson]
[formatjson]
gam calendar|calendars <CalendarEntity> print events [<EventEntity>] <EventDisplayProperty>* gam calendar|calendars <CalendarEntity> print events [<EventEntity>] <EventDisplayProperty>*
[fields <EventFieldNameList>] [showdayofweek] [fields <EventFieldNameList>] [showdayofweek]
[countsonly [eventrowfilter]] (addcsvdata <FieldName> <String>)*
[formatjson [quotechar <Character>]] [todrive <ToDriveAttribute>*] [eventrowfilter]
[countsonly|(formatjson [quotechar <Character>])] [todrive <ToDriveAttribute>*]
gam calendar <CalendarEntity> addevent <EventAttribute>+ [<EventNotificationAttribute>] gam calendar <CalendarEntity> addevent <EventAttribute>+ [<EventNotificationAttribute>]
[showdayofweek] [showdayofweek]
@@ -3383,6 +3388,7 @@ gam print course-materials [todrive <ToDriveAttribute>*]
(orderby <CourseMaterialOrderByFieldName> [ascending|descending])*) (orderby <CourseMaterialOrderByFieldName> [ascending|descending])*)
[showcreatoremails|creatoremail] [showtopicnames] [fields <CourseMaterialFieldNameList>] [showcreatoremails|creatoremail] [showtopicnames] [fields <CourseMaterialFieldNameList>]
[timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
[oneitemperrow]
[countsonly] [formatjson [quotechar <Character>]] [countsonly] [formatjson [quotechar <Character>]]
gam print course-submissions [todrive <ToDriveAttribute>*] gam print course-submissions [todrive <ToDriveAttribute>*]
(course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] states <CourseStateList>]) (course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] states <CourseStateList>])
@@ -3404,6 +3410,7 @@ gam print course-works [todrive <ToDriveAttribute>*]
[showcreatoremails|creatoremail] [showtopicnames] [fields <CourseWorkFieldNameList>] [showcreatoremails|creatoremail] [showtopicnames] [fields <CourseWorkFieldNameList>]
[showstudentsaslist [<Boolean>]] [delimiter <Character>] [showstudentsaslist [<Boolean>]] [delimiter <Character>]
[timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
[oneitemperrow]
[countsonly] [formatjson [quotechar <Character>]] [countsonly] [formatjson [quotechar <Character>]]
# Classroom - Student Groups # Classroom - Student Groups
@@ -3743,16 +3750,14 @@ gam print domaincontacts|peoplecontacts [todrive <ToDriveAttribute>*]
[sources <PeopleSourceName>] [sources <PeopleSourceName>]
[query <String>] [query <String>]
[mergesources <PeopleMergeSourceName>] [mergesources <PeopleMergeSourceName>]
[coountsonly]
[allfields|(fields <PeopleFieldNameList>)] [showmetadata] [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
[formatjson [quotechar <Character>]] [coountsonly|(formatjson [quotechar <Character>])]
gam show domaincontacts|peoplecontacts gam show domaincontacts|peoplecontacts
[sources <PeopleSourceName>] [sources <PeopleSourceName>]
[query <String>] [query <String>]
[mergesources <PeopleMergeSourceName>] [mergesources <PeopleMergeSourceName>]
[coountsonly]
[allfields|(fields <PeopleFieldNameList>)] [showmetadata] [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
[formatjson] [coountsonly|formatjson]
gam info people|peopleprofile <PeopleResourceNameEntity> gam info people|peopleprofile <PeopleResourceNameEntity>
[allfields|(fields <PeopleFieldNameList>)] [showmetadata] [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
@@ -3760,15 +3765,13 @@ gam info people|peopleprofile <PeopleResourceNameEntity>
gam print people|peopleprofile [todrive <ToDriveAttribute>*] gam print people|peopleprofile [todrive <ToDriveAttribute>*]
[query <String>] [query <String>]
[mergesources <PeopleMergeSourceName>] [mergesources <PeopleMergeSourceName>]
[coountsonly]
[allfields|(fields <PeopleFieldNameList>)] [showmetadata] [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
[formatjson [quotechar <Character>]] [coountsonly|(formatjson [quotechar <Character>])]
gam show people|peopleprofile gam show people|peopleprofile
[query <String>] [query <String>]
[mergesources <PeopleMergeSourceName>] [mergesources <PeopleMergeSourceName>]
[coountsonly]
[allfields|(fields <PeopleFieldNameList>)] [showmetadata] [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
[formatjson] [coountsonly|formatjson]
# Email Audit Monitor # Email Audit Monitor
@@ -6313,12 +6316,11 @@ gam <UserTypeEntity> info events <UserCalendarEntity> [<EventEntity>] [maxinstan
[formatjson] [formatjson]
gam <UserTypeEntity> show events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>* gam <UserTypeEntity> show events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>*
[fields <EventFieldNameList>] [showdayofweek] [fields <EventFieldNameList>] [showdayofweek]
[countsonly] [countsonly|formatjson]
[formatjson]
gam <UserTypeEntity> print events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>* gam <UserTypeEntity> print events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>*
[fields <EventFieldNameList>] [showdayofweek] [fields <EventFieldNameList>] [showdayofweek]
[countsonly [eventrowfilter]] [eventrowfilter]]
[formatjson [quotechar <Character>]] [todrive <ToDriveAttribute>*] [countsonly|(formatjson [quotechar <Character>])] [todrive <ToDriveAttribute>*]
gam <UserTypeEntity> update calattendees <UserCalendarEntity> <EventEntity> [anyorganizer] gam <UserTypeEntity> update calattendees <UserCalendarEntity> <EventEntity> [anyorganizer]
[<EventNotificationAttribute>] [splitupdate] [dryrun|doit] [<EventNotificationAttribute>] [splitupdate] [dryrun|doit]
@@ -8342,13 +8344,13 @@ gam <UserTypeEntity> info contacts
gam <UserTypeEntity> show contacts gam <UserTypeEntity> show contacts
<PeoplePrintShowUserContactSelection> <PeoplePrintShowUserContactSelection>
[orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending) [orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
[countsonly|allfields|(fields <PeopleFieldNameList>)] [showgroups] [showmetadata] [allfields|(fields <PeopleFieldNameList>)] [showgroups] [showmetadata]
[formatjson] [countsonly|formatjson]
gam <UserTypeEntity> print contacts [todrive <ToDriveAttribute>*] gam <UserTypeEntity> print contacts [todrive <ToDriveAttribute>*]
<PeoplePrintShowUserContactSelection> <PeoplePrintShowUserContactSelection>
[orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending) [orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
[countsonly|allfields|(fields <PeopleFieldNameList>)] [[showgroups|showgroupnameslist] showmetadata] [allfields|(fields <PeopleFieldNameList>)] [[showgroups|showgroupnameslist] showmetadata]
[formatjson [quotechar <Character>]] [countsonly|(formatjson [quotechar <Character>])]
<OtherContactsFieldName> ::= <OtherContactsFieldName> ::=
emailaddresses| emailaddresses|
@@ -8582,7 +8584,7 @@ gam <UserTypeEntity> info tasklist <TasklistEntity>
gam <UserTypeEntity> show tasklists gam <UserTypeEntity> show tasklists
[countsonly|formatjson] [countsonly|formatjson]
gam <UserTypeEntity> print tasklists [todrive <ToDriveAttribute>*] gam <UserTypeEntity> print tasklists [todrive <ToDriveAttribute>*]
[countsonly | (formatjson [quotechar <Character>])] [countsonly|(formatjson [quotechar <Character>])]
# Users - Shared Drives # Users - Shared Drives

View File

@@ -1,3 +1,51 @@
7.23.06
Added option `types <AdminAssigneeTypeList>` to `gam print|show admins` that allows filtering
of admin assignments by the type of the assignee; by default, all assignee types are displayed.
```
<AdminAssigneeType> ::= group|user|serviceaccount|unknown
<AdminAssigneeTypeList> ::= "<AdminAssigneeType>(,<AdminAssigneeType>)*"
```
7.23.05
Added option `recursive` that will display assignments to the members
of security groups assigned to roles; the security group membership is recursively expanded.
7.23.04
Added option `addcsvdata <FieldName> <String>` to `gam <UserTypeEntity> print events`
and `gam calendars <CalendarEntity> print events` that adds additional columns of data to the CSV file output.
An example would be to get the calendar name in addition to the calendar ID when printing events.
```
gam redirect csv ./Resources.csv print resources fields email,name
gam redirect csv ./ResourceEventCounts.csv multiprocess redirect stderr - multiprocess csv Resources.csv gam calendar "~resourceEmail" print events starttime -1y countsonly addcsvdata calendarName "~resourceName"
```
Upgraded to OpenSSL 3.6.0.
7.23.03
Upgraded to OpenSSL 3.5.4.
7.23.02
Added option `oneitemperrow` to 'gam print course-materials|course-work` to have each of a
course's materials displayed on a separate row with all of the other course fields.
This produces a CSV file that can be used in subsequent commands to process the materials without further script processing.
7.23.00
Added `chat_max_results` variable to `gam.cfg`.
```
chat_max_results
When retrieving lists of Chat items from API,
how many should be retrieved in each API call
Default: 100
Range: 1 - 1000
```
Previously, this vaule was always set to 1000 which could cause errors.
7.22.07 7.22.07
Added options `showdetails` and `returnidonly` to `gam create|copy vaultquery`. Added options `showdetails` and `returnidonly` to `gam create|copy vaultquery`.
@@ -101,7 +149,7 @@ GAM now builds on macOS 26 Tahoe and properly identifies the OS.
A custom build of the cryptography library is no longer needed for Windows arm64 builds as the project now releases their own build for the OS. A custom build of the cryptography library is no longer needed for Windows arm64 builds as the project now releases their own build for the OS.
Upgrade to OpenSSL 3.5.3 latest Upgraded to OpenSSL 3.5.3.
7.21.01 7.21.01

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.22.07' __version__ = '7.23.06'
__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
@@ -7868,6 +7868,13 @@ class CSVPrintFile():
if title not in self.titlesSet: if title not in self.titlesSet:
self.AddTitle(title) self.AddTitle(title)
def InsertTitles(self, position, titles):
for title in titles if isinstance(titles, list) else [titles]:
if title not in self.titlesSet:
self.titlesSet.add(title)
self.titlesList.insert(position, title)
position += 1
def SetTitles(self, titles): def SetTitles(self, titles):
self.titlesSet = set() self.titlesSet = set()
self.titlesList = [] self.titlesList = []
@@ -16983,21 +16990,38 @@ def doDeleteAdmin():
except (GAPI.forbidden, GAPI.permissionDenied) as e: except (GAPI.forbidden, GAPI.permissionDenied) as e:
ClientAPIAccessDeniedExit(str(e)) ClientAPIAccessDeniedExit(str(e))
ASSIGNEE_EMAILTYPE_TOFIELD_MAP = { ADMIN_ASSIGNEE_TYPE_TO_ASSIGNEDTO_FIELD_MAP = {
'user': 'assignedToUser', 'user': 'assignedToUser',
'group': 'assignedToGroup', 'group': 'assignedToGroup',
'serviceaccount': 'assignedToServiceAccount', 'serviceaccount': 'assignedToServiceAccount',
'unknown': 'assignedToUnknown',
} }
PRINT_ADMIN_FIELDS = ['roleAssignmentId', 'roleId', 'assignedTo', 'scopeType', 'orgUnitId'] ALL_ASSIGNEE_TYPES = ['user', 'group', 'serviceaccount']
PRINT_ADMIN_FIELDS = ['roleAssignmentId', 'roleId', 'assignedTo', 'scopeType', 'orgUnitId', 'assigneeType']
PRINT_ADMIN_TITLES = ['roleAssignmentId', 'roleId', 'role', PRINT_ADMIN_TITLES = ['roleAssignmentId', 'roleId', 'role',
'assignedTo', 'assignedToUser', 'assignedToGroup', 'assignedToServiceAccount', 'assignedToUnknown', 'assignedTo', 'assignedToUser', 'assignedToGroup', 'assignedToServiceAccount', 'assignedToUnknown',
'scopeType', 'orgUnitId', 'orgUnit'] 'scopeType', 'orgUnitId', 'orgUnit']
def getAssigneeTypes(myarg, typesSet):
if myarg in {'type', 'types'}:
for gtype in getString(Cmd.OB_ADMIN_ASSIGNEE_TYPE_LIST).lower().replace(',', ' ').split():
if gtype in ADMIN_ASSIGNEE_TYPE_TO_ASSIGNEDTO_FIELD_MAP:
typesSet.add(ADMIN_ASSIGNEE_TYPE_TO_ASSIGNEDTO_FIELD_MAP[gtype])
else:
invalidChoiceExit(gtype, ADMIN_ASSIGNEE_TYPE_TO_ASSIGNEDTO_FIELD_MAP, True)
else:
return False
return True
# gam print admins [todrive <ToDriveAttribute>*] # gam print admins [todrive <ToDriveAttribute>*]
# [user|group <EmailAddress>|<UniqueID>] [role <RoleItem>] [condition] # [user|group <EmailAddress>|<UniqueID>] [role <RoleItem>]
# [privileges] [oneitemperrow] # [types <AdminAssigneeTypeList>]
# [recursive] [condition] [privileges] [oneitemperrow]
# gam show admins # gam show admins
# [user|group <EmailAddress>|<UniqueID>] [role <RoleItem>] [condition] [privileges] # [user|group <EmailAddress>|<UniqueID>] [role <RoleItem>]
# [types <AdminAssigneeTypeList>]
# [recursive] [condition] [privileges]
def doPrintShowAdmins(): def doPrintShowAdmins():
def _getPrivileges(admin): def _getPrivileges(admin):
if showPrivileges: if showPrivileges:
@@ -17024,19 +17048,18 @@ def doPrintShowAdmins():
def _setNamesFromIds(admin, privileges): def _setNamesFromIds(admin, privileges):
admin['role'] = role_from_roleid(admin['roleId']) admin['role'] = role_from_roleid(admin['roleId'])
assignedTo = admin['assignedTo'] assignedTo = admin['assignedTo']
admin['assignedToUnknown'] = False
if assignedTo not in assignedToIdEmailMap: if assignedTo not in assignedToIdEmailMap:
assigneeType = admin.get('assigneeType')
assignedToField = ASSIGNEE_EMAILTYPE_TOFIELD_MAP.get(assigneeType, None)
assigneeEmail, assigneeType = convertUIDtoEmailAddressWithType(f'uid:{assignedTo}', cd, sal, assigneeEmail, assigneeType = convertUIDtoEmailAddressWithType(f'uid:{assignedTo}', cd, sal,
emailTypes=list(ASSIGNEE_EMAILTYPE_TOFIELD_MAP.keys())) emailTypes=ALL_ASSIGNEE_TYPES if admin.get('assigneeType') != 'group' else ['group'])
if not assignedToField and assigneeType in ASSIGNEE_EMAILTYPE_TOFIELD_MAP: if assigneeType in ADMIN_ASSIGNEE_TYPE_TO_ASSIGNEDTO_FIELD_MAP:
assignedToField = ASSIGNEE_EMAILTYPE_TOFIELD_MAP[assigneeType] assignedToField = ADMIN_ASSIGNEE_TYPE_TO_ASSIGNEDTO_FIELD_MAP[assigneeType]
if assigneeType == 'unknown': else:
assignedToField = 'assignedToUnknown' assignedToField = 'assignedToUnknown'
if assignedToField == 'assignedToUnknown':
assigneeEmail = True assigneeEmail = True
assignedToIdEmailMap[assignedTo] = {'assignedToField': assignedToField, 'assigneeEmail': assigneeEmail} assignedToIdEmailMap[assignedTo] = {'assignedToField': assignedToField, 'assigneeEmail': assigneeEmail}
admin[assignedToIdEmailMap[assignedTo]['assignedToField']] = assignedToIdEmailMap[assignedTo]['assigneeEmail'] admin[assignedToIdEmailMap[assignedTo]['assignedToField']] = assignedToIdEmailMap[assignedTo]['assigneeEmail']
admin['assignedToField'] = assignedToIdEmailMap[assignedTo]['assignedToField']
if privileges is not None: if privileges is not None:
admin.update(privileges) admin.update(privileges)
if 'orgUnitId' in admin: if 'orgUnitId' in admin:
@@ -17052,7 +17075,8 @@ def doPrintShowAdmins():
csvPF = CSVPrintFile(PRINT_ADMIN_TITLES) if Act.csvFormat() else None csvPF = CSVPrintFile(PRINT_ADMIN_TITLES) if Act.csvFormat() else None
roleId = None roleId = None
userKey = None userKey = None
oneItemPerRow = showPrivileges = False oneItemPerRow = recursive = showPrivileges = False
typesSet = set()
kwargs = {} kwargs = {}
rolePrivileges = {} rolePrivileges = {}
fieldsList = PRINT_ADMIN_FIELDS fieldsList = PRINT_ADMIN_FIELDS
@@ -17065,6 +17089,17 @@ def doPrintShowAdmins():
userKey = kwargs['userKey'] = getEmailAddress() userKey = kwargs['userKey'] = getEmailAddress()
elif myarg == 'role': elif myarg == 'role':
_, roleId = getRoleId() _, roleId = getRoleId()
elif getAssigneeTypes(myarg, typesSet):
pass
elif myarg == 'recursive':
recursive = True
allGroupRoles = ','.join(sorted(ALL_GROUP_ROLES))
memberOptions = initMemberOptions()
memberOptions[MEMBEROPTION_INCLUDEDERIVEDMEMBERSHIP] = True
memberOptions[MEMBEROPTION_DISPLAYMATCH] = False
memberDisplayOptions = initIPSGMGroupMemberDisplayOptions()
for role in [Ent.ROLE_MEMBER, Ent.ROLE_MANAGER, Ent.ROLE_OWNER]:
memberDisplayOptions[role]['show'] = True
elif myarg == 'condition': elif myarg == 'condition':
fieldsList.append('condition') fieldsList.append('condition')
if csvPF: if csvPF:
@@ -17078,13 +17113,15 @@ def doPrintShowAdmins():
if roleId and not kwargs: if roleId and not kwargs:
kwargs['roleId'] = roleId kwargs['roleId'] = roleId
roleId = None roleId = None
if not typesSet:
typesSet = set(ADMIN_ASSIGNEE_TYPE_TO_ASSIGNEDTO_FIELD_MAP.values())
fields = getItemFieldsFromFieldsList('items', fieldsList) fields = getItemFieldsFromFieldsList('items', fieldsList)
printGettingAllAccountEntities(Ent.ADMIN_ROLE_ASSIGNMENT) printGettingAllAccountEntities(Ent.ADMIN_ROLE_ASSIGNMENT)
try: try:
admins = callGAPIpages(cd.roleAssignments(), 'list', 'items', admins = callGAPIpages(cd.roleAssignments(), 'list', 'items',
pageMessage=getPageMessage(), pageMessage=getPageMessage(),
throwReasons=[GAPI.INVALID, GAPI.USER_NOT_FOUND, throwReasons=[GAPI.INVALID, GAPI.USER_NOT_FOUND,
GAPI.FORBIDDEN, GAPI.SERVICE_NOT_AVAILABLE, GAPI.NOT_FOUND, GAPI.FORBIDDEN, GAPI.SERVICE_NOT_AVAILABLE,
GAPI.BAD_REQUEST, GAPI.CUSTOMER_NOT_FOUND, GAPI.BAD_REQUEST, GAPI.CUSTOMER_NOT_FOUND,
GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED], GAPI.FORBIDDEN, GAPI.PERMISSION_DENIED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS, retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
@@ -17092,39 +17129,77 @@ def doPrintShowAdmins():
except (GAPI.invalid, GAPI.userNotFound): except (GAPI.invalid, GAPI.userNotFound):
entityUnknownWarning(Ent.ADMINISTRATOR, userKey) entityUnknownWarning(Ent.ADMINISTRATOR, userKey)
return return
except (GAPI.serviceNotAvailable) as e: except GAPI.notFound as e:
entityActionFailedExit([Ent.ADMINISTRATOR, userKey, Ent.ADMIN_ROLE, roleId], str(e)) entityActionFailedExit([Ent.ADMIN_ROLE, kwargs['roleId']], str(e))
except (GAPI.forbidden, GAPI.serviceNotAvailable) as e:
entityActionFailedExit([Ent.ADMINISTRATOR, userKey], str(e))
except (GAPI.badRequest, GAPI.customerNotFound): except (GAPI.badRequest, GAPI.customerNotFound):
accessErrorExit(cd) accessErrorExit(cd)
except (GAPI.forbidden, GAPI.permissionDenied) as e: except (GAPI.forbidden, GAPI.permissionDenied) as e:
ClientAPIAccessDeniedExit(str(e)) ClientAPIAccessDeniedExit(str(e))
count = len(admins)
groupMembers = {}
expandedAdmins = []
i = 0
for admin in admins:
i += 1
if roleId and roleId != admin['roleId']:
continue
assignedTo = admin['assignedTo']
if admin['assigneeType'] != 'group' or not recursive:
_setNamesFromIds(admin, _getPrivileges(admin))
if admin['assignedToField'] in typesSet:
expandedAdmins.append(admin)
continue
if assignedTo not in groupMembers:
membersList = []
membersSet = set()
level = 0
getGroupMembers(cd, assignedTo, allGroupRoles, membersList, membersSet, i, count,
memberOptions, memberDisplayOptions, level, {Ent.TYPE_USER})
groupMembers[assignedTo] = membersList[:]
_setNamesFromIds(admin, _getPrivileges(admin))
if admin[assignedToIdEmailMap[assignedTo]['assignedToField']] not in typesSet:
continue
expandedAdmins.append(admin)
if not groupMembers[assignedTo]:
expandedAdmins.append(admin)
continue
admin['assigneeType'] = 'user'
admin['assignedToGroup'] = assignedToIdEmailMap[assignedTo]['assigneeEmail']
for member in groupMembers[assignedTo]:
userAdmin = admin.copy()
userAdmin['assignedTo'] = member['id']
_setNamesFromIds(userAdmin, _getPrivileges(admin))
expandedAdmins.append(userAdmin)
admins = expandedAdmins
count = len(expandedAdmins)
if not csvPF: if not csvPF:
count = len(admins)
performActionNumItems(count, Ent.ADMIN_ROLE_ASSIGNMENT) performActionNumItems(count, Ent.ADMIN_ROLE_ASSIGNMENT)
Ind.Increment() Ind.Increment()
i = 0 i = 0
for admin in admins: for admin in expandedAdmins:
i += 1 i += 1
if roleId and roleId != admin['roleId']:
continue
_setNamesFromIds(admin, _getPrivileges(admin))
printEntity([Ent.ADMIN_ROLE_ASSIGNMENT, admin['roleAssignmentId']], i, count) printEntity([Ent.ADMIN_ROLE_ASSIGNMENT, admin['roleAssignmentId']], i, count)
Ind.Increment() Ind.Increment()
for field in PRINT_ADMIN_TITLES: for field in PRINT_ADMIN_TITLES:
if field in admin: if field in admin:
if field == 'roleAssignmentId': if field == 'roleAssignmentId':
continue continue
if field != 'rolePrivileges': printKeyValueList([field, admin[field]])
printKeyValueList([field, admin[field]]) if showPrivileges:
else: rolePrivileges = admin.get('rolePrivileges', [])
showJSON(None, admin[field]) jcount = len(rolePrivileges)
if jcount > 0:
printKeyValueList(['rolePrivileges', jcount])
Ind.Increment()
showJSON(None, rolePrivileges)
Ind.Decrement()
Ind.Decrement() Ind.Decrement()
Ind.Decrement() Ind.Decrement()
else: else:
for admin in admins: for admin in expandedAdmins:
if roleId and roleId != admin['roleId']: admin.pop('assignedToField')
continue
_setNamesFromIds(admin, _getPrivileges(admin))
if not oneItemPerRow or 'rolePrivileges' not in admin: if not oneItemPerRow or 'rolePrivileges' not in admin:
csvPF.WriteRowTitles(flattenJSON(admin)) csvPF.WriteRowTitles(flattenJSON(admin))
else: else:
@@ -22429,12 +22504,12 @@ def infoUserPeopleContacts(users):
# gam <UserTypeEntity> print contacts [todrive <ToDriveAttribute>*] <PeoplePrintShowUserContactSelection> # gam <UserTypeEntity> print contacts [todrive <ToDriveAttribute>*] <PeoplePrintShowUserContactSelection>
# [showgroups|showgroupnameslist] [orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending) # [showgroups|showgroupnameslist] [orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
# [countsonly|allfields|fields <PeopleFieldNameList>] [showmetadata] # [allfields|fields <PeopleFieldNameList>] [showmetadata]
# [formatjson [quotechar <Character>]] # [countsonly|(formatjson [quotechar <Character>])]
# gam <UserTypeEntity> show contacts <PeoplePrintShowUserContactSelection> # gam <UserTypeEntity> show contacts <PeoplePrintShowUserContactSelection>
# [showgroups] [orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending) # [showgroups] [orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
# [countsonly|allfields|(fields <PeopleFieldNameList>)] [showmetadata] # [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
# [formatjson] # [countsonly|formatjson]
def printShowUserPeopleContacts(users): def printShowUserPeopleContacts(users):
entityType = Ent.USER entityType = Ent.USER
entityTypeName = Ent.Singular(entityType) entityTypeName = Ent.Singular(entityType)
@@ -22473,6 +22548,8 @@ def printShowUserPeopleContacts(users):
else: else:
FJQC.GetFormatJSONQuoteChar(myarg, True) FJQC.GetFormatJSONQuoteChar(myarg, True)
if countsOnly: if countsOnly:
if csvPF:
csvPF.SetFormatJSON(False)
fieldsList = ['emailAddresses'] fieldsList = ['emailAddresses']
if contactQuery['mainContacts']: if contactQuery['mainContacts']:
fields = _getPersonFields(PEOPLE_FIELDS_CHOICE_MAP, PEOPLE_CONTACTS_DEFAULT_FIELDS, fieldsList, parameters) fields = _getPersonFields(PEOPLE_FIELDS_CHOICE_MAP, PEOPLE_CONTACTS_DEFAULT_FIELDS, fieldsList, parameters)
@@ -22710,11 +22787,11 @@ def processUserPeopleOtherContacts(users):
Ind.Decrement() Ind.Decrement()
# gam <UserTypeEntity> print othercontacts [todrive <ToDriveAttribute>*] <OtherContactSelection> # gam <UserTypeEntity> print othercontacts [todrive <ToDriveAttribute>*] <OtherContactSelection>
# [countsonly|allfields|(fields <OtherContactFieldNameList>)] [showmetadata] # [allfields|(fields <OtherContactFieldNameList>)] [showmetadata]
# [formatjson [quotechar <Character>]] # [countsonly|(formatjson [quotechar <Character>])]
# gam <UserTypeEntity> show othercontacts <OtherContactSelection> # gam <UserTypeEntity> show othercontacts <OtherContactSelection>
# [countsonly|allfields|(fields <OtherContactFieldNameList>)] [showmetadata] # [allfields|(fields <OtherContactFieldNameList>)] [showmetadata]
# [formatjson] # [countsonly|formatjson]
def printShowUserPeopleOtherContacts(users): def printShowUserPeopleOtherContacts(users):
entityType = Ent.USER entityType = Ent.USER
entityTypeName = Ent.Singular(entityType) entityTypeName = Ent.Singular(entityType)
@@ -22744,6 +22821,8 @@ def printShowUserPeopleOtherContacts(users):
else: else:
FJQC.GetFormatJSONQuoteChar(myarg, True) FJQC.GetFormatJSONQuoteChar(myarg, True)
if countsOnly: if countsOnly:
if csvPF:
csvPF.SetFormatJSON(False)
fieldsList = ['emailAddresses'] fieldsList = ['emailAddresses']
fields = _getPersonFields(PEOPLE_OTHER_CONTACTS_FIELDS_CHOICE_MAP, PEOPLE_CONTACTS_DEFAULT_FIELDS, fieldsList, parameters) fields = _getPersonFields(PEOPLE_OTHER_CONTACTS_FIELDS_CHOICE_MAP, PEOPLE_CONTACTS_DEFAULT_FIELDS, fieldsList, parameters)
i, count, users = getEntityArgument(users) i, count, users = getEntityArgument(users)
@@ -22813,6 +22892,8 @@ def _printShowPeople(source):
function = 'searchDirectoryPeople' function = 'searchDirectoryPeople'
else: else:
FJQC.GetFormatJSONQuoteChar(myarg, True) FJQC.GetFormatJSONQuoteChar(myarg, True)
if countsOnly and csvPF:
csvPF.SetFormatJSON(False)
fields = _getPersonFields(PEOPLE_FIELDS_CHOICE_MAP, PEOPLE_CONTACTS_DEFAULT_FIELDS, fieldsList, parameters) fields = _getPersonFields(PEOPLE_FIELDS_CHOICE_MAP, PEOPLE_CONTACTS_DEFAULT_FIELDS, fieldsList, parameters)
printGettingAllEntityItemsForWhom(peopleEntityType, GC.Values[GC.DOMAIN], query=kwargs.get('query')) printGettingAllEntityItemsForWhom(peopleEntityType, GC.Values[GC.DOMAIN], query=kwargs.get('query'))
try: try:
@@ -22850,29 +22931,24 @@ def doInfoDomainPeopleContacts():
# gam print people|peopleprofile [todrive <ToDriveAttribute>*] # gam print people|peopleprofile [todrive <ToDriveAttribute>*]
# [query <String>] # [query <String>]
# [mergesources <PeopleMergeSourceName>] # [mergesources <PeopleMergeSourceName>]
# [countsonly]
# [allfields|(fields <PeopleFieldNameList>)] [showmetadata] # [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
# [formatjson [quotechar <Character>]] # [countsonly|(formatjson [quotechar <Character>])]
# gam show people|peopleprofile # gam show people|peopleprofile
# [query <String>] # [query <String>]
# [mergesources <PeopleMergeSourceName>] # [mergesources <PeopleMergeSourceName>]
# [countsonly]
# [allfields|(fields <PeopleFieldNameList>)] [showmetadata] # [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
# [formatjson] # [countsonlyformatjson]
# gam print domaincontacts|peoplecontacts [todrive <ToDriveAttribute>*] # gam print domaincontacts|peoplecontacts [todrive <ToDriveAttribute>*]
# [sources <PeopleSourceName>] # [sources <PeopleSourceName>]
# [query <String>] # [query <String>]
# [mergesources <PeopleMergeSourceName>] # [mergesources <PeopleMergeSourceName>]
# [countsonly]
# [allfields|(fields <PeopleFieldNameList>)] [showmetadata] # [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
# [formatjson [quotechar <Character>]] # [countsonly|(formatjson [quotechar <Character>])]
# gam show domaincontacts|peoplecontacts # gam show domaincontacts|peoplecontacts
# [sources <PeopleSourceName>] # [sources <PeopleSourceName>]
# [query <String>] # [query <String>]
# [mergesources <PeopleMergeSourceName>] # [mergesources <PeopleMergeSourceName>]
# [countsonly] # [countsonlyformatjson]
# [allfields|(fields <PeopleFieldNameList>)] [showmetadata]
# [formatjson]
def doPrintShowDomainPeopleProfiles(): def doPrintShowDomainPeopleProfiles():
_printShowPeople('profile') _printShowPeople('profile')
@@ -26579,7 +26655,7 @@ def printShowChatEmojis(users):
pageMessage=_getChatPageMessage(Ent.CHAT_EMOJI, user, i, count, pfilter), pageMessage=_getChatPageMessage(Ent.CHAT_EMOJI, user, i, count, pfilter),
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED], throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS, retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
pageSize=CHAT_PAGE_SIZE, filter=pfilter) pageSize=GC.Values[GC.CHAT_MAX_RESULTS], filter=pfilter)
except (GAPI.notFound, GAPI.invalidArgument, GAPI.permissionDenied) as e: except (GAPI.notFound, GAPI.invalidArgument, GAPI.permissionDenied) as e:
exitIfChatNotConfigured(chat, kvList, str(e), i, count) exitIfChatNotConfigured(chat, kvList, str(e), i, count)
continue continue
@@ -26649,7 +26725,14 @@ def getChatSpaceParameters(myarg, body, typeChoicesMap, updateMask):
CHAT_MEMBER_ROLE_MAP = { CHAT_MEMBER_ROLE_MAP = {
'member': 'ROLE_MEMBER', 'member': 'ROLE_MEMBER',
'manager': 'ROLE_MANAGER' 'manager': 'ROLE_MANAGER',
'owner': 'ROLE_OWNER',
}
CHAT_ROLE_ENTITY_TYPE_MAP = {
'ROLE_MEMBER': Ent.CHAT_MEMBER_USER,
'ROLE_MANAGER': Ent.CHAT_MANAGER_USER,
'ROLE_OWNER': Ent.CHAT_OWNER_USER,
} }
CHAT_MEMBER_TYPE_MAP = { CHAT_MEMBER_TYPE_MAP = {
@@ -27006,7 +27089,6 @@ def _getChatSpaceSearchParms(myarg, queries, queryTimes, OBY):
return False return False
return True return True
CHAT_PAGE_SIZE = 1000
CHAT_SPACES_ADMIN_ORDERBY_CHOICE_MAP = { CHAT_SPACES_ADMIN_ORDERBY_CHOICE_MAP = {
'createtime': 'createTime', 'createtime': 'createTime',
'lastactivetime': 'lastActiveTime', 'lastactivetime': 'lastActiveTime',
@@ -27086,7 +27168,7 @@ def printShowChatSpaces(users):
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.INTERNAL_ERROR, throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.INTERNAL_ERROR,
GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION], GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS, retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
fields=fields, pageSize=CHAT_PAGE_SIZE, **kwargsCS) fields=fields, pageSize=GC.Values[GC.CHAT_MAX_RESULTS], **kwargsCS)
if showAccessSettings: if showAccessSettings:
for space in spaces: for space in spaces:
if space['spaceType'] == 'SPACE': if space['spaceType'] == 'SPACE':
@@ -27152,7 +27234,7 @@ def _getChatSpaceMembers(cd, chatSpace, ciGroupName):
pageMessage=_getChatPageMessage(Ent.CHAT_MEMBER, user, 0, 0, qfilter), pageMessage=_getChatPageMessage(Ent.CHAT_MEMBER, user, 0, 0, qfilter),
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED], throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS, retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
parent=chatSpace, fields=fields, pageSize=CHAT_PAGE_SIZE, **kwargsUAA) parent=chatSpace, fields=fields, pageSize=GC.Values[GC.CHAT_MAX_RESULTS], **kwargsUAA)
for member in members: for member in members:
_getChatMemberEmail(cd, member) _getChatMemberEmail(cd, member)
gmember = {} gmember = {}
@@ -27231,7 +27313,7 @@ def createChatMember(users):
throwReasons=[GAPI.ALREADY_EXISTS, GAPI.NOT_FOUND, GAPI.INVALID, GAPI.INVALID_ARGUMENT, throwReasons=[GAPI.ALREADY_EXISTS, GAPI.NOT_FOUND, GAPI.INVALID, GAPI.INVALID_ARGUMENT,
GAPI.INTERNAL_ERROR, GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION], GAPI.INTERNAL_ERROR, GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
parent=parent, body=body, **kwargsUAA) parent=parent, body=body, **kwargsUAA)
if role != 'ROLE_MEMBER' and entityType == Ent.CHAT_MANAGER_USER: if role != 'ROLE_MEMBER' and entityType in (Ent.CHAT_MANAGER_USER, Ent.CHAT_OWNER_USER):
member = callGAPI(chat.spaces().members(), 'patch', member = callGAPI(chat.spaces().members(), 'patch',
bailOnInternalError=True, bailOnInternalError=True,
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.INTERNAL_ERROR, throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.INTERNAL_ERROR,
@@ -27289,7 +27371,7 @@ def createChatMember(users):
missingArgumentExit('space') missingArgumentExit('space')
if not userList and not groupList: if not userList and not groupList:
missingArgumentExit('user|members|group|groups') missingArgumentExit('user|members|group|groups')
userEntityType = Ent.CHAT_MEMBER_USER if role == 'ROLE_MEMBER' else Ent.CHAT_MANAGER_USER userEntityType = CHAT_ROLE_ENTITY_TYPE_MAP[role]
userMembers = [] userMembers = []
for user in userList: for user in userList:
userMembers.append({'member': {'name': f'users/{user}', 'type': mtype}}) userMembers.append({'member': {'name': f'users/{user}', 'type': mtype}})
@@ -27546,7 +27628,7 @@ def syncChatMembers(users):
unknownArgumentExit() unknownArgumentExit()
if not parent: if not parent:
missingArgumentExit('space') missingArgumentExit('space')
userEntityType = Ent.CHAT_MEMBER_USER if role == 'ROLE_MEMBER' else Ent.CHAT_MANAGER_USER userEntityType = CHAT_ROLE_ENTITY_TYPE_MAP[role]
userMembers = {} userMembers = {}
syncUsersSet = set() syncUsersSet = set()
for user in userList: for user in userList:
@@ -27576,7 +27658,7 @@ def syncChatMembers(users):
pageMessage=_getChatPageMessage(Ent.CHAT_MEMBER, user, i, count, qfilter), pageMessage=_getChatPageMessage(Ent.CHAT_MEMBER, user, i, count, qfilter),
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION], throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS, retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
parent=parent, showGroups=groupsSpecified, pageSize=CHAT_PAGE_SIZE, **kwargs, **kwargsUAA) parent=parent, showGroups=groupsSpecified, pageSize=GC.Values[GC.CHAT_MAX_RESULTS], **kwargs, **kwargsUAA)
for member in members: for member in members:
if 'member' in member: if 'member' in member:
if member['member']['type'] == mtype and member['role'] == role: if member['member']['type'] == mtype and member['role'] == role:
@@ -27777,7 +27859,7 @@ def printShowChatMembers(users):
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.INTERNAL_ERROR, throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.INTERNAL_ERROR,
GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION], GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
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=GC.Values[GC.CHAT_MAX_RESULTS],
**kwargsCS) **kwargsCS)
for space in sorted(spaces, key=lambda k: k[sortName]): 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:
@@ -27794,7 +27876,7 @@ def printShowChatMembers(users):
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.INTERNAL_ERROR, throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.INTERNAL_ERROR,
GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION], GAPI.PERMISSION_DENIED, GAPI.FAILED_PRECONDITION],
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=GC.Values[GC.CHAT_MAX_RESULTS],
**kwargsCS) **kwargsCS)
for space in sorted(spaces, key=lambda k: k[sortName]): for space in sorted(spaces, key=lambda k: k[sortName]):
# if 'membershipCount' in space: # if 'membershipCount' in space:
@@ -27825,7 +27907,7 @@ def printShowChatMembers(users):
pageMessage=_getChatPageMessage(Ent.CHAT_MEMBER, user, j, jcount, qfilter), pageMessage=_getChatPageMessage(Ent.CHAT_MEMBER, user, j, jcount, qfilter),
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED], throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS, retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
parent=parentName, fields=fields, pageSize=CHAT_PAGE_SIZE, **kwargs, **kwargsUAA) parent=parentName, fields=fields, pageSize=GC.Values[GC.CHAT_MAX_RESULTS], **kwargs, **kwargsUAA)
for member in members: for member in members:
_getChatMemberEmail(cd, member) _getChatMemberEmail(cd, member)
except (GAPI.notFound, GAPI.invalidArgument, GAPI.permissionDenied) as e: except (GAPI.notFound, GAPI.invalidArgument, GAPI.permissionDenied) as e:
@@ -28139,7 +28221,7 @@ def printShowChatMessages(users):
pageMessage=_getChatPageMessage(Ent.CHAT_MESSAGE, user, i, count, qfilter), pageMessage=_getChatPageMessage(Ent.CHAT_MESSAGE, user, i, count, qfilter),
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED], throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS, retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
pageSize=CHAT_PAGE_SIZE, parent=parentName, filter=pfilter, showDeleted=showDeleted, pageSize=GC.Values[GC.CHAT_MAX_RESULTS], parent=parentName, filter=pfilter, showDeleted=showDeleted,
fields=fields) fields=fields)
for message in messages: for message in messages:
if 'sender' in message: if 'sender' in message:
@@ -28257,7 +28339,7 @@ def printShowChatEvents(users):
pageMessage=_getChatPageMessage(Ent.CHAT_EVENT, user, i, count, qfilter), pageMessage=_getChatPageMessage(Ent.CHAT_EVENT, user, i, count, qfilter),
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED], throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS, retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
pageSize=CHAT_PAGE_SIZE, parent=parentName, filter=pfilter) pageSize=GC.Values[GC.CHAT_MAX_RESULTS], parent=parentName, filter=pfilter)
except (GAPI.notFound, GAPI.invalidArgument, GAPI.permissionDenied) as e: except (GAPI.notFound, GAPI.invalidArgument, GAPI.permissionDenied) as e:
exitIfChatNotConfigured(chat, kvList, str(e), i, count) exitIfChatNotConfigured(chat, kvList, str(e), i, count)
continue continue
@@ -40119,7 +40201,7 @@ def _createCalendarEvents(user, origCal, function, calIds, count, body, paramete
else: else:
if parameters['showDayOfWeek']: if parameters['showDayOfWeek']:
_getEventDaysOfWeek(event) _getEventDaysOfWeek(event)
_printCalendarEvent(user, calId, event, parameters['csvPF'], parameters['FJQC']) _printCalendarEvent(user, calId, event, parameters['csvPF'], parameters['FJQC'], {})
except (GAPI.invalid, GAPI.required, GAPI.timeRangeEmpty, GAPI.eventDurationExceedsLimit, except (GAPI.invalid, GAPI.required, GAPI.timeRangeEmpty, GAPI.eventDurationExceedsLimit,
GAPI.requiredAccessLevel, GAPI.participantIsNeitherOrganizerNorAttendee, GAPI.requiredAccessLevel, GAPI.participantIsNeitherOrganizerNorAttendee,
GAPI.malformedWorkingLocationEvent, GAPI.badRequest) as e: GAPI.malformedWorkingLocationEvent, GAPI.badRequest) as e:
@@ -40223,7 +40305,7 @@ def _updateCalendarEvents(origUser, user, origCal, calIds, count, calendarEventE
else: else:
if parameters['showDayOfWeek']: if parameters['showDayOfWeek']:
_getEventDaysOfWeek(event) _getEventDaysOfWeek(event)
_printCalendarEvent(user, calId, event, parameters['csvPF'], parameters['FJQC']) _printCalendarEvent(user, calId, event, parameters['csvPF'], parameters['FJQC'], {})
except (GAPI.notFound, GAPI.deleted) as e: except (GAPI.notFound, GAPI.deleted) as e:
if not checkCalendarExists(cal, calId, j, jcount): if not checkCalendarExists(cal, calId, j, jcount):
entityUnknownWarning(Ent.CALENDAR, calId, j, jcount) entityUnknownWarning(Ent.CALENDAR, calId, j, jcount)
@@ -40520,10 +40602,12 @@ def _showCalendarEvent(primaryEmail, calId, eventEntityType, event, k, kcount, F
showJSON(None, event, skipObjects) showJSON(None, event, skipObjects)
Ind.Decrement() Ind.Decrement()
def _printCalendarEvent(user, calId, event, csvPF, FJQC): def _printCalendarEvent(user, calId, event, csvPF, FJQC, addCSVData):
row = {'calendarId': calId, 'id': event['id']} row = {'calendarId': calId, 'id': event['id']}
if user: if user:
row['primaryEmail'] = user row['primaryEmail'] = user
if addCSVData:
row.update(addCSVData)
flattenJSON(event, flattened=row, timeObjects=EVENT_TIME_OBJECTS) flattenJSON(event, flattened=row, timeObjects=EVENT_TIME_OBJECTS)
if not FJQC.formatJSON: if not FJQC.formatJSON:
csvPF.WriteRowTitles(row) csvPF.WriteRowTitles(row)
@@ -40536,7 +40620,7 @@ def _printCalendarEvent(user, calId, event, csvPF, FJQC):
csvPF.WriteRowNoFilter(row) csvPF.WriteRowNoFilter(row)
def _printShowCalendarEvents(origUser, user, origCal, calIds, count, calendarEventEntity, def _printShowCalendarEvents(origUser, user, origCal, calIds, count, calendarEventEntity,
csvPF, FJQC, fieldsList): csvPF, FJQC, fieldsList, addCSVData):
i = 0 i = 0
for calId in calIds: for calId in calIds:
i += 1 i += 1
@@ -40562,7 +40646,7 @@ def _printShowCalendarEvents(origUser, user, origCal, calIds, count, calendarEve
for event in events: for event in events:
if calendarEventEntity['showDayOfWeek']: if calendarEventEntity['showDayOfWeek']:
_getEventDaysOfWeek(event) _getEventDaysOfWeek(event)
_printCalendarEvent(user, calId, event, csvPF, FJQC) _printCalendarEvent(user, calId, event, csvPF, FJQC, addCSVData)
elif GC.Values[GC.CSV_OUTPUT_USERS_AUDIT] and user: elif GC.Values[GC.CSV_OUTPUT_USERS_AUDIT] and user:
csvPF.WriteRowNoFilter({'calendarId': calId, 'primaryEmail': user, 'id': ''}) csvPF.WriteRowNoFilter({'calendarId': calId, 'primaryEmail': user, 'id': ''})
else: else:
@@ -40580,6 +40664,8 @@ def _printShowCalendarEvents(origUser, user, origCal, calIds, count, calendarEve
row = {'calendarId': calId} row = {'calendarId': calId}
if user: if user:
row['primaryEmail'] = user row['primaryEmail'] = user
if addCSVData:
row.update(addCSVData)
row['events'] = jcount row['events'] = jcount
if not calendarEventEntity['eventRowFilter']: if not calendarEventEntity['eventRowFilter']:
csvPF.WriteRow(row) csvPF.WriteRow(row)
@@ -40810,6 +40896,8 @@ def _getCalendarPrintShowEventOptions(calendarEventEntity, entityType):
csvPF = CSVPrintFile(['primaryEmail', 'calendarId', 'id'] if entityType == Ent.USER else ['calendarId', 'id'], 'sortall', indexedTitles=EVENT_INDEXED_TITLES) if Act.csvFormat() else None csvPF = CSVPrintFile(['primaryEmail', 'calendarId', 'id'] if entityType == Ent.USER else ['calendarId', 'id'], 'sortall', indexedTitles=EVENT_INDEXED_TITLES) if Act.csvFormat() else None
FJQC = FormatJSONQuoteChar(csvPF) FJQC = FormatJSONQuoteChar(csvPF)
fieldsList = [] fieldsList = []
addCSVData = {}
addCSVDataLoc = 2 if entityType == Ent.USER else 1
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
myarg = getArgument() myarg = getArgument()
if csvPF and myarg == 'todrive': if csvPF and myarg == 'todrive':
@@ -40818,6 +40906,9 @@ def _getCalendarPrintShowEventOptions(calendarEventEntity, entityType):
pass pass
elif myarg == 'fields': elif myarg == 'fields':
_getEventFields(fieldsList) _getEventFields(fieldsList)
elif csvPF and myarg == 'addcsvdata':
k = getString(Cmd.OB_STRING)
addCSVData[k] = getString(Cmd.OB_STRING, minLen=0)
elif myarg == 'countsonly': elif myarg == 'countsonly':
calendarEventEntity['countsOnly'] = True calendarEventEntity['countsOnly'] = True
elif myarg == 'showdayofweek': elif myarg == 'showdayofweek':
@@ -40830,27 +40921,35 @@ def _getCalendarPrintShowEventOptions(calendarEventEntity, entityType):
fieldsList = ['id'] fieldsList = ['id']
if csvPF: if csvPF:
if calendarEventEntity['countsOnly']: if calendarEventEntity['countsOnly']:
csvPF.SetFormatJSON(False)
csvPF.RemoveTitles(['id']) csvPF.RemoveTitles(['id'])
if addCSVData:
csvPF.InsertTitles(addCSVDataLoc, sorted(addCSVData.keys()))
csvPF.AddTitles(['events']) csvPF.AddTitles(['events'])
csvPF.SetSortAllTitles()
calendarEventEntity['countsOnlyTitles'] = csvPF.titlesList[:] calendarEventEntity['countsOnlyTitles'] = csvPF.titlesList[:]
elif not FJQC.formatJSON and not fieldsList: else:
csvPF.AddSortTitles(EVENT_PRINT_ORDER) if addCSVData:
csvPF.InsertTitles(addCSVDataLoc, sorted(addCSVData.keys()))
if not FJQC.formatJSON and not fieldsList:
csvPF.AddTitles(EVENT_PRINT_ORDER)
csvPF.SetSortAllTitles()
_addEventEntitySelectFields(calendarEventEntity, fieldsList) _addEventEntitySelectFields(calendarEventEntity, fieldsList)
return (csvPF, FJQC, fieldsList) return (csvPF, FJQC, fieldsList, addCSVData)
# gam calendars <CalendarEntity> print events <EventEntity> <EventDisplayProperties>* # gam calendars <CalendarEntity> print events <EventEntity> <EventDisplayProperties>*
# [fields <EventFieldNameList>] [showdayofweek] # [fields <EventFieldNameList>] [showdayofweek]
# [countsonly [eventrowfilter]] # (addcsvdata <FieldName> <String>)*
# [formatjson [quotechar <Character>]] [todrive <ToDriveAttribute>*] # [eventrowfilter]
# [countsonly|(formatjson [quotechar <Character>])] [todrive <ToDriveAttribute>*]
# gam calendars <CalendarEntity> show events <EventEntity> <EventDisplayProperties>* # gam calendars <CalendarEntity> show events <EventEntity> <EventDisplayProperties>*
# [fields <EventFieldNameList>] [showdayofweek] # [fields <EventFieldNameList>] [showdayofweek]
# [countsonly] # [countsonly|formatjson]
# [formatjson]
def doCalendarsPrintShowEvents(calIds): def doCalendarsPrintShowEvents(calIds):
calendarEventEntity = getCalendarEventEntity() calendarEventEntity = getCalendarEventEntity()
csvPF, FJQC, fieldsList = _getCalendarPrintShowEventOptions(calendarEventEntity, Ent.CALENDAR) csvPF, FJQC, fieldsList, addCSVData = _getCalendarPrintShowEventOptions(calendarEventEntity, Ent.CALENDAR)
_printShowCalendarEvents(None, None, None, calIds, len(calIds), calendarEventEntity, _printShowCalendarEvents(None, None, None, calIds, len(calIds), calendarEventEntity,
csvPF, FJQC, fieldsList) csvPF, FJQC, fieldsList, addCSVData)
if csvPF: if csvPF:
if calendarEventEntity['countsOnly'] and calendarEventEntity['eventRowFilter']: if calendarEventEntity['countsOnly'] and calendarEventEntity['eventRowFilter']:
csvPF.SetTitles(calendarEventEntity['countsOnlyTitles']) csvPF.SetTitles(calendarEventEntity['countsOnlyTitles'])
@@ -48857,13 +48956,15 @@ def _doInfoCourses(courseIdList):
# gam info courses <CourseEntity> [owneraccess] # gam info courses <CourseEntity> [owneraccess]
# [owneremail] [alias|aliases] [show none|all|students|teachers] [countsonly] # [owneremail] [alias|aliases] [show none|all|students|teachers] [countsonly]
# [fields <CourseFieldNameList>] [skipfields <CourseFieldNameList>] [formatjson] # [fields <CourseFieldNameList>] [skipfields <CourseFieldNameList>]
# [formatjson]
def doInfoCourses(): def doInfoCourses():
_doInfoCourses(getEntityList(Cmd.OB_COURSE_ENTITY, shlexSplit=True)) _doInfoCourses(getEntityList(Cmd.OB_COURSE_ENTITY, shlexSplit=True))
# gam info course <CourseID> [owneraccess] # gam info course <CourseID> [owneraccess]
# [owneremail] [alias|aliases] [show none|all|students|teachers] [countsonly] # [owneremail] [alias|aliases] [show none|all|students|teachers] [countsonly]
# [fields <CourseFieldNameList>] [skipfields <CourseFieldNameList>] [formatjson] # [fields <CourseFieldNameList>] [skipfields <CourseFieldNameList>]
# [formatjson]
def doInfoCourse(): def doInfoCourse():
_doInfoCourses(getStringReturnInList(Cmd.OB_COURSE_ID)) _doInfoCourses(getStringReturnInList(Cmd.OB_COURSE_ID))
@@ -49181,7 +49282,7 @@ COURSE_ANNOUNCEMENTS_INDEXED_TITLES = ['materials']
# (orderby <CourseAnnouncementOrderByFieldName> [ascending|descending])*) # (orderby <CourseAnnouncementOrderByFieldName> [ascending|descending])*)
# [showcreatoremails|creatoremail] [fields <CourseAnnouncementFieldNameList>] # [showcreatoremails|creatoremail] [fields <CourseAnnouncementFieldNameList>]
# [timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] # [timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
# [countsonly] [formatjson [quotechar <Character>]] # [countsonly|(formatjson [quotechar <Character>])]
def doPrintCourseAnnouncements(): def doPrintCourseAnnouncements():
def _printCourseAnnouncement(course, courseAnnouncement, i, count): def _printCourseAnnouncement(course, courseAnnouncement, i, count):
if applyCourseItemFilter and not _courseItemPassesFilter(courseAnnouncement, courseItemFilter): if applyCourseItemFilter and not _courseItemPassesFilter(courseAnnouncement, courseItemFilter):
@@ -49237,6 +49338,8 @@ def doPrintCourseAnnouncements():
coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties) coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties)
if coursesInfo is None: if coursesInfo is None:
return return
if countsOnly:
csvPF.SetFormatJSON(False)
applyCourseItemFilter = _setApplyCourseItemFilter(courseItemFilter, fieldsList) applyCourseItemFilter = _setApplyCourseItemFilter(courseItemFilter, fieldsList)
if showCreatorEmail and fieldsList: if showCreatorEmail and fieldsList:
fieldsList.append('creatorUserId') fieldsList.append('creatorUserId')
@@ -49293,7 +49396,7 @@ COURSE_TOPICS_SORT_TITLES = ['courseId', 'courseName', 'topicId', 'name', 'updat
# (course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] states <CourseStateList>]) # (course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] states <CourseStateList>])
# [topicids <CourseTopicIDEntity>] # [topicids <CourseTopicIDEntity>]
# [timefilter updatetime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] # [timefilter updatetime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
# [countsonly] [formatjson [quotechar <Character>]] # [countsonly|(formatjson [quotechar <Character>])]
def doPrintCourseTopics(): def doPrintCourseTopics():
def _printCourseTopic(course, courseTopic): def _printCourseTopic(course, courseTopic):
if applyCourseItemFilter and not _courseItemPassesFilter(courseTopic, courseItemFilter): if applyCourseItemFilter and not _courseItemPassesFilter(courseTopic, courseItemFilter):
@@ -49334,6 +49437,8 @@ def doPrintCourseTopics():
coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties) coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties)
if coursesInfo is None: if coursesInfo is None:
return return
if countsOnly:
csvPF.SetFormatJSON(False)
applyCourseItemFilter = _setApplyCourseItemFilter(courseItemFilter, fieldsList) applyCourseItemFilter = _setApplyCourseItemFilter(courseItemFilter, fieldsList)
courseTopicIdsLists = courseTopicIds if isinstance(courseTopicIds, dict) else None courseTopicIdsLists = courseTopicIds if isinstance(courseTopicIds, dict) else None
i = 0 i = 0
@@ -49467,6 +49572,16 @@ def doPrintCourseWM(entityIDType, entityStateType):
pass pass
return topicNames return topicNames
def _printCourseWMrow(course, courseWM):
row = flattenJSON(courseWM, flattened={'courseId': course['id'], 'courseName': course['name']}, timeObjects=TimeObjects,
simpleLists=['studentIds'] if showStudentsAsList else None, delimiter=delimiter)
if not FJQC.formatJSON:
csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row):
csvPF.WriteRowNoFilter({'courseId': course['id'], 'courseName': course['name'],
'JSON': json.dumps(cleanJSON(courseWM, timeObjects=TimeObjects),
ensure_ascii=False, sort_keys=True)})
def _printCourseWM(course, courseWM, i, count): def _printCourseWM(course, courseWM, i, count):
if applyCourseItemFilter and not _courseItemPassesFilter(courseWM, courseItemFilter): if applyCourseItemFilter and not _courseItemPassesFilter(courseWM, courseItemFilter):
return return
@@ -49478,14 +49593,13 @@ def doPrintCourseWM(entityIDType, entityStateType):
topicId = courseWM.get('topicId') topicId = courseWM.get('topicId')
if topicId: if topicId:
courseWM['topicName'] = topicNames.get(topicId, topicId) courseWM['topicName'] = topicNames.get(topicId, topicId)
row = flattenJSON(courseWM, flattened={'courseId': course['id'], 'courseName': course['name']}, timeObjects=TimeObjects, if not oneItemPerRow or not courseWM.get('materials', []):
simpleLists=['studentIds'] if showStudentsAsList else None, delimiter=delimiter) _printCourseWMrow(course, courseWM)
if not FJQC.formatJSON: else:
csvPF.WriteRowTitles(row) courseMaterials = courseWM.pop('materials')
elif csvPF.CheckRowTitles(row): for courseMaterial in courseMaterials:
csvPF.WriteRowNoFilter({'courseId': course['id'], 'courseName': course['name'], courseWM['materials'] = courseMaterial
'JSON': json.dumps(cleanJSON(courseWM, timeObjects=TimeObjects), _printCourseWMrow(course, courseWM)
ensure_ascii=False, sort_keys=True)})
croom = buildGAPIObject(API.CLASSROOM) croom = buildGAPIObject(API.CLASSROOM)
if entityIDType == Ent.COURSE_WORK_ID: if entityIDType == Ent.COURSE_WORK_ID:
@@ -49523,7 +49637,7 @@ def doPrintCourseWM(entityIDType, entityStateType):
courseShowProperties = _initCourseShowProperties(['name']) courseShowProperties = _initCourseShowProperties(['name'])
OBY = OrderBy(OrderbyChoiceMap) OBY = OrderBy(OrderbyChoiceMap)
creatorEmails = {} creatorEmails = {}
showCreatorEmail = showTopicNames = False oneItemPerRow = showCreatorEmail = showTopicNames = False
delimiter = GC.Values[GC.CSV_OUTPUT_FIELD_DELIMITER] delimiter = GC.Values[GC.CSV_OUTPUT_FIELD_DELIMITER]
countsOnly = showStudentsAsList = False countsOnly = showStudentsAsList = False
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
@@ -49540,6 +49654,9 @@ def doPrintCourseWM(entityIDType, entityStateType):
pass pass
elif myarg == 'orderby': elif myarg == 'orderby':
OBY.GetChoice() OBY.GetChoice()
elif myarg == 'oneitemperrow':
oneItemPerRow = True
csvPF.RemoveIndexedTitles('materials')
elif myarg in {'showcreatoremails', 'creatoremail'}: elif myarg in {'showcreatoremails', 'creatoremail'}:
showCreatorEmail = True showCreatorEmail = True
elif myarg == 'showtopicnames': elif myarg == 'showtopicnames':
@@ -49566,6 +49683,8 @@ def doPrintCourseWM(entityIDType, entityStateType):
coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties) coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties)
if coursesInfo is None: if coursesInfo is None:
return return
if countsOnly:
csvPF.SetFormatJSON(False)
applyCourseItemFilter = _setApplyCourseItemFilter(courseItemFilter, fieldsList) applyCourseItemFilter = _setApplyCourseItemFilter(courseItemFilter, fieldsList)
courseWMIds = courseWMSelectionParameters['courseWMIds'] courseWMIds = courseWMSelectionParameters['courseWMIds']
courseWMIdsLists = courseWMIds if isinstance(courseWMIds, dict) else {} courseWMIdsLists = courseWMIds if isinstance(courseWMIds, dict) else {}
@@ -49620,7 +49739,8 @@ def doPrintCourseWM(entityIDType, entityStateType):
# (orderby <CourseMaterialsOrderByFieldName> [ascending|descending])*) # (orderby <CourseMaterialsOrderByFieldName> [ascending|descending])*)
# [showcreatoremails|creatoremail] [showtopicnames] [fields <CourseMaterialFieldNameList>] # [showcreatoremails|creatoremail] [showtopicnames] [fields <CourseMaterialFieldNameList>]
# [timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] # [timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
# [countsonly] [formatjson [quotechar <Character>]] # [oneitemperrow]
# [countsonly|(formatjson [quotechar <Character>])]
def doPrintCourseMaterials(): def doPrintCourseMaterials():
doPrintCourseWM(Ent.COURSE_MATERIAL_ID, Ent.COURSE_MATERIAL_STATE) doPrintCourseWM(Ent.COURSE_MATERIAL_ID, Ent.COURSE_MATERIAL_STATE)
@@ -49631,7 +49751,8 @@ def doPrintCourseMaterials():
# [showcreatoremails|creatoremail] [showtopicnames] [fields <CourseWorkFieldNameList>] # [showcreatoremails|creatoremail] [showtopicnames] [fields <CourseWorkFieldNameList>]
# [showstudentsaslist [<Boolean>]] [delimiter <Character>] # [showstudentsaslist [<Boolean>]] [delimiter <Character>]
# [timefilter creationtime|updatetime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] # [timefilter creationtime|updatetime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
# [countsonly] [formatjson [quotechar <Character>]] # [oneitemperrow]
# [countsonly|(formatjson [quotechar <Character>])]
def doPrintCourseWork(): def doPrintCourseWork():
doPrintCourseWM(Ent.COURSE_WORK_ID, Ent.COURSE_WORK_STATE) doPrintCourseWM(Ent.COURSE_WORK_ID, Ent.COURSE_WORK_STATE)
@@ -49675,7 +49796,7 @@ def _gettingCourseSubmissionQuery(courseSubmissionStates, late, userId):
# (submissionids <CourseSubmissionIDEntity>)|((submissionstates <CourseSubmissionStateList>)*) [late|notlate] # (submissionids <CourseSubmissionIDEntity>)|((submissionstates <CourseSubmissionStateList>)*) [late|notlate]
# [fields <CourseSubmissionFieldNameList>] [showuserprofile] # [fields <CourseSubmissionFieldNameList>] [showuserprofile]
# [timefilter creationtime|updatetime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] # [timefilter creationtime|updatetime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
# [countsonly] [formatjson [quotechar <Character>]] # [countsonly|(formatjson [quotechar <Character>])]
def doPrintCourseSubmissions(): def doPrintCourseSubmissions():
def _printCourseSubmission(course, courseSubmission): def _printCourseSubmission(course, courseSubmission):
if applyCourseItemFilter and not _courseItemPassesFilter(courseSubmission, courseItemFilter): if applyCourseItemFilter and not _courseItemPassesFilter(courseSubmission, courseItemFilter):
@@ -49757,6 +49878,8 @@ def doPrintCourseSubmissions():
coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties, getOwnerId=True) coursesInfo = _getCoursesInfo(croom, courseSelectionParameters, courseShowProperties, getOwnerId=True)
if coursesInfo is None: if coursesInfo is None:
return return
if countsOnly:
csvPF.SetFormatJSON(False)
applyCourseItemFilter = _setApplyCourseItemFilter(courseItemFilter, fieldsList) applyCourseItemFilter = _setApplyCourseItemFilter(courseItemFilter, fieldsList)
courseWorkIds = courseWMSelectionParameters['courseWMIds'] courseWorkIds = courseWMSelectionParameters['courseWMIds']
courseWorkIdsLists = courseWorkIds if isinstance(courseWorkIds, dict) else {} courseWorkIdsLists = courseWorkIds if isinstance(courseWorkIds, dict) else {}
@@ -53503,16 +53626,16 @@ def infoCalendarEvents(users):
# gam <UserTypeEntity> print events <UserCalendarEntity> <EventEntity> <EventDisplayProperties>* # gam <UserTypeEntity> print events <UserCalendarEntity> <EventEntity> <EventDisplayProperties>*
# [fields <EventFieldNameList>] [showdayofweek] # [fields <EventFieldNameList>] [showdayofweek]
# [countsonly [eventrowfilter]] # (addcsvdata <FieldName> <String>)*
# [formatjson [quotechar <Character>]] [todrive <ToDriveAttribute>*] # [eventrowfilter]
# [countsonly|(formatjson [quotechar <Character>])] [todrive <ToDriveAttribute>*]
# gam <UserTypeEntity> show events <UserCalendarEntity> <EventEntity> <EventDisplayProperties>* # gam <UserTypeEntity> show events <UserCalendarEntity> <EventEntity> <EventDisplayProperties>*
# [fields <EventFieldNameList>] [showdayofweek] # [fields <EventFieldNameList>] [showdayofweek]
# [countsonly]] # ~[countsonly|formatjson]
# [formatjson]
def printShowCalendarEvents(users): def printShowCalendarEvents(users):
calendarEntity = getUserCalendarEntity() calendarEntity = getUserCalendarEntity()
calendarEventEntity = getCalendarEventEntity() calendarEventEntity = getCalendarEventEntity()
csvPF, FJQC, fieldsList = _getCalendarPrintShowEventOptions(calendarEventEntity, Ent.USER) csvPF, FJQC, fieldsList, addCSVData = _getCalendarPrintShowEventOptions(calendarEventEntity, Ent.USER)
i, count, users = getEntityArgument(users) i, count, users = getEntityArgument(users)
for user in users: for user in users:
i += 1 i += 1
@@ -53523,7 +53646,7 @@ def printShowCalendarEvents(users):
continue continue
Ind.Increment() Ind.Increment()
_printShowCalendarEvents(origUser, user, cal, calIds, jcount, calendarEventEntity, _printShowCalendarEvents(origUser, user, cal, calIds, jcount, calendarEventEntity,
csvPF, FJQC, fieldsList) csvPF, FJQC, fieldsList, addCSVData)
Ind.Decrement() Ind.Decrement()
if csvPF: if csvPF:
if calendarEventEntity['countsOnly'] and calendarEventEntity['eventRowFilter']: if calendarEventEntity['countsOnly'] and calendarEventEntity['eventRowFilter']:
@@ -53967,7 +54090,7 @@ def printShowStatusEvent(users, eventType):
for event in events: for event in events:
if showDayOfWeek: if showDayOfWeek:
_getEventDaysOfWeek(event) _getEventDaysOfWeek(event)
_printCalendarEvent(user, calId, event, csvPF, FJQC) _printCalendarEvent(user, calId, event, csvPF, FJQC, {})
if 'pdelta' in wlDate: if 'pdelta' in wlDate:
first = first.shift(**wlDate['pdelta']) first = first.shift(**wlDate['pdelta'])
last = last.shift(**wlDate['pdelta']) last = last.shift(**wlDate['pdelta'])
@@ -77218,7 +77341,7 @@ TASK_QUERY_STATE_MAP = {
# [updatedmin <Time>] # [updatedmin <Time>]
# [showcompleted [<Boolean>]] [showdeleted [<Boolean>]] [showhidden [<Boolean>]] [showall] # [showcompleted [<Boolean>]] [showdeleted [<Boolean>]] [showhidden [<Boolean>]] [showall]
# [orderby completed|due|updated] # [orderby completed|due|updated]
# [countsonly | (formatjson [quotechar <Character>])] # [countsonly|(formatjson [quotechar <Character>])]
def printShowTasks(users): def printShowTasks(users):
def _showTaskAndChildren(tasklist, taskId, k, compact): def _showTaskAndChildren(tasklist, taskId, k, compact):
if taskId in taskParentsProcessed: if taskId in taskParentsProcessed:
@@ -77285,8 +77408,11 @@ def printShowTasks(users):
csvPF.SetTitles(['User', CSVTitle]) csvPF.SetTitles(['User', CSVTitle])
else: else:
FJQC.GetFormatJSONQuoteChar(myarg, False) FJQC.GetFormatJSONQuoteChar(myarg, False)
if csvPF and FJQC.formatJSON: if csvPF:
csvPF.SetJSONTitles(['User', 'tasklistId', 'id', 'taskId', 'title', 'JSON']) if countsOnly:
csvPF.SetFormatJSON(False)
elif FJQC.formatJSON:
csvPF.SetJSONTitles(['User', 'tasklistId', 'id', 'taskId', 'title', 'JSON'])
i, count, users = getEntityArgument(users) i, count, users = getEntityArgument(users)
for user in users: for user in users:
i += 1 i += 1
@@ -77485,7 +77611,7 @@ def processTasklists(users):
# gam <UserTypeEntity> show tasklists # gam <UserTypeEntity> show tasklists
# [countsonly|formatjson] # [countsonly|formatjson]
# gam <UserTypeEntity> print tasklists [todrive <ToDriveAttribute>*] # gam <UserTypeEntity> print tasklists [todrive <ToDriveAttribute>*]
# [countsonly | (formatjson [quotechar <Character>])] # [countsonly|(formatjson [quotechar <Character>])]
def printShowTasklists(users): def printShowTasklists(users):
csvPF = CSVPrintFile(['User', 'id', 'title']) if Act.csvFormat() else None csvPF = CSVPrintFile(['User', 'id', 'title']) if Act.csvFormat() else None
if csvPF: if csvPF:
@@ -77503,6 +77629,8 @@ def printShowTasklists(users):
csvPF.SetTitles(['User', CSVTitle]) csvPF.SetTitles(['User', CSVTitle])
else: else:
FJQC.GetFormatJSONQuoteChar(myarg, True) FJQC.GetFormatJSONQuoteChar(myarg, True)
if countsOnly and csvPF:
csvPF.SetFormatJSON(False)
i, count, users = getEntityArgument(users) i, count, users = getEntityArgument(users)
for user in users: for user in users:
i += 1 i += 1

View File

@@ -69,6 +69,8 @@ CACHE_DISCOVERY_ONLY = 'cache_discovery_only'
CHANNEL_CUSTOMER_ID = 'channel_customer_id' CHANNEL_CUSTOMER_ID = 'channel_customer_id'
# Character set of batch, csv, data files # Character set of batch, csv, data files
CHARSET = 'charset' CHARSET = 'charset'
# When retrieving lists of Chat items from API, how many should be retrieved in each chunk
CHAT_MAX_RESULTS = 'chat_max_results'
# When retrieving lists of Google Classroom items from API, how many should be retrieved in each chunk # When retrieving lists of Google Classroom items from API, how many should be retrieved in each chunk
CLASSROOM_MAX_RESULTS = 'classroom_max_results' CLASSROOM_MAX_RESULTS = 'classroom_max_results'
# Path to client_secrets.json # Path to client_secrets.json
@@ -335,6 +337,7 @@ Defaults = {
CACHE_DISCOVERY_ONLY: TRUE, CACHE_DISCOVERY_ONLY: TRUE,
CHARSET: DEFAULT_CHARSET, CHARSET: DEFAULT_CHARSET,
CHANNEL_CUSTOMER_ID: '', CHANNEL_CUSTOMER_ID: '',
CHAT_MAX_RESULTS: '100',
CLASSROOM_MAX_RESULTS: '0', CLASSROOM_MAX_RESULTS: '0',
CLIENT_SECRETS_JSON: FN_CLIENT_SECRETS_JSON, CLIENT_SECRETS_JSON: FN_CLIENT_SECRETS_JSON,
CLOCK_SKEW_IN_SECONDS: '10', CLOCK_SKEW_IN_SECONDS: '10',
@@ -502,6 +505,7 @@ VAR_INFO = {
CACHE_DISCOVERY_ONLY: {VAR_TYPE: TYPE_BOOLEAN, VAR_SIGFILE: 'allcache.txt', VAR_SFFT: (TRUE, FALSE)}, CACHE_DISCOVERY_ONLY: {VAR_TYPE: TYPE_BOOLEAN, VAR_SIGFILE: 'allcache.txt', VAR_SFFT: (TRUE, FALSE)},
CHARSET: {VAR_TYPE: TYPE_STRING, VAR_ENVVAR: 'GAM_CHARSET', VAR_LIMITS: (1, None)}, CHARSET: {VAR_TYPE: TYPE_STRING, VAR_ENVVAR: 'GAM_CHARSET', VAR_LIMITS: (1, None)},
CHANNEL_CUSTOMER_ID: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)}, CHANNEL_CUSTOMER_ID: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
CHAT_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 1000)},
CLASSROOM_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (0, 1000)}, CLASSROOM_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (0, 1000)},
CLIENT_SECRETS_JSON: {VAR_TYPE: TYPE_FILE, VAR_ENVVAR: 'CLIENTSECRETS', VAR_ACCESS: os.R_OK}, CLIENT_SECRETS_JSON: {VAR_TYPE: TYPE_FILE, VAR_ENVVAR: 'CLIENTSECRETS', VAR_ACCESS: os.R_OK},
CLOCK_SKEW_IN_SECONDS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (10, 3600)}, CLOCK_SKEW_IN_SECONDS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (10, 3600)},

View File

@@ -1138,6 +1138,7 @@ class GamCLArgs():
OB_ARGUMENT = 'argument' OB_ARGUMENT = 'argument'
OB_ASP_ID_LIST = 'ASPIDList' OB_ASP_ID_LIST = 'ASPIDList'
OB_ASSET_ID = 'AssetID' OB_ASSET_ID = 'AssetID'
OB_ADMIN_ASSIGNEE_TYPE_LIST = 'AdminAssigneeTypeList'
OB_BROWSER_ENROLLEMNT_TOKEN_ID = 'BrowserEnrollmentTokenID' OB_BROWSER_ENROLLEMNT_TOKEN_ID = 'BrowserEnrollmentTokenID'
OB_BROWSER_ENTITY = 'BrowserEntity' OB_BROWSER_ENTITY = 'BrowserEntity'
OB_BUILDING_ID = 'BuildingID' OB_BUILDING_ID = 'BuildingID'

View File

@@ -96,6 +96,7 @@ class GamEntity():
CHAT_MEMBER_USER = 'chmu' CHAT_MEMBER_USER = 'chmu'
CHAT_MESSAGE = 'chms' CHAT_MESSAGE = 'chms'
CHAT_MESSAGE_ID = 'chmi' CHAT_MESSAGE_ID = 'chmi'
CHAT_OWNER_USER = 'chou'
CHAT_SPACE = 'chsp' CHAT_SPACE = 'chsp'
CHAT_THREAD = 'chth' CHAT_THREAD = 'chth'
CHILD_ORGANIZATIONAL_UNIT = 'corg' CHILD_ORGANIZATIONAL_UNIT = 'corg'
@@ -462,6 +463,7 @@ class GamEntity():
CHAT_MEMBER: ['Chat Members', 'Chat Member'], CHAT_MEMBER: ['Chat Members', 'Chat Member'],
CHAT_MEMBER_GROUP: ['Chat Group Members', 'Chat Group Member'], CHAT_MEMBER_GROUP: ['Chat Group Members', 'Chat Group Member'],
CHAT_MEMBER_USER: ['Chat User Members', 'Chat User Member'], CHAT_MEMBER_USER: ['Chat User Members', 'Chat User Member'],
CHAT_OWNER_USER: ['Chat User Owners', 'Chat User Owner'],
CHAT_SPACE: ['Chat Spaces', 'Chat Space'], CHAT_SPACE: ['Chat Spaces', 'Chat Space'],
CHAT_THREAD: ['Chat Threads', 'Chat Thread'], CHAT_THREAD: ['Chat Threads', 'Chat Thread'],
CHILD_ORGANIZATIONAL_UNIT: ['Child Organizational Units', 'Child Organizational Unit'], CHILD_ORGANIZATIONAL_UNIT: ['Child Organizational Units', 'Child Organizational Unit'],

View File

@@ -1475,16 +1475,20 @@ gam delete admin <RoleAssignmentId>
## Display administrators ## Display administrators
``` ```
gam print admins [todrive <ToDriveAttribute>*] gam print admins [todrive <ToDriveAttribute>*]
[user|group <EmailAddress>|<UniqueID>] [role <RoleItem>] [condition] [user|group <EmailAddress>|<UniqueID>] [role <RoleItem>]
[privileges] [oneitemperrow] [recursive] [condition] [privileges] [oneitemperrow]
gam show admins gam show admins
[user|group <EmailAddress>|<UniqueID>] [role <RoleItem>] [condition] [privileges] [user|group <EmailAddress>|<UniqueID>] [role <RoleItem>]
[recursive] [condition] [privileges]
``` ```
By default, all administrators and roles are displayed; choose from the following By default, all administrators and roles are displayed; choose from the following
options to limit the display: options to limit the display:
* `user <UserItem>` - Display only this administrator * `user|group <EmailAddress>|<UniqueID>` - Display assignments to this administrator
* `role <RoleItem>` - Display only administrators with this role * `role <RoleItem>` - Display only administrators with this role
By default, assignments to security groups are shown as a single item; use `recursive`
to display assignments to the members of the security groups; the security group membershop is recursively expanded.
* `condition` - Display any conditions associated with a role assignment * `condition` - Display any conditions associated with a role assignment
* `privileges` - Display privileges associated with each role assignment * `privileges` - Display privileges associated with each role assignment

View File

@@ -567,7 +567,7 @@ By default, Gam displays the information as an indented list of keys and values.
``` ```
gam calendar <CalendarEntity> show events [<EventEntity>] <EventDisplayProperty>* gam calendar <CalendarEntity> show events [<EventEntity>] <EventDisplayProperty>*
[fields <EventFieldNameList>] [showdayofweek] [fields <EventFieldNameList>] [showdayofweek]
[countsly] [formatjson] [countsly|formatjson]
``` ```
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options. In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
@@ -586,8 +586,9 @@ By default, Gam displays event details, use `countsonly` to display only the num
``` ```
gam calendar <CalendarEntity> print events [<EventEntity>] <EventDisplayProperty>* gam calendar <CalendarEntity> print events [<EventEntity>] <EventDisplayProperty>*
[fields <EventFieldNameList>] [showdayofweek] [fields <EventFieldNameList>] [showdayofweek]
[countsonly [eventrowfilter]] (addcsvdata <FieldName> <String>)*
[formatjson [quotechar <Character>]] [todrive <ToDriveAttribute>*] [eventrowfilter]
[countsonly|(formatjson [quotechar <Character>])] [todrive <ToDriveAttribute>*]
``` ```
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options. In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
@@ -598,6 +599,9 @@ option `singleevents` to display all instances of a recurring event.
`showdayofweek` displays columns `start.dayOfWeek` and `end.dayOfWeek` when event start and end times are displayed. `showdayofweek` displays columns `start.dayOfWeek` and `end.dayOfWeek` when event start and end times are displayed.
Add additional columns of data from the command line to the output after the calendarId.
* `addcsvdata <FieldName> <String>`
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format, 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. * `formatjson` - Display the fields in JSON format.

View File

@@ -570,6 +570,7 @@ gam print course-materials [todrive <ToDriveAttribute>*]
(orderby <CourseMaterialOrderByFieldName> [ascending|descending])*) (orderby <CourseMaterialOrderByFieldName> [ascending|descending])*)
[showcreatoremails|creatoremail] [showtopicnames] [fields <CourseMaterialFieldNameList>] [showcreatoremails|creatoremail] [showtopicnames] [fields <CourseMaterialFieldNameList>]
[timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
[oneitemperrow]
[countsonly] [formatjson [quotechar <Character>]] [countsonly] [formatjson [quotechar <Character>]]
``` ```
By default, the `print course-materials` command displays course materials information for all courses. By default, the `print course-materials` command displays course materials information for all courses.
@@ -600,6 +601,10 @@ By default, all course materials fields are displayed; use the following options
* `showtopicnames` - Display topic names; requires and additional API call per course. * `showtopicnames` - Display topic names; requires and additional API call per course.
* `fields <CourseMaterialsFieldNameList>` - Select specific fields to display. * `fields <CourseMaterialsFieldNameList>` - Select specific fields to display.
With `print course-materials`, the materials selected for display are all output on one row/line as a repeating item with the other course fields.
When `oneitemperrow` is specified, each material is output on a separate row/line with the other course fields.
This simplifies processing the materials in the CSV file with subsequent Gam commands.
Use the `countsonly` option to display the number of course materials in a course but not their details. Use the `countsonly` option to display the number of course materials in a course but not their details.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format, By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
@@ -662,6 +667,7 @@ gam print course-work [todrive <ToDriveAttribute>*]
[showcreatoremails] [showtopicnames] [fields <CourseWorkFieldNameList>] [showcreatoremails] [showtopicnames] [fields <CourseWorkFieldNameList>]
[showstudentsaslist [<Boolean>]] [delimiter <Character>] [showstudentsaslist [<Boolean>]] [delimiter <Character>]
[timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
[oneitemperrow]
[countsonly] [formatjson [quotechar <Character>]] [countsonly] [formatjson [quotechar <Character>]]
``` ```
By default, the `print course-work` command displays course work information for all courses. By default, the `print course-work` command displays course work information for all courses.
@@ -695,6 +701,10 @@ By default, all course work fields are displayed; use the following options to m
By default, when course work is assigned to individual students, the student IDs are displayed in multiple indexed columns. By default, when course work is assigned to individual students, the student IDs are displayed in multiple indexed columns.
Use options `showstudentsaslist [<Boolean>]` and `delimiter <Character>` to display the student IDs is a single column as a delimited list. Use options `showstudentsaslist [<Boolean>]` and `delimiter <Character>` to display the student IDs is a single column as a delimited list.
With `print course-work`, any materials are all output on one row/line as a repeating item with the other course fields.
When `oneitemperrow` is specified, each material is output on a separate row/line with the other course fields.
This simplifies processing the materials in the CSV file with subsequent Gam commands.
Use the `countsonly` option to display the number of course works in a course but not their details. Use the `countsonly` option to display the number of course works in a course but not their details.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format, By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,

View File

@@ -10,7 +10,7 @@
- [Delete duplicate email addresses from contacts](#delete-duplicate-email-addresses-from-contacts) - [Delete duplicate email addresses from contacts](#delete-duplicate-email-addresses-from-contacts)
- [Manage domain contact photos](#manage-domain-contact-photos) - [Manage domain contact photos](#manage-domain-contact-photos)
- [Display domain shared contacts](#display-domain-shared-contacts) - [Display domain shared contacts](#display-domain-shared-contacts)
- [Display global address list](#display-global-address-list) - [Display global address list](#Global-Address-List)
## API documentation ## API documentation
* [Domain Shared Contacts API](https://developers.google.com/admin-sdk/domain-shared-contacts) * [Domain Shared Contacts API](https://developers.google.com/admin-sdk/domain-shared-contacts)

View File

@@ -25,14 +25,14 @@ start a new terminal session and reissue the command from above.
## Executable, Manual ## Executable, Manual
* Executable Archive, Manual, Linux/Google Cloud Shell * Executable Archive, Manual, Linux/Google Cloud Shell
- `gam-7.wx.yz-linux-x86_64-glibc2.35.tar.xz` - `gam-7.wx.yz-linux-x86_64-glibc2.36.tar.xz`
- `gam-7.wx.yz-linux-x86_64-glibc2.39.tar.xz` - `gam-7.wx.yz-linux-x86_64-glibc2.39.tar.xz`
- `gam-7.wx.yz-linux-x86_64-legacy.tar.xz` - `gam-7.wx.yz-linux-x86_64-legacy.tar.xz`
- Download the archive, extract the contents into some directory. - Download the archive, extract the contents into some directory.
- Start a terminal session. - Start a terminal session.
* Executable Archive, Manual, Raspberry Pi/ChromeOS ARM devices * Executable Archive, Manual, Raspberry Pi/ChromeOS ARM devices
- `gam-7.wx.yz-linux-arm64-glibc2.35.tar.xz` - `gam-7.wx.yz-linux-arm64-glibc2.36.tar.xz`
- `gam-7.wx.yz-linux-arm64-glibc2.39.tar.xz` - `gam-7.wx.yz-linux-arm64-glibc2.39.tar.xz`
- `gam-7.wx.yz-linux-arm64-legacy.tar.xz` - `gam-7.wx.yz-linux-arm64-legacy.tar.xz`
- Download the archive, extract the contents into some directory. - Download the archive, extract the contents into some directory.
@@ -43,16 +43,26 @@ start a new terminal session and reissue the command from above.
- Download the archive, extract the contents into some directory. - Download the archive, extract the contents into some directory.
- Start a terminal session. - Start a terminal session.
* Executable Archive, Manual, Mac OS versions Sequoia - M3 * Executable Archive, Manual, Mac OS versions Sequoia - M2/M3
- `gam-7.wx.yz-macos15.4-arm64.tar.xz` - `gam-7.wx.yz-macos15.6-arm64.tar.xz`
- Download the archive, extract the contents into some directory. - Download the archive, extract the contents into some directory.
- Start a terminal session. - Start a terminal session.
* Executable Archive, Manual, Mac OS, versions Ventura, Sonoma, Sequoia - Intel * Executable Archive, Manual, Mac OS versions Tahoe - M2/M3/M4
- `gam-7.wx.yz-macos26.0-arm64.tar.xz`
- Download the archive, extract the contents into some directory.
- Start a terminal session.
* Executable Archive, Manual, Mac OS, versions Ventura, Sonoma - Intel
- `gam-7.wx.yz-macos13.7-x86_64.tar.xz` - `gam-7.wx.yz-macos13.7-x86_64.tar.xz`
- Download the archive, extract the contents into some directory. - Download the archive, extract the contents into some directory.
- Start a terminal session. - Start a terminal session.
* Executable Archive, Manual, Mac OS, versions Sequoia, Tahoe - Intel
- `gam-7.wx.yz-macos15.6-x86_64.tar.xz`
- Download the archive, extract the contents into some directory.
- Start a terminal session.
* Executable Archive, Manual, Windows 64 bit * Executable Archive, Manual, Windows 64 bit
- `gam-7.wx.yz-windows-x86_64.zip` - `gam-7.wx.yz-windows-x86_64.zip`
- Download the archive, extract the contents into some directory. - Download the archive, extract the contents into some directory.

View File

@@ -10,6 +10,51 @@ 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.23.05
Added option `recursive` to `gam print|show admins` that will display assignments to the members
of security groups assigned to roles; the security group membership is recursively expanded.
### 7.23.04
Added option `addcsvdata <FieldName> <String>` to `gam <UserTypeEntity> print events`
and `gam calendars <CalendarEntity> print events` that adds additional columns of data to the CSV file output.
An example would be to get the calendar name in addition to the calendar ID when printing events.
```
gam redirect csv ./Resources.csv print resources fields email,name
gam redirect csv ./ResourceEventCounts.csv multiprocess redirect stderr - multiprocess csv Resources.csv gam calendar "~resourceEmail" print events starttime -1y countsonly addcsvdata calendarName "~resourceName"
```
Upgraded to OpenSSL 3.6.0.
### 7.23.03
Upgraded to OpenSSL 3.5.4.
### 7.23.02
Added option `oneitemperrow` to 'gam print course-materials|course-work` to have each of a
course's materials displayed on a separate row with all of the other course fields.
This produces a CSV file that can be used in subsequent commands to process the materials without further script processing.
### 7.23.00
Added `chat_max_results` variable to `gam.cfg`.
```
chat_max_results
When retrieving lists of Chat items from API,
how many should be retrieved in each API call
Default: 100
Range: 1 - 1000
```
Previously, this vaule was always set to 1000 which could cause errors.
### 7.22.07
Added options `showdetails` and `returnidonly` to `gam create|copy vaultquery`.
Added option `<JSONData>` to `gam create vaultexport|vaultquery and `gam print vaultcounts``.
### 7.22.06 ### 7.22.06
Added commands to create, copy and delete Vault saved queries. Added commands to create, copy and delete Vault saved queries.

View File

@@ -252,10 +252,10 @@ 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.22.06 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.23.05 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.7 64-bit final Python 3.13.7 64-bit final
MacOS Sequoia 15.6.1 x86_64 macOS Tahoe 26.0.1 x86_64
Path: /Users/admin/bin/gam7 Path: /Users/admin/bin/gam7
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com

View File

@@ -378,7 +378,7 @@ Select the users for whom information is desired.
* `showorgunit` - Add a column labelled `orgUnitPath` to the output; an additional API call is made to get the email addresses of the users in `<OrgUnitPath>` * `showorgunit` - Add a column labelled `orgUnitPath` to the output; an additional API call is made to get the email addresses of the users in `<OrgUnitPath>`
* `select <UserTypeEntity>` - A selected collection of users, e.g., `select group staff@domain.com`; there is one API call per user * `select <UserTypeEntity>` - A selected collection of users, e.g., `select group staff@domain.com`; there is one API call per user
By default, when `user all` is specified (or no user specification in supplied), GAM backs up looking for data with a (basically) random user. If the randaom By default, when `user all` is specified (or no user specification in supplied), GAM backs up looking for data with a (basically) random user. If the random
doesn't have any data, the command reports that no data was found. Use `allverifyuser <UserItem>` to specify a specific user to use to search for data. doesn't have any data, the command reports that no data was found. Use `allverifyuser <UserItem>` to specify a specific user to use to search for data.
Specify the report date; the default is today's date. Specify the report date; the default is today's date.

View File

@@ -653,7 +653,7 @@ By default, Gam displays the information as an indented list of keys and values.
``` ```
gam <UserTypeEntity> show events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>* gam <UserTypeEntity> show events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>*
[fields <EventFieldNameList>] [showdayofweek] [fields <EventFieldNameList>] [showdayofweek]
[countsonly] [formatjson] [countsonly|formatjson]
``` ```
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options. In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
@@ -672,8 +672,8 @@ By default, Gam displays event details, use `countsonly` to display only the num
``` ```
gam <UserTypeEntity> print events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>* gam <UserTypeEntity> print events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>*
[fields <EventFieldNameList>] [showdayofweek] [fields <EventFieldNameList>] [showdayofweek]
[countsonly] (addcsvdata <FieldName> <String>)*
[formatjson [quotechar <Character>]] [todrive <ToDriveAttribute>*] [eventrowfilter] [countsonly|(formatjson [quotechar <Character>])] [todrive <ToDriveAttribute>*]
``` ```
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options. In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
@@ -684,6 +684,9 @@ option `singleevents` to display all instances of a recurring event.
`showdayofweek` displays columns `start.dayOfWeek` and `end.dayOfWeek` when event start and end times are displayed. `showdayofweek` displays columns `start.dayOfWeek` and `end.dayOfWeek` when event start and end times are displayed.
Add additional columns of data from the command line to the output after the calendarId.
* `addcsvdata <FieldName> <String>`
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format, 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. * `formatjson` - Display the fields in JSON format.

View File

@@ -398,8 +398,8 @@ By default, Gam displays the information as an indented list of keys and values.
gam <UserTypeEntity> show contacts gam <UserTypeEntity> show contacts
<PeoplePrintShowUserContactSelection> <PeoplePrintShowUserContactSelection>
[orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending) [orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
[countsonly|allfields|(fields <PeopleFieldNameList>)] [showgroups] [showmetadata] [allfields|(fields <PeopleFieldNameList>)] [showgroups] [showmetadata]
[formatjson] [countsonly|formatjson]
``` ```
By default, Gam displays all of a user's people contacts. By default, Gam displays all of a user's people contacts.
* `query <String>` - Display contacts based on the data in their fields * `query <String>` - Display contacts based on the data in their fields
@@ -416,8 +416,8 @@ By default, Gam displays the information as an indented list of keys and values.
gam <UserTypeEntity> print contacts [todrive <ToDriveAttribute>*] gam <UserTypeEntity> print contacts [todrive <ToDriveAttribute>*]
<PeoplePrintShowUserContactSelection> <PeoplePrintShowUserContactSelection>
[orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending) [orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
[countsonly|allfields|(fields <PeopleFieldNameList>)] [showgroups] [showmetadata] [allfields|(fields <PeopleFieldNameList>)] [showgroups] [showmetadata]
[formatjson [quotechar <Character>]] [countsonly|(formatjson [quotechar <Character>])]
``` ```
By default, Gam displays all of a user's people contacts. By default, Gam displays all of a user's people contacts.
* `query <String>` - Display contacts based on the data in their fields * `query <String>` - Display contacts based on the data in their fields
@@ -547,8 +547,8 @@ User: user@domain.com, Delete maximum of 15 Other Contacts
``` ```
gam <UserTypeEntity> show othercontacts gam <UserTypeEntity> show othercontacts
[<OtherContactsSelection>] [<OtherContactsSelection>]
[countsonly|allfields|(fields <OtherContactsFieldNameList>)] [showmetadata] [allfields|(fields <OtherContactsFieldNameList>)] [showmetadata]
[formatjson] [countsonly|formatjson]
``` ```
By default, Gam displays all of a user's Other Contacts; use By default, Gam displays all of a user's Other Contacts; use
`<OtherContactsSelection>` to display a selection of Other Contacts. `<OtherContactsSelection>` to display a selection of Other Contacts.
@@ -563,8 +563,8 @@ By default, Gam displays the information as an indented list of keys and values.
``` ```
gam <UserTypeEntity> print othercontacts [todrive <ToDriveAttribute>*] gam <UserTypeEntity> print othercontacts [todrive <ToDriveAttribute>*]
[<OtherContactsSelection>] [<OtherContactsSelection>]
[countsonly|allfields|(fields <OtherContactsFieldNameList>)] [showmetadata] [allfields|(fields <OtherContactsFieldNameList>)] [showmetadata]
[formatjson [quotechar <Character>]] [countsonly|(formatjson [quotechar <Character>])]
``` ```
By default, Gam displays all of a user's Other Contacts; use By default, Gam displays all of a user's Other Contacts; use
`<OtherContactsSelection>` to display a selection of Other Contacts. `<OtherContactsSelection>` to display a selection of Other Contacts.

View File

@@ -122,7 +122,7 @@ gam <UserTypeEntity> show tasks [tasklists <TasklistEntity>]
[updatedmin <Time>] [updatedmin <Time>]
[showcompleted [<Boolean>]] [showdeleted [<Boolean>]] [showhidden [<Boolean>]] [showall] [showcompleted [<Boolean>]] [showdeleted [<Boolean>]] [showhidden [<Boolean>]] [showall]
[orderby completed|due|updated] [orderby completed|due|updated]
[countsonly|compact|formatjson] [compact|countsonly|formatjson]
``` ```
The API only supports dates in `duemin` and `duemax' but you must supply a null time: The API only supports dates in `duemin` and `duemax' but you must supply a null time:
* `duemin YYYY-MM-DDT00:00:00Z` - Specify the starting due date * `duemin YYYY-MM-DDT00:00:00Z` - Specify the starting due date
@@ -152,7 +152,7 @@ gam <UserTypeEntity> print tasks [tasklists <TasklistEntity>] [todrive <ToDriveA
[updatedmin <Time>] [updatedmin <Time>]
[showcompleted [<Boolean>]] [showdeleted [<Boolean>]] [showhidden [<Boolean>]] [showall] [showcompleted [<Boolean>]] [showdeleted [<Boolean>]] [showhidden [<Boolean>]] [showall]
[orderby completed|due|updated] [orderby completed|due|updated]
[countsonly | (formatjson [quotechar <Character>])] [countsonly|(formatjson [quotechar <Character>])]
``` ```
The API only supports dates in `duemin` and `duemax' but you must supply a null time: The API only supports dates in `duemin` and `duemax' but you must supply a null time:
* `duemin YYYY-MM-DDT00:00:00Z` - Specify the starting due date * `duemin YYYY-MM-DDT00:00:00Z` - Specify the starting due date
@@ -230,7 +230,7 @@ By default, Gam displays the task lists as an indented list of keys and values.
``` ```
gam <UserTypeEntity> print tasklists [todrive <ToDriveAttribute>*] gam <UserTypeEntity> print tasklists [todrive <ToDriveAttribute>*]
[countsonly | (formatjson [quotechar <Character>])] [countsonly|(formatjson [quotechar <Character>])]
``` ```
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format, 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. * `formatjson` - Display the fields in JSON format.

View File

@@ -3,6 +3,7 @@
- [Query documentation](#query-documentation) - [Query documentation](#query-documentation)
- [Python Regular Expressions](Python-Regular-Expressions) Match function - [Python Regular Expressions](Python-Regular-Expressions) Match function
- [Definitions](#definitions) - [Definitions](#definitions)
- [Special quoting](#special-quoting)
- [Vault Matters](#vault-matters) - [Vault Matters](#vault-matters)
- [Create Vault Matters](#create-vault-matters) - [Create Vault Matters](#create-vault-matters)
- [Manage Vault Matters](#manage-vault-matters) - [Manage Vault Matters](#manage-vault-matters)
@@ -57,6 +58,7 @@
<EmailAddressList> ::= "<EmailAddess>(,<EmailAddress>)*" <EmailAddressList> ::= "<EmailAddess>(,<EmailAddress>)*"
<EmailAddressEntity> ::= <EmailAddressList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector> <EmailAddressEntity> ::= <EmailAddressList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
See: https://github.com/GAM-team/GAM/wiki/Collections-of-Items See: https://github.com/GAM-team/GAM/wiki/Collections-of-Items
<JSONData> ::= (json [charset <Charset>] <String>) | (json file <FileName> [charset <Charset>]) |
<TimeZone> ::= <String> <TimeZone> ::= <String>
See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
<UniqueID> ::= id:<String> <UniqueID> ::= id:<String>
@@ -76,6 +78,7 @@
<ExportStatusList> ::= "<ExportStatus>(,<ExportStatus>)*" <ExportStatusList> ::= "<ExportStatus>(,<ExportStatus>)*"
<HoldItem> ::= <UniqueID>|<String> <HoldItem> ::= <UniqueID>|<String>
<MatterItem> ::= <UniqueID>|<String> <MatterItem> ::= <UniqueID>|<String>
<MatterItemList> ::= "<MatterItem>(,<MatterItem>)*"
<MatterState> ::= open|closed|deleted <MatterState> ::= open|closed|deleted
<MatterStateList> ::= "<MatterState>(,<MatterState>)*" <MatterStateList> ::= "<MatterState>(,<MatterState>)*"
<QueryItem> ::= <UniqueID>|<String> <QueryItem> ::= <UniqueID>|<String>
@@ -141,9 +144,29 @@
<VaultQueryFieldNameList> ::= "<VaultQueryFieldName>(,<VaultQueryFieldName>)*" <VaultQueryFieldNameList> ::= "<VaultQueryFieldName>(,<VaultQueryFieldName>)*"
``` ```
You specify matters, exports and holds by ID (`<UniqueID>`) or name (`<String>`). The API requires an ID, so if you specify a name, You specify matters, exports and holds by ID (`<UniqueID>`) or name (`<String>`). The API requires an ID, so if you specify a name,
GAM has to make additional API calls to convert the name to an ID. GAM has to make additional API calls to convert the name to an ID.
## Special quoting
You specify a single matter with `matter <MatterItem>` and a list of matters with `matters <MatterItemList>`.
As matter names can contain spaces, some care must be used when entering `<MatterItem>` and `<MatterItemList>` with names.
Suppose you have a matter `Foo Bar`. To get information about a specific export: `gam info vaultexport "Foo Bar" <ExportItem>`
The shell strips the `"` leaving a single argument `Foo Bar`; gam correctly processes the argument.
Suppose you enter the command: `gam show vaultexports matters "Foo Bar"`
The shell strips the `"` leaving a single argument `Foo Bar`; gam splits the argument on space leaving two items and then tries to process `Foo` and `Bar`, not what you want.
You must enter: `gam info show vaultexports matters "'Foo Bar'"`
The shell strips the `"` leaving a single argument `'Foo Bar'`; gam splits the argument on space while honoring the `'` leaving one item `Foo Bar` and correctly processes the item.
For quoting rules, see: [List Quoting Rules](Command-Line-Parsing)
## Vault Matters ## Vault Matters
## Create Vault Matters ## Create Vault Matters
Create a Google Vault matter. Create a Google Vault matter.
@@ -232,12 +255,13 @@ gam print vaultcounts [todrive <ToDriveAttributes>*]
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone|entireorg (accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone|entireorg
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>] [terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
[excludedrafts <Boolean>] [excludedrafts <Boolean>]
[<JSONData>]
[wait <Integer>] [wait <Integer>]
``` ```
Specify the search method, this is optional: Specify the search method, this is optional:
* `accounts <EmailAddressEntity>` - Search all accounts specified in `<EmailAddressEntity>` * `accounts <EmailAddressEntity>` - Search all accounts specified in `<EmailAddressEntity>`
* `orgunit|org|ou <OrgUnitPath>` - Search all accounts in the OU `<OrgUnitPath>` * `orgunit|org|ou <OrgUnitPath>` - Search all accounts in the OU `<OrgUnitPath>`
* `everyone` - Search for all accounts in the organization * `everyone|entireorg` - Search for all accounts in the organization
For `corpus mail|group`, you can specify search terms to limit the search. For `corpus mail|group`, you can specify search terms to limit the search.
* `terms <String>` - [Vault search](https://support.google.com/vault/answer/2474474) * `terms <String>` - [Vault search](https://support.google.com/vault/answer/2474474)
@@ -246,6 +270,8 @@ For `corpus mail|group`, you can specify time limits on the search:
* `start|starttime <Date>|<Time>` - The start time range for the search query. These timestamps are in GMT and rounded down to the start of the given date. * `start|starttime <Date>|<Time>` - The start time range for the search query. These timestamps are in GMT and rounded down to the start of the given date.
* `end|endtime <Date>|<Time>` - The end time range for the search query. These timestamps are in GMT and rounded down to the start of the given date. * `end|endtime <Date>|<Time>` - The end time range for the search query. These timestamps are in GMT and rounded down to the start of the given date.
You can specify query options with `<JSONData>`.
Check the status of a previous count operation with the name from a previous command. Check the status of a previous count operation with the name from a previous command.
``` ```
gam print vaultcounts [todrive <ToDriveAttributes>*] gam print vaultcounts [todrive <ToDriveAttributes>*]
@@ -283,6 +309,7 @@ gam create vaultexport|export matter <MatterItem> [name <String>]
[locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>] [locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>]
[responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>] [responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>]
(covereddata calllogs|textmessages|voicemails)* (covereddata calllogs|textmessages|voicemails)*
[<JSONData>]
[driveclientsideencryption any|encrypted|unencrypted] [driveclientsideencryption any|encrypted|unencrypted]
[includeaccessinfo <Boolean>] [includeaccessinfo <Boolean>]
[excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted] [excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted]
@@ -308,7 +335,7 @@ Specify the corpus of data, this option is required:
Specify the search method, this option is required: Specify the search method, this option is required:
* `accounts <EmailAddressEntity>` - Search all accounts specified in `<EmailAddressEntity>` * `accounts <EmailAddressEntity>` - Search all accounts specified in `<EmailAddressEntity>`
* `orgunit|org|ou <OrgUnitPath>` - Search all accounts in the OU `<OrgUnitPath>` * `orgunit|org|ou <OrgUnitPath>` - Search all accounts in the OU `<OrgUnitPath>`
* `everyone` - Search for all accounts in the organization * `everyone|entireorg` - Search for all accounts in the organization
* `documentids <DriveFileIDList>` - Search for all drive files specified in `<DriveFileIDList>` * `documentids <DriveFileIDList>` - Search for all drive files specified in `<DriveFileIDList>`
* `documentids select <FileSelector>|<CSVFileSelector>` - Search for all drive files specified in `<FileSelector>|<CSVFileSelector>` * `documentids select <FileSelector>|<CSVFileSelector>` - Search for all drive files specified in `<FileSelector>|<CSVFileSelector>`
* `shareddrives|teamdrives <SharedDriveIDList>` - Search for all accounts in the Shared Drives specified in `<SharedDriveIDList>` * `shareddrives|teamdrives <SharedDriveIDList>` - Search for all accounts in the Shared Drives specified in `<SharedDriveIDList>`
@@ -349,10 +376,6 @@ For `corpus calendar`, you can specify advanced search options:
* Search the current version of the Calendar event, but export the contents of the last version saved before 12:00 AM UTC on the specified date. * Search the current version of the Calendar event, but export the contents of the last version saved before 12:00 AM UTC on the specified date.
* Enter the date in UTC. * Enter the date in UTC.
For `corpus calendar`, you can specify the format of the exported data:
* `format ics` - Export in ICS format, this is the default
* `format pst` - Export in PST format
For `corpus drive`, you can specify advanced search options: For `corpus drive`, you can specify advanced search options:
* `driveversiondate <Date>|<Time>` - Search the versions of the Drive file as of the reference date. These timestamps are in GMT and rounded down to the given date. * `driveversiondate <Date>|<Time>` - Search the versions of the Drive file as of the reference date. These timestamps are in GMT and rounded down to the given date.
* `includeshareddrives False` - Mapped to `sharedrivesoption included_if_account_is_not_a_member` * `includeshareddrives False` - Mapped to `sharedrivesoption included_if_account_is_not_a_member`
@@ -360,6 +383,16 @@ For `corpus drive`, you can specify advanced search options:
* `sharedrivesoption included` - Resources in shared drives are included in the search * `sharedrivesoption included` - Resources in shared drives are included in the search
* `sharedrivesoption included_if_account_is_not_a_member` - Resources in shared drives where account is not a member are included in the search, this is the default * `sharedrivesoption included_if_account_is_not_a_member` - Resources in shared drives where account is not a member are included in the search, this is the default
* `sharedrivesoption not_included` - Resources in shared drives are not included in the search * `sharedrivesoption not_included` - Resources in shared drives are not included in the search
For `corpus hangouts_chat` you can specify advanced search options:
* `includerooms False` - Do not include rooms, this is the default
* `includerooms True` - Include rooms
You can specify query options with `<JSONData>`.
## Vault Export options
For `corpus drive`, you can specify advanced search options:
* `driveclientsideencryption any` - Include both client-side encrypted and unencrypted content in search, this is the default. * `driveclientsideencryption any` - Include both client-side encrypted and unencrypted content in search, this is the default.
* `driveclientsideencryption encrypted` - Include client-side encrypted content only in search. * `driveclientsideencryption encrypted` - Include client-side encrypted content only in search.
* `driveclientsideencryption unencrypted` - Include client-side unencrypted content only in search. * `driveclientsideencryption unencrypted` - Include client-side unencrypted content only in search.
@@ -368,10 +401,6 @@ For `corpus drive`, you can specify whether to include access information for us
* `includeaccessinfo False` - Do not include access information for users with indirect access, this is the default * `includeaccessinfo False` - Do not include access information for users with indirect access, this is the default
* `includeaccessinfo True` - Include access information for users with indirect access * `includeaccessinfo True` - Include access information for users with indirect access
For `corpus hangouts_chat` you can specify advanced search options:
* `includerooms False` - Do not include rooms, this is the default
* `includerooms True` - Include rooms
For `corpus mail`, you can specify advanced search options: For `corpus mail`, you can specify advanced search options:
* `excludedrafts False` - Do not exclude drafts, this is the default * `excludedrafts False` - Do not exclude drafts, this is the default
* `excludedrafts True` - Exclude drafts * `excludedrafts True` - Exclude drafts
@@ -405,8 +434,7 @@ For `corpus groups`, `corpus hangouts_chat`, `corpus mail` and `corpus voice`, y
* `format mbox` - Export in MBOX format, this is the default * `format mbox` - Export in MBOX format, this is the default
* `format pst` - Export in PST format * `format pst` - Export in PST format
For `corpus voice` you can specify the data covered by the export, For `corpus voice` you can specify the data covered by the export, multiple values are allowed.:
multiple values are allowed.:
* `covereddata calllogs` - Call logs * `covereddata calllogs` - Call logs
* `covereddata textmessages` - Voice text messages * `covereddata textmessages` - Voice text messages
* `covereddata voicemail` - Voicemail * `covereddata voicemail` - Voicemail
@@ -817,8 +845,10 @@ gam create vaultquery <MatterItem> [name <String>]
[locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>] [locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>]
[responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>] [responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>]
(covereddata calllogs|textmessages|voicemails)* (covereddata calllogs|textmessages|voicemails)*
[shownames] [formatjson] [<JSONData>]
``` [shownames]
[showdetails|returnidonly|formatjson]
``
If `name <String>` is omitted, the query is named `GAM <corpus> Query - <Time>` If `name <String>` is omitted, the query is named `GAM <corpus> Query - <Time>`
@@ -826,10 +856,17 @@ The `shownames` argument controls whether org unit and shared drive names are di
See: [Vault Query options](#vault-query-options) See: [Vault Query options](#vault-query-options)
Use the `showdetails` option to have the full details of the saved query displayed.
Use the `returnidonly` option to have only the saved query ID displayed.
Use the `formatjson` option to have only the saved query JSON displayed.
## Copy Vault Saved Queries ## Copy Vault Saved Queries
``` ```
gam copy vaultquery <MatterItem> <QueryItem> [targetmatter <MatterItem>] [name <String>] gam copy vaultquery <MatterItem> <QueryItem> [targetmatter <MatterItem>] [name <String>]
[shownames] [formatjson] [shownames]
[showdetails|returnidonly|formatjson]
``` ```
If `targetmatter <MatterItem>` is omitted, the query is copied in the source matter. If `targetmatter <MatterItem>` is omitted, the query is copied in the source matter.
@@ -840,6 +877,12 @@ If `name <String>` is omitted:
The `shownames` argument controls whether org unit and shared drive names are displayed in queries; additional API calls are required to get the names. The `shownames` argument controls whether org unit and shared drive names are displayed in queries; additional API calls are required to get the names.
Use the `showdetails` option to have the full details of the saved query displayed.
Use the `returnidonly` option to have only the saved query ID displayed.
Use the `formatjson` option to have only the saved query JSON displayed.
## Delete Vault Saved Queries ## Delete Vault Saved Queries
``` ```
gam delete vaultquery <QueryItem> matter <MatterItem> gam delete vaultquery <QueryItem> matter <MatterItem>

View File

@@ -3,10 +3,10 @@
Print the current version of Gam with details Print the current version of Gam with details
``` ```
gam version gam version
GAM 7.22.06 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.23.05 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.7 64-bit final Python 3.13.7 64-bit final
macOS Sequoia 15.7 x86_64 macOS Tahoe 26.0.1 x86_64
Path: /Users/Admin/bin/gam7 Path: /Users/Admin/bin/gam7
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
Time: 2023-06-02T21:10:00-07:00 Time: 2023-06-02T21:10:00-07:00
@@ -15,10 +15,10 @@ 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.22.06 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.23.05 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.7 64-bit final Python 3.13.7 64-bit final
macOS Sequoia 15.7 x86_64 macOS Tahoe 26.0.1 x86_64
Path: /Users/Admin/bin/gam7 Path: /Users/Admin/bin/gam7
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
Your system time differs from www.googleapis.com by less than 1 second Your system time differs from www.googleapis.com by less than 1 second
@@ -27,10 +27,10 @@ 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.22.06 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.23.05 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.7 64-bit final Python 3.13.7 64-bit final
macOS Sequoia 15.7 x86_64 macOS Tahoe 26.0.1 x86_64
Path: /Users/Admin/bin/gam7 Path: /Users/Admin/bin/gam7
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
Time: 2023-06-02T21:10:00-07:00 Time: 2023-06-02T21:10:00-07:00
@@ -89,7 +89,7 @@ gam help
GAM 7.22.00 - https://github.com/GAM-team/GAM GAM 7.22.00 - https://github.com/GAM-team/GAM
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.7 64-bit final Python 3.13.7 64-bit final
macOS Sequoia 15.7 x86_64 macOS Tahoe 26.0.1 x86_64
Path: /Users/Admin/bin/gam7 Path: /Users/Admin/bin/gam7
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
Time: 2023-06-02T21:10:00-07:00 Time: 2023-06-02T21:10:00-07:00

View File

@@ -109,6 +109,11 @@ charset
Character set of gam batch, gam csv, gam loop files. Character set of gam batch, gam csv, gam loop files.
Default: utf-8 Default: utf-8
Environment variable: GAM_CHARSET Environment variable: GAM_CHARSET
chat_max_results
When retrieving lists of Chat items from API,
how many should be retrieved in each API call
Default: 100
Range: 1 - 1000
classroom_max_results classroom_max_results
When retrieving lists of Google Classroom items from API, When retrieving lists of Google Classroom items from API,
how many should be retrieved in each API call how many should be retrieved in each API call