mirror of
https://github.com/GAM-team/GAM.git
synced 2026-07-03 20:31:35 +00:00
Compare commits
80 Commits
v7.0.0
...
20240920.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6718938c1a | ||
|
|
acd1a9ad91 | ||
|
|
cce2894dac | ||
|
|
877ea0cc19 | ||
|
|
cd4c1fc7ac | ||
|
|
09292fd28b | ||
|
|
ccef86d2a0 | ||
|
|
ba34ef4494 | ||
|
|
26eca09bb9 | ||
|
|
64d4cc00e4 | ||
|
|
33b4de86a9 | ||
|
|
f33da85518 | ||
|
|
93ecbf479e | ||
|
|
ca2d6541ce | ||
|
|
db7154dca9 | ||
|
|
72bba3d948 | ||
|
|
07bbf4d4ea | ||
|
|
7aafbbe58e | ||
|
|
c2058211fe | ||
|
|
08a6cbb270 | ||
|
|
c5da8963d4 | ||
|
|
89b854ea57 | ||
|
|
42fd8cd1e8 | ||
|
|
0e0f49c540 | ||
|
|
f0b1b62e79 | ||
|
|
7606a40a58 | ||
|
|
ac5098522b | ||
|
|
d84ff8d392 | ||
|
|
4a0687cfe9 | ||
|
|
19e386ed21 | ||
|
|
8165c72606 | ||
|
|
5267992e31 | ||
|
|
1949b3346c | ||
|
|
38375b1710 | ||
|
|
281e790260 | ||
|
|
2b8b2521d1 | ||
|
|
52601edb35 | ||
|
|
5475f281eb | ||
|
|
b1f8893783 | ||
|
|
640cb322d7 | ||
|
|
c4f15cbf3a | ||
|
|
bef392cf7a | ||
|
|
abb49ed336 | ||
|
|
fe5bc5569d | ||
|
|
18615f246d | ||
|
|
7958632046 | ||
|
|
3e8bff23c4 | ||
|
|
0221781a05 | ||
|
|
e6ced7fff6 | ||
|
|
484238ece2 | ||
|
|
ee32bb87f0 | ||
|
|
73803acb89 | ||
|
|
a40df40f9b | ||
|
|
a33b89788c | ||
|
|
54f815e503 | ||
|
|
e54d3d274a | ||
|
|
b7a20ceb4f | ||
|
|
bbc965d38f | ||
|
|
8935cf7041 | ||
|
|
4583f6d996 | ||
|
|
92282fb493 | ||
|
|
65ea328f2a | ||
|
|
2da4833a0d | ||
|
|
631ce68126 | ||
|
|
480aca680d | ||
|
|
6e3ab6700d | ||
|
|
61319fa08e | ||
|
|
673e9f88ad | ||
|
|
f2b8200a3b | ||
|
|
0383624c72 | ||
|
|
cb03b8d9d4 | ||
|
|
e7e821ca3d | ||
|
|
6b21fdbcc6 | ||
|
|
ee326c6fe3 | ||
|
|
8945fd163c | ||
|
|
4dab0bd4bb | ||
|
|
49ec0c6df4 | ||
|
|
f3d29c47e2 | ||
|
|
41b4577665 | ||
|
|
2ca813f209 |
13
.github/actions/entitlements.plist
vendored
Normal file
13
.github/actions/entitlements.plist
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<!-- These are required for binaries built by PyInstaller -->
|
||||||
|
<key>com.apple.security.cs.allow-jit</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||||
|
<true/>
|
||||||
|
<key>com.apple.security.cs.disable-library-validation</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
211
.github/workflows/build.yml
vendored
211
.github/workflows/build.yml
vendored
@@ -31,68 +31,68 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: ubuntu-20.04
|
- os: ubuntu-22.04
|
||||||
jid: 1
|
jid: 1
|
||||||
goal: build
|
goal: build
|
||||||
arch: x86_64
|
arch: x86_64
|
||||||
openssl_archs: linux-x86_64
|
openssl_archs: linux-x86_64
|
||||||
- os: [self-hosted, linux, arm64]
|
- os: ubuntu-20.04
|
||||||
jid: 2
|
jid: 2
|
||||||
goal: build
|
goal: build
|
||||||
|
arch: x86_64
|
||||||
|
openssl_archs: linux-x86_64
|
||||||
|
- os: [self-hosted, linux, arm64]
|
||||||
|
jid: 3
|
||||||
|
goal: build
|
||||||
arch: aarch64
|
arch: aarch64
|
||||||
openssl_archs: linux-aarch64
|
openssl_archs: linux-aarch64
|
||||||
- os: ubuntu-20.04
|
- os: ubuntu-20.04
|
||||||
jid: 3
|
jid: 4
|
||||||
goal: build
|
goal: build
|
||||||
arch: x86_64
|
arch: x86_64
|
||||||
openssl_archs: linux-x86_64
|
openssl_archs: linux-x86_64
|
||||||
staticx: yes
|
staticx: yes
|
||||||
- os: [self-hosted, linux, arm64]
|
- os: [self-hosted, linux, arm64]
|
||||||
jid: 4
|
jid: 5
|
||||||
goal: build
|
goal: build
|
||||||
arch: aarch64
|
arch: aarch64
|
||||||
openssl_archs: linux-aarch64
|
openssl_archs: linux-aarch64
|
||||||
staticx: yes
|
staticx: yes
|
||||||
- os: macos-12
|
- os: macos-13
|
||||||
jid: 5
|
jid: 6
|
||||||
goal: build
|
goal: build
|
||||||
arch: x86_64
|
arch: x86_64
|
||||||
openssl_archs: darwin64-x86_64
|
openssl_archs: darwin64-x86_64
|
||||||
- os: macos-14
|
- os: macos-14
|
||||||
jid: 6
|
jid: 7
|
||||||
goal: build
|
goal: build
|
||||||
arch: aarch64
|
arch: aarch64
|
||||||
openssl_archs: darwin64-arm64
|
openssl_archs: darwin64-arm64
|
||||||
- os: macos-14
|
|
||||||
jid: 7
|
|
||||||
goal: build
|
|
||||||
arch: universal2
|
|
||||||
openssl_archs: darwin64-arm64 darwin64-x86_64
|
|
||||||
- os: windows-2022
|
- os: windows-2022
|
||||||
jid: 8
|
jid: 9
|
||||||
goal: build
|
goal: build
|
||||||
arch: Win64
|
arch: Win64
|
||||||
openssl_archs: VC-WIN64A
|
openssl_archs: VC-WIN64A
|
||||||
- os: ubuntu-22.04
|
- os: ubuntu-22.04
|
||||||
goal: test
|
goal: test
|
||||||
python: "3.8"
|
python: "3.13"
|
||||||
jid: 9
|
|
||||||
arch: x86_64
|
|
||||||
- os: ubuntu-22.04
|
|
||||||
goal: test
|
|
||||||
python: "3.9"
|
|
||||||
jid: 10
|
jid: 10
|
||||||
arch: x86_64
|
arch: x86_64
|
||||||
- os: ubuntu-22.04
|
- os: ubuntu-22.04
|
||||||
goal: test
|
goal: test
|
||||||
python: "3.10"
|
python: "3.9"
|
||||||
jid: 11
|
jid: 11
|
||||||
arch: x86_64
|
arch: x86_64
|
||||||
- os: ubuntu-22.04
|
- os: ubuntu-22.04
|
||||||
goal: test
|
goal: test
|
||||||
python: "3.11"
|
python: "3.10"
|
||||||
jid: 12
|
jid: 12
|
||||||
arch: x86_64
|
arch: x86_64
|
||||||
|
- os: ubuntu-22.04
|
||||||
|
goal: test
|
||||||
|
python: "3.11"
|
||||||
|
jid: 8
|
||||||
|
arch: x86_64
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
cache.tar.xz
|
cache.tar.xz
|
||||||
key: gam-${{ matrix.jid }}-20240903
|
key: gam-${{ matrix.jid }}-20240918
|
||||||
|
|
||||||
- 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'
|
||||||
@@ -201,6 +201,14 @@ jobs:
|
|||||||
#brew install swig
|
#brew install swig
|
||||||
#brew install ncurses
|
#brew install ncurses
|
||||||
|
|
||||||
|
- name: MacOS import developer certificates for signing
|
||||||
|
if: runner.os == 'macOS'
|
||||||
|
uses: apple-actions/import-codesign-certs@v3
|
||||||
|
with:
|
||||||
|
keychain: signing_temp
|
||||||
|
p12-file-base64: ${{ secrets.CERTIFICATES_P12 }}
|
||||||
|
p12-password: ${{ secrets.CERTIFICATES_P12_PASSWORD }}
|
||||||
|
|
||||||
- name: Windows Configure VCode
|
- name: Windows Configure VCode
|
||||||
uses: ilammy/msvc-dev-cmd@v1
|
uses: ilammy/msvc-dev-cmd@v1
|
||||||
if: runner.os == 'Windows' && steps.cache-python-ssl.outputs.cache-hit != 'true'
|
if: runner.os == 'Windows' && steps.cache-python-ssl.outputs.cache-hit != 'true'
|
||||||
@@ -293,7 +301,8 @@ jobs:
|
|||||||
- name: Rename GNU link on Windows
|
- name: Rename GNU link on Windows
|
||||||
if: matrix.goal == 'build' && runner.os == 'Windows' && steps.cache-python-ssl.outputs.cache-hit != 'true'
|
if: matrix.goal == 'build' && runner.os == 'Windows' && steps.cache-python-ssl.outputs.cache-hit != 'true'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: mv /usr/bin/link /usr/bin/gnulink
|
run: |
|
||||||
|
mv -v /usr/bin/link /usr/bin/gnulink
|
||||||
|
|
||||||
- name: Make OpenSSL
|
- name: Make OpenSSL
|
||||||
if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit != 'true'
|
if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit != 'true'
|
||||||
@@ -311,7 +320,7 @@ jobs:
|
|||||||
cd "${GITHUB_WORKSPACE}/src/openssl-${openssl_arch}"
|
cd "${GITHUB_WORKSPACE}/src/openssl-${openssl_arch}"
|
||||||
# install_sw saves us ages processing man pages :-)
|
# install_sw saves us ages processing man pages :-)
|
||||||
$MAKE install_sw
|
$MAKE install_sw
|
||||||
mv "${OPENSSL_INSTALL_PATH}" "${GITHUB_WORKSPACE}/bin/ssl-${openssl_arch}"
|
mv -v "${OPENSSL_INSTALL_PATH}" "${GITHUB_WORKSPACE}/bin/ssl-${openssl_arch}"
|
||||||
done
|
done
|
||||||
mkdir -vp "${OPENSSL_INSTALL_PATH}/lib"
|
mkdir -vp "${OPENSSL_INSTALL_PATH}/lib"
|
||||||
mkdir -vp "${OPENSSL_INSTALL_PATH}/bin"
|
mkdir -vp "${OPENSSL_INSTALL_PATH}/bin"
|
||||||
@@ -521,61 +530,59 @@ jobs:
|
|||||||
- name: Build GAM with PyInstaller
|
- name: Build GAM with PyInstaller
|
||||||
if: matrix.goal != 'test'
|
if: matrix.goal != 'test'
|
||||||
run: |
|
run: |
|
||||||
if [[ "${staticx}" == "yes" ]]; then
|
|
||||||
export distpath="./dist/gam"
|
export distpath="./dist/gam"
|
||||||
export gampath="${distpath}"
|
mkdir -p -v "${distpath}"
|
||||||
else
|
|
||||||
export distpath="./dist"
|
|
||||||
export gampath="${distpath}/gam"
|
|
||||||
fi
|
|
||||||
mkdir -p -v "${gampath}"
|
|
||||||
if [[ "${RUNNER_OS}" == "macOS" ]]; then
|
if [[ "${RUNNER_OS}" == "macOS" ]]; then
|
||||||
# brew OpenSSL gets picked up by PyInstaller breaking our self-compiled version
|
# Tell our gam.spec to use our code sign certificate
|
||||||
|
export codesign_identity="Jay Lee"
|
||||||
|
# brew OpenSSL gets picked up by PyInstaller
|
||||||
|
# breaking our self-compiled version
|
||||||
brew uninstall --ignore-dependencies openssl
|
brew uninstall --ignore-dependencies openssl
|
||||||
export gampath=$($PYTHON -c "import os; print(os.path.realpath('$gampath'))")
|
|
||||||
elif [[ "${RUNNER_OS}" == "Windows" ]]; then
|
elif [[ "${RUNNER_OS}" == "Windows" ]]; then
|
||||||
# Work around issue where PyInstaller picks up python3.dll from other Python versions
|
# Work around issue where PyInstaller picks up python3.dll from other Python versions
|
||||||
# https://github.com/pyinstaller/pyinstaller/issues/7102
|
# https://github.com/pyinstaller/pyinstaller/issues/7102
|
||||||
export PATH="$(dirname ${PYTHON}):/usr/bin"
|
export PATH="$(dirname ${PYTHON}):/usr/bin"
|
||||||
else
|
|
||||||
export gampath=$(realpath "${gampath}")
|
|
||||||
fi
|
fi
|
||||||
export gam="${gampath}/gam"
|
if [[ "${staticx}" != "yes" ]]; then
|
||||||
echo "gampath=${gampath}" >> $GITHUB_ENV
|
export PYINSTALLER_BUILD_ONEDIR=yes
|
||||||
# TEMP force everything back to one file.
|
fi
|
||||||
export PYINSTALLER_BUILD_ONEFILE="yes"
|
|
||||||
export distpath="./dist/gam"
|
|
||||||
export gampath="${distpath}"
|
|
||||||
"${PYTHON}" -m PyInstaller --clean --noconfirm --distpath="${distpath}" gam.spec
|
"${PYTHON}" -m PyInstaller --clean --noconfirm --distpath="${distpath}" gam.spec
|
||||||
echo "WARNINGS FROM build/gam/warn-gam.txt"
|
if [[ "$PYINSTALLER_BUILD_ONEDIR" == "yes" ]]; then
|
||||||
cat build/gam/warn-gam.txt
|
mv -v "${distpath}/gam" "${distpath}/gam7"
|
||||||
echo "Analysis FROM build/gam/Analysis-00.toc"
|
export gampath="${distpath}/gam7"
|
||||||
cat build/gam/Analysis-00.toc
|
|
||||||
echo "EXE data FROM build/gam/EXE-00.toc"
|
|
||||||
cat build/gam/EXE-00.toc
|
|
||||||
if [ -x "$(command -v realpath)" ]; then
|
|
||||||
realpath=realpath
|
|
||||||
else
|
else
|
||||||
brew install coreutils
|
mv -v "$distpath" "${distpath}7"
|
||||||
realpath=grealpath
|
export gampath="${distpath}7"
|
||||||
fi
|
fi
|
||||||
export gam=$(realpath "$gam")
|
export gampath=$(realpath "$gampath")
|
||||||
|
echo "gampath ${gampath} results:"
|
||||||
|
ls -alRF "$gampath"
|
||||||
|
#echo "WARNINGS FROM build/gam/warn-gam.txt"
|
||||||
|
#cat build/gam/warn-gam.txt
|
||||||
|
#echo "Analysis FROM build/gam/Analysis-00.toc"
|
||||||
|
#cat build/gam/Analysis-00.toc
|
||||||
|
#echo "EXE data FROM build/gam/EXE-00.toc"
|
||||||
|
#cat build/gam/EXE-00.toc
|
||||||
|
export gam="${gampath}/gam"
|
||||||
if [[ "${RUNNER_OS}" == "Windows" ]]; then
|
if [[ "${RUNNER_OS}" == "Windows" ]]; then
|
||||||
export gam=$(cygpath -w "$gam")
|
export gam=$(cygpath -w "$gam")
|
||||||
echo "GAM on Windows at ${gam}"
|
echo "GAM on Windows at ${gam}"
|
||||||
|
else
|
||||||
|
export gam=$(realpath "$gam")
|
||||||
fi
|
fi
|
||||||
|
echo "gampath=${gampath}" >> $GITHUB_ENV
|
||||||
echo "gam=${gam}" >> $GITHUB_ENV
|
echo "gam=${gam}" >> $GITHUB_ENV
|
||||||
echo -e "GAM: ${gam}\nGAMPATH: ${gampath}"
|
echo -e "GAM: ${gam}\nGAMPATH: ${gampath}"
|
||||||
|
|
||||||
- name: Copy extra package files
|
- name: Copy extra package files
|
||||||
if: matrix.goal == 'build'
|
if: matrix.goal == 'build'
|
||||||
run: |
|
run: |
|
||||||
cp -v cacerts.pem $gampath
|
cp -v cacerts.pem "$gampath"
|
||||||
cp -v LICENSE $gampath
|
cp -v LICENSE "$gampath"
|
||||||
cp -v GamCommands.txt $gampath
|
cp -v GamCommands.txt "$gampath"
|
||||||
cp -v GamUpdate.txt $gampath
|
cp -v GamUpdate.txt "$gampath"
|
||||||
if [[ "${RUNNER_OS}" == "Windows" ]]; then
|
if [[ "${RUNNER_OS}" == "Windows" ]]; then
|
||||||
cp -v gam-setup.bat $gampath
|
cp -v gam-setup.bat "$gampath"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Install StaticX
|
- name: Install StaticX
|
||||||
@@ -596,9 +603,21 @@ jobs:
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
echo "ldlib=${ldlib}"
|
echo "ldlib=${ldlib}"
|
||||||
$PYTHON -m staticx -l "${ldlib}" "${gam}" "${gam}-staticx"
|
$PYTHON -m staticx -l "${ldlib}" "$gam" "${gam}-staticx"
|
||||||
rm -v "${gam}"
|
rm -v "$gam"
|
||||||
mv -v "${gam}-staticx" "${gam}"
|
mv -v "${gam}-staticx" "$gam"
|
||||||
|
|
||||||
|
- name: MacOS send GAM binary for Apple notarization
|
||||||
|
if: runner.os == 'macOS'
|
||||||
|
env:
|
||||||
|
ASP_NOTARIZE: ${{ secrets.ASP_NOTARIZE }}
|
||||||
|
run: |
|
||||||
|
# Apple wants some kind of "package" submitted so just add gam to a .zip
|
||||||
|
# name it something we can track and link in Apple's notarize process
|
||||||
|
zipfilename="./gam-${RUNNER_ARCH}-${GITHUB_RUN_ID}-${GITHUB_RUN_NUMBER}.zip"
|
||||||
|
zip -r "$zipfilename" "$gampath"
|
||||||
|
xcrun notarytool submit --apple-id "jay0lee@gmail.com" --password "$ASP_NOTARIZE" --team-id GZ85H2DRLM "$zipfilename"
|
||||||
|
rm -v "$zipfilename"
|
||||||
|
|
||||||
- name: Basic Tests all jobs
|
- name: Basic Tests all jobs
|
||||||
id: basictests
|
id: basictests
|
||||||
@@ -609,7 +628,7 @@ jobs:
|
|||||||
echo "GAM Version ${GAMVERSION}"
|
echo "GAM Version ${GAMVERSION}"
|
||||||
echo "GAMVERSION=${GAMVERSION}" >> $GITHUB_ENV
|
echo "GAMVERSION=${GAMVERSION}" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Attest Binary Provenance
|
- name: Attest gam executable was generated from this Action
|
||||||
uses: actions/attest-build-provenance@v1
|
uses: actions/attest-build-provenance@v1
|
||||||
if: matrix.goal == 'build'
|
if: matrix.goal == 'build'
|
||||||
with:
|
with:
|
||||||
@@ -619,28 +638,51 @@ jobs:
|
|||||||
if: runner.os != 'Windows' && matrix.goal == 'build'
|
if: runner.os != 'Windows' && matrix.goal == 'build'
|
||||||
run: |
|
run: |
|
||||||
if [[ "${RUNNER_OS}" == "macOS" ]]; then
|
if [[ "${RUNNER_OS}" == "macOS" ]]; then
|
||||||
GAM_ARCHIVE="gam-${GAMVERSION}-macos-${arch}.tar.xz"
|
GAM_ARCHIVE="${GITHUB_WORKSPACE}/gam-${GAMVERSION}-macos-${arch}.tar.xz"
|
||||||
elif [[ "${RUNNER_OS}" == "Linux" ]]; then
|
elif [[ "${RUNNER_OS}" == "Linux" ]]; then
|
||||||
if [[ "${staticx}" == "yes" ]]; then
|
if [[ "${staticx}" == "yes" ]]; then
|
||||||
libver="legacy"
|
libver="legacy"
|
||||||
else
|
else
|
||||||
libver="glibc$(ldd --version | awk '/ldd/{print $NF}')"
|
libver="glibc$(ldd --version | awk '/ldd/{print $NF}')"
|
||||||
fi
|
fi
|
||||||
GAM_ARCHIVE="gam-${GAMVERSION}-linux-$(arch)-${libver}.tar.xz"
|
GAM_ARCHIVE="${GITHUB_WORKSPACE}/gam-${GAMVERSION}-linux-$(arch)-${libver}.tar.xz"
|
||||||
fi
|
fi
|
||||||
echo "GAM Archive ${GAM_ARCHIVE}"
|
echo "GAM Archive ${GAM_ARCHIVE}"
|
||||||
tar -C dist/ --create --verbose --exclude-from "${GITHUB_WORKSPACE}/.github/actions/package_exclusions.txt" --file $GAM_ARCHIVE --xz gam
|
tar -C "${gampath}/.." --create --verbose --exclude-from "${GITHUB_WORKSPACE}/.github/actions/package_exclusions.txt" --file $GAM_ARCHIVE --xz gam7
|
||||||
|
|
||||||
- name: Windows package
|
- name: Windows package
|
||||||
if: runner.os == 'Windows' && matrix.goal != 'test'
|
if: runner.os == 'Windows' && matrix.goal != 'test'
|
||||||
run: |
|
run: |
|
||||||
cd dist/
|
cd "${gampath}/.."
|
||||||
GAM_ARCHIVE="../gam-${GAMVERSION}-windows-${GAM_ARCHIVE_ARCH}.zip"
|
GAM_ARCHIVE="${GITHUB_WORKSPACE}/gam-${GAMVERSION}-windows-${GAM_ARCHIVE_ARCH}.zip"
|
||||||
/c/Program\ Files/7-Zip/7z.exe a -tzip $GAM_ARCHIVE gam "-xr@${GITHUB_WORKSPACE}/.github/actions/package_exclusions.txt" -bb3
|
/c/Program\ Files/7-Zip/7z.exe a -tzip "$GAM_ARCHIVE" gam7 "-xr@${GITHUB_WORKSPACE}/.github/actions/package_exclusions.txt" -bb3
|
||||||
cd ..
|
#cd ../..
|
||||||
/c/Program\ Files\ \(x86\)/WiX\ Toolset\ v3.14/bin/candle.exe -arch "${WIX_ARCH}" gam.wxs
|
#$PYTHON tools/gen-wix-xml-filelist.py "$gampath" gam.wxs.template gam.wxs
|
||||||
/c/Program\ Files\ \(x86\)/WiX\ Toolset\ v3.14/bin/light.exe -ext /c/Program\ Files\ \(x86\)/WiX\ Toolset\ v3.14/bin/WixUIExtension.dll gam.wixobj -o "gam-${GAMVERSION}-windows-${GAM_ARCHIVE_ARCH}.msi" || true;
|
#echo '-- begin generated gam.wxs --'
|
||||||
rm -v -f *.wixpdb
|
#cat gam.wxs
|
||||||
|
#echo '-- end generated gam.wxs --'
|
||||||
|
#/c/Program\ Files\ \(x86\)/WiX\ Toolset\ v3.14/bin/candle.exe -arch "${WIX_ARCH}" gam.wxs
|
||||||
|
#/c/Program\ Files\ \(x86\)/WiX\ Toolset\ v3.14/bin/light.exe -ext /c/Program\ Files\ \(x86\)/WiX\ Toolset\ v3.14/bin/WixUIExtension.dll gam.wixobj -o "gam-${GAMVERSION}-windows-${GAM_ARCHIVE_ARCH}.msi" || true;
|
||||||
|
#rm -v -f *.wixpdb
|
||||||
|
|
||||||
|
- name: Attest that gam package files were generated from this Action
|
||||||
|
uses: actions/attest-build-provenance@v1
|
||||||
|
if: (github.event_name == 'push' || github.event_name == 'schedule') && matrix.goal == 'build'
|
||||||
|
with:
|
||||||
|
subject-path: |
|
||||||
|
gam*.tar.xz
|
||||||
|
gam*.zip
|
||||||
|
gam*.msi
|
||||||
|
|
||||||
|
- name: Archive production artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
if: (github.event_name == 'push' || github.event_name == 'schedule') && matrix.goal != 'test'
|
||||||
|
with:
|
||||||
|
name: gam-binaries-${{ env.GAMOS }}-${{ env.arch }}-${{ matrix.jid }}
|
||||||
|
path: |
|
||||||
|
gam*.tar.xz
|
||||||
|
gam*.zip
|
||||||
|
gam*.msi
|
||||||
|
|
||||||
- name: Basic Tests build jobs only
|
- name: Basic Tests build jobs only
|
||||||
if: matrix.goal != 'test' && steps.cache-python-ssl.outputs.cache-hit != 'true'
|
if: matrix.goal != 'test' && steps.cache-python-ssl.outputs.cache-hit != 'true'
|
||||||
@@ -715,7 +757,8 @@ jobs:
|
|||||||
done
|
done
|
||||||
driveid=$($gam user $gam_user add shareddrive "${newbase}" returnidonly)
|
driveid=$($gam user $gam_user add shareddrive "${newbase}" returnidonly)
|
||||||
echo "Created shared drive ${driveid}"
|
echo "Created shared drive ${driveid}"
|
||||||
$gam create user $newuser firstname GHA lastname $JID displayname "Github Actions ${JID}" password random ou "${newou}" recoveryphone 12125121110 recoveryemail jay0lee@gmail.com gha.jid $JID languages en+,en-GB-
|
# 9/17/24 - temp create in root due to Google API issues creating users in new OUs
|
||||||
|
$gam create user $newuser firstname GHA lastname $JID displayname "Github Actions ${JID}" password random recoveryphone 12125121110 recoveryemail jay0lee@gmail.com gha.jid $JID languages en+,en-GB- # ou "${newou}"
|
||||||
$gam user $newuser update photo https://dummyimage.com/400x600/000/fff
|
$gam user $newuser update photo https://dummyimage.com/400x600/000/fff
|
||||||
$gam user $newuser get photo
|
$gam user $newuser get photo
|
||||||
$gam user $newuser delete photo
|
$gam user $newuser delete photo
|
||||||
@@ -734,7 +777,8 @@ jobs:
|
|||||||
$gam update group $newgroup add owner $gam_user
|
$gam update group $newgroup add owner $gam_user
|
||||||
$gam update group $newgroup add member $newuser
|
$gam update group $newgroup add member $newuser
|
||||||
$gam config enable_dasa false save
|
$gam config enable_dasa false save
|
||||||
$gam create admin $newuser _GROUPS_EDITOR_ROLE CUSTOMER # condition nonsecuritygroup
|
# 9/17/24 temp disable due to Google API sluggishness to see new users for admin commands
|
||||||
|
# $gam create admin $newuser _GROUPS_EDITOR_ROLE CUSTOMER # condition nonsecuritygroup
|
||||||
$gam create admin $newgroup _HELP_DESK_ADMIN_ROLE org_unit "${newou}"
|
$gam create admin $newgroup _HELP_DESK_ADMIN_ROLE org_unit "${newou}"
|
||||||
$gam config csv_output_row_filter "assignedToUser:regex:${newuser}" print admins | $gam csv - gam delete admin "~roleAssignmentId"
|
$gam config csv_output_row_filter "assignedToUser:regex:${newuser}" print admins | $gam csv - gam delete admin "~roleAssignmentId"
|
||||||
$gam config csv_output_row_filter "assignedToGroup:regex:${newgroup}" print admins | $gam csv - gam delete admin "~roleAssignmentId"
|
$gam config csv_output_row_filter "assignedToGroup:regex:${newgroup}" print admins | $gam csv - gam delete admin "~roleAssignmentId"
|
||||||
@@ -858,7 +902,7 @@ jobs:
|
|||||||
echo "printer model count:"
|
echo "printer model count:"
|
||||||
$gam print printermodels | wc -l
|
$gam print printermodels | wc -l
|
||||||
$gam print printers
|
$gam print printers
|
||||||
printerid=$($gam create printer displayname "${newbase}" uri ipp://localhost:631 driverless description "made by $(gam_user)" ou "${newou}" nodetails | awk '{print substr($2, 1, length($2)-1)}')
|
printerid=$($gam create printer displayname "${newbase}" uri ipp://localhost:631 driverless description "made by ${gam_user}" ou "${newou}" nodetails | awk '{print substr($2, 1, length($2)-1)}')
|
||||||
$gam info printer "$printerid"
|
$gam info printer "$printerid"
|
||||||
$gam delete printer "$printerid"
|
$gam delete printer "$printerid"
|
||||||
$gam delete ou "${newou}"
|
$gam delete ou "${newou}"
|
||||||
@@ -874,25 +918,6 @@ jobs:
|
|||||||
fi
|
fi
|
||||||
tar cJvvf cache.tar.xz $tar_folders
|
tar cJvvf cache.tar.xz $tar_folders
|
||||||
|
|
||||||
- name: Attest Build Archive Provenance
|
|
||||||
uses: actions/attest-build-provenance@v1
|
|
||||||
if: (github.event_name == 'push' || github.event_name == 'schedule') && matrix.goal == 'build'
|
|
||||||
with:
|
|
||||||
subject-path: |
|
|
||||||
src/gam*.tar.xz
|
|
||||||
src/gam*.zip
|
|
||||||
src/gam*.msi
|
|
||||||
|
|
||||||
- name: Archive production artifacts
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
if: (github.event_name == 'push' || github.event_name == 'schedule') && matrix.goal != 'test'
|
|
||||||
with:
|
|
||||||
name: gam-binaries-${{ env.GAMOS }}-${{ env.arch }}-${{ matrix.jid }}
|
|
||||||
path: |
|
|
||||||
src/gam*.tar.xz
|
|
||||||
src/gam*.zip
|
|
||||||
src/gam*.msi
|
|
||||||
|
|
||||||
merge:
|
merge:
|
||||||
if: (github.event_name == 'push' || github.event_name == 'schedule')
|
if: (github.event_name == 'push' || github.event_name == 'schedule')
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
GAM is a command line tool for Google Workspace admins to manage domain and user settings quickly and easily.
|
GAM is a command line tool for Google Workspace admins to manage domain and user settings quickly and easily.
|
||||||
|
|
||||||

|
[](https://github.com/GAM-team/GAM/actions/workflows/build.yml)
|
||||||
|
|
||||||
# Quick Start
|
# Quick Start
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ There is a public chat room hosted in Google Chat. [Instructions to join](https:
|
|||||||
|
|
||||||
# Author
|
# Author
|
||||||
|
|
||||||
GAM is maintained by [Jay Lee](mailto:jay0lee@gmail.com). Please direct "how do I?" questions to [Google Groups].
|
GAM is maintained by [Jay (James) Lee](mailto:jay0lee@gmail.com) and [Ross Scroggs](mailto:ross.scroggs@gmail.com). Please direct "how do I?" questions to [Google Groups].
|
||||||
|
|
||||||
[GAM release]: https://github.com/GAM-team/GAM/releases
|
[GAM release]: https://github.com/GAM-team/GAM/releases
|
||||||
[GitHub Releases]: https://github.com/GAM-team/GAM/releases
|
[GitHub Releases]: https://github.com/GAM-team/GAM/releases
|
||||||
|
|||||||
@@ -176,6 +176,7 @@ Client access works when accessing Resource calendars.
|
|||||||
<AttendeeStatus> ::= accepted|declined|needsaction|tentative
|
<AttendeeStatus> ::= accepted|declined|needsaction|tentative
|
||||||
|
|
||||||
<EventType> ::=
|
<EventType> ::=
|
||||||
|
birthday|
|
||||||
default|
|
default|
|
||||||
focustime|
|
focustime|
|
||||||
fromgmail|
|
fromgmail|
|
||||||
@@ -241,6 +242,7 @@ Client access works when accessing Resource calendars.
|
|||||||
(attendee <EmailAddress>)|
|
(attendee <EmailAddress>)|
|
||||||
(attendeestatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddress>)|
|
(attendeestatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddress>)|
|
||||||
available|
|
available|
|
||||||
|
(birthday <Date>)|
|
||||||
(color <EventColorName>)|
|
(color <EventColorName>)|
|
||||||
(colorindex|colorid <EventColorIndex>)|
|
(colorindex|colorid <EventColorIndex>)|
|
||||||
(description <String>)|
|
(description <String>)|
|
||||||
@@ -261,7 +263,7 @@ Client access works when accessing Resource calendars.
|
|||||||
(privateproperty <PropertyKey> <PropertyValue>)|
|
(privateproperty <PropertyKey> <PropertyValue>)|
|
||||||
(range <Date> <Date>)|
|
(range <Date> <Date>)|
|
||||||
(recurrence <RRULE, EXRULE, RDATE and EXDATE line>)|
|
(recurrence <RRULE, EXRULE, RDATE and EXDATE line>)|
|
||||||
(reminder <Number> email|popup))|
|
(reminder <Number> email|popup)|
|
||||||
(selectattendees [<AttendeeAttendance>] [<AttendeeStatus>] <UserTypeEntity>)|
|
(selectattendees [<AttendeeAttendance>] [<AttendeeStatus>] <UserTypeEntity>)|
|
||||||
(sequence <Integer>)|
|
(sequence <Integer>)|
|
||||||
(sharedproperty <PropertyKey> <PropertyValue>)|
|
(sharedproperty <PropertyKey> <PropertyValue>)|
|
||||||
|
|||||||
@@ -7,15 +7,17 @@
|
|||||||
- [Definitions](#definitions)
|
- [Definitions](#definitions)
|
||||||
- [Display a specific Chrome policy schema](#display-a-specific-chrome-policy-schema)
|
- [Display a specific Chrome policy schema](#display-a-specific-chrome-policy-schema)
|
||||||
- [Display all or filtered Chrome policy schemas](#display-all-or-filtered-chrome-policy-schemas)
|
- [Display all or filtered Chrome policy schemas](#display-all-or-filtered-chrome-policy-schemas)
|
||||||
- [Display Chrome policy schemas in same format as Standard GAM](#display-chrome-policy-schemas-in-same-format-as-standard-gam)
|
- [Display Chrome policy schemas in same format as Legacy GAM](#display-chrome-policy-schemas-in-same-format-as-legacy-gam)
|
||||||
- [Create a Chrome policy image](#create-a-chrome-policy-image)
|
- [Create a Chrome policy image](#create-a-chrome-policy-image)
|
||||||
- [Update Chrome policy](#update-chrome-policy)
|
- [Update Chrome policy](#update-chrome-policy)
|
||||||
- [Delete Chrome policy](#delete-chrome-policy)
|
- [Delete Chrome policy](#delete-chrome-policy)
|
||||||
- [Display Chrome policies](#display-chrome-policies)
|
- [Display Chrome policies](#display-chrome-policies)
|
||||||
- [Copy simple policies set directly in one OU to another OU](#copy-simple-policies-set-directly-in-one-ou-to-another-ou)
|
- [Copy simple policies set directly in one OU to another OU](#copy-simple-policies-set-directly-in-one-ou-to-another-ou)
|
||||||
- [Copy simple and complex policies set directly in one OU to another OU](#copy-simple-and-complex-policies-set-directly-in-one-ou-to-another-ou)
|
- [Copy simple and complex policies set directly in one OU to another OU](#copy-simple-and-complex-policies-set-directly-in-one-ou-to-another-ou)
|
||||||
|
- [Copy simple and complex policies set directly in one OU to multiple other OUs](#copy-simple-and-complex-policies-set-directly-in-one-ou-to-multiple-other-ous)
|
||||||
- [Copy simple policies in one Group to another Group](#copy-simple-policies-in-one-group-to-another-group)
|
- [Copy simple policies in one Group to another Group](#copy-simple-policies-in-one-group-to-another-group)
|
||||||
- [Copy simple and complex policies in one Group to another Group](#copy-simple-and-complex-policies-in-one-group-to-another-group)
|
- [Copy simple and complex policies in one Group to another Group](#copy-simple-and-complex-policies-in-one-group-to-another-group)
|
||||||
|
- [Copy simple and complex policies in one Group to multiple other Groups](#copy-simple-and-complex-policies-in-one-group-to-multiple-other-groups)
|
||||||
- [Create Chrome network](#create-chrome-network)
|
- [Create Chrome network](#create-chrome-network)
|
||||||
- [Delete Chrome network](#delete-chrome-network)
|
- [Delete Chrome network](#delete-chrome-network)
|
||||||
- [Chrome Policy Schema Table](#chrome-policy-schema-table)
|
- [Chrome Policy Schema Table](#chrome-policy-schema-table)
|
||||||
@@ -116,7 +118,7 @@ When using the `formatjson` option, double quotes are used extensively in the da
|
|||||||
The `quotechar <Character>` option allows you to choose an alternate quote character, single quote for instance, that makes for readable/processable output.
|
The `quotechar <Character>` option allows you to choose an alternate quote character, single quote for instance, that makes for readable/processable output.
|
||||||
`quotechar` defaults to `gam.cfg/csv_output_quote_char`. When uploading CSV files to Google, double quote `"` should be used.
|
`quotechar` defaults to `gam.cfg/csv_output_quote_char`. When uploading CSV files to Google, double quote `"` should be used.
|
||||||
|
|
||||||
## Display Chrome policy schemas in same format as Standard GAM
|
## Display Chrome policy schemas in same format as Legacy GAM
|
||||||
```
|
```
|
||||||
gam show chromeschemas std
|
gam show chromeschemas std
|
||||||
[filter <String>]
|
[filter <String>]
|
||||||
@@ -356,6 +358,22 @@ gam redirect csv ChromePolicies.csv print chromepolicies ou "/Path/To/OU1" forma
|
|||||||
gam config csv_input_row_filter "direct:boolean:true" csv ChromePolicies.csv quotechar "'" gam update chromepolicy "~name" json "~JSON" ou "/Path/To/OU2"
|
gam config csv_input_row_filter "direct:boolean:true" csv ChromePolicies.csv quotechar "'" gam update chromepolicy "~name" json "~JSON" ou "/Path/To/OU2"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Copy simple and complex policies set directly in one OU to multiple other OUs
|
||||||
|
Display direct policies, update all
|
||||||
|
```
|
||||||
|
gam redirect csv ChromePolicies.csv print chromepolicies ou "/Path/To/OU1" show direct formatjson quotechar "'"
|
||||||
|
```
|
||||||
|
Make a batch file (SetPolicies.bat) with a line for each target OU
|
||||||
|
```
|
||||||
|
gam csv ChromePolicies.csv quotechar "'" gam update chromepolicy "~name" json "~JSON" ou "/Path/To/OU2"
|
||||||
|
gam csv ChromePolicies.csv quotechar "'" gam update chromepolicy "~name" json "~JSON" ou "/Path/To/OU3"
|
||||||
|
...
|
||||||
|
```
|
||||||
|
Execute batch
|
||||||
|
```
|
||||||
|
gam redirect stdout ./SetPolicies.log multiprocess redirect stderr stdout tbatch SetPolicies.bat
|
||||||
|
```
|
||||||
|
|
||||||
## Copy simple policies in one Group to another Group
|
## Copy simple policies in one Group to another Group
|
||||||
Display all policies, update all
|
Display all policies, update all
|
||||||
```
|
```
|
||||||
@@ -369,6 +387,22 @@ gam redirect csv ChromePolicies.csv print chromepolicies group group1@domain.com
|
|||||||
gam csv ChromePolicies.csv quotechar "'" gam update chromepolicy "~name" json "~JSON" group group2@domain.com
|
gam csv ChromePolicies.csv quotechar "'" gam update chromepolicy "~name" json "~JSON" group group2@domain.com
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Copy simple and complex policies in one Group to multiple other Groups
|
||||||
|
Display all policies, update all
|
||||||
|
```
|
||||||
|
gam redirect csv ChromePolicies.csv print chromepolicies group group1@domain.com formatjson quotechar "'"
|
||||||
|
```
|
||||||
|
Make a batch file (SetPolicies.bat) with a line for each target group
|
||||||
|
```
|
||||||
|
gam csv ChromePolicies.csv quotechar "'" gam update chromepolicy "~name" json "~JSON" group group2@domain.com
|
||||||
|
gam csv ChromePolicies.csv quotechar "'" gam update chromepolicy "~name" json "~JSON" group group3@domain.com
|
||||||
|
...
|
||||||
|
```
|
||||||
|
Execute batch
|
||||||
|
```
|
||||||
|
gam redirect stdout ./SetPolicies.log multiprocess redirect stderr stdout tbatch SetPolicies.bat
|
||||||
|
```
|
||||||
|
|
||||||
## Create Chrome network
|
## Create Chrome network
|
||||||
See: [Chrome Policy Schema Table](#chrome-policy-schema-table) for the allowed network settings.
|
See: [Chrome Policy Schema Table](#chrome-policy-schema-table) for the allowed network settings.
|
||||||
* chrome.networks.ethernet.Details: Ethernet network configuration details.
|
* chrome.networks.ethernet.Details: Ethernet network configuration details.
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ gam <Command> cros <CrOSEntity> ...
|
|||||||
```
|
```
|
||||||
The first form allows more powerful selection of devices with `<CrOSTypeEntity>`.
|
The first form allows more powerful selection of devices with `<CrOSTypeEntity>`.
|
||||||
|
|
||||||
The second form is backwards compatible with Standard GAM and selection with `<CrOSEntity>` is limited.
|
The second form is backwards compatible with Legacy GAM and selection with `<CrOSEntity>` is limited.
|
||||||
|
|
||||||
## Definitions
|
## Definitions
|
||||||
* [`<CrOSTypeEntity>`](Collections-of-ChromeOS-Devices)
|
* [`<CrOSTypeEntity>`](Collections-of-ChromeOS-Devices)
|
||||||
@@ -465,7 +465,7 @@ gam getcommand cros <CrOSEntity> commandid <CommandID> [times_to_check_status <I
|
|||||||
### Action Examples
|
### Action Examples
|
||||||
Remove user profile data from the device; the device will remain enrolled and connected.
|
Remove user profile data from the device; the device will remain enrolled and connected.
|
||||||
User data not synced to the Cloud including Downloads, Android app data and Crostini Linux VMs will be permanently lost.
|
User data not synced to the Cloud including Downloads, Android app data and Crostini Linux VMs will be permanently lost.
|
||||||
Commands with issuecommand directly after gam will work with standard GAM & GAMADV-XTD3, whereas commands where the issuecommand is after the cros <CrOSTypeEntity> will work only with GAMADV-XTD3.
|
Commands with issuecommand directly after gam will work with Legacy GAM & GAMADV-XTD3, whereas commands where the issuecommand is after the cros <CrOSTypeEntity> will work only with GAMADV-XTD3.
|
||||||
```
|
```
|
||||||
gam issuecommand cros dd1d659a-0ea4-4e94-905e-4726c7a5f1e9 command wipe_users doit
|
gam issuecommand cros dd1d659a-0ea4-4e94-905e-4726c7a5f1e9 command wipe_users doit
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -50,6 +50,8 @@
|
|||||||
|
|
||||||
<UserGoogleDoc> ::=
|
<UserGoogleDoc> ::=
|
||||||
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>)
|
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>)
|
||||||
|
|
||||||
|
<SheetEntity> ::= <String>|id:<Number>
|
||||||
<UserGoogleSheet> ::=
|
<UserGoogleSheet> ::=
|
||||||
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>) <SheetEntity>
|
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>) <SheetEntity>
|
||||||
|
|
||||||
|
|||||||
@@ -55,6 +55,8 @@
|
|||||||
|
|
||||||
<UserGoogleDoc> ::=
|
<UserGoogleDoc> ::=
|
||||||
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>)
|
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>)
|
||||||
|
|
||||||
|
<SheetEntity> ::= <String>|id:<Number>
|
||||||
<UserGoogleSheet> ::=
|
<UserGoogleSheet> ::=
|
||||||
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>) <SheetEntity>
|
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>) <SheetEntity>
|
||||||
```
|
```
|
||||||
@@ -88,8 +90,6 @@
|
|||||||
<SharedDriveIDEntity> |
|
<SharedDriveIDEntity> |
|
||||||
<SharedDriveNameEntity>
|
<SharedDriveNameEntity>
|
||||||
|
|
||||||
<SheetEntity> ::= <String>|id:<Number>
|
|
||||||
|
|
||||||
<UserTypeEntity> ::=
|
<UserTypeEntity> ::=
|
||||||
(all users|users_ns|users_susp|users_ns_susp)|
|
(all users|users_ns|users_susp|users_ns_susp)|
|
||||||
(user <UserItem>)|
|
(user <UserItem>)|
|
||||||
|
|||||||
56
docs/Downloads-Installs-GAM7.md
Normal file
56
docs/Downloads-Installs-GAM7.md
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
# Downloads-Installs-GAM7
|
||||||
|
You can download and install the current GAM7 release from the [GitHub Releases](https://github.com/GAM-team/GAM/releases/latest) page.
|
||||||
|
Choose one of the following:
|
||||||
|
|
||||||
|
* Executable Archive, Automatic, Linux/Mac OS/Google Cloud Shell/Raspberry Pi/ChromeOS
|
||||||
|
- Start a terminal session and execute one of the following commands:
|
||||||
|
- New install, default path `$HOME/bin`
|
||||||
|
- `bash <(curl -s -S -L https://git.io/gam-install)`
|
||||||
|
- New install, specify a path
|
||||||
|
- `bash <(curl -s -S -L https://git.io/gam-install) -d <Path>`
|
||||||
|
- Update to latest version, do not create project or authorizations, default path `$HOME/bin`
|
||||||
|
- `bash <(curl -s -S -L https://git.io/gam-install) -l`
|
||||||
|
- Update to latest version, do not create project or authorizations, specify a path
|
||||||
|
- `bash <(curl -s -S -L https://git.io/gam-install) -l -d <Path>`
|
||||||
|
|
||||||
|
By default, a folder, `gam7`, is created in the default or specified path and the files are downloaded into that folder.
|
||||||
|
Add the `-s` option to the end of the above commands to suppress creating the `gam7` folder; the files are downloaded directly into the default or specified path.
|
||||||
|
|
||||||
|
* 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.31.tar.xz`
|
||||||
|
- `gam-7.wx.yz-linux-x86_64-legacy.tar.xz`
|
||||||
|
- Download the archive, extract the contents into some directory.
|
||||||
|
- Start a terminal session.
|
||||||
|
|
||||||
|
* Executable Archive, Manual, Raspberry Pi/ChromeOS ARM devices
|
||||||
|
- `gam-7.wx.yz-linux-aarch-glibc2.31.tar.xz`
|
||||||
|
- `gam-7.wx.yz-linux-aarch-legacy.tar.xz`
|
||||||
|
- Download the archive, extract the contents into some directory.
|
||||||
|
- Start a terminal session.
|
||||||
|
|
||||||
|
* Executable Archive, Manual, Mac OS versions Big Sur, Monterey, Ventura - M1/M2
|
||||||
|
- `gam-7.wx.yz-macos-aarch.tar.xz`
|
||||||
|
- Download the archive, extract the contents into some directory.
|
||||||
|
- Start a terminal session.
|
||||||
|
|
||||||
|
* Executable Archive, Manual, Mac OS, versions Big Sur, Monterey, Ventura - Intel
|
||||||
|
- `gam-7.wx.yz-macos-x86_64.tar.xz`
|
||||||
|
- Download the archive, extract the contents into some directory.
|
||||||
|
- Start a terminal session.
|
||||||
|
|
||||||
|
* Executable Archive, Manual, Windows 64 bit
|
||||||
|
- `gam-7.wx.yz-windows-x86_64.zip`
|
||||||
|
- Download the archive, extract the contents into some directory.
|
||||||
|
- Start a Command Prompt/PowerShell session.
|
||||||
|
|
||||||
|
* Executable Installer, Manual, Windows 64 bit
|
||||||
|
- `gam-7.wx.yz-windows-x86_64.msi`
|
||||||
|
- Download the installer and run it.
|
||||||
|
- Start a Command Prompt/PowerShell session.
|
||||||
|
|
||||||
|
* Source, all platforms
|
||||||
|
- `Source code(zip)`
|
||||||
|
- `Source code(tar.gz)`
|
||||||
|
- Download the archive, extract the contents into some directory.
|
||||||
|
- Start a terminal/Command Prompt/PowerShell session.
|
||||||
@@ -4,7 +4,7 @@ Many of the changes are internal to Gam and have no visible effect. Google has m
|
|||||||
A variable, `drive_v3_native_names` (default value is True), has been added to `gam.cfg` to control the field names on output: when True, the v3 native field names are used; when False, the v3 native field names are mapped to the v2 field names.
|
A variable, `drive_v3_native_names` (default value is True), has been added to `gam.cfg` to control the field names on output: when True, the v3 native field names are used; when False, the v3 native field names are mapped to the v2 field names.
|
||||||
|
|
||||||
If you have scripts that process the output from these print commands, you may have to make modifications to your scripts.
|
If you have scripts that process the output from these print commands, you may have to make modifications to your scripts.
|
||||||
Run your print/show commands with a version of Standard Gam and save the output.
|
Run your print/show commands with a version of Legacy Gam and save the output.
|
||||||
With drive_v3_native_names = False, run your print/show commands with this version of Gam and compare the output to that saved in the previous run;
|
With drive_v3_native_names = False, run your print/show commands with this version of Gam and compare the output to that saved in the previous run;
|
||||||
modify your scripts that process the output as appropriate.
|
modify your scripts that process the output as appropriate.
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,46 @@ Add the `-s` option to the end of the above commands to suppress creating the `g
|
|||||||
|
|
||||||
See [Downloads-Installs](https://github.com/taers232c/GAMADV-XTD3/wiki/Downloads-Installs) for Windows or other options, including manual installation
|
See [Downloads-Installs](https://github.com/taers232c/GAMADV-XTD3/wiki/Downloads-Installs) for Windows or other options, including manual installation
|
||||||
|
|
||||||
|
### 7.00.05
|
||||||
|
|
||||||
|
Fixed bug that caused an error when creating a calendar birthday event.
|
||||||
|
|
||||||
|
### 7.00.04
|
||||||
|
|
||||||
|
Improved performance of `gam report users orgunit <OrgUnitPath>` when `showorgunit` is not specified.
|
||||||
|
|
||||||
|
Added option `birthday <Date>` to `gam <UserTypeEntity> create event <UserCalendarEntity>` that adds
|
||||||
|
an annual recurring event to the calendar.
|
||||||
|
|
||||||
|
Added `birthday` to `<EventType>` for use in various calendar event commands.
|
||||||
|
|
||||||
|
### 7.00.03
|
||||||
|
|
||||||
|
Updated `gam delete ou` and `gam print admins` to handle the following error:
|
||||||
|
```
|
||||||
|
ERROR: 503: serviceNotAvailable - The service is currently unavailable.
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7.00.02
|
||||||
|
|
||||||
|
Added option `showlastmodification` to `gam <UserTypeEntity> print|show filecounts` that adds
|
||||||
|
the following fields to the output: `lastModifiedFileId,lastModifiedFileName,lastModifyingUser,lastModifiedTime`;
|
||||||
|
these are for the most recently modified file.
|
||||||
|
|
||||||
|
Added option `keepforever [<Boolean>]` to `gam <UserTypeEntity> update filerevisions` that allows setting
|
||||||
|
`Keep forever` in revisions.
|
||||||
|
|
||||||
|
Upgraded to Python 3.12.6 where possible.
|
||||||
|
|
||||||
|
### 7.00.01
|
||||||
|
|
||||||
|
Added option `shownames` to `gam <UserTypeEntity> print|show sheet` that causes GAM
|
||||||
|
to make an additional API call to get and display the sheet file name that is not supplied by the Sheets API.
|
||||||
|
|
||||||
|
### 7.00.00
|
||||||
|
|
||||||
|
Merged GAM-Team version
|
||||||
|
|
||||||
### 6.81.02
|
### 6.81.02
|
||||||
|
|
||||||
Updated `gam update group postmaster@domain.com` to handle the error that is generated.
|
Updated `gam update group postmaster@domain.com` to handle the error that is generated.
|
||||||
|
|||||||
@@ -25,6 +25,24 @@
|
|||||||
|
|
||||||
## Definitions
|
## Definitions
|
||||||
See [Collections of Items](Collections-of-Items)
|
See [Collections of Items](Collections-of-Items)
|
||||||
|
|
||||||
|
* [Command data from Google Docs/Sheets/Storage](Command-Data-From-Google-Docs-Sheets-Storage)
|
||||||
|
```
|
||||||
|
<StorageBucketName> ::= <String>
|
||||||
|
<StorageObjectName> ::= <String>
|
||||||
|
<StorageBucketObjectName> ::=
|
||||||
|
https://storage.cloud.google.com/<StorageBucketName>/<StorageObjectName>|
|
||||||
|
https://storage.googleapis.com/<StorageBucketName>/<StorageObjectName>|
|
||||||
|
gs://<StorageBucketName>/<StorageObjectName>|
|
||||||
|
<StorageBucketName>/<StorageObjectName>
|
||||||
|
|
||||||
|
<UserGoogleDoc> ::=
|
||||||
|
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>)
|
||||||
|
|
||||||
|
<SheetEntity> ::= <String>|id:<Number>
|
||||||
|
<UserGoogleSheet> ::=
|
||||||
|
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>) <SheetEntity>
|
||||||
|
```
|
||||||
```
|
```
|
||||||
<DeliverySetting> ::=
|
<DeliverySetting> ::=
|
||||||
allmail|
|
allmail|
|
||||||
|
|||||||
14
docs/Home.md
14
docs/Home.md
@@ -1,8 +1,7 @@
|
|||||||
- [Introduction](#introduction)
|
- [Introduction](#introduction)
|
||||||
- [Requirements](#requirements)
|
- [Requirements](#requirements)
|
||||||
- [Installation - First time GAM installation](#installation---first-time-gam-installation)
|
- [Installation - First time GAM installation](#installation---first-time-gam-installation)
|
||||||
- [Installation - Upgrading from a GAM version other than a prior version of GAMADV-X or GAMADV-XTD or GAMADV-XTD3](#installation---upgrading-from-a-gam-version-other-than-a-prior-version-of-gamadv-x-or-gamadv-xtd-or-gamadv-xtd3)
|
- [Installation - Upgrading from Legacy GAM](#installation---upgrading-from-legacy-gam)
|
||||||
- [Installation - Upgrading from a prior version of GAMADV-X or GAMADV-XTD or GAMADV-XTD3](#installation---upgrading-from-a-prior-version-of-gamadv-x-or-gamadv-xtd-or-gamadv-xtd3)
|
|
||||||
|
|
||||||
# Introduction
|
# Introduction
|
||||||
GAMADV-XTD3 is a free, open source command line tool for Google Workspace Administrators to manage domain and user settings quickly and easily.
|
GAMADV-XTD3 is a free, open source command line tool for Google Workspace Administrators to manage domain and user settings quickly and easily.
|
||||||
@@ -43,20 +42,13 @@ and all necessary authentications.
|
|||||||
* Configuration: [GAM Configuration](gam.cfg)
|
* Configuration: [GAM Configuration](gam.cfg)
|
||||||
* Install: [How to Install Advanced GAM](How-to-Install-Advanced-GAM)
|
* Install: [How to Install Advanced GAM](How-to-Install-Advanced-GAM)
|
||||||
|
|
||||||
# Installation - Upgrading from a GAM version other than a prior version of GAMADV-X or GAMADV-XTD or GAMADV-XTD3
|
# Installation - Upgrading from Legacy GAM
|
||||||
Use these steps if you have used any version of GAM in your domain. They will update your GAM project
|
Use these steps if you have used any version of GAM in your domain. They will update your GAM project
|
||||||
and all necessary authentications.
|
and all necessary authentications.
|
||||||
|
|
||||||
* Download: [Downloads-Installs](Downloads-Installs)
|
* Download: [Downloads-Installs](Downloads-Installs)
|
||||||
* Configuration: [GAM Configuration](gam.cfg)
|
* Configuration: [GAM Configuration](gam.cfg)
|
||||||
* Upgrade: [How to Upgrade from Standard GAM](How-to-Upgrade-from-Standard-GAM)
|
* Upgrade: [How to Upgrade from Legacy GAM](How-to-Upgrade-from-Legacy-GAM)
|
||||||
|
|
||||||
# Installation - Upgrading from a prior version of GAMADV-X or GAMADV-XTD or GAMADV-XTD3
|
|
||||||
Use these steps if you already use GAMADV-X or GAMADV-XTD or GAMADV-XTD3. The updates may tell you to update your GAM project
|
|
||||||
or authentications because new features have been included.
|
|
||||||
|
|
||||||
* Updates: [GAM Updates]
|
|
||||||
* Download: [Downloads-Installs](Downloads-Installs)
|
|
||||||
|
|
||||||
You can install multiple versions of GAM and GAMADV-XTD3 in different parallel directories.
|
You can install multiple versions of GAM and GAMADV-XTD3 in different parallel directories.
|
||||||
|
|
||||||
|
|||||||
120
docs/How-to-Update-Advanced-GAM-to-GAM7.md
Normal file
120
docs/How-to-Update-Advanced-GAM-to-GAM7.md
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
# Installation - Update Advanced GAM to GAM7
|
||||||
|
|
||||||
|
- [Downloads-Installs-GAM7](Downloads-Installs-GAM7)
|
||||||
|
- [Linux and MacOS and Google Cloud Shell](#linux-and-mac-os-and-google-cloud-shell)
|
||||||
|
- [Windows](#windows)
|
||||||
|
|
||||||
|
## Linux and MacOS and Google Cloud Shell
|
||||||
|
|
||||||
|
This example assumes that GAMADV-XTD3 was installed in /Users/admin/bin/gamadv-xtd3.
|
||||||
|
If GAMADV-XTD3 was installed in another directory, substitute that value in the directions.
|
||||||
|
|
||||||
|
Rename install directory.
|
||||||
|
```
|
||||||
|
mv /Users/admin/bin/gamadv-xtd3 /Users/admin/bin/gam7
|
||||||
|
```
|
||||||
|
|
||||||
|
See: [Downloads-Installs-GAM7](Downloads-Installs-GAM7)
|
||||||
|
|
||||||
|
You can download and install the current GAM7 release from the [GitHub Releases](https://github.com/GAM-team/GAM/releases/latest) page. Choose one of the following:
|
||||||
|
|
||||||
|
* Executable Archive, Automatic, Linux/Mac OS/Google Cloud Shell/Raspberry Pi/ChromeOS
|
||||||
|
- Start a terminal session and execute one of the following commands:
|
||||||
|
- Update to latest version, do not create project or authorizations, default path `$HOME/bin`
|
||||||
|
- `bash <(curl -s -S -L https://git.io/gam-install) -l`
|
||||||
|
- Update to latest version, do not create project or authorizations, specify a path
|
||||||
|
- `bash <(curl -s -S -L https://git.io/gam-install) -l -d <Path>`
|
||||||
|
|
||||||
|
In these examples, the user home folder is shown as /Users/admin; adjust according to your
|
||||||
|
specific situation; e.g., /home/administrator.
|
||||||
|
|
||||||
|
### Update gam alias
|
||||||
|
You should set an alias to point to /Users/admin/bin/gam/gam so you can operate from the /Users/admin/GAMWork directory.
|
||||||
|
Aliases aren't available in scripts, so you may want to set a symlink instead, see below.
|
||||||
|
|
||||||
|
Change the following line:
|
||||||
|
```
|
||||||
|
alias gam="/Users/admin/bin/gamadv-xtd3/gam"
|
||||||
|
```
|
||||||
|
to
|
||||||
|
```
|
||||||
|
alias gam="/Users/admin/bin/gam7/gam"
|
||||||
|
```
|
||||||
|
in one of these files based on your shell:
|
||||||
|
```
|
||||||
|
~/.bash_aliases
|
||||||
|
~/.bash_profile
|
||||||
|
~/.bashrc
|
||||||
|
~/.zshrc
|
||||||
|
~/.profile
|
||||||
|
```
|
||||||
|
|
||||||
|
Issue the following command replacing `<Filename>` with the name of the file you edited:
|
||||||
|
```
|
||||||
|
source <Filename>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Set a symlink if desired
|
||||||
|
Set a symlink in `/usr/local/bin` (or some other location on $PATH) to point to GAM.
|
||||||
|
```
|
||||||
|
ln -s "/Users/admin/bin/gam7/gam" /usr/local/bin/gam
|
||||||
|
```
|
||||||
|
|
||||||
|
### Test
|
||||||
|
```
|
||||||
|
gam version
|
||||||
|
```
|
||||||
|
|
||||||
|
## Windows
|
||||||
|
|
||||||
|
You can download and install the current GAM7 release from the [GitHub Releases](https://github.com/GAM-team/GAM/releases/latest) page.
|
||||||
|
|
||||||
|
This example assumes that GAMADV-XTD3 was installed in C:\GAMADV-XTD3.
|
||||||
|
If GAMADV-XTD3 was installed in another directory, substitute that value in the directions.
|
||||||
|
|
||||||
|
These steps assume Command Prompt, adjust if you're using PowerShell.
|
||||||
|
|
||||||
|
Rename install directory.
|
||||||
|
```
|
||||||
|
ren C:\GAMADV-STD3 C:\GAM7
|
||||||
|
```
|
||||||
|
|
||||||
|
See: [Downloads-Installs-GAM7](Downloads-Installs-GAM7)
|
||||||
|
|
||||||
|
* Executable Archive, Manual, Windows 64 bit
|
||||||
|
- `gam-7.wx.yz-windows-x86_64.zip`
|
||||||
|
- Download the archive, extract the contents into C:\GAM7.
|
||||||
|
- Start a Command Prompt/PowerShell session.
|
||||||
|
|
||||||
|
* Executable Installer, Manual, Windows 64 bit
|
||||||
|
- `gam-7.wx.yz-windows-x86_64.msi`
|
||||||
|
- Download the installer and run it.
|
||||||
|
- Start a Command Prompt/PowerShell session.
|
||||||
|
|
||||||
|
### Update system path
|
||||||
|
You should set the system path to point to C:\GAM7 so you can operate from the C:\GAMWork directory.
|
||||||
|
```
|
||||||
|
Start Control Panel
|
||||||
|
Click System
|
||||||
|
Click Advanced system settings
|
||||||
|
Click Environment Variables...
|
||||||
|
Click Path under System variables
|
||||||
|
Click Edit...
|
||||||
|
If you have an existing entry referencing GAMADV-XTD3:
|
||||||
|
Click that entry
|
||||||
|
Click Delete
|
||||||
|
If C:\GAM7 is already on the Path, skip the next three steps
|
||||||
|
Click New
|
||||||
|
Enter C:\GAM7
|
||||||
|
Click OK
|
||||||
|
Click OK
|
||||||
|
Click OK
|
||||||
|
Exit Control Panel
|
||||||
|
```
|
||||||
|
|
||||||
|
At this point, you should restart Command Prompt so that it has the updated path and environment variables.
|
||||||
|
|
||||||
|
### Test
|
||||||
|
```
|
||||||
|
gam version
|
||||||
|
```
|
||||||
1262
docs/How-to-Upgrade-from-Legacy-GAM.md
Normal file
1262
docs/How-to-Upgrade-from-Legacy-GAM.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -251,7 +251,7 @@ writes the credentials into the file oauth2.txt.
|
|||||||
admin@server:/Users/admin$ rm -f /Users/admin/GAMConfig/oauth2.txt
|
admin@server:/Users/admin$ rm -f /Users/admin/GAMConfig/oauth2.txt
|
||||||
admin@server:/Users/admin$ gam version
|
admin@server:/Users/admin$ gam version
|
||||||
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
|
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
|
||||||
GAMADV-XTD3 6.81.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
GAMADV-XTD3 7.00.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
||||||
Ross Scroggs <ross.scroggs@gmail.com>
|
Ross Scroggs <ross.scroggs@gmail.com>
|
||||||
Python 3.12.5 64-bit final
|
Python 3.12.5 64-bit final
|
||||||
MacOS Sonoma 14.5 x86_64
|
MacOS Sonoma 14.5 x86_64
|
||||||
@@ -923,7 +923,7 @@ writes the credentials into the file oauth2.txt.
|
|||||||
C:\>del C:\GAMConfig\oauth2.txt
|
C:\>del C:\GAMConfig\oauth2.txt
|
||||||
C:\>gam version
|
C:\>gam version
|
||||||
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
|
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
|
||||||
GAMADV-XTD3 6.81.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
GAMADV-XTD3 7.00.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
||||||
Ross Scroggs <ross.scroggs@gmail.com>
|
Ross Scroggs <ross.scroggs@gmail.com>
|
||||||
Python 3.12.5 64-bit final
|
Python 3.12.5 64-bit final
|
||||||
Windows-10-10.0.17134 AMD64
|
Windows-10-10.0.17134 AMD64
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Scripts
|
# Scripts
|
||||||
|
|
||||||
These scripts can be used to enhance GAM's capabilities; all are supported with Advanced GAM,
|
These scripts can be used to enhance GAM's capabilities; all are supported with Advanced GAM,
|
||||||
many are supported with Standard GAM. They require that Python 3 be installed on you computer.
|
many are supported with Legacy GAM. They require that Python 3 be installed on you computer.
|
||||||
|
|
||||||
* https://github.com/taers232c/GAM-Scripts3
|
* https://github.com/taers232c/GAM-Scripts3
|
||||||
* https://www.python.org/
|
* https://www.python.org/
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
* https://developers.google.com/calendar/v3/reference/events
|
* https://developers.google.com/calendar/v3/reference/events
|
||||||
* https://developers.google.com/calendar/v3/reference/events/import
|
* https://developers.google.com/calendar/v3/reference/events/import
|
||||||
* https://developers.google.com/calendar/api/guides/working-hours-and-location
|
* https://developers.google.com/calendar/api/guides/working-hours-and-location
|
||||||
|
* https://developers.google.com/calendar/api/guides/event-types#birthday
|
||||||
|
|
||||||
## Definitions
|
## Definitions
|
||||||
* [`<UserTypeEntity>`](Collections-of-Users)
|
* [`<UserTypeEntity>`](Collections-of-Users)
|
||||||
@@ -241,6 +242,7 @@
|
|||||||
```
|
```
|
||||||
```
|
```
|
||||||
<EventType> ::=
|
<EventType> ::=
|
||||||
|
birthday|
|
||||||
default|
|
default|
|
||||||
focustime|
|
focustime|
|
||||||
fromgmail|
|
fromgmail|
|
||||||
@@ -306,6 +308,7 @@
|
|||||||
(attendee <EmailAddress>)|
|
(attendee <EmailAddress>)|
|
||||||
(attendeestatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddress>)|
|
(attendeestatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddress>)|
|
||||||
available|
|
available|
|
||||||
|
(birthday <Date>)|
|
||||||
(color <EventColorName>)|
|
(color <EventColorName>)|
|
||||||
(colorindex|colorid <EventColorIndex>)|
|
(colorindex|colorid <EventColorIndex>)|
|
||||||
(description <String>)|
|
(description <String>)|
|
||||||
@@ -326,7 +329,7 @@
|
|||||||
(privateproperty <PropertyKey> <PropertyValue>)|
|
(privateproperty <PropertyKey> <PropertyValue>)|
|
||||||
(range <Date> <Date>)|
|
(range <Date> <Date>)|
|
||||||
(recurrence <RRULE, EXRULE, RDATE and EXDATE line>)|
|
(recurrence <RRULE, EXRULE, RDATE and EXDATE line>)|
|
||||||
(reminder <Number> email|popup))|
|
(reminder <Number> email|popup)|
|
||||||
(selectattendees [<AttendeeAttendance>] [<AttendeeStatus>] <UserTypeEntity>)|
|
(selectattendees [<AttendeeAttendance>] [<AttendeeStatus>] <UserTypeEntity>)|
|
||||||
(sequence <Integer>)|
|
(sequence <Integer>)|
|
||||||
(sharedproperty <PropertyKey> <PropertyValue>)|
|
(sharedproperty <PropertyKey> <PropertyValue>)|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
# Users - Chat
|
# Users - Chat
|
||||||
- [API documentation](#api-documentation)
|
- [API documentation](#api-documentation)
|
||||||
- [Introduction](#introduction)
|
- [Introduction](#introduction)
|
||||||
- [Developer Preview Admin Access](#developer-preview-admin-access)
|
|
||||||
- [Set up a Chat Bot](#set-up-a-chat-bot)
|
- [Set up a Chat Bot](#set-up-a-chat-bot)
|
||||||
- [Definitions](#definitions)
|
- [Definitions](#definitions)
|
||||||
- [Manage Chat Spaces](#manage-chat-spaces)
|
- [Manage Chat Spaces](#manage-chat-spaces)
|
||||||
@@ -30,36 +29,11 @@ To use these commands you must update your service account authorization.
|
|||||||
gam user user@domain.com update serviceaccount
|
gam user user@domain.com update serviceaccount
|
||||||
|
|
||||||
[*] 4) Chat API - Memberships (supports readonly)
|
[*] 4) Chat API - Memberships (supports readonly)
|
||||||
|
[*] 5) Chat API - Memberships Admin (supports readonly)
|
||||||
[*] 6) Chat API - Messages (supports readonly)
|
[*] 6) Chat API - Messages (supports readonly)
|
||||||
[*] 7) Chat API - Spaces (supports readonly)
|
[*] 7) Chat API - Spaces (supports readonly)
|
||||||
[*] 9) Chat API - Spaces Delete
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
## Developer Preview Admin Access
|
|
||||||
The Chat API Developer Preview allows an admin to perform certain actions
|
|
||||||
on all Chat Spaces. These commands were added in version 6.77.00.
|
|
||||||
|
|
||||||
You must be enrolled in the Developer Preview program for the CHAT API to use these commands.
|
|
||||||
|
|
||||||
```
|
|
||||||
gam <UserItem> delete chatspace asadmin
|
|
||||||
gam <UserItem> update chatspace asadmin
|
|
||||||
gam <UserItem> info chatspace asadmin
|
|
||||||
gam <UserItem> print|show chatspaces asadmin
|
|
||||||
gam <UserItem> create chatmember asadmin
|
|
||||||
gam <UserItem> delete|remove chatmember asadmin
|
|
||||||
gam <UserItem> update|modify chatmember asadmin
|
|
||||||
gam <UserItem> sync chatmembers asadmin
|
|
||||||
gam <UserItem> info chatmember asadmin
|
|
||||||
gam <UserItem> print|show chatmembers|asadmin
|
|
||||||
```
|
|
||||||
To use these commands you must update your service account authorization.
|
|
||||||
```
|
|
||||||
gam user user@domain.com update serviceaccount
|
|
||||||
|
|
||||||
[*] 5) Chat API - Memberships Admin (supports readonly)
|
|
||||||
[*] 8) Chat API - Spaces Admin (supports readonly)
|
[*] 8) Chat API - Spaces Admin (supports readonly)
|
||||||
|
[*] 9) Chat API - Spaces Delete
|
||||||
[*] 10) Chat API - Spaces Delete Admin
|
[*] 10) Chat API - Spaces Delete Admin
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -71,15 +45,6 @@ Added `use_chat_admin_access` Boolean variable to `gam.cfg`.
|
|||||||
* Default: False
|
* Default: False
|
||||||
```
|
```
|
||||||
|
|
||||||
If your account is not enrolled in the Chat API Developer Preview, you will see errors like this:
|
|
||||||
```
|
|
||||||
$ gam user admin@domain.com show chatspaces asadmin
|
|
||||||
Getting all Chat Spaces that match query (customer = "customers/my_customer" AND spaceType = "SPACE") for admin@domain.com(asadmin)
|
|
||||||
Chat Admin: admin@domain.com(asadmin), Show Failed: Method not found.
|
|
||||||
```
|
|
||||||
|
|
||||||
To enroll in the Developer Preview program, see: https://developers.google.com/workspace/preview
|
|
||||||
|
|
||||||
Google requires that you have a Chat Bot configured in order to use the Chat API; set up a Chat Bot as described in the next section.
|
Google requires that you have a Chat Bot configured in order to use the Chat API; set up a Chat Bot as described in the next section.
|
||||||
|
|
||||||
## Set up a Chat Bot
|
## Set up a Chat Bot
|
||||||
@@ -398,7 +363,6 @@ When using the `formatjson` option, double quotes are used extensively in the da
|
|||||||
The `quotechar <Character>` option allows you to choose an alternate quote character, single quote for instance, that makes for readable/processable output.
|
The `quotechar <Character>` option allows you to choose an alternate quote character, single quote for instance, that makes for readable/processable output.
|
||||||
`quotechar` defaults to `gam.cfg/csv_output_quote_char`. When uploading CSV files to Google, double quote `"` should be used.
|
`quotechar` defaults to `gam.cfg/csv_output_quote_char`. When uploading CSV files to Google, double quote `"` should be used.
|
||||||
|
|
||||||
|
|
||||||
## Manage Chat Members
|
## Manage Chat Members
|
||||||
### Add members to a user's chat space
|
### Add members to a user's chat space
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -693,7 +693,8 @@ gam <UserTypeEntity> print filecounts [todrive <ToDriveAttribute>*]
|
|||||||
[filenamematchpattern <RegularExpression>]
|
[filenamematchpattern <RegularExpression>]
|
||||||
<PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
|
<PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
|
||||||
[excludetrashed]
|
[excludetrashed]
|
||||||
[showsize] [showmimetypesize] (addcsvdata <FieldName> <String>)*
|
[showsize] [showmimetypesize] [showlastmodification]
|
||||||
|
(addcsvdata <FieldName> <String>)*
|
||||||
[summary none|only|plus] [summaryuser <String>]
|
[summary none|only|plus] [summaryuser <String>]
|
||||||
gam <UserTypeEntity> show filecounts
|
gam <UserTypeEntity> show filecounts
|
||||||
[((query <QueryDriveFile>) | (fullquery <QueryDriveFile>) | <DriveFileQueryShortcut>)
|
[((query <QueryDriveFile>) | (fullquery <QueryDriveFile>) | <DriveFileQueryShortcut>)
|
||||||
@@ -707,7 +708,7 @@ gam <UserTypeEntity> show filecounts
|
|||||||
[filenamematchpattern <RegularExpression>]
|
[filenamematchpattern <RegularExpression>]
|
||||||
<PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
|
<PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
|
||||||
[excludetrashed]
|
[excludetrashed]
|
||||||
[showsize] [showmimetypesize]
|
[showsize] [showmimetypesize] [showlastmodification]
|
||||||
[summary none|only|plus] [summaryuser <String>]
|
[summary none|only|plus] [summaryuser <String>]
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -723,6 +724,10 @@ The `showsize` option displays the total size (in bytes) of the files counted.
|
|||||||
|
|
||||||
The showmimetypesize' displays the total size (in bytes) of each MIME type counted.
|
The showmimetypesize' displays the total size (in bytes) of each MIME type counted.
|
||||||
|
|
||||||
|
The option `showlastmodification` displays the following fields:
|
||||||
|
`lastModifiedFileId,lastModifiedFileName,lastModifyingUser,lastModifiedTime`;
|
||||||
|
these are for the most recently modified file.
|
||||||
|
|
||||||
For print filecouts, add additional columns of data from the command line to the output:
|
For print filecouts, add additional columns of data from the command line to the output:
|
||||||
* `addcsvdata <FieldName> <String>` - Add additional columns of data from the command line to the output
|
* `addcsvdata <FieldName> <String>` - Add additional columns of data from the command line to the output
|
||||||
|
|
||||||
|
|||||||
@@ -208,7 +208,7 @@ If `noduplicate` is specfied, GAM will issue a warning and not perform the creat
|
|||||||
exists in the parent folder.
|
exists in the parent folder.
|
||||||
|
|
||||||
By default, when files are uploaded from local content, they are created with `binary` format, i.e., the data is uploaded
|
By default, when files are uploaded from local content, they are created with `binary` format, i.e., the data is uploaded
|
||||||
without any conversion. Standard GAM had an option `convert` that was passed to the Drive API v2 that it used.
|
without any conversion. Legacy GAM had an option `convert` that was passed to the Drive API v2 that it used.
|
||||||
* convert - Whether to convert this file to the corresponding Docs Editors format
|
* convert - Whether to convert this file to the corresponding Docs Editors format
|
||||||
|
|
||||||
Advanced GAM uses Drive API v3 that doesn't support the `convert` option; it uses the `mimetype` argument to cause conversions.
|
Advanced GAM uses Drive API v3 that doesn't support the `convert` option; it uses the `mimetype` argument to cause conversions.
|
||||||
|
|||||||
@@ -85,6 +85,8 @@ gam <UserTypeEntity> update filerevisions <DriveFileEntity> select <DriveFileRev
|
|||||||
```
|
```
|
||||||
When `select <DriveFileRevisionIDEntity>` is omitted, all revisions are updated.
|
When `select <DriveFileRevisionIDEntity>` is omitted, all revisions are updated.
|
||||||
|
|
||||||
|
* `keepforever true` - Keep revision forever, even if it is no longer the head revision
|
||||||
|
* `keepforever false` - Do not keep revision forever
|
||||||
* `published true` - Publish these revision to the web
|
* `published true` - Publish these revision to the web
|
||||||
* `published false` - Do not publish these revision to the web
|
* `published false` - Do not publish these revision to the web
|
||||||
* `publishauto true` - Automaticaly publish subsequent revisions to the web
|
* `publishauto true` - Automaticaly publish subsequent revisions to the web
|
||||||
|
|||||||
@@ -231,18 +231,24 @@ gam user testuser@domain.com update sheet <DriveFileItem> json file Sheet.json
|
|||||||
gam <UserTypeEntity> info|show sheet <DriveFileEntity>
|
gam <UserTypeEntity> info|show sheet <DriveFileEntity>
|
||||||
[fields <SpreadsheetFieldList>] [sheetsfields <SpreadsheetSheetsFieldList>]
|
[fields <SpreadsheetFieldList>] [sheetsfields <SpreadsheetSheetsFieldList>]
|
||||||
(range <SpreadsheetRange>)* (rangelist <SpreadsheetRangeList>)*
|
(range <SpreadsheetRange>)* (rangelist <SpreadsheetRangeList>)*
|
||||||
[includegriddata [<Boolean>]]
|
[includegriddata [<Boolean>]] [shownames]
|
||||||
[formatjson]
|
[formatjson]
|
||||||
```
|
```
|
||||||
|
By default, the Sheets API does not return the sheet file name, use the `shownames` option to have GAM
|
||||||
|
make an additional API call to get and display the sheet file name.
|
||||||
|
|
||||||
The output is formatted for human readability. Use the following option to produce JSON output for program parsing.
|
The output is formatted for human readability. Use the following option to produce JSON output for program parsing.
|
||||||
* `formatjson` - Display output in JSON format.
|
* `formatjson` - Display output in JSON format.
|
||||||
```
|
```
|
||||||
gam <UserTypeEntity> print sheet <DriveFileEntity> [todrive <ToDriveAttribute>*]
|
gam <UserTypeEntity> print sheet <DriveFileEntity> [todrive <ToDriveAttribute>*]
|
||||||
[fields <SpreadsheetFieldList>] [sheetsfields <SpreadsheetSheetsFieldList>]
|
[fields <SpreadsheetFieldList>] [sheetsfields <SpreadsheetSheetsFieldList>]
|
||||||
(range <SpreadsheetRange>)* (rangelist <SpreadsheetRangeList>)*
|
(range <SpreadsheetRange>)* (rangelist <SpreadsheetRangeList>)*
|
||||||
[includegriddata [<Boolean>]]
|
[includegriddata [<Boolean>]] [shownames]
|
||||||
[formatjson [quotechar <Character>]]
|
[formatjson [quotechar <Character>]]
|
||||||
```
|
```
|
||||||
|
By default, the Sheets API does not return the sheet file name, use the `shownames` option to have GAM
|
||||||
|
make an additional API call to get and display the sheet file name.
|
||||||
|
|
||||||
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
|
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
|
||||||
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
|
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
|
||||||
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
|
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
|
||||||
|
|||||||
@@ -80,6 +80,22 @@ queries "`"orgUnitPath=\'/Students/Lower\ School/2027\'`",`"orgUnitPath=\'/Stude
|
|||||||
* [`<UserTypeEntity>`](Collections-of-Users)
|
* [`<UserTypeEntity>`](Collections-of-Users)
|
||||||
* [Command data from Google Docs/Sheets/Storage](Command-Data-From-Google-Docs-Sheets-Storage)
|
* [Command data from Google Docs/Sheets/Storage](Command-Data-From-Google-Docs-Sheets-Storage)
|
||||||
```
|
```
|
||||||
|
<StorageBucketName> ::= <String>
|
||||||
|
<StorageObjectName> ::= <String>
|
||||||
|
<StorageBucketObjectName> ::=
|
||||||
|
https://storage.cloud.google.com/<StorageBucketName>/<StorageObjectName>|
|
||||||
|
https://storage.googleapis.com/<StorageBucketName>/<StorageObjectName>|
|
||||||
|
gs://<StorageBucketName>/<StorageObjectName>|
|
||||||
|
<StorageBucketName>/<StorageObjectName>
|
||||||
|
|
||||||
|
<UserGoogleDoc> ::=
|
||||||
|
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>)
|
||||||
|
|
||||||
|
<SheetEntity> ::= <String>|id:<Number>
|
||||||
|
<UserGoogleSheet> ::=
|
||||||
|
<EmailAddress> <DriveFileIDEntity>|<DriveFileNameEntity>|(<SharedDriveEntity> <SharedDriveFileNameEntity>) <SheetEntity>
|
||||||
|
```
|
||||||
|
```
|
||||||
<DeliverySetting> ::=
|
<DeliverySetting> ::=
|
||||||
allmail|
|
allmail|
|
||||||
abridged|daily|
|
abridged|daily|
|
||||||
@@ -736,7 +752,7 @@ When updating a user's password, you can send a message with the new password to
|
|||||||
|
|
||||||
In versions of GAMADV-XTD3 prior to 5.07.00, if you do `gam update users <UserTypeEntity>` or `gam <UserTypeEntity> update users` and
|
In versions of GAMADV-XTD3 prior to 5.07.00, if you do `gam update users <UserTypeEntity>` or `gam <UserTypeEntity> update users` and
|
||||||
specify `password random`, all of the users in `<UserTypeEntity>` are assigned the same random password;
|
specify `password random`, all of the users in `<UserTypeEntity>` are assigned the same random password;
|
||||||
this is the same behavior as in Standard GAM. If you would like each of the users in `<UserTypeEntity>` to be
|
this is the same behavior as in Legacy GAM. If you would like each of the users in `<UserTypeEntity>` to be
|
||||||
assigned a unique random password, specify `password uniquerandom`.
|
assigned a unique random password, specify `password uniquerandom`.
|
||||||
|
|
||||||
If you update a user with `password random|uniquerandom`, the `lograndompassword <FileName>` option causes GAM
|
If you update a user with `password random|uniquerandom`, the `lograndompassword <FileName>` option causes GAM
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
Print the current version of Gam with details
|
Print the current version of Gam with details
|
||||||
```
|
```
|
||||||
gam version
|
gam version
|
||||||
GAMADV-XTD3 6.81.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
GAMADV-XTD3 7.00.05 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
||||||
Ross Scroggs <ross.scroggs@gmail.com>
|
Ross Scroggs <ross.scroggs@gmail.com>
|
||||||
Python 3.12.5 64-bit final
|
Python 3.12.5 64-bit final
|
||||||
MacOS Sonoma 14.5 x86_64
|
MacOS Sonoma 14.5 x86_64
|
||||||
@@ -15,7 +15,7 @@ Time: 2023-06-02T21:10:00-07:00
|
|||||||
Print the current version of Gam with details and time offset information
|
Print the current version of Gam with details and time offset information
|
||||||
```
|
```
|
||||||
gam version timeoffset
|
gam version timeoffset
|
||||||
GAMADV-XTD3 6.81.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
GAMADV-XTD3 7.00.05 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
||||||
Ross Scroggs <ross.scroggs@gmail.com>
|
Ross Scroggs <ross.scroggs@gmail.com>
|
||||||
Python 3.12.5 64-bit final
|
Python 3.12.5 64-bit final
|
||||||
MacOS Sonoma 14.5 x86_64
|
MacOS Sonoma 14.5 x86_64
|
||||||
@@ -27,7 +27,7 @@ Your system time differs from www.googleapis.com by less than 1 second
|
|||||||
Print the current version of Gam with extended details and SSL information
|
Print the current version of Gam with extended details and SSL information
|
||||||
```
|
```
|
||||||
gam version extended
|
gam version extended
|
||||||
GAMADV-XTD3 6.81.02 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
GAMADV-XTD3 7.00.05 - https://github.com/taers232c/GAMADV-XTD3 - pythonsource
|
||||||
Ross Scroggs <ross.scroggs@gmail.com>
|
Ross Scroggs <ross.scroggs@gmail.com>
|
||||||
Python 3.12.5 64-bit final
|
Python 3.12.5 64-bit final
|
||||||
MacOS Sonoma 14.5 x86_64
|
MacOS Sonoma 14.5 x86_64
|
||||||
@@ -64,7 +64,7 @@ MacOS High Sierra 10.13.6 x86_64
|
|||||||
Path: /Users/Admin/bin/gamadv-xtd3
|
Path: /Users/Admin/bin/gamadv-xtd3
|
||||||
Version Check:
|
Version Check:
|
||||||
Current: 5.35.08
|
Current: 5.35.08
|
||||||
Latest: 6.81.02
|
Latest: 7.00.05
|
||||||
echo $?
|
echo $?
|
||||||
1
|
1
|
||||||
```
|
```
|
||||||
@@ -72,7 +72,7 @@ echo $?
|
|||||||
Print the current version number without details
|
Print the current version number without details
|
||||||
```
|
```
|
||||||
gam version simple
|
gam version simple
|
||||||
6.81.02
|
7.00.05
|
||||||
```
|
```
|
||||||
In Linux/MacOS you can do:
|
In Linux/MacOS you can do:
|
||||||
```
|
```
|
||||||
@@ -82,7 +82,7 @@ echo $VER
|
|||||||
Print the current version of Gam and address of this Wiki
|
Print the current version of Gam and address of this Wiki
|
||||||
```
|
```
|
||||||
gam help
|
gam help
|
||||||
GAM 6.81.02 - https://github.com/taers232c/GAMADV-XTD3
|
GAM 7.00.05 - https://github.com/taers232c/GAMADV-XTD3
|
||||||
Ross Scroggs <ross.scroggs@gmail.com>
|
Ross Scroggs <ross.scroggs@gmail.com>
|
||||||
Python 3.12.5 64-bit final
|
Python 3.12.5 64-bit final
|
||||||
MacOS Sonoma 14.5 x86_64
|
MacOS Sonoma 14.5 x86_64
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ Update History
|
|||||||
|
|
||||||
Installation
|
Installation
|
||||||
* [How to Install Advanced GAM](How-to-Install-Advanced-GAM)
|
* [How to Install Advanced GAM](How-to-Install-Advanced-GAM)
|
||||||
|
* [How to Update Advanced GAM to GAM7](How-to-Update-Advanced-GAM-to-GAM7)
|
||||||
* [How to Update Advanced GAM](How-to-Update-Advanced-GAM)
|
* [How to Update Advanced GAM](How-to-Update-Advanced-GAM)
|
||||||
* [How to Upgrade from Standard GAM](How-to-Upgrade-from-Standard-GAM)
|
* [How to Upgrade from Legacy GAM](How-to-Upgrade-from-Legacy-GAM)
|
||||||
* [How to Upgrade from GAMADV-X or GAMADV-XTD](How-to-Upgrade-from-GAMADV-X-or-GAMADV-XTD)
|
|
||||||
* [Install GAM as Python Library](Install-GAM-as-Python-Library)
|
* [Install GAM as Python Library](Install-GAM-as-Python-Library)
|
||||||
* [GAMADV-XTD3 on Chrome OS Devices](GAMADV-XTD3-on-Chrome-OS-Devices)
|
* [GAMADV-XTD3 on Chrome OS Devices](GAMADV-XTD3-on-Chrome-OS-Devices)
|
||||||
* [GAMADV-XTD3 on Android Devices](GAMADV-XTD3-on-Android-Devices)
|
* [GAMADV-XTD3 on Android Devices](GAMADV-XTD3-on-Android-Devices)
|
||||||
|
|||||||
@@ -944,11 +944,11 @@ domain = goo.com
|
|||||||
customer_id = my_customer
|
customer_id = my_customer
|
||||||
config_dir = goo
|
config_dir = goo
|
||||||
```
|
```
|
||||||
### Existing clients that have been accessed with Standard GAM.
|
### Existing clients that have been accessed with Legacy GAM.
|
||||||
You have two clients: foo and goo.
|
You have two clients: foo and goo.
|
||||||
Make sub-directories foo and goo in the same folder/directory as gam.cfg.
|
Make sub-directories foo and goo in the same folder/directory as gam.cfg.
|
||||||
For each client, copy the client_secrets.json and oauth2service.json files from their Standard GAM location
|
For each client, copy the client_secrets.json and oauth2service.json files from their Legacy GAM location
|
||||||
to the appropriate sub-directory. If the Standard Gam files do not have these names,
|
to the appropriate sub-directory. If the Legacy Gam files do not have these names,
|
||||||
rename them after copying them to the sub-directory.
|
rename them after copying them to the sub-directory.
|
||||||
|
|
||||||
Perform the following commands for each client (replace xxx with foo and goo).
|
Perform the following commands for each client (replace xxx with foo and goo).
|
||||||
|
|||||||
@@ -1594,6 +1594,7 @@ gam calendar <CalendarEntity> printacl [todrive <ToDriveAttribute>*]
|
|||||||
<AttendeeStatus> ::= accepted|declined|needsaction|tentative
|
<AttendeeStatus> ::= accepted|declined|needsaction|tentative
|
||||||
|
|
||||||
<EventType> ::=
|
<EventType> ::=
|
||||||
|
birthday|
|
||||||
default|
|
default|
|
||||||
focustime|
|
focustime|
|
||||||
fromgmail|
|
fromgmail|
|
||||||
@@ -3541,11 +3542,11 @@ gam [<UserTypeEntity>] show drivelabels
|
|||||||
[formatjson] [adminaccess|asadmin]
|
[formatjson] [adminaccess|asadmin]
|
||||||
`
|
`
|
||||||
gam [<UserTypeEntity>] create drivelabelpermission <DriveLabelNameEntity>
|
gam [<UserTypeEntity>] create drivelabelpermission <DriveLabelNameEntity>
|
||||||
(user <UserItem>) | (group <GroupItem) | (audience <String>)
|
(user <UserItem>) | (group <GroupItem>) | (audience <String>)
|
||||||
role applier|editor|organizer|reader
|
role applier|editor|organizer|reader
|
||||||
[formatjson] [adminaccess|asadmin]
|
[formatjson] [adminaccess|asadmin]
|
||||||
gam [<UserTypeEntity>] delete drivelabelpermission <DriveLabelNameEntity>
|
gam [<UserTypeEntity>] delete drivelabelpermission <DriveLabelNameEntity>
|
||||||
(user <UserItem>) | (group <GroupItem) | (audience <String>)
|
(user <UserItem>) | (group <GroupItem>) | (audience <String>)
|
||||||
[adminaccess|asadmin]
|
[adminaccess|asadmin]
|
||||||
gam [<UserTypeEntity>] remove drivelabelpermission <DriveLabelPermissionNameEntity>
|
gam [<UserTypeEntity>] remove drivelabelpermission <DriveLabelPermissionNameEntity>
|
||||||
[adminaccess|asadmin]
|
[adminaccess|asadmin]
|
||||||
@@ -5847,6 +5848,7 @@ gam <UserTypeEntity> transfer calendars|seccals <UserItem> [<UserCalendarEntity>
|
|||||||
<AttendeeStatus> ::= accepted|declined|needsaction|tentative
|
<AttendeeStatus> ::= accepted|declined|needsaction|tentative
|
||||||
|
|
||||||
<EventType> ::=
|
<EventType> ::=
|
||||||
|
birthday|
|
||||||
default|
|
default|
|
||||||
focustime|
|
focustime|
|
||||||
outofoffice|
|
outofoffice|
|
||||||
@@ -5896,13 +5898,15 @@ gam <UserTypeEntity> transfer calendars|seccals <UserItem> [<UserCalendarEntity>
|
|||||||
<AttendeeStatus> ::= accepted|declined|needsaction|tentative
|
<AttendeeStatus> ::= accepted|declined|needsaction|tentative
|
||||||
|
|
||||||
<EventAttribute> ::=
|
<EventAttribute> ::=
|
||||||
|
(allday <Date>)|
|
||||||
(anyonecanaddself [<Boolean>])|
|
(anyonecanaddself [<Boolean>])|
|
||||||
(attachment <String> <URL>)|
|
(attachment <String> <URL>)|
|
||||||
(attendee <EmailAddress>)|
|
(attendee <EmailAddress>)|
|
||||||
(attendeestatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddress>)|
|
(attendeestatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddress>)|
|
||||||
available|
|
available|
|
||||||
|
(birthday <Date>)|
|
||||||
(color <EventColorName>)|
|
(color <EventColorName>)|
|
||||||
(colorindex|colorid <EventColorIndex>))|
|
(colorindex|colorid <EventColorIndex>)|
|
||||||
(description <String>)|
|
(description <String>)|
|
||||||
(end|endtime (allday <Date>)|<Time>)|
|
(end|endtime (allday <Date>)|<Time>)|
|
||||||
(guestscaninviteothers <Boolean>)|
|
(guestscaninviteothers <Boolean>)|
|
||||||
@@ -5912,14 +5916,16 @@ gam <UserTypeEntity> transfer calendars|seccals <UserItem> [<UserCalendarEntity>
|
|||||||
guestscantseeotherguests|
|
guestscantseeotherguests|
|
||||||
hangoutsmeet|
|
hangoutsmeet|
|
||||||
<JSONData>|
|
<JSONData>|
|
||||||
(jsonattendees [charset <Charset>] <String>)|(jsonattendees file <FileName> [charset <Charset>])|
|
(jsonattendees [charset <Charset>] <String>)|
|
||||||
|
(jsonattendees file <FileName> [charset <Charset>])|
|
||||||
(location <String>)|
|
(location <String>)|
|
||||||
(noreminders|(reminder email|popup <Number>))|
|
(noreminders|(reminder email|popup <Number>))|
|
||||||
(optionalattendee <EmailAddress>)|
|
(optionalattendee <EmailAddress>)|
|
||||||
(originalstart|originalstarttime (allday <Date>)|<Time>)|
|
(originalstart|originalstarttime (allday <Date>)|<Time>)|
|
||||||
(privateproperty <PropertyKey> <PropertyValue>)|
|
(privateproperty <PropertyKey> <PropertyValue>)|
|
||||||
|
(range <Date> <Date>)|
|
||||||
(recurrence <RRULE, EXRULE, RDATE and EXDATE line>)|
|
(recurrence <RRULE, EXRULE, RDATE and EXDATE line>)|
|
||||||
(reminder <Number> email|popup))|
|
(reminder <Number> email|popup)|
|
||||||
(selectattendees [<AttendeeAttendance>] [<AttendeeStatus>] <UserTypeEntity>)|
|
(selectattendees [<AttendeeAttendance>] [<AttendeeStatus>] <UserTypeEntity>)|
|
||||||
(sequence <Integer>)|
|
(sequence <Integer>)|
|
||||||
(sharedproperty <PropertyKey> <PropertyValue>)|
|
(sharedproperty <PropertyKey> <PropertyValue>)|
|
||||||
@@ -5928,6 +5934,7 @@ gam <UserTypeEntity> transfer calendars|seccals <UserItem> [<UserCalendarEntity>
|
|||||||
(status confirmed|tentative|cancelled)|
|
(status confirmed|tentative|cancelled)|
|
||||||
(summary <String>)|
|
(summary <String>)|
|
||||||
tentative|
|
tentative|
|
||||||
|
(timerange <Time> <Time>)|
|
||||||
(timezone <TimeZone>)|
|
(timezone <TimeZone>)|
|
||||||
(transparency opaque|transparent)|
|
(transparency opaque|transparent)|
|
||||||
(visibility default|public|private)
|
(visibility default|public|private)
|
||||||
@@ -7043,7 +7050,8 @@ gam <UserTypeEntity> print filecounts [todrive <ToDriveAttribute>*]
|
|||||||
[filenamematchpattern <RegularExpression>]
|
[filenamematchpattern <RegularExpression>]
|
||||||
<PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
|
<PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
|
||||||
[excludetrashed]
|
[excludetrashed]
|
||||||
[showsize] [showmimetypesize] (addcsvdata <FieldName> <String>)*
|
[showsize] [showmimetypesize] [showlastmodification]
|
||||||
|
(addcsvdata <FieldName> <String>)*
|
||||||
[summary none|only|plus] [summaryuser <String>]
|
[summary none|only|plus] [summaryuser <String>]
|
||||||
gam <UserTypeEntity> show filecounts
|
gam <UserTypeEntity> show filecounts
|
||||||
[((query <QueryDriveFile>) | (fullquery <QueryDriveFile>) | <DriveFileQueryShortcut>)
|
[((query <QueryDriveFile>) | (fullquery <QueryDriveFile>) | <DriveFileQueryShortcut>)
|
||||||
@@ -7052,12 +7060,12 @@ gam <UserTypeEntity> show filecounts
|
|||||||
[corpora <CorporaAttribute>]
|
[corpora <CorporaAttribute>]
|
||||||
[select <SharedDriveEntity>]
|
[select <SharedDriveEntity>]
|
||||||
[anyowner|(showownedby any|me|others)]
|
[anyowner|(showownedby any|me|others)]
|
||||||
[showmimetype [not] <MimeTypeList>] [`<showmimetype category <MimeTypeNameList>]
|
[showmimetype [not] <MimeTypeList>] [showmimetype category <MimeTypeNameList>]
|
||||||
[sizefield quotabytesused|size] [minimumfilesize <Integer>] [maximumfilesize <Integer>]
|
[sizefield quotabytesused|size] [minimumfilesize <Integer>] [maximumfilesize <Integer>]
|
||||||
[filenamematchpattern <RegularExpression>]
|
[filenamematchpattern <RegularExpression>]
|
||||||
<PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
|
<PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
|
||||||
[excludetrashed]
|
[excludetrashed]
|
||||||
[showsize] [showmimetypesize]
|
[showsize] [showmimetypesize] [showlastmodification]
|
||||||
[summary none|only|plus] [summaryuser <String>]
|
[summary none|only|plus] [summaryuser <String>]
|
||||||
|
|
||||||
gam <UserTypeEntity> print filesharecounts [todrive <ToDriveAttribute>*]
|
gam <UserTypeEntity> print filesharecounts [todrive <ToDriveAttribute>*]
|
||||||
@@ -8244,12 +8252,12 @@ gam <UserTypeEntity> update sheet <DriveFileEntity>
|
|||||||
gam <UserTypeEntity> info|show sheet <DriveFileEntity>
|
gam <UserTypeEntity> info|show sheet <DriveFileEntity>
|
||||||
[fields <SpreadsheetFieldList>] [sheetsfields <SpreadsheetSheetsFieldList>]
|
[fields <SpreadsheetFieldList>] [sheetsfields <SpreadsheetSheetsFieldList>]
|
||||||
(range <SpreadsheetRange>)* (rangelist <SpreadsheetRangeList>)*
|
(range <SpreadsheetRange>)* (rangelist <SpreadsheetRangeList>)*
|
||||||
[includegriddata [<Boolean>]]
|
[includegriddata [<Boolean>]] [shownames]
|
||||||
[formatjson]
|
[formatjson]
|
||||||
gam <UserTypeEntity> print sheet <DriveFileEntity> [todrive <ToDriveAttribute>*]
|
gam <UserTypeEntity> print sheet <DriveFileEntity> [todrive <ToDriveAttribute>*]
|
||||||
[fields <SpreadsheetFieldList>] [sheetsfields <SpreadsheetSheetsFieldList>]
|
[fields <SpreadsheetFieldList>] [sheetsfields <SpreadsheetSheetsFieldList>]
|
||||||
(range <SpreadsheetRange>)* (rangelist <SpreadsheetRangeList>)*
|
(range <SpreadsheetRange>)* (rangelist <SpreadsheetRangeList>)*
|
||||||
[includegriddata [<Boolean>]]
|
[includegriddata [<Boolean>]] [shownames]
|
||||||
[formatjson [quotechar <Character>]]
|
[formatjson [quotechar <Character>]]
|
||||||
|
|
||||||
See: https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values#ValueRange
|
See: https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values#ValueRange
|
||||||
|
|||||||
@@ -1,3 +1,39 @@
|
|||||||
|
7.00.05
|
||||||
|
|
||||||
|
Fixed bug that caused an error when creating a calendar birthday event.
|
||||||
|
|
||||||
|
7.00.04
|
||||||
|
|
||||||
|
Improved performance of `gam report users orgunit <OrgUnitPath>` when `showorgunit` is not specified.
|
||||||
|
|
||||||
|
Added option `birthday <Date>` to `gam <UserTypeEntity> create event <UserCalendarEntity>` that adds
|
||||||
|
an annual recurring event to the calendar.
|
||||||
|
|
||||||
|
Added `birthday` to `<EventType>` for use in various calendar event commands.
|
||||||
|
|
||||||
|
7.00.03
|
||||||
|
|
||||||
|
Updated `gam delete ou` and `gam print admins` to handle the following error:
|
||||||
|
```
|
||||||
|
ERROR: 503: serviceNotAvailable - The service is currently unavailable.
|
||||||
|
```
|
||||||
|
|
||||||
|
7.00.02
|
||||||
|
|
||||||
|
Added option `showlastmodification` to `gam <UserTypeEntity> print|show filecounts` that adds
|
||||||
|
the following fields to the output: `lastModifiedFileId,lastModifiedFileName,lastModifyingUser,lastModifiedTime`;
|
||||||
|
these are for the most recently modified file.
|
||||||
|
|
||||||
|
Added option `keepforever [<Boolean>]` to `gam <UserTypeEntity> update filerevisions` that allows setting
|
||||||
|
`Keep forever` in revisions.
|
||||||
|
|
||||||
|
Upgraded to Python 3.12.6 where possible.
|
||||||
|
|
||||||
|
7.00.01
|
||||||
|
|
||||||
|
Added option `shownames` to `gam <UserTypeEntity> print|show sheet` that causes GAM
|
||||||
|
to make an additional API call to get and display the sheet file name that is not supplied by the Sheets API.
|
||||||
|
|
||||||
7.00.00
|
7.00.00
|
||||||
|
|
||||||
Merged GAM-Team version
|
Merged GAM-Team version
|
||||||
|
|||||||
@@ -16,12 +16,12 @@ OPTIONS:
|
|||||||
-u Admin user email address to use with GAM. Default is to prompt.
|
-u Admin user email address to use with GAM. Default is to prompt.
|
||||||
-r Regular user email address. Used to test service account access to user data. Default is to prompt.
|
-r Regular user email address. Used to test service account access to user data. Default is to prompt.
|
||||||
-v Version to install (latest, prerelease, draft, 3.8, etc). Default is latest.
|
-v Version to install (latest, prerelease, draft, 3.8, etc). Default is latest.
|
||||||
-s Strip gam7 component from extracted files, files will be downloaded directly to $target_dir
|
-s Strip gam component from extracted files, files will be downloaded directly to $target_dir
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
target_dir="$HOME/bin"
|
target_dir="$HOME/bin"
|
||||||
target_gam="gam/gam"
|
target_gam="gam7/gam"
|
||||||
gamarch=$(uname -m)
|
gamarch=$(uname -m)
|
||||||
gamos=$(uname -s)
|
gamos=$(uname -s)
|
||||||
osversion=""
|
osversion=""
|
||||||
@@ -30,7 +30,7 @@ upgrade_only=false
|
|||||||
gamversion="latest"
|
gamversion="latest"
|
||||||
adminuser=""
|
adminuser=""
|
||||||
regularuser=""
|
regularuser=""
|
||||||
gam_x86_64_glibc_vers="2.31"
|
gam_x86_64_glibc_vers="2.35 2.31"
|
||||||
gam_arm64_glibc_vers="2.31"
|
gam_arm64_glibc_vers="2.31"
|
||||||
strip_gam="--strip-components 0"
|
strip_gam="--strip-components 0"
|
||||||
|
|
||||||
@@ -141,7 +141,28 @@ case $gamos in
|
|||||||
;;
|
;;
|
||||||
[Mm]ac[Oo][sS]|[Dd]arwin)
|
[Mm]ac[Oo][sS]|[Dd]arwin)
|
||||||
gamos="macos"
|
gamos="macos"
|
||||||
gamfile="macos-universal2.tar.xz"
|
fullversion=$(sw_vers -productVersion)
|
||||||
|
osversion=${fullversion:0:2}
|
||||||
|
case $gamarch in
|
||||||
|
x86_64)
|
||||||
|
gamfile="macos-x86_64.tar.xz"
|
||||||
|
minimum_version=13
|
||||||
|
;;
|
||||||
|
arm|arm64|aarch64)
|
||||||
|
gamfile="macos-aarch64.tar.xz"
|
||||||
|
minimum_version=14
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo_red "ERROR: this installer currently only supports x86_64 and arm64 MacOS. Looks like you're running on $gamarch. Exiting."
|
||||||
|
exit
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
if [[ "$osversion" -ge "$minimum_version" ]]; then
|
||||||
|
echo_green "You are running MacOS ${fullversion}, good. Using GAM with ${gamfile}."
|
||||||
|
else
|
||||||
|
echo_red "Sorry, you are running MacOS ${fullversion} but GAM on ${gamarch} requires MacOS ${minimum_version}. Exiting."
|
||||||
|
exit
|
||||||
|
fi
|
||||||
;;
|
;;
|
||||||
MINGW64_NT*)
|
MINGW64_NT*)
|
||||||
gamos="windows"
|
gamos="windows"
|
||||||
@@ -154,7 +175,9 @@ case $gamos in
|
|||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
if [ "$gamversion" == "latest" -o "$gamversion" == "prerelease" -o "$gamversion" == "draft" ]; then
|
if [ "$gamversion" == "latest" ]; then
|
||||||
|
release_url="https://api.github.com/repos/GAM-team/GAM/releases/latest"
|
||||||
|
elif [ "$gamversion" == "prerelease" -o "$gamversion" == "draft" ]; then
|
||||||
release_url="https://api.github.com/repos/GAM-team/GAM/releases"
|
release_url="https://api.github.com/repos/GAM-team/GAM/releases"
|
||||||
else
|
else
|
||||||
release_url="https://api.github.com/repos/GAM-team/GAM/releases/tags/v$gamversion"
|
release_url="https://api.github.com/repos/GAM-team/GAM/releases/tags/v$gamversion"
|
||||||
|
|||||||
82
src/gam.spec
82
src/gam.spec
@@ -21,7 +21,7 @@ hiddenimports = [
|
|||||||
'gam.gamlib.yubikey',
|
'gam.gamlib.yubikey',
|
||||||
]
|
]
|
||||||
|
|
||||||
print(f"datas before analysis:\n{datas}")
|
runtime_hooks = []
|
||||||
a = Analysis(
|
a = Analysis(
|
||||||
['gam/__main__.py'],
|
['gam/__main__.py'],
|
||||||
pathex=[],
|
pathex=[],
|
||||||
@@ -30,30 +30,35 @@ a = Analysis(
|
|||||||
hiddenimports=hiddenimports,
|
hiddenimports=hiddenimports,
|
||||||
hookspath=[],
|
hookspath=[],
|
||||||
hooksconfig={},
|
hooksconfig={},
|
||||||
runtime_hooks=[],
|
runtime_hooks=runtime_hooks,
|
||||||
excludes=[],
|
excludes=[],
|
||||||
win_no_prefer_redirects=False,
|
win_no_prefer_redirects=False,
|
||||||
win_private_assemblies=False,
|
win_private_assemblies=False,
|
||||||
cipher=None,
|
cipher=None,
|
||||||
noarchive=False,
|
noarchive=False,
|
||||||
)
|
)
|
||||||
print(f"datas from analysis:\n{a.datas}")
|
#print(f"datas from analysis:\n{a.datas}")
|
||||||
for d in a.datas:
|
for d in a.datas:
|
||||||
if 'pyconfig' in d[0]:
|
if 'pyconfig' in d[0]:
|
||||||
a.datas.remove(d)
|
a.datas.remove(d)
|
||||||
break
|
break
|
||||||
print(f"datas after pyconfig cleanup:\n{a.datas}")
|
#print(f"datas after pyconfig cleanup:\n{a.datas}")
|
||||||
pyz = PYZ(a.pure,
|
pyz = PYZ(a.pure,
|
||||||
a.zipped_data,
|
a.zipped_data,
|
||||||
cipher=None)
|
cipher=None)
|
||||||
# requires Python 3.10+ but no one should be compiling
|
# requires Python 3.10+ but no one should be compiling
|
||||||
# GAM with older versions anyway
|
# GAM with older versions anyway
|
||||||
|
target_arch = None
|
||||||
|
codesign_identity = None
|
||||||
|
entitlements_file = None
|
||||||
match platform:
|
match platform:
|
||||||
case "darwin":
|
case "darwin":
|
||||||
if getenv('arch') == 'universal2':
|
if getenv('arch') == 'universal2':
|
||||||
target_arch = "universal2"
|
target_arch = "universal2"
|
||||||
else:
|
|
||||||
target_arch = None
|
codesign_identity = getenv('codesign_identity')
|
||||||
|
if codesign_identity:
|
||||||
|
entitlements_file = '../.github/actions/entitlements.plist'
|
||||||
strip = True
|
strip = True
|
||||||
case "win32":
|
case "win32":
|
||||||
target_arch = None
|
target_arch = None
|
||||||
@@ -68,9 +73,38 @@ upx = False
|
|||||||
console = True
|
console = True
|
||||||
disable_windowed_traceback = False
|
disable_windowed_traceback = False
|
||||||
argv_emulation = False
|
argv_emulation = False
|
||||||
codesign_identity = None
|
if getenv('PYINSTALLER_BUILD_ONEDIR') == 'yes':
|
||||||
entitlements_file = None
|
# Build one directory
|
||||||
if not getenv('PYINSTALLER_BUILD_ONEDIR') == 'yes':
|
exe = EXE(
|
||||||
|
pyz,
|
||||||
|
a.scripts,
|
||||||
|
[],
|
||||||
|
exclude_binaries=True,
|
||||||
|
name=name,
|
||||||
|
debug=debug,
|
||||||
|
bootloader_ignore_signals=bootloader_ignore_signals,
|
||||||
|
strip=strip,
|
||||||
|
upx=upx,
|
||||||
|
console=console,
|
||||||
|
# put most everyting under a lib/ subfolder
|
||||||
|
contents_directory='lib',
|
||||||
|
disable_windowed_traceback=disable_windowed_traceback,
|
||||||
|
argv_emulation=argv_emulation,
|
||||||
|
target_arch=target_arch,
|
||||||
|
codesign_identity=codesign_identity,
|
||||||
|
entitlements_file=entitlements_file,
|
||||||
|
)
|
||||||
|
coll = COLLECT(
|
||||||
|
exe,
|
||||||
|
a.binaries,
|
||||||
|
a.zipfiles,
|
||||||
|
a.datas,
|
||||||
|
strip=strip,
|
||||||
|
upx=upx,
|
||||||
|
upx_exclude=[],
|
||||||
|
name=name,
|
||||||
|
)
|
||||||
|
else:
|
||||||
# Build one file
|
# Build one file
|
||||||
exe = EXE(
|
exe = EXE(
|
||||||
pyz,
|
pyz,
|
||||||
@@ -91,32 +125,4 @@ if not getenv('PYINSTALLER_BUILD_ONEDIR') == 'yes':
|
|||||||
codesign_identity=codesign_identity,
|
codesign_identity=codesign_identity,
|
||||||
entitlements_file=entitlements_file,
|
entitlements_file=entitlements_file,
|
||||||
)
|
)
|
||||||
else:
|
|
||||||
# Build one folder
|
|
||||||
exe = EXE(
|
|
||||||
pyz,
|
|
||||||
a.scripts,
|
|
||||||
[],
|
|
||||||
exclude_binaries=True,
|
|
||||||
name=name,
|
|
||||||
debug=debug,
|
|
||||||
bootloader_ignore_signals=bootloader_ignore_signals,
|
|
||||||
strip=strip,
|
|
||||||
upx=upx,
|
|
||||||
console=console,
|
|
||||||
disable_windowed_traceback=disable_windowed_traceback,
|
|
||||||
argv_emulation=argv_emulation,
|
|
||||||
target_arch=target_arch,
|
|
||||||
codesign_identity=codesign_identity,
|
|
||||||
entitlements_file=entitlements_file,
|
|
||||||
)
|
|
||||||
coll = COLLECT(
|
|
||||||
exe,
|
|
||||||
a.binaries,
|
|
||||||
a.zipfiles,
|
|
||||||
a.datas,
|
|
||||||
strip=strip,
|
|
||||||
upx=upx,
|
|
||||||
upx_exclude=[],
|
|
||||||
name=name,
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
<ComponentGroup
|
<ComponentGroup
|
||||||
Id="ProductComponents"
|
Id="ProductComponents"
|
||||||
Directory="INSTALLFOLDER"
|
Directory="INSTALLFOLDER"
|
||||||
Source="dist/gam">
|
Source="dist/gam7">
|
||||||
<Component Id="gam_exe" Guid="d046ea24-c9f8-40ca-84db-70b0119933ff">
|
<Component Id="gam_exe" Guid="d046ea24-c9f8-40ca-84db-70b0119933ff">
|
||||||
<File Name="gam.exe" KeyPath="yes" />
|
<File Name="gam.exe" KeyPath="yes" />
|
||||||
<Environment Id="PATH" Name="PATH" Value="[INSTALLFOLDER]" Permanent="yes" Part="last" Action="set" System="yes" />
|
<Environment Id="PATH" Name="PATH" Value="[INSTALLFOLDER]" Permanent="yes" Part="last" Action="set" System="yes" />
|
||||||
|
|||||||
56
src/gam.wxs.template
Normal file
56
src/gam.wxs.template
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" >
|
||||||
|
<Product
|
||||||
|
Id="*"
|
||||||
|
Name="GAM7"
|
||||||
|
Language="1033"
|
||||||
|
Version="$(env.GAMVERSION)"
|
||||||
|
Manufacturer="GAM Team - google-apps-manager@googlegroups.com"
|
||||||
|
UpgradeCode="D86B52B2-EFE9-4F9D-8BA3-9D84B9B2D319">
|
||||||
|
<Package
|
||||||
|
InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />
|
||||||
|
|
||||||
|
<MajorUpgrade
|
||||||
|
DowngradeErrorMessage=
|
||||||
|
"A newer version of [ProductName] is already installed."
|
||||||
|
Schedule="afterInstallExecute" />
|
||||||
|
<MediaTemplate EmbedCab="yes" />
|
||||||
|
|
||||||
|
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLFOLDER" />
|
||||||
|
<WixVariable Id="WixUILicenseRtf" Value="LICENSE.rtf" />
|
||||||
|
<UIRef Id="WixUI_InstallDir" />
|
||||||
|
|
||||||
|
<Feature
|
||||||
|
Id="gam"
|
||||||
|
Title="GAM7"
|
||||||
|
Level="1">
|
||||||
|
<ComponentGroupRef Id="ProductComponents" />
|
||||||
|
</Feature>
|
||||||
|
</Product>
|
||||||
|
|
||||||
|
<Fragment>
|
||||||
|
<SetDirectory Id="WINDOWSVOLUME" Value="[WindowsVolume]"/>
|
||||||
|
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||||
|
<Directory Id="WINDOWSVOLUME">
|
||||||
|
<Directory Id="INSTALLFOLDER" Name="GAM7" />
|
||||||
|
</Directory>
|
||||||
|
</Directory>
|
||||||
|
</Fragment>
|
||||||
|
|
||||||
|
<Fragment>
|
||||||
|
<!-- Group of components that are our main application items -->
|
||||||
|
<ComponentGroup
|
||||||
|
Id="ProductComponents"
|
||||||
|
Directory="INSTALLFOLDER"
|
||||||
|
Source="dist/gam7">
|
||||||
|
REPLACE_ME_WITH_FILE_COMPONENTS
|
||||||
|
</ComponentGroup>
|
||||||
|
</Fragment>
|
||||||
|
|
||||||
|
<Fragment>
|
||||||
|
<InstallUISequence>
|
||||||
|
<ExecuteAction />
|
||||||
|
<Show Dialog="WelcomeDlg" Before="ProgressDlg" />
|
||||||
|
</InstallUISequence>
|
||||||
|
</Fragment>
|
||||||
|
</Wix>
|
||||||
@@ -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.00.00'
|
__version__ = '7.00.05'
|
||||||
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
||||||
|
|
||||||
#pylint: disable=wrong-import-position
|
#pylint: disable=wrong-import-position
|
||||||
@@ -9190,6 +9190,7 @@ MACOS_CODENAMES = {
|
|||||||
12: 'Monterey',
|
12: 'Monterey',
|
||||||
13: 'Ventura',
|
13: 'Ventura',
|
||||||
14: 'Sonoma',
|
14: 'Sonoma',
|
||||||
|
15: 'Sequoia',
|
||||||
}
|
}
|
||||||
|
|
||||||
def getOSPlatform():
|
def getOSPlatform():
|
||||||
@@ -9231,7 +9232,7 @@ def doCheckConnection():
|
|||||||
api_hosts.append(host)
|
api_hosts.append(host)
|
||||||
hosts.extend(sorted(api_hosts))
|
hosts.extend(sorted(api_hosts))
|
||||||
host_count = len(hosts)
|
host_count = len(hosts)
|
||||||
httpObj = getHttpObj(timeout=10)
|
httpObj = getHttpObj(timeout=30)
|
||||||
httpObj.follow_redirects = False
|
httpObj.follow_redirects = False
|
||||||
headers = {'user-agent': GAM_USER_AGENT}
|
headers = {'user-agent': GAM_USER_AGENT}
|
||||||
okay = createGreenText('OK')
|
okay = createGreenText('OK')
|
||||||
@@ -13803,6 +13804,7 @@ def doReport():
|
|||||||
Ent.SetGetting(Ent.REPORT)
|
Ent.SetGetting(Ent.REPORT)
|
||||||
elif userKey == 'all':
|
elif userKey == 'all':
|
||||||
if orgUnitId:
|
if orgUnitId:
|
||||||
|
if showOrgUnit:
|
||||||
userOrgUnits = getUserOrgUnits(cd, orgUnit, orgUnitId)
|
userOrgUnits = getUserOrgUnits(cd, orgUnit, orgUnitId)
|
||||||
forWhom = f'users in orgUnit {orgUnit}'
|
forWhom = f'users in orgUnit {orgUnit}'
|
||||||
else:
|
else:
|
||||||
@@ -13989,6 +13991,7 @@ def doReport():
|
|||||||
orgUnitId = None
|
orgUnitId = None
|
||||||
elif userKey == 'all':
|
elif userKey == 'all':
|
||||||
if orgUnitId:
|
if orgUnitId:
|
||||||
|
if showOrgUnit:
|
||||||
userOrgUnits = getUserOrgUnits(cd, orgUnit, orgUnitId)
|
userOrgUnits = getUserOrgUnits(cd, orgUnit, orgUnitId)
|
||||||
printGettingEntityItemForWhom(Ent.REPORT, f'users in orgUnit {orgUnit}')
|
printGettingEntityItemForWhom(Ent.REPORT, f'users in orgUnit {orgUnit}')
|
||||||
else:
|
else:
|
||||||
@@ -16623,13 +16626,15 @@ def doPrintShowAdmins():
|
|||||||
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, GAPI.BAD_REQUEST,
|
throwReasons=[GAPI.INVALID, GAPI.USER_NOT_FOUND,
|
||||||
GAPI.CUSTOMER_NOT_FOUND, GAPI.FORBIDDEN],
|
GAPI.FORBIDDEN, GAPI.SERVICE_NOT_AVAILABLE,
|
||||||
|
GAPI.BAD_REQUEST, GAPI.CUSTOMER_NOT_FOUND],
|
||||||
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
||||||
customer=GC.Values[GC.CUSTOMER_ID], fields=fields, **kwargs)
|
customer=GC.Values[GC.CUSTOMER_ID], fields=fields, **kwargs)
|
||||||
except (GAPI.invalid, GAPI.userNotFound):
|
except (GAPI.invalid, GAPI.userNotFound):
|
||||||
entityUnknownWarning(Ent.ADMINISTRATOR, userKey)
|
entityUnknownWarning(Ent.ADMINISTRATOR, userKey)
|
||||||
return
|
return
|
||||||
except GAPI.forbidden as e:
|
except (GAPI.forbidden, GAPI.serviceNotAvailable) as e:
|
||||||
entityActionFailedExit([Ent.ADMINISTRATOR, userKey, Ent.ADMIN_ROLE, roleId], str(e))
|
entityActionFailedExit([Ent.ADMINISTRATOR, userKey, Ent.ADMIN_ROLE, roleId], str(e))
|
||||||
except (GAPI.badRequest, GAPI.customerNotFound):
|
except (GAPI.badRequest, GAPI.customerNotFound):
|
||||||
accessErrorExit(cd)
|
accessErrorExit(cd)
|
||||||
@@ -17334,14 +17339,17 @@ def _doDeleteOrgs(entityList):
|
|||||||
try:
|
try:
|
||||||
orgUnitPath = makeOrgUnitPathAbsolute(orgUnitPath)
|
orgUnitPath = makeOrgUnitPathAbsolute(orgUnitPath)
|
||||||
callGAPI(cd.orgunits(), 'delete',
|
callGAPI(cd.orgunits(), 'delete',
|
||||||
throwReasons=[GAPI.CONDITION_NOT_MET, GAPI.INVALID_ORGUNIT, GAPI.ORGUNIT_NOT_FOUND, GAPI.BACKEND_ERROR, GAPI.BAD_REQUEST, GAPI.INVALID_CUSTOMER_ID, GAPI.LOGIN_REQUIRED],
|
throwReasons=[GAPI.CONDITION_NOT_MET, GAPI.INVALID_ORGUNIT, GAPI.ORGUNIT_NOT_FOUND, GAPI.BACKEND_ERROR,
|
||||||
|
GAPI.INVALID_CUSTOMER_ID, GAPI.SERVICE_NOT_AVAILABLE,
|
||||||
|
GAPI.BAD_REQUEST, GAPI.LOGIN_REQUIRED],
|
||||||
|
retryReasons=GAPI.SERVICE_NOT_AVAILABLE_RETRY_REASONS,
|
||||||
customerId=GC.Values[GC.CUSTOMER_ID], orgUnitPath=encodeOrgUnitPath(makeOrgUnitPathRelative(orgUnitPath)))
|
customerId=GC.Values[GC.CUSTOMER_ID], orgUnitPath=encodeOrgUnitPath(makeOrgUnitPathRelative(orgUnitPath)))
|
||||||
entityActionPerformed([Ent.ORGANIZATIONAL_UNIT, orgUnitPath], i, count)
|
entityActionPerformed([Ent.ORGANIZATIONAL_UNIT, orgUnitPath], i, count)
|
||||||
except GAPI.conditionNotMet:
|
except GAPI.conditionNotMet:
|
||||||
entityActionFailedWarning([Ent.ORGANIZATIONAL_UNIT, orgUnitPath], Msg.HAS_CHILD_ORGS.format(Ent.Plural(Ent.ORGANIZATIONAL_UNIT)), i, count)
|
entityActionFailedWarning([Ent.ORGANIZATIONAL_UNIT, orgUnitPath], Msg.HAS_CHILD_ORGS.format(Ent.Plural(Ent.ORGANIZATIONAL_UNIT)), i, count)
|
||||||
except (GAPI.invalidOrgunit, GAPI.orgunitNotFound, GAPI.backendError):
|
except (GAPI.invalidOrgunit, GAPI.orgunitNotFound, GAPI.backendError):
|
||||||
entityActionFailedWarning([Ent.ORGANIZATIONAL_UNIT, orgUnitPath], Msg.DOES_NOT_EXIST, i, count)
|
entityActionFailedWarning([Ent.ORGANIZATIONAL_UNIT, orgUnitPath], Msg.DOES_NOT_EXIST, i, count)
|
||||||
except GAPI.invalidCustomerId as e:
|
except (GAPI.invalidCustomerId, GAPI.serviceNotAvailable) as e:
|
||||||
### Check for my_customer
|
### Check for my_customer
|
||||||
entityActionFailedWarning([Ent.ORGANIZATIONAL_UNIT, orgUnitPath, Ent.CUSTOMER_ID, GC.Values[GC.CUSTOMER_ID]], str(e), i, count)
|
entityActionFailedWarning([Ent.ORGANIZATIONAL_UNIT, orgUnitPath, Ent.CUSTOMER_ID, GC.Values[GC.CUSTOMER_ID]], str(e), i, count)
|
||||||
except (GAPI.badRequest, GAPI.loginRequired):
|
except (GAPI.badRequest, GAPI.loginRequired):
|
||||||
@@ -37335,6 +37343,7 @@ def doCalendarsPrintShowACLs(calIds):
|
|||||||
if csvPF:
|
if csvPF:
|
||||||
csvPF.writeCSVfile('Calendar ACLs')
|
csvPF.writeCSVfile('Calendar ACLs')
|
||||||
|
|
||||||
|
EVENT_TYPE_BIRTHDAY = 'birthday'
|
||||||
EVENT_TYPE_DEFAULT = 'default'
|
EVENT_TYPE_DEFAULT = 'default'
|
||||||
EVENT_TYPE_FOCUSTIME = 'focusTime'
|
EVENT_TYPE_FOCUSTIME = 'focusTime'
|
||||||
EVENT_TYPE_FROMGMAIL = 'fromGmail'
|
EVENT_TYPE_FROMGMAIL = 'fromGmail'
|
||||||
@@ -37342,6 +37351,7 @@ EVENT_TYPE_OUTOFOFFICE = 'outOfOffice'
|
|||||||
EVENT_TYPE_WORKINGLOCATION = 'workingLocation'
|
EVENT_TYPE_WORKINGLOCATION = 'workingLocation'
|
||||||
|
|
||||||
EVENT_TYPES_CHOICE_MAP = {
|
EVENT_TYPES_CHOICE_MAP = {
|
||||||
|
'birthday': EVENT_TYPE_BIRTHDAY,
|
||||||
'default': EVENT_TYPE_DEFAULT,
|
'default': EVENT_TYPE_DEFAULT,
|
||||||
'focustime': EVENT_TYPE_FOCUSTIME,
|
'focustime': EVENT_TYPE_FOCUSTIME,
|
||||||
'fromgmail': EVENT_TYPE_FROMGMAIL,
|
'fromgmail': EVENT_TYPE_FROMGMAIL,
|
||||||
@@ -37349,20 +37359,6 @@ EVENT_TYPES_CHOICE_MAP = {
|
|||||||
'workinglocation': EVENT_TYPE_WORKINGLOCATION,
|
'workinglocation': EVENT_TYPE_WORKINGLOCATION,
|
||||||
}
|
}
|
||||||
|
|
||||||
#EVENT_TYPE_DEFAULT_PROPERTIES_MAP = {
|
|
||||||
# EVENT_TYPE_DEFAULT: {'eventType': EVENT_TYPE_DEFAULT},
|
|
||||||
# EVENT_TYPE_FOCUSTIME: {'eventType': EVENT_TYPE_FOCUSTIME,
|
|
||||||
# 'focusTimeProperties': {'autoDeclineMode': 'declineNone', 'declineMessage': 'Declined', 'chatStatus': 'doNotDisturb'},
|
|
||||||
# 'transparency':'opaque'},
|
|
||||||
# EVENT_TYPE_FROMGMAIL: {'eventType': EVENT_TYPE_FROMGMAIL},
|
|
||||||
# EVENT_TYPE_OUTOFOFFICE: {'eventType': EVENT_TYPE_OUTOFOFFICE,
|
|
||||||
# 'outOfOfficeProperties': {'autoDeclineMode': 'declineOnlyNewConflictingInvitations', 'declineMessage': 'Declined'},
|
|
||||||
# 'transparency':'opaque'},
|
|
||||||
# EVENT_TYPE_WORKINGLOCATION: {'eventType': EVENT_TYPE_WORKINGLOCATION,
|
|
||||||
# 'workingLocationProperties': {},
|
|
||||||
# 'visibility': 'public', 'transparency':'transparent'},
|
|
||||||
# }
|
|
||||||
|
|
||||||
EVENT_TYPE_PROPERTIES_NAME_MAP = {
|
EVENT_TYPE_PROPERTIES_NAME_MAP = {
|
||||||
EVENT_TYPE_DEFAULT: None,
|
EVENT_TYPE_DEFAULT: None,
|
||||||
EVENT_TYPE_FOCUSTIME: f'{EVENT_TYPE_FOCUSTIME}Properties',
|
EVENT_TYPE_FOCUSTIME: f'{EVENT_TYPE_FOCUSTIME}Properties',
|
||||||
@@ -37372,6 +37368,7 @@ EVENT_TYPE_PROPERTIES_NAME_MAP = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
EVENT_TYPE_ENTITY_MAP = {
|
EVENT_TYPE_ENTITY_MAP = {
|
||||||
|
EVENT_TYPE_BIRTHDAY: Ent.EVENT_BIRTHDAY,
|
||||||
EVENT_TYPE_DEFAULT: None,
|
EVENT_TYPE_DEFAULT: None,
|
||||||
EVENT_TYPE_FOCUSTIME: Ent.EVENT_FOCUSTIME,
|
EVENT_TYPE_FOCUSTIME: Ent.EVENT_FOCUSTIME,
|
||||||
EVENT_TYPE_FROMGMAIL: None,
|
EVENT_TYPE_FROMGMAIL: None,
|
||||||
@@ -37605,6 +37602,16 @@ def _getCalendarEventAttribute(myarg, body, parameters, function):
|
|||||||
elif myarg == 'timerange':
|
elif myarg == 'timerange':
|
||||||
body['start'] = {'dateTime': getTimeOrDeltaFromNow()}
|
body['start'] = {'dateTime': getTimeOrDeltaFromNow()}
|
||||||
body['end'] = {'dateTime': getTimeOrDeltaFromNow()}
|
body['end'] = {'dateTime': getTimeOrDeltaFromNow()}
|
||||||
|
elif myarg == 'birthday':
|
||||||
|
body['eventType'] = EVENT_TYPE_BIRTHDAY
|
||||||
|
body['visibility'] = 'private'
|
||||||
|
body['transparency'] = 'transparent'
|
||||||
|
bday = getYYYYMMDD(returnDateTime=True)
|
||||||
|
body['start'] = body['end'] = {'date': bday.strftime(YYYYMMDD_FORMAT)}
|
||||||
|
if bday.month != 2 or bday.day != 29:
|
||||||
|
body['recurrence'] = ['RRULE:FREQ=YEARLY']
|
||||||
|
else:
|
||||||
|
body['recurrence'] = ['RRULE:FREQ=YEARLY;BYMONTH=2;BYMONTHDAY=-1']
|
||||||
elif myarg == 'attachment':
|
elif myarg == 'attachment':
|
||||||
body.setdefault('attachments', [])
|
body.setdefault('attachments', [])
|
||||||
body['attachments'].append({'title': getString(Cmd.OB_STRING), 'fileUrl': getString(Cmd.OB_URL)})
|
body['attachments'].append({'title': getString(Cmd.OB_STRING), 'fileUrl': getString(Cmd.OB_URL)})
|
||||||
@@ -38015,12 +38022,14 @@ def _createCalendarEvents(user, origCal, function, calIds, count, body, paramete
|
|||||||
if function == 'insert':
|
if function == 'insert':
|
||||||
event = callGAPI(cal.events(), 'insert',
|
event = callGAPI(cal.events(), 'insert',
|
||||||
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.INVALID, GAPI.REQUIRED, GAPI.TIME_RANGE_EMPTY, GAPI.EVENT_DURATION_EXCEEDS_LIMIT,
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.INVALID, GAPI.REQUIRED, GAPI.TIME_RANGE_EMPTY, GAPI.EVENT_DURATION_EXCEEDS_LIMIT,
|
||||||
GAPI.REQUIRED_ACCESS_LEVEL, GAPI.DUPLICATE, GAPI.FORBIDDEN, GAPI.MALFORMED_WORKING_LOCATION_EVENT],
|
GAPI.REQUIRED_ACCESS_LEVEL, GAPI.DUPLICATE, GAPI.FORBIDDEN,
|
||||||
|
GAPI.MALFORMED_WORKING_LOCATION_EVENT, GAPI.BAD_REQUEST],
|
||||||
calendarId=calId, conferenceDataVersion=1, sendUpdates=parameters['sendUpdates'], supportsAttachments=True, body=body, fields=fields)
|
calendarId=calId, conferenceDataVersion=1, sendUpdates=parameters['sendUpdates'], supportsAttachments=True, body=body, fields=fields)
|
||||||
else:
|
else:
|
||||||
event = callGAPI(cal.events(), 'import_',
|
event = callGAPI(cal.events(), 'import_',
|
||||||
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.INVALID, GAPI.REQUIRED, GAPI.TIME_RANGE_EMPTY, GAPI.EVENT_DURATION_EXCEEDS_LIMIT,
|
throwReasons=GAPI.CALENDAR_THROW_REASONS+[GAPI.INVALID, GAPI.REQUIRED, GAPI.TIME_RANGE_EMPTY, GAPI.EVENT_DURATION_EXCEEDS_LIMIT,
|
||||||
GAPI.REQUIRED_ACCESS_LEVEL, GAPI.DUPLICATE, GAPI.FORBIDDEN, GAPI.MALFORMED_WORKING_LOCATION_EVENT,
|
GAPI.REQUIRED_ACCESS_LEVEL, GAPI.DUPLICATE, GAPI.FORBIDDEN,
|
||||||
|
GAPI.MALFORMED_WORKING_LOCATION_EVENT, GAPI.BAD_REQUEST,
|
||||||
GAPI.PARTICIPANT_IS_NEITHER_ORGANIZER_NOR_ATTENDEE],
|
GAPI.PARTICIPANT_IS_NEITHER_ORGANIZER_NOR_ATTENDEE],
|
||||||
calendarId=calId, conferenceDataVersion=1, supportsAttachments=True, body=body, fields=fields)
|
calendarId=calId, conferenceDataVersion=1, supportsAttachments=True, body=body, fields=fields)
|
||||||
if parameters['csvPF'] is None:
|
if parameters['csvPF'] is None:
|
||||||
@@ -38030,7 +38039,8 @@ def _createCalendarEvents(user, origCal, function, calIds, count, body, paramete
|
|||||||
_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.malformedWorkingLocationEvent) as e:
|
GAPI.requiredAccessLevel, GAPI.participantIsNeitherOrganizerNorAttendee,
|
||||||
|
GAPI.malformedWorkingLocationEvent, GAPI.badRequest) as e:
|
||||||
entityActionFailedWarning([Ent.CALENDAR, calId, Ent.EVENT, event['id']], str(e), i, count)
|
entityActionFailedWarning([Ent.CALENDAR, calId, Ent.EVENT, event['id']], str(e), i, count)
|
||||||
except GAPI.duplicate as e:
|
except GAPI.duplicate as e:
|
||||||
entityActionFailedWarning([Ent.CALENDAR, calId, Ent.EVENT, event['id']], str(e), i, count)
|
entityActionFailedWarning([Ent.CALENDAR, calId, Ent.EVENT, event['id']], str(e), i, count)
|
||||||
@@ -51080,7 +51090,7 @@ def createStatusEvent(users, eventType):
|
|||||||
missingArgumentExit('|'.join(WORKING_LOCATION_CHOICE_MAP))
|
missingArgumentExit('|'.join(WORKING_LOCATION_CHOICE_MAP))
|
||||||
elif eventType == EVENT_TYPE_OUTOFOFFICE:
|
elif eventType == EVENT_TYPE_OUTOFOFFICE:
|
||||||
getOutOfOfficeProperties(body, parameters, dateList)
|
getOutOfOfficeProperties(body, parameters, dateList)
|
||||||
else: # eventType == EVENT_TYPE_FOCUSTIME
|
else: # elif eventType == EVENT_TYPE_FOCUSTIME:
|
||||||
getFocusTimeProperties(body, parameters, dateList)
|
getFocusTimeProperties(body, parameters, dateList)
|
||||||
if not dateList:
|
if not dateList:
|
||||||
missingChoiceExit(STATUS_EVENTS_DATETIME_CHOICES)
|
missingChoiceExit(STATUS_EVENTS_DATETIME_CHOICES)
|
||||||
@@ -53967,12 +53977,14 @@ def deleteFileRevisions(users):
|
|||||||
Ind.Decrement()
|
Ind.Decrement()
|
||||||
|
|
||||||
REVISIONS_FIELDS_CHOICE_MAP = {
|
REVISIONS_FIELDS_CHOICE_MAP = {
|
||||||
|
'keepforever': 'keepForever',
|
||||||
'published': 'published',
|
'published': 'published',
|
||||||
'publishauto': 'publishAuto',
|
'publishauto': 'publishAuto',
|
||||||
'publishedoutsidedomain': 'publishedOutsideDomain'
|
'publishedoutsidedomain': 'publishedOutsideDomain'
|
||||||
}
|
}
|
||||||
# gam <UserTypeEntity> update filerevisions <DriveFileEntity> select <DriveFileRevisionIdEntity> [previewupdate]
|
# gam <UserTypeEntity> update filerevisions <DriveFileEntity> select <DriveFileRevisionIdEntity> [previewupdate]
|
||||||
# [published [<Boolean>]] [publishauto [<Boolean>]] [publishedoutsidedomain [<Boolean>]]
|
# [published [<Boolean>]] [publishauto [<Boolean>]] [publishedoutsidedomain [<Boolean>]]
|
||||||
|
# [keepforever [<Boolean>]}
|
||||||
# [showtitles] [doit] [max_to_update <Number>]
|
# [showtitles] [doit] [max_to_update <Number>]
|
||||||
def updateFileRevisions(users):
|
def updateFileRevisions(users):
|
||||||
fileIdEntity = getDriveFileEntity()
|
fileIdEntity = getDriveFileEntity()
|
||||||
@@ -56118,7 +56130,8 @@ def printFileParentTree(users):
|
|||||||
# [filenamematchpattern <RegularExpression>]
|
# [filenamematchpattern <RegularExpression>]
|
||||||
# <PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
|
# <PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
|
||||||
# [excludetrashed] (addcsvdata <FieldName> <String>)*
|
# [excludetrashed] (addcsvdata <FieldName> <String>)*
|
||||||
# [showsize] [showmimetypesize]
|
# [showsize] [showmimetypesize] [showlastmodification]
|
||||||
|
# (addcsvdata <FieldName> <String>)*
|
||||||
# [summary none|only|plus] [summaryuser <String>]
|
# [summary none|only|plus] [summaryuser <String>]
|
||||||
# gam <UserTypeEntity> show filecounts
|
# gam <UserTypeEntity> show filecounts
|
||||||
# [((query <QueryDriveFile>) | (fullquery <QueryDriveFile>) | <DriveFileQueryShortcut>) (querytime<String> <Time>)*]
|
# [((query <QueryDriveFile>) | (fullquery <QueryDriveFile>) | <DriveFileQueryShortcut>) (querytime<String> <Time>)*]
|
||||||
@@ -56131,7 +56144,7 @@ def printFileParentTree(users):
|
|||||||
# [filenamematchpattern <RegularExpression>]
|
# [filenamematchpattern <RegularExpression>]
|
||||||
# <PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
|
# <PermissionMatch>* [<PermissionMatchMode>] [<PermissionMatchAction>]
|
||||||
# [excludetrashed]
|
# [excludetrashed]
|
||||||
# [showsize] [showmimetypesize]
|
# [showsize] [showmimetypesize] [showlastmodification]
|
||||||
# [summary none|only|plus] [summaryuser <String>]
|
# [summary none|only|plus] [summaryuser <String>]
|
||||||
def printShowFileCounts(users):
|
def printShowFileCounts(users):
|
||||||
def _setSelectionFields():
|
def _setSelectionFields():
|
||||||
@@ -56139,6 +56152,8 @@ def printShowFileCounts(users):
|
|||||||
fieldsList.extend(OWNED_BY_ME_FIELDS_TITLES)
|
fieldsList.extend(OWNED_BY_ME_FIELDS_TITLES)
|
||||||
if showSize or (DLP.minimumFileSize is not None) or (DLP.maximumFileSize is not None):
|
if showSize or (DLP.minimumFileSize is not None) or (DLP.maximumFileSize is not None):
|
||||||
fieldsList.append(sizeField)
|
fieldsList.append(sizeField)
|
||||||
|
if showLastModification:
|
||||||
|
fieldsList.extend(['id,name,modifiedTime,lastModifyingUser(emailAddress)'])
|
||||||
if DLP.filenameMatchPattern:
|
if DLP.filenameMatchPattern:
|
||||||
fieldsList.append('name')
|
fieldsList.append('name')
|
||||||
if DLP.excludeTrashed:
|
if DLP.excludeTrashed:
|
||||||
@@ -56148,7 +56163,7 @@ def printShowFileCounts(users):
|
|||||||
if DLP.onlySharedDrives or getPermissionsForSharedDrives:
|
if DLP.onlySharedDrives or getPermissionsForSharedDrives:
|
||||||
fieldsList.append('driveId')
|
fieldsList.append('driveId')
|
||||||
|
|
||||||
def showMimeTypeInfo(user, mimeTypeInfo, sharedDriveId, sharedDriveName, i, count):
|
def showMimeTypeInfo(user, mimeTypeInfo, sharedDriveId, sharedDriveName, lastModification, i, count):
|
||||||
if summary != FILECOUNT_SUMMARY_NONE:
|
if summary != FILECOUNT_SUMMARY_NONE:
|
||||||
if count != 0:
|
if count != 0:
|
||||||
for mimeType, mtinfo in iter(mimeTypeInfo.items()):
|
for mimeType, mtinfo in iter(mimeTypeInfo.items()):
|
||||||
@@ -56173,6 +56188,10 @@ def printShowFileCounts(users):
|
|||||||
dataList.extend(['Item cap', f"{countTotal/SHARED_DRIVE_MAX_FILES_FOLDERS:.2%}"])
|
dataList.extend(['Item cap', f"{countTotal/SHARED_DRIVE_MAX_FILES_FOLDERS:.2%}"])
|
||||||
printEntityKVList(kvList, dataList, i, count)
|
printEntityKVList(kvList, dataList, i, count)
|
||||||
Ind.Increment()
|
Ind.Increment()
|
||||||
|
if showLastModification:
|
||||||
|
printKeyValueList(['lastModifiedFile', f"{lastModification['lastModifiedFileName']}({lastModification['lastModifiedFileId']})",
|
||||||
|
'lastModifyingUser', lastModification['lastModifyingUser'],
|
||||||
|
'lastModifiedTime', formatLocalTime(lastModification['lastModifiedTime'])])
|
||||||
for mimeType, mtinfo in sorted(iter(mimeTypeInfo.items())):
|
for mimeType, mtinfo in sorted(iter(mimeTypeInfo.items())):
|
||||||
if not showMimeTypeSize:
|
if not showMimeTypeSize:
|
||||||
printKeyValueList([mimeType, mtinfo['count']])
|
printKeyValueList([mimeType, mtinfo['count']])
|
||||||
@@ -56186,6 +56205,11 @@ def printShowFileCounts(users):
|
|||||||
row = {'User': user, 'Total': countTotal}
|
row = {'User': user, 'Total': countTotal}
|
||||||
if showSize:
|
if showSize:
|
||||||
row['Size'] = sizeTotal
|
row['Size'] = sizeTotal
|
||||||
|
if showLastModification:
|
||||||
|
row.update({'lastModifiedFileId': lastModification['lastModifiedFileId'],
|
||||||
|
'lastModifiedFileName': lastModification['lastModifiedFileName'],
|
||||||
|
'lastModifyingUser': lastModification['lastModifyingUser'],
|
||||||
|
'lastModifiedTime': formatLocalTime(lastModification['lastModifiedTime'])})
|
||||||
if addCSVData:
|
if addCSVData:
|
||||||
row.update(addCSVData)
|
row.update(addCSVData)
|
||||||
for mimeType, mtinfo in sorted(iter(mimeTypeInfo.items())):
|
for mimeType, mtinfo in sorted(iter(mimeTypeInfo.items())):
|
||||||
@@ -56200,13 +56224,16 @@ def printShowFileCounts(users):
|
|||||||
fieldsList = ['mimeType']
|
fieldsList = ['mimeType']
|
||||||
DLP = DriveListParameters({'allowChoose': False, 'allowCorpora': True, 'allowQuery': True, 'mimeTypeInQuery': True})
|
DLP = DriveListParameters({'allowChoose': False, 'allowCorpora': True, 'allowQuery': True, 'mimeTypeInQuery': True})
|
||||||
sharedDriveId = sharedDriveName = ''
|
sharedDriveId = sharedDriveName = ''
|
||||||
continueOnInvalidQuery = showSize = showMimeTypeSize = False
|
continueOnInvalidQuery = showSize = showLastModification = showMimeTypeSize = False
|
||||||
sizeField = 'quotaBytesUsed'
|
sizeField = 'quotaBytesUsed'
|
||||||
summary = FILECOUNT_SUMMARY_NONE
|
summary = FILECOUNT_SUMMARY_NONE
|
||||||
summaryUser = FILECOUNT_SUMMARY_USER
|
summaryUser = FILECOUNT_SUMMARY_USER
|
||||||
summaryMimeTypeInfo = {}
|
summaryMimeTypeInfo = {}
|
||||||
fileIdEntity = {}
|
fileIdEntity = {}
|
||||||
addCSVData = {}
|
addCSVData = {}
|
||||||
|
summaryLastModification = {
|
||||||
|
'lastModifiedFileId': '', 'lastModifiedFileName': '',
|
||||||
|
'lastModifyingUser': '', 'lastModifiedTime': NEVER_TIME}
|
||||||
while Cmd.ArgumentsRemaining():
|
while Cmd.ArgumentsRemaining():
|
||||||
myarg = getArgument()
|
myarg = getArgument()
|
||||||
if csvPF and myarg == 'todrive':
|
if csvPF and myarg == 'todrive':
|
||||||
@@ -56221,6 +56248,8 @@ def printShowFileCounts(users):
|
|||||||
showSize = True
|
showSize = True
|
||||||
elif myarg == 'sizefield':
|
elif myarg == 'sizefield':
|
||||||
sizeField = getChoice(SIZE_FIELD_CHOICE_MAP, mapChoice=True)
|
sizeField = getChoice(SIZE_FIELD_CHOICE_MAP, mapChoice=True)
|
||||||
|
elif myarg == 'showlastmodification':
|
||||||
|
showLastModification = True
|
||||||
elif myarg == 'showmimetypesize':
|
elif myarg == 'showmimetypesize':
|
||||||
showMimeTypeSize = showSize = True
|
showMimeTypeSize = showSize = True
|
||||||
elif myarg == 'summary':
|
elif myarg == 'summary':
|
||||||
@@ -56252,6 +56281,8 @@ def printShowFileCounts(users):
|
|||||||
sortTitles = ['User', 'id', 'name', 'Total', 'Item cap'] if fileIdEntity.get('shareddrive') else ['User', 'Total']
|
sortTitles = ['User', 'id', 'name', 'Total', 'Item cap'] if fileIdEntity.get('shareddrive') else ['User', 'Total']
|
||||||
if showSize:
|
if showSize:
|
||||||
sortTitles.insert(sortTitles.index('Total')+1, 'Size')
|
sortTitles.insert(sortTitles.index('Total')+1, 'Size')
|
||||||
|
if showLastModification:
|
||||||
|
sortTitles.extend(['lastModifiedFileId', 'lastModifiedFileName', 'lastModifyingUser', 'lastModifiedTime'])
|
||||||
if addCSVData:
|
if addCSVData:
|
||||||
sortTitles.extend(sorted(addCSVData.keys()))
|
sortTitles.extend(sorted(addCSVData.keys()))
|
||||||
csvPF.SetTitles(sortTitles)
|
csvPF.SetTitles(sortTitles)
|
||||||
@@ -56269,6 +56300,9 @@ def printShowFileCounts(users):
|
|||||||
else:
|
else:
|
||||||
sharedDriveName = ''
|
sharedDriveName = ''
|
||||||
mimeTypeInfo = {}
|
mimeTypeInfo = {}
|
||||||
|
userLastModification = {
|
||||||
|
'lastModifiedFileId': '', 'lastModifiedFileName': '',
|
||||||
|
'lastModifyingUser': '', 'lastModifiedTime': NEVER_TIME}
|
||||||
printGettingAllEntityItemsForWhom(Ent.DRIVE_FILE_OR_FOLDER, user, i, count, query=DLP.fileIdEntity['query'])
|
printGettingAllEntityItemsForWhom(Ent.DRIVE_FILE_OR_FOLDER, user, i, count, query=DLP.fileIdEntity['query'])
|
||||||
try:
|
try:
|
||||||
feed = yieldGAPIpages(drive.files(), 'list', 'files',
|
feed = yieldGAPIpages(drive.files(), 'list', 'files',
|
||||||
@@ -56309,7 +56343,15 @@ def printShowFileCounts(users):
|
|||||||
mimeTypeInfo.setdefault(f_file['mimeType'], {'count': 0, 'size': 0})
|
mimeTypeInfo.setdefault(f_file['mimeType'], {'count': 0, 'size': 0})
|
||||||
mimeTypeInfo[f_file['mimeType']]['count'] += 1
|
mimeTypeInfo[f_file['mimeType']]['count'] += 1
|
||||||
mimeTypeInfo[f_file['mimeType']]['size'] += int(f_file.get(sizeField, '0'))
|
mimeTypeInfo[f_file['mimeType']]['size'] += int(f_file.get(sizeField, '0'))
|
||||||
showMimeTypeInfo(user, mimeTypeInfo, sharedDriveId, sharedDriveName, i, count)
|
if showLastModification:
|
||||||
|
if f_file.get('modifiedTime', NEVER_TIME) > userLastModification['lastModifiedTime'] and 'lastModifyingUser' in f_file:
|
||||||
|
userLastModification['lastModifiedFileId'] = f_file['id']
|
||||||
|
userLastModification['lastModifiedFileName'] = _stripControlCharsFromName(f_file['name'])
|
||||||
|
userLastModification['lastModifiedTime'] = f_file['modifiedTime']
|
||||||
|
userLastModification['lastModifyingUser'] = f_file['lastModifyingUser'].get('emailAddress', UNKNOWN)
|
||||||
|
showMimeTypeInfo(user, mimeTypeInfo, sharedDriveId, sharedDriveName, userLastModification, i, count)
|
||||||
|
if showLastModification and userLastModification['lastModifiedTime'] > summaryLastModification['lastModifiedTime']:
|
||||||
|
summaryLastModification = userLastModification.copy()
|
||||||
except (GAPI.invalidQuery, GAPI.invalid, GAPI.badRequest):
|
except (GAPI.invalidQuery, GAPI.invalid, GAPI.badRequest):
|
||||||
entityActionFailedWarning([Ent.USER, user, Ent.DRIVE_FILE_OR_FOLDER, None], invalidQuery(DLP.fileIdEntity['query']), i, count)
|
entityActionFailedWarning([Ent.USER, user, Ent.DRIVE_FILE_OR_FOLDER, None], invalidQuery(DLP.fileIdEntity['query']), i, count)
|
||||||
if not continueOnInvalidQuery:
|
if not continueOnInvalidQuery:
|
||||||
@@ -56324,7 +56366,9 @@ def printShowFileCounts(users):
|
|||||||
continue
|
continue
|
||||||
if summary != FILECOUNT_SUMMARY_NONE:
|
if summary != FILECOUNT_SUMMARY_NONE:
|
||||||
showMimeTypeInfo(summaryUser, summaryMimeTypeInfo,
|
showMimeTypeInfo(summaryUser, summaryMimeTypeInfo,
|
||||||
'' if count > 1 else sharedDriveId, '' if count > 1 else sharedDriveName, 0, 0)
|
'' if count > 1 else sharedDriveId,
|
||||||
|
'' if count > 1 else sharedDriveName,
|
||||||
|
summaryLastModification, 0, 0)
|
||||||
if csvPF:
|
if csvPF:
|
||||||
csvPF.writeCSVfile('Drive File Counts')
|
csvPF.writeCSVfile('Drive File Counts')
|
||||||
|
|
||||||
@@ -66995,14 +67039,14 @@ SPREADSHEET_SHEETS_SUBFIELDS_CHOICE_MAP = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# gam <UserTypeEntity> info|show sheet <DriveFileEntity>
|
# gam <UserTypeEntity> info|show sheet <DriveFileEntity>
|
||||||
# [fields <SpreadsheetFieldList>]
|
# [fields <SpreadsheetFieldList>] [sheetsfields <SpreadsheetSheetsFieldList>]
|
||||||
# (range <SpreadsheetRange>)* (rangelist <SpreadsheetRangeList>)*
|
# (range <SpreadsheetRange>)* (rangelist <SpreadsheetRangeList>)*
|
||||||
# [includegriddata [<Boolean>]]
|
# [includegriddata [<Boolean>]] [shownames]
|
||||||
# [formatjson]
|
# [formatjson]
|
||||||
# gam <UserTypeEntity> print sheet <DriveFileEntity> [todrive <ToDriveAttribute>*]
|
# gam <UserTypeEntity> print sheet <DriveFileEntity> [todrive <ToDriveAttribute>*]
|
||||||
# [fields <SpreadsheetFieldList>]
|
# [fields <SpreadsheetFieldList>] [sheetsfields <SpreadsheetSheetsFieldList>]
|
||||||
# (range <SpreadsheetRange>)* (rangelist <SpreadsheetRangeList>)*
|
# (range <SpreadsheetRange>)* (rangelist <SpreadsheetRangeList>)*
|
||||||
# [includegriddata [<Boolean>]]
|
# [includegriddata [<Boolean>]] [shownames]
|
||||||
# [formatjson [quotechar <Character>]]
|
# [formatjson [quotechar <Character>]]
|
||||||
def infoPrintShowSheets(users):
|
def infoPrintShowSheets(users):
|
||||||
csvPF = CSVPrintFile(['User', 'spreadsheetId'], 'sortall') if Act.csvFormat() else None
|
csvPF = CSVPrintFile(['User', 'spreadsheetId'], 'sortall') if Act.csvFormat() else None
|
||||||
@@ -67010,7 +67054,7 @@ def infoPrintShowSheets(users):
|
|||||||
spreadsheetIdEntity = getDriveFileEntity()
|
spreadsheetIdEntity = getDriveFileEntity()
|
||||||
fieldsList = []
|
fieldsList = []
|
||||||
ranges = []
|
ranges = []
|
||||||
includeGridData = False
|
includeGridData = showSheetNames = False
|
||||||
while Cmd.ArgumentsRemaining():
|
while Cmd.ArgumentsRemaining():
|
||||||
myarg = getArgument()
|
myarg = getArgument()
|
||||||
if csvPF and myarg == 'todrive':
|
if csvPF and myarg == 'todrive':
|
||||||
@@ -67029,8 +67073,16 @@ def infoPrintShowSheets(users):
|
|||||||
fieldsList.append(SPREADSHEET_SHEETS_SUBFIELDS_CHOICE_MAP[field])
|
fieldsList.append(SPREADSHEET_SHEETS_SUBFIELDS_CHOICE_MAP[field])
|
||||||
else:
|
else:
|
||||||
invalidChoiceExit(field, SPREADSHEET_SHEETS_SUBFIELDS_CHOICE_MAP, True)
|
invalidChoiceExit(field, SPREADSHEET_SHEETS_SUBFIELDS_CHOICE_MAP, True)
|
||||||
|
elif myarg == 'shownames':
|
||||||
|
showSheetNames = True
|
||||||
else:
|
else:
|
||||||
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
FJQC.GetFormatJSONQuoteChar(myarg, True)
|
||||||
|
if csvPF and showSheetNames:
|
||||||
|
csvPF.AddTitles('spreadsheetName')
|
||||||
|
csvPF.SetSortAllTitles()
|
||||||
|
if FJQC.formatJSON:
|
||||||
|
csvPF.AddJSONTitles('spreadsheetName')
|
||||||
|
csvPF.MoveJSONTitlesToEnd(['JSON'])
|
||||||
if includeGridData and fieldsList:
|
if includeGridData and fieldsList:
|
||||||
fieldsList.append(SPREADSHEET_SHEETS_SUBFIELDS_CHOICE_MAP['data'])
|
fieldsList.append(SPREADSHEET_SHEETS_SUBFIELDS_CHOICE_MAP['data'])
|
||||||
fields = getFieldsFromFieldsList(fieldsList)
|
fields = getFieldsFromFieldsList(fieldsList)
|
||||||
@@ -67040,6 +67092,10 @@ def infoPrintShowSheets(users):
|
|||||||
user, sheet, jcount = _validateUserGetSpreadsheetIDs(user, i, count, spreadsheetIdEntity, not FJQC.formatJSON)
|
user, sheet, jcount = _validateUserGetSpreadsheetIDs(user, i, count, spreadsheetIdEntity, not FJQC.formatJSON)
|
||||||
if jcount == 0:
|
if jcount == 0:
|
||||||
continue
|
continue
|
||||||
|
if showSheetNames:
|
||||||
|
_, drive = buildGAPIServiceObject(API.DRIVE3, user, i, count)
|
||||||
|
if not drive:
|
||||||
|
continue
|
||||||
Ind.Increment()
|
Ind.Increment()
|
||||||
j = 0
|
j = 0
|
||||||
for spreadsheetId in spreadsheetIdEntity['list']:
|
for spreadsheetId in spreadsheetIdEntity['list']:
|
||||||
@@ -67051,10 +67107,24 @@ def infoPrintShowSheets(users):
|
|||||||
if not includeGridData and 'sheets' in result:
|
if not includeGridData and 'sheets' in result:
|
||||||
for usheet in result['sheets']:
|
for usheet in result['sheets']:
|
||||||
usheet.pop('data', None)
|
usheet.pop('data', None)
|
||||||
|
if showSheetNames:
|
||||||
|
try:
|
||||||
|
spreadsheetName = callGAPI(drive.files(), 'get',
|
||||||
|
throwReasons=GAPI.DRIVE_GET_THROW_REASONS,
|
||||||
|
fileId=spreadsheetId, fields='name', supportsAllDrives=True)['name']
|
||||||
|
except (GAPI.fileNotFound, GAPI.serviceNotAvailable, GAPI.authError, GAPI.domainPolicy):
|
||||||
|
spreadsheetName = spreadsheetId
|
||||||
if not csvPF:
|
if not csvPF:
|
||||||
if FJQC.formatJSON:
|
if FJQC.formatJSON:
|
||||||
printLine('{'+f'"User": "{user}", "spreadsheetId": "{spreadsheetId}", "JSON": {json.dumps(result, ensure_ascii=False, sort_keys=False)}'+'}')
|
baserow = {'User': user, 'spreadsheetId': spreadsheetId}
|
||||||
|
if showSheetNames:
|
||||||
|
baserow['spreadsheetName'] = spreadsheetName
|
||||||
|
baserow['JSON'] = result
|
||||||
|
printLine(json.dumps(baserow, ensure_ascii=False, sort_keys=False)+'\n')
|
||||||
continue
|
continue
|
||||||
|
if showSheetNames:
|
||||||
|
printEntity([Ent.SPREADSHEET, f'{spreadsheetName}({spreadsheetId})'], j, jcount)
|
||||||
|
else:
|
||||||
printEntity([Ent.SPREADSHEET, spreadsheetId], j, jcount)
|
printEntity([Ent.SPREADSHEET, spreadsheetId], j, jcount)
|
||||||
Ind.Increment()
|
Ind.Increment()
|
||||||
if 'spreadsheetUrl' in result:
|
if 'spreadsheetUrl' in result:
|
||||||
@@ -67074,12 +67144,15 @@ def infoPrintShowSheets(users):
|
|||||||
Ind.Decrement()
|
Ind.Decrement()
|
||||||
Ind.Decrement()
|
Ind.Decrement()
|
||||||
else:
|
else:
|
||||||
row = flattenJSON(result, flattened={'User': user, 'spreadsheetId': spreadsheetId})
|
baserow = {'User': user, 'spreadsheetId': spreadsheetId}
|
||||||
|
if showSheetNames:
|
||||||
|
baserow['spreadsheetName'] = spreadsheetName
|
||||||
|
row = flattenJSON(result, flattened=baserow.copy())
|
||||||
if not FJQC.formatJSON:
|
if not FJQC.formatJSON:
|
||||||
csvPF.WriteRowTitles(row)
|
csvPF.WriteRowTitles(row)
|
||||||
elif csvPF.CheckRowTitles(row):
|
elif csvPF.CheckRowTitles(row):
|
||||||
csvPF.WriteRowNoFilter({'User': user, 'spreadsheetId': spreadsheetId,
|
baserow['JSON'] = json.dumps(cleanJSON(result), ensure_ascii=False, sort_keys=False)
|
||||||
'JSON': json.dumps(result, ensure_ascii=False, sort_keys=False)})
|
csvPF.WriteRowNoFilter(baserow)
|
||||||
except (GAPI.notFound, GAPI.forbidden, GAPI.permissionDenied,
|
except (GAPI.notFound, GAPI.forbidden, GAPI.permissionDenied,
|
||||||
GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.badRequest,
|
GAPI.internalError, GAPI.insufficientFilePermissions, GAPI.badRequest,
|
||||||
GAPI.invalid, GAPI.invalidArgument, GAPI.failedPrecondition) as e:
|
GAPI.invalid, GAPI.invalidArgument, GAPI.failedPrecondition) as e:
|
||||||
|
|||||||
@@ -215,6 +215,7 @@ class GamEntity():
|
|||||||
END_TIME = 'endt'
|
END_TIME = 'endt'
|
||||||
ENTITY = 'enti'
|
ENTITY = 'enti'
|
||||||
EVENT = 'evnt'
|
EVENT = 'evnt'
|
||||||
|
EVENT_BIRTHDAY = 'evbd'
|
||||||
EVENT_FOCUSTIME = 'evft'
|
EVENT_FOCUSTIME = 'evft'
|
||||||
EVENT_OUTOFOFFICE = 'evoo'
|
EVENT_OUTOFOFFICE = 'evoo'
|
||||||
EVENT_WORKINGLOCATION = 'evwl'
|
EVENT_WORKINGLOCATION = 'evwl'
|
||||||
@@ -565,6 +566,7 @@ class GamEntity():
|
|||||||
END_TIME: ['End Times', 'End Time'],
|
END_TIME: ['End Times', 'End Time'],
|
||||||
ENTITY: ['Entities', 'Entity'],
|
ENTITY: ['Entities', 'Entity'],
|
||||||
EVENT: ['Events', 'Event'],
|
EVENT: ['Events', 'Event'],
|
||||||
|
EVENT_BIRTHDAY: ['Borthday Events', 'Birthday Event'],
|
||||||
EVENT_FOCUSTIME: ['Focus Time Events', 'Focus Time Event'],
|
EVENT_FOCUSTIME: ['Focus Time Events', 'Focus Time Event'],
|
||||||
EVENT_OUTOFOFFICE: ['Out of Office Events', 'Out of Office Event'],
|
EVENT_OUTOFOFFICE: ['Out of Office Events', 'Out of Office Event'],
|
||||||
EVENT_WORKINGLOCATION: ['Working Location Events', 'Working Location Event'],
|
EVENT_WORKINGLOCATION: ['Working Location Events', 'Working Location Event'],
|
||||||
|
|||||||
@@ -13,10 +13,10 @@ keywords = google, oauth2, gsuite, google-apps, google-admin-sdk, google-drive,
|
|||||||
classifiers =
|
classifiers =
|
||||||
Programming Language :: Python :: 3
|
Programming Language :: Python :: 3
|
||||||
Programming Language :: Python :: 3 :: Only
|
Programming Language :: Python :: 3 :: Only
|
||||||
Programming Language :: Python :: 3.8
|
|
||||||
Programming Language :: Python :: 3.9
|
Programming Language :: Python :: 3.9
|
||||||
Programming Language :: Python :: 3.10
|
Programming Language :: Python :: 3.10
|
||||||
Programming Language :: Python :: 3.11
|
Programming Language :: Python :: 3.11
|
||||||
|
Programming Language :: Python :: 3.12
|
||||||
License :: OSI Approved :: Apache License
|
License :: OSI Approved :: Apache License
|
||||||
|
|
||||||
[options]
|
[options]
|
||||||
|
|||||||
58
src/tools/gen-wix-xml-filelist.py
Normal file
58
src/tools/gen-wix-xml-filelist.py
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
source_dir = sys.argv[1]
|
||||||
|
template_file = sys.argv[2]
|
||||||
|
target_file = sys.argv[3]
|
||||||
|
|
||||||
|
existing_components = {
|
||||||
|
'gam.exe': ''' <Component Id="gam_exe" Guid="d046ea24-c9f8-40ca-84db-70b0119933ff">
|
||||||
|
<File Name="gam.exe" KeyPath="yes" />
|
||||||
|
<Environment Id="PATH" Name="PATH" Value="[INSTALLFOLDER]" Permanent="yes" Part="last" Action="set" System="yes" />
|
||||||
|
</Component>
|
||||||
|
''',
|
||||||
|
'LICENSE': ''' <Component Id="license" Guid="c76864c5-d005-44d5-bb7c-a27e5923792d">
|
||||||
|
<File Name="LICENSE" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
''',
|
||||||
|
'gam-setup.bat': ''' <Component Id="gam_setup_bat" Guid="5e6bbacb-d86f-4d80-a10b-89b81ee63fcb">
|
||||||
|
<File Name="gam-setup.bat" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
''',
|
||||||
|
'GamCommands.txt': ''' <Component Id="GamCommands_txt" Guid="a2dca862-b222-469e-a637-95ea2a1c53e7">
|
||||||
|
<File Name="GamCommands.txt" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
''',
|
||||||
|
'GamUpdate.txt': ''' <Component Id="GamUpdate_txt" Guid="1b7cdd48-0fff-4943-a219-102fcd14c755">
|
||||||
|
<File Name="GamUpdate.txt" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
''',
|
||||||
|
'cacerts.pem': ''' <Component Id="cacerts_pem" Guid="61fe2b2d-1646-4bed-b844-193965e97727">
|
||||||
|
<File Name="cacerts.pem" KeyPath="yes" />
|
||||||
|
</Component>
|
||||||
|
''',
|
||||||
|
}
|
||||||
|
|
||||||
|
component_xml = ''
|
||||||
|
all_files = []
|
||||||
|
for root, dirs, files in os.walk(source_dir):
|
||||||
|
for filename in files:
|
||||||
|
relpath = os.path.relpath(root, source_dir)
|
||||||
|
if relpath == '.':
|
||||||
|
all_files.append(filename)
|
||||||
|
else:
|
||||||
|
all_files.append(os.path.join(relpath, filename))
|
||||||
|
all_files.sort()
|
||||||
|
for filename in all_files:
|
||||||
|
component_xml += existing_components.get(filename,
|
||||||
|
f' <Component>\n <File Name="{filename}" KeyPath="yes"/>\n </Component>\n')
|
||||||
|
|
||||||
|
with open(template_file, 'r') as f:
|
||||||
|
template = f.read()
|
||||||
|
|
||||||
|
full_xml = template.replace('REPLACE_ME_WITH_FILE_COMPONENTS', component_xml)
|
||||||
|
|
||||||
|
with open(target_file, 'w') as f:
|
||||||
|
f.write(full_xml)
|
||||||
|
|
||||||
Reference in New Issue
Block a user